令人放心食用的JVM指南
食前指南
Java程序是交给JVM执行的,所谓Java内存(JVM内存)也就是讲JVM运行时数据区,首先我们先来看下Java程序的执行过程。
菜单1.Method Area(方法区)
方法区也被称为永久代,方法区和堆一样是属于线程共享区域,所以要考虑数据的线程安全问题。方法区包含运行时常量池,在类和接口被加载到JVM之后,对应的运行时常量池就被创建出来。
在方法区中存储了已被虚拟机加载的类的信息(类加载器在类加载时从类文件中提取出来的,比如类的名称、方法信息、字段信息)、静态变量、常量以及即时编译器编译后的代码等数据。
JVM规范中方法区无法满足内存分配需求的时候也会抛出OOM,虽然规范中方法区不必实现垃圾收集,方法区中也是有垃圾回收的,而他回收的对象是废弃常量和无用类。
菜单2.Heap(堆)
堆也是线程共享区域,在JVM中只有一个堆。
堆是JVM中内存占用最大的区域,其唯一的用途就是用存放对象实例和数组
菜单3.VM Stack(Java栈/虚拟机栈)
Java栈是Java方法执行的内存模型。
Java栈中存放的是一个个的栈帧,每个栈帧对应一个被调用的方法,在栈帧中包括局部变量表、操作栈数、动态链接、方法出口等等。
线程私有,每个线程对应一个Java虚拟机栈,生命周期是与线程共进退。每个Java方法在被调用的时候都会创建一个栈帧,并入栈。一旦完成调用,则出栈。所有的栈帧都出栈之后线程也就完成了自己的使命。
菜单4.Native Method Stack(本地方法栈)
本地方法栈与Java栈的作用和原理非常相似。Java栈是为虚拟机使用到的Java方法服务,而本地方法栈则是为虚拟机使用到的Native服务。
菜单5.Program Counter Register(程序计数器)
程序计数器是指CPU中的寄存器也被称为PC寄存器。每个处理器都只会执行一条线程中的指令,因此每个线程都有属于它自己的PC寄存器。
PC寄存器的作用是记录当前线程执行的虚拟机字节码的指令地址,如果该线程在执行一个Native方法,那么指令地址为“Undefined”。
特别菜单.Version Difference(版本差异)
JDK1.7版本把运行时常量池、静态变量等等从方法区中移出放在堆中。
JDK1.8版本把方法区剥离出来,放在本地内存里面。简单说就是“元数据区代替了永久代”,“元数据空间并不在虚拟机中,使用的是本地内存”。
点心.Useless(废弃常量和无用类)
废弃常量是指不在任何地方被引用则会被标记成废弃常量。
标记为无用类需要三个条件:
1.Java堆中不存在该类的任何实例对象;
2.加载该类的类加载器被回收;
3.该类对应的java.lang.Class对象不在任何地方被引用,且无法在任何地方通过反射访问该类的方法。
饮品.Stack(局部变量表和方法出口)
局部变量表包括了八大数据类和对象引用等,我们平时说的引用所在的栈大都是指局部变量表。
当一个方法执行完之后,要返回之前调用它的地方,因此栈帧中必须保存一个方法返回的地址,也就是方法出口。
厨师长语录:
饭菜是否合胃口,请在下方留言,我不一定会看,看了也不一定会回复,因为我每天都要加班。