白话Java基础系列—JVM内存结构
本系列呢,主要将我理解的Java基础内容,以比较白话的方式,解释出来,希望能帮助大家快速的理解一些概念。
本小结将分享下 JVM内存结构。
文章目录
一、 什么是JVM ?
JVM 是 JRE(Java Runtime Enviroment)的一部分, 它是一个虚拟的计算机,通过在实际计算机上仿真模拟计算机的各种功能来实现的。有完善的硬件架构, 如处理器、堆栈、寄存器等,还具有指令系统。
主要工作是解释自己指令集(字节码)映射成本地CPU指令集或OS的系统调用。(翻译成本地计算机可识别的指令集,并去调用)
二、 JVM内存结构
参考文档: http://47.103.216.138/archives/80, 图片直接引用了 Hollis博客里的图片。
2.1 如何理解JVM内存结构?
JVM内存结构是JVM定义的一个规范,描述Java程序运行时,JVM 管理的不同的数据区域;
主要可以分为两类: 线程独享型/线程共享性
线程独享型:The PC Register、JVM Stack、Native Method Stack
线程共享性: JVM Heap、Method Area(Run-Time Constant Pool)
2.2 JVM 各数据区域作用是什么?
2.2.1 方法区(永久代、非堆)
存储JVM 加载的类信息、常量、静态变量。线程共享区域,默认为16M, 最大值为64M, 可以通过 -XX:PermSize 和 -XX:MaxPermSize 参数限制方法区大小;
运行时常量池:在类的加载阶段,将class文件常量池中内容存放到运行时常量池(还保持这符号引用)中。经过链接过程的resolve阶段后, 把符号引用替换为直接应用;
关于符号引用和直接引用参考文档: https://juejin.im/post/6844903785416884231
2.2.2 虚拟机栈
方法执行时,都会创建一个栈帧,用于存储局部变量表、操作栈、方法出口等信息,每个方法执行完的过程,就对应着一个战阵在虚拟机栈中从入栈到出栈的过程。
生命周期与线程相同,是线程私有的。
2.2.3. 本地方法栈
JVM栈执行的Java 方法, 而本地方法栈执行的是Native方法。
2.2.4 堆(JAVA堆,GC堆)
综述
是有JVM 管理的内存中最大的一个区域, JVM启动时创建,存放实例及数组。
默认大小为物理内存的 1/64, 最大为物理内存的 1/4, 可以通过 -Xms 和 -Xmx 参数进行控制。如: -Xms500m;
默认Idle < 40%, 将使用 Xmx; 当Idle > 70%, 将使用 Xms, 为了避免运行时,频繁调整,我们通常将 Xms与Xmx设置为相同数值;
细节
JDK默认堆空间分配比例
现代垃圾回收器都是采用分代回收算法,堆被划分为 新生代(Young Generation)和老年代(Old Generation);
新生代:新生代主要是存放新创建的对象, 可以通过 -Xmn控制新生代大小,新生代又分为 Eden Space 和 Survivor Space,SUN JVM 一般将比例设置为 8比1, 也可以通过-XX:SurvivorRation来调整Survivor和Eden大小;
Eden Span 存放新生对象; Survivor Space存放每次Minor GC后存活的对象
老年代:用来存放应用生命周期长的存活对象(新生代多次GC依然存活的对象),如缓存对象;但是不是所有的新创建的对象都会在新生代中,大对象和大数组都会直接进入老年代; 年老代 = Xmx -Xmn
2.2.5 程序计数器
是JVM里 记录当前线程所执行的字节码的行号指示器。在JVM的模型里,字节码解释器工作时,是通过改变计数器来选取下一条需要执行的字节码命令的,分支、循环、异常处理、线程恢复都依赖计数器完成。
3 直接内存
直接内存并不是Java虚拟机内存的一部分,也不是Java虚拟机规范中定义的内存区域。JDK4中新加入NIO,引入了通道与缓冲区的IO方式,它可以调用Native方法直接分配对外内存,这个对外内存就是本机内存,不会影响到对内存的大小。
4 如何设置JVM各数据区域大小 ?
可以用 JConsole 查看程序运行时,Java中堆内存的大小,来调整各参数。
5 PS:遗留难点问题:
快问快答,简要描述。
5.1 常量池
5.1.1 什么是常量?
被final修饰得成员变量, 静态变量,实例变量,局部变量;
5.1.2 什么是常量池?
Class中除了有类版本,字段、方法等描述信息外,还有一项信息就是常量池,用来存放编译器编译器生成各种字面量和符号引用;
5.1.3 什么是方法区运行时常量池?
常量池中得内容,在类加载后,进入方法区。
5.1.4 常量池得好处?
实现对象得共享,避免频繁创建和销毁对象
5.2 什么时字面量和符号引用变量?
final int i = 1;(字面量) 符号应用: 类和接口的全限定名java.lang.Object;字段的名称和描述符I;方法的名称和描述符()V
可以参考: http://47.103.216.138/archives/2517
s 、yushuai_w 都会进入类常量池, s 就是符号引用, yushuai 就是字面量
String s = "yushuai_w";