JVM运行时数据区详解-Heap堆(优化配置、代码样例)
2013-04-12 15:31
239 查看
在Java虚拟机中,堆(Heap)是可供各条线程共享的运行时内存区域,也是供所有类实例和数组对象分配内存的区域。
Java堆在虚拟机启动的时候就被创建,它存储了被自动内存管理系统(Automatic Storage Management System,也即是常说的“Garbage Collector(垃圾收集器)”)所管理的各种对象,这些受管理的对象无需,也无法显式地被销毁。本规范中所描述的Java虚拟机并未假设采用什么具体的技术去实现自动内存管理系统。虚拟机实现者可以根据系统的实际需要来选择自动内存管理技术。Java堆的容量可以是固定大小的,也可以随着程序执行的需求动态扩展,并在不需要过多空间时自动收缩。Java堆所使用的内存不需要保证是连续的。
堆内存分为三部分:
Permanent Space 永久存储区
慢慢琢磨JVM
永久存储区是一个常驻内存区域,用于存放JDK 自身所携带的Class,Interface 的元数据,也
就是说它存储的是运行环境必须的类信息,被装载进此区域的数据是不会被垃圾回收器回收掉的,
关闭JVM 才会释放此区域所占用的内存。
Young Generation Space 新生区
新生区是类的诞生、成长、消亡的区域,一个类在这里产生,应用,最后被垃圾回收器收集,
结束生命。新生区又分为两部分: 伊甸区(Eden space)和幸存者区(Survivor pace),所有的
类都是在伊甸区被new 出来的。幸存区有两个: 0 区(Survivor 0 space)和1 区(Survivor 1 space)。
当伊甸园的空间用完时,程序又需要创建对象,JVM 的垃圾回收器将对伊甸园区进行垃圾回收,将
伊甸园区中的不再被其他对象所引用的对象进行销毁。然后将伊甸园中的剩余对象移动到幸存0
区。若幸存0 区也满了,再对该区进行垃圾回收,然后移动到1 区。那如果1 区也满了呢?再移动
到养老区。
Tenure generation space养老区
养老区用于保存从新生区筛选出来的JAVA 对象,一般池对象都在这个区域活跃。 三个区的
示意图如下:
Method Area 方法区
方法区是被所有线程共享,该区域保存所有字段和方法字节码,以及一些特殊方法如构造函数,
接口代码也在此定义。
PC Register 程序计数器
每个线程都有一个程序计数器,就是一个指针,指向方法区中的方法字节码,由执行引擎读取
下一条指令。
Native Method Stack 本地方法栈
Java虚拟机实现应当提供给程序员或者最终用户调节Java堆初始容量的手段,对于可以动态扩展和收缩Java堆来说,则应当提供调节其最大、最小容量的手段。
Java堆可能发生如下异常情况:
如果实际所需的堆超过了自动内存管理系统能提供的最大容量,那Java虚拟机将会抛出一个OutOfMemoryError异常。
同样通过代码来理解一下
?
不停的创建新的对象,来使堆内存溢出。启动参数设置:-Xmx2m
运行结果:
178702
178703
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
大概17w左右开始内存溢出。增大参数看看效果,-Xmx10m
305677
305678
305679
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
由此可见,通过设置-Xmx参数,可以调整JVM中堆的大小,从而可以在内存中保存更多的对象。
再看看另一种OutOfMemoryError: java.lang.OutOfMemoryError: PermGen space。
同样是,通过代码构造一个PermGen space的异常。(OneCoder认为,你会构造出异常,自然就会慢慢理解这个异常是怎么产生的,什么参数会对这个有影响。)
由于PermGen space一般发生在预加载类的过程中,所以OneCoder这里利用tomcat启动来进行测试。设置Tomcat 启动参数为:-server -XX:MaxPermSize=2m -XX:PermSize=2m
java.lang.OutOfMemoryError: PermGen space
at sun.misc.URLClassPath$JarLoader$1.run(URLClassPath.java:608)
果然发生PermGen space异常。如果你逐渐放大该配置,会发现报错的时机逐渐推后,也就是可以加载更多的类。OneCoder给tomcat指定一个合理的值比如: -server -XX:MaxPermSize=64m -XX:PermSize=64m
程序即可重新启动了。
你也可以多做一些试验,验证你的想法,所谓实践出真知。
概念参考:Java虚拟机规范
慢慢琢磨JVM
如非特别注明,本站内容均为OneCoder原创,转载请务必注明作者和原始出处。
本文地址:http://www.coderli.com/jvm-heap-code-overflow
Java堆在虚拟机启动的时候就被创建,它存储了被自动内存管理系统(Automatic Storage Management System,也即是常说的“Garbage Collector(垃圾收集器)”)所管理的各种对象,这些受管理的对象无需,也无法显式地被销毁。本规范中所描述的Java虚拟机并未假设采用什么具体的技术去实现自动内存管理系统。虚拟机实现者可以根据系统的实际需要来选择自动内存管理技术。Java堆的容量可以是固定大小的,也可以随着程序执行的需求动态扩展,并在不需要过多空间时自动收缩。Java堆所使用的内存不需要保证是连续的。
堆内存分为三部分:
Permanent Space 永久存储区
慢慢琢磨JVM
永久存储区是一个常驻内存区域,用于存放JDK 自身所携带的Class,Interface 的元数据,也
就是说它存储的是运行环境必须的类信息,被装载进此区域的数据是不会被垃圾回收器回收掉的,
关闭JVM 才会释放此区域所占用的内存。
Young Generation Space 新生区
新生区是类的诞生、成长、消亡的区域,一个类在这里产生,应用,最后被垃圾回收器收集,
结束生命。新生区又分为两部分: 伊甸区(Eden space)和幸存者区(Survivor pace),所有的
类都是在伊甸区被new 出来的。幸存区有两个: 0 区(Survivor 0 space)和1 区(Survivor 1 space)。
当伊甸园的空间用完时,程序又需要创建对象,JVM 的垃圾回收器将对伊甸园区进行垃圾回收,将
伊甸园区中的不再被其他对象所引用的对象进行销毁。然后将伊甸园中的剩余对象移动到幸存0
区。若幸存0 区也满了,再对该区进行垃圾回收,然后移动到1 区。那如果1 区也满了呢?再移动
到养老区。
Tenure generation space养老区
养老区用于保存从新生区筛选出来的JAVA 对象,一般池对象都在这个区域活跃。 三个区的
示意图如下:
Method Area 方法区
方法区是被所有线程共享,该区域保存所有字段和方法字节码,以及一些特殊方法如构造函数,
接口代码也在此定义。
PC Register 程序计数器
每个线程都有一个程序计数器,就是一个指针,指向方法区中的方法字节码,由执行引擎读取
下一条指令。
Native Method Stack 本地方法栈
Java虚拟机实现应当提供给程序员或者最终用户调节Java堆初始容量的手段,对于可以动态扩展和收缩Java堆来说,则应当提供调节其最大、最小容量的手段。
Java堆可能发生如下异常情况:
如果实际所需的堆超过了自动内存管理系统能提供的最大容量,那Java虚拟机将会抛出一个OutOfMemoryError异常。
同样通过代码来理解一下
?
运行结果:
178702
178703
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
大概17w左右开始内存溢出。增大参数看看效果,-Xmx10m
305677
305678
305679
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
由此可见,通过设置-Xmx参数,可以调整JVM中堆的大小,从而可以在内存中保存更多的对象。
再看看另一种OutOfMemoryError: java.lang.OutOfMemoryError: PermGen space。
同样是,通过代码构造一个PermGen space的异常。(OneCoder认为,你会构造出异常,自然就会慢慢理解这个异常是怎么产生的,什么参数会对这个有影响。)
由于PermGen space一般发生在预加载类的过程中,所以OneCoder这里利用tomcat启动来进行测试。设置Tomcat 启动参数为:-server -XX:MaxPermSize=2m -XX:PermSize=2m
java.lang.OutOfMemoryError: PermGen space
at sun.misc.URLClassPath$JarLoader$1.run(URLClassPath.java:608)
果然发生PermGen space异常。如果你逐渐放大该配置,会发现报错的时机逐渐推后,也就是可以加载更多的类。OneCoder给tomcat指定一个合理的值比如: -server -XX:MaxPermSize=64m -XX:PermSize=64m
程序即可重新启动了。
你也可以多做一些试验,验证你的想法,所谓实践出真知。
概念参考:Java虚拟机规范
慢慢琢磨JVM
如非特别注明,本站内容均为OneCoder原创,转载请务必注明作者和原始出处。
本文地址:http://www.coderli.com/jvm-heap-code-overflow
相关文章推荐
- JVM数据运行区详解
- JVM内存管理机制--运行时数据区域(详解)
- Jvm 运行时数据区域详解
- JVM【第二回】:【JVM运行时数据区域详解】
- JVM的运行原理及优化配置
- JVM详解及优化(含eclipse.ini参数配置)
- JVM 运行时数据区总结 栈 堆 堆大小配置总结
- JVM内存管理机制--运行时数据区域(详解)
- MySQL写入插入数据优化配置
- Storm项目:流数据监控2《代码详解…
- YARN and MapReduce的【内存】优化配置详解
- JVM运行时数据区域分配
- MySQL配置文件my.cnf参数优化和中文详解
- VisualStudio2012 & OpenCV & OpenNi编写运行C++代码使用配置的详细说明
- Swift - HTTP网络操作库Alamofire使用详解1(配置,以及数据请求)
- JVM——运行时数据区梳理
- nginx 优化策列 配置文件详解
- Eclipse配置Hadoop环境并运行WordCount样例
- jvm-运行时数据区域
- 运用 ADO.NET 对象优化数据查询代码