java jdk1.7常量池移到哪去了?
2015-12-22 09:38
495 查看
今天模拟了一下常量池的oom,突然发现设置的参数-XX:PermSize=10M -XX:MaxPermSize=10M不管用了,同时发现内存一直在上升,当上升到一个极值就会趋于平稳,然后再过一段时间会报:
Exception in thread “main” java.lang.OutOfMemoryError: GC overhead limit exceeded
这个异常是当GC的时间超过总运行时间的98%才会报的,是为了防止GC占用的时间过长。
模拟常量池源码:
那么问题来了,我们从前知道的是常量池是放在Java JVM中的方法区中的,许多人也叫它“永久代”,可以通过-XX:PermSize=20M -XX:MaxPermSize=20M来设置大小,当这个区域内存溢出会报:
Exception in thread “main” java.lang.OutOfMemoryError:PermGen space的内存溢出异常,但是这里却不是那么一回事,反而GC的时间会过长,那么我猜测这个常量池是移动到了java堆中去了,下面测试一下:
首先,源代码不变,增加运行时JVM的参数:
-Xmx20m -Xms20m -XX:-UseGCOverheadLimit,这里的-XX:-UseGCOverheadLimit是关闭GC占用时间过长时会报的异常,然后限制堆的大小,运行程序,果然,一会后报异常:
Exception in thread “main” java.lang.OutOfMemoryError: Java heap space
从上面的异常可以知道我们测试增加的常量都放到了堆中,所以限制堆内存以后,不断增加常量,堆内存会溢出。和我们猜测的一样,同时我也查看了官网发现了官网有说明http://www.oracle.com/technetwork/java/javase/jdk7-relnotes-418459.html:
Area: HotSpot
Synopsis: In JDK 7, interned strings are no longer allocated in the permanent generation of the Java heap, but are instead allocated in the main part of the Java heap (known as the young and old generations), along with the other objects created by the application. This change will result in more data residing in the main Java heap, and less data in the permanent generation, and thus may require heap sizes to be adjusted. Most applications will see only relatively small differences in heap usage due to this change, but larger applications that load many classes or make heavy use of the String.intern() method will see more significant differences.
RFE: 6962931
通过自己的实践和官网说明,可以知道java jdk1.7中的常量池确实是移到了堆中,同时jdk1.8中可能会移除整个方法区,取而代之的是一个叫元空间(Metaspace)的区域,如果想了解更多可以参考:
http://www.oracle.com/technetwork/java/javase/jdk7-relnotes-418459.html
http://blog.csdn.net/zhyhang/article/details/17246223/
Exception in thread “main” java.lang.OutOfMemoryError: GC overhead limit exceeded
这个异常是当GC的时间超过总运行时间的98%才会报的,是为了防止GC占用的时间过长。
模拟常量池源码:
[code]public static void main(String[] args) throws Throwable { List<String> list = new ArrayList<String>(); int i=0; while(true){ list.add(String.valueOf(i++).intern()); } }
那么问题来了,我们从前知道的是常量池是放在Java JVM中的方法区中的,许多人也叫它“永久代”,可以通过-XX:PermSize=20M -XX:MaxPermSize=20M来设置大小,当这个区域内存溢出会报:
Exception in thread “main” java.lang.OutOfMemoryError:PermGen space的内存溢出异常,但是这里却不是那么一回事,反而GC的时间会过长,那么我猜测这个常量池是移动到了java堆中去了,下面测试一下:
首先,源代码不变,增加运行时JVM的参数:
-Xmx20m -Xms20m -XX:-UseGCOverheadLimit,这里的-XX:-UseGCOverheadLimit是关闭GC占用时间过长时会报的异常,然后限制堆的大小,运行程序,果然,一会后报异常:
Exception in thread “main” java.lang.OutOfMemoryError: Java heap space
从上面的异常可以知道我们测试增加的常量都放到了堆中,所以限制堆内存以后,不断增加常量,堆内存会溢出。和我们猜测的一样,同时我也查看了官网发现了官网有说明http://www.oracle.com/technetwork/java/javase/jdk7-relnotes-418459.html:
Area: HotSpot
Synopsis: In JDK 7, interned strings are no longer allocated in the permanent generation of the Java heap, but are instead allocated in the main part of the Java heap (known as the young and old generations), along with the other objects created by the application. This change will result in more data residing in the main Java heap, and less data in the permanent generation, and thus may require heap sizes to be adjusted. Most applications will see only relatively small differences in heap usage due to this change, but larger applications that load many classes or make heavy use of the String.intern() method will see more significant differences.
RFE: 6962931
通过自己的实践和官网说明,可以知道java jdk1.7中的常量池确实是移到了堆中,同时jdk1.8中可能会移除整个方法区,取而代之的是一个叫元空间(Metaspace)的区域,如果想了解更多可以参考:
http://www.oracle.com/technetwork/java/javase/jdk7-relnotes-418459.html
http://blog.csdn.net/zhyhang/article/details/17246223/
相关文章推荐
- Caused by: java.lang.UnsatisfiedLinkError: Couldn't load zbar: findLibrary returned null
- Java 理论与实践: 正确使用 Volatile 变量
- spring xml namespace
- jdk1.7
- Ibator插件安装、配置及使用说明
- spring mvc default-servlet mvc:resources mvc:default-servlet-handler区别
- spring mvc default-servlet mvc:resources mvc:default-servlet-handler区别
- Java C# MD5 加密串一致性
- Java 实现当当网泄露数据快速检索
- 四道Java基础题 你能对几道?
- 使用Java开发多线程端口扫描工具 推荐
- java模拟浏览器下载图片
- java实现ftp上传下载(jdk1.7以上)
- Java 8 时间日期库的20个使用示例
- java实现ftp上传下载(jdk1.7以下)
- Spring 文件上传功能
- 用一天的时间学习Java EE中的SSH框架
- mac下同时安装多个版本的jdk
- 在Java的Hibernate框架中对数据库数据进行查询操作
- Java基础题 你能对几道?