在jdk1.8的環境下模擬永久代內存溢出

相信很多小夥伴在看深刻理解Java虛擬機的時候,做者給咱們舉例一個demo來發生PermGen spaceexpress

一、經過List不斷添加String.intern();this

二、經過設置對應的-XX:PermSize與-XX:MaxPermSize(更快看到效果),spa

三、在jdk1.6的環境下會拋出OOM:PermGen space異常對象

public static void main(String[] args) {
    List<String> str=new ArrayList<>();
    int i=0;
    while (true){
        str.add(String.valueOf(i).intern());
    }

}

然而在jdk1.8的環境下,這段代碼,會出現OOM,但不是出現PermGenSpace,而是會當堆內存不夠用(-Xmx)的時候,拋出Java heap space,並且會舒適提示內存

ignoring option PermSize=10M; support was removed in 8.0ci

ignoring option MaxPermSize=10M; support was removed in 8.0rem

---------------------------------------------------------------------------------------------------------字符串

首先咱們看一下String.intern()方法,官方的註釋是虛擬機

Returns a canonical representation for the string object. A pool of strings, initially empty, is maintained privately by the class String. When the intern method is invoked, if the pool already contains a string equal to this String object as determined by the equals(Object) method, then the string from the pool is returned. Otherwise, this String object is added to the pool and a reference to this String object is returned. It follows that for any two strings s and t, s.intern() == t.intern() is true if and only if s.equals(t) is true. All literal strings and string-valued constant expressions are interned. String literals are defined in section 3.10.5 of the The Java? Language Specification.string

大概意思就是,若是常量池已經存在這個string對象,那麼就返回這個字符串的引用。不然將此string對象加入常量池,再返回引用

~

可是在jdk1.8中,其實已經沒有永久代這一說了,取而代之的是一個叫元空間(Meta space)。而常量池放到了堆中,因此也就不會出現PermGen space了

---------------------------------------------------------------------------------------------------------

那麼若是想看到metaspace的異常怎麼作呢?

一個是能夠把這兩個值設置的足夠小,那麼啓動就會報錯了。

-XX:MetaspaceSize=3M -XX:MaxMetaspaceSize=3M

一個是能夠使用jdk動態加載技術,例如cglib動態的生成大量的數據來達到

相關文章
相關標籤/搜索