JVM原理及调优(2)–JVM内存结构

1.JVM内存结构

JVM按照运行时数据的存储结构来划分内存结构,不同格式的数据分别存储在不同的区域,统称为运行时数据,运行时数据包括Java程序本身的数据信息和JVM运行Java需要的额外数据信息。

JVM原理及调优(2)--JVM内存结构

  • JVM内存结构

    • Non-Heap
      CodeCache
      Permanent Generation space
      Direct Momery

    • Heap

  • JVM GC管理

1.1 jvm运行时的数据区

  • 线程私有:程序计数器、Java虚拟机栈、本地方法栈

  • 线程公用:Java堆、方法区

1.2 jvm内存分配

  • 栈内存分配

    • 保存参数、局部变量、中间计算过程和其他数据。退出方法的时候,修改栈顶指针就可以把栈帧中的内容销毁。

    • 栈的优点:存取速度比堆快,仅次于寄存器,栈数据可以共享。

    • 栈的缺点:存在栈中的数据大小、生存期是在编译时就确定的,导致其缺乏灵活性。

  • 堆内存分配

    • 堆的优点:动态地分配内存大小,生存期不必事先告诉编译器,它是在运行期动态分配的,垃圾回收器会自动收走不再使用的空间区域。

    • 堆的缺点:运行时动态分配内存,在分配和销毁时都要占用时间,因此堆的效率较低。

  • 多线程的Java应用程序:
    为了让每个线程正常工作就提出了程序计数器(Program Counter Register),每个线程都有自己的程序计数器这样当线程执行切换的时候就可以在上次执行的基础上继续执行,仅仅从一条线程线性执行的角度而言,代码是一条一条的往下执行的,这个时候就是Program Counter Register,JVM就是通过读取Program Counter Register的值来决定该线程下一条需要执行的字节码指令,进而进行选择语句、循环、异常处理等

  • 线程:
    从OOP而言,相当于一个对象,该对象中具有执行代码,同时也有要处理的数据,数据包含Thread工作时候要访问的数据,同时也包含现在的Stack,在Stack中包含了Thread本地的数据,也包含了拷贝的全局数据;从面向过程的角度而言:线程 = 代码 + 数据

  • Main Memory:全局共享内存空间

区域化管理的好处:分而治之,优化对象

2.JVM堆结构

2.1 JVM堆结构

JVM原理及调优(2)--JVM内存结构

2.2 jvm堆配置参数

  1. -Xms初始堆大小
    默认物理内存的1/64(<1GB),官方建议,可以按实际情况调整

  2. -Xmx最大堆大小
    默认物理内存的1/4(<1GB),实际中建议不大于4GB

  3. 一般建议设置 -Xms = -Xmx
    避免每次在gc后,调整堆的大小,减少内存抖动,系统内存分配开销

  4. 整个堆大小 = 年轻代大小 + 年老代大小 + 持久代大小

2.3 jvm新生代(young generation)

  1. 新生代 = 1个eden区 + 2个Survivor区(e+s0+s1)

  2. -Xmn年轻代大小(1.4 or later)
    -XX:NewSize,-XX:MaxNewSize(设置年轻代大小(for 1.3/14))
    默认值大小为整个堆的3/8

  3. -XX:NewRatio
    年轻代(放在Eden和两个Survivor区)与年老代的比值(除去持久代)Xms=Xmx并且设置了Xmn的情况下,该参数不需要进行设置。

  4. -XX:SurvivorRatio
    Eden区与Survivor区的大小比值,设置为8,则两个Survivor区与一个Eden区的比值为2:8,一个Survivor区占整个年轻代的1/10

  5. 用来存放JVM刚分配的Java对象

2.4 jvm老年代(tenured generation)

  1. 老年代=整个堆- 年轻代大小 - 持久代大小

  2. 年轻代中经过垃圾回收没有回收掉的对象被复制到年老代

  3. 老年代存储对象比年轻代年龄大的多,而且不乏大对象

  4. 新建的对象也有可能直接进入老年代


    • 大对象,可通过启动参数设置-XX:PretenureSizeThreshold=1024(单位为字节,默认为0)来代表超过多大时就不在新生代分配,而是直接在老年代分配

    • 大的数据对象,切数组中无引用外部对象

  5. 老年代大小无配置参数

2.5 jvm持久代(perm generation)

  1. 持久代 = 整个堆 - 年轻代大小 - 老年代大小

  2. -XX:PermSize -XX:MaxPermSize
    设置持久代的大小,一般情况推荐把-XX:PermSize设置成XX:MaxPermSize的值为相同的值,因为永久代大小的调整也会导致堆内存需要触发fgc

  3. 存储Class、Method元信息,其大小与项目的规模、类、方法的数量有关。一般设置为128M就足够,设置原则是预留30%的空间

  4. 永久代的回收方式

    • 常量池中的常量,无用的类信息,常量的回帖很简单,没有引用了就可以被回收

    • 对于无用的类进行回收,必须保证3点:
      类的所有实例都已经被回收
      加载类的ClassLoader已经被回收
      类对象的Class对象没有被引用(即没有通过反射引用该类的地方)

anzhihe安志合个人博客,版权所有丨 如未注明,均为原创 丨转载请注明转自:https://chegva.com/2923.html | ☆★★每天进步一点点,加油!★★☆

您可能还感兴趣的文章!

发表评论

电子邮件地址不会被公开。 必填项已用*标注