当前位置:   article > 正文

【JVM】基本结构

【JVM】基本结构


前言

最近重新温习了一遍JVM的信息,把我认为重要的知识点梳理一遍,记录在这里
JVM的知识点,有一说一,平时用到的不是特别多,一般的应用不需要那么细致的参数微调
都是简单分配一下各代指标、配置简单的调试参数,比如输出GC详情等

但是当我们遇到程序异常时,比如程序无明显征兆崩溃、内存溢出、频繁GC等等,这些疑难杂症要想快速且妥善的修复,那么了解JVM相关的知识则是必不可少的,所谓书到用时方恨少,不出问题则以,出了问题就抓瞎了

所以我认为ava程序员,对JVM进行一定程度的了解还是非常有必要的。
并且,对各项参数、指标的了解,对发现问题、出现问题的修复都是有非常大的帮助


虚拟机基本结构

JVM基本结构

方法区

方法区是线程共享的内存区域,用于存储已被虚拟机加载的类信息、常量、静态变量、即使编译器编译后的代码等数据,别名Non-Heap,也是为了区分Java堆。

了解HotSpot的朋友应该听过“永久代”的说法,这也是HotSpot团队将永久代放到方法区实现才得来的名字,不过一段时间过后,大家发现这可能不是一个好的方案,因为永久代的回收效率导致容易遇到内存溢出的问题(需要通过参数配置XX:MaxPermSize),所以HotSpot团队也是决定调整这部分实现方式,参照其他JVM,比如JRockit、IBM J9等,将永久代拆解开来

JDK 1.7,把原本在永久代的字符串常量池移出
JDK 1.8,把内部字符串和静态类数据移到Java堆;为类元数据显式分配和释放本机内存;新类元数据的分配将受到可用本机内存量的限制,而不是由 -XX:MaxPermSize 的值固定,无论是默认值还是在命令行上指定

新的概念称之为元空间,参数也调整为了如下:
-XX:MetaspaceSize:初始阈值,达到这个阈值会触发FGC
-XX:MaxMetaspaceSize:最大可扩展的容量

具体说明可以参考这个博客:JVM源码分析之Metaspace解密
JVM调整信息参照官网信息:JEP 122: Remove the Permanent Generation


Java 堆

与方法区一样,Java堆也是线程共享的内存区域,我们创建的对象和数组都保存在Java堆的内存中,同样,我们可以猜想到这里也是垃圾收集器的主战场

由于现代的收集器基本都采用分代收集算法,所以Java堆中还可以细分为:新生代和老年代
新生代再细致点可以分为:Eden、From Survivor、To Survivor

默认情况下,新生代与老年带的比例为1:2;Eden和From Survivor、ToSurvivor的默认比例为8:1:1
在这里插入图片描述
如果在堆中没有内存完成实例的成功分配、且堆无法扩容时,就会抛出OOM异常


程序计数器(寄存器)

它是一块较小的内存空间,是当前线程所执行的字节码行号指示器,每条线程都有一个独立的程序计数器,所以它是线程私有

如果执行Java函数的话,计数器记录的是虚拟机字节码当前指令的地址,如果是Native方法,则是Undefined
这个内存区域也是唯一一个在虚拟机中没有规定任何OOM情况的区域


虚拟机栈

与程序计数器一样,虚拟机栈也是线程私有的,生命周期与线程相同
是描述Java方法执行的内存模型,每个方法在执行的同时都会创建一个栈帧,用于存储局部变量表,操作数栈、动态链接和方法出口等信息。

存放了编译器可知的各种基本数据类型、对象应用以及returnAddress类型(指向了1条字节码指令的地址)

每一个方法从调用至执行完成的过程,就对应着一个栈帧在虚拟机栈入栈到出栈的过程


本地方法栈

本地方法栈和虚拟机栈作用相似,区别在于虚拟机栈为执行Java方法服务,而本地方法栈服务于Native方法


参考资料

《深入理解Java虚拟机》 —— 周志明 机械工业出版社
《Java虚拟机 JVM故障诊断与性能优化 第2版》 —— 葛一鸣 电子工业出版社

声明:本文内容由网友自发贡献,转载请注明出处:【wpsshop】
推荐阅读
相关标签
  

闽ICP备14008679号