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

  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://stackoverflow.com/questions/16130292/java-lang-outofmemoryerror-permgen-space-java-reflection


你可能感兴趣的:(如何分析JVM 永久代内存溢出java.lang.OutOfMemoryError: PermGen space)