如何分析JVM 永久代内存溢出java.lang.OutOfMemoryError: PermGen space

时间:2023-02-07 17:22:01

  weblogic出现永久代内存溢出,以前处理这种情况就是加大永久代,但现在已经加到1GB还是不够,先临时加到1.5G,监控GC日志,永久代在不断的增长,说明在发送内存泄露。

java.lang.OutOfMemoryError: PermGen space

Dumping heap to java_pid92235.hprof ...

1.分析dump文件,根据定位堆内存溢出的经验,找到主要矛盾。

   Java Basics --> class loader explorer 查找哪个类最多,问题来了,无法定位出来,类太多了,无法归纳。

2.有两个JVM参数,用来跟踪类加载和卸载的信息,是乎可以从这里下手,哪些没有被卸载的类找出来。

  -XX:+TraceClassLoading -XX:+TraceClassUnloading用来打印类被加载和卸载的过程信息,如下:

[Loaded java.lang.Object from /data/jdk1.6.0_45/jre/lib/rt.jar]
[Loaded java.io.Serializable from /data/jdk1.6.0_45/jre/lib/rt.jar]
[Loaded java.lang.Comparable from /data/jdk1.6.0_45/jre/lib/rt.jar]
[Loaded java.lang.CharSequence from /data/jdk1.6.0_45/jre/lib/rt.jar]
[Loaded java.lang.String from /data/jdk1.6.0_45/jre/lib/rt.jar]
[Loaded java.lang.reflect.GenericDeclaration from /data/jdk1.6.0_45/jre/lib/rt.jar]
[Loaded java.lang.reflect.Type from /data/jdk1.6.0_45/jre/lib/rt.jar]
.....................................................................
[Unloading class com.webservice.material.wms.client.physinventory.IPhysInventoryClientService]
[Unloading class com.groupmaterial.performance.appservice.IPerformanceService]
[Unloading class com.comtop.usermanagement.usernode.UserNode]
[Unloading class com.material.inventory.issue.exception.IssueException]
[Unloading class com.material.purchase.contractmark.model.ContractPerformGradeItemVO]
[Unloading class com.ps.internal.projectinfo.appservice.ICommuniSubprojectVInternalBizService]
[Unloading class com.ps.internal.projectinfo.model.ScheduleItemTemplateDTO]

打印了大量这样的信息,需要写一个程序解析,以下是我写的程序:

--初始化数据开始
drop table load_class purge;
truncate table load_class;
create table load_class
(
nu number,
action varchar2(20),
class_name varchar2(1000),
class_file varchar2(1000)
);
--执行java代码导入之后,处理一些特殊的格式
update load_class
set action = replace(action, '[', ''),
class_file = replace(class_file, ']', ''),
class_name = replace(class_name, ']', '');
commit;
update load_class
set class_name = replace(class_name, 'file:', ''),
class_file = replace(class_file, 'file:', '');
commit;

select count(1) from load_class;


--显示加载且没有卸载的类
drop table load_class_result purge;
create table load_class_result as
with res as
(select count(*) over(partition by action,class_name order by nu asc) rn,
t.*
from load_class t)
,res1 as (select rn,class_name from res a where a.action='Loaded'
minus
select rn,class_name from res b where b.action='Unloading')
select b.* from res1 a, res b where a.rn= b.rn and a.class_name= b.class_name;



import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
/**
* [Loaded java.lang.ClassNotFoundException from /usr/local/jdk1.6/jre/lib/rt.jar]
* [Unloading class com.material.externalinterface.fmis.impl.FmisBizService]
*
*/
public class PermAla {
static final String driver_class = "oracle.jdbc.driver.OracleDriver";
static final String connectionURL = "jdbc:oracle:thin:@10.11.115.164:1521:orcl";
static final String userID = "test";
static final String userPassword = "test";
public static void readTxtFile(String filePath){
Connection con = null;
String s_sql = "insert into load_class values(?,?,?,?)";
PreparedStatement pstmt = null;
int i=0;
try {
Class.forName (driver_class).newInstance();
con = DriverManager.getConnection(connectionURL, userID, userPassword);
pstmt = con.prepareStatement(s_sql);
con.setAutoCommit(false);
String encoding="GBK";
File file=new File(filePath);
InputStreamReader read = new InputStreamReader(
new FileInputStream(file),encoding);//考虑到编码格式
BufferedReader bufferedReader = new BufferedReader(read);
String lineTxt = null;
String[] lineTxtArray= null;
while((lineTxt = bufferedReader.readLine()) != null){
if(lineTxt.indexOf("[Loaded")==0 ) {
lineTxtArray = lineTxt.split(" ");
pstmt.setInt(1, i);
pstmt.setString(2, lineTxtArray[0]);
pstmt.setString(3, lineTxtArray[1]);
if(lineTxtArray.length ==4) {
pstmt.setString(4, lineTxtArray[3]);
}else{
System.out.println(lineTxt);
}
pstmt.addBatch();
i++;
} else if(lineTxt.indexOf("[Unloading")==0){
lineTxtArray = lineTxt.split(" ");
pstmt.setInt(1, i);
pstmt.setString(2, lineTxtArray[0]);
pstmt.setString(3, lineTxtArray[2]);
pstmt.addBatch();
i++;
}
if(i % 10000 == 0){
pstmt.executeBatch();
con.commit();
}
}
con.commit();
read.close();
} catch (Exception e) {
System.out.println("读取文件内容出错,行数:"+i);
e.printStackTrace();
}finally{
if(pstmt != null){
try {
pstmt.close();
} catch (Exception e) {
e.printStackTrace();
}finally{
pstmt = null;
}
}
if(con != null){
try {
con.close();
} catch (Exception e) {
e.printStackTrace();
}finally{
con = null;
}
}
}

}

public static void main(String argv[]){
String filePath = "E:\\20161213\\nohup.out";
readTxtFile(filePath);
}
}

select t.nu,t.action,t.class_name,t.class_file from load_class_result t;
  NU  ACTION  CLASS_NAME                       CLASS_FILE
----- ------- ------------------------------ ------------------------------------------------------------
98988 Loaded  ConditionEvaluator1797b72541ab __JVM_DefineClass__
12221 Loaded  antlr.ANTLRException           /data/wls1035/modules/com.bea.core.antlr.runtime_2.7.7.jar
96647 Loaded  antlr.ANTLRException           /data/LCAM/Domain/_Domain/servers/Server1/stage/EAR/EAR/APP-INF/lib/wlfullclient.jar
12237 Loaded  antlr.ANTLRHashString          /data/wls1035/modules/com.bea.core.antlr.runtime_2.7.7.jar
96685 Loaded  antlr.ANTLRHashString          /data/LCAM/Domain/Domain/servers/Server1/stage/EAR/EAR/APP-INF/lib/wlfullclient.jar
12236 Loaded  antlr.ANTLRStringBuffer        /data/wls1035/modules/com.bea.core.antlr.runtime_2.7.7.jar
96684 Loaded  antlr.ANTLRStringBuffer        /data/LCAM/Domain/Domain/servers/Server1/stage/EAR/EAR/APP-INF/lib/wlfullclient.jar
96662 Loaded  antlr.ASTFactory               /data/LCAM/Domain/Domain/servers/Server1/stage/EAR/EAR/APP-INF/lib/wlfullclient.jar
96710 Loaded  antlr.ASTNULLType              /data/LCAM/Domain/Domain/servers/Server1/stage/EAR/EAR/APP-INF/lib/wlfullclient.jar

..............................................................

以下是我负责的应用类的加载情况,我粗略的估计一下,1万个类100M。

__JVM_DefineClass__(反射产生的类) 21865
EAR/APP-INF/lib 25326
EAR/APP-INF/classes 21275
wls1035 19007
Server1/cache/EJBCompilerCache 5996
/data/jdk1.6.0_45/jre 3485
weblogic.utils.classloaders.GenericClassLoader
sun.misc.Launcher$AppClassLoader
weblogic.utils.classloaders.ChangeAwareClassLoader
2511
jsp_temp 527
在多个时间点分析nohup.out日志,看到反射的类在不断增大,sun公司jdk可以设置  -Dsun.reflect.inflationThreshold=2147483647,IBM的jdk设置-Dsun.reflect.inflationThreshold=0 , 可以减少反射类的生成。实测反射类降到了3000。

http://*.com/questions/16130292/java-lang-outofmemoryerror-permgen-space-java-reflection