最近公司测试环境Cassandra的一次PermGen Space,好久没排查此类问题了,对JVM也有点陌生,借此机会重新学习学习,经过一段时间的不断尝试,终于基本定位问题所在,PermGen OOM 是因为Casandra 在运行过程中不断的往PermGen里面放入String常量导致OOM,但没找到Cassandra在什么情况下会不断的产生新的String 常量,还要继续跟进。
排查过程如下:
好久没真正排查OOM问题了,一开始也没什么办法,只好重新启动Cassandra ,过一段时间又继续OOM,一直感觉很诡异,之前运行那么久都没有问题,怎么现在老是OOM,查看OOM日志,也没什么明确信息,然后拿着OOM时的java_pidXXX.hprof文件,通过Eclipse 的MemoryAanlyzerTool工具分析,看了半天,也没看出来什么明显问题,后来无意中发现jmap这个命令(其实之前也用过,好久没用了都忘得差不多了,看来久不久得练练)可以直接查看当前heap使用情况,直接jmap -heap pid,发现我们Cassandra实例内存默认配置如下:
Heap Configuration:
MinHeapFreeRatio = 40
MaxHeapFreeRatio = 70
MaxHeapSize = 2147483648 (2048.0MB)
NewSize = 419430400 (400.0MB)
MaxNewSize = 419430400 (400.0MB)
OldSize = 5439488 (5.1875MB)
NewRatio = 2
SurvivorRatio = 8
PermSize = 21757952 (20.75MB)
MaxPermSize = 85983232 (82.0MB)
PernGen Size 的值使用JVM默认值,配置中没有具体指定,而我们的Cassandra OOM以后又启动起来,Perm Generation 已经使用了81M,接近100%的使用率,怪不得运行一段时间以后又继续OOM,只好手动设置Cassandra MaxPermSize=256M,重新启动,感觉这样也没查出具体问题,继续查看permstat,命令
jmap -permstat pid
发现218566 intern Strings occupying 66681200 bytes,终于确定问题所在,原来里面保存了65M的String常量
现在基本确定OOM的原因了,但还是没搞清楚Cassandra是如何在运行过程中把String常量放入PermGen,还需继续努力。
下面是测试String的不同使用方法对JVM内存的使用情况:
环境:
java version "1.6.0_51"
jvm: Java HotSpot(TM) 64-Bit Server VM (build 20.51-b01-457, mixed mode)
程序伪代码1:
i=0
if(i<100000)
i++;
String.valueOf(i).intern()
结论:
1、String 对象会在新生代创建并占用内存
2、String 的值会被放入永久代中并占用内存
2、当新生代GC时,不会把String对象指向的String字符串转入老年代中,这些字符串已经被放入永久代,只会把String对象其他信息(具体还不能确定是什么信息)放入老年代
占用内存相对较少,但String字符串存放在永久代,下面是YGC=4的时候,JVM使用情况
S0C S1C S0U S1U EC EU OC OU PC PU YGC YGCT FGC FGCT GCT
2112.0 2112.0 9.8 0.0 17024.0 571.0 63872.0 7337.4 11264.0 11120.7 4 0.023 0 0.000 0.023
程序伪代码2:
i=0
if(i<100000)
i++;
String.valueOf(i) 或者new String(i+"")或者 i+""
结论:
1、String 对象会在新生代创建并占用内存
2、String 的值不会被放入永久代中并占用内存
2、当新生代GC时,会把String对象指向的String字符串和String对象其他信息都放入老年代
new String(i+"") 占用内存相对较少,下面是YGC=4的时候,JVM使用情况
S0C S1C S0U S1U EC EU OC OU PC PU YGC YGCT FGC FGCT GCT
2112.0 2112.0 2112.0 0.0 17024.0 5835.4 63872.0 28361.7 5120.0 4952.8 4 0.064 0 0.000 0.064
i+"“ 与 new String(i+"") 占用内存差不多,下面是YGC=4的时候,JVM使用情况
S0C S1C S0U S1U EC EU OC OU PC PU YGC YGCT FGC FGCT GCT
2112.0 2112.0 2112.0 0.0 17024.0 965.2 63872.0 28373.7 5120.0 4952.5 4 0.081 0 0.000 0.081
String.valueOf(i) 占用内存相对较多,下面是YGC=4的时候,JVM使用情况
S0C S1C S0U S1U EC EU OC OU PC PU YGC YGCT FGC FGCT GCT
2112.0 2112.0 2112.0 0.0 17024.0 571.0 92956.0 55772.8 8252.0 4949.8 4 0.129 96 0.468 0.598
相关推荐
java JVM Runtime Data Area and Instruction Set
《深入理解JVM实战篇-String类》 在Java编程中,String类是使用最频繁的类之一,它涉及到许多底层机制,特别是与JVM(Java虚拟机)的交互。本文将探讨String类的一些关键特性,包括字面量与运行时常量池、String的...
本测试程序旨在深入理解和探索`String`类的一些核心功能和内部机制。以下是一些关于`String`类的关键知识点: 1. **不可变性**:`String`对象在创建后就不能更改。这意味着一旦创建了`String`实例,它的值就固定了...
java 测试jvm工具可执行加入java 测试jvm工具可执行加入java 测试jvm工具可执行加入java 测试jvm工具可执行加入java 测试jvm工具可执行加入java 测试jvm工具可执行加入java 测试jvm工具可执行加入java 测试jvm工具可...
"JVM内存分配及String常用方法解析" 通过对JVM内存分配和String常用方法的解析,我们可以了解到JVM的内存模型和String类的使用方法。 一、JVM内存分配 JVM将内存分为多个不同的区域,每个区域都有其特定的用途和...
本文将探讨如何在Windows环境下通过简单的命令行工具来监控JVM实例的数量,以及如何进行线程测试,特别是在单例模式下的JVM实例验证。 首先,了解如何监控JVM实例数量。在Windows操作系统中,我们可以使用`jps`命令...
- **运行时常量池(Runtime Constant Pool)**:存储类文件的常量,包括字符串字面量和符号引用。在Java 8中,运行时常量池也被移到了堆中。 ### 2. JVM Heap 内存结构 堆内存是Java对象的主要存储区域,分为...
原项目下载地址:...使用说明: 1、将SizeOf.jar放到Eclipse工程路径下,添加到classpath中; 2、运行前添加VM参数:-javaagent:lib/SizeOf.jar 运行即可(将jar放在lib路径下)。
- **Runtime Constant Pool(运行时常量池)**:运行时常量池是方法区的一部分,它包含了Class文件中的常量池内容。这些内容会在类加载后进入方法区的运行时常量池中。此外,运行时常量池还支持动态性,即允许在运行...
Java Runtime Environment(JRE)是Java程序运行所需的基础组件,它是Oracle公司提供的Java平台标准版(Java SE)的一部分。在本例中,我们讨论的是64位版本的JRE 1.8.0,适用于Windows操作系统。这个版本的JRE包含...
标题中提到了JVM原理、JVM调优、JVM内存模型和JAVA并发,这些都是Java虚拟机(JVM)相关的核心概念。JVM是运行Java字节码的虚拟计算机,为Java提供了一个跨平台的环境,确保Java程序可以在不同的操作系统上运行而...
在Java虚拟机(JVM)中,`String.intern()` 是一个非常特殊且重要的方法,它与字符串常量池紧密相关。字符串常量池是一种内存优化机制,存储了程序中所有的字符串字面值和通过 `intern()` 方法添加的字符串。这个池...
[jvm]深入JVM(一):从"abc"=="abc"看java的连接过程收藏 一般说来,我不关注java底层的东西,这次是一个朋友问到了,注意不光是 System.out.println("abc"=="abc");返回true, System.out.println(("a"+"b"+"c")....
Java虚拟机(JVM)是Java程序运行的核心,它负责解释和执行字节码,为Java应用程序提供了一个跨平台的运行环境。JDK(Java Development Kit)包含了开发和运行Java程序所需的所有工具,包括JVM。当我们谈论"jdk,jvm...
JVM的垃圾回收机制是为了自动释放不再被引用的对象所占用的内存,它涉及多个回收算法和策略。垃圾回收器会周期性地检查堆中的对象,标识出不再使用的对象,并回收其占用的空间。新生代和旧生代的堆结构设计是垃圾...
- **垃圾收集**:指JVM回收那些不再被使用的对象占用的内存空间。 - **垃圾收集器**:不同垃圾收集器有不同的算法和特点,如G1收集器、CMS收集器等。 - **垃圾收集算法**:标记-清除、复制、标记-整理、分代收集等。...
该文档描述了开发测试环境中Docker及JVM内存限制部署方案
jvm支持最大线程数简单测试 jvm支持最大线程数简单测试是非常重要的知识点,下面将详细介绍该知识点。 1. JVM支持的最大线程数 jvm支持的最大线程数是受多种因素影响的,包括java堆内存大小、Thread的Stack内存...
在Java编程环境中,了解JVM(Java虚拟机)中所有线程的活动状态对于调试多线程程序至关重要。本文将详细讲解如何查看JVM中的线程活动情况,并提供相关示例代码。 首先,Java提供了`java.lang.management....