美文网首页
01 JVM 运行时数据区

01 JVM 运行时数据区

作者: 格林哈 | 来源:发表于2020-07-23 15:49 被阅读0次

1. 运行时数据区

java虚拟机运行时数据区域
  • java运行过程中把内存分为几个不同区域,方法区存储类的结构信息,代码解释执行,像刷题的表达式求值,需要 虚拟机栈 进行运算,程序计数器 保存不同线程切换正在执行字节码指令地址,本地方法栈 执行native 方法,如c++方法,海康sdk 很多就是native方法,堆空间进行对象内存分配。

1.1 程序计数器/PC寄存器

  • 作用: 保持java虚拟机正在执行的字节码指令的地址

    • 非本地(Native)方法
      • 值是正在执行的虚拟机字节码指令的地址
    • 本地(Native)方法
      • 值为空(Undefined,未定义)
        • 本地方法的执行依赖硬件PC寄存器,其值是由操作系统来维护的,虚拟机实现的PC寄存器对本地方法不会产生任何作用。
  • 大小: 应当能保存一个returnAddress类型(指向了一条字节码指令的地址)或者一个与平台相关的本地指针的值

  • 背景: Java虚拟机的多线程是通过线程轮流切换、分配处理器执行时间的方式来实现的,在任何一个确定的时刻,一个处理器(对于多核处理器来说是一个内核)都只会执行一条线程中的指令。因此,为了线程切换后能恢复到正确的执行位置,每条线程都需要有一个独立的程序计数器。

  • 生命周期: 栈帧相同(不是很确定)

  • 注意点: 在《Java虚拟机规范》中没有规定任何OutOfMemoryError情况的区域。

1.2 java虚拟机栈

  • 作用: java栈是和线程关联在一起,每当创建一个线程时,JVM就会为这个线程创建一个对应的Java栈,每个方法被执行的时候,java虚拟机都会同步创建一个栈帧Stack Frame),用于存储局部变量表、操作数栈、动态连接、方法出口等信息。
  • JVM规范
    • 允许java虚拟机栈被实现成固定大小的
      • 每个线程地栈容量在线程创建时就应明确
    • 根据运行状况动态地扩展和收缩
      • 提供调节最大,最小容量地手段。
  • 可能异常:
    • 如果线程请求分配地栈容量(栈的深度)超过java虚拟机栈允许地最大容量,抛出StackOverflowError
    • 如果JVM栈可以动态扩展,尝试扩展后无法申请到足够的内存,抛出OutOfMemoryError
    • 创建新的线程没有足够内存取创建对应的虚拟机栈,抛出OutOfMemoryError
  • 生命周期: 线程相同
  • 注意点: HotSpot虚拟机的栈容量是不可以动态扩展的
  • JVM参数
    • -Xss 单个线程栈的大小,默认1M 如 -Xss128k
      • 等价于-XX:ThreadStackSize=

1.3 本地方法栈

  • 作用: 与虚拟机栈所发挥的作用是非常相似的,JVM运行Native方法(用java以外的其他语言编写的方法)准备的空间。在JVM利用JIT技术时会将一些Java方法重新编译为NativeCode代码,这些编译后的本地代码通常也是利用这个栈来跟踪方法的执行状态的。

  • 注意点: Hot-Spot虚拟机,直接就把本地方法栈和虚拟机栈合二为一

1.3 java堆

  • 作用: 存放对象实例(类实例和数组对象)
    • java不允许程序员直接操作内存,内存管理任务统一交由虚拟机处理(自动内存管理)
  • JVM规范:
    • java虚拟机实现应当提供给程序员或者最终用户调节java堆出事容量的手段,对于可以动态扩展或者收缩java堆来说,则应当提供调节其最大,最小容量的手段。
  • 可能异常:
    • 如果实际所需的堆超过了自动内存管理系统能提供的最大容量,抛出OutOfMemoryError
  • JVM参数
    • -Xms 堆初始大小 如-Xms20m 很多时候设置成Xmx相等的值 这样可以减少程序运行时进行垃圾回收的次数
    • -Xmx 堆最大值 如-Xmx100m
    • -Xmn Young区(新生代)大小
    • -XX:PermSize= 初始Perm区(永久代)大小 JDK1.6,JDK1.7
    • -XX:MaxPermSize= Perm区(永久代)最大值 JDK1.6,JDK1.7
    • -XX:MaxMetaspaceSize= 元数据区最大值
    • -XX:+HeapDumpOnOutOfMemoryError 发生内存溢出时自动的生成堆内存快照
    • -XX:HeapDumpPath=/home/pi/software/dataGathering/logs 设置快照的生成路径
    • -XX:SurvivorRatio 设置新生代中eden区和Survivor(from/to)区空间的比例关系 默认是8 eden:to 8:1 eden比例8/10 to和from 一样大小 2/10
    • -XX:NewRatio 老年代与新生代比例 如 4表示 老年代:新生代=4 新生代= 1/5 老年代 4/5
    • 例子
      • java -Xms128m -Xmx512m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/home/pi/software/dataGathering/logs
  • 堆的结构:
  • 根据垃圾回收机制不同,java可能有不同结构,最常见的将java堆分为新生代老年代。
    • 新生代
      • eden区
        • 28定律,绝大部分对象朝生夕死,大多数情况首先分配在eden区
      • 等比例的s0区和s1区 也称from区和to区
      • -XX:SurvivorRatio eden区/from和to区比例关系 jdk8 默认是8
    • 老年代
    • 永久代
      • Hotspot虚拟机特有的概念,是方法区的一种实现,JDK8永久代被彻底移除,取而代之的是另一块与堆不相连的本地内存——元空间

1.4 方法区

  • 作用: 存储了每一个类的结构信息(例如,运行时常量池,字段和方法数据,构造函数,普通方法字节码内容,类,实例初始化用到的特殊方法)
    • 方法区属于堆的一个逻辑部分,但很多情况下,都把方法区与堆区分开来说。平时开发中通过反射获取到的类名、方法名、字段名称、访问修饰符等信息都是从这块区域获取的。
  • 实现:
    • HotSpot虚拟机 方法区对应为永久代 使用的还是堆空间
    • 对于其他的虚拟机(JRockit、J9)来说 元空间,不存在永久代这个概念,使用的是Native Memory(直接内存)
  • 可能异常:
    • 如果方法区的内存空间不能满足内存分配请求,java虚拟机抛出一个OutOfMemoryError 异常
  • JVM参数
    • -XX:PermSize=和-XX:MaxPermSize= jdk7 设置设置永久代的大小
    • -XX:MetaspaceSize=(初始化元空间大小)和-XX:MaxMetaspaceSize= 元空间最大值 jdk8

1.5 运行时常量池

public class Main {
    private int m = 2;
    private static  String istr = "istrValue";
    private final String finalX = "finalXValue";

    public Boolean change(int m , String str ) {
        this.m = m;
        istr = str;
        return true;
    }
}
  • Main class结构
  • 作用: 方法区的一部分,用于存放编译期生成的各种字面量与符号引用,这部分内容将在类加载后存放到方法区的运行时常量池中
    • 字面量 相当于Java语言层面常量的概念,比如:字符串常量、声明为final的常量等等,如代码中的"istrValue,finalXValue"
    • 符号引用 用一组符号来描述所引用的目标,符号可以是任何形式的字面量,只要使用时能无歧义的定位到目标即可
      • 类和接口和全限定名 例如对于String这个类,它的全限定名就是java/lang/String。
      • 字段的名称和描述符 类或者接口中声明的变量,包括类级别变量(static)和实例级的变量
      • 方法的名称和描述符 谓描述符就相当于方法的参数类型+返回值类型。
  • 可能异常:
    • 当创建类或接口时候,如果构造运行时常量池所需要的内存空间超过了方法区所能提供的最大值,那么java虚拟机将会抛出一个OutOfMemoryError异常

1.6 直接内存

  • 作用: 直接内存(Direct Memory)并不是虚拟机运行时数据区的一部分
    • 在JDK 1.4中新加入了NIO(NewInput/Output)类,引入了一种基于通道(Channel)与缓冲区(Buffer)的I/O方式,它可以使用Native函数库直接分配堆外内存,然后通过一个存储在Java堆里面的DirectByteBuffer对象作为这块内存的引用进行操作。这样能在一些场景中显著提高性能,因为避免了在Java堆和Native堆中来回复制数据。
  • 可能异常:
    • 本机直接内存的分配不会受到Java堆大小的限制,但是,既然是内存,则肯定还是会受到本机总内存(包括物理内存、SWAP分区或者分页文件)大小以及处理器寻址空间的限制
    • 如果根据实际内存去设置-Xmx等参数信息,但经常忽略掉直接内存,使得各个内存区域总和大于物理内存限制(包括物理的和操作系统级的限制),从而导致动态扩展时出现OutOfMemoryError异常。
  • JVM参数
    • -XX:MaxDirectMemorySize 配置直接内存大小 ,如果不设置,默认值为最大堆空间即-Xmx

参考 深入理解Java虚拟机

相关文章

  • Java从入门到入坑(底层篇)

    01:JVM 1:JVM内存结构 class 文件格式、运行时数据区:堆、栈、方法区、直接内存、运行时常量池、 堆...

  • Java虚拟机02-JVM运行时数据区

    1 JVM运行时数据区 JVM运行时数据区(JVM Runtime Area)其实就是指JVM在运行期间,其对计算...

  • JVM学习笔记

    JVM 注意:0、JVM运行时数据区和JVM内存模型不要搞混1、运行时数据区可以分为:堆、方法区、虚拟机栈、本地方...

  • 线程在JVM中的运行原理

    。线程在启动运行时,主要是在运行时数据区(JVM的内存模型),而JVM的运行时数据区主要包括堆,方法区,Java栈...

  • jvm 运行时数据区-01

    jvm 运行时数据区 jvm 运行时数据区 ,将内存划分为5个区域,java 代码在运行时 类里面的 组成部分 分...

  • 线程安全之可见性问题

    Java内存模型 VS JVM运行时数据区 首先Java内存模型(JMM)和JVM运行时数据区并不是一个东西,许多...

  • jvm内存模型及GC记录

    在jvm中有一块非常重要的区域,就是jvm运行时数据区。今天对该区域做下总结和记录: 在讨论jvm运行时数据区前,...

  • java面试jvm总结

    JVM→ JVM 内存结构运行时数据区:堆、栈、方法区、直接内存、运行时常量池、堆存放对象, 方法区他用于存储已被...

  • Java虚拟机内存区域详解

    JVM 运行时的数据区域 首先获取一个直观的认识: 总共也就这么 5 个区(直接内存不属于 JVM 运行时数据区的...

  • 《深入理解Java虚拟机-JVM高级特性与最佳实践》学习总结(第

    一、运行时数据区 JVM将我们机器上的内存当做一个运行时数据区来进行处理。该运行时数据区包括以下几个部分: 方法区...

网友评论

      本文标题:01 JVM 运行时数据区

      本文链接:https://www.haomeiwen.com/subject/qqhyyhtx.html