JDK1.6、JDK1.7、JDK1.8 内存模型对比

Python011

JDK1.6、JDK1.7、JDK1.8 内存模型对比,第1张

如图25-1 是 JDK 1.6、1.7、1.8 的内存模型演变过程,其实这个内存模型就是 JVM 运行时数据区依照JVM虚拟机规范的具体实现过程。

JDK 1.6:程序计数器、Java虚拟机栈、本地方法栈、堆、方法区[永久代](字符串常量池、静态变量、运行时常量池、类常量池)

JDK 1.7:程序计数器、Java虚拟机栈、本地方法栈、堆(字符串常量、静态变量)、方法区[永久代](运行时常量池、类常量池)

JDK 1.8:程序计数器、Java虚拟机栈、本地方法栈、堆(字符串常量)、元数据(静态变量、运行时常量池、类常量池)

JDK 1.8 JVM 的内存结构主要由三大块组成:堆内存、元空间和栈,Java 堆是内存空间占据最大的一块区域。

Java 堆,由年轻代和年老代组成,分别占据1/3和2/3。

年轻代又分为三部分, Eden 、 From Survivor 、 To Survivor ,占据比例为8:1:1,可调。

元空间从虚拟机Java堆中转移到本地内存,默认情况下,元空间的大小仅受本地内存的限制,说白了也就是以后不会因为永久代空间不够而抛出OOM异常出现了。 jdk1.8以前版本的 class和JAR包数据存储在 PermGen下面 ,PermGen 大小是固定的,而且项目之间无法共用,公有的 class,所以比较容易出现OOM异常。

升级JDK 1.8后,元空间配置参数,-XX:MetaspaceSize=512M XX:MaxMetaspaceSize=1024M。

小技巧通过jps、jinfo查看元空间,如下:

通过jinfo查看默认MetaspaceSize大小(约20M),MaxMetaspaceSize比较大。

其他:关于JDK1.8 元空间的介绍:  Move part of the contents of the permanent generation in Hotspot to the Java heap and the remainder to native memory. http://openjdk.java.net/jeps/122

能够使用更少的内存以及延迟获取更大的吞吐量。Java是一门面向对象编程语言,1990年代初由詹姆斯高斯林等人开发出Java语言的雏形,最初被命名为Oak,java虚拟内存模型的性能调优方法的重要性是能够使用更少的内存以及延迟获取更大的吞吐量。虚拟机是一种抽象化的计算机,通过在实际的计算机上仿真模拟各种计算机功能来实现的。

java内存区域主要分程序计数器、Java虚拟机栈、本地方法栈、Java堆、方法区、直接内存。其中程序计数器、Java虚拟机栈、本地方法栈属于线程隔离,即他们都有自己的线程归属,其他属于线程共享的。

1、程序计数器。这个是当前线程正在执行的字节码行号指示器。根据这里面的内存数据来确定程序接下来执行的指令。每个线程都有一个,相互隔离,线程切换回来时才知道怎么执行。如果执行的是方法,这里记录的是虚拟机字节码指令的地址。当执行的是Native方法的时候为空(Undefined)。

2、Java虚拟机栈。每个线程私有,里面装的多个栈帧,每个栈帧对于的一个方法。里面存储的是Java方法的内存模型。相当于描述的是一个方法需要的内容。

3、本地方法栈。线程私有,和上一个Java虚拟机栈作用相似,Java虚拟机栈是为Java方法服务,本地方法栈是为Native服务。

4、Java虚拟机管理最大的一块,线程共享,存放对象实例和数组。分新生代(1/3)和老年代(2/3),新生代还可以分Eden(8/10)、FromSurvivor(1/10)、ToSurvivor(1/10),是主要根据垃圾清理来分的。

5、方法区。线程共享,主要存储被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码。运行时常量池也是方法区的一部分,比如String有一个常量池,他就是放到这个里面的。

6、直接内存。NIO通过使用Native函数库直接分配对外内存。