方法区内存溢出测试

本文介绍如何通过String.intern()方法导致运行时常量池溢出,演示了如何设置虚拟机参数来限制方法区大小,并展示了相应的代码实现及溢出错误。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

package com.jfans;

import java.util.ArrayList;
import java.util.List;

/*
 * 如果要向运行时常量池(位于方法区Method Area)中添加内容,最简单的做法是使用String.intern()这个Native方法了。
 * 由于常量池分配 在方法区(持久代),我们可以通过-XX:PermSize和-XX:MaxPermSize限制方法区的大小,从而间接限制其中常量池的容量
 *
 * VM参数:-XX:PermSize10M -XX:MaxPermSize10M
 *
 * 抛出如下异常:
    Exception in thread "main" java.lang.OutOfMemoryError: PermGen space
 at java.lang.String.intern(Native Method)
 at com.jfans.RuntimeConstantPoolOOM.main(RuntimeConstantPoolOOM.java:26)
 
 从运行结果可以看到,运行时常量池溢出,在OutOfMemoryError后面跟随的提示信息是"PermSize space",说明运行时常量属于方法区(HotSpot虚拟
         机中的永久代)的一部分。
        
     另外,还有方法区溢出,本机直接内存溢出等。
 */
public class RuntimeConstantPoolOOM {

 
 /**
  * @param args
  */
 public static void main(String[] args) {


  //使用List保持着常量池引用,避免Full GC回收常量池行为
  List<String> list = new ArrayList<String>();
  
  int i=0;
  while(true){
   list.add(String.valueOf(i++).intern());
  }


 }

}

### 堆内存溢出 (Heap Memory Overflow) 堆内存溢出通常是因为应用程序尝试分配的内存超出了JVM堆的最大容量。这种情况下,JVM会抛出 `java.lang.OutOfMemoryError` 错误。 #### 原因 - **大对象分配失败**:一次性创建过大的对象或集合结构,导致剩余堆空间不足[^2]。 - **内存泄漏**:某些对象不再被使用但仍保持引用,阻止垃圾回收器清理这些对象[^4]。 #### 解决方案 - 提高堆内存上限通过调整 `-Xmx` 参数来增大最大堆大小。 - 使用性能监控工具定位并修复内存泄漏问题,例如 VisualVM 或 JProfiler。 ```bash java -Xms512m -Xmx2g MyApplication ``` --- ### 栈内存溢出 (Stack Overflow) 栈内存溢出通常是由于线程调用层次太深或者存在无限递归造成的。 #### 原因 - **死循环递归**:函数反复自我调用直到栈帧耗尽所有可用栈空间[^1]。 - **局部变量过多**:单个方法中定义了大量局部变量也可能引发此问题。 #### 解决方案 - 减少递归深度改写算法逻辑为迭代形式。 - 调整线程栈大小参数 `-Xss` 来增加每个线程默认拥有的栈尺寸。 ```bash java -Xss1m RecursiveExample ``` --- ### 方法区(元空间)内存溢出 (Metaspace/Metaspace Overflow) 方法区内存主要用于存储类的相关数据,在 JDK 8 及之后称为元空间(Metaspace),而在更早版本则被称为永久代(PermGen Space)。 #### 原因 - **加载太多 Class 文件**:动态代理、反射操作频繁生成新类实例可能导致该域膨胀迅速。 - **未释放无用 Classes**:即使应用卸载了一些模块但对应 classes 并未真正销毁仍占据着位置[^5]。 #### 解决方案 - 对于旧版 JDK (<8), 设置适当 Permanent Generation 大小 via `-XX:MaxPermSize`. - 新版 JDK 中, 扩展 MetaSpace 上限至合理范围 by modifying `-XX:MaxMetaSpaceSize`. ```bash # For older versions of Java before JDK 8 java -XX:MaxPermSize=256m MyClassLoader # For newer versions starting from JDK 8 onwards java -XX:MaxMetaspaceSize=512m DynamicClassLoaderApp ``` --- ### 总结注意事项 除了上述三种主要类型的 OOM 异常外还有其他情况比如直接缓冲池满等情况也需要留意处理方式各有侧重需具体分析实际应用场景做出相应优化措施[^3].
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值