我们有一个Java应用程序,我可以说也利用了很多字符串变量。此外,我们以最大和初始内存都设置为256Mb来启动它。此后运行了一段时间,直到最近,我们发现它首先是一个GC,近两周后又出现了另一个GC。因此,我们发现FC的平均值为0.2145s,YGC为0.0511s。我们不确定这些值是否合适或导致其他问题?我们决定将内存增加到512Mb,并考虑其他一些GC设置,例如CMS设置?还应该优化代码,例如使用String变量吗?通常,什么对象或变量类型将移入“旧对象”?

Timestamp     S0      S1     E     O      P      YGC    YGCT      FGC FGCT   GCT
   2752472.6  69.74   0.00   3.67  51.72  44.17   4614  235.630   2   0.429  236.059
   2752477.6  69.74   0.00   5.38  51.72  44.17   4614  235.630   2   0.429  236.059
   2752482.6  69.74   0.00   7.51  51.72  44.17   4614  235.630   2   0.429  236.059
   2752487.6  69.74   0.00   9.52  51.72  44.17   4614  235.630   2   0.429  236.059
   2752492.6  69.74   0.00  10.55  51.72  44.17   4614  235.630   2   0.429  236.059


代码段

BoneCP connectionPool = null;
  class ConnectionHandler implements Runnable {


    private Socket receivedSocketConn1;
    ConnectionHandler(Socket receivedSocketConn1) {
      this.receivedSocketConn1=receivedSocketConn1;
    }
    Connection dbconn = null;

    public void run() { // etc
     BufferedWriter writeBuffer = null;
     BufferedReader readBuffer = null;
     String capturedMessage="";

     try{
        dbconn = connectionPool.getConnection();
        dbconn.setAutoCommit(false);

        while ((nextChar=readBuffer.read()) != -1){
          capturedMessage += (char) nextChar;

          if (nextChar == '*')
          {
           try{

                //all queries here.
                //for insert query this how i do
                Statement stmt1 = null;
                stmt1 = dbconn.createStatement();
                String insertQuery3 =........
                count = stmt9.executeUpdate(insertQuery3);
                try{
                  if ( stmt1!= null ){  stmt1.close();
                }
                else{
                System.out.println("No stm1 exist");

                }
                }catch(SQLException ex){
                  System.out.println("SQLException has been caught for stmt1");
                  ex.printStackTrace(System.out);
                }

                ///For select we do this

                Statement stmt2 = null;
                stmt2 = dbconn.createStatement();
                String selectQuery2= .........
                ResultSet rs2 = stmt2.executeQuery(selectQuery2);

                if(rs2.next())
                {

                }
                try{
                 if ( rs2!= null ){
                     rs2.close();
                 }   else{
                 System.out.println("No rs2 exist");
                 }

                 if ( stmt2!= null ){
                      stmt2.close();
                 }   else{
                 System.out.println("No stm2 exist");

                 }
                }catch(SQLException ex)
                {
                System.out.println("SQLException has been caught for stmt2");
                ex.printStackTrace(System.out);
                }



               dbconn.commit
            }
           catch (SQLException ex){
                ex.printStackTrace(System.out);
                try{
              dbconn.rollback();
           }
           catch (Exception rollback){
              rollback.printStackTrace(System.out);
              }
       }
       catch (Exception e){
           e.printStackTrace(System.out);
           try{
              dbconn.rollback();
           }
           catch (Exception rollback){
              rollback.printStackTrace(System.out);
             }
       }
       finally
     {

     }


        }
     catch (SocketTimeoutException ex){
           ex.printStackTrace();
     }
     catch (IOException ex){
           ex.printStackTrace();
     }
     catch (Exception ex){
           ex.printStackTrace(System.out);
     }
      finally{
        try{
         if ( dbconn != null ){
           dbconn.close();
         }
         else{
          System.out.println("dbConn is null in finally close");
         }
        }
        catch(SQLException ex){
            ex.printStackTrace();
        }
        try{
          if ( writeBuffer != null ){
            writeBuffer.close();
         }
         else{
          System.out.println("w is null in finally close");
         }
        }
        catch(IOException ex){
            ex.printStackTrace(System.out);
        }
       }
      }
    }


来自的终结器分析
sun.misc.Launcher $ ExtClassLoader @ 0xe003a648(50%)
大小:11.2 MB类:196对象:201.7k类加载器:7

共有91个对象实现了finalize方法。

 Histogram of Objects with Finalize Method
Class Name                         Objects Shallow Heap
com.mysql.jdbc.JDBC4Connection
First 10 of 38 objects             38      42,560
java.net.SocksSocketImpl
First 10 of 39 objects             39      4,368
java.util.jar.JarFile
All 6 objects                      6        384
java.util.zip.Inflater
All 6 objects                      6        192
java.util.concurrent.ScheduledThreadPoolExecutor
All 1 objects                      1        80
java.util.concurrent.ThreadPoolExecutor
All 1 objects                      1        72
Total: 6 entries
 91 47,656


来自的终结器分析

(46%)
大小:13.6 MB类:578对象:304.8k类加载器:4

总共19,341个对象实现了finalize方法。

Class Name                        Objects Shallow Heap
java.net.SocksSocketImpl
First 10 of 18,354 objects        18,354  2,055,648
com.sun.mail.smtp.SMTPTransport
First 10 of 162 objects           162     25,920
java.io.FileOutputStream
First 10 of 742 objects           742     23,744
com.mysql.jdbc.JDBC4Connection
First 10 of 15 objects            15       16,800
java.util.jar.JarFile
First 10 of 20 objects            20       1,280
java.util.zip.Inflater
First 10 of 25 objects            25       800
java.util.concurrent.ThreadPoolExecutor
All 8 objects                     8        576
sun.net.www.protocol.jar.URLJarFile
All 5 objects                     5        400
java.util.concurrent.ScheduledThreadPoolExecutor
All 2 objects                     2        160
java.lang.ClassLoader$NativeLibrary
All 4 objects                     4        128
java.io.FileInputStream
All 3 objects                     3        96
sun.jdbc.odbc.JdbcOdbcDriver
All 1 objects                     1        24
Total: 12 entries
 19,341 2,125,576


来自org.rzo.yajsw.boot.WrapperClassLoader @ 0xe02818c0的终结器分析(4%)
大小:966.3 KB类:361对象:19.9k类装载器:3

共有22个对象实现finalize方法。

 Histogram of Objects with Finalize Method
Class Name                              Objects Shallow Heap
java.util.jar.JarFile
First 10 of 11 objects                  11      704
java.util.zip.Inflater
All 10 objects                          10      320
java.util.concurrent.ThreadPoolExecutor
All 1 objects                           1       72
Total: 3 entries
 22 1,096


Histo Live结果。

 num     #instances         #bytes  class name
----------------------------------------------
   1:          6001       18078232  [I
   2:         44562        7196072  [B
   3:        103183        6054240  [C
   4:         31832        4786936  <constMethodKlass>
   5:         31832        4340240  <methodKlass>
   6:         31638        3543456  java.net.SocksSocketImpl
   7:         20127        3542352  com.mysql.jdbc.JDBC4ResultSet
   8:         41022        3461576  [Ljava.util.HashMap$Entry;
   9:        104185        3333920  java.lang.String
  10:         20198        3070096  com.mysql.jdbc.StatementImpl
  11:         20323        2926512  com.mysql.jdbc.Field
  12:         60329        2895792  java.util.TreeMap
  13:          2343        2800032  <constantPoolKlass>
  14:         61239        2449560  java.util.TreeMap$Entry
  15:        149690        2395040  java.lang.Object
  16:         41000        1968000  java.util.HashMap
  17:          2343        1895080  <instanceKlassKlass>
  18:          1954        1569536  <constantPoolCacheKlass>
  19:         31623        1517904  java.net.SocketInputStream


套接字的初始启动

71:             2            224  java.net.SocksSocketImpl
176:            1             32  java.net.Socket
202:            1             24  java.net.InetSocketAddress
206:            1             24  java.net.ServerSocket


运行50个套接字后。

 19:            52           5824  java.net.SocksSocketImpl
 37:            50           2400  java.net.SocketInputStream
 48:            51           1632  java.net.Socket
 88:             8            384  java.net.SocketOutputStream
 95:             8            320  java.net.SocketTimeoutException
 135:            7            112  java.net.Socket$3
 136:            7            112  java.net.Socket$2
 229:            1             24  java.net.ServerSocket

最佳答案

512 MB听起来并不多,您可能不值得花时间尝试进一步优化它。 BTW 512 Mb是512兆位。

中长期生存的物体最终出现在旧时代。

您可以使用内存分析器优化代码,以减少String的使用。您可以使用StringBuilder回收对象并降低GC压力,这是对象最终错误地租用在保管空间中的常见原因。

极端地说,您可能会发现可以消除所有String生成,但是我怀疑这样做是否值得,将内存增加到1 GB可能更简单/更便宜。

关于java - GC和YGC的发生以及下一步的 Action ,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/19500611/

10-09 16:36
查看更多