JVM虚拟机系统性学习-运行时数据区(方法区、程序计数器、直接内存)

方法区

方法区本质上是 Java 编译后代码的存储区域,存储了每一个类的结构信息,如:运行时常量池、成员变量、方法、构造方法和普通方法的字节码指令等内容

方法区主要存储的数据如下:

  • Class
    1. 类型信息,如该 Class 为 class 类、接口、枚举、注解,类的修饰符等等信息
    2. 方法信息(方法名称、方法返回值、方法参数等等)
    3. 字段信息:保存字段信息,如字段名称、字段类型、字段修饰符
    4. 类变量(静态变量):JDK1.7 之后转移到堆中存储
  • 运行时常量池(字符串常量池):JDK1.7 之后,转移到堆中存储
  • JIT 编译器编译之后的代码缓存

方法区的具体实现有两种:永久代(PermGen)、元空间(Metaspace)

  • JDK1.8 之前通过永久代实现方法区,JDK1.8 及之后使用元空间实现方法区
  • 这两种实现的不同,从存储位置来看:
    • 永久代使用的内存区域为 JVM 进程所使用的区域,大小受 JVM 限制
    • 元空间使用的内存区域为物理内存区域,大小受机器的物理内存限制
  • 从存储内容来看:
    • 永久代存储的信息上边方法区中规定的信息
    • 元空间只存储类的元信息,而静态变量和运行时常量池都转移到堆中进行存储

为什么永久代要被元空间替换?

  • 字符串存在永久代中,容易出现性能问题和永久代内存溢出。
  • 类及方法的信息等比较难确定其大小,因此对于永久代的大小指定比较困难,太小容易出现永久代溢出,太大则容易导致老年代溢出。
  • 永久代会为 GC 带来不必要的复杂度,并且回收效率偏低。

常量池

  • class常量池:一个class文件只有一个class常量池

    字面量:数值型(int、float、long、double)、双引号引起来的字符串值等

    符号引用:Class、Method、Field等

  • 运行时常量池:一个class对象有一个运行时常量池

    字面量:数值型(int、float、long、double)、双引号引起来的字符串值等

    符号引用:Class、Method、Field等

  • 字符串常量池:全局只有一个字符串常量池

    双引号引起来的字符串值

程序计数器

程序计数器用于存储当前线程所执行的字节码指令的行号,用于选取下一条需要执行的字节码指令

分支,循环,跳转,异常处理,线程回复等都需要依赖这个计数器来完成

通过程序计数器,可以在线程发生切换时,可以保存该线程执行的位置

直接内存

直接内存(也成为堆外内存)并不是虚拟机运行时数据区的一部分,直接内存的大小受限于系统的内存

在 JDK1.4 引入了 NIO 类,在 NIO 中可以通过使用 native 函数库直接分配堆外内存,然后通过存储在堆中的 DirectByteBuffer 对象作为这块内存的引用进行操作

使用直接内存,可以避免了 Java 堆和 Native 堆中来回复制数据

直接内存使用场景:

  • 有很大的数据需要存储,且数据生命周期长
  • 频繁的 IO 操作,如网络并发场景

直接内存与堆内存比较:

  • 直接内存申请空间耗费更高的性能,当频繁申请到一定量时尤为明显
  • 直接内存IO读写的性能要优于普通的堆内存,在多次读写操作的情况下差异明显

直接内存相比于堆内存,避免了数据的二次拷贝。

  • 我们先来分析不使用直接内存的情况,我们在网络发送数据需要将数据先写入 Socket 的缓冲区内,那么如果数据存储在 JVM 的堆内存中的话,会先将堆内存中的数据复制一份到直接内存中,再将直接内存中的数据写入到 Socket 缓冲区中,之后进行数据的发送

    • 为什么不能直接将 JVM 堆内存中的数据写入 Socket 缓冲区中呢?

      在 JVM 堆内存中有 GC 机制,GC 后可能会导致堆内存中数据位置发生变化,那么如果直接将 JVM 堆内存中的数据写入 Socket 缓冲区中,如果写入过程中发生 GC,导致我们需要写入的数据位置发生变化,就会将错误的数据写入 Socket 缓冲区

  • 那么如果使用直接内存的时候,我们将数据直接存放在直接内存中,在堆内存中只存放了对直接内存中数据的引用,这样在发送数据时,直接将数据从直接内存取出,放入 Socket 缓冲区中即可,减少了一次堆内存到直接内存的拷贝

在这里插入图片描述

直接内存与非直接内存性能比较:

public class ByteBufferCompare {public static void main(String[] args) {//allocateCompare(); //分配比较operateCompare(); //读写比较}/*** 直接内存 和 堆内存的 分配空间比较* 结论: 在数据量提升时,直接内存相比非直接内的申请,有很严重的性能问题*/public static void allocateCompare() {int time = 1000 * 10000; //操作次数,1千万long st = System.currentTimeMillis();for (int i = 0; i < time; i++) {//ByteBuffer.allocate(int capacity) 分配一个新的字节缓冲区。ByteBuffer buffer = ByteBuffer.allocate(2); //非直接内存分配申请}long et = System.currentTimeMillis();System.out.println("在进行" + time + "次分配操作时,堆内存 分配耗时:" +(et - st) + "ms");long st_heap = System.currentTimeMillis();for (int i = 0; i < time; i++) {//ByteBuffer.allocateDirect(int capacity) 分配新的直接字节缓冲区。ByteBuffer buffer = ByteBuffer.allocateDirect(2); //直接内存分配申请}long et_direct = System.currentTimeMillis();System.out.println("在进行" + time + "次分配操作时,直接内存 分配耗时:" +(et_direct - st_heap) + "ms");}/*** 直接内存 和 堆内存的 读写性能比较* 结论:直接内存在直接的IO 操作上,在频繁的读写时 会有显著的性能提升*/public static void operateCompare() {int time = 10 * 10000 * 10000; //操作次数,10亿ByteBuffer buffer = ByteBuffer.allocate(2 * time);long st = System.currentTimeMillis();for (int i = 0; i < time; i++) {// putChar(char value) 用来写入 char 值的相对 put 方法buffer.putChar('a');}buffer.flip();for (int i = 0; i < time; i++) {buffer.getChar();}long et = System.currentTimeMillis();System.out.println("在进行" + time + "次读写操作时,非直接内存读写耗时:" +(et - st) + "ms");ByteBuffer buffer_d = ByteBuffer.allocateDirect(2 * time);long st_direct = System.currentTimeMillis();for (int i = 0; i < time; i++) {// putChar(char value) 用来写入 char 值的相对 put 方法buffer_d.putChar('a');}buffer_d.flip();for (int i = 0; i < time; i++) {buffer_d.getChar();}long et_direct = System.currentTimeMillis();System.out.println("在进行" + time + "次读写操作时,直接内存读写耗时:" +(et_direct - st_direct) + "ms");}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/265412.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux:环境变量

目录 1.基本变量 2.通过代码获取环境变量 2.1 main传参 2.2 全局变量environ 2.3 系统调用getenv() 3.在脚本文件中添加环境变量 4.环境变量通常是具有全局属性 1.基本变量 环境变量(environment variables)一般是指在操作系统中用来指定操作系统运行环境的一些参数…

vuepress-----22、其他评论方案

vuepress 支持评论 本文讲述 vuepress 站点如何集成评论系统&#xff0c;选型是 valineleancloud, 支持匿名评论&#xff0c;缺点是数据没有存储在自己手里。市面上也有其他的方案, 如 gitalk,vssue 等, 但需要用户登录 github 才能发表评论, 但 github 经常无法连接,导致体验…

指针,函数指针,二级指针,指针传参,回调函数,指针步长

文章目录 指针是什么&#xff1f;指针的定义指针的大小 指针类型指针有哪些类型&#xff1f;指针类型有什么意义&#xff1f;代码演示&#xff1a;(偏移)代码演示(指针解引用时取出的字节数)其他例子 野指针野指针的成因如何避免野指针 指针运算指针整数指针-指针指针的关系运算…

上市公司碳排放数据,shp/excel格式,总数量近3400条,含多项指标及对应可视化矢量图

基本信息. 数据名称: 上市公司碳排放数据 数据格式: Shp、excel 数据时间: 2021年 数据几何类型: 点 数据坐标系: WGS84坐标系 数据来源&#xff1a;网络公开数据 数据字段&#xff1a;www.bajidata.com 序号字段名称字段说明1province省名称2city城市名称3county区…

Linux上的MAC地址欺骗

Linux上的MAC地址欺骗 1、查看mac地址法1&#xff1a;ifconfig法2&#xff1a;ip link show 2、临时性改变 MAC 地址法1&#xff1a;使用iproute2工具包法2&#xff1a;使用macchanger工具 3、永久性改变 MAC 地址3.1 在 Fedora、RHEL下实践3.2 在 Debian、Ubuntu、Linux Mint下…

告别 Navicat!一款能支持几乎所有数据库的开源工具!

数据库连接工具&#xff0c;后端程序员必须要用到工具&#xff0c;常用的是 Navicat&#xff0c;Navicat是收费工具&#xff0c;今天给大家推荐一款开源免费的数据库连接工具 -- dbeaver。 功能特性 1、几乎支持所有数据库产品&#xff0c;包括&#xff1a;MySQL、SQL Server…

【数学建模】《实战数学建模:例题与讲解》第八讲-回归分析(含Matlab代码)

【数学建模】《实战数学建模&#xff1a;例题与讲解》第八讲-回归分析&#xff08;含Matlab代码&#xff09; 回归分析基本概念经典多元线性回归&#xff08;MLR&#xff09;主成分回归&#xff08;PCR&#xff09;偏最小二乘回归&#xff08;PLS&#xff09;建模过程应用和优势…

XML映射文件(第二种方式执行SQL语句)

第一种方式是注解的方式在下面&#xff1a; 注解操作SQL语句https://blog.csdn.net/m0_71149935/article/details/134908856?spm1001.2014.3001.5501 要想使用XML&#xff0c;需要遵守三项规范&#xff1a; XML映射文件的名称与Mapper接口名称一致&#xff0c;并且将XML映射…

计算机毕业设计 SpringBoot的人事管理系统 Javaweb项目 Java实战项目 前后端分离 文档报告 代码讲解 安装调试

&#x1f34a;作者&#xff1a;计算机编程-吉哥 &#x1f34a;简介&#xff1a;专业从事JavaWeb程序开发&#xff0c;微信小程序开发&#xff0c;定制化项目、 源码、代码讲解、文档撰写、ppt制作。做自己喜欢的事&#xff0c;生活就是快乐的。 &#x1f34a;心愿&#xff1a;点…

基于SSM的健身房预约系统设计与实现

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SSM 前端&#xff1a;Vue 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#xff1a;是 目录…

智能优化算法应用:基于正余弦算法3D无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用&#xff1a;基于正余弦算法3D无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用&#xff1a;基于正余弦算法3D无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.正余弦算法4.实验参数设定5.算法结果6.参考文…

【Docker】进阶之路:(二)Docker简介

【Docker】进阶之路&#xff1a;&#xff08;二&#xff09;Docker简介 什么是 DockerDocker 由来与发展历程Docker的架构与组成Docker容器生态容器核心技术容器规范容器平台技术 为什么使用DockerDocker的应用场景 什么是 Docker 简单地讲&#xff0c;Docker就是一个应用容器…