JVM介绍

运行时数据区

运行时数据区能够分为:办法区、堆、虚拟机栈、本地办法栈、程序计数器.其中办法区和堆为线程共享区,虚拟机栈、本地办法栈和程序计数器为线程独享区.线程独享区的内存空间随线程的创立被开拓,随线程的销毁被回收,所以垃圾回收器次要是作用在办法区和堆区.

堆能够被分为新生代和老年代,其中新生代由能够分为eden区和surrivor1、surrrivor2区.老年代和新生代默认占比为2:1,能够通过-XX:NewRatio=2配置从新设置占比.Eden和S1、S2的占比为8:1:1,能够通过-XX:NewSurrivor=4配置从新设置占比.

堆大小设置

-Xms:256M 设置JVM的初始内存大小,默认是为零碎内存的1/64之一;
-Xmx:256M 设置JVM的最大内存大小,默认是为零碎内存的1/4之一;
通常咱们优化是将初始化内存和最大内存设置为一样的值,这样能够防止不必要的major gc或full gc,造成STW,引起程序利用不必要的卡顿.

回收算法

新生代个别都会采纳复制算法,该算法的效率较高且满足新生代的对象个性.当新生代数据区满时,个别状况下新生代百分之八十左右的数据都可能被回收掉,留下的数据和S1区域会被回收的数据一起复制到S2区.第二次放生minor gc时,eden和S2存活的对象会被复制到S1区,默认状况下,存活的对象默认状况下达到15时,下次产生minor gc时,该存活的对象会放到老年代中.能够通过-XX:MaxTenuringThreshold=15配置从新设置新生代对象的最大年龄.
老年代会采纳标记革除或标记整顿算法.标记革除会产生内存空间碎片,须要额定保护一个闲暇列表,但相较于标记整顿算法会快一些.标记整顿是先将标记存活的对象都压缩到内存的一端,最初在清理掉边界之外的所有空间,所以不会产生内存碎片.

办法区

办法区是JVM标准,不同jdk版本之间的实现各有不同.jdk1.7及以前,办法区的实现是永恒代(Permanent Generation),能够通过-XX:Permsize和-XX:MaxPermsize来调配永恒代的初始空间和最大可调配空间.JDK8采纳元空间来替换永恒代,最大的区别是元空间不在JVM设置的内存中,而是应用本地内存,能够通过-XX:MetaspaceSize和-XX:MaxMetaspaceSize指定元空间的初始和最大空间.
办法区内寄存的构造为类信息和运行时常量池,字符串常量池、动态变量在1.7及当前被划分到了堆中.该区也会产生垃圾回收解决.

虚拟机栈默认大小为1M,当遇到递归次数较多的办法,可能会产生StackOverFlowError异样,能够通过-Xss100m指令配置调整栈内存大小.
每个线程都会对应一个虚拟机栈,多个线程就会对应多个虚拟机栈.一个虚拟机栈外面会蕴含多个栈帧,每一个栈帧是为办法执行而创立的,栈帧中形容的是java办法执行的内存模型.
栈帧中蕴含局部变量表、操作数栈、动静链接、返回地址.

局部变量表

它定义为数字数组,次要用于存储办法参数和定义在办法内的局部变量.局部变量表所需的容量在编译期间确定,在运行期间是不扭转其容量.

操作数栈

它是一个后进先出的栈,依据字节码指令,往栈中写入或取出数据.操作包含:复制、替换、求和等.

动静链接

被调用的办法在编译期间无奈被确定下来,只能在程序运行时将调用办法的符号援用转换为间接援用,因为这种援用转换的过程具备动态性,被称为动静链接.

办法返回地址

办法在返回的时候须要在栈帧中保留一些信息,用来复原调用该办法的下层办法的执行状态.

程序计数器

程序计数器就是一块较小的内存空间,它是以后线程执行字节码的行号指示器.每个栈帧都会保护一个属于本人的程序计数器,这个计数器就是用来记录执行的地址的.

本地办法栈

本地办法栈和虚拟机栈类所施展的作用十分相似.它们之间的区别就是虚拟机栈为虚拟机执行Java办法服务,而本地办法栈为虚拟机所应用到的native办法服务.本地办法只有被调用之前,DLL才会被加载,即通过调用java.system.loadLibrary()实现的.

[下一章节 介绍执行引擎]