JVM详解 本文详细讲解了JVM(Java Virtual Machine)的方方面面,首先由java的特性来描绘VM 的大致应用,再细细阐述了VM的原理及内存管理机制和调优.最后讲述了与VM密切相 关的Java GC机制 本文内容大多来自网络,但内容十分丰富,是学习VM的好资料。 后面会再针对V的两大职责class loader和execution engine进行讲解 若有疑问<ymkyve501 @gmail.com》 月录 Java相关 .2 1.1Java定义 .2 1.2Java的开发流程 2 1.3Java运行的原理 3 1.4半编译半解释. 双 1.5平台无关性 .5 JVM内存模型 .5 2.1JVM规范 .6 2.2 Sun JVM........... .9 2.3 SUN JVM内存管理(优化) 10 2.4 SUN JVM调优… 13 2.5.JVM简单理解. .16 2.5.1Java栈. 16 2.5.2堆 16 2.5.3堆栈分离的好处…19 2.5.4堆(heap)和栈(stack) 19 JAVA垃圾收集器 .20 3.1垃圾收集简史 20 3.2常见的垃圾收集策略.… .20 3.2.1 Reference Counting(引用计数) .20 3.2.2跟踪收集器. …21 3.3JVM的垃圾收集策略… .25 3.3.1 Serial Collector...... .25 3.3.2 Parallel Collector........... ,25 3.3.3 Concurrent Collector....... .26 Java虚拟机(VM)参数配置说明… 26
JVM 详解 本文详细讲解了 JVM(Java Virtual Machine)的方方面面,首先由 java 的特性来描绘 JVM 的大致应用,再细细阐述了 JVM 的原理及内存管理机制和调优.最后讲述了与 JVM 密切相 关的 Java GC 机制. 本文内容大多来自网络,但内容十分丰富,是学习 JVM 的好资料. 后面会再针对 JVM 的两大职责 class loader 和 execution engine 进行讲解 若有疑问 目录 Java 相关............................................................................................................................. 2 1.1Java 定义.............................................................................................................. 2 1.2Java 的开发流程.................................................................................................. 2 1.3Java 运行的原理.................................................................................................. 3 1.4 半编译半解释...................................................................................................... 4 1.5 平台无关性.......................................................................................................... 5 JVM 内存模型 ................................................................................................................... 5 2.1 JVM 规范.............................................................................................................. 6 2.2 Sun JVM............................................................................................................... 9 2.3 SUN JVM 内存管理(优化)................................................................................ 10 2.4 SUN JVM 调优.................................................................................................... 13 2.5.JVM 简单理解.................................................................................................... 16 2.5.1 Java 栈................................................................................................... 16 2.5.2 堆............................................................................................................ 16 2.5.3 堆栈分离的好处.................................................................................... 19 2.5.4 堆(heap)和栈(stack)......................................................................... 19 JAVA 垃圾收集器 ............................................................................................................. 20 3.1 垃圾收集简史.................................................................................................... 20 3.2 常见的垃圾收集策略........................................................................................ 20 3.2.1 Reference Counting(引用计数)....................................................... 20 3.2.2 跟踪收集器............................................................................................ 21 3.3 JVM 的垃圾收集策略......................................................................................... 25 3.3.1 Serial Collector.................................................................................... 25 3.3.2 Parallel Collector ..................................................................................... 25 3.3.3 Concurrent Collector................................................................................ 26 Java 虚拟机(JVM)参数配置说明................................................................................ 26
Java相关 1.1Java定义 一种简单、面向对象、分布式、跨平台、半编译半解释、健壮、 安全、高性能、多线程的动态的语言一Sun定义 1.2Java的开发流程
Java 相关 1.1Java 定义 1.2Java 的开发流程
Java程序的开发流程★ class HelloWorld public static void main(String args[]){ 编写并运行杞序 System.out.printin("Hello Hello World World!"): 输写0a源程序,并保行 保存HelloWorld源代码 后级名java 保存后做名为 ·所有代码必须保存为扩展名 a的文件 java ·源文件名称必须和类名相同 ·class关键字后面的即类名 ,class文件 正确的文件名为: HelloWorld.java 编译源代码: 运行va文#务 javac HelloWorld.java 运行结果 Hello World 运行程序: 在0口下 生成结果 java HelloWorld 1.3Java运行的原理
1.3Java 运行的原理
Java运行的原理 A.java B.java C.java A.class B.class C.class 通过本 ↓↓↓ 地或网 络传输 Java Java Java Java编译器 Class 虚拟机 虚拟机 虚拟机 文件 A.class B.class C.class Object.class String.class 程序的class:文件 Java API的Class文件 Java运行的原理 av治源程序(村展名为java JVM (Java Virtual achine)一Java虚拟机 ava字节码文件(由打展名为.class) √一个虚构出来的计算机 行 √通过在实际的计算机上仿 JVM撞概机 真模拟各种计算机功能来 Linux卜的 能节依解箱 实现的。 ava字节码 Jav节 解释程序 的CPU √Java虚拟机有自己完善的硬 件架构如处理器、堆栈、 机机器指 寄存器等,还具有相应的指 Windows 令系统。 操作系统 操作系绕 1.4半编译半解释
1.4 半编译半解释
·半编译半解释? √系统先将用户输入的指令翻译成一种通用的,比较规则的中间形 式的代码,保密性强,运行时则由所在机器的解释器进行解释 √java语言的开发效率高,但执行效率低。(相当于c++的 55%) Source Code puble class HalloWorld public ste void mainString arg) Naf学achine古Cada Syster.out printnHello Wond) Compiler 广Interprte Class File Load Java Virtual Bylecode Machine 1.5平台无关性 平台无关性? 何谓平台:即一套特定的硬件再加上运行其上的操作系统,即硬件十软件。编程 语言对不同平台的支持有所不同。(VB、C/C+、Java) Java完全不用修改任何源代码,也不用重新编译就可以直接移植到其他平台。 √Java的平台无关性给程序的部署带来了很大的灵活性,节约开发和升级成本。 怎样理解平台无关性呢?JVM(java Virtual Machine)起到了主要作用。JM是运 行在平台之上的程序,它能够虚拟出一台目标机,所有字节码就是在虚拟出的目 标机上运行。 程序不可能在所有的平台上都可以运行:(1)因为不同平台的内存管理模式和 CPU的指令集等都有很大的差别。(2)为了让java实现平台无关性,Sun公司在不 同平台上用软件模拟出虚拟目标机,虚拟出CPU指令集和内存。(3)因此虽然平 台间的差异比较大,但是虚拟出来的JVM是完全一样的。(4)Java的字节码仅仅 运行在JVM上,不会和平台的底层直接打交道。(5)JM根据平台的不同,把字节 码解释成不同的本地代码(6)JVM就像翻译,把通用的普通话翻译成不同地方特 色的方言。 √但是有一个缺点:java代码必须要经过JVM解释才能运行,使得java运行的效率降 低。 √WORA:Write Once,.Run Anywhere(一次编写,到处运行) JVM内存模型
1.5 平台无关性 JVM 内存模型
2.1JVM规范 JVM specification对JWM内存的描述 首先我们来了解JVM specification中的JVM整体架构。如下图: CLASS FILES CLASS LOADER RUNTIME DATA AREA METHOD AREA JAVA STACK NATIVE METHOD STACK HEAP PROGRAM COUNTER REGISTER NATIVE NATIVE EXECUTION ENGINE INTERFACE LIBRARIES RUNTIME DATA AREAS SHARED AMONG ALL THREADS THREAD SPECIFIC RUNTIME DATA AREAS javabeanz.wordpress.com 主要包括两个子系统和两个组件:Class loader(类装载器)子系统, Execution engine(执行引擎)子系统;Runtime data area(运行时数据区域) 组件,Native interface(本地接口)组件。 Class loader子系统的作用:根据给定的全限定名类名(如 java.lang.Object)来装载class文件的内容到Runtime data area中的method area(方法区域)。Javsa程序员可以extends java.lang.ClassLoader类来写自 己的Class1 oader. Execution engine子系统的作用:执行classes中的指令。任何JVM specification实现(JDK)的核心是Execution engine,换句话说:Sun的JDK 和IBWM的JDK好坏主要取决于他们各自实现的Execution engine的好坏。每个 运行中的线程都有一个Execution engine的实例。 Native interface组件:与native libraries交互,是其它编程语言交 互的接口。 Runtime data area组件:这个组件就是JVM中的内存。下面对这个部分 进行详细介绍
2.1 JVM 规范 JVM specification 对 JVM 内存的描述 首先我们来了解 JVM specification 中的 JVM 整体架构。如下图: 主要包括两个子系统和两个组件: Class loader(类装载器) 子系统, Execution engine(执行引擎) 子系统;Runtime data area (运行时数据区域) 组件, Native interface(本地接口)组件。 Class loader 子系统的作用 :根据给定的全限定名类名(如 java.lang.Object)来装载 class 文件的内容到 Runtime data area 中的 method area(方法区域)。Javsa 程序员可以 extends java.lang.ClassLoader 类来写自 己的 Class loader。 Execution engine 子系统的作用 :执行 classes 中的指令。任何 JVM specification 实现(JDK)的核心是 Execution engine, 换句话说:Sun 的 JDK 和 IBM 的 JDK 好坏主要取决于他们各自实现的 Execution engine 的好坏。每个 运行中的线程都有一个 Execution engine 的实例。 Native interface 组件 :与 native libraries 交互,是其它编程语言交 互的接口。 Runtime data area 组件:这个组件就是 JVM 中的内存。 下面对这个部分 进行详细介绍
JVM Shared among all Threads Thread 1 Heap Thread 2 PC Stack Per Method Basis Class Instances and Arrays P℃Stack Per Method Basis Instance Variables Frame 1 Frame 2 Frame 1 Frame 2 Reference Local Variables Partial Results Local Variables Partial Results (Including Parameters) (including Parameters) Operand Stack Method Area Operand Stack Runtime Constant Pool Method Code Per Class Basis Static Variables and Methods Runtime Constant Pool Native Method Stacks Method Code Per Class Basis 调用 Static Variables and Methods 水地library V之外,荣作系统内存 Runtime data area的整体架构图 Runtime data area主要包括五个部分:Heap(堆),Method Area(方法区 域),Java Stack(java的栈),Program Counter(程序计数器),Native method stack(本地方法栈)。Heap和Method Area是被所有线程的共享使用的;而 Java stack,Program counter和Native method stack是以线程为粒度的
Runtime data area 的整体架构图 Runtime data area 主要包括五个部分:Heap (堆), Method Area(方法区 域), Java Stack(java 的栈), Program Counter(程序计数器), Native method stack(本地方法栈)。Heap 和 Method Area 是被所有线程的共享使用的;而 Java stack, Program counter 和 Native method stack 是以线程为粒度的
每个线程独自拥有。 Heap Java程序在运行时创建的所有类实或数组都放在同一个堆中。而一个Java虚拟 实例中只存在一个堆空间,因此所有线程都将共享这个堆。每一个java程序独 占一个JVM实例,因而每个java程序都有它自己的堆空间,它们不会彼此干扰。 但是同一java程序的多个线程都共享着同一个堆空间,就得考虑多线程访问对 象(堆数据)的同步问题。(这里可能出现的异常java.lang.OutOfMemoryError: Java heap space) Method area 在Java虚拟机中,被装载的class的信息存储在Method area的内存中。当虚 拟机装载某个类型时,它使用类装载器定位相应的class文件,然后读入这个 class文件内容并把它传输到虚拟机中。紧接着虚拟机提取其中的类型信息,并 将这些信息存储到方法区。该类型中的类(静态)变量同样也存储在方法区中。 与Heap一样,method area是多线程共享的,因此要考虑多线程访问的同步问 题。比如,假设同时两个线程都企图访问一个名为Lava的类,而这个类还没有 内装载入虚拟机,那么,这时应该只有一个线程去装载它,而另一个线程则只能 等待。(这里可能出现的异常java.lang.OutOfMemoryError:PermGen full) Java stack Java stack以帧为单位保存线程的运行状态。虚拟机只会直接对Java stack执行两种操作:以帧为单位的压栈或出栈。每当线程调用一个方法的时 候,就对当前状态作为一个帧保存到java stack中(压栈):当一个方法调用返 回时,从java stack弹出一个帧(出栈)。栈的大小是有一定的限制,这个可能 出现StackOverF1ow问题。下面的程序可以说明这个问题。 public class TestStackOverFlow public static void main(String[]args){ Recursive r=new Recursive(: r.doit(10000); /Exception in thread "main" java.lang.StackOverflowError } } class Recursive public int doit(int t){ if(t<=1){ return 1;
每个线程独自拥有。 Heap Java 程序在运行时创建的所有类实或数组都放在同一个堆中。而一个 Java 虚拟 实例中只存在一个堆空间,因此所有线程都将共享这个堆。每一个 java 程序独 占一个 JVM 实例,因而每个 java 程序都有它自己的堆空间,它们不会彼此干扰。 但是同一 java 程序的多个线程都共享着同一个堆空间,就得考虑多线程访问对 象(堆数据)的同步问题。(这里可能出现的异常 java.lang.OutOfMemoryError: Java heap space) Method area 在 Java 虚拟机中,被装载的 class 的信息存储在 Method area 的内存中。当虚 拟机装载某个类型时,它使用类装载器定位相应的 class 文件,然后读入这个 class 文件内容并把它传输到虚拟机中。紧接着虚拟机提取其中的类型信息,并 将这些信息存储到方法区。该类型中的类(静态)变量同样也存储在方法区中。 与 Heap 一样,method area 是多线程共享的,因此要考虑多线程访问的同步问 题。比如,假设同时两个线程都企图访问一个名为 Lava 的类,而这个类还没有 内装载入虚拟机,那么,这时应该只有一个线程去装载它,而另一个线程则只能 等待。 (这里可能出现的异常 java.lang.OutOfMemoryError: PermGen full) Java stack Java stack 以帧为单位保存线程的运行状态。虚拟机只会直接对 Java stack 执行两种操作:以帧为单位的压栈或出栈。每当线程调用一个方法的时 候,就对当前状态作为一个帧保存到 java stack 中(压栈);当一个方法调用返 回时,从 java stack 弹出一个帧(出栈)。栈的大小是有一定的限制,这个可能 出现 StackOverFlow 问题。 下面的程序可以说明这个问题。 public class TestStackOverFlow { public static void main(String[] args) { Recursive r = new Recursive(); r.doit(10000); // Exception in thread "main" java.lang.StackOverflowError } } class Recursive { public int doit(int t) { if (t <= 1) { return 1;
return t doit(t -1); Program counter 每个运行中的ava程序,每一个线程都有它自己的PC寄存器,也是该线程启动时创建 的。PC寄存器的内容总是指向下一条将被执行指令的饿“地址”,这里的 “地址”可以是一个本地指针,也可以是在方法区中相对应于该方法起始指 令的偏移量。 Native method stack 对于一个运行中的Jva程序而言,它还能会用到一些跟本地方法相关的数据区。当某个 线程调用一个本地方法时,它就进入了一个全新的并且不再受虚拟机限制的世界。本地 方法可以通过本地方法接口来访问虚拟机的运行时数据区,不止与此,它还可以做任何 它想做的事情。比如,可以调用寄存器,或在操作系统中分配内存等。总之,本地方法 具有和VM相同的能力和权限。(这里出现VM无法控制的内存溢出问题native heap OutOfMemory】 2.2 Sun JVM Sun JVM中对JVM Specification的实现(内存部分) JVM Specification只是抽象的说明了VM实例按照子系统、内存区、数据类型以及指令 这几个术语来描述的,但是规范并非是要强制规定Jva虚拟机实现内部的体系结构, 更多的是为了严格地定义这些实现的外部特征。 Sun JVM实现中:Runtime data area(VM内存)五个部分中的Java Stack,Program Counter,,Native method stack三部分和规范中的描述基本一致;但对Heap和Method Area进行了自己独特的实现。这个实现和Sun JVM的Garbage collector(垃圾回收)机 制有关,下面的章节进行详细描述。 垃圾分代回收算法(Generational Collecting) 基于对对象生命周期分析后得出的垃圾回收算法。把对象分为年青代、年老代、持久 代,对不同生命周期的对象使用不同的算法(上述方式中的一个)进行回收。现在的垃 圾回收器(从J2SE1.2开始)都是使用此算法的
} return t + doit(t - 1); } } Program counter 每个运行中的 Java 程序,每一个线程都有它自己的 PC 寄存器,也是该线程启动时创建 的。PC 寄存器的内容总是指向下一条将被执行指令的饿“地址”,这里的 “地址”可以是一个本地指针,也可以是在方法区中相对应于该方法起始指 令的偏移量。 Native method stack 对于一个运行中的 Java 程序而言,它还能会用到一些跟本地方法相关的数据区。当某个 线程调用一个本地方法时,它就进入了一个全新的并且不再受虚拟机限制的世界。本地 方法可以通过本地方法接口来访问虚拟机的运行时数据区,不止与此,它还可以做任何 它想做的事情。比如,可以调用寄存器,或在操作系统中分配内存等。总之,本地方法 具有和 JVM 相同的能力和权限。 (这里出现 JVM 无法控制的内存溢出问题 native heap OutOfMemory ) 2.2 Sun JVM Sun JVM 中对 JVM Specification 的实现(内存部分) JVM Specification 只是抽象的说明了 JVM 实例按照子系统、内存区、数据类型以及指令 这几个术语来描述的, 但是规范并非是要强制规定 Java 虚拟机实现内部的体系结构, 更多的是为了严格地定义这些实现的外部特征。 Sun JVM 实现中:Runtime data area(JVM 内存) 五个部分中的 Java Stack , Program Counter, Native method stack 三部分和规范中的描述基本一致;但对 Heap 和 Method Area 进行了自己独特的实现。这个实现和 Sun JVM 的 Garbage collector(垃圾回收)机 制有关,下面的章节进行详细描述。 垃圾分代回收算法(Generational Collecting) 基于对对象生命周期分析后得出的垃圾回收算法。把对象分为年青代、年老代、持久 代,对不同生命周期的对象使用不同的算法(上述方式中的一个)进行回收。现在的垃 圾回收器(从 J2SE1.2 开始)都是使用此算法的
Tenured Eden lenA IenA en Young Perm 如上图所示,为Java堆中的各代分布。 1.Young(年轻代)VM specification中的Heap的一部份 年轻代分三个区。一个Eden区,两个Survivor区。大部分对象在Eden区中生成。当 Eden区满时,还存活的对象将被复制到Survivor区(两个中的一个),当这个Survivor 区满时,此区的存活对象将被复制到另外一个Survivor区,当这个Survivor去也满了的 时候,从第一个Survivor区复制过来的并且此时还存活的对象,将被复制“年老区 (Tenured)”。需要注意,Survivor的两个区是对称的,没先后关系,所以同一个区 中可能同时存在从Eden复制过来对象,和从前一个Survivor复制过来的对象,而复制 到年老区的只有从第一个Survivor去过来的对象。而且,Survivor区总有一个是空的。 2.Tenured(年老代)VM specification中的Heap的一部份 年老代存放从年轻代存活的对象。一般来说年老代存放的都是生命期较长的对象。 3.Perm(持久代)VM specification中的Method area 用于存放静态文件,如今va类、方法等。持久代对垃圾回收没有显著影响,但是有些 应用可能动态生成或者调用一些class,例如Hibernate等,在这种时候需要设置一个比 较大的持久代空间来存放这些运行过程中新增的类。持久代大小通过-XX:MaxPermSize= 进行设置。 2.3 SUN JVM内存管理(优化)
如上图所示,为 Java 堆中的各代分布。 1. Young(年轻代)JVM specification 中的 Heap 的一部份 年轻代分三个区。一个 Eden 区,两个 Survivor 区。大部分对象在 Eden 区中生成。当 Eden 区满时,还存活的对象将被复制到 Survivor 区(两个中的一个),当这个 Survivor 区满时,此区的存活对象将被复制到另外一个 Survivor 区,当这个 Survivor 去也满了的 时候,从第一个 Survivor 区复制过来的并且此时还存活的对象,将被复制“年老区 (Tenured)”。需要注意,Survivor 的两个区是对称的,没先后关系,所以同一个区 中可能同时存在从 Eden 复制过来 对象,和从前一个 Survivor 复制过来的对象,而复制 到年老区的只有从第一个 Survivor 去过来的对象。而且,Survivor 区总有一个是空的。 2. Tenured(年老代)JVM specification 中的 Heap 的一部份 年老代存放从年轻代存活的对象。一般来说年老代存放的都是生命期较长的对象。 3. Perm(持久代) JVM specification 中的 Method area 用于存放静态文件,如今 Java 类、方法等。持久代对垃圾回收没有显著影响,但是有些 应用可能动态生成或者调用一些 class,例如 Hibernate 等,在这种时候需要设置一个比 较大的持久代空间来存放这些运行过程中新增的类。持久代大小通过-XX:MaxPermSize= 进行设置。 2.3 SUN JVM 内存管理(优化)