1、jvm經常使用配置參數java
其實這樣來看,from和to其實只是一個邏輯概念,對於物理上來講,新生代其實就是分配對象的內存+待複製對象的內存空間apache
-XX:+PrintGCDetails -XX:+PrintGCDetails這個是每次gc都會打印的,只是程序結束後纔打印詳細的堆信息 -Xmx不包含,持久代空間 堆空間是連續的
精簡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包。
曲折的求道之旅jvm
對這個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
rt存放路徑 (就是jre中的lib rt.jar)測試
精簡後的路徑lsspa
壓縮精簡後的文件3d
jar cvf rt.jar * 壓縮後的rt.jar替換掉jre中lib下的rt.jar 記得備份 這個rt.jar 只能運行和上邊main函數依賴同樣的環境,不通用,測試成功記得替換回來,這個主要做用就是爲了線上環境或者給客戶部署的時候減少jre的包大小。
classes下執行日誌
java com.tencent.tubemq.example.PermOOM
工具類
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>
忽略這塊我記錄用的
認爲最可能的啓動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
打印堆棧錯誤信息到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所在目錄
jvisualvm
導入.hprof後綴文件
開始分析
結合代碼
totalMemory() :返回 Java 虛擬機中的內存總量。 maxMemory() :返回 Java 虛擬機試圖使用的最大內存量。 freeMemory() :返回 Java 虛擬機中的空閒內存量。
真實狀況
堆內存的分配
這個是jdk6的湊合看吧和jdk8的名稱不太同樣不過也就是改個名字
總結