### JVMå ååé çç¥ å ³äºJVMçå åç»æåå ååé æ¹å¼ï¼ä¸æ¯æ¬æçéç¹ï¼è¿éåªåç®åå顾ã以䏿¯æä»¬ç¥éçä¸äºå¸¸è¯ï¼ 1ãæ ¹æ®Javaèææºè§èï¼Javaèææºæç®¡ççå åå æ¬æ¹æ³åºãèææºæ ãæ¬å°æ¹æ³æ ãå ãç¨åºè®¡æ°å¨çã 2ãæä»¬é常认为JVMä¸è¿è¡æ¶æ°æ®åå¨å æ¬å åæ ãè¿éææå°çæ å ¶å®æçæ¯èææºæ ï¼æè 说æ¯èææ ä¸çå±é¨åé表ã 3ãæ ä¸åæ¾ä¸äºåºæ¬ç±»åçåéæ°æ®ï¼int/short/long/byte/float/double/Boolean/charï¼å对象å¼ç¨ã 4ãå ä¸ä¸»è¦åæ¾å¯¹è±¡ï¼å³éè¿newå ³é®åå建ç对象ã 5ãæ°ç»å¼ç¨å鿝忾卿 å åä¸ï¼æ°ç»å ç´ æ¯åæ¾å¨å å åä¸ã å¨ãæ·±å ¥çè§£Javaèææºä¸ãå ³äºJavaå å åæè¿æ ·ä¸æ®µæè¿°ï¼ 使¯ï¼éçJITç¼è¯æçåå±ä¸éé¸åæææ¯éæ¸æçï¼æ ä¸åé ãæ éæ¿æ¢ä¼åææ¯å°ä¼å¯¼è´ä¸äºå¾®å¦çååï¼ææç对象é½åé å°å ä¸ä¹æ¸æ¸åå¾ä¸é£ä¹âç»å¯¹âäºã è¿éåªæ¯ç®åæäºä¸å¥ï¼å¹¶æ²¡ææ·±å ¥åæï¼å¾å¤äººçå°è¿éç±äºå¯¹JITãéé¸åæçææ¯ä¸äºè§£ï¼æä»¥ä¹æ æ³çæ£çè§£ä¸é¢è¿æ®µè¯çå«ä¹ã **PSï¼è¿éé»è®¤å¤§å®¶é½äºè§£ä»ä¹æ¯JITï¼ä¸äºè§£çæåå¯ä»¥å èªè¡Googleäºè§£ä¸ï¼æè å å ¥æçç¥è¯æçï¼é 读é£ç¯çåä¸äº«æç« ã** å ¶å®ï¼å¨ç¼è¯æé´ï¼JITä¼å¯¹ä»£ç åå¾å¤ä¼åãå ¶ä¸æä¸é¨åä¼åçç®çå°±æ¯åå°å åå åé ååï¼å ¶ä¸ä¸ç§éè¦çææ¯å«å**éé¸åæ**ã ### éé¸åæ éé¸åæ(Escape Analysis)æ¯ç®åJavaèææºä¸æ¯è¾å沿çä¼åææ¯ãè¿æ¯ä¸ç§å¯ä»¥ææåå°Java ç¨åºä¸åæ¥è´è½½åå åå åé ååçè·¨å½æ°å ¨å±æ°æ®æµåæç®æ³ãéè¿éé¸åæï¼Java Hotspotç¼è¯å¨è½å¤åæåºä¸ä¸ªæ°ç对象çå¼ç¨ç使ç¨èå´ä»èå³å®æ¯å¦è¦å°è¿ä¸ªå¯¹è±¡åé å°å ä¸ã éé¸åæçåºæ¬è¡ä¸ºå°±æ¯åæå¯¹è±¡å¨æä½ç¨åï¼å½ä¸ä¸ªå¯¹è±¡å¨æ¹æ³ä¸è¢«å®ä¹åï¼å®å¯è½è¢«å¤é¨æ¹æ³æå¼ç¨ï¼ä¾å¦ä½ä¸ºè°ç¨åæ°ä¼ éå°å ¶ä»å°æ¹ä¸ï¼ç§°ä¸ºæ¹æ³éé¸ã ä¾å¦ï¼ public static StringBuffer craeteStringBuffer(String s1, String s2) { StringBuffer sb = new StringBuffer(); sb.append(s1); sb.append(s2); return sb; } StringBuffer sbæ¯ä¸ä¸ªæ¹æ³å é¨åéï¼ä¸è¿°ä»£ç ä¸ç´æ¥å°sbè¿åï¼è¿æ ·è¿ä¸ªStringBufferæå¯è½è¢«å ¶ä»æ¹æ³ææ¹åï¼è¿æ ·å®çä½ç¨åå°±ä¸åªæ¯å¨æ¹æ³å é¨ï¼è½ç¶å®æ¯ä¸ä¸ªå±é¨åéï¼ç§°å ¶éé¸å°äºæ¹æ³å¤é¨ãçè³è¿æå¯è½è¢«å¤é¨çº¿ç¨è®¿é®å°ï¼è¬å¦èµå¼ç»ç±»åéæå¯ä»¥å¨å ¶ä»çº¿ç¨ä¸è®¿é®çå®ä¾åéï¼ç§°ä¸ºçº¿ç¨éé¸ã ä¸è¿°ä»£ç 妿æ³è¦StringBuffer sbä¸éåºæ¹æ³ï¼å¯ä»¥è¿æ ·åï¼ public static String createStringBuffer(String s1, String s2) { StringBuffer sb = new StringBuffer(); sb.append(s1); sb.append(s2); return sb.toString(); } ä¸ç´æ¥è¿å StringBufferï¼é£ä¹StringBufferå°ä¸ä¼éé¸åºæ¹æ³ã 使ç¨éé¸åæï¼ç¼è¯å¨å¯ä»¥å¯¹ä»£ç åå¦ä¸ä¼åï¼ ä¸ã忥çç¥ã妿ä¸ä¸ªå¯¹è±¡è¢«åç°åªè½ä»ä¸ä¸ªçº¿ç¨è¢«è®¿é®å°ï¼é£ä¹å¯¹äºè¿ä¸ªå¯¹è±¡çæä½å¯ä»¥ä¸èè忥ã äºãå°å åé 转å为æ åé ã妿ä¸ä¸ªå¯¹è±¡å¨åç¨åºä¸è¢«åé ï¼è¦ä½¿æå该对象çæéæ°¸è¿ä¸ä¼éé¸ï¼å¯¹è±¡å¯è½æ¯æ åé çåéï¼è䏿¯å åé ã ä¸ãåç¦»å¯¹è±¡ææ éæ¿æ¢ãæç对象å¯è½ä¸éè¦ä½ä¸ºä¸ä¸ªè¿ç»çå åç»æåå¨ä¹å¯ä»¥è¢«è®¿é®å°ï¼é£ä¹å¯¹è±¡çé¨åï¼æå ¨é¨ï¼å¯ä»¥ä¸åå¨å¨å åï¼èæ¯åå¨å¨CPUå¯åå¨ä¸ã ä¸é¢çå ³äºåæ¥çç¥çå å®¹ï¼æå¨ã[æ·±å ¥çè§£å¤çº¿ç¨ï¼äºï¼ââ Javaèææºçéä¼åææ¯][1]ã䏿ä»ç»è¿ï¼å³éä¼åä¸ç鿶餿æ¯ï¼ä¾èµç乿¯éé¸åæææ¯ã æ¬æï¼ä¸»è¦æ¥ä»ç»éé¸åæç第äºä¸ªç¨éï¼å°å åé 转å为æ åé ã > å ¶å®ï¼ä»¥ä¸ä¸ç§ä¼åä¸ï¼æ ä¸å ååé å ¶å®æ¯ä¾é æ éæ¿æ¢æ¥å®ç°çãç±äºä¸æ¯æ¬æéç¹ï¼è¿éå°±ä¸å±å¼ä»ç»äºã妿大家æå ´è¶£ï¼æåé¢ä¸é¨åºä¸ç¯æç« ï¼å ¨é¢ä»ç»ä¸éé¸åæã å¨Java代ç è¿è¡æ¶ï¼éè¿JVM忰坿宿¯å¦å¼å¯éé¸åæï¼ `-XX:+DoEscapeAnalysis` ï¼ è¡¨ç¤ºå¼å¯éé¸åæ `-XX:-DoEscapeAnalysis` ï¼ è¡¨ç¤ºå ³ééé¸åæ ä»jdk 1.7å¼å§å·²ç»é»è®¤å¼å§éé¸åæï¼å¦éå ³éï¼éè¦æå®`-XX:-DoEscapeAnalysis` ### å¯¹è±¡çæ ä¸å ååé æä»¬ç¥éï¼å¨ä¸è¬æ åµä¸ï¼å¯¹è±¡åæ°ç»å ç´ çå ååé æ¯å¨å å åä¸è¿è¡çã使¯éçJITç¼è¯å¨çæ¥æ¸æçï¼å¾å¤ä¼å使è¿ç§åé çç¥å¹¶ä¸ç»å¯¹ãJITç¼è¯å¨å°±å¯ä»¥å¨ç¼è¯æé´æ ¹æ®éé¸åæçç»æï¼æ¥å³å®æ¯å¦å¯ä»¥å°å¯¹è±¡çå ååé ä»å 转å为æ ã æä»¬æ¥ç以ä¸ä»£ç ï¼ public static void main(String[] args) { long a1 = System.currentTimeMillis(); for (int i = 0; i < 1000000; i++) { alloc(); } // æ¥çæ§è¡æ¶é´ long a2 = System.currentTimeMillis(); System.out.println("cost " + (a2 - a1) + " ms"); // ä¸ºäºæ¹ä¾¿æ¥çå å åä¸å¯¹è±¡ä¸ªæ°ï¼çº¿ç¨sleep try { Thread.sleep(100000); } catch (InterruptedException e1) { e1.printStackTrace(); } } private static void alloc() { User user = new User(); } static class User { } å ¶å®ä»£ç å 容å¾ç®åï¼å°±æ¯ä½¿ç¨for循ç¯ï¼å¨ä»£ç ä¸å建100ä¸ä¸ªUser对象ã **æä»¬å¨allocæ¹æ³ä¸å®ä¹äºUser对象ï¼ä½æ¯å¹¶æ²¡æå¨æ¹æ³å¤é¨å¼ç¨ä»ãä¹å°±æ¯è¯´ï¼è¿ä¸ªå¯¹è±¡å¹¶ä¸ä¼éé¸å°allocå¤é¨ãç»è¿JITçéé¸åæä¹åï¼å°±å¯ä»¥å¯¹å ¶å ååé è¿è¡ä¼åã** æä»¬æå®ä»¥ä¸JVMåæ°å¹¶è¿è¡ï¼ -Xmx4G -Xms4G -XX:-DoEscapeAnalysis -XX:+PrintGCDetails -XX:+HeapDumpOnOutOfMemoryError å¨ç¨åºæå°åº `cost XX ms` åï¼ä»£ç è¿è¡ç»æä¹åï¼æä»¬ä½¿ç¨`[jmap][1]`å½ä»¤ï¼æ¥æ¥çä¸å½åå å å䏿å¤å°ä¸ªUserå¯¹è±¡ï¼ â ~ jps 2809 StackAllocTest 2810 Jps â ~ jmap -histo 2809 num #instances #bytes class name ---------------------------------------------- 1: 524 87282184 [I 2: 1000000 16000000 StackAllocTest$User 3: 6806 2093136 [B 4: 8006 1320872 [C 5: 4188 100512 java.lang.String 6: 581 66304 java.lang.Class ä»ä¸é¢çjmapæ§è¡ç»æä¸æä»¬å¯ä»¥çå°ï¼å ä¸å ±å建äº100ä¸ä¸ª`StackAllocTest$User`å®ä¾ã å¨å ³ééé¿åæçæ åµä¸ï¼-XX:-DoEscapeAnalysisï¼ï¼è½ç¶å¨allocæ¹æ³ä¸å建çUser对象并没æéé¸å°æ¹æ³å¤é¨ï¼ä½æ¯è¿æ¯è¢«åé å¨å å åä¸ãä¹å°±è¯´ï¼å¦ææ²¡æJITç¼è¯å¨ä¼åï¼æ²¡æéé¸åæææ¯ï¼æ£å¸¸æ åµä¸å°±åºè¯¥æ¯è¿æ ·çã峿æå¯¹è±¡é½åé å°å å åä¸ã æ¥ä¸æ¥ï¼æä»¬å¼å¯éé¸åæï¼åæ¥æ§è¡ä¸ä»¥ä¸ä»£ç ã -Xmx4G -Xms4G -XX:+DoEscapeAnalysis -XX:+PrintGCDetails -XX:+HeapDumpOnOutOfMemoryError å¨ç¨åºæå°åº `cost XX ms` åï¼ä»£ç è¿è¡ç»æä¹åï¼æä»¬ä½¿ç¨`jmap`å½ä»¤ï¼æ¥æ¥çä¸å½åå å å䏿å¤å°ä¸ªUserå¯¹è±¡ï¼ â ~ jps 709 2858 Launcher 2859 StackAllocTest 2860 Jps â ~ jmap -histo 2859 num #instances #bytes class name ---------------------------------------------- 1: 524 101944280 [I 2: 6806 2093136 [B 3: 83619 1337904 StackAllocTest$User 4: 8006 1320872 [C 5: 4188 100512 java.lang.String 6: 581 66304 java.lang.Class ä»ä»¥ä¸æå°ç»æä¸å¯ä»¥åç°ï¼å¼å¯äºéé¸åæä¹åï¼-XX:+DoEscapeAnalysisï¼ï¼å¨å å åä¸åªæ8ä¸å¤ä¸ª`StackAllocTest$User`对象ãä¹å°±æ¯è¯´å¨ç»è¿JITä¼åä¹åï¼å å åä¸åé ç对象æ°éï¼ä»100ä¸éå°äº8ä¸ã > é¤äºä»¥ä¸éè¿jmapéªè¯å¯¹è±¡ä¸ªæ°çæ¹æ³ä»¥å¤ï¼è¯»è è¿å¯ä»¥å°è¯å°å å åè°å°ï¼ç¶åæ§è¡ä»¥ä¸ä»£ç ï¼æ ¹æ®GCçæ¬¡æ°æ¥åæï¼ä¹è½åç°ï¼å¼å¯äºéé¸åæä¹åï¼å¨è¿è¡æé´ï¼GC次æ°ä¼ææ¾åå°ãæ£æ¯å 为å¾å¤å ä¸åé 被ä¼åæäºæ ä¸åé ï¼æä»¥GCæ¬¡æ°æäºææ¾çåå°ã ### æ»ç» æä»¥ï¼å¦æä»¥ååæäººé®ä½ ï¼æ¯ä¸æ¯ææçå¯¹è±¡åæ°ç»é½ä¼å¨å å ååé 空é´ï¼ é£ä¹ä½ å¯ä»¥åè¯ä»ï¼ä¸ä¸å®ï¼éçJITç¼è¯å¨çåå±ï¼å¨ç¼è¯æé´ï¼å¦æJITç»è¿éé¸åæï¼åç°æäºå¯¹è±¡æ²¡æéé¸åºæ¹æ³ï¼é£ä¹æå¯è½å å ååé ä¼è¢«ä¼åææ å ååé ã使¯è¿ä¹å¹¶ä¸æ¯ç»å¯¹çãå°±åæä»¬åé¢çå°ç䏿 ·ï¼å¨å¼å¯éé¸åæä¹åï¼ä¹å¹¶ä¸æ¯ææUserå¯¹è±¡é½æ²¡æå¨å ä¸åé ã [1]: http://www.hollischuang.com/archives/2344