問題:字符串常量池分配在什麼內存區域? 方法區?永久區? 堆內存?java
首先明晰幾個概念:app
方法區
- java虛擬機規範
的運行時數據區
方法區
概念屬於 java虛擬機規範
的運行時數據區
的一部分. 運行時數據區包括: 程序計數器
、java虛擬機棧
、本地方法棧
、java堆
、方法區
. 其中, 方法區
跟 java堆
都是全部線程共享的數據區, 用於存放已被jvm加載的class信息、常量、static變量、JIT即時編譯後的代碼等這些數據.jvm
永久區
- jvm實現
永久區又叫PermGen
, 是jvm實現, 且只存在於jdk7和以前的版本;jdk8中已完全移除PermGen,jdk8引入了一個新的內存區域:metaspace
;ui
而後再看下面程序的輸出, 可肯定java的版本 jdk6/7/8中的字符串分配的內存區域. 運行時指定 VM Options
參數 java -Xms20m -Xmx20m StringOOM
令程序內存過限:spa
import java.util.ArrayList; import java.util.List; public class StringOOM { static String base = "somethings"; public static void main(String[] args) { List<String> list = new ArrayList<>(); for (int i = 0; i < Integer.MAX_VALUE; i++) { String str = base + base; base = str; // 只是用來增加 /** intern 會把字符串發佈到 字符串常量池中去 */ list.add(str.intern()); } } }
JDK8-在堆內存: OutOfMemoryError: Java heap space線程
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space at java.util.Arrays.copyOf(Arrays.java:3332) at java.lang.AbstractStringBuilder.ensureCapacityInternal(AbstractStringBuilder.java:124) at java.lang.AbstractStringBuilder.append(AbstractStringBuilder.java:448) at java.lang.StringBuilder.append(StringBuilder.java:136) at com.niewj.demo.lang.StringOOM.main(StringOOM.java:12) Java HotSpot(TM) 64-Bit Server VM warning: ignoring option PermSize=8m; support was removed in 8.0 Java HotSpot(TM) 64-Bit Server VM warning: ignoring option MaxPermSize=8m; support was removed in 8.0
JDK7-在堆內存: OutOfMemoryError: Java heap spacecode
PS C:\devs\java\jdk7\bin> .\java.exe -Xms20m -Xmx20m -XX:PermSize=8m -XX:MaxPermSize=8 StringOOM Exception in thread "main" java.lang.OutOfMemoryError: Java heap space at java.util.Arrays.copyOfRange(Arrays.java:2694) at java.lang.String.<init>(String.java:203) at java.lang.StringBuilder.toString(StringBuilder.java:405) at StringOOM.main(StringOOM.java:10)
JDK6-在永久區: OutOfMemoryError: PermGen space內存
List<String> list = new ArrayList<>(); 沒法編譯, 必須寫完整:List<String> list = new ArrayList<String>(); PS C:\devs\java\jdk6> .\bin\java.exe StringOOM Exception in thread "main" java.lang.OutOfMemoryError: PermGen space at java.lang.String.intern(Native Method) at StringOOM.main(StringOOM.java:12)
結論:
JDK6-在永久區: OutOfMemoryError: PermGen space
JDK7-在堆內存: OutOfMemoryError: Java heap space
JDK8-在堆內存: OutOfMemoryError: Java heap spaceci
可見, JDK6
的jvm 對字符串常量池的內存區域的實現, 還在永久區(PermGen)
; 而JDK7/JDK8
就都是在堆內存
中劃分的內存了;rem