`

JVM内存错误问题的处理建议

    博客分类:
  • j2ee
阅读更多

Unloading class sun.reflect.GeneratedMethodAccessor

问题可能的原因一:由于Xms和Xmx设置大小不当造成的,当程序进行反射操作时没有内存进行此操作。

    解决方案:使用-XX:PermSize 与 -XX:MaxPermSize  来增加Perm空间大小。因为通过reflect调用方法,实际上,都会生成一个实际的class,并且在perm空间装载。而如果perm空间不够大,同时GC又无法卸载原来装载的类,则会抛出异常。

     1.设置MaxPermSize
     MaxPermSize 可以设置为最大堆分配 (mx) 的一半。尝试设置 .XX:MaxPermSize=256m,但是,也有人设置到和MX一样的.可以尝试一下.
     2.Heap Size
    你的ERROR不是OUTOFMEMEROY,所以HEAP的大小应该可用.-Xms512m -Xmx512m 可以试一试.但是最近4月底有人发表意见说设成相同的比太好,会导致GC运行时间过短,导致效率下降.
     3.HeapFreeRatio
    这项设置对你的问题有没有帮助不太清楚,做一个比较反差的测试,-XX:MinHeapFreeRatio=10,-XX:MaxHeapFreeRatio=20,看看区别,建议最终设置:
             -XX:MinHeapFreeRatio=30,-XX:MaxHeapFreeRatio=70
     4.NewRatio
    有可能是young generation 的大小过大,导致permanent generation大小不够,所以调整NewRatio有可能有用.
           -XX:NewRatio=4

    结论:尝试将Xms设小了一些,问题仍未解决,只是出现错误的周期变长。 如果初始值(Xms)太大,虽然开始阶段不会有多少GC,但是,由于一开始就在一个很大的空间分配,所以,会出现很多碎片,(这好像叫暗碎片dark heap),就会浪费很多heap,(我好像没有见过SUN的JVM有compaction,即碎片整理)。如果heap的初始值比较小,那么就能减少很多碎片的产生,它能使heap被占满的时间周期变长。

问题可能的原因二:代码中肯定有内存泄露。GC很可能没有及时的回收内存垃圾,所以造成了momery leak。

    建议:不能依赖GC回收,真正有效的途径只能是及时释放资源。笨方法之一是不输出 gc 日志,就不会有问题。



与垃圾收集和序列化有关的问题

垃圾收集器与类装入器的交互很密切。在众多的事情当中,收集器检查类装入器的数据结构,来判断哪个类是活动的 —— 也就是说,不应当被当作垃圾收集的。这通常会带来一些意料之外的问题。

场景演示:在这个场景中,序列化以一种意料之外的方式影响了类的垃圾收集(GC):


在这个示例中,SerializationTest 实例化了一个 URLClassLoader,叫做 loader。在装入 SerializationClass 之后,对类装入器的引用被取消。想法是希望这样可以允许类装入器装入的类被垃圾收集掉。这些类的代码如清单 9 和 10 所示:


清单 9. SerializationTest.java

                                
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;

public class SerializationTest extends ClassLoader {

   public static void main(String args[]) {
      try {
         URLClassLoader loader = new URLClassLoader(new URL[] { new URL(
               "file://C:/CL_Article/Serialization/dir1/") });
         System.out.println("Loading SerializationClass");
         Class c = loader.loadClass("SerializationClass");
         System.out.println("Creating an instance of SerializationClass");
         c.newInstance();
         System.out.println("Dereferencing the class loader");
         c = null;
         loader = null;
        
         System.out.println("Running GC...");
         System.gc();
         System.out.println("Triggering a Javadump");
         com.ibm.jvm.Dump.JavaDump();
        
      } catch (MalformedURLException e) {
         e.printStackTrace();
      } catch (InstantiationException e) {
         e.printStackTrace();
      } catch (IllegalAccessException e) {
         e.printStackTrace();
      } catch (ClassNotFoundException e) {
         e.printStackTrace();
      }
   }
}



清单 10. SerializationClass.java

                                
import java.io.File;
import java.io.FileOutputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

public class SerializationClass implements Serializable {

    private static final long serialVersionUID = 5024741671582526226L;

    public SerializationClass() {
        try {
            File file = new File("C:/CL_Article/Serialization/test.txt");
            FileOutputStream fos = new FileOutputStream(file);
            ObjectOutputStream oos = new ObjectOutputStream(fos);
            oos.writeObject(this);
            oos.reset();
            oos.close();
            fos.close();
            oos = null;
            fos = null;
            file = null;
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}



使用 Javadump,可以发现类装入器是否被垃圾收集了。如果在类装入器的列表中出现以下部分,就说明它没有被收集:


------a- Loader java/net/URLClassLoader(0x44DC6DE0), Shadow 0x00ADB6D8,
        Parent sun/misc/Launcher$AppClassLoader(0x00ADB7B0)
        Number of loaded classes 1
        Number of cached classes 11      
        Allocation used for loaded classes 1      
        Package owner 0x00ADB6D8



虽然取消对用户定义的类装入器的引用看起来像是一种确保类被垃圾收集的方法,但实际并不是这回事。在前面的示例中,由于 java.io.ObjectOutputStream.writeObject(Object obj) 的使用以及它对 GC 的影响,所以产生了问题。

在调用 writeObject() 时(用来序列化 SerializationClass),对这个类对象的引用就在内部被传递给 ObjectStreamClass 并保存在一个查询表中(也就是内部缓存)。保存这个引用是为了加快日后对同一个类的序列化。

当取消对类装入器的引用时,它装入的类就变成无法进行垃圾收集的了。这是因为在 ObjectStreamClass 查询表中,没有了对 SerializationClass 类的活动引用。ObjectStreamClass 是一个原始类,所以永远不会被垃圾收集。查询表是从 ObjectStreamClass 中的静态字段引用的,而且保存在类本身之中,而不是保存在实例中。所以,对 SerializationClass 的引用存在于 JVM 的生命周期中,所以类就不能被垃圾收集。重要的是,SerializationClass 类有一个到其定义类装入器的引用,所以它也不可能完整地取消引用。

为了避免这个问题,凡是要进行序列化的类,都应当由不需要被垃圾收集的类装入器装入 —— 例如由系统类装入器装入。

分享到:
评论

相关推荐

    JVM内存空间分配笔记

    ### JVM内存空间分配详解 #### 一、JVM内存模型概览 ...综上所述,理解JVM内存分配机制对于Java开发者来说至关重要,这不仅有助于编写高效、稳定的代码,还能在遇到性能瓶颈时快速定位问题并进行优化。

    如何配置Tomcat的JVM虚拟机内存大小

    本文将详细探讨如何在Tomcat服务器上配置JVM内存,包括其背景、配置方法以及最佳实践。 #### Tomcat与JVM的关系 Tomcat作为一款流行的开源Java Servlet容器,用于部署和运行基于Java的Web应用。然而,Tomcat自身并...

    JVM Diagnostics Guide 1.4.2

    2. **内存模型**:详细讲解JVM内存结构,如堆内存(Heap)、栈内存(Stack)、方法区(Method Area)、本地方法栈(Native Method Stack)和程序计数器(PC Register)等,以及它们各自的作用和相互关系。...

    JVM堆内存分析工具,OOM排查工具。包括ha和mat两种

    在Java虚拟机(JVM)的运行环境中,内存管理是至关重要的一个环节,尤其是在大型应用或者高并发场景下。当程序出现性能问题或者...通过持续监控和优化,可以确保JVM在处理复杂任务时保持高效且不会因内存问题而崩溃。

    jvm.rar_JAVA虚拟机_jvm

    7. **异常处理**:JVM支持异常处理机制,通过try-catch-finally语句块来捕获和处理运行时错误。 8. **多线程**:JVM原生支持多线程,每个线程有自己的程序计数器、虚拟机栈和本地方法栈,共享堆内存。 9. **JNI...

    33、JVM探究.pdf

    例如,了解JVM内部机制,能更快地调试和优化程序,处理运行时错误,如StackOverflowError和OOM。 总之,JVM是一个复杂且关键的领域,深入学习可以帮助Java开发者更好地理解和控制程序的运行。无论是面试还是实际...

    myeclipse内存溢出问题解决方案

    如果堆内存不足,JVM会尝试通过垃圾回收(GC)释放空间,但如果连续回收后仍无法满足需求,就会抛出`OutofMemoryError`错误。 为了防止内存溢出,应合理设置-Xms和-Xmx,一般推荐它们保持相同值以避免每次GC后调整...

    JVM优化3(Tomcat参数调优,JVM参数调优,jvm字节码,代码优化).pdf

    JVM参数调优部分未在提供的内容中显示,但一般来说,JVM参数调优会涉及到调整堆内存分配、堆外内存大小、垃圾回收器选择、新生代和老年代的比例,以及各种相关参数如-Xms、-Xmx、-Xmn、-XX:+UseG1GC等。这些调整能...

    IBM JVM参数选项

    IBM Java虚拟机(JVM)为开发者提供了丰富的配置选项来优化应用程序性能、诊断问题以及调整各种资源使用情况。本文将详细解释IBM JVM中的关键参数及其功能,帮助您更好地管理和调优Java应用。 #### 基础参数 1. **-...

    JVM相关的常见面试问题汇总.pdf

    ### JVM相关的常见面试问题知识点汇总 #### 1. 什么是JVM? - **定义**: JVM全称Java Virtual Machine,即Java虚拟机,是Java程序运行的底层平台。 - **作用**: 它为Java应用程序提供了一个运行环境,可以执行Java...

    java内存泄露、溢出检查方法和工具

    通过对代码进行调整,并优化JVM内存设置,成功解决了内存溢出的问题。 #### 八、扩展阅读 - **Eclipse Memory Analyzer (MAT)**: [官方网站](https://www.eclipse.org/mat/) - **VisualVM**: [官方网站]...

    整理-JVM相关面试题2024

    - **定义**:当JVM无法为新对象分配足够的内存空间时,就会发生内存溢出错误。这通常发生在堆内存不足的情况下。 #### 4.1 什么是内存泄漏? - **定义**:内存泄漏指的是程序中不再使用的对象未能及时被垃圾回收器...

    Weblogic内存大小配置

    #### OOM问题与JVM处理机制 当Java堆或本地内存耗尽时,JVM会抛出“Out of Memory Error”,即OOM错误。对于Java堆内存不足,JVM会尝试触发垃圾回收,如果仍无法解决问题,则会抛出异常并终止应用程序。本地内存...

    ibm内存查看工具.zip

    3. **日志文件分析**:工具可以分析WAS的日志文件,查找与内存问题相关的错误或警告,快速定位问题根源。 4. **内存溢出文件检查**:当WAS发生内存溢出时,会生成相应的dump文件。该工具能够解析这些文件,帮助分析...

    java内存分析指引07_v0.2.doc

    解决内存溢出问题通常需要结合日志分析、代码审查和调整JVM内存参数。对于大数据量处理,可以采用分页策略减少一次性加载的数据量。对于代码层面,避免死循环和递归,确保对象在不再使用时被正确释放。最后,优化JVM...

    myeclipse-tomcat jdk内存溢出

    ### MyEclipse-Tomcat JDK 内存...- 对于生产环境,建议使用更严格的监控机制来预防和处理内存溢出问题。 通过以上步骤,可以有效地解决MyEclipse中Tomcat服务器出现的JDK内存溢出问题,提高开发效率和系统的稳定性。

    bitmap内存问题

    然而,在处理大量或高分辨率图像时,不当的`Bitmap`管理常常会导致内存溢出问题,这严重影响了应用程序的性能和用户体验。接下来,我们将深入探讨如何有效地管理和优化`Bitmap`的使用,从而避免内存溢出。 #### ...

    IBM SDK, Java Technology Edition, Version 5.0 IBM Java JVM诊断指南

    - **内存管理概述**:解释了JVM如何处理内存分配和释放。 - **对象分配**:探讨了JVM如何分配内存空间来存储新创建的对象。 - **可达性分析**:描述了如何确定哪些对象仍然是活跃的并需要保留内存。 - **垃圾收集**...

Global site tag (gtag.js) - Google Analytics