引用
方法区和运行时常量池溢出 ide配置参考堆溢出 附件
import com.google.common.collect.Lists;
import java.util.List;
/**
* @Author admin Date: 2017/6/19 10:40
* @description: 方法区和运行时常量池溢出 ide配置参考堆溢出 附件
*/
public class RuntimeConstantPoolOOM {
public static void main(String[] args){
// 使用List 保持着常量池引用,避免Full GC回收常量池行为
List<String> list = Lists.newArrayList();
// 10MB 的permsize 在integer 范围内足够产生OOM了
int i= 0;
while (true){
list.add(String.valueOf(i++).intern());
}
}
}
/**jdk1.7中GC不会回收 list中添加的常量 1.8中回收了
所以输出的错误信息 不是 permeGen space
而是:
[Full GC (Ergonomics) [PSYoungGen: 8191K->8191K(9216K)] [ParOldGen: 10053K->10053K(10240K)] 18245K->18245K(19456K), [Metaspace: 3439K->3439K(1056768K)], 0.0456493 secs] [Times: user=0.14 sys=0.00, real=0.05 secs]
[Full GC (Ergonomics) [PSYoungGen: 8191K->8191K(9216K)] [ParOldGen: 10055K->10055K(10240K)] 18247K->18247K(19456K), [Metaspace: 3439K->3439K(1056768K)], 0.0464576 secs] [Times: user=0.09 sys=0.00, real=0.05 secs]
[Full GC (Ergonomics) [PSYoungGen: 8191K->8191K(9216K)] [ParOldGen: 10056K->10056K(10240K)] 18248K->18248K(19456K), [Metaspace: 3439K->3439K(1056768K)], 0.0454579 secs] [Times: user=0.14 sys=0.00, real=0.05 secs]
[Full GC (Ergonomics) Exception in thread "main" java.lang.OutOfMemoryError: GC overhead limit exceeded
[PSYoungGen: 8191K->8191K(9216K)] [ParOldGen: 10058K->10058K(10240K)] 18250K->18250K(19456K), [Metaspace: 3439K->3439K(1056768K)], 0.0457579 secs] [Times: user=0.11 sys=0.00, real=0.05 secs]
[Full GC (Ergonomics) at java.lang.Integer.toString(Integer.java:401)
[PSYoungGen: 8192K->0K(9216K)] [ParOldGen: 10075K->1049K(10240K)] 18267K->1049K(19456K), [Metaspace: 3463K->3463K(1056768K)], 0.0074261 secs] [Times: user=0.00 sys=0.00, real=0.01 secs]
Heap
at java.lang.String.valueOf(String.java:3099)
PSYoungGen total 9216K, used 193K [0x00000000ff600000, 0x0000000100000000, 0x0000000100000000)
at RuntimeConstantPoolOOM.main(RuntimeConstantPoolOOM.java:20)
eden space 8192K, 2% used [0x00000000ff600000,0x00000000ff630478,0x00000000ffe00000)
from space 1024K, 0% used [0x00000000ffe00000,0x00000000ffe00000,0x00000000fff00000)
to space 1024K, 0% used [0x00000000fff00000,0x00000000fff00000,0x0000000100000000)
ParOldGen total 10240K, used 1049K [0x00000000fec00000, 0x00000000ff600000, 0x00000000ff600000)
object space 10240K, 10% used [0x00000000fec00000,0x00000000fed064a8,0x00000000ff600000)
Metaspace used 3470K, capacity 4600K, committed 4864K, reserved 1056768K
class space used 377K, capacity 424K, committed 512K, reserved 1048576K
Process finished with exit code 1
*/
引用
下面是测试1.8中和1.7中还有1.6中引用的不同
import com.google.common.collect.Lists;
import java.util.List;
/**
* @Author admin Date: 2017/6/19 10:40
* @description: 方法区和运行时常量池溢出 ide配置参考堆溢出 附件
*/
public class RuntimeConstantPoolOOM {
public static void main(String[] args){
// // 使用List 保持着常量池引用,避免Full GC回收常量池行为
//
// List<String> list = Lists.newArrayList();
//
// // 10MB 的permsize 在integer 范围内足够产生OOM了
//
// int i= 0;
// while (true){
// list.add(String.valueOf(i++).intern());
// }
String str1 = new StringBuilder("马云").append("马化腾").toString();
System.out.println(str1.intern() == str1);
String str2 = new StringBuilder("ja").append("va").toString();
System.out.println(str2.intern() == str2);
}
}
/**
jdk1.6中 执行结果返回的是 false false
jdk1.7中 执行结果返回的是 true false
jdk1.8中 执行结果返回的是 true false
*/
// jdk1..8如下:
true
false
Heap
PSYoungGen total 9216K, used 4431K [0x00000000ff600000, 0x0000000100000000, 0x0000000100000000)
eden space 8192K, 54% used [0x00000000ff600000,0x00000000ffa53d90,0x00000000ffe00000)
from space 1024K, 0% used [0x00000000fff00000,0x00000000fff00000,0x0000000100000000)
to space 1024K, 0% used [0x00000000ffe00000,0x00000000ffe00000,0x00000000fff00000)
ParOldGen total 10240K, used 0K [0x00000000fec00000, 0x00000000ff600000, 0x00000000ff600000)
object space 10240K, 0% used [0x00000000fec00000,0x00000000fec00000,0x00000000ff600000)
Metaspace used 3353K, capacity 4500K, committed 4864K, reserved 1056768K
class space used 363K, capacity 388K, committed 512K, reserved 1048576K
Process finished with exit code 0
jdk1.6 中运行 intern()方法会把首次遇到的字符串实例复制到永久代中,返回的也是永久代这个字符串实例的引用,而由StringBuilder创建的字符串实例会在java堆上,所以必然不是一个引用,返回false,而1.7(以及部分其他虚拟机,例如JRockit)的intern()实现不会复制实例,只是在常量池中记录首次出现的实例引用,因此intern()返回true,str2返回false是因为“java”字符串在执行StringBuilder.toString()之前已经出现过,字符常量池总中已经有了他的引用,不符合“首次出现”所以返回false 1.8和1.7相同
分享到:
相关推荐
常量池包含了各种字面量(如字符串、数字)和符号引用(如类和方法的全限定名、字段和方法的标识符)。这些信息在编译时就已经确定,并且在类加载时静态地存储于运行时常量池。 运行时常量池的一个关键特性是它的...
常量池分为静态常量池、运行时常量池、字符串常量池和整型常量池。静态常量池存在于每个*.class文件中,包含了字面量和符号引用,这部分在类加载的链接阶段会被解析成直接引用。运行时常量池则是在虚拟机运行时载入...
在Java内存管理中,堆(Heap)、栈(Stack)、常量池(Constant Pool)和方法区(Method Area)是四个核心概念,它们在Java程序运行时扮演着不同的角色。 首先,方法区是用来存放类的信息、常量、静态变量等数据的...
3. **方法区和运行时常量池溢出** - 当方法区无法满足新的内存分配需求时,会抛出`OutOfMemoryError`异常。 #### 四、垃圾收集 1. **判断对象是否存活** - **引用计数器法**:不常用,容易导致对象共享引用时不...
2.4.3 方法区和运行时常量池溢出 2.4.4 本机直接内存溢出 2.5 本章小结 第3章 垃圾收集器与内存分配策略 3.1 概述 3.2 对象已死吗 3.2.1 引用计数算法 3.2.2 可达性分析算法 3.2.3 再谈引用 3.2.4 生存...
在Java中,内存主要分为四个区域:寄存器、栈、堆和方法区(包括常量池)。以下是这四个区域的详细说明: 1. **寄存器**: 这是计算机硬件的一部分,用于存储非常快速访问的数据。在Java中,寄存器主要由JVM直接管理...
字符串常量池位于方法区的运行时常量池部分。在Java 8之前,这个池是在永久代(PermGen Space)中,而在Java 8及之后,由于移除了永久代,字符串常量池被移到了堆内存的元空间(Metaspace)。 字符串常量池的工作...
4. **掌握方法区和运行时常量池内存溢出异常的测试**:研究如何通过动态生成大量类的方法来填充方法区,最终导致方法区溢出;另外,探索如何通过创建大量的字符串常量来填满运行时常量池,触发溢出异常。 5. **掌握...
综上所述,JVM的运行时数据区主要包括程序计数器、栈、堆、方法区、运行时常量池以及本地方法栈。这些区域对于Java程序的正常运行至关重要,理解它们的工作原理有助于开发者更好地管理和优化Java应用程序的性能。
- 常量池存储了类中的字符串字面量、数值常量以及字段和方法的符号引用。在运行时,常量池中的符号引用会被解析为直接引用,以便直接访问方法区中的实际数据。 3. **静态变量与实例变量**: - 静态变量存储在...
在Java 8之前,字符串常量池位于方法区,从Java 8开始,字符串常量池被移到了堆中。常量池允许字符串的复用,减少了内存的消耗。例如,多个引用相同字符串的变量实际上都指向常量池中的同一个实例。 6. 非RAM存储:...
java技术面试必问:JVM-内存模型讲解 本文将详细介绍Java技术面试中必问的JVM内存模型...OutOfMemoryError出现在方法区无法满足内存分配需求的时候,比如一直往常量池中加入数据,运行时常量池就会溢出,从而报错。
在实际开发中,我们还需要关注JVM的其他重要概念,如类加载机制(加载、验证、准备、解析、初始化)、类文件结构(魔数、版本号、常量池等)、垃圾回收算法(如标记-清除、复制、标记-整理、分代收集)以及执行引擎...
运行时常量池是方法区的一部分,它不仅包含编译时期的常量,还能在运行时添加新的常量,比如 String 的 intern() 方法。当运行时常量池无法扩展时,同样会导致内存溢出。直接内存是 Java 应用可以直接访问的非堆内存...
运行时常量池是方法区的一部分,Class 文件中除了有类的版本、字段、方法、接口等描述信息外,还有一项信息是常量池表,用于存放编译器生成的各种字面量与符号引用,这部分内容在类加载后存放到运行时常量池。...