åœ¨åÆˆå‘程åºä¸åQŒç¨‹åºå‘˜ä¼?x¨¬)特别关注ä¸åŒè¿›½E‹æˆ–¾U¿ç¨‹ä¹‹é—´çš„æ•°æ®åŒæ¥ï¼Œç‰¹åˆ«æ˜¯å¤šä¸ªçº¿½E‹åŒæ—¶ä¿®æ”¹åŒä¸€å˜é‡æ—Óž¼Œå¿…须采å–å¯é çš„åŒæ¥æˆ–其它措施ä¿éšœæ•°æ®è¢«æ£¼‹®åœ°ä¿®æ”¹åQŒè¿™é‡Œçš„一æ¡é‡è¦åŽŸåˆ™æ˜¯åQšä¸è¦å‡è®¾æŒ‡ä»¤æ‰§è¡Œçš„™åºåºåQŒä½ æ— æ³•é¢„çŸ¥ä¸åŒ¾U¿ç¨‹ä¹‹é—´çš„æŒ‡ä»¤ä¼š(x¨¬)以何¿Ué¡ºåºæ‰§è¡Œã€?/p>
但是在啾U¿ç¨‹½E‹åºä¸ï¼Œé€šå¸¸æˆ‘们å®ÒŽ(gu¨©)˜“å‡è®¾æŒ‡ä×o(h¨´)æ˜¯é¡ºåºæ‰§è¡Œçš„åQŒå¦åˆ™å¯ä»¥æƒ³è±¡ç¨‹åºä¼š(x¨¬)å‘ç”Ÿä»€ä¹ˆå¯æ€•çš„å˜åŒ–ã€‚ç†æƒ³çš„æ¨¡åž‹æ˜¯ï¼š(x¨¬)å„ç§æŒ‡ä×o(h¨´)æ‰§è¡Œçš„é¡ºåºæ˜¯å”¯ä¸€ä¸”有åºçš„åQŒè¿™ä¸ªé¡ºåºå°±æ˜¯å®ƒä»¬è¢«¾~–写在代ç ä¸çš„顺åºï¼Œä¸Žå¤„ç†å™¨æˆ–å…¶å®ƒå› ç´ æ— å…»I¼Œ˜q™ç§æ¨¡åž‹è¢«ç§°ä½œé¡ºåºä¸€è‡´æ€§æ¨¡åž‹ï¼Œä¹Ÿæ˜¯åŸÞZºŽå†?#183;è¯ÞZ¾æ›ég½“¾pÈš„模型。当ç„?d¨°ng)ž¼Œ˜q™ç§å‡è®¾æœ¬èín是åˆç†çš„åQŒåœ¨å®žè·µä¸ä¹Ÿé²œæœ‰å¼‚常å‘生åQŒä½†äº‹å®žä¸Šï¼Œæ²¡æœ‰å“ªä¸ªçŽîC»£å¤šå¤„ç†å™¨æž¶æž„ä¼?x¨¬)采用这¿Uæ¨¡åž‹ï¼Œå› äØ“(f¨´)它是在是太低效了(ji¨£n)。而在¾~–译优化和CPU‹¹æ°´¾U¿ä¸åQŒå‡ 乎都涉åŠ(qi¨¢ng)åˆ°æŒ‡ä»¤é‡æŽ’åºã€?/p>
¾~–è¯‘æœŸé‡æŽ’åº
¾~–è¯‘æœŸé‡æŽ’åºçš„典型就是通过调整指ä×o(h¨´)™åºåºåQŒåœ¨ä¸æ”¹å˜ç¨‹åºè¯ä¹‰çš„å‰æä¸‹ï¼Œž®½å¯èƒ½å‡ž®‘寄å˜å™¨çš„读å–ã€å˜å‚¨æ¬¡æ•ŽÍ¼Œå……分å¤ç”¨å¯„å˜å™¨çš„å˜å‚¨å€¹{€?/p>
å‡è®¾½W¬ä¸€æ¡æŒ‡ä»¤è®¡½Ž—ä¸€ä¸ªå€ÆDµ‹¾l™å˜é‡Aòq¶å˜æ”‘Öœ¨å¯„å˜å™¨ä¸åQŒç¬¬äºŒæ¡æŒ‡ä×o(h¨´)与Aæ— å…³ä½†éœ€è¦å 用寄å˜å™¨åQˆå‡è®‘Ö®ƒ?y¨u)®†å 用A所在的那个寄å˜å™¨ï¼‰(j¨ª)åQŒç¬¬ä¸‰æ¡æŒ‡ä×o(h¨´)使用Açš„å€ég¸”ä¸Žç¬¬äºŒæ¡æŒ‡ä×o(h¨´)æ— å…³ã€‚é‚£ä¹ˆå¦‚æžœæŒ‰ç…§é¡ºåºä¸€è‡´æ€§æ¨¡åž‹ï¼ŒAåœ¨ç¬¬ä¸€æ¡æŒ‡ä»¤æ‰§è¡Œè¿‡åŽè¢«æ”‘Ö…¥å¯„å˜å™¨ï¼Œåœ¨ç¬¬äºŒæ¡æŒ‡ä×o(h¨´)执行时Aä¸å†å˜åœ¨åQŒç¬¬ä¸‰æ¡æŒ‡ä×o(h¨´)执行时A釿–°è¢«è¯»å…¥å¯„å˜å™¨åQŒè€Œè¿™ä¸ªè¿‡½E‹ä¸åQŒA的值没有å‘生å˜åŒ–。通常¾~–译器都ä¼?x¨¬)交æ¢ç¬¬äºŒå’Œ½W¬ä¸‰æ¡æŒ‡ä»¤çš„ä½ç½®åQŒè¿™æ ïL(f¨¥ng)¬¬ä¸€æ¡æŒ‡ä»¤ç»“æŸæ—¶Aå˜åœ¨äºŽå¯„å˜å™¨ä¸ï¼ŒæŽ¥ä¸‹æ¥å¯ä»¥ç›´æŽ¥ä»Žå¯„å˜å™¨ä¸è¯Õd–Açš„å€û|¼Œé™ä½Žäº?ji¨£n)é‡å¤è¯»å–的开销ã€?br />
釿ޒåºå¯¹äºŽæµæ°´çº¿çš„æ„ä¹?/strong>
çŽîC»£CPUå‡ ä¹Žéƒ½é‡‡ç”¨æµæ°´çº¿æœºåˆ¶åŠ å¿«æŒ‡ä×o(h¨´)的处ç†é€Ÿåº¦åQŒä¸€èˆ¬æ¥è¯ß_(d¨¢)¼Œä¸€æ¡æŒ‡ä»¤éœ€è¦è‹¥òq²ä¸ªCPUæ—‰™’Ÿå‘¨æœŸå¤„ç†åQŒè€Œé€šè¿‡‹¹æ°´¾U¿åƈ行执行,å¯ä»¥åœ¨åŒ½{‰çš„æ—‰™’Ÿå‘¨æœŸå†…执行若òq²æ¡æŒ‡ä×o(h¨´)åQŒå…·ä½“åšæ³•简å•地说就是把指ä×o(h¨´)åˆ†äØ“(f¨´)ä¸åŒçš„æ‰§è¡Œå‘¨æœŸï¼Œä¾‹å¦‚è¯Õd–ã€å¯»å€ã€è§£æžã€æ‰§è¡Œç‰æ¥éª¤åQŒåƈ攑֜¨ä¸åŒçš„元件ä¸å¤„ç†åQŒåŒæ—¶åœ¨æ‰§è¡Œå•å…ƒEUä¸ï¼ŒåŠŸèƒ½å•元被分ä¸ÞZ¸åŒçš„å…ƒäšgåQŒä¾‹å¦‚åŠ æ³•å…ƒä»¶ã€ä¹˜æ³•元件ã€åŠ è½½å…ƒä»¶ã€å˜å‚¨å…ƒä»¶ç‰åQŒå¯ä»¥è¿›ä¸€æ¥å®žçŽîC¸åŒçš„计算òq¶è¡Œæ‰§è¡Œã€?/p>
‹¹æ°´¾U¿æž¶æž„决定了(ji¨£n)指ä×o(h¨´)åº”è¯¥è¢«åÆˆè¡Œæ‰§è¡Œï¼Œè€Œä¸æ˜¯åœ¨™åºåºåŒ–æ¨¡åž‹ä¸æ‰€è®¤äØ“(f¨´)çš„é‚£æ —÷€‚é‡æŽ’åºæœ‰åˆ©äºŽå……分ä‹Éç”¨æµæ°´çº¿åQŒè¿›è€Œè¾¾åˆ°è¶…æ ‡é‡çš„æ•ˆæžœã€?br />
¼‹®ä¿?r¨´n)åºåºæ€?/strong>
ž®½ç®¡æŒ‡ä×o(h¨´)在执行时òq¶ä¸ä¸€å®šæŒ‰ç…§æˆ‘们所¾~–å†™çš„é¡ºåºæ‰§è¡Œï¼Œä½†æ¯‹åº¸ç½®ç–‘的是,在啾U¿ç¨‹çŽ¯å¢ƒä¸‹ï¼ŒæŒ‡ä×o(h¨´)执行的最¾lˆæ•ˆæžœåº”当与其在™åºåºæ‰§è¡Œä¸‹çš„æ•ˆæžœä¸€è‡ß_(d¨¢)¼Œå¦åˆ™˜q™ç§ä¼˜åŒ–便会(x¨¬)失去æ„义ã€?/p>
é€šå¸¸æ— è®ºæ˜¯åœ¨¾~–译期还是è¿è¡ŒæœŸ˜q›è¡Œçš„æŒ‡ä»¤é‡æŽ’åºåQŒéƒ½ä¼?x¨¬)满‘³ä¸Šé¢çš„原则ã€?/p>
Javaå˜å‚¨æ¨¡åž‹ä¸çš„釿ޒåº?/strong>
在Javaå˜å‚¨æ¨¡åž‹åQˆJava Memory Model, JMMåQ‰ä¸åQŒé‡æŽ’åºæ˜¯å分é‡è¦çš„一节,特别是在òq¶å‘¾~–程ä¸ã€‚JMM通过happens-before法则ä¿è¯™åºåºæ‰§è¡Œè¯ä¹‰åQŒå¦‚果想è¦è®©æ‰§è¡Œæ“作B的线½E‹è§‚察到执行æ“作A的线½E‹çš„¾l“æžœåQŒé‚£ä¹ˆAå’ŒBž®±å¿…™åÀL»¡‘³happens-before原则åQŒå¦åˆ™ï¼ŒJVMå¯ä»¥å¯¹å®ƒä»¬è¿›è¡Œä“Qæ„æŽ’åºä»¥æé«˜½E‹åºæ€§èƒ½ã€?/p>
volatile关键å—å¯ä»¥ä¿è¯å˜é‡çš„å¯è§æ€§ï¼Œå› 䨓(f¨´)对volatileçš„æ“作都在Main Memoryä¸ï¼Œè€ŒMain Memory是被所有线½E‹æ‰€å…׃ín的,˜q™é‡Œçš„代价就是牺牲了(ji¨£n)性能åQŒæ— 法利用寄å˜å™¨æˆ–CacheåQŒå› ä¸ºå®ƒä»¬éƒ½ä¸æ˜¯å…¨å±€çš„ï¼Œæ— æ³•ä¿è¯å¯è§æ€§ï¼Œå¯èƒ½äº§ç”Ÿè„读ã€?/p>
volatile˜q˜æœ‰ä¸€ä¸ªä½œç”¨å°±æ˜¯å±€éƒ¨é˜»æ¢é‡æŽ’åºçš„å‘生,对volatileå˜é‡çš„æ“ä½œæŒ‡ä»¤éƒ½ä¸ä¼š(x¨¬)è¢«é‡æŽ’åºåQŒå› ä¸ºå¦‚æžœé‡æŽ’åºåQŒåˆå¯èƒ½äº§ç”Ÿå¯è§æ€§é—®é¢˜ã€?/p>
在ä¿è¯å¯è§æ€§æ–¹é¢ï¼Œé”(包括昑ּé”ã€å¯¹è±¡é”åQ‰ä»¥å?qi¨¢ng)对原åå˜é‡çš„读写都å¯ä»¥¼‹®ä¿å˜é‡çš„å¯è§æ€§ã€‚但是实现方å¼ç•¥æœ‰ä¸åŒï¼Œä¾‹å¦‚åŒæ¥é”ä¿è¯å¾—åˆ°é”æ—¶ä»Žå†…å˜é‡Œé‡æ–°è¯»å…¥æ•°æ®åˆ·æ–°ç¼“å˜ï¼Œé‡Šæ”¾é”æ—¶ž®†æ•°æ®å†™å›žå†…å˜ä»¥ä¿æ•°æ®å¯è§ï¼Œè€Œvolatileå˜é‡òq²è„†éƒ½æ˜¯è¯Õd†™å†…å˜ã€?/p>
ç”׃ºŽ ConcurrentHashMap 是å¾ç«‹åœ¨ Java å†…å˜æ¨¡åž‹åŸºç¡€ä¸Šçš„åQŒäØ“(f¨´)äº?ji¨£n)更好的ç†è§?ConcurrentHashMapåQŒè®©æˆ‘们首先æ¥äº†(ji¨£n)解一ä¸?Java çš„å†…å˜æ¨¡åž‹ã€?/p>
Java è¯è¨€çš„å†…å˜æ¨¡åž‹ç”±ä¸€äº›è§„则组æˆï¼Œ˜q™äº›è§„则¼‹®å®š¾U¿ç¨‹å¯¹å†…å˜çš„讉K—®å¦‚何排åºä»¥åŠ(qi¨¢ng)何时å¯ä»¥¼‹®ä¿å®ƒä»¬å¯¹çº¿½E‹æ˜¯å¯è§çš„ã€‚ä¸‹é¢æˆ‘ä»¬å°†åˆ†åˆ«ä»‹ç» Java å†…å˜æ¨¡åž‹çš„釿ޒåºåQŒå†…å˜å¯è§æ€§å’Œ happens-before 关系ã€?/p>
å†…å˜æ¨¡åž‹æè¿°äº?ji¨£n)程åºçš„å¯èƒ½è¡ŒäØ?f¨´)。具体的¾~–译器实现å¯ä»¥äñ”生ä“Qæ„它喜欢的代ç ?-- åªè¦æ‰€æœ‰æ‰§è¡Œè¿™äº›ä»£ç äñ”生的¾l“æžœåQŒèƒ½å¤Ÿå’Œå†…å˜æ¨¡åž‹é¢„æµ‹çš„ç»“æžœä¿æŒä¸€è‡´ã€‚这为编译器实现者æä¾›äº†(ji¨£n)很大的自由,包括æ“ä½œçš„é‡æŽ’åºã€?/p>
¾~–è¯‘å™¨ç”ŸæˆæŒ‡ä»¤çš„‹Æ¡åºåQŒå¯ä»¥ä¸åŒäºŽæºä»£ç 所暗示çš?#8220;昄¡„¶”ç‰ˆæœ¬ã€‚é‡æŽ’åºåŽçš„æŒ‡ä×o(h¨´)åQŒå¯¹äºŽä¼˜åŒ–执行以å?qi¨¢ng)æˆç†Ÿçš„全局寄å˜å™¨åˆ†é…算法的使用åQŒéƒ½æ˜¯å¤§æœ‰è„¾ç›Šçš„åQŒå®ƒä½¿å¾—½E‹åºåœ¨è®¡½Ž—性能上有äº?ji¨£n)很大的æå‡ã€?/p>
釿ޒåºç±»åž‹åŒ…括:(x¨¬)
ç”׃ºŽçŽîC»£å¯å…±äº«å†…å˜çš„多处ç†å™¨æž¶æž„å¯èƒ½å¯ÆD‡´ä¸€ä¸ªçº¿½E‹æ— 法马上(甚至永远åQ‰çœ‹åˆ°å¦ä¸€ä¸ªçº¿½E‹æ“作äñ”生的¾l“果。所ä»?Java å†…å˜æ¨¡åž‹è§„定äº?JVM 的一¿U最ž®ä¿è¯ï¼š(x¨¬)什么时候写入一个å˜é‡å¯¹å…¶ä»–¾U¿ç¨‹å¯è§ã€?/p>
在现代å¯å…׃ín内å˜çš„多处ç†å™¨ä½“¾pÈ»“æž„ä¸æ¯ä¸ªå¤„ç†å™¨éƒ½æœ‰è‡ªå·Þqš„¾~“å˜åQŒåƈ周期性的与主内å˜å调一致。å‡è®„¡º¿½E?A 写入一个å˜é‡å€?VåQŒéšåŽå¦ä¸€ä¸ªçº¿½E?B è¯Õd–å˜é‡ V çš„å€û|¼Œåœ¨ä¸‹åˆ—情况下åQŒçº¿½E?B è¯Õd–的值å¯èƒ½ä¸æ˜¯çº¿½E?A 写入的最新å€û|¼š(x¨¬)
happens-before 关系ä¿è¯åQšå¦‚果线½E?A 与线½E?B 满èƒö happens-before 关系åQŒåˆ™¾U¿ç¨‹ A 执行动作的结果对于线½E?B 是å¯è§çš„。如果两个æ“作未æŒ?happens-before 排åºåQŒJVM ž®†å¯ä»¥å¯¹ä»–们ä»ÀL„釿ޒåºã€?/p>
下é¢ä»‹ç»å‡ 个与ç†è§?ConcurrentHashMap 有关çš?happens-before 关系法则åQ?/p>
òq´è½»ä»£åˆåˆ†æˆ3个部分,一个eden区和两个相åŒçš„survior区。刚开始创建的对象都是攄¡½®åœ¨eden区的。分æˆè¿™æ ?ä¸ªéƒ¨åˆ†ï¼Œä¸»è¦æ˜¯äØ“(f¨´)äº?ji¨£n)生命周期çŸçš„对象尽é‡ç•™åœ¨å¹´è½Õd¸¦ã€‚当eden区申请ä¸åˆ°ç©ºé—´çš„æ—¶å€™ï¼Œ˜q›è¡ŒminorGCåQŒæŠŠå˜æ´»çš„对象拷è´åˆ°survior。年è€ä»£ä¸»è¦å˜æ”¾ç”Ÿå‘½å‘¨æœŸæ¯”较长的对象åQŒæ¯”如缓å˜å¯¹è±¡ã€‚具体jvm内å˜å›žæ”¶˜q‡ç¨‹æè¿°å¦‚下åQˆå¯ä»¥ç»“åˆä¸Šå›¾ï¼‰(j¨ª)åQ?/p>
1ã€å¯¹è±¡åœ¨Eden区完æˆå†…å˜åˆ†é…?br />2ã€å½“Eden区满äº?ji¨£n),å†åˆ›å»ºå¯¹è±¡ï¼Œä¼š(x¨¬)å› ä¸ºç”³è¯·ä¸åˆ°ç©ºé—ß_(d¨¢)¼Œè§¦å‘minorGCåQŒè¿›è¡Œyoung(eden+1survivor)区的垃圾回收
3ã€minorGCæ—Óž¼ŒEdenä¸èƒ½è¢«å›žæ”¶çš„对象被放入到½Iºçš„survivoråQˆEden肯定ä¼?x¨¬)被清空åQ‰ï¼Œå¦ä¸€ä¸ªsurvivor里ä¸èƒ½è¢«GC回收的对象也ä¼?x¨¬)被攑օ¥˜q™ä¸ªsurvivoråQŒå§‹¾lˆä¿è¯ä¸€ä¸ªsurvivor是空çš?br />4ã€å½“åšç¬¬3æ¥çš„æ—¶å€™ï¼Œå¦‚æžœå‘现survivor满了(ji¨£n)åQŒåˆ™˜q™äº›å¯¹è±¡è¢«copy到old区,或者survivoròq¶æ²¡æœ‰æ»¡åQŒä½†æ˜¯æœ‰äº›å¯¹è±¡å·²¾lèƒö够OldåQŒä¹Ÿè¢«æ”¾å…¥OldåŒ?nbsp;XX:MaxTenuringThreshold
5ã€å½“OldåŒø™¢«æ”¾æ»¡çš„之åŽï¼Œ˜q›è¡ŒfullGC
在知é“垃圑֛žæ”¶æœºåˆ¶ä»¥åŽï¼Œå¤§å®¶å¯ä»¥åœ¨å¯¹jvmä¸å †çš„å„ä¸ªå‚æ•°è¿›è¡Œä¼˜åŒ–设¾|®ï¼Œæ¥æé«˜æ€§èƒ½ã€?/p>
The reason for the HotSpot JVM's two survivor spaces is to reduce the need to deal with fragmentation. New objects are allocated in eden space. All well and good. When that's full, you need a GC, so kill stale objects and move live ones to a survivor space, where they can mature for a while before being promoted to the old generation. Still good so far. The next time we run out of eden space, though, we have a conundrum. The next GC comes along and clears out some space in both eden and our survivor space, but the spaces aren't contiguous. So is it better to
Sun's answer to the question is obvious.
对于如何辑ֈ°“æ— ç¢Žç‰?#8221;的目的,ç†è§£ä¸Šå¯èƒ½æœ‰äº›å›°éš¾ï¼Œä¸‹é¢æˆ‘把新生代回收机制详¾l†è§£é‡Šä¸€ä¸‹ï¼š(x¨¬)
注æ„åQ?span style="color: #ff0000;">两个survivor是交替ä‹É用的åQŒåœ¨ä»ÀL„一个时刻,必定有一个survivor为空åQŒä¸€ä¸ªsurvivorä¸å˜æ”„¡€å¯¹è±¡åQˆè¿ž¾lå˜æ”¾ï¼Œæ— 碎片)(j¨ª)。回收过½E‹å¦‚下:(x¨¬)
S1ã€GCåQŒå°†edenä¸çš„live对象攑օ¥å½“å‰ä¸äØ“(f¨´)½Iºçš„survivorä¸ï¼Œž®†edenä¸çš„éžlive对象回收。如果survivor满了(ji¨£n)åQŒä¸‹‹Æ¡å›žæ”¶æ‰§è¡ŒS2åQ›å¦‚æžœsurvivor未满åQŒä¸‹‹Æ¡å›žæ”¶ä»ç„¶ä»¥S1的方å¼å›žæ”Óž¼›
S2ã€GCåQŒå°†edenå’Œå˜æ”„¡€å¯¹è±¡çš„survivorä¸çš„live对象攑օ¥å½“å‰ä¸ºç©ºçš„survivorä¸ï¼Œž®†éžlive对象回收ã€?/p>
å¯ä»¥çœ‹åˆ°åQŒä¸Š˜q°çš„æ–°ç”Ÿä»£å›žæ”¶æœºåˆ¶ä¿è¯äº†(ji¨£n)一个survivor为空åQŒå¦ä¸€ä¸ªéž½Iºsurvivor䏿— ¼„Žç‰‡ã€?/p>
在执行一定次数的minor GCåŽï¼Œä¼?x¨¬)通过Full GCž®†æ–°ç”Ÿä»£çš„survivorä¸çš„对象¿UÕd…¥è€å¹´ä»£ã€?/p>
对于ç†è§£GC的整个机åˆÓž¼ŒæŽ¨è一½‹‡éžå¸¸å¥½çš„æ–‡ç«?/span>åQ?a target="_blank" style="color: #ca0000; text-decoration: none;">http://www.cubrid.org/blog/dev-platform/understanding-java-garbage-collection/
一ã€JVMå†…å˜æ¨¡åž‹å?qi¨¢ng)垃圾收集算æ?/p>
1.æ ÒŽ(gu¨©)®Javaè™šæ‹Ÿæœø™§„范,JVMž®†å†…å˜åˆ’åˆ†äØ“(f¨´)åQ?/p>
å…¶ä¸Newå’ŒTenuredå±žäºŽå †å†…å˜ï¼Œå †å†…å˜ä¼š(x¨¬)从JVMå¯åЍ傿•°åQ?Xmx:3GåQ‰æŒ‡å®šçš„内å˜ä¸åˆ†é…,Permä¸å±žäºŽå †å†…å˜åQŒæœ‰è™šæ‹Ÿæœºç›´æŽ¥åˆ†é…,但å¯ä»¥é€šè¿‡-XX:PermSize -XX:MaxPermSize ½{‰å‚数调整其大å°ã€?/p>
Newåˆåˆ†ä¸ºå‡ 个部分:(x¨¬)
2.垃圾回收½Ž—法
垃圾回收½Ž—法å¯ä»¥åˆ†äØ“(f¨´)三类åQŒéƒ½åŸÞZºŽæ ‡è®°-清除åQˆå¤åˆÓž¼‰(j¨ª)½Ž—法åQ?/p>
JVMä¼?x¨¬)æ ¹æ®æœºå™¨çš„¼‹¬äšgé…ç½®å¯ÒŽ(gu¨©)¯ä¸ªå†…å˜ä»£é€‰æ‹©é€‚åˆçš„回收算法,比如åQŒå¦‚果机器多äº?ä¸ªæ ¸åQŒä¼š(x¨¬)对年è½ÖM»£é€‰æ‹©òq¶è¡Œ½Ž—法åQŒå…³äºŽé€‰æ‹©¾l†èŠ‚è¯·å‚考JVM调优文档ã€?/p>
½E微解释下的是,òq¶è¡Œ½Ž—法是用多线½E‹è¿›è¡Œåžƒåœ‘Ö›žæ”Óž¼Œå›žæ”¶æœŸé—´ä¼?x¨¬)æš‚åœç¨‹åºçš„æ‰§è¡ŒåQŒè€Œåƈå‘算法,也是多线½E‹å›žæ”Óž¼Œä½†æœŸé—´ä¸åœæ¢åº”用执行。所以,òq¶å‘½Ž—法适用于交互性高的一些程åºã€‚绘q‡è§‚察,òq¶å‘½Ž—法ä¼?x¨¬)凞®‘å¹´è½ÖM»£çš„大ž®ï¼Œå…¶å®žž®±æ˜¯ä½¿ç”¨äº?ji¨£n)一个大的年è€ä»£åQŒè¿™å过æ¥è·Ÿòq¶è¡Œ½Ž—法相比åžåé‡ç›¸å¯¹è¾ƒä½Žã€?/p>
˜q˜æœ‰ä¸€ä¸ªé—®é¢˜æ˜¯åQŒåžƒåœ‘Ö›žæ”¶åŠ¨ä½œä½•æ—¶æ‰§è¡Œï¼Ÿ
å¦ä¸€ä¸ªé—®é¢˜æ˜¯åQŒä½•时会(x¨¬)抛出OutOfMemoryExceptionåQŒåÆˆä¸æ˜¯å†…å˜è¢«è€—ç©ºçš„æ—¶å€™æ‰æŠ›å‡º
满èƒö˜q™ä¸¤ä¸ªæ¡ä»¶å°†è§¦å‘OutOfMemoryExceptionåQŒè¿™ž®†ä¼š(x¨¬)留给¾pÈ»Ÿä¸€ä¸ªå¾®ž®çš„间隙以åšä¸€äº›Down之å‰çš„æ“ä½œï¼Œæ¯”å¦‚æ‰‹åŠ¨æ‰“å°Heap Dumpã€?/p>
二ã€å†…å˜æ³„æ¼åŠ(qi¨¢ng)解决æ–ÒŽ(gu¨©)³•
1.¾pÈ»Ÿå´©æºƒå‰çš„一些现象:(x¨¬)
之厾pÈ»Ÿä¼?x¨¬)æ— æ³•å“åº”æ–°çš„è¯·æ±‚ï¼Œé€æ¸åˆ°è¾¾OutOfMemoryErrorçš„äÍ(f¨´)界倹{€?/p>
2.生æˆå †çš„dumpæ–‡äšg
通过JMXçš„MBean生æˆå½“å‰çš„Heapä¿¡æ¯åQŒå¤§ž®äØ“(f¨´)一ä¸?GåQˆæ•´ä¸ªå †çš„大ž®ï¼‰(j¨ª)çš„hprofæ–‡äšgåQŒå¦‚果没有å¯åЍJMXå¯ä»¥é€šè¿‡Javaçš„jmap命ä×o(h¨´)æ¥ç”Ÿæˆè¯¥æ–‡äšgã€?/p>
3.分æždumpæ–‡äšg
下é¢è¦è€ƒè™‘的是如何打开˜q™ä¸ª3Gçš„å †ä¿¡æ¯æ–‡äšgåQŒæ˜¾ç„¶ä¸€èˆ¬çš„Window¾pÈ»Ÿæ²¡æœ‰˜q™ä¹ˆå¤§çš„内å˜åQŒå¿…™åÕd€ŸåŠ©é«˜é…¾|®çš„Linux。当然我们å¯ä»¥å€ŸåŠ©X-Window把Linux上的囑ÖŞ导入到Window。我们考虑用下é¢å‡ ¿Uå·¥å…äh‰“开该文ä»Óž¼š(x¨¬)
使用˜q™äº›å·¥å…·æ—¶äØ“(f¨´)äº?ji¨£n)ç¡®ä¿åŠ è½½é€Ÿåº¦åQŒå¾è®®è®¾¾|®æœ€å¤§å†…å˜äØ“(f¨´)6G。ä‹É用åŽå‘现åQŒè¿™äº›å·¥å…·éƒ½æ— æ³•ç›´è§‚åœ°è§‚å¯Ÿåˆ°å†…å˜æ³„æ¼åQŒVisual VM虽能观察到对象大ž®ï¼Œä½†çœ‹ä¸åˆ°è°ƒç”¨å †æ ˆåQ›HeapAnalyzerè™½ç„¶èƒ½çœ‹åˆ°è°ƒç”¨å †æ ˆï¼Œå´æ— 法棼‹®æ‰“开一ä¸?Gçš„æ–‡ä»¶ã€‚å› æ¤ï¼Œæˆ‘们åˆé€‰ç”¨äº?ji¨£n)Eclipse专门的é™(r¨´n)æ€å†…å˜åˆ†æžå·¥å…øP¼š(x¨¬)Matã€?/p>
4.分æžå†…å˜æ³„æ¼
通过Mat我们能清楚地看到åQŒå“ªäº›å¯¹è±¡è¢«æ€€ç–‘䨓(f¨´)å†…å˜æ³„æ¼åQŒå“ªäº›å¯¹è±¡å 的空间最大åŠ(qi¨¢ng)对象的调用关¾p…R€‚é’ˆå¯ÒŽ(gu¨©)œ¬æ¡ˆï¼Œåœ¨ThreadLocal䏿œ‰å¾ˆå¤šçš„JbpmContext实例åQŒç»˜q‡è°ƒæŸ¥æ˜¯JBPMçš„Contextæ²¡æœ‰å…³é—æ‰€è‡´ã€?/p>
å¦ï¼Œé€šè¿‡Mat或JMX我们˜q˜å¯ä»¥åˆ†æžçº¿½E‹çжæ€ï¼Œå¯ä»¥è§‚察到线½E‹è¢«é˜Õd¡žåœ¨å“ªä¸ªå¯¹è±¡ä¸ŠåQŒä»Žè€Œåˆ¤æ–ç³»¾lŸçš„瓉™¢ˆã€?/p>
5.回归问题
QåQ?span style="color: #0000ff">ä¸ÞZ»€ä¹ˆå´©æºƒå‰åžƒåœ¾å›žæ”¶çš„æ—¶é—´è¶Šæ¥è¶Šé•¿ï¼Ÿ
A:æ ÒŽ(gu¨©)®å†…å˜æ¨¡åž‹å’Œåžƒåœ‘Ö›žæ”¶ç®—法,垃圾回收分两部分åQšå†…å˜æ ‡è®°ã€æ¸…除(å¤åˆ¶åQ‰ï¼Œæ ‡è®°éƒ¨åˆ†åªè¦å†…å˜å¤§å°å›ºå®šæ—‰™—´æ˜¯ä¸å˜çš„åQŒå˜çš„æ˜¯å¤åˆ¶éƒ¨åˆ†åQŒå› 为毋ơ垃圑֛žæ”‰™ƒ½æœ‰ä¸€äº›å›žæ”¶ä¸æŽ‰çš„内å˜åQŒæ‰€ä»¥å¢žåŠ äº†(ji¨£n)å¤åˆ¶é‡ï¼Œå¯ÆD‡´æ—‰™—´å»‰™•¿ã€‚所以,垃圾回收的时间也å¯ä»¥ä½œäØ“(f¨´)判æ–å†…å˜æ³„æ¼çš„便?/span>
QåQ?span style="color: #0000ff">ä¸ÞZ»€ä¹ˆF(tu¨¢n)ull GC的次数越æ¥è¶Šå¤šï¼Ÿ
AåQ?span style="color: #ff6600">å› æ¤å†…å˜çš„ç§¯ç´¯ï¼Œé€æ¸è€—å°½äº?ji¨£n)å¹´è€ä»£çš„内å˜ï¼Œå¯ÆD‡´æ–°å¯¹è±¡åˆ†é…没有更多的½Iºé—´åQŒä»Žè€Œå¯¼è‡´é¢‘¾J的垃圾回收
Q:ä¸ÞZ»€ä¹ˆå¹´è€ä»£å 用的内å˜è¶Šæ¥è¶Šå¤§ï¼Ÿ
A:å› äØ“(f¨´)òq´è½»ä»£çš„å†…å˜æ— 法被回æ”Óž¼Œ‘Šæ¥‘Šå¤šåœ°è¢«Copy到年è€ä»£
ä¸‰ã€æ€§èƒ½è°ƒä¼˜
除了(ji¨£n)ä¸Šè¿°å†…å˜æ³„æ¼å¤–,我们˜q˜å‘现CPU长期ä¸èƒö3%åQŒç³»¾lŸåžåé‡ä¸å¤ŸåQŒé’ˆå¯?core×16Gã€?4bitçš„LinuxæœåС噍æ¥è¯ß_(d¨¢)¼Œæ˜¯ä¸¥é‡çš„资溋¹ªè´¹ã€?/p>
在CPUè´Ÿè²ä¸èƒöçš„åŒæ—Óž¼Œå¶å°”ä¼?x¨¬)æœ‰ç”¨æˆ·åæ˜ è¯äh±‚的时间过长,我们æ„识到必™åÕd¯¹½E‹åºå?qi¨¢ng)JVM˜q›è¡Œè°ƒä¼˜ã€‚ä»Žä»¥ä¸‹å‡ ä¸ªæ–šw¢˜q›è¡ŒåQ?/p>
1.Java¾U¿ç¨‹æ± (java.util.concurrent.ThreadPoolExecutoråQ?/p>
大多数JVM6上的应用采用的线½E‹æ± 都是JDK自带的线½E‹æ± åQŒä¹‹æ‰€ä»¥æŠŠæˆç†Ÿçš„Java¾U¿ç¨‹æ± è¿›è¡Œç½—å—¦è¯´æ˜Žï¼Œæ˜¯å› ä¸ø™¯¥¾U¿ç¨‹æ± çš„è¡ŒäØ“(f¨´)与我们想象的有点出入。Java¾U¿ç¨‹æ± æœ‰å‡ ä¸ªé‡è¦çš„é…¾|®å‚敎ͼš(x¨¬)
Java¾U¿ç¨‹æ± 需è¦ä¼ 入一个Queue傿•°åQˆworkQueueåQ‰ç”¨æ¥å˜æ”¾æ‰§è¡Œçš„ä»ÕdŠ¡åQŒè€Œå¯¹Queueçš„ä¸åŒé€‰æ‹©åQŒçº¿½E‹æ± 有完全ä¸åŒçš„è¡ŒäØ“(f¨´)åQ?/p>
SynchronousQueueåQ?/a>
ä¸€ä¸ªæ— å®šw‡çš„ç‰å¾…队列,一个线½E‹çš„insertæ“作必须½{‰å¾…å¦ä¸€¾U¿ç¨‹çš„removeæ“作åQŒé‡‡ç”¨è¿™ä¸ªQueue¾U¿ç¨‹æ± å°†ä¼?x¨¬)äØ?f¨´)æ¯ä¸ªä»ÕdŠ¡åˆ†é…一个新¾U¿ç¨‹
LinkedBlockingQueue åQ?/code> æ— ç•Œé˜Ÿåˆ—åQŒé‡‡ç”¨è¯¥QueueåQŒçº¿½E‹æ± ž®†å¿½ç•?/code> maximumPoolSize傿•°åQŒä»…用corePoolSize的线½E‹å¤„ç†æ‰€æœ‰çš„ä»ÕdŠ¡åQŒæœªå¤„ç†çš„ä“Q务便åœ?code>LinkedBlockingQueue䏿ޒé˜?/code>
ArrayBlockingQueueåQ?/a> 有界队列åQŒåœ¨æœ‰ç•Œé˜Ÿåˆ—å’?/code> maximumPoolSize的作用下åQŒç¨‹åºå°†å¾ˆéš¾è¢«è°ƒä¼˜ï¼š(x¨¬)更大的Queueå’Œå°çš„maximumPoolSizež®†å¯¼è‡´CPU的低负è²åQ›å°çš„Queueå’Œå¤§çš„æ± åQŒQueuež®±æ²¡èµ·åŠ¨åº”æœ‰çš„ä½œç”¨ã€?/li>
å…¶å®žæˆ‘ä»¬çš„è¦æ±‚很½Ž€å•,希望¾U¿ç¨‹æ± èƒ½è·Ÿè¿žæŽ¥æ± ä¸€æ øP¼Œèƒ½è®¾¾|®æœ€ž®çº¿½E‹æ•°ã€æœ€å¤§çº¿½E‹æ•°åQŒå½“最ž®æ•°<ä»ÕdŠ¡<最大数æ—Óž¼Œåº”è¯¥åˆ†é…æ–°çš„¾U¿ç¨‹å¤„ç†åQ›å½“ä»ÕdŠ¡>最大数æ—Óž¼Œåº”该½{‰å¾…有空闲线½E‹å†å¤„ç†è¯¥ä“Q务ã€?/p>
但线½E‹æ± 的设计æ€èµ\是,ä»ÕdŠ¡åº”è¯¥æ”‘Öˆ°Queueä¸ï¼Œå½“Queue放ä¸ä¸‹æ—¶å†è€ƒè™‘用新¾U¿ç¨‹å¤„ç†åQŒå¦‚æžœQ(j¨¬ng)ueueæ»¡ä¸”æ— æ³•‹z„¡”Ÿæ–°çº¿½E‹ï¼Œž®±æ‹’¾l该ä»ÕdŠ¡ã€‚è®¾è®¡å¯¼è‡?#8220;先放½{‰æ‰§è¡?#8221;ã€?#8220;放ä¸ä¸‹å†æ‰§è¡Œ”ã€?#8220;æ‹’ç»ä¸ç‰å¾?#8221;。所以,æ ÒŽ(gu¨©)®ä¸åŒçš„Queue傿•°åQŒè¦æé«˜åžåé‡ä¸èƒ½ä¸€å‘›_œ°å¢žå¤§maximumPoolSizeã€?/p>
当然åQŒè¦è¾‘Öˆ°æˆ‘ä»¬çš„ç›®æ ‡ï¼Œå¿…é¡»å¯¹çº¿½E‹æ± ˜q›è¡Œä¸€å®šçš„ž®è£…åQŒå¹¸˜q的是ThreadPoolExecutorä¸ç•™äº?ji¨£n)èƒö够的自定义接å£ä»¥å¸®åŠ©æˆ‘ä»¬è¾‘Öˆ°ç›®æ ‡ã€‚我们å°è£…çš„æ–¹å¼æ˜¯ï¼š(x¨¬)
- 以SynchronousQueueä½œäØ“(f¨´)傿•°åQŒä‹ÉmaximumPoolSize呿Œ¥ä½œç”¨åQŒä»¥é˜²æ¢¾U¿ç¨‹è¢«æ— é™åˆ¶çš„分é…ï¼ŒåŒæ—¶å¯ä»¥é€šè¿‡æé«˜maximumPoolSizeæ¥æé«˜ç³»¾lŸåžåé‡
- 自定义一个RejectedExecutionHandleråQŒå½“¾U¿ç¨‹æ•°è¶…˜q‡maximumPoolSize时进行处ç†ï¼Œå¤„ç†æ–¹å¼ä¸ºéš”一ŒD‰|—¶é—´æ£€æŸ¥çº¿½E‹æ± 是å¦å¯ä»¥æ‰§è¡Œæ–°TaskåQŒå¦‚æžœå¯ä»¥æŠŠæ‹’ç»çš„Task釿–°æ”‘Ö…¥åˆ°çº¿½E‹æ± åQŒæ£€æŸ¥çš„æ—‰™—´ä¾èµ–keepAliveTime的大ž®ã€?/li>
2.˜qžæŽ¥æ± (org.apache.commons.dbcp.BasicDataSourceåQ?/p>
在ä‹É用org.apache.commons.dbcp.BasicDataSourceçš„æ—¶å€™ï¼Œå› äØ“(f¨´)之å‰é‡‡ç”¨äº?ji¨£n)默认酾|®ï¼Œæ‰€ä»¥å½“讉K—®é‡å¤§æ—Óž¼Œé€šè¿‡JMX观察到很多Tomcat¾U¿ç¨‹éƒ½é˜»å¡žåœ¨BasicDataSource使用的Apache ObjectPoolçš„é”ä¸Šï¼Œç›´æŽ¥åŽŸå› å½“æ—¶æ˜¯å› ä¸ºBasicDataSource˜qžæŽ¥æ± 的最大连接数讄¡½®çš„太ž®ï¼Œé»˜è®¤çš„BasicDataSourceé…ç½®åQŒä»…使用8个最大连接ã€?/p>
我还观察åˆîC¸€ä¸ªé—®é¢˜ï¼Œå½“较长的旉™—´ä¸è®¿é—®ç³»¾lŸï¼Œæ¯”如2天,DB上的Mysqlä¼?x¨¬)æ–æŽ‰æ‰€ä»¥çš„˜qžæŽ¥åQŒå¯¼è‡´è¿žæŽ¥æ± ä¸ç¼“å˜çš„˜qžæŽ¥ä¸èƒ½ç”¨ã€‚䨓(f¨´)äº?ji¨£n)解册™¿™äº›é—®é¢˜ï¼Œæˆ‘ä»¬å……åˆ†ç ”ç©¶äº†(ji¨£n)BasicDataSourceåQŒå‘çŽîCº†(ji¨£n)一些优化的点:(x¨¬)
- Mysql默认支æŒ100个链接,所以æ¯ä¸ªè¿žæŽ¥æ± 的酾|®è¦æ ÒŽ(gu¨©)®é›†ç¾¤ä¸çš„æœºå™¨æ•°è¿›è¡Œï¼Œå¦‚有2å°æœåС噍åQŒå¯æ¯ä¸ªè®„¡½®ä¸?0
- initialSizeåQšå‚数是一直打开的连接数
- minEvictableIdleTimeMillisåQšè¯¥å‚数讄¡½®æ¯ä¸ª˜qžæŽ¥çš„空闲时é—ß_(d¨¢)¼Œ‘…过˜q™ä¸ªæ—‰™—´˜qžæŽ¥ž®†è¢«å…³é—
- timeBetweenEvictionRunsMillisåQšåŽå°çº¿½E‹çš„˜q行周期åQŒç”¨æ¥æ£€‹¹‹è¿‡æœŸè¿žæŽ?/li>
- maxActiveåQšæœ€å¤§èƒ½åˆ†é…的连接数
- maxIdleåQšæœ€å¤§ç©ºé—²æ•°åQŒå½“˜qžæŽ¥ä½¿ç”¨å®Œæ¯•åŽå‘现连接数大于maxIdleåQŒè¿žæŽ¥å°†è¢«ç›´æŽ¥å…³é—ã€‚åªæœ‰initialSize < x < maxIdle的连接将被定期检‹¹‹æ˜¯å¦è¶…æœŸã€‚è¿™ä¸ªå‚æ•îC¸»è¦ç”¨æ¥åœ¨å³°å€ÆD®¿é—®æ—¶æé«˜åžåé‡ã€?/li>
- initialSizeæ˜¯å¦‚ä½•ä¿æŒçš„åQŸç»˜q‡ç ”½I¶ä»£ç å‘玎ͼŒBasicDataSourceä¼?x¨¬)关闿‰€æœ‰è¶…期的˜qžæŽ¥åQŒç„¶åŽå†æ‰“å¼€initialSizeæ•°é‡çš„连接,˜q™ä¸ªç‰ÒŽ(gu¨©)€§ä¸ŽminEvictableIdleTimeMillisã€timeBetweenEvictionRunsMillis一起ä¿è¯äº†(ji¨£n)所有超期的initialSize˜qžæŽ¥éƒ½ä¼š(x¨¬)è¢«é‡æ–°è¿žæŽ¥ï¼Œä»Žè€Œé¿å…了(ji¨£n)Mysqlé•¿æ—¶é—´æ— åŠ¨ä½œä¼?x¨¬)æ–æŽ‰è¿žæŽ¥çš„é—®é¢˜ã€?/li>
3.JVM傿•°
在JVMå¯åЍ傿•°ä¸ï¼Œå¯ä»¥è®„¡½®è·Ÿå†…å˜ã€åžƒåœ‘Ö›žæ”¶ç›¸å…³çš„ä¸€äº›å‚æ•°è®¾¾|®ï¼Œé»˜è®¤æƒ…况ä¸åšä»ÖM½•讄¡½®JVMä¼?x¨¬)工作的很好åQŒä½†å¯¹ä¸€äº›é…¾|®å¾ˆå¥½çš„Server和具体的应用必须仔细调优æ‰èƒ½èŽ·å¾—æœ€ä½Ïx€§èƒ½ã€‚通过讄¡½®æˆ‘们希望辑ֈ°ä¸€äº›ç›®æ ‡ï¼š(x¨¬)
- GC的时间èƒö够的ž®?/li>
- GC的次数èƒö够的ž®?/li>
- å‘生Full GC的周期èƒö够的é•?/li>
å‰ä¸¤ä¸ªç›®å‰æ˜¯ç›¸æ?zh¨¨n)–çš„ï¼Œè¦æƒ³GCæ—‰™—´ž®å¿…™å»è¦ä¸€ä¸ªæ›´ž®çš„å †ï¼Œè¦ä¿è¯GC‹Æ¡æ•°‘›_¤Ÿž®‘,必须ä¿è¯ä¸€ä¸ªæ›´å¤§çš„å †ï¼Œæˆ‘ä»¬åªèƒ½å–å…¶òqŒ™¡¡ã€?/p>
åQ?åQ‰é’ˆå¯¹JVMå †çš„è®„¡½®ä¸€èˆ¬ï¼Œå¯ä»¥é€šè¿‡-Xms -Xmxé™å®šå…¶æœ€ž®ã€æœ€å¤§å€û|¼Œä¸ÞZº†(ji¨£n)防æ¢åžƒåœ¾æ”‰™›†å™¨åœ¨æœ€ž®ã€æœ€å¤§ä¹‹é—´æ”¶¾~©å †è€Œäñ”生é¢å¤–的旉™—´åQŒæˆ‘ä»¬é€šå¸¸æŠŠæœ€å¤§ã€æœ€ž®è®¾¾|®äØ“(f¨´)相åŒçš„å€?br /> åQ?åQ‰å¹´è½ÖM»£å’Œå¹´è€ä»£ž®†æ ¹æ®é»˜è®¤çš„æ¯”例åQ?åQ?åQ‰åˆ†é…å †å†…å˜åQŒå¯ä»¥é€šè¿‡è°ƒæ•´äºŒè€…之间的比率NewRadioæ¥è°ƒæ•´äºŒè€…之间的大å°åQŒä¹Ÿå¯ä»¥é’ˆå¯¹å›žæ”¶ä»£ï¼Œæ¯”如òq´è½»ä»£ï¼Œé€šè¿‡ -XX:newSize -XX:MaxNewSizeæ¥è®¾¾|®å…¶¾l对大å°ã€‚åŒæ øP¼Œä¸ÞZº†(ji¨£n)防æ¢òq´è½»ä»£çš„å †æ”¶¾~©ï¼Œæˆ‘们通常ä¼?x¨¬)æŠ?XX:newSize -XX:MaxNewSize讄¡½®ä¸ºåŒæ ·å¤§ž®?/p>
åQ?åQ‰å¹´è½ÖM»£å’Œå¹´è€ä»£è®„¡½®å¤šå¤§æ‰ç®—åˆç†åQŸè¿™ä¸ªæˆ‘é—®é¢˜æ¯«æ— ç–‘é—®æ˜¯æ²¡æœ‰ç”æ¡ˆçš„åQŒå¦åˆ™ä¹Ÿž®×ƒ¸ä¼?x¨¬)有调优。我们观察一下二者大ž®å˜åŒ–有哪些影å“
- 更大的年è½ÖM»£å¿…ç„¶å¯ÆD‡´æ›´å°çš„å¹´è€ä»£åQŒå¤§çš„å¹´è½ÖM»£ä¼?x¨¬)åšg长普通GC的周期,但会(x¨¬)å¢žåŠ æ¯æ¬¡GC的时é—ß_(d¨¢)¼›ž®çš„òq´è€ä»£ä¼?x¨¬)导致更频ç¹çš„Full GC
- æ›´å°çš„å¹´è½ÖM»£å¿…ç„¶å¯ÆD‡´æ›´å¤§òq´è€ä»£åQŒå°çš„å¹´è½ÖM»£ä¼?x¨¬)导致普通GC很频¾J,但毋ơ的GCæ—‰™—´ä¼?x¨¬)æ›´çŸï¼›å¤§çš„òq´è€ä»£ä¼?x¨¬)凞®‘Full GC的频çŽ?/li>
- 如何选择应该ä¾èµ–应用½E‹åºå¯¹è±¡ç”Ÿå‘½å‘¨æœŸçš„分布情况:(x¨¬)如果应用å˜åœ¨å¤§é‡çš„äÍ(f¨´)时对象,应该选择更大的年è½ÖM»£åQ›å¦‚æžœå˜åœ¨ç›¸å¯¹è¾ƒå¤šçš„æŒä¹…å¯¹è±¡åQŒå¹´è€ä»£åº”该适当增大。但很多应用都没有这æ äh˜Žæ˜„¡š„ç‰ÒŽ(gu¨©)€§ï¼Œåœ¨æŠ‰æ‹©æ—¶åº”该æ ÒŽ(gu¨©)®ä»¥ä¸‹ä¸¤ç‚¹åQšï¼ˆAåQ‰æœ¬ç€Full GCž®½é‡ž®‘的原则åQŒè®©òq´è€ä»£ž®½é‡¾~“å˜å¸¸ç”¨å¯¹è±¡åQŒJVM的默认比ä¾?åQ?也是˜q™ä¸ªé“ç† åQˆBåQ‰é€šè¿‡è§‚察应用一ŒD‰|—¶é—ß_(d¨¢)¼Œçœ‹å…¶ä»–在峰值时òq´è€ä»£ä¼?x¨¬)å 多少内å˜åQŒåœ¨ä¸åª„(ji¨£ng)å“Full GCçš„å‰æä¸‹åQŒæ ¹æ®å®žé™…æƒ…å†µåŠ å¤§å¹´è½ÖM»£åQŒæ¯”如å¯ä»¥æŠŠæ¯”例控制åœ?åQ?。但应该¾l™å¹´è€ä»£è‡›_°‘预留1/3的增长空é—?/li>
åQ?åQ‰åœ¨é…置较好的机器上åQˆæ¯”å¦‚å¤šæ ¸ã€å¤§å†…å˜åQ‰ï¼Œå¯ä»¥ä¸ºå¹´è€ä»£é€‰æ‹©òq¶è¡Œæ”‰™›†½Ž—法åQ?-XX:+UseParallelOldGC åQŒé»˜è®¤äØ“(f¨´)Serial攉™›†
åQ?åQ‰çº¿½E‹å †æ ˆçš„讄¡½®åQšæ¯ä¸ªçº¿½E‹é»˜è®¤ä¼š(x¨¬)å¼€å?Mçš„å †æ ˆï¼Œç”¨äºŽå˜æ”¾æ ˆå“áã€è°ƒç”¨å‚æ•°ã€å±€éƒ¨å˜é‡ç‰åQŒå¯¹å¤§å¤šæ•°åº”用而言˜q™ä¸ªé»˜è®¤å€¼å¤ªäº?ji¨£n),一èˆ?56Kž®Þpƒö用。ç†è®ÞZ¸ŠåQŒåœ¨å†…å˜ä¸å˜çš„æƒ…况下åQŒå‡ž®‘æ¯ä¸ªçº¿½E‹çš„å †æ ˆåQŒå¯ä»¥äñ”生更多的¾U¿ç¨‹åQŒä½†˜q™å®žé™…上˜q˜å—é™äºŽæ“作¾pÈ»Ÿã€?/p>
åQ?åQ‰å¯ä»¥é€šè¿‡ä¸‹é¢çš„傿•°æ‰“Heap Dumpä¿¡æ¯
- -XX:HeapDumpPath
- -XX:+PrintGCDetails
- -XX:+PrintGCTimeStamps
- -Xloggc:/usr/aaa/dump/heap_trace.txt
通过下é¢å‚æ•°å¯ä»¥æŽ§åˆ¶OutOfMemoryError时打å°å †çš„ä¿¡æ?/p>
- -XX:+HeapDumpOnOutOfMemoryError
è¯ïL(f¨¥ng)œ‹ä¸€ä¸‹ä¸€ä¸ªæ—¶é—´çš„Java傿•°é…ç½®åQšï¼ˆæœåŠ¡å™¨ï¼š(x¨¬)Linux 64BitåQ?Core×16GåQ?/p>
JAVA_OPTS="$JAVA_OPTS -server -Xms3G -Xmx3G -Xss256k -XX:PermSize=128m -XX:MaxPermSize=128m -XX:+UseParallelOldGC -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/usr/aaa/dump -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -Xloggc:/usr/aaa/dump/heap_trace.txt -XX:NewSize=1G -XX:MaxNewSize=1G"
¾l过观察该酾|®éžå¸¸ç¨³å®šï¼Œæ¯æ¬¡æ™®é€šGC的时间在10mså·¦å³åQŒFull GC基本ä¸å‘生,或隔很长很长的时间æ‰å‘生一‹Æ?/p>
通过分æždumpæ–‡äšgå¯ä»¥å‘现åQŒæ¯ä¸?ž®æ—¶éƒ½ä¼š(x¨¬)å‘生一‹Æ¡Full GCåQŒç»˜q‡å¤šæ–ÒŽ(gu¨©)±‚è¯ï¼Œåªè¦åœ¨JVMä¸å¼€å¯äº†(ji¨£n)JMXæœåŠ¡åQŒJMXž®†ä¼š(x¨¬)1ž®æ—¶æ‰§è¡Œä¸€‹Æ¡Full GC以清除引用,关于˜q™ç‚¹è¯·å‚考附件文档ã€?/span>
4.½E‹åº½Ž—法调优åQšæœ¬‹Æ¡ä¸ä½œäØ“(f¨´)é‡ç‚¹
å‚考资料:(x¨¬)
http://java.sun.com/javase/technologies/hotspot/gc/gc_tuning_6.html

]]>
Java GC 垃圾攉™›† http://www.aygfsteel.com/stevenjohn/archive/2013/05/28/399870.htmlabin abin Tue, 28 May 2013 06:31:00 GMT http://www.aygfsteel.com/stevenjohn/archive/2013/05/28/399870.html http://www.aygfsteel.com/stevenjohn/comments/399870.html http://www.aygfsteel.com/stevenjohn/archive/2013/05/28/399870.html#Feedback 0 http://www.aygfsteel.com/stevenjohn/comments/commentRss/399870.html http://www.aygfsteel.com/stevenjohn/services/trackbacks/399870.html Javaå †ï¼Œåˆ†é…对象实例所在空é—ß_(d¨¢)¼Œæ˜¯GC的主è¦å¯¹è±¡ã€‚分ä¸?/div> 新生ä»?Young Generation/New) è€å¹´ä»?Tenured Generation/Old)
新生代åˆåˆ’分æˆ?/div> Eden Space From Survivor/Survivor 0 To Survivor/Survivor 1 新生代è¦å¦‚æ¤åˆ’åˆ†æ˜¯å› ä¸ºæ–°ç”Ÿä»£ä½¿ç”¨çš„GC½Ž—法是å¤åˆ¶æ”¶é›†ç®—法。这¿U算法效率较高,而GCä¸»è¦æ˜¯å‘生在对象¾l常消亡的新生代åQŒå› æ¤æ–°ç”Ÿä»£é€‚åˆä½¿ç”¨˜q™ç§å¤åˆ¶æ”‰™›†½Ž—法。由于有一个å‡è®¾ï¼š(x¨¬)在一‹Æ¡æ–°ç”Ÿä»£çš„GC(Minor GC)åŽå¤§éƒ¨åˆ†çš„对象å 用的内å˜éƒ½ä¼š(x¨¬)被回æ”Óž¼Œå› æ¤ç•™å˜çš„æ”¾¾|®GCåŽä»ç„¶æ´»çš„对象的½Iºé—´ž®±æ¯”较å°äº?ji¨£n)。这个留å˜çš„½Iºé—´ž®±æ˜¯Survivor spaceåQšFrom Survivor或To Survivor。这两个Survivor½Iºé—´æ˜¯ä¸€æ ·å¤§ž®çš„。例如,新生代大ž®æ˜¯10M(Xmn10M)åQŒé‚£ä¹ˆç¼ºçœæƒ…况下(-XX:SurvivorRatio=8)åQŒEden Space æ˜?MåQŒFromå’ŒTo都是1Mã€?/div>在new一个对象时åQŒå…ˆåœ¨Eden Space上分é…,如果Eden Space½Iºé—´ä¸å¤Ÿž®Þp¦åšä¸€‹Æ¡Minor GC。Minor GCåŽï¼Œè¦æŠŠEdenå’ŒFromä¸ä»ç„¶æ´»ç€çš„对象们å¤åˆ¶åˆ°To½Iºé—´ä¸åŽ»ã€‚å¦‚æžœTo½Iºé—´ä¸èƒ½å®¹çº³Minor GCåŽæ´»ç€çš„æŸä¸ªå¯¹è±¡ï¼Œé‚£ä¹ˆè¯¥å¯¹è±¡å°±è¢«promote到è€å¹´ä»£ç©ºé—´ã€‚从Eden½Iºé—´è¢«å¤åˆ¶åˆ°To½Iºé—´çš„对象就有了(ji¨£n)age=1。æ¤age=1的对象如果在下一‹Æ¡çš„Minor GCåŽä»ç„¶å˜?g¨°u)z»ï¼Œå®ƒè¿˜ä¼?x¨¬)被å¤åˆ¶åˆ°å¦ä¸€ä¸ªSurvivor½Iºé—´(å¦‚æžœè®¤äØ“(f¨´)Fromå’ŒTo是固定的åQŒå°±æ˜¯åˆä»ŽTo回到äº?ji¨£n)From½Iºé—´)åQŒè€Œå®ƒçš„age=2。如æ¤åå¤ï¼Œå¦‚æžœage大于æŸä¸ªé˜ˆå€?-XX:MaxTenuringThreshold=n)åQŒé‚£ä¸ªè¯¥å¯¹è±¡ž®×ƒ¹Ÿå¯ä»¥promote到è€å¹´ä»£äº†(ji¨£n)ã€?/div>如果Survivor½Iºé—´ä¸ç›¸åŒage(例如åQŒage=5)对象的æ€Õd’Œå¤§äºŽ½{‰äºŽSurvivor½Iºé—´çš„一åŠï¼Œé‚£ä¹ˆage>=5的对象在下一‹Æ¡Minor GCåŽå°±å¯ä»¥ç›´æŽ¥promote到è€å¹´ä»£ï¼Œè€Œä¸ç”¨ç‰åˆ°age增长到阈倹{€?/div>在åšMinor GCæ—Óž¼Œåªå¯¹æ–°ç”Ÿä»£åšå›žæ”¶åQŒä¸ä¼?x¨¬)回收è€å¹´ä»£ã€‚å³ä½¿è€å¹´ä»£çš„å¯¹è±¡æ— äh索引也将ä»ç„¶å˜æ´»åQŒç›´åˆîC¸‹ä¸€‹Æ¡Full GCã€?/div>
abin 2013-05-28 14:31 å‘表评论]]>JVM傿•°é…置大全 http://www.aygfsteel.com/stevenjohn/archive/2012/11/14/391310.htmlabin abin Wed, 14 Nov 2012 05:48:00 GMT http://www.aygfsteel.com/stevenjohn/archive/2012/11/14/391310.html http://www.aygfsteel.com/stevenjohn/comments/391310.html http://www.aygfsteel.com/stevenjohn/archive/2012/11/14/391310.html#Feedback 0 http://www.aygfsteel.com/stevenjohn/comments/commentRss/391310.html http://www.aygfsteel.com/stevenjohn/services/trackbacks/391310.html
å‰é˜µåé‡åˆ°å‡ 个é¢è¯•题都是关于对Javaå†…å˜æŽ§åˆ¶çš?å› æ¤ä»Žç½‘上找到这½‹‡æ–‡ç«?希望自己对Java的内å˜åˆ†é…æœ‰é‡æ–°çš„认è¯?
/usr/local/jdk/bin/java -Dresin.home=/usr/local/resin -server -Xms1800M -Xmx1800M -Xmn300M -Xss512K -XX:PermSize=300M -XX:MaxPermSize=300M -XX:SurvivorRatio=8 -XX:MaxTenuringThreshold=5 -XX:GCTimeRatio=19 -Xnoclassgc -XX:+DisableExplicitGC -XX:+UseParNewGC -XX:+UseConcMarkSweepGC -XX:+UseCMSCompactAtFullCollection -XX:CMSFullGCsBeforeCompaction=0 -XX:-CMSParallelRemarkEnabled -XX:CMSInitiatingOccupancyFraction=70 -XX:SoftRefLRUPolicyMSPerMB=0 -XX:+PrintClassHistogram -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintHeapAtGC -Xloggc:log/gc.log
- å †å¤§ž®è®¾¾|?br />JVM 䏿œ€å¤§å †å¤§å°æœ‰ä¸‰æ–šw¢é™åˆ¶åQšç›¸å…Ïx“作系¾lŸçš„æ•°æ®æ¨¡åž‹åQ?2-bt˜q˜æ˜¯64-bitåQ‰é™åˆÓž¼›¾pÈ»Ÿçš„å¯ç”¨è™šæ‹Ÿå†…å˜é™åˆÓž¼›¾pÈ»Ÿçš„å¯ç”¨ç‰©ç†å†…å˜é™åˆ¶ã€?2ä½ç³»¾lŸä¸‹åQŒä¸€èˆ¬é™åˆ¶åœ¨1.5G~2GåQ?4为æ“作系¾lŸå¯¹å†…å˜æ— é™åˆ¶ã€‚我在Windows Server 2003 ¾pÈ»ŸåQ?.5G物ç†å†…å˜åQŒJDK5.0下测试,最大å¯è®„¡½®ä¸?478mã€?br />典型讄¡½®åQ?/strong>
- java -Xmx3550m -Xms3550m -Xmn2g -Xss128k
-Xmx3550måQšè®¾¾|®JVM最大å¯ç”¨å†…å˜äØ“(f¨´)3550Mã€?br />-Xms3550måQšè®¾¾|®JVMä¿?j¨©)ä‹É内å˜ä?550m。æ¤å€¼å¯ä»¥è®¾¾|®ä¸Ž-Xmx相åŒåQŒä»¥é¿å…æ¯æ¬¡åžƒåœ¾å›žæ”¶å®ŒæˆåŽJVM釿–°åˆ†é…内å˜ã€?br />-Xmn2gåQšè®¾¾|®å¹´è½ÖM»£å¤§å°ä¸?Gã€?strong>æ•´ä¸ªå †å¤§ž®?òq´è½»ä»£å¤§ž®?+ òq´è€ä»£å¤§å° + æŒä¹…代大ž®?/strong>。æŒä¹…代一般固定大ž®äØ“(f¨´)64måQŒæ‰€ä»¥å¢žå¤§å¹´è½ÖM»£åŽï¼Œž®†ä¼š(x¨¬)å‡å°òq´è€ä»£å¤§å°ã€‚æ¤å€¼å¯¹¾pÈ»Ÿæ€§èƒ½å½±å“较大åQŒSun官方推èé…ç½®ä¸ºæ•´ä¸ªå †çš?/8ã€?br />-Xss128kåQšè®¾¾|®æ¯ä¸ªçº¿½E‹çš„å †æ ˆå¤§å°ã€‚JDK5.0ä»¥åŽæ¯ä¸ª¾U¿ç¨‹å †æ ˆå¤§å°ä¸?MåQŒä»¥å‰æ¯ä¸ªçº¿½E‹å †æ ˆå¤§ž®äØ“(f¨´)256K。更具应用的¾U¿ç¨‹æ‰€éœ€å†…å˜å¤§å°˜q›è¡Œè°ƒæ•´ã€‚在相åŒç‰©ç†å†…å˜ä¸‹ï¼Œå‡å°˜q™ä¸ªå€ÆDƒ½ç”Ÿæˆæ›´å¤šçš„线½E‹ã€‚但是æ“作系¾lŸå¯¹ä¸€ä¸ªè¿›½E‹å†…的线½E‹æ•°˜q˜æ˜¯æœ‰é™åˆ¶çš„åQŒä¸èƒ½æ— é™ç”Ÿæˆï¼Œ¾l验值在3000~5000å·¦å³ã€? - java -Xmx3550m -Xms3550m -Xss128k -XX:NewRatio=4 -XX:SurvivorRatio=4 -XX:MaxPermSize=16m -XX:MaxTenuringThreshold=0
-XX:NewRatio=4:讄¡½®òq´è½»ä»£ï¼ˆåŒ…括Eden和两个Survivor区)(j¨ª)与年è€ä»£çš„æ¯”å€û|¼ˆé™¤åŽ»æŒä¹…代)(j¨ª)。设¾|®äØ“(f¨´)4åQŒåˆ™òq´è½»ä»£ä¸Žòq´è€ä»£æ‰€å 比å€égØ“(f¨´)1åQ?åQŒå¹´è½ÖM»£å æ•´ä¸ªå †æ ˆçš„1/5
-XX:SurvivorRatio=4åQšè®¾¾|®å¹´è½ÖM»£ä¸EdenåŒÞZ¸ŽSurvivoråŒºçš„å¤§å°æ¯”倹{€‚设¾|®äØ“(f¨´)4åQŒåˆ™ä¸¤ä¸ªSurvivoråŒÞZ¸Žä¸€ä¸ªEden区的比å€égØ“(f¨´)2:4åQŒä¸€ä¸ªSurvivoråŒºå æ•´ä¸ªòq´è½»ä»£çš„1/6
-XX:MaxPermSize=16m:讄¡½®æŒä¹…代大ž®äØ“(f¨´)16mã€?br />-XX:MaxTenuringThreshold=0åQšè®¾¾|®åžƒåœ¾æœ€å¤§å¹´é¾„ã€?strong>如果讄¡½®ä¸?çš„è¯åQŒåˆ™òq´è½»ä»£å¯¹è±¡ä¸¾l过Survivor区,直接˜q›å…¥òq´è€ä»£ã€‚对于年è€ä»£æ¯”较多的应用åQŒå¯ä»¥æé«˜æ•ˆçއã€?strong>如果ž®†æ¤å€ÆD®¾¾|®äØ“(f¨´)一个较大å€û|¼Œåˆ™å¹´è½ÖM»£å¯¹è±¡ä¼?x¨¬)在SurvivoråŒø™¿›è¡Œå¤š‹Æ¡å¤åˆÓž¼Œ˜q™æ ·å¯ä»¥å¢žåŠ å¯¹è±¡å†å¹´è½ÖM»£çš„å˜?g¨°u)zÀL—¶é—?/strong>åQŒå¢žåŠ åœ¨òq´è½»ä»£å³è¢«å›žæ”¶çš„æ¦‚论ã€?/li>
- 回收器选择
JVM¾l™äº†(ji¨£n)三ç§é€‰æ‹©åQ?strong>串行攉™›†å™¨ã€åƈ行收集器ã€åÆˆå‘æ”¶é›†å™¨åQŒä½†æ˜¯ä¸²è¡Œæ”¶é›†å™¨åªé€‚ç”¨äºŽå°æ•°æ®é‡çš„æƒ…况åQŒæ‰€ä»¥è¿™é‡Œçš„选择主è¦é’ˆå¯¹òq¶è¡Œæ”‰™›†å™¨å’Œòq¶å‘攉™›†å™¨ã€‚默认情况下åQŒJDK5.0以å‰éƒ½æ˜¯ä½¿ç”¨ä¸²è¡Œæ”‰™›†å™¨ï¼Œå¦‚果想ä‹É用其他收集器需è¦åœ¨å¯åŠ¨æ—¶åŠ å…¥ç›¸åº”å‚æ•°ã€‚JDK5.0以åŽåQŒJVMä¼?x¨¬)æ ¹æ®å½“å?a >¾pÈ»Ÿé…ç½®˜q›è¡Œåˆ¤æ–ã€?
- åžåé‡ä¼˜å…?/strong>çš„åÆˆè¡Œæ”¶é›†å™¨
如上文所˜qŽÍ¼Œòq¶è¡Œæ”‰™›†å™¨ä¸»è¦ä»¥åˆ°è¾¾ä¸€å®šçš„åžåé‡äØ“(f¨´)ç›®æ ‡åQŒé€‚ç”¨äºŽç§‘å¦æŠ€æœ¯å’ŒåŽå°å¤„熽{‰ã€?br />典型é…ç½®åQ?
- java -Xmx3800m -Xms3800m -Xmn2g -Xss128k -XX:+UseParallelGC -XX:ParallelGCThreads=20
-XX:+UseParallelGCåQšé€‰æ‹©åžƒåœ¾æ”‰™›†å™¨äØ“(f¨´)òq¶è¡Œæ”‰™›†å™¨ã€?strong>æ¤é…¾|®ä»…对年è½ÖM»£æœ‰æ•ˆã€‚å³ä¸Šè¿°é…置下,òq´è½»ä»£ä‹Éç”¨åÆˆå‘æ”¶é›†ï¼Œè€Œå¹´è€ä»£ä»æ—§ä½¿ç”¨ä¸²è¡Œæ”‰™›†ã€?br />-XX:ParallelGCThreads=20åQšé…¾|®åƈ行收集器的线½E‹æ•°åQŒå³åQšåŒæ—¶å¤šž®‘个¾U¿ç¨‹ä¸€èµ¯‚¿›è¡Œåžƒåœ‘Ö›žæ”¶ã€‚æ¤å€¼æœ€å¥½é…¾|®ä¸Žå¤„ç†å™¨æ•°ç›®ç›¸½{‰ã€? - java -Xmx3550m -Xms3550m -Xmn2g -Xss128k -XX:+UseParallelGC -XX:ParallelGCThreads=20 -XX:+UseParallelOldGC
-XX:+UseParallelOldGCåQšé…¾|®å¹´è€ä»£åžƒåœ¾æ”‰™›†æ–¹å¼ä¸ºåƈ行收集。JDK6.0支æŒå¯¹å¹´è€ä»£òq¶è¡Œæ”‰™›†ã€? - java -Xmx3550m -Xms3550m -Xmn2g -Xss128k -XX:+UseParallelGC -XX:MaxGCPauseMillis=100
-XX:MaxGCPauseMillis=100:讄¡½®æ¯æ¬¡òq´è½»ä»£åžƒåœ‘Ö›žæ”¶çš„æœ€é•¿æ—¶é—ß_(d¨¢)¼Œå¦‚æžœæ— æ³•æ»¡èƒöæ¤æ—¶é—ß_(d¨¢)¼ŒJVMä¼?x¨¬)自动调整年è½ÖM»£å¤§å°åQŒä»¥æ»¡èƒöæ¤å€¹{€? - java -Xmx3550m -Xms3550m -Xmn2g -Xss128k -XX:+UseParallelGC -XX:MaxGCPauseMillis=100-XX:+UseAdaptiveSizePolicy
-XX:+UseAdaptiveSizePolicyåQšè®¾¾|®æ¤é€‰é¡¹åŽï¼Œòq¶è¡Œæ”‰™›†å™¨ä¼š(x¨¬)自动选择òq´è½»ä»£åŒºå¤§å°å’Œç›¸åº”çš„SurvivoråŒºæ¯”ä¾‹ï¼Œä»¥è¾¾åˆ°ç›®æ ‡ç³»¾lŸè§„定的最低相应时间或者收集频率ç‰åQŒæ¤å€¼å¾è®®ä‹Éç”¨åÆˆè¡Œæ”¶é›†å™¨æ—Óž¼Œä¸€ç›´æ‰“å¼€ã€?/li>
- å“应旉™—´ä¼˜å…ˆçš„åÆˆå‘æ”¶é›†å™¨
如上文所˜qŽÍ¼Œòq¶å‘攉™›†å™¨ä¸»è¦æ˜¯ä¿è¯¾pÈ»Ÿçš„å“应时é—ß_(d¨¢)¼Œå‡å°‘垃圾攉™›†æ—¶çš„åœé¡¿æ—‰™—´ã€‚适用于应用æœåС噍ã€ç”µ(sh¨´)信领域ç‰ã€?br />典型é…ç½®åQ?
- java -Xmx3550m -Xms3550m -Xmn2g -Xss128k -XX:ParallelGCThreads=20 -XX:+UseConcMarkSweepGC -XX:+UseParNewGC
-XX:+UseConcMarkSweepGCåQšè®¾¾|®å¹´è€ä»£ä¸ºåÆˆå‘æ”¶é›†ã€‚测试ä¸é…ç½®˜q™ä¸ªä»¥åŽåQ?XX:NewRatio=4的酾|®å¤±æ•ˆäº†(ji¨£n)åQŒåŽŸå› ä¸æ˜Žã€‚æ‰€ä»¥ï¼Œæ¤æ—¶òq´è½»ä»£å¤§ž®æœ€å¥½ç”¨-Xmn讄¡½®ã€?br />-XX:+UseParNewGC:讄¡½®òq´è½»ä»£äØ“(f¨´)òq¶è¡Œæ”‰™›†ã€‚å¯ä¸ŽCMS攉™›†åŒæ—¶ä½¿ç”¨ã€‚JDK5.0以上åQŒJVMä¼?x¨¬)æ ¹æ®ç³»¾lŸé…¾|®è‡ªè¡Œè®¾¾|®ï¼Œæ‰€ä»¥æ— 需å†è®¾¾|®æ¤å€¹{€? - java -Xmx3550m -Xms3550m -Xmn2g -Xss128k -XX:+UseConcMarkSweepGC -XX:CMSFullGCsBeforeCompaction=5 -XX:+UseCMSCompactAtFullCollection
-XX:CMSFullGCsBeforeCompactionåQšç”±äºŽåÆˆå‘æ”¶é›†å™¨ä¸å¯¹å†…嘽Iºé—´˜q›è¡ŒåŽ‹ç¾ƒã€æ•´ç†ï¼Œæ‰€ä»¥è¿è¡Œä¸€ŒD‰|—¶é—´ä»¥åŽä¼š(x¨¬)产生“¼„Žç‰‡”åQŒä‹Éå¾—è¿è¡Œæ•ˆçއé™ä½Žã€‚æ¤å€ÆD®¾¾|®è¿è¡Œå¤šž®‘次GC以åŽå¯¹å†…å˜ç©ºé—´è¿›è¡ŒåŽ‹¾~©ã€æ•´ç†ã€?br />-XX:+UseCMSCompactAtFullCollectionåQ𿉓开坹年è€ä»£çš„压¾~©ã€‚å¯èƒ½ä¼š(x¨¬)影哿€§èƒ½åQŒä½†æ˜¯å¯ä»¥æ¶ˆé™¤ç¢Žç‰?/li>
辅助信æ¯
JVMæä¾›äº?ji¨£n)大é‡å‘½ä»¤è¡Œå‚æ•°åQŒæ‰“åîC¿¡æ¯ï¼Œä¾›è°ƒè¯•ä‹Éç”¨ã€‚ä¸»è¦æœ‰ä»¥ä¸‹ä¸€äº›ï¼š(x¨¬)
- -XX:+PrintGC
输出形å¼åQš[GC 118250K->113543K(130112K), 0.0094143 secs]
[Full GC 121376K->10414K(130112K), 0.0650971 secs]
- -XX:+PrintGCDetails
输出形å¼åQš[GC [DefNew: 8614K->781K(9088K), 0.0123035 secs] 118250K->113543K(130112K), 0.0124633 secs]
[GC [DefNew: 8614K->8614K(9088K), 0.0000665 secs][Tenured: 112761K->10414K(121024K), 0.0433488 secs] 121376K->10414K(130112K), 0.0436268 secs]
- -XX:+PrintGCTimeStamps -XX:+PrintGCåQšPrintGCTimeStampså¯ä¸Žä¸Šé¢ä¸¤ä¸ªæ··åˆä½¿ç”¨
输出形å¼åQ?strong>11.851: [GC 98328K->93620K(130112K), 0.0082960 secs]
- -XX:+PrintGCApplicationConcurrentTime:æ‰“å°æ¯æ¬¡åžƒåœ¾å›žæ”¶å‰ï¼Œ½E‹åºæœªä¸æ–的执行旉™—´ã€‚å¯ä¸Žä¸Šé¢æØœåˆä‹Éç”?br />输出形å¼åQ?strong>Application time: 0.5291524 seconds
- -XX:+PrintGCApplicationStoppedTimeåQ𿉓å°åžƒåœ‘Ö›žæ”¶æœŸé—´ç¨‹åºæš‚åœçš„æ—‰™—´ã€‚å¯ä¸Žä¸Šé¢æØœåˆä‹Éç”?br />输出形å¼åQ?strong>Total time for which application threads were stopped: 0.0468229 seconds
- -XX:PrintHeapAtGC:打å°GCå‰åŽçš„详¾l†å †æ ˆä¿¡æ?br />输出形å¼åQ?br />34.702: [GC {Heap before gc invocations=7:
def new generation total 55296K, used 52568K [0x1ebd0000, 0x227d0000, 0x227d0000)
eden space 49152K, 99% used [0x1ebd0000, 0x21bce430, 0x21bd0000)
from space 6144K, 55% used [0x221d0000, 0x22527e10, 0x227d0000)
to space 6144K, 0% used [0x21bd0000, 0x21bd0000, 0x221d0000)
tenured generation total 69632K, used 2696K [0x227d0000, 0x26bd0000, 0x26bd0000)
the space 69632K, 3% used [0x227d0000, 0x22a720f8, 0x22a72200, 0x26bd0000)
compacting perm gen total 8192K, used 2898K [0x26bd0000, 0x273d0000, 0x2abd0000)
the space 8192K, 35% used [0x26bd0000, 0x26ea4ba8, 0x26ea4c00, 0x273d0000)
ro space 8192K, 66% used [0x2abd0000, 0x2b12bcc0, 0x2b12be00, 0x2b3d0000)
rw space 12288K, 46% used [0x2b3d0000, 0x2b972060, 0x2b972200, 0x2bfd0000)
34.735: [DefNew: 52568K->3433K(55296K), 0.0072126 secs] 55264K->6615K(124928K)Heap after gc invocations=8:
def new generation total 55296K, used 3433K [0x1ebd0000, 0x227d0000, 0x227d0000)
eden space 49152K, 0% used [0x1ebd0000, 0x1ebd0000, 0x21bd0000)
from space 6144K, 55% used [0x21bd0000, 0x21f2a5e8, 0x221d0000)
to space 6144K, 0% used [0x221d0000, 0x221d0000, 0x227d0000)
tenured generation total 69632K, used 3182K [0x227d0000, 0x26bd0000, 0x26bd0000)
the space 69632K, 4% used [0x227d0000, 0x22aeb958, 0x22aeba00, 0x26bd0000)
compacting perm gen total 8192K, used 2898K [0x26bd0000, 0x273d0000, 0x2abd0000)
the space 8192K, 35% used [0x26bd0000, 0x26ea4ba8, 0x26ea4c00, 0x273d0000)
ro space 8192K, 66% used [0x2abd0000, 0x2b12bcc0, 0x2b12be00, 0x2b3d0000)
rw space 12288K, 46% used [0x2b3d0000, 0x2b972060, 0x2b972200, 0x2bfd0000)
}
, 0.0757599 secs] - -Xloggc:filename:与上é¢å‡ 个é…åˆä‹É用,把相å…Ïx—¥å¿—ä¿¡æ¯è®°å½•到文äšg以便分æžã€?/li>
常è§é…置汇æ€?/strong>
- å †è®¾¾|?
- -Xms:åˆå§‹å †å¤§ž®?
- -Xmx:æœ€å¤§å †å¤§å°
- -XX:NewSize=n:讄¡½®òq´è½»ä»£å¤§ž®?
- -XX:NewRatio=n:讄¡½®òq´è½»ä»£å’Œòq´è€ä»£çš„æ¯”倹{€‚如:ä¸?åQŒè¡¨½Cºå¹´è½ÖM»£ä¸Žå¹´è€ä»£æ¯”å€égØ“(f¨´)1åQ?åQŒå¹´è½ÖM»£å 整个年è½ÖM»£òq´è€ä»£å’Œçš„1/4
- -XX:SurvivorRatio=n:òq´è½»ä»£ä¸EdenåŒÞZ¸Žä¸¤ä¸ªSurvivor区的比倹{€‚注æ„Survivor区有两个。如åQ?åQŒè¡¨½CºEdenåQšSurvivor=3åQ?åQŒä¸€ä¸ªSurvivoråŒºå æ•´ä¸ªòq´è½»ä»£çš„1/5
- -XX:MaxPermSize=n:讄¡½®æŒä¹…代大ž®?/li>
攉™›†å™¨è®¾¾|?
- -XX:+UseSerialGC:讄¡½®ä¸²è¡Œæ”‰™›†å™?
- -XX:+UseParallelGC:讄¡½®òq¶è¡Œæ”‰™›†å™?
- -XX:+UseParalledlOldGC:讄¡½®òq¶è¡Œòq´è€ä»£æ”‰™›†å™?
- -XX:+UseConcMarkSweepGC:讄¡½®òq¶å‘攉™›†å™?/li>
垃圾回收¾lŸè®¡ä¿¡æ¯
- -XX:+PrintGC
- -XX:+PrintGCDetails
- -XX:+PrintGCTimeStamps
- -Xloggc:filename
òq¶è¡Œæ”‰™›†å™¨è®¾¾|?
- -XX:ParallelGCThreads=n:讄¡½®òq¶è¡Œæ”‰™›†å™¨æ”¶é›†æ—¶ä½¿ç”¨çš„CPUæ•°ã€‚åÆˆè¡Œæ”¶é›†çº¿½E‹æ•°ã€?
- -XX:MaxGCPauseMillis=n:讄¡½®òq¶è¡Œæ”‰™›†æœ€å¤§æš‚åœæ—¶é—?
- -XX:GCTimeRatio=n:讄¡½®åžƒåœ¾å›žæ”¶æ—‰™—´å 程åºè¿è¡Œæ—¶é—´çš„癑ֈ†æ¯”。公å¼äØ“(f¨´)1/(1+n)
òq¶å‘攉™›†å™¨è®¾¾|?
- -XX:+CMSIncrementalMode:讄¡½®ä¸ºå¢žé‡æ¨¡å¼ã€‚适用于å•CPU情况ã€?
- -XX:ParallelGCThreads=n:讄¡½®òq¶å‘攉™›†å™¨å¹´è½ÖM»£æ”‰™›†æ–¹å¼ä¸ºåƈ行收集时åQŒä‹É用的CPUæ•°ã€‚åÆˆè¡Œæ”¶é›†çº¿½E‹æ•°ã€?/li>
å››ã€è°ƒä¼˜æ€È»“
- òq´è½»ä»£å¤§ž®é€‰æ‹©
- å“应旉™—´ä¼˜å…ˆçš„应ç”?/strong>åQ?strong>ž®½å¯èƒ½è®¾å¤§ï¼Œç›´åˆ°æŽ¥è¿‘¾pÈ»Ÿçš„æœ€ä½Žå“应时间é™åˆ?/strong>åQˆæ ¹æ®å®žé™…情况选择åQ‰ã€‚在æ¤ç§æƒ…况下,òq´è½»ä»£æ”¶é›†å‘生的频率也是最ž®çš„ã€‚åŒæ—Óž¼Œå‡å°‘到达òq´è€ä»£çš„对象ã€?
- åžåé‡ä¼˜å…ˆçš„应用åQšå°½å¯èƒ½çš„设¾|®å¤§åQŒå¯èƒ½åˆ°è¾¾Gbitçš„ç¨‹åº¦ã€‚å› ä¸ºå¯¹å“应旉™—´æ²¡æœ‰è¦æ±‚åQŒåžƒåœ¾æ”¶é›†å¯ä»¥åƈ行进行,一般适åˆ8CPU以上的应用ã€?/li>
- òq´è€ä»£å¤§å°é€‰æ‹©
- å“应旉™—´ä¼˜å…ˆçš„应ç”?/strong>åQšå¹´è€ä»£ä½¿ç”¨òq¶å‘攉™›†å™¨ï¼Œæ‰€ä»¥å…¶å¤§å°éœ€è¦å°å¿?j¨©)设¾|®ï¼Œä¸€èˆ¬è¦è€ƒè™‘òq¶å‘ä¼?x¨¬)è¯ç?/strong>å’?strong>ä¼?x¨¬)è¯æŒç®‹æ—‰™—?/strong>½{‰ä¸€äº›å‚æ•°ã€‚å¦‚æžœå †è®„¡½®ž®äº†(ji¨£n)åQŒå¯ä»¥ä¼š(x¨¬)é€ æˆå†…嘼„Žç‰‡ã€é«˜å›žæ”¶é¢‘率以åŠ(qi¨¢ng)应用暂åœè€Œä‹Éç”¨ä¼ ¾lŸçš„æ ‡è®°æ¸…除方å¼åQ›å¦‚æžœå †å¤§äº†(ji¨£n)åQŒåˆ™éœ€è¦è¾ƒé•¿çš„æ”‰™›†æ—‰™—´ã€‚最优化的方案,一般需è¦å‚考以下数æ®èŽ·å¾—ï¼š(x¨¬)
- òq¶å‘垃圾攉™›†ä¿¡æ¯
- æŒä¹…ä»£åÆˆå‘æ”¶é›†æ¬¡æ•?
- ä¼ ç»ŸGCä¿¡æ¯
- 花在òq´è½»ä»£å’Œòq´è€ä»£å›žæ”¶ä¸Šçš„æ—‰™—´æ¯”例
å‡å°‘òq´è½»ä»£å’Œòq´è€ä»£èŠÞp´¹çš„æ—¶é—ß_(d¨¢)¼Œä¸€èˆ¬ä¼š(x¨¬)æé«˜åº”用的效çŽ?/li>- åžåé‡ä¼˜å…ˆçš„应用åQšä¸€èˆ¬åžåé‡ä¼˜å…ˆçš„应用都有一个很大的òq´è½»ä»£å’Œä¸€ä¸ªè¾ƒ?y¨u)®çš„òq´è€ä»£ã€‚åŽŸå› æ˜¯åQŒè¿™æ ·å¯ä»¥å°½å¯èƒ½å›žæ”¶æŽ‰å¤§éƒ¨åˆ†çŸæœŸå¯¹è±¡åQŒå‡ž®‘䏿œŸçš„对象åQŒè€Œå¹´è€ä»£ž®½å˜æ”ùN•¿æœŸå˜?g¨°u)zÕd¯¹è±¡ã€?/li>
- 较å°å †å¼•èµïL(f¨¥ng)š„¼„Žç‰‡é—®é¢˜
å› äØ“(f¨´)òq´è€ä»£çš„åÆˆå‘æ”¶é›†å™¨ä½¿ç”¨æ ‡è®°ã€æ¸…除算法,所以ä¸ä¼?x¨¬)å¯¹å †è¿›è¡ŒåŽ‹¾~©ã€‚当攉™›†å™¨å›žæ”¶æ—¶åQŒä»–ä¼?x¨¬)把盔R‚»çš„空间进行åˆòqÓž¼Œ˜q™æ ·å¯ä»¥åˆ†é…¾l™è¾ƒå¤§çš„å¯¹è±¡ã€‚ä½†æ˜¯ï¼Œå½“å †½Iºé—´è¾ƒå°æ—Óž¼Œ˜q行一ŒD‰|—¶é—´ä»¥åŽï¼Œž®×ƒ¼š(x¨¬)出现“¼„Žç‰‡”åQŒå¦‚æžœåÆˆå‘æ”¶é›†å™¨æ‰¾ä¸åˆ°èƒö够的½Iºé—´åQŒé‚£ä¹ˆåÆˆå‘æ”¶é›†å™¨ž®†ä¼š(x¨¬)åœæ¢åQŒç„¶åŽä‹Éç”¨ä¼ ¾lŸçš„æ ‡è®°ã€æ¸…除方å¼è¿›è¡Œå›žæ”¶ã€‚如果出çŽ?#8220;¼„Žç‰‡”åQŒå¯èƒ½éœ€è¦è¿›è¡Œå¦‚下酾|®ï¼š(x¨¬)
- -XX:+UseCMSCompactAtFullCollectionåQšä‹Éç”¨åÆˆå‘æ”¶é›†å™¨æ—Óž¼Œå¼€å¯å¯¹òq´è€ä»£çš„压¾~©ã€?
- -XX:CMSFullGCsBeforeCompaction=0åQšä¸Šé¢é…¾|®å¼€å¯çš„æƒ…况下,˜q™é‡Œè®„¡½®å¤šå°‘‹Æ¡Full GCåŽï¼Œå¯¹å¹´è€ä»£˜q›è¡ŒåŽ‹ç¾ƒ
- jvm的内å˜é™åˆ?/li>
windows2003�612M
http://www.cnblogs.com/edwardlauxh/archive/2010/04/25/1918603.html
abin 2012-11-14 13:48 å‘表评论]]>JVM çŽ¯å¢ƒå‚æ•°é…ç½® http://www.aygfsteel.com/stevenjohn/archive/2012/11/14/391309.htmlabin abin Wed, 14 Nov 2012 05:40:00 GMT http://www.aygfsteel.com/stevenjohn/archive/2012/11/14/391309.html http://www.aygfsteel.com/stevenjohn/comments/391309.html http://www.aygfsteel.com/stevenjohn/archive/2012/11/14/391309.html#Feedback 0 http://www.aygfsteel.com/stevenjohn/comments/commentRss/391309.html http://www.aygfsteel.com/stevenjohn/services/trackbacks/391309.html 典型JVM傿•°è®„¡½®åQ?
java -Xmx3550m -Xms3550m -Xmn2g -Xss128k
-Xmx3550måQšè®¾¾|®JVM最大å¯ç”¨å†…å˜äØ“(f¨´)3550Mã€?
-Xms3550måQšè®¾¾|®JVMä¿?j¨©)ä‹É内å˜ä?550m。æ¤å€¼å¯ä»¥è®¾¾|®ä¸Ž-Xmx相åŒåQŒä»¥é¿å…æ¯æ¬¡åžƒåœ¾å›žæ”¶å®ŒæˆåŽJVM釿–°åˆ†é…内å˜ã€?
-Xmn2gåQšè®¾¾|®å¹´è½ÖM»£å¤§å°ä¸?Gã€‚æ•´ä¸ªå †å¤§å°=òq´è½»ä»£å¤§ž®?+ òq´è€ä»£å¤§å° + æŒä¹…代大ž®ã€‚æŒä¹…代一般固定大ž®äØ“(f¨´)64måQŒæ‰€ä»¥å¢žå¤§å¹´è½ÖM»£åŽï¼Œž®†ä¼š(x¨¬)å‡å°òq´è€ä»£å¤§å°ã€‚æ¤å€¼å¯¹¾pÈ»Ÿæ€§èƒ½å½±å“较大åQŒSun官方推èé…ç½®ä¸ºæ•´ä¸ªå †çš?/8ã€?
-Xss128kåQšè®¾¾|®æ¯ä¸ªçº¿½E‹çš„å †æ ˆå¤§å°ã€‚JDK5.0ä»¥åŽæ¯ä¸ª¾U¿ç¨‹å †æ ˆå¤§å°ä¸?MåQŒä»¥å‰æ¯ä¸ªçº¿½E‹å †æ ˆå¤§ž®äØ“(f¨´)256K。更具应用的¾U¿ç¨‹æ‰€éœ€å†…å˜å¤§å°˜q›è¡Œè°ƒæ•´ã€‚在相åŒç‰©ç†å†…å˜ä¸‹ï¼Œå‡å°˜q™ä¸ªå€ÆDƒ½ç”Ÿæˆæ›´å¤šçš„线½E‹ã€‚但是æ“作系¾lŸå¯¹ä¸€ä¸ªè¿›½E‹å†…的线½E‹æ•°˜q˜æ˜¯æœ‰é™åˆ¶çš„åQŒä¸èƒ½æ— é™ç”Ÿæˆï¼Œ¾l验值在3000~5000å·¦å³ã€?
java -Xmx3550m -Xms3550m -Xss128k -XX:NewRatio=4 -XX:SurvivorRatio=4 -XX:MaxPermSize=16m -XX:MaxTenuringThreshold=0
-XX:NewRatio=4:讄¡½®òq´è½»ä»£ï¼ˆåŒ…括Eden和两个Survivor区)(j¨ª)与年è€ä»£çš„æ¯”å€û|¼ˆé™¤åŽ»æŒä¹…代)(j¨ª)。设¾|®äØ“(f¨´)4åQŒåˆ™òq´è½»ä»£ä¸Žòq´è€ä»£æ‰€å 比å€égØ“(f¨´)1åQ?åQŒå¹´è½ÖM»£å æ•´ä¸ªå †æ ˆçš„1/5
-XX:SurvivorRatio=4åQšè®¾¾|®å¹´è½ÖM»£ä¸EdenåŒÞZ¸ŽSurvivoråŒºçš„å¤§å°æ¯”倹{€‚设¾|®äØ“(f¨´)4åQŒåˆ™ä¸¤ä¸ªSurvivoråŒÞZ¸Žä¸€ä¸ªEden区的比å€égØ“(f¨´)2:4åQŒä¸€ä¸ªSurvivoråŒºå æ•´ä¸ªòq´è½»ä»£çš„1/6
-XX:MaxPermSize=16m:讄¡½®æŒä¹…代大ž®äØ“(f¨´)16mã€?
-XX:MaxTenuringThreshold=0åQšè®¾¾|®åžƒåœ¾æœ€å¤§å¹´é¾„。如果设¾|®äØ“(f¨´)0çš„è¯åQŒåˆ™òq´è½»ä»£å¯¹è±¡ä¸¾l过Survivor区,直接˜q›å…¥òq´è€ä»£ã€‚对于年è€ä»£æ¯”较多的应用åQŒå¯ä»¥æé«˜æ•ˆçŽ‡ã€‚å¦‚æžœå°†æ¤å€ÆD®¾¾|®äØ“(f¨´)一个较大å€û|¼Œåˆ™å¹´è½ÖM»£å¯¹è±¡ä¼?x¨¬)在SurvivoråŒø™¿›è¡Œå¤š‹Æ¡å¤åˆÓž¼Œ˜q™æ ·å¯ä»¥å¢žåŠ å¯¹è±¡å†å¹´è½ÖM»£çš„å˜?g¨°u)zÀL—¶é—ß_(d¨¢)¼Œå¢žåŠ åœ¨å¹´è½ÖM»£åŒ™¢«å›žæ”¶çš„æ¦‚论ã€?/pre>
abin 2012-11-14 13:40 å‘表评论]]> 利用 Runtime 监控 Java ¾pÈ»Ÿèµ„æº http://www.aygfsteel.com/stevenjohn/archive/2012/11/14/391305.htmlabin abin Wed, 14 Nov 2012 05:01:00 GMT http://www.aygfsteel.com/stevenjohn/archive/2012/11/14/391305.html http://www.aygfsteel.com/stevenjohn/comments/391305.html http://www.aygfsteel.com/stevenjohn/archive/2012/11/14/391305.html#Feedback 0 http://www.aygfsteel.com/stevenjohn/comments/commentRss/391305.html http://www.aygfsteel.com/stevenjohn/services/trackbacks/391305.html 阅读全文
abin 2012-11-14 13:01 å‘表评论]]> Javaå†…å˜æº¢å‡º http://www.aygfsteel.com/stevenjohn/archive/2012/10/25/390240.htmlabin abin Thu, 25 Oct 2012 15:16:00 GMT http://www.aygfsteel.com/stevenjohn/archive/2012/10/25/390240.html http://www.aygfsteel.com/stevenjohn/comments/390240.html http://www.aygfsteel.com/stevenjohn/archive/2012/10/25/390240.html#Feedback 0 http://www.aygfsteel.com/stevenjohn/comments/commentRss/390240.html http://www.aygfsteel.com/stevenjohn/services/trackbacks/390240.html
å†…å˜æº¢å‡ºä¸Žæ•°æ®åº“é”表的问题,å¯ä»¥è¯´æ˜¯å¼€å‘äh员的噩梦åQŒä¸€èˆ¬çš„½E‹åºå¼‚常åQŒæ€ÀL˜¯å¯ä»¥çŸ¥é“在什么时候或是在什么æ“作æ¥éª¤ä¸Šå‡ºçްäº?ji¨£n)异常,而且æ ÒŽ(gu¨©)®å †æ ˆä¿¡æ¯ä¹Ÿå¾ˆå®ÒŽ(gu¨©)˜“定ä½åˆ°ç¨‹åºä¸æ˜¯æŸå¤„出çŽîCº†(ji¨£n)é—®é¢˜ã€‚å†…å˜æº¢å‡ÞZ¸Žé”表则ä¸ç„?d¨°ng)ž¼Œä¸€èˆ¬çŽ°è±¡æ˜¯æ“作一般时间厾pÈ»Ÿ‘Šæ¥‘Šæ…¢åQŒç›´åˆ°æ»æœºï¼Œä½†åƈä¸èƒ½æ˜Žç¡®æ˜¯åœ¨ä»€ä¹ˆæ“作上出现的,å‘生的时间点也没有规律,查看日志æˆ?span style="background-color: yellow; color: #ee6600" id="Mark">查看数æ®åº“也ä¸èƒ½å®šä½å‡ºé—®é¢˜çš„代ç ã€?/p>
更严é‡çš„æ˜¯å†…å˜æº¢å‡ÞZ¸Žæ•°æ®åº“é”表在¾pÈ»Ÿå¼€å‘å’Œå•å…ƒ‹¹‹è¯•阶段òq¶ä¸å®ÒŽ(gu¨©)˜“被å‘玎ͼŒå½“ç³»¾lŸæ£å¼ä¸Š¾U¿ä¸€èˆ¬æ—¶é—´åŽåQŒæ“作的òq¶å‘é‡ä¸Šæ¥äº†(ji¨£n)åQŒæ•°æ®ä¹Ÿ¿U¯ç¯äº?ji¨£n)一些,¾pÈ»Ÿž®±å®¹æ˜“å‡ºçŽ°å†…å˜æº¢å‡ºæˆ–是é”表的现象åQŒè€Œæ¤æ—¶ç³»¾lŸåˆä¸èƒ½éšæ„åœæœºæˆ–é‡å¯ï¼Œä¸ÞZ¿®æ£BUG带æ¥å¾ˆå¤§çš„å›°éš¾ã€?/p>
本文以笔者开å‘和支æŒçš„å¤šä¸ªé¡¹ç›®äØ“(f¨´)例,与大家分享在开å‘过½E‹ä¸é‡åˆ°çš„Javaå†…å˜æº¢å‡ºå’Œæ•°æ®åº“é”表的检‹¹‹å’Œå¤„ç†è§£å†³˜q‡ç¨‹ã€?/p>
2åQŽå†…å˜æº¢å‡ºçš„分æž
å†…å˜æº¢å‡ºæ˜¯æŒ‡åº”用¾pÈ»Ÿä¸å˜åœ¨æ— æ³•å›žæ”¶çš„å†…å˜æˆ–ä‹É用的内嘘q‡å¤šåQŒæœ€¾lˆä‹É得程åºè¿è¡Œè¦ç”¨åˆ°çš„内å˜å¤§äºŽè™šæ‹Ÿæœºèƒ½æä¾›çš„æœ€å¤§å†…å˜ã€‚䨓(f¨´)äº?ji¨£n)解决Javaä¸å†…å˜æº¢å‡ºé—®é¢˜ï¼Œæˆ‘们首先必须äº?ji¨£n)è§£Java是如何管ç†å†…å˜çš„。Java的内å˜ç®¡ç†å°±æ˜¯å¯¹è±¡çš„分é…和释æ”ùN—®é¢˜ã€‚在Javaä¸ï¼Œå†…å˜çš„åˆ†é…æ˜¯ç”Þq¨‹åºå®Œæˆçš„åQŒè€Œå†…å˜çš„释放是由垃圾攉™›†å™?Garbage CollectionåQŒGC)完æˆçš„,½E‹åºå‘˜ä¸éœ€è¦é€šè¿‡è°ƒç”¨GC函数æ¥é‡Šæ”‘Ö†…å˜ï¼Œå› 䨓(f¨´)ä¸åŒçš„JVM实现者å¯èƒ½ä‹É用ä¸åŒçš„½Ž—法½Ž¡ç†GCåQŒæœ‰çš„æ˜¯å†…å˜ä½¿ç”¨åˆ°è¾¾ä¸€å®šç¨‹åº¦æ—¶åQŒGCæ‰å¼€å§‹å·¥ä½œï¼Œä¹Ÿæœ‰å®šæ—¶æ‰§è¡Œçš„ï¼Œæœ‰çš„æ˜¯ä¸æ–弿‰§è¡ŒGC。但GCåªèƒ½å›žæ”¶æ— 用òq¶ä¸”ä¸å†è¢«å…¶å®ƒå¯¹è±¡å¼•用的那些对象所å 用的空间。Java的内å˜åžƒåœ‘Ö›žæ”¶æœºåˆ¶æ˜¯ä»Žç¨‹åºçš„主覘q行对象开始检查引用链åQŒå½“é历一éåŽå‘现没有被引用的å¤ç«‹å¯¹è±¡ž®×ƒ½œä¸ºåžƒåœ‘Ö›žæ”¶ã€?/p>
引è“vå†…å˜æº¢å‡ºçš„åŽŸå› æœ‰å¾ˆå¤š¿U,常è§çš„æœ‰ä»¥ä¸‹å‡ ç§åQ?/p>
l 内å˜ä¸åŠ è½½çš„æ•°æ®é‡è¿‡äºŽåºžå¤§ï¼Œå¦‚一‹Æ¡ä»Žæ•°æ®åº“å–å‡?gu¨®)™¿‡å¤šæ•°æ®ï¼?/p>
l 集刾cÖM¸æœ‰å¯¹å¯¹è±¡çš„å¼•ç”¨ï¼Œä½¿ç”¨å®ŒåŽæœªæ¸…½Iºï¼Œä½¿å¾—JVMä¸èƒ½å›žæ”¶åQ?/p>
l 代ç ä¸å˜åœ¨æ»å¾ªçŽ¯æˆ–åó@环äñ”生过多é‡å¤çš„对象实体åQ?/p>
l 使用的第三方软äšgä¸çš„BUGåQ?/p>
l å¯åЍ傿•°å†…å˜å€ÆD®¾å®šçš„˜q‡å°åQ?/p>
3åQŽå†…å˜æº¢å‡ºçš„解决
å†…å˜æº¢å‡ºè™½ç„¶å¾ˆæ£˜æ‰‹ï¼Œä½†ä¹Ÿæœ‰ç›¸åº”的解决办法åQŒå¯ä»¥æŒ‰ç…§ä»Žæ˜“åˆ°éš¾ï¼Œä¸€æ¥æ¥çš„解冟ë€?/p>
½W¬ä¸€æ¥ï¼Œž®±æ˜¯ä¿®æ”¹JVMå¯åЍ傿•°åQŒç›´æŽ¥å¢žåР内å˜ã€‚这一点看上去ä¼ég¹Žå¾ˆç®€å•,但很å®ÒŽ(gu¨©)˜“被忽略。JVM默认å¯ä»¥ä½¿ç”¨çš„内å˜äØ“(f¨´)64MåQŒTomcat默认å¯ä»¥ä½¿ç”¨çš„内å˜äØ“(f¨´)128MBåQŒå¯¹äºŽç¨å¤æ‚一点的¾pÈ»Ÿž®×ƒ¼š(x¨¬)ä¸å¤Ÿç”¨ã€‚在æŸé¡¹ç›®ä¸åQŒå°±å› 䨓(f¨´)å¯åЍ傿•°ä½¿ç”¨çš„默认å€û|¼Œ¾l常æŠ?#8220;OutOfMemory”é”™è¯¯ã€‚å› æ¤ï¼Œ-XmsåQ?Xmx傿•°ä¸€å®šä¸è¦å¿˜è®°åŠ ã€?/p>
½W¬äºŒæ¥ï¼Œ‹‚€(g¨¨)查错误日志,查看“OutOfMemory”é”™è¯¯å‰æ˜¯å¦æœ‰å…¶å®ƒå¼‚常或错误。在一个项目ä¸åQŒä‹É用两个数æ®åº“˜qžæŽ¥åQŒå…¶ä¸ä¸“用于å‘é€çŸä¿¡çš„æ•°æ®åº“连接ä‹É用DBCP˜qžæŽ¥æ± 管ç†ï¼Œç”¨æˆ·ä¸ÞZ¸ž®†çŸä¿¡å‘出,有愞®†æ•°æ®åº“˜qžæŽ¥ç”¨æˆ·åæ”¹é”™ï¼Œä½¿å¾—æ—¥å¿—ä¸æœ‰è®¸å¤šæ•°æ®åº“连接异常的日志åQŒä¸€ŒD‰|—¶é—´åŽåQŒå°±å‡ºçް“OutOfMemory”错误。ç»åˆ†æžåQŒè¿™æ˜¯ç”±äºŽDBCP˜qžæŽ¥æ± BUG引è“v的,数æ®åº“连接ä¸ä¸ŠåŽåQŒæ²¡æœ‰å°†˜qžæŽ¥é‡Šæ”¾åQŒæœ€¾lˆä‹Éå¾—DBCPæŠ?#8220;OutOfMemory”错误。绘q‡ä¿®æ”ÒŽ(gu¨©)£¼‹®æ•°æ®åº“˜qžæŽ¥å‚æ•°åŽï¼Œž®±æ²¡æœ‰å†å‡ºçŽ°å†…å˜æº¢å‡ºçš„错误ã€?/p>
查看日志对于分æžå†…å˜æº¢å‡ºæ˜¯éžå¸”R‡è¦çš„åQŒé€šè¿‡ä»”细查看日志åQŒåˆ†æžå†…å˜æº¢å‡ºå‰åšè¿‡å“ªäº›æ“作åQŒå¯ä»¥å¤§è‡´å®šä½æœ‰é—®é¢˜çš„æ¨¡å—ã€?/p>
½W¬ä¸‰æ¥ï¼Œå®‰æŽ’有ç»éªŒçš„¾~–程人员对代ç 进行走查和分æžåQŒæ‰¾å‡ºå¯èƒ½å‘ç”Ÿå†…å˜æº¢å‡ºçš„ä½ç½®ã€‚é‡ç‚ÒŽ(gu¨©)Ž’æŸ¥ä»¥ä¸‹å‡ ç‚¹ï¼š(x¨¬)
l ‹‚€(g¨¨)查代ç 䏿˜¯å¦æœ‰æ»å¾ªçŽ¯æˆ–é€’å½’è°ƒç”¨ã€?/p>
l ‹‚€(g¨¨)æŸ¥æ˜¯å¦æœ‰å¤§åó@环é‡å¤äñ”生新对象实体ã€?/p>
l ‹‚€(g¨¨)查对数æ®åº“查询ä¸åQŒæ˜¯å¦æœ‰ä¸€‹Æ¡èŽ·å¾—å…¨éƒ¨æ•°æ®çš„æŸ¥è¯¢ã€‚一般æ¥è¯ß_(d¨¢)¼Œå¦‚果一‹Æ¡å–å万æ¡è®°å½•到内å˜åQŒå°±å¯èƒ½å¼•è“vå†…å˜æº¢å‡ºã€‚这个问题比较éšè”½ï¼Œåœ¨ä¸Š¾U¿å‰åQŒæ•°æ®åº“䏿•°æ®è¾ƒ?y¨u)®‘,ä¸å®¹æ˜“出问题åQŒä¸Š¾U¿åŽåQŒæ•°æ®åº“䏿•°æ®å¤šäº?ji¨£n),一‹Æ¡æŸ¥è¯¢å°±æœ‰å¯èƒ½å¼•èµ·å†…å˜æº¢å‡ºã€‚å› æ¤å¯¹äºŽæ•°æ®åº“查询ž®½é‡é‡‡ç”¨åˆ†é¡µçš„æ–¹å¼æŸ¥è¯¢ã€?/p>
l ‹‚€(g¨¨)查Listã€MAP½{‰é›†åˆå¯¹è±¡æ˜¯å¦æœ‰ä½¿ç”¨å®ŒåŽåQŒæœªæ¸…除的问题。Listã€MAP½{‰é›†åˆå¯¹è±¡ä¼š(x¨¬)å§‹ç»ˆå˜æœ‰å¯¹å¯¹è±¡çš„引用åQŒä‹É得这些对象ä¸èƒ½è¢«GC回收ã€?/p>
½W¬å››æ¥ï¼Œä½¿ç”¨å†…å˜æŸ¥çœ‹å·¥å…·åЍæ€?span style="background-color: yellow; color: #ee6600" id="Mark">查看内å˜ä½¿ç”¨æƒ…况。æŸä¸ªé¡¹ç›®ä¸Š¾U¿åŽåQŒæ¯‹Æ¡ç³»¾lŸå¯åЍ䏤天åŽåQŒå°±ä¼?x¨¬)å‡ºçŽ°å†…å˜æº¢å‡ºçš„错误。这¿U情况一般是代ç ä¸å‡ºçŽîCº†(ji¨£n)¾~“æ…¢çš„å†…å˜æ³„æ¼ï¼Œç”¨ä¸Šé¢ä¸‰ä¸ªæ¥éª¤è§£å†³ä¸äº?ji¨£n),˜q™å°±éœ€è¦ä‹É用内å?span style="background-color: yellow; color: #ee6600" id="Mark">查看工具äº?ji¨£n)ã€?/p>
å†…å˜æŸ¥çœ‹å·¥å…·æœ‰è®¸å¤šï¼Œæ¯”较有å的有åQšOptimizeit Profilerã€JProbe Profilerã€JinSightå’ŒJava1.5çš„Jconsole½{‰ã€‚它们的基本工作原ç†å¤§åŒž®å¼‚åQŒéƒ½æ˜¯ç›‘‹¹‹Java½E‹åº˜q行时所有对象的甌™¯·ã€é‡Šæ”„¡‰åŠ¨ä½œåQŒå°†å†…å˜½Ž¡ç†çš„æ‰€æœ‰ä¿¡æ¯è¿›è¡Œç»Ÿè®¡ã€åˆ†æžã€å¯è§†åŒ–。开å‘äh员å¯ä»¥æ ¹æ®è¿™äº›ä¿¡æ¯åˆ¤æ–ç¨‹åºæ˜¯å¦æœ‰å†…å˜æ³„æ¼é—®é¢˜ã€‚一般æ¥è¯ß_(d¨¢)¼Œä¸€ä¸ªæ£å¸¸çš„¾pÈ»Ÿåœ¨å…¶å¯åŠ¨å®ŒæˆåŽå…¶å†…å˜çš„å ç”¨é‡æ˜¯åŸºæœ¬ç¨³å®šçš„åQŒè€Œä¸åº”è¯¥æ˜¯æ— é™åˆ¶çš„增长的。挾l地观察¾pÈ»Ÿ˜q行时ä‹É用的内å˜çš„大ž®ï¼Œå¯ä»¥çœ‹åˆ°åœ¨å†…å˜ä‹É用监控窗å£ä¸æ˜¯åŸºæœ¬è§„则的锯é‹É形的囄¡º¿åQŒå¦‚果内å˜çš„大尿Œç®‹åœ°å¢žé•¿ï¼Œåˆ™è¯´æ˜Žç³»¾lŸå˜åœ¨å†…å˜æ³„æ¼é—®é¢˜ã€‚通过间隔一ŒD‰|—¶é—´å–一‹Æ¡å†…å˜å¿«ç…§ï¼Œç„¶åŽå¯¹å†…å˜å¿«ç…§ä¸å¯¹è±¡çš„ä‹É用与引用½{‰ä¿¡æ¯è¿›è¡Œæ¯”对与分æžåQŒå¯ä»¥æ‰¾å‡ºæ˜¯å“ªä¸ª¾cÈš„对象在泄æ¼ã€?/p>
通过以上四个æ¥éª¤çš„分æžä¸Žå¤„ç†åQŒåŸºæœ¬èƒ½å¤„ç†å†…å˜æº¢å‡ºçš„问题。当ç„?d¨°ng)ž¼Œåœ¨è¿™äº›è¿‡½E‹ä¸ä¹Ÿéœ€è¦ç›¸å½“çš„¾léªŒä¸Žæ•æ„Ÿåº¦åQŒéœ€è¦åœ¨å®žé™…的开å‘与调试˜q‡ç¨‹ä¸ä¸æ–积累ã€?/p>
æ€ÖM½“上æ¥è¯ß_(d¨¢)¼Œäº§ç”Ÿå†…å˜æº¢å‡ºæ˜¯ç”±äºŽä»£ç 写的ä¸å¥½é€ æˆçš„ï¼Œå› æ¤æé«˜ä»£ç çš„è´¨é‡æ˜¯æœ€æ ÒŽ(gu¨©)œ¬çš„解军_Šžæ³•ã€‚æœ‰çš„ähè®¤äØ“(f¨´)先把功能实现åQŒæœ‰BUGæ—¶å†åœ¨æµ‹è¯•阶ŒDµè¿›è¡Œä¿®æ£ï¼Œ˜q™ç§æƒÏx³•是错误的。æ£å¦‚一件äñ”å“çš„è´¨é‡æ˜¯åœ¨ç”Ÿäñ”刉™€ çš„˜q‡ç¨‹ä¸å†³å®šçš„åQŒè€Œä¸æ˜¯è´¨é‡æ£€‹¹‹æ—¶å†›_®šçš„,软äšg的质é‡åœ¨è®¾è®¡ä¸Žç¼–ç 阶ŒDµå°±å·²ç»å†›_®šäº?ji¨£n),‹¹‹è¯•åªæ˜¯å¯¹èÊYä»¶è´¨é‡çš„一个验è¯ï¼Œå› 䨓(f¨´)‹¹‹è¯•ä¸å¯èƒ½æ‰¾å‡?gu¨®)™ÊY件䏿‰€æœ‰çš„BUGã€?/p>
--------------------------------------------------------------------------------------------------------------------------------
åŽŸå› æœ‰å¾ˆå¤šç§åQŒæ¯”如:(x¨¬)
1.æ•°æ®é‡è¿‡äºŽåºžå¤§ï¼›æÕdó@çŽ?åQ›é™(r¨´n)æ€å˜é‡å’Œé?r¨´n)æ€æ–¹æ³•过多;递归åQ›æ— 法确定是å¦è¢«å¼•用的对象;
2.虚拟æœÞZ¸å›žæ”¶å†…å˜åQˆå†…å˜æ³„æ¼ï¼‰(j¨ª)åQ?/p>
说白äº?ji¨£n)就是程åºè¿è¡Œè¦ç”¨åˆ°çš„内å˜å¤§äºŽè™šæ‹Ÿæœºèƒ½æä¾›çš„æœ€å¤§å†…å˜å°±å‘ç”Ÿå†…å˜æº¢å‡ºäº?ji¨£n)ã€?å†…å˜æº¢å‡ºçš„问题è¦çœ‹ä¸šåŠ¡å’Œ¾pÈ»Ÿå¤§å°è€Œå®šåQŒå¯¹äºŽæŸäº›ç³»¾lŸå¯èƒ½å†…å˜æº¢å‡ÞZ¸å¸¸è§åQŒä½†æŸäº›¾pÈ»Ÿ˜q˜æ˜¯å¾ˆå¸¸è§çš„解决的方法,
一个是优化½E‹åºä»£ç åQŒå¦‚æžœä¸šåŠ¡åºžå¤§ï¼Œé€»è¾‘å¤æ‚åQŒå°½é‡å‡ž®‘全局å˜é‡çš„引用,让程åºä‹É用完å˜é‡çš„æ—¶å€™é‡Šæ”¾è¯¥å¼•用能够让垃圑֛žæ”¶å™¨å›žæ”¶åQŒé‡Šæ”¾èµ„æºã€?br />二就是物ç†è§£å†»I¼Œå¢žå¤§ç‰©ç†å†…å˜åQŒç„¶åŽé€šè¿‡åQ?Xms256m -Xmx256m -XX:MaxNewSize=256m -XX:MaxPermSize=256m的修æ”?/p>
一ã€å†…å˜æº¢å‡ºç±»åž?/font>
1 �java.lang.OutOfMemoryError: PermGen space
JVM ½Ž¡ç†ä¸¤ç§¾cÕdž‹çš„内å˜ï¼Œå †å’Œéžå †ã€‚å †æ˜¯ç»™å¼€å‘äh员用的上é¢è¯´çš„就是,是在 JVM å¯åŠ¨æ—¶åˆ›å»ºï¼›éžå †æ˜¯ç•™¾l?JVM 自己用的åQŒç”¨æ¥å˜æ”„¡±»çš„ä¿¡æ¯çš„ã€‚å®ƒå’Œå †ä¸åŒåQŒè¿è¡ŒæœŸå†?GC ä¸ä¼š(x¨¬)释放½Iºé—´ã€‚如æž?web app 用了(ji¨£n)大é‡çš„第三方 jar 或者应用有太多çš?class æ–‡äšg而æ°å¥?MaxPermSize 讄¡½®è¾ƒå°åQŒè¶…å‡ÞZº†(ji¨£n)也会(x¨¬)坯D‡´˜q™å—内å˜çš„å ç”¨è¿‡å¤šé€ æˆæº¢å‡ºåQŒæˆ–è€?tomcat çƒéƒ¨¾|²æ—¶ä¾¯ä¸ä¼?x¨¬)清ç†å‰é¢åŠ è½½çš„çŽ¯å¢ƒåQŒåªä¼?x¨¬)å°?context 更改为新部çÖv的,éžå †å˜çš„内容ž®×ƒ¼š(x¨¬)‘Šæ¥‘Šå¤šã€?/p>
2 �java.lang.OutOfMemoryError: Java heap space
½W¬ä¸€¿U情冉|˜¯ä¸ªè¡¥å……,主è¦å˜åœ¨é—®é¢˜ž®±æ˜¯å‡ºçŽ°åœ¨è¿™ä¸ªæƒ…å†µä¸ã€‚其默认½Iºé—´ ( å?-Xms) 是物ç†å†…å˜çš„ 1/64 åQŒæœ€å¤§ç©ºé—?(-Xmx) 是物ç†å†…å˜çš„ 1/4 。如果内å˜å‰©ä½™ä¸åˆ?40 åQ…, JVM ž®×ƒ¼š(x¨¬)å¢žå¤§å †åˆ° Xmx 讄¡½®çš„å€û|¼Œå†…å˜å‰©ä½™‘…过 70 åQ…, JVM ž®×ƒ¼š(x¨¬)å‡å°å †åˆ° Xms 讄¡½®çš„倹{€‚所以æœåС噍çš?Xmx å’?Xms 讄¡½®ä¸€èˆ¬åº”该设¾|®ç›¸åŒé¿å…毋Æ?GC åŽéƒ½è¦è°ƒæ•´è™šæ‹Ÿæœºå †çš„大å°ã€‚å‡è®„¡‰©ç†å†…å˜æ— é™å¤§åQŒé‚£ä¹?JVM 内å˜çš„æœ€å¤§å€ÆD·Ÿæ“作¾pÈ»Ÿæœ‰å…³åQŒä¸€èˆ?32 使œºæ˜?1.5g åˆ?3g 之间åQŒè€?64 ä½çš„ž®×ƒ¸ä¼?x¨¬)有é™åˆ¶äº†(ji¨£n)ã€?/p>
注æ„åQšå¦‚æž?Xms ‘…过äº?Xmx å€û|¼Œæˆ–è€…å †æœ€å¤§å€¼å’Œéžå †æœ€å¤§å€¼çš„æ€Õd’Œ‘…过äº?ji¨£n)物ç†å†…å˜æˆ–者æ“作系¾lŸçš„æœ€å¤§é™åˆ‰™ƒ½ä¼?x¨¬)引èµähœåС噍å¯åЍä¸è“væ¥ã€?/p>
垃圾回收 GC 的角�/p>
JVM 调用 GC 的频度还是很高的åQŒä¸»è¦ä¸¤¿U情况下˜q›è¡Œåžƒåœ¾å›žæ”¶åQ?/p>
当应用程åºçº¿½E‹ç©ºé—ÔŒ¼›å¦ä¸€ä¸ªæ˜¯ java 内å˜å †ä¸‘Ïx—¶åQŒä¼š(x¨¬)䏿–调用 GC åQŒè‹¥˜qžç®‹å›žæ”¶éƒ½è§£å†³ä¸äº?ji¨£n)内å˜å †ä¸èƒö的问题时åQŒå°±ä¼?x¨¬)æŠ?out of memory é”™è¯¯ã€‚å› ä¸ø™¿™ä¸ªå¼‚å¸¸æ ¹æ®ç³»¾lŸè¿è¡ŒçŽ¯å¢ƒå†³å®šï¼Œæ‰€ä»¥æ— æ³•é¢„æœŸå®ƒä½•æ—¶å‡ºçŽ°ã€?/p>
æ ÒŽ(gu¨©)® GC 的机åˆÓž¼Œ½E‹åºçš„è¿è¡Œä¼š(x¨¬)引è“v¾pÈ»Ÿ˜q行环境的å˜åŒ–ï¼Œå¢žåŠ GC çš„è§¦å‘æœºä¼?x¨¬)ã€?/p>
ä¸ÞZº†(ji¨£n)é¿å…˜q™äº›é—®é¢˜åQŒç¨‹åºçš„设计和编写就应é¿å…垃圑֯¹è±¡çš„内å˜å 用å’?GC 的开销。显½Cø™°ƒç”?System.GC() åªèƒ½å»ø™®® JVM 需è¦åœ¨å†…å˜ä¸å¯¹åžƒåœ¾å¯¹è±¡˜q›è¡Œå›žæ”¶åQŒä½†ä¸æ˜¯å¿…须马上回收åQ?/p>
一个是òq¶ä¸èƒ½è§£å†›_†…å˜èµ„æºè€—空的局é¢ï¼Œå¦å¤–也会(x¨¬)å¢žåŠ GC 的消耗ã€?/p>
二ã€?JVM 内å˜åŒºåŸŸ¾l„æˆ
½Ž€å•çš„è¯?javaä¸çš„å †å’Œæ ?/p>
java把内å˜åˆ†ä¸¤ç§åQšä¸€¿Uæ˜¯æ ˆå†…å˜ï¼Œå¦ä¸€¿Uæ˜¯å †å†…å?/p>
1。在函数ä¸å®šä¹‰çš„基本¾cÕdž‹å˜é‡å’Œå¯¹è±¡çš„引用å˜é‡éƒ½åœ¨å‡½æ•°çš„æ ˆå†…å˜ä¸åˆ†é…ï¼›
2ã€‚å †å†…å˜ç”¨æ¥å˜æ”¾ç”?new创å¾çš„对象和数组
在函敎ͼˆä»£ç å—)(j¨ª)ä¸å®šä¹‰ä¸€ä¸ªå˜é‡æ—¶åQ?javaž®±åœ¨æ ˆä¸ä¸ø™¿™ä¸ªå˜é‡åˆ†é…内å˜ç©ºé—ß_(d¨¢)¼Œå½“è¶…˜q‡å˜é‡çš„作用域åŽåQ?javaä¼?x¨¬)è‡ªåŠ¨é‡Šæ”¾æŽ‰ä¸ø™¯¥å˜é‡æ‰€åˆ†é…的内å˜ç©ºé—ß_(d¨¢)¼›åœ¨å †ä¸åˆ†é…的内å˜ç”?javaè™šæ‹Ÿæœºçš„è‡ªåŠ¨åžƒåœ¾å›žæ”¶å™¨æ¥½Ž¡ç†
å †çš„ä¼˜åŠ¿æ˜¯å¯ä»¥åЍæ€åˆ†é…内å˜å¤§ž®ï¼Œç”Ÿå˜æœŸä¹Ÿä¸å¿…事先告诉¾~–è¯‘å™¨ï¼Œå› äØ“(f¨´)它是在è¿è¡Œæ—¶åЍæ€åˆ†é…内å˜çš„。缺点就是è¦åœ¨è¿è¡Œæ—¶åЍæ€åˆ†é…内å˜ï¼Œå˜å–速度较慢åQ?/p>
æ ˆçš„ä¼˜åŠ¿æ˜¯å˜å–é€Ÿåº¦æ¯”å †è¦å¿«åQŒç¼ºç‚ÒŽ(gu¨©)˜¯å˜åœ¨æ ˆä¸çš„æ•°æ®å¤§ž®ä¸Žç”Ÿå˜æœŸå¿…™åÀL˜¯¼‹®å®šçš„æ— ç‰|´» 性ã€?/p>
java å †åˆ†ä¸ÞZ¸‰ä¸ªåŒºåQ?New ã€?Old å’?Permanent
GC 有两个线½E‹ï¼š(x¨¬)
新创建的对象被分é…到 New åŒºï¼Œå½“è¯¥åŒø™¢«å¡«æ»¡æ—¶ä¼š(x¨¬)è¢?GC 辅助¾U¿ç¨‹¿UÕdˆ° Old 区,å½?Old åŒÞZ¹Ÿå¡«æ»¡äº?ji¨£n)ä¼?x¨¬)è§¦å‘ GC ä¸Èº¿½E‹éåŽ†å †å†…å˜é‡Œçš„æ‰€æœ‰å¯¹è±¡ã€?Old 区的大尽{‰äºŽ Xmx å‡åŽ» -Xmn
javaæ ˆå˜æ”?/p>
æ ˆè°ƒæ•ß_(d¨¢)¼š(x¨¬)傿•°æœ?+UseDefaultStackSize -Xss256KåQŒè¡¨½Cºæ¯ä¸ªçº¿½E‹å¯ç”Œ™¯· 256kçš„æ ˆ½Iºé—´
æ¯ä¸ª¾U¿ç¨‹éƒ½æœ‰ä»–自å·Þqš„ Stack
三ã€?JVM如何讄¡½®è™šæ‹Ÿå†…å˜
æç¤ºåQšåœ¨ JVMä¸å¦‚æž?98åQ…的旉™—´æ˜¯ç”¨äº?GC且å¯ç”¨çš„ Heap size ä¸èƒö 2åQ…的时候将抛出æ¤å¼‚叿€¿¡æ¯ã€?/p>
æç¤ºåQ?Heap Size 最大ä¸è¦è¶…˜q‡å¯ç”¨ç‰©ç†å†…å˜çš„ 80åQ…,一般的è¦å°† -Xmså’?-Xmx选项讄¡½®ä¸ºç›¸åŒï¼Œè€?-Xmnä¸?1/4çš?-Xmx倹{€?/p>
æç¤ºåQ?JVMåˆå§‹åˆ†é…的内å˜ç”± -Xms指定åQŒé»˜è®¤æ˜¯ç‰©ç†å†…å˜çš?1/64åQ?JVM最大分é…的内å˜ç”?-Xmx指定åQŒé»˜è®¤æ˜¯ç‰©ç†å†…å˜çš?1/4ã€?/p>
默认½IÞZ½™å †å†…å˜å°äº?40%æ—Óž¼Œ JVMž®×ƒ¼š(x¨¬)å¢žå¤§å †ç›´åˆ?-Xmx的最大é™åˆÓž¼›½IÞZ½™å †å†…å˜å¤§äº?70%æ—Óž¼Œ JVMä¼?x¨¬)凞®‘å †ç›´åˆ?-Xms的最ž®é™åˆ¶ã€‚å› æ¤æœåŠ¡å™¨ä¸€èˆ¬è®¾¾|?-Xmsã€?-Xmx相ç‰ä»¥é¿å…åœ¨æ¯æ¬¡ GC åŽè°ƒæ•´å †çš„大ž®ã€?/p>
æç¤ºåQšå‡è®„¡‰©ç†å†…å˜æ— é™å¤§çš„è¯åQ?JVM内å˜çš„æœ€å¤§å€ÆD·Ÿæ“作¾pÈ»Ÿæœ‰å¾ˆå¤§çš„关系ã€?/p>
½Ž€å•的说就 32ä½å¤„ç†å™¨è™½ç„¶å¯æŽ§å†…嘽Iºé—´æœ?4GB,但是具体的æ“作系¾lŸä¼š(x¨¬)¾l™ä¸€ä¸ªé™åˆÓž¼Œ
˜q™ä¸ªé™åˆ¶ä¸€èˆ¬æ˜¯ 2GB-3GBåQˆä¸€èˆ¬æ¥è¯?Windows¾pÈ»Ÿä¸‹äØ“(f¨´) 1.5G-2GåQ?Linux¾pÈ»Ÿä¸‹äØ“(f¨´) 2G-3GåQ‰ï¼Œ è€?64bit以上的处ç†å™¨ž®×ƒ¸ä¼?x¨¬)有é™åˆ¶ä?/p>
æç¤ºåQ𿳍æ„:(x¨¬)如果 Xms‘…过äº?Xmxå€û|¼Œæˆ–è€…å †æœ€å¤§å€¼å’Œéžå †æœ€å¤§å€¼çš„æ€Õd’Œ‘…过äº?ji¨£n)物ç†å†?å˜æˆ–者æ“作系¾lŸçš„æœ€å¤§é™åˆ‰™ƒ½ä¼?x¨¬)引èµähœåС噍å¯åЍä¸è“væ¥ã€?/p>
æç¤ºåQšè®¾¾|?NewSizeã€?MaxNewSize相ç‰åQ?“new”的大ž®æœ€å¥½ä¸è¦å¤§äº?“old”的一åŠï¼ŒåŽŸå› æ˜?old区如果ä¸å¤Ÿå¤§ä¼?x¨¬)频¾Jçš„è§¦å‘ “ä¸?” GC åQŒå¤§å¤§é™ä½Žäº†(ji¨£n)性能
JVM使用 -XX:PermSize讄¡½®éžå †å†…å˜åˆå§‹å€û|¼Œé»˜è®¤æ˜¯ç‰©ç†å†…å˜çš„ 1/64åQ?/p>
ç”?XX:MaxPermSize讄¡½®æœ€å¤§éžå †å†…å˜çš„大å°åQŒé»˜è®¤æ˜¯ç‰©ç†å†…å˜çš?1/4ã€?/p>
解决æ–ÒŽ(gu¨©)³•åQšæ‰‹åŠ¨è®¾¾|?Heap size
修改 TOMCAT_HOME/bin/catalina.bat
åœ?#8220; echo “Using CATALINA_BASE: $CATALINA_BASE””上é¢åŠ å…¥ä»¥ä¸‹è¡Œï¼š(x¨¬)
- JAVA_OPTS=”-server -Xms800m -Xmx800m -XX:MaxNewSize=256m”
å››ã€æ€§èƒ½‹‚€(g¨¨)查工具ä‹Éç”?/font>
定ä½å†…å˜æ³„æ¼åQ?/p>
JProfiler 工具主è¦ç”¨äºŽ‹‚€(g¨¨)查和跟踪¾pÈ»ŸåQˆé™äº?Java å¼€å‘çš„åQ‰çš„æ€§èƒ½ã€?JProfiler å¯ä»¥é€šè¿‡æ—¶æ—¶çš„监控系¾lŸçš„内å˜ä½¿ç”¨æƒ…况åQŒéšæ—¶ç›‘è§†åžƒåœ‘Ö›žæ”Óž¼Œ¾U¿ç¨‹˜q行状况½{‰æ‰‹ŒDµï¼Œä»Žè€Œå¾ˆå¥½çš„监视 JVM ˜q行情况å?qi¨¢ng)其性能ã€?/p>
1. 应用æœåС噍内å˜é•¿æœŸä¸åˆç†å 用åQŒå†…å˜ç»å¸¸å¤„于高ä½å 用,很难回收åˆîC½Žä½ï¼›
2. 应用æœåС噍æžä¸ÞZ¸½E›_®šåQŒå‡ 乎æ¯ä¸¤å¤©é‡æ–°å¯åЍ䏀‹Æ¡ï¼Œæœ‰æ—¶ç”šè‡³æ¯å¤©é‡æ–°å¯åЍ䏀‹Æ¡ï¼›
3. 应用æœåС噍ç»å¸¸åš Full GC(Garbage Collection)åQŒè€Œä¸”æ—‰™—´å¾ˆé•¿åQŒå¤§¾U¦éœ€è¦?30-40¿U’,应用æœåŠ¡å™¨åœ¨å?Full GC的时候是ä¸å“应客æˆïL(f¨¥ng)š„交易è¯äh±‚的,éžå¸¸å½±å“¾pÈ»Ÿæ€§èƒ½ã€?/p>
å› äØ“(f¨´)å¼€å‘环境和产å“环境ä¼?x¨¬)有ä¸åŒåQŒå¯¼è‡´è¯¥é—®é¢˜å‘生有时ä¼?x¨¬)在产å“环境ä¸å‘生ï¼?通常å¯ä»¥ä½¿ç”¨å·¥å…·è·Ÿè¸ª¾pÈ»Ÿçš„内å˜ä‹É用情况,在有些个别情况下或许æŸä¸ªæ—¶åˆ»¼‹®å®ž 是ä‹É用了(ji¨£n)大é‡å†…å˜å¯ÆD‡´ out of memoryåQŒè¿™æ—¶åº”¾l§ç®‹è·Ÿè¸ªçœ‹æŽ¥ä¸‹æ¥æ˜¯å¦ä¼?x¨¬)有下é™åQ?/p>
如果一直居高ä¸ä¸‹è¿™è‚¯å®šž®±å› 为程åºçš„åŽŸå› å¯ÆD‡´å†…å˜æ³„æ¼ã€?/p>
五ã€ä¸å¥å£®ä»£ç 的特å¾åŠ(qi¨¢ng)解决办法
1 ã€å°½æ—©é‡Šæ”¾æ— 用对象的引用。好的办法是使用临时å˜é‡çš„æ—¶å€™ï¼Œè®©å¼•用å˜é‡åœ¨é€€å‡ºæ´»åŠ¨åŸŸåŽï¼Œè‡ªåŠ¨è®„¡½®ä¸?null åQŒæš—½Cºåžƒåœ¾æ”¶é›†å™¨æ¥æ”¶é›†è¯¥å¯¹è±¡åQŒé˜²æ¢å‘ç”Ÿå†…å˜æ³„霌Ӏ?/p>
对于ä»ç„¶æœ‰æŒ‡é’ˆæŒ‡å‘的实例åQ?jvm ž®×ƒ¸ä¼?x¨¬)回收该资æº?, å› äØ“(f¨´)垃圾回收ä¼?x¨¬)å°†å€égØ“(f¨´) null 的对象作为垃圾,æé«˜ GC 回收机制效率åQ?/p>
2 ã€æˆ‘们的½E‹åºé‡Œä¸å¯é¿å…大é‡ä‹É用嗽W¦ä¸²å¤„ç†åQŒé¿å…ä‹Éç”?String åQŒåº”大é‡ä½¿ç”¨ StringBuffer åQŒæ¯ä¸€ä¸?String 对象都得独立å 用内å˜ä¸€å—区域;
- String str = “aaa”;
-
- String str2 = “bbb”;
-
- String str3 = str + str2;// å‡å¦‚æ‰§è¡Œæ¤æ¬¡ä¹‹åŽ str ,str2 以åŽå†ä¸è¢«è°ƒç”?, 那它?y¨u)®×ƒ¼?x¨¬)被放在内å˜ä¸½{‰å¾… Java çš?gc åŽÕd›žæ”?, ½E‹åºå†…过多的出现˜q™æ ·çš„æƒ…况就ä¼?x¨¬)报上é¢çš„那个错è?, 廸™®®åœ¨ä‹É用嗽W¦ä¸²æ—¶èƒ½ä½¿ç”¨ StringBuffer ž®×ƒ¸è¦ç”¨ String, ˜q™æ ·å¯ä»¥çœä¸ž®‘开销åQ?
3 ã€å°½é‡å°‘用é™(r¨´n)æ€å˜é‡ï¼Œå› 䨓(f¨´)é?r¨´n)æ€å˜é‡æ˜¯å…¨å±€çš„, GC ä¸ä¼š(x¨¬)回收的;
4 ã€é¿å…集ä¸åˆ›å»ºå¯¹è±¡å°¤å…¶æ˜¯å¤§å¯¹è±¡ï¼Œ JVM ä¼?x¨¬)çªç„‰™œ€è¦å¤§é‡å†…å˜ï¼Œ˜q™æ—¶å¿…ç„¶ä¼?x¨¬)触å?GC 优化¾pÈ»Ÿå†…å˜çŽ¯å¢ƒåQ›æ˜¾½Cºçš„声明数组½Iºé—´åQŒè€Œä¸”甌™¯·æ•°é‡˜q˜æžå¤§ã€?/p>
˜q™æ˜¯ä¸€ä¸ªæ¡ˆä¾‹æƒ³å®šä¾›å¤§å®¶è¦æˆ’:
使用jspsmartUpload作文件上ä¼?现在˜q行˜q‡ç¨‹ä¸ç»å¸¸å‡ºçްjava.outofMemoryError的错误,用top命ä×o(h¨´)看看˜q›ç¨‹ä½¿ç”¨æƒ…况åQŒå‘现内å˜ä¸‘?MåQŒèбäº?ji¨£n)很长时é—ß_(d¨¢)¼Œå‘现是jspsmartupload的问题。把jspsmartupload¾l„äšgçš„æºç æ–‡ä»Óž¼ˆclassæ–‡äšgåQ‰å¾~–译æˆJavaæ–‡äšgåQŒå¦‚梦方醒:(x¨¬)
- m_totalBytes = m_request.getContentLength();
- m_binArray = new byte[m_totalBytes];
å˜é‡m_totalBytesè¡¨ç¤ºç”¨æˆ·ä¸Šä¼ çš„æ–‡ä»¶çš„æ€»é•¿åº¦ï¼Œ˜q™æ˜¯ä¸€ä¸ªå¾ˆå¤§çš„æ•°ã€‚如果用˜q™æ ·å¤§çš„æ•°åŽ»å£°æ˜Žä¸€ä¸ªbyte数组åQŒåƈ¾l™æ•°¾l„çš„æ¯ä¸ªå…ƒç´ 分é…内嘽Iºé—´åQŒè€Œä¸”m_binArray数组ä¸èƒ½é©¬ä¸Šè¢«é‡Šæ”¾ï¼ŒJVM的垃圑֛žæ”¶ç¡®å®žæœ‰é—®é¢˜åQŒå¯¼è‡´çš„¾l“æžœž®±æ˜¯å†…å˜æº¢å‡ºã€?/p>
jspsmartUploadä¸ÞZ»€æœ«è¦˜q™æ ·ä½œï¼Œæœ‰ä»–çš„åŽŸå› ï¼Œæ ÒŽ(gu¨©)®RFC1867çš„httpä¸Šä¼ æ ‡å‡†åQŒå¾—åˆîC¸€ä¸ªæ–‡ä»¶æµåQŒåƈä¸çŸ¥é“文件æµçš„长度。设计者如果想文äšgçš„é•¿åº¦ï¼Œåªæœ‰æ“作servletinputstream一‹Æ¡æ‰çŸ¥é“åQŒå› ä¸ÞZ“Q何æµéƒ½ä¸çŸ¥é“大å°ã€‚åªæœ‰çŸ¥é“文仉™•¿åº¦äº†(ji¨£n)åQŒæ‰å¯ä»¥é™åˆ¶ç”¨æˆ·ä¸Šä¼ æ–‡äšgçš„é•¿åº¦ã€‚äØ“(f¨´)äº?ji¨£n)çœåŽ»è¿™ä¸ªéº»çƒ¦(ch¨³),jspsmartUpload设计者直接在内å˜ä¸æ‰“开文äšgåQŒåˆ¤æ–长度是å¦ç¬¦åˆæ ‡å‡†ï¼Œ½W¦åˆž®±å†™åˆ°æœåŠ¡å™¨çš„ç¡¬ç›˜ã€‚è¿™æ ·äñ”ç”Ÿå†…å˜æº¢å‡ºï¼Œ˜q™åªæ˜¯æˆ‘的一个猜‹¹‹è€Œå·²ã€?/p>
所以编½E‹çš„æ—¶å€™ï¼Œä¸è¦åœ¨å†…å˜ä¸ç”Œ™¯·å¤§çš„½Iºé—´åQŒå› 为webæœåŠ¡å™¨çš„å†…å˜æœ‰é™åQŒåƈ且尽å¯èƒ½çš„ä‹Éç”¨æµæ“作åQŒä¾‹å¦?/p>
- byte[] mFileBody = new byte[512];
- Blob vField= rs.getBlob("FileBody");
- InputStream instream=vField.getBinaryStream();
- FileOutputStream fos=new FileOutputStream(saveFilePath+CFILENAME);
- int b;
- while( (b =instream.read(mFileBody)) != -1){
- fos.write(mFileBody,0,b);
- }
- fos.close();
- instream.close();
5 ã€å°½é‡è¿ç”¨å¯¹è±¡æ± 技术以æé«˜¾pÈ»Ÿæ€§èƒ½åQ›ç”Ÿå‘½å‘¨æœŸé•¿çš„对象拥有生命周期çŸçš„对象时å®ÒŽ(gu¨©)˜“引å‘å†…å˜æ³„æ¼åQŒä¾‹å¦‚大集åˆå¯¹è±¡æ‹¥æœ‰å¤§æ•°æ®é‡çš„业务对象的时候,å¯ä»¥è€ƒè™‘分嗘q›è¡Œå¤„ç†åQŒç„¶åŽè§£å†³ä¸€å—释放一å—çš„½{–ç•¥ã€?/p>
6 ã€ä¸è¦åœ¨¾l常调用的方法ä¸åˆ›å¾å¯¹è±¡åQŒå°¤å…¶æ˜¯å¿Œè®³åœ¨åó@环ä¸åˆ›å¾å¯¹è±¡ã€‚å¯ä»¥é€‚当的ä‹Éç”?hashtable åQ?vector 创å¾ä¸€¾l„对象容器,然åŽä»Žå®¹å™¨ä¸åŽÕd–那些对象åQŒè€Œä¸ç”¨æ¯‹Æ?new 之åŽåˆä¸¢å¼?/p>
7 ã€ä¸€èˆ¬éƒ½æ˜¯å‘生在开å¯å¤§åž‹æ–‡ä»¶æˆ–è·Ÿæ•°æ®åº“一‹Æ¡æ‹¿äº?ji¨£n)太多的数æ®åQŒé€ æˆ Out Of Memory Error 的状况,˜q™æ—¶ž®±å¤§æ¦‚è¦è®¡ç®—一下数æ®é‡çš„æœ€å¤§å€¼æ˜¯å¤šå°‘åQŒåƈ且设定所需最ž®åŠ(qi¨¢ng)最大的内嘽Iºé—´å€¹{€?/p>

abin 2012-10-25 23:16 å‘表评论]]>
Ö÷Õ¾Ö©Öë³ØÄ£°å£º
÷ºÓ¿ÚÊÐ|
Àײ¨ÏØ|
ÒËÖÝÊÐ|
ÎÚÀÌØºóÆì|
ÐËÒµÏØ|
ÓÀÐÞÏØ|
°à¸êÏØ|
ÄÚ»ÆÏØ|
Îä´¨ÏØ|
¹«°²ÏØ|
̨½ÏØ|
µ±ÐÛÏØ|
¶¨½áÏØ|
¹ðƽÊÐ|
°×Ë®ÏØ|
ºÍÆ½ÏØ|
´ïÖÝÊÐ|
·À³Ç¸ÛÊÐ|
¶«°¢ÏØ|
»´±±ÊÐ|
¹âÔóÏØ|
½¡¿µ|
¸ßÌ¨ÏØ|
ÓݳÇÏØ|
Ðû³ÇÊÐ|
´ó³§|
ÃàÖñÊÐ|
ººÊÙÏØ|
ÅíÑôÏØ|
À¼¿¼ÏØ|
¿Ëʲ¿ËÌÚÆì|
ͨµÀ|
ºéÔóÏØ|
лͨÃÅÏØ|
ÕØ¶«ÊÐ|
ÄÏÆ½ÊÐ|
ÕòÔ¶ÏØ|
ÃûÉ½ÏØ|
±¦¼¦ÊÐ|
»ù¡ÊÐ|
ÆÑ³ÇÏØ|