上段时间有台机器发生了 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和加载类的情况并没有呈现直线上涨,已经他们一直都使用者动态类生成类的静态缓存,但是这种动态创建类使用静态缓存在一些情况下并不适合需求。
分享到:
相关推荐
假设在使用Spring框架结合Hibernate持久层技术时遇到PermGen Space内存溢出的问题,通常是因为Spring AOP使用了CGLIB动态代理技术,这会动态生成大量类,进而消耗更多的PermGen Space资源。解决此类问题时,除了增大...
- **方法区内存溢出(outOfMemoryError:permgen space)**:随着Java 8的发布,方法区被元空间(Metaspace)所替代,但它仍然可能发生内存溢出。当程序加载了大量的类、常量、静态变量,或者使用了反射、CGLIB等技术...
### JVM实战-对象访问与内存溢出异常解析 #### 实验背景与目标 在Java虚拟机(JVM)中,不同的内存区域负责不同的功能,并且各自可能会出现特定类型的内存溢出异常。通过本实验,旨在深入理解JVM内存管理机制以及...
方法区也可能会出现内存溢出错误,尤其是在大量使用反射、动态代理、CGLIB等字节码操作框架的情况下。为了解决方法区的内存溢出问题,可以调整JVM参数以增加方法区的大小。 ### 解决JAVA内存溢出问题的关键参数 在...
PermGen space溢出是指永久保存区域(Permanent Generation space)内存溢出的情况。PermGen space主要用于存放Class和Meta信息。当 PermGen space的大小不足以存储类信息时,会抛出`java.lang.OutOfMemoryError: ...
本文将详细介绍 JAVA 内存溢出案例的汇总,主要涵盖栈深度溢出、永久代内存溢出、本地方法栈溢出等多种类型的内存溢出场景,并提供相应的解决方案和编程建议。 栈深度溢出 栈深度溢出是指 Java 虚拟机栈的深度超过...
CGlib的核心是ASM库,ASM是一个底层的Java字节码操纵和分析框架,可以用来动态生成类或增强已有类的功能。CGlib在其之上进行了封装,使其更易于使用。下面我们将详细探讨CGlib的主要功能和使用方法: 1. **动态代理...
CGlib,全称为Code Generation Library,是一款强大的Java字节码操作库,它允许开发者在运行时动态创建和修改类。这个库被广泛应用于许多框架和工具中,如Spring AOP、Hibernate等,用于实现面向切面编程和持久化层...
Cglib子类代理是Java动态代理的一种实现方式,它主要通过字节码技术在运行时动态创建一个目标对象的子类,以此来实现代理功能。Cglib是一个强大的高性能的代码生成库,它在许多AOP(面向切面编程)框架中被广泛应用...
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的工作原理是基于ASM库,ASM是一个字节码操作和分析框架,它可以用来动态生成类或增强已存在的Java类的功能。ASM提供了一种直接操作字节码的方法,这使得CGLib能够创建目标类的子类,并在子类中拦截并扩展父类...
CGLIB介绍与原理(部分节选自网络) 一、什么是CGLIB? CGLIB是一个功能强大,高性能的代码生成包。它为没有实现接口的类提供代理,为JDK的动态代理提供了很好的补充。通常可以使用Java的动态代理创建代理,但当要...
【CGLib:强大的Java代码生成库】 CGLib(Code Generation Library)是一个强大的、高性能的代码生成库,它在运行期扩展Java类与实现Java接口。这个库最初是为EJB的透明代理而设计的,但后来发展成为了一个广泛的...
CGLib,全称为Code Generation Library,是一个强大的Java代码生成库,广泛用于动态代理、AOP(面向切面编程)等领域。它允许开发者在运行时创建和扩展Java类,而无需直接编写新的源代码或编译步骤。这个压缩包...
CGLIB,全称为Code Generation Library,是一个强大的高性能的代码生成库,被广泛应用于Java世界,尤其是Spring框架中。它允许程序在运行时动态地创建Java对象并扩展已有类的功能。CGLIB是通过字节码技术实现的,而...
8. **注意事项**:尽管Cglib提供了便捷的类生成能力,但生成的子类可能会增加内存占用,且对于final方法或final类,Cglib无法生成子类,这时需要考虑其他代理方案,如Java的动态代理。 总的来说,Cglib3.3.0作为一...
CGLIB是基于ASM库来实现的,ASM是一个底层的Java字节码操控和分析框架,它可以用来动态生成类或者增强已有类的功能。 **一、CGLIB的用途** 1. **动态代理**:CGLIB是Spring框架中AOP(面向切面编程)的重要组成...