3.深刻jvm內核-原理、診斷與優化-3.經常使用jvm配置參數

1、jvm經常使用配置參數java

  1. 其實這樣來看,from和to其實只是一個邏輯概念,對於物理上來講,新生代其實就是分配對象的內存+待複製對象的內存空間apache

    -XX:+PrintGCDetails
     -XX:+PrintGCDetails這個是每次gc都會打印的,只是程序結束後纔打印詳細的堆信息
      -Xmx不包含,持久代空間
     堆空間是連續的
  2. 精簡jrewindows

    首先了解到:Java運行主要引賴於bin和Lib目錄,bin目錄主要存儲了java命令和須要的dll
     lib目錄是java虛擬機要用到的class和配置文件。
     bin目錄精簡的方式:
     一、bin目錄最主要的工具是java.exe,它用來執行class文件.
     若是隻是爲了單純運行Java程序的話,其餘可執行文件通常都是用不到的(可剔除).
    
     二、 bin目錄裏面的動態連接庫文件dll是java.exe執行class文件過程當中調用的.
     執行class文件,java.exe須要哪一個庫文件就加載哪一個dll,不需用的能夠剔除.
     查看java用到那個dll的,能夠經過windows的任務管理器,查看進程號,再用其它工具(如360)
     查看引用到的dll
    
     lib精簡方式:
     這裏面我給出一個精簡rt.jar的程序,本身寫的.(這裏主要是給出了精簡rt.jar的程序)
     主要思想就是:
     一、把程序運行所須要的class文件經過-XX:TraceClassLoading打印到文本文件
     二、用本身寫的程序把須要的class和rt路徑,精簡rt存放的路徑設置好
     三、而後將rt1裏面的目錄和文件打包成rt.zip,更名爲rt.jar,而後替換原來的rt.jar
     四、能夠達到精簡的做用,再將Java.exe和對應的dll copy到相應的目錄,
     五、寫一個批處理命令,用於自帶的Java去執行jar包。
  3. 曲折的求道之旅jvm

    1. 對這個main函數用不到的rt.jar精簡函數

      package com.tencent.tubemq.example;
      
      
      	import java.util.Vector;
      
      	/**
      	 * description:
      	 *
      	 * @author: dawn.he QQ:       905845006
      	 * @email: dawn.he@cloudwise.com
      	 * @email: 905845006@qq.com
      	 * @date: 2019/9/22    8:44 AM
      	 */
      	public class PermOOM {
      
      		public static void main(String[] args) {
      
      			Vector v=new Vector();
      			for(int i=0;i<10;i++)
      				v.add(new byte[1*1024*1024]);
      		        System.out.println("-------");
      		}
      	}

    1.(上邊main函數)須要的class 生成工具

    執行
     java -XX:+TraceClassLoading  com.tencent.tubemq.example.PermOOM>a.log
  4. rt存放路徑 (就是jre中的lib rt.jar)測試

  5. 精簡後的路徑lsspa

  6. 壓縮精簡後的文件3d

    jar cvf rt.jar *
    
     壓縮後的rt.jar替換掉jre中lib下的rt.jar 記得備份
     這個rt.jar 只能運行和上邊main函數依賴同樣的環境,不通用,測試成功記得替換回來,這個主要做用就是爲了線上環境或者給客戶部署的時候減少jre的包大小。
  7. classes下執行日誌

    java  com.tencent.tubemq.example.PermOOM

    1. 工具類

      package com.tencent.tubemq.example;
      
      	/**
      	 * description:jar cvf rt.jar *
      	 *
      	 * @author: dawn.he QQ:       905845006
      	 * @email: dawn.he@cloudwise.com
      	 * @email: 905845006@qq.com
      	 * @date: 2019/9/22    1:39 PM
      	 */
      
      	import java.io.BufferedReader;
      	import java.io.File;
      	import java.io.FileInputStream;
      	import java.io.FileOutputStream;
      	import java.io.IOException;
      	import java.io.InputStream;
      	import java.io.InputStreamReader;
      	import java.util.jar.JarEntry;
      	import java.util.jar.JarFile;
      
      	import org.apache.commons.io.IOUtils;
      
      	//本身寫的
      	public class CutJre {
      		private static String needClazz = "/Users/heliming/IdeaProjects/TubeMQ/tubemq-example/target/classes/a.log";//須要的class
      		private String rtPath = "/Library/Java/JavaVirtualMachines/jdk1.8.0_211.jdk/Contents/Home/jre/lib";//rt存放路徑
      		private String dstRtPath = "./cutJar/";//精簡後的路徑ls
      		private JarFile rtJar;
      
      		public static void main(String[] args) throws Exception {
      
      
      			CutJre cutJre = new CutJre();
      			cutJre.rtJar = new JarFile(cutJre.rtPath + "/rt.jar");
      			BufferedReader br = new BufferedReader(new InputStreamReader(
      					new FileInputStream(needClazz)));
      			String string = br.readLine();
      			while (string != null) {
      				string = br.readLine();
      
      				cutJre.copyClass(string);
      			}
      	//		 cutJre.execute();
      		}
      
      		private void execute() throws Exception {
      			BufferedReader br = new BufferedReader(new InputStreamReader(
      					new FileInputStream(needClazz)));
      			String string = br.readLine();
      			while (string != null) {
      				string = br.readLine();
      			}
      		}
      
      		private boolean copyClass(String traceStr) throws IOException {
      			//不是rt裏面的Jar包,是本身有的
      			if (traceStr == null || !traceStr.contains("/jre/lib/rt.jar")) {
      				return true;
      			}
      			if (traceStr.startsWith("[Loaded")) {
      				String className = traceStr.split(" ")[1];
      
      				copyFile(className);
      			}
      			return false;
      		}
      
      		private void copyFile(String className) throws IOException {
      			String classFile = className.replace(".", "/") + ".class";
      			String classDir = classFile.substring(0, classFile.lastIndexOf("/"));
      
      			File dir = new File(dstRtPath + classDir);
      			System.out.println(dir);
      			if (!dir.exists()) {
      				dir.mkdirs();
      			}
      			JarEntry jarEntry = rtJar.getJarEntry(classFile);
      			InputStream ins = rtJar.getInputStream(jarEntry);
      			File file = new File(dstRtPath + classFile);
      			System.out.println(file);
      			if (!file.exists()) {
      				file.createNewFile();
      			}
      			FileOutputStream fos = new FileOutputStream(file);
      			IOUtils.copy(ins, fos);
      			ins.close();
      			fos.close();
      
      		}
      	}

      工具類 pom文件中依賴個io的jar包

      <dependency>
       <groupId>commons-io</groupId>
       <artifactId>commons-io</artifactId>
       <version>2.5</version>
      </dependency>
  8. 忽略這塊我記錄用的

    認爲最可能的啓動JVM參數:
     -Xms25m -Xmx40m -Xmn7m -XX:+PrintGCDetails -XX:PermSize=16m
    
     首先 def new generation   total 6464K, used 115K [0x34e80000, 0x35580000, 0x35580000)
      eden space 5760K,   2% used [0x34e80000, 0x34e9cd38, 0x35420000)
       from space 704K,   0% used [0x354d0000, 0x354d0000, 0x35580000)
       to   space 704K,   0% used [0x35420000, 0x35420000, 0x354d0000)
     經過這一行能夠知道年輕代大小是7m.
    
     經過 tenured generation   total 18124K, used 8277K [0x35580000, 0x36733000, 0x37680000)
    
     (0x37680000-0x35580000)/1024/1024獲得的結果是33m
    
     經過以上能夠獲得最大堆是40m。但經過eden大小和 tenured generation   total 18124K計算出最小堆應該是25m
    
     經過compacting perm gen  total 16384K, 能夠計算出持久堆-XX:PermSize=16m
  9. 打印堆棧錯誤信息到log

    也是在classes下執行
    
     java -Xmx20m -Xms5m  -XX:+HeapDumpOnOutOfMemoryError com.tencent.tubemq.example.PermOOM>c.log

    1.打印gc日誌和導出dump文件

    -Xmx20m -Xms5m -XX:+HeapDumpOnOutOfMemoryError -XX:+TraceClassLoading -XX:HeapDumpPath=/Users/heliming -Xloggc:./gc.log

    在本路徑生成gc.log 在/Users/heliming目錄下生成

    find / -name 'jre' 搜索jre所在目錄
  10. jvisualvm

  11. 導入.hprof後綴文件

  12. 開始分析

    結合代碼

    totalMemory() :返回 Java 虛擬機中的內存總量。
     maxMemory() :返回 Java 虛擬機試圖使用的最大內存量。
     freeMemory() :返回 Java 虛擬機中的空閒內存量。

    真實狀況

  13. 堆內存的分配

  14. 這個是jdk6的湊合看吧和jdk8的名稱不太同樣不過也就是改個名字

    1. 是jdk8的話這裏3改成4
  15. 總結

相關文章
相關標籤/搜索