jvm之PermGen的离开与MetaSpace新生

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/a718515028/article/details/86614889

先从代码来看,永生代的更迭

测试代码如下:

    public static void main(String[] args){

        // jdk 1.6 设置 -XX:PermSize=10M -XX:MaxPermSize=10M
        // jdk 1.7 1.8只有设置-Xmx20m -Xms20m -XX:-UseGCOverheadLimit才能起作用(这里的-XX:-UseGCOverheadLimit是关闭GC占用时间过长时会报的异常)
        List<String> list = new ArrayList<String>();
        int i=0;
        while(true){
            list.add(String.valueOf(i++).intern());
        }
    }
  • jdk1.6测试:
    设置-XX:PermSize=10M -XX:MaxPermSize=10M,执行代码,报错:
Exception in thread "main" java.lang.OutOfMemoryError: PermGen space
	at java.lang.String.intern(Native Method)
	at com.yanming.lession2.main(lession2.java:21)

可以得出结论,在1.6时代,字符串常量存放在永生代中

  • jdk1.7 1.8 测试,继续设置-XX:PermSize=10M -XX:MaxPermSize=10M
    可以发现一只可以运行下去。
    此时,加入设置-Xmx20m -Xms20m
    运行结果:
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
	at java.lang.Integer.toString(Integer.java:401)
	at java.lang.String.valueOf(String.java:3099)
	at com.yanming.lession2.main(lession2.java:21)
Java HotSpot(TM) 64-Bit Server VM warning: ignoring option PermSize=10M; support was removed in 8.0
Java HotSpot(TM) 64-Bit Server VM warning: ignoring option MaxPermSize=10M; support was removed in 8.0
  • 从结果看到,增加的常量都放到了堆中,所以限制堆内存以后,不断增加常量,堆内存会溢出。并且出现警告,PermSize和MaxPermSize从8中移除
  • 官网有说明
    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

Metaspace

  • 移除永久代(PermGen)的工作从JDK1.7就开始了。

  • JDK1.7中,存储在永久代的部分数据就已经转移到了Java Heap或者是 Native Heap。但永久代仍存在于JDK1.7中,并没完全移除,譬如符号引用(Symbols)转移到了native heap;字面量(interned strings)转移到了java heap;类的静态变量(class statics,Class对象、静态变量)转移到了java heap。

  • 1.8之后彻底移除永久代,取而代之的是元空间Metaspace(即本地内存,独立于jvm之外),不再占用堆内存 ,它可以通过自动增长来避免JDK7以及前期版本中常见的永久内存错误(java.lang.OutOfMemoryError: PermGen),当然JDK8也提供了一个新的设置Matespace内存
    大小的参数,通过这个参数可以设置Matespace内存大小,这样我们可以根据自己
    项目的实际情况,避免过度浪费本地内存,达到有效利用。

  • Metaspace用于存放类元数据,并不是存放常量静态变量等,常量跟1.7一样放入堆中

  • 元空间并不在虚拟机中,而是使用本地内存。因此,默认情况下,元空间的大小仅受本地内存限制,但可以通过以下参数来指定元空间的大小。

  • 默认情况下,类元数据只受可用的本地内存限制(容量取决于是32位或是64位操作系统的可用虚拟内存大小)

  • 当类元数据区使用量到达MetaspaceSize的时候,会触发垃圾回收,然后回收掉无用的类加载器和class对象

  • -XX:MaxMetaspaceSize=128m,-XX:MaxMetaspaceSize,最大空间,默认是没有限制的.设置最大的元内存空间128m。如果你设置的元内存空间过小,你的应用程序可能得到下面错误:java.lang.OutOfMemoryError: Metadata space

  • -XX:MetaspaceSize,初始空间大小,达到该值就会触发垃圾收集进行类型卸载,同时GC会对该值进行调整:如果释放了大量的空间,就适当降低该值;如果释放了很少的空间,那么在不超过MaxMetaspaceSize时,适当提高该值。

  • -XX:MinMetaspaceFreeRatio,在GC之后,最小的Metaspace剩余空间容量的百分比,减少为分配空间所导致的垃圾收集

  • -XX:MaxMetaspaceFreeRatio,在GC之后,最大的Metaspace剩余空间容量的百分比,减少为释放空间所导致的垃圾收集

更新原因:

猜你喜欢

转载自blog.csdn.net/a718515028/article/details/86614889