`
touchmm
  • 浏览: 1039817 次
  • 性别: Icon_minigender_1
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

简单分析cglib引起的PermSize Space内存溢出

 
阅读更多
上段时间有台机器发生了 java.lang.OutOfMemoryError: PermGen space 内存溢出的异常,当时大概判断了原因后就把 MaxPermSize 配置调高后,就把问题解决了,不过空下时间后还是需要继续把review代码。

一般来说PermSize Space OOM的话,第一种可能就是方法区溢出,第二种就是运行时常量池溢出,第二种查看后基本排除掉,问题就应该出现在方法区的溢出,方法区用于存放class的相关信息,如类名,访问修饰符,常量池,字段描述,方法描述等等,对于这个区域的溢出,基本上都是运行时产生大量的类填满了整个方法区,直到溢出。
spring aop中都是使用到了cglib这类字节码的技术,动态代理的类越多,就需要越多的方法区来保证动态生成的class可以加载入到内存中去,下面的例使用cglib直接进行动态代理产生大量的动态类,然后使用jconsole进行观察。

首先将本机的jvm配置为 -XX:PermSize=64M -XX:MaxPermSize=64M ,给到PermSize最大为64M的内存

 

public   class  PermgenOOM {

    
public   static   void  main(String[] args)  throws  InterruptedException {
        
int  i = 0 ;
        
while ( true ){
            Enhancer enhancer 
=   new  Enhancer();
            enhancer.setSuperclass(Product.
class );
            enhancer.setUseCache(
false ); //  关闭CGLib缓存,否则总是生成同一个类
            enhancer.setCallback( new  MethodInterceptor() {                
                @Override
                
public  Object intercept(Object obj, Method method, Object[] args,
                        MethodProxy methodproxy) 
throws  Throwable {
                    
//  TODO Auto-generated method stub
                     return  methodproxy.invokeSuper(obj,args);
                }
            });
            enhancer.create();
            Thread.sleep(
100 );
        }
    }
}

 

很快,系统就抛出了 java.lang.OutOfMemoryError: PermGen space
内存池peimgen的情况


加载类的情况



并且在方法区中,一个类如果要被垃圾收集器回收掉,判断的条件是非常苛刻的,很多人都把方法区称为“永久区”(Permanent Generation),但据说2者在本质上是不一致的,另外还有称呼为“非堆区”,不纠结这个了。

再看看enhancer.setUseCache(false),如果选择为true的话,那么就使用和更新一类具有相同属性生成的类的静态缓存,而不会在同一个类文件还继续被动态加载并视为不同的类,这个其实跟类的equals()和hashCode()有关,它们是与cglib内部的class cache的key相关的。

将上面的程序 enhancer.setUseCache(false) 改为 enhancer.setUseCache(ture)

 

public   class  PermgenOOM {

    
public   static   void  main(String[] args)  throws  InterruptedException {
        
int  i = 0 ;
        
while ( true ){
            Enhancer enhancer 
=   new  Enhancer();
            enhancer.setSuperclass(Product.
class );
            enhancer.setUseCache(
true ); //  或者不写,默认值就是true
            enhancer.setCallback( new  MethodInterceptor() {                
                @Override
                
public  Object intercept(Object obj, Method method, Object[] args,
                        MethodProxy methodproxy) 
throws  Throwable {
                    
//  TODO Auto-generated method stub
                     return  methodproxy.invokeSuper(obj,args);
                }
            });
            enhancer.create();
            Thread.sleep(
100 );
        }
    }
}

 

内存池peimgen的情况


加载类的情况



可以发现内存池peimgen和加载类的情况并没有呈现直线上涨,已经他们一直都使用者动态类生成类的静态缓存,但是这种动态创建类使用静态缓存在一些情况下并不适合需求。
2
0
分享到:
评论

相关推荐

    eclipse 内存溢出解决办法

    假设在使用Spring框架结合Hibernate持久层技术时遇到PermGen Space内存溢出的问题,通常是因为Spring AOP使用了CGLIB动态代理技术,这会动态生成大量类,进而消耗更多的PermGen Space资源。解决此类问题时,除了增大...

    jvm内存溢出

    - **方法区内存溢出(outOfMemoryError:permgen space)**:随着Java 8的发布,方法区被元空间(Metaspace)所替代,但它仍然可能发生内存溢出。当程序加载了大量的类、常量、静态变量,或者使用了反射、CGLIB等技术...

    JVM实战-对象访问与内存溢出异常解析

    ### JVM实战-对象访问与内存溢出异常解析 #### 实验背景与目标 在Java虚拟机(JVM)中,不同的内存区域负责不同的功能,并且各自可能会出现特定类型的内存溢出异常。通过本实验,旨在深入理解JVM内存管理机制以及...

    解决JAVA内存溢出问题

    方法区也可能会出现内存溢出错误,尤其是在大量使用反射、动态代理、CGLIB等字节码操作框架的情况下。为了解决方法区的内存溢出问题,可以调整JVM参数以增加方法区的大小。 ### 解决JAVA内存溢出问题的关键参数 在...

    Java内存溢出实现原因及解决方案

    PermGen space溢出是指永久保存区域(Permanent Generation space)内存溢出的情况。PermGen space主要用于存放Class和Meta信息。当 PermGen space的大小不足以存储类信息时,会抛出`java.lang.OutOfMemoryError: ...

    JAVA 内存溢出案例汇总

    本文将详细介绍 JAVA 内存溢出案例的汇总,主要涵盖栈深度溢出、永久代内存溢出、本地方法栈溢出等多种类型的内存溢出场景,并提供相应的解决方案和编程建议。 栈深度溢出 栈深度溢出是指 Java 虚拟机栈的深度超过...

    cglib的依赖包

    CGlib的核心是ASM库,ASM是一个底层的Java字节码操纵和分析框架,可以用来动态生成类或增强已有类的功能。CGlib在其之上进行了封装,使其更易于使用。下面我们将详细探讨CGlib的主要功能和使用方法: 1. **动态代理...

    cglib 源代码分析(原创)

    CGlib,全称为Code Generation Library,是一款强大的Java字节码操作库,它允许开发者在运行时动态创建和修改类。这个库被广泛应用于许多框架和工具中,如Spring AOP、Hibernate等,用于实现面向切面编程和持久化层...

    简单实现Cglib子类代理

    Cglib子类代理是Java动态代理的一种实现方式,它主要通过字节码技术在运行时动态创建一个目标对象的子类,以此来实现代理功能。Cglib是一个强大的高性能的代码生成库,它在许多AOP(面向切面编程)框架中被广泛应用...

    CGLIB依赖jar包

    CGLIB是基于ASM(一个底层的Java字节码操作和分析框架)来实现的,它允许开发者在运行时为Java类创建子类,而无需访问其源代码或重新编译。这种技术在许多场景下都非常有用,比如实现AOP(面向切面编程)中的动态...

    基于Cglib简单实现Spring体系(Ioc+Aop+Mvc)

    基于Cglib简单实现Spring体系(Ioc+Aop+Mvc)基于Cglib简单实现Spring体系(Ioc+Aop+Mvc)基于Cglib简单实现Spring体系(Ioc+Aop+Mvc)基于Cglib简单实现Spring体系(Ioc+Aop+Mvc)基于Cglib简单实现Spring体系(Ioc+Aop+Mvc)...

    cglib及其依赖包

    CGLib的工作原理是基于ASM库,ASM是一个字节码操作和分析框架,它可以用来动态生成类或增强已存在的Java类的功能。ASM提供了一种直接操作字节码的方法,这使得CGLib能够创建目标类的子类,并在子类中拦截并扩展父类...

    cglib.jar下载

    CGLIB介绍与原理(部分节选自网络) 一、什么是CGLIB? CGLIB是一个功能强大,高性能的代码生成包。它为没有实现接口的类提供代理,为JDK的动态代理提供了很好的补充。通常可以使用Java的动态代理创建代理,但当要...

    cglib_cglib3.2_remain3gr_cglibjar包_cglib.jar_

    【CGLib:强大的Java代码生成库】 CGLib(Code Generation Library)是一个强大的、高性能的代码生成库,它在运行期扩展Java类与实现Java接口。这个库最初是为EJB的透明代理而设计的,但后来发展成为了一个广泛的...

    cglib_cglib.zip

    CGLib,全称为Code Generation Library,是一个强大的Java代码生成库,广泛用于动态代理、AOP(面向切面编程)等领域。它允许开发者在运行时创建和扩展Java类,而无需直接编写新的源代码或编译步骤。这个压缩包...

    CGLIB需要的asm-2.2.3.jar和cglib-nodep-2.2.jar

    CGLIB,全称为Code Generation Library,是一个强大的高性能的代码生成库,被广泛应用于Java世界,尤其是Spring框架中。它允许程序在运行时动态地创建Java对象并扩展已有类的功能。CGLIB是通过字节码技术实现的,而...

    Cglib3.3.0最新版jar包

    8. **注意事项**:尽管Cglib提供了便捷的类生成能力,但生成的子类可能会增加内存占用,且对于final方法或final类,Cglib无法生成子类,这时需要考虑其他代理方案,如Java的动态代理。 总的来说,Cglib3.3.0作为一...

    cglib2.2jar包

    CGLIB是基于ASM库来实现的,ASM是一个底层的Java字节码操控和分析框架,它可以用来动态生成类或者增强已有类的功能。 **一、CGLIB的用途** 1. **动态代理**:CGLIB是Spring框架中AOP(面向切面编程)的重要组成...

Global site tag (gtag.js) - Google Analytics