java.lang.OutOfMemoryError: PermGen space

在JDK 1.7环境下,由于PermGen空间溢出,导致A应用出现RPC调用无响应。通过日志分析定位到异常为java.lang.OutOfMemoryError: PermGen space。经过分析,这是由于持久代内存溢出,存储class等信息的空间不足。解决方案是调整JVM配置,增大持久代大小至256M,问题得到解决。
摘要由CSDN通过智能技术生成

java.lang.OutOfMemoryError: PermGen space


异常背景

  • 系统版本:JDK 1.7

  • 问题反馈:同事反馈开发环境A应用RPC(Dubbo)调用无响应

  • 问题排查:登录 Dubbo Admin 检查A应用的接口提供者,发现无注册

  • 问题定位:A 应用挂掉

  • 查询日志:

    • 业务日志:common.log
    • 系统日志:localhost.log

      java.lang.OutOfMemoryError: PermGen space
      BO bo = redis.get(key,BO.class)

  • 异常处理:

    • 定位应用问题在于内存溢出
    • 重启服务器后问题修复,通知同事服务可以调用
    • 排查问题原因

异常分析

  • 异常信息:持久代内存溢出

  • 内存结构:

    • JVM 内存模型规范1:方法区、堆区、栈区、本地方法栈、程序计数器
    • JVM 内存模型实现2:新生代(Eden,S0,S1);老年代(old)以及持久代(Metaspace/Perm)
    • 方法区与持久代的区别与联系3
      • 方法区是一种规范,是JVM内存模型
      • 持久代是前者实现,是JVM内存分区,且持久代只在 (hotspot JVM 且 JDK 1.7 版本前 )才有
      • 存储内容:两者基本相同
        • 存储class、运行时常量池、字段、方法、代码、JIT代码
  • 溢出场景4

    • 运行时常量池溢出
    • 方法区中保存的class对象没有被及时回收掉
    • class信息占用的内存超过了系统配置的最大空间
    • Class对象未被释放,Class对象占用信息过多,有过多的Class对象
  • 容量查询

    • 系统配置:Tomcat 中 JVM 相关配置在 catalina.sh5
    • 查询结果:文件中没有配置,查看默认设置的持久代的最大容量
    • 运行配置:查看 A 应用运行时的 JVM 配置
      • 跳转机器:ssh -p rootName@ip 登录到服务部署服务器
      • 查看进程:ps -ef | grep “applicationName” 带有 tomcat 信息的进程PID
      • 查看配置:jstat -gcpermcapacity pid 6
        • 其中 PGCMX 表示 持久带的最大配置,单位为 KB ,默认 64M
      • GC 情况:
        • jstat -gcutil pid 1000 5 每 1000 s 打印一次,共打印 5 次7

          [application@ip ~]$ jstat -gcutil 16396 1000 5
          S0 S1 E O P YGC YGCT FGC FGCT GCT
          15.13 0.00 82.08 60.50 99.76 16 2.712 2 0.972 3.685
          15.13 0.00 82.08 60.50 99.76 16 2.712 2 0.972 3.685
          15.13 0.00 82.08 60.50 99.76 16 2.712 2 0.972 3.685
          15.13 0.00 82.08 60.50 99.76 16 2.712 2 0.972 3.685
          15.13 0.00 82.08 60.50 99.76 16 2.712 2 0.972 3.685

        • 从打印结果上看,PermGen 使用率过高,且FGC 次数频繁

  • 日志分析

    • 系统日志:localhost.log8 与 catalina.log 记录基本相同,不如后者详细
    • 日志分析:
      • 调用 A 系统中某 HTTP 接口
      • 接口 I 被 HttpIntercept 拦截,并调用 Redis 查询数据,缓存到 session中
      • 调用 Redis 获取数据时发生异常
  • 猜测原因

    • 持久代预设空间已满,当新的Class文件加载欲存入持久代时空间不足
  • 猜想印证

    • Class 对象9:java类编译后生成的.class文件,它包含了与类有关的信息
    • Class 加载:10JVM 懒加载机制,只有当 Class 首次调用时才会被ClassLoader加载放入持久代中
  • 异常结论

    • 文件数量过多,Class对象过多,大于开发环境的预设的持久代大小
  • 异常解决

    • 设置 catalina.sh 中添加 JVM 配置参数,将持久代大小调整为 256M
  • 问题修复

    • vi /tomcat/bin/catalina.sh

    • 启动参数后新增

      -server -XX:PermSize=128m -XX:MaxPermSize=256m -Xmn1536m -Xms2048m -Xmx2048m -XX:+UseParNewGC -XX:+UseConcMarkSweepGC 
      -XX:+CMSParallelRemarkEnabled -XX:CMSFullGCsBeforeCompaction=6 -XX:+CMSClassUnloadingEnabled -XX:+CMSPermGenSweepingEnabled 
      -XX:CMSInitiatingOccupancyFraction=75  -XX:SurvivorRatio=8 -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=../dump/
      
    • 重启服务

    • 再次查询GC

      [application@ip ~]$ jstat -gcutil 2232 1000 5
      S0 S1 E O P YGC YGCT FGC FGCT GCT
      100.00 0.00 80.84 17.21 23.50 2 2.345 0 0.000 2.345
      100.00 0.00 88.53 17.21 24.64 2 2.345 0 0.000 2.345
      100.00 0.00 93.70 17.21 27.23 2 2.345 0 0.000 2.345
      100.00 0.00 95.62 17.21 28.31 2 2.345 0 0.000 2.345
      100.00 19.15 100.00 17.22 28.40 3 2.345 0 0.000 2.345

    • FGC 使用率下降


  1. 深入理解JVM(一)——JVM之内存模型(JMM)JDK1.7 ↩︎

  2. Jvm组成以及调优 ↩︎

  3. JVM的方法区和永久带是什么关系? ↩︎

  4. JVM内存溢出详解(栈溢出,堆溢出,持久代溢出以及无法创建本地线程) ↩︎

  5. 【Tomcat】Tomcat配置JVM参数步骤 ↩︎

  6. PermGen space 溢出 使用jstat查看 Permsize 占用情况 并设置 PermSize和MaxPermSize ↩︎

  7. Java JVM- jstat查看jvm的GC情况 ↩︎

  8. 【Tomcat】tomcat logs 目录下各日志文件的含义 ↩︎

  9. java Class对象 ↩︎

  10. Java中Class对象详解 ↩︎

### 回答1: "java.lang.outofmemoryerror: permgen space" 意思是Java虚拟机的永久代空间已经用完了。这是由于在运行过程中加载的类或元数据占用了太多的内存,导致永久代空间不足。可以通过增加永久代空间的大小来解决这个问题。 ### 回答2: Java.lang.outofmemoryerror: permgen spaceJava虚拟机在执行Java应用时,当永久代的内存被占满了,而无法再为新的类、反射信息、字符串等分配内存时所抛出的异常。一般来说,Java应用使用的是堆内存和永久代内存,而堆内存主要是用于对象实例化和存储,而永久代内存则主要用于存储类信息、方法信息、静态变量信息以及字符串常量等元数据信息。因此,当应用程序中有大量动态创建的类或字符串常量等元数据信息时,就容易导致永久代内存被占满,从而导致该错误发生。 要解决Java.lang.outofmemoryerror: permgen space,可以采取以下几种方法: 1、增大永久代内存:可以通过设置JVM参数-XX:PermSize和-XX:MaxPermSize来增大永久代内存的大小。 2、JVM升级:JVM的新版本优化了永久代内存的管理方式,可以通过升级JVM来解决该错误。 3、清理未使用的类:可以使用一些工具来对应用程序中未使用的类进行清理,从而释放永久代内存。 4、优化应用程序:可以对应用程序进行优化,减少其动态创建类和字符串常量等元数据信息的数量,从而减少永久代内存的占用。 5、重启应用程序:如果以上方法都未能解决该错误,可以尝试重启应用程序,从而释放永久代内存。 总之,Java.lang.outofmemoryerror: permgen space是开发过程中比较常见的错误,需要根据具体情况采取不同的解决方法。 ### 回答3: Java.lang.OutOfMemoryError: PermGen space(永久代空间)通常是在JVM内存不足时发生的错误。PermGen space指的是JVM用于存储类、方法定义等元数据的永久代空间。当JVM加载过多的类、方法或者字符串等时,PermGen space的空间可能会被耗尽,导致OutOfMemoryError的错误。 为了避免Java中的OutOfMemoryError: PermGen space错误,可以采取以下措施: 1. 调整JVM的参数。通过增加PermGen space的大小来缓解这个错误。可以通过在Java命令中使用-XX:PermSize和-XX:MaxPermSize参数来增加永久代的大小,但这样做只解决了问题的表面,没有根本解决这个问题。 2. 优化代码和资源管理。优化代码可以减少类和方法等元数据的数量,同时及时释放程序中不再需要的对象,防止内存泄漏等资源浪费现象。 3. 尽量避免使用动态代理、反射等技术。这些技术会增加系统的开销,导致产生更多的类和方法等元数据,可能会加重PermGen space的压力。 总之,避免OutOfMemoryError: PermGen space错误需要细致的内存管理及代码调优。理性使用JVM的参数调整,避免过渡依赖动态代理、反射等技术是有效的措施。同时,可以借助各种性能工具和监控工具对程序进行优化和管理,提升应用的性能和稳定性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值