˜q™ä¸ªåå—代表了异æ¥JavaScript+XMLHTTPRequeståQŒåƈ且æ„味ç€ä½ å¯ä»¥åœ¨åŸÞZºŽ‹¹è§ˆå™¨çš„JavaScriptå’ŒæœåŠ¡å™¨ä¹‹é—´å»ºç«‹å¥—æŽ¥å—通讯。其实AJAXòq¶ä¸æ˜¯ä¸€¿Uæ–°æŠ€æœ¯ï¼Œè€Œæ˜¯å·²ç»æˆåŠŸåœ°ç”¨äºŽçŽ°ä»£æµè§ˆå™¨ä¸çš„若干æˆåŠŸæŠ€æœ¯çš„å¯èƒ½æ€§ç»„åˆã€‚所有的AJAX应用½E‹åºå®žçŽ°äº†ä¸€¿U“丰富的â€UI——这是通过JavaScriptæ“作HTML文档对象模型òq¶ä¸”¾lç”±XMLHttpRequest实现的精¼‹®å®šä½çš„æ•°æ®‹‚€ç´¢æ¥å®žçŽ°çš„ã€‚å…¸åž‹çš„½CÞZ¾‹AJAX应用½E‹åºæ˜¯Google Labs(http://labs.google.com)çš„Google Mapså’ŒGoogle Suggest。这些应用程åºçŽ°åœºç›‘è§†ç”¨æˆ¯‚¾“å…¥åÆˆä¸”æä¾›å®žæ—¶çš„™åµé¢æ›´æ–°ã€‚最é‡è¦çš„æ˜¯åQŒåœ¨ç”¨æˆ·é€šè¿‡åœ°å›¾å¯ÆDˆªæˆ–输入一个查扑֗½W¦ä¸²çš„åŒæ—Óž¼Œ˜q™äº›äº‹äšgä¸éœ€è¦åˆ·æ–°é¡µé¢ã€?/FONT>
  事实上,支挘q™äº›ä»¤äh感到惊讶的应用的技术已¾l出çŽîC¸€ŒD‰|—¶é—´äº†åQŒå°½½Ž¡å®ƒä»¬è¦æ±‚夿‚的技能以åŠä‹É用æµè§ˆå™¨çš„æŠ€å·§ã€‚一些专利äñ”å“å°±æä¾›äº†ç›¸ä¼¼çš„能力——如Macromedia Flashæ’äšgåQŒJava Appletsæˆ?NET˜q行时——在辑ֈ°å®žç”¨ä¸Šå·²¾l有一ŒD‰|—¶é—´äº†ã€‚把一¿Uå¯ä¸ŽæœåŠ¡å™¨é€šè¯çš„脚本组件引入到‹¹è§ˆå™¨ä¸çš„æ€æƒ³æ—©åœ¨IE 5.0ä¸å°±å·²ç»å˜åœ¨ã€‚Firefox和其它æµè¡Œçš„‹¹è§ˆå™¨ä¹ŸåŠ å…¥åˆ°æµè§ˆå™¨å¤§å†›ä¸åƈ以一¿U内¾|®å¯¹è±¡åÅžå¼æ”¯æŒXMLHTTPRequest。éšç€è·¨åã^å°æµè§ˆå™¨çš„出玎ͼŒ˜q™äº›æŠ€æœ¯å¾—åˆîCº†è®¤å¯òq¶åœ¨2004òq?月一家称为Adaptive Pathçš„å…¬åæ€¸æ£å¼æå‡ºäº†AJAXã€?/FONT>
  ½Ž€è€Œè¨€ä¹‹ï¼Œç”׃ºŽæ¥è‡ªäºŽGoogle的支æŒå’Œå®‰è£…了一点å¯ç”¨çš„‹¹è§ˆå™¨æŠ€æœ¯ï¼ŒåŠ ä¸Šä¸ÞZº†ä¸€¿U?更好的用户体éª?åQŒæ¯ä¸ªäh都在把客æˆïL«¯æŠ€æœ¯æ·»åŠ åˆ°Web应用½E‹åºä¸Šã€?/FONT>
  äº? AJAXä¸Žä¼ ¾lŸåº”用程åºçš„区别
ã€€ã€€ä¸€ä¸ªä¼ ¾lŸWeb应用½E‹åºæ¨¡åž‹å®žé™…上是一¿U基本的事äšg——用戯‚¢«˜q«æäº¤è¡¨å•以实现™åµé¢äº¤æ¢ã€‚也ž®±æ˜¯è¯ß_¼Œè¡¨å•æäº¤å’Œé¡µé¢ä¼ 逿— 法得åˆîC¿è¯?˜q˜æœ‰æ›´å的情形——用户需è¦å†‹Æ¡ç‚¹å‡…R€‚这与AJAX截然ä¸åŒ-——数æ®è·¨˜q‡çº¿è·¯è€Œä¸æ˜¯å®Œæ•´çš„HTML™åµé¢ä¼ 输。这¿Uæ•°æ®äº¤æ¢æ˜¯¾l由特定的æµè§ˆå™¨å¯¹è±¡:XMLHttpRequest实现çš?å†ç”±é€‚当的逻辑æ¥å¤„ç†æ¯ä¸ªæ•°æ®è¯·æ±‚çš„¾l“æžœåQŒé¡µé¢çš„ç‰¹å®šåŒºåŸŸè€Œä¸æ˜¯å®Œæ•´çš„™åµé¢è¢«æ›´æ–°ã€‚结果是更快的速度åQŒæ›´ž®‘的拥挤和更好的信æ¯ä¼ é€æŽ§åˆ¶ã€?/FONT>
ã€€ã€€ä¼ ç»Ÿåž?click-refresh"Web应用½E‹åºå¼ø™¿«ç”¨æˆ·ä¸æ–工作˜q‡ç¨‹è€Œç‰å¾…页é¢çš„é‡è£…。通过引入AJAX技术,一个客æˆïL«¯è„šæœ¬èƒ½å¤Ÿå¼‚æ¥åœîC¸ŽæœåŠ¡å™¨é€šè¯åQŒè€Œç”¨æˆ·ä»èƒ½ä¿æŒè¾“入数æ®ã€‚é™¤äº†å¯¹ç”¨æˆ·é€æ˜Žä¹‹å¤–åQŒè¿™æ ïLš„å¼‚æ¥æ„å‘³ç€æœåС噍å¯ä»¥æœ‰æ›´å¤šæ—‰™—´æ¥å¤„ç†è¯·æ±‚ã€?/FONT>
ã€€ã€€ä¼ ç»ŸWeb应用½E‹åºæŠŠæ‰€æœ‰çš„处ç†ä»£ç†åˆ°æœåС噍òq¶ä¸”å¼ø™¿«æœåŠ¡å™¨è¿›è¡ŒçŠ¶æ€ç®¡ç†ã€‚AJAXå…许ç‰|´»åˆ’分应用½E‹åºé€»è¾‘以åŠå®¢æˆ·å’ŒæœåŠ¡å™¨ä¹‹é—´çš„çŠ¶æ€ç®¡ç†ã€‚è¿™ž®±æ¶ˆé™¤äº†ä¸€¿U?click-refresh"ä¾èµ–æ€§åÆˆä¸”æä¾›æ›´å¥½çš„æœåŠ¡å™¨å¯ä¼¸ç¾ƒæ€§ã€‚当该状æ€å˜å‚¨åœ¨å®¢æˆ·ç«¯ï¼Œä½ å°±ä¸å¿…跨越æœåŠ¡å™¨æ¥¾l´æŒä¼šè¯æˆ–ä¿å?¾l“æŸçжæ€?å…¶ä‹Éç”¨æœŸé™æ˜¯ç”±å®¢æˆïL«¯æ¥å®šä¹‰çš„ã€?/FONT>
  ä¸? AJAX——分布å¼çš„MVC
  ž®½ç®¡AJAX应用½E‹åºä¾é JavaScriptæ¥å®žçްæ˜q°å±‚åQŒç„¶è€Œå¤„ç†èƒ½åŠ›å’ŒçŸ¥è¯†åº“ä»ç„¶å˜åœ¨äºŽæœåŠ¡å™¨ä¸Šã€‚æ¤æ—Óž¼ŒAJAX应用½E‹åºå¤§é‡çš„与J2EEæœåŠ¡å™¨é€šè®¯â€”â€”æŠŠæ•°æ®è¾“å…¥/输出WebæœåŠ¡å’Œservlets。具有基于AJAXçš„æ˜q°å±‚çš„J2EE应用½E‹åºå’Œæ ‡å‡†J2EE应用½E‹åºä¹‹é—´çš„区别首先在于,MVC是通过¾U¿èµ\分布的。通过使用AJAXåQŒè§†å›¾æ˜¯æœ¬åœ°çš„,而模型和控制器是分布å¼çš„——这使得开å‘者能够絋zÕdœ°å†›_®šå“ªäº›éƒ¨äšg会是åŸÞZºŽå®¢æˆ·ç«¯çš„。具体地è¯ß_¼Œæœ¬åœ°è§†å›¾é€šè¿‡å·§å¦™åœ°æ“作HTML DOM而生æˆå›¾å½?控制器局部地处ç†ç”¨æˆ·è¾“å…¥òq¶ä¸”æ ÒŽ®å¼€å‘è€…çš„åˆ¤æ–æ‰©å±•到æœåŠ¡å™¨çš„å¤„ç†â€”—ç»ç”±HTTPè¯äh±‚(WebæœåŠ¡åQŒXML/RPC或其å®?实现;模型的远½E‹éƒ¨åˆ†æ˜¯æ ÒŽ®å®¢æˆ·ç«¯éœ€è¦è€Œä¸‹è½½çš„以达到实时更新客æˆïL«¯™åµé¢;òq¶ä¸”çŠ¶æ€æ˜¯åœ¨å®¢æˆïL«¯æ”‰™›†çš„ã€?/FONT>
  在以åŽçš„AJAXæ–‡ç« ä¸ï¼Œæˆ‘们ž®†æ¯”较深入地讨论˜q™é‡Œçš„æ¯ä¸€¿Uç»„ä»¶åÆˆæä¾›æœ‰å…³å®ƒä»¬è”åˆåœ¨ä¸€èµ¯‚¿›è¡Œåº”用的½CÞZ¾‹ã€‚现在,先ä¸å¤šè¯´åQŒè®©æˆ‘们详细地分æžä¸€ä¸ªç®€å•çš„AJAX½CÞZ¾‹ã€?/FONT>
  å›? é‚®æ”¿åŒºå·æ ¡éªŒå’ŒæŸ¥è¯?/STRONG>
  我们ž®†åˆ›å»ÞZ¸€ä¸ªåŒ…å«ä¸‰ä¸ªINPUTå—æ®µ(ZipåQŒCityå’ŒState)çš„HTML™åµé¢ã€‚我们将ä¿è¯åQŒåªè¦ç”¨æˆ¯‚¾“入邮政区åïLš„å‰ä¸‰ä¸ªæ•°å—,该页é¢ä¸Šçš„å—ŒDµå°±ä¼šç”¨½W¬ä¸€ä¸ªåŒ¹é…的状æ€å€¼å¡«å……。一旦用戯‚¾“入了所有五ä½é‚®æ”¿åŒºåäh•°åQŒæˆ‘们将立å³å†›_®šå’Œå¡«å……相应的城市。如果邮政区åäh— æ•?在æœåŠ¡å™¨çš„æ•°æ®åº“没有扑ֈ°)åQŒé‚£ä¹ˆæˆ‘们将把邮政区åïLš„边界讄¡½®ä¸ºçº¢è‰ŒÓ€‚è¿™æ ïLš„å¯è§†åŒ–线索有助于用户òq¶ä¸”在现代æµè§ˆå™¨ä¸å·²¾læˆä¸ÞZ¸€¿Uæ ‡å‡?ä½œäØ“ä¸€å®žä¾‹åQŒå½“Firefox扑ֈ°ä¸€ä¸ªHTML™åµé¢ä¸çš„匚w…关键嗿—¶åQŒå®ƒä¼šé«˜äº®ä¸Žä½ 在‹¹è§ˆå™¨æŸ¥æ‰‘ÖŸŸè¾“入的内容一致的部分)ã€?/FONT>
  让我们首先创å»ÞZ¸€ä¸ªç®€å•的包å«ä¸‰ä¸ªINPUTå—æ®µçš„HTML:zipåQŒcityå’Œstate。请注æ„åQŒä¸€æ—¦ä¸€ä¸ªå—½W¦è¾“入进邮政区å·å—段域ä¸åQŒå³è°ƒç”¨æ–ÒŽ³•zipChanged()。JavaScript函数zipChanged()(è§ä¸‹)在当zip长度ä¸?时调用函数updateState()åQŒè€Œåœ¨å½“zip长度ä¸?时调用函数up-dateCity()。而updateCity()å’ŒupdateState()把大部分的工作代ç†åˆ°å¦ä¸€ä¸ªå‡½æ•°ask()ã€?/FONT>
Zip:åQœinput id="zipcode" type="text" maxlength="5" onKeyUp="zipChanged()"
style="width:60"/åQ?BR>City: åQœinput id="city" disabled maxlength="32" style="width:160"/åQ?BR>State:åQœinput id="state" disabled maxlength="2" style="width:30"/åQ?BR>åQœscript src="xmlhttp.js"åQžï¼œ/scriptåQ?BR>åQœscriptåQ?BR>var zipField = null;
function zipChanged(){
zipField = document.getElementById("zipcode")
var zip = zipField.value;
zip.length == 3?updateState(zip):zip.length == 5?updateCity(zip):"";
}
function updateState(zip) {
 var stateField = document.getElementById("state");
 ask("resolveZip.jsp?lookupType=state&zip="+zipåQ?stateFieldåQ?zipField);
}
function updateCity(zip) {
 var cityField = document.getElementById("city");
 ask("resolveZip.jsp? lookupType=city&zip="+zipåQ?cityFieldåQ?zipField);
}
åQ?scriptåQ?BR>
函数ask()与æœåС噍˜q›è¡Œé€šè®¯òq¶åˆ†é…一个回调函数æ¥å¤„ç†æœåŠ¡å™¨çš„å“应(è§ä¸‹åˆ—代ç ?。åŽé¢ï¼Œæˆ‘们ž®†åˆ†æžå…·æœ‰åŒé‡ç‰¹ç‚¹çš„resolveZip.jsp的内å®?å®ƒæ ¹æ®zipå—æ®µä¸çš„å—符数查找city或stateä¿¡æ¯ã€‚é‡è¦çš„æ˜¯ï¼Œask()使用了具有异æ¥ç‰¹ç‚¹çš„XmlHttpRequeståQŒè¿™æ ·å¡«å……stateå’Œcityå—æ®µæˆ–ç€è‰²zipå—æ®µè¾¹ç•Œž®±å¯ä»¥ä¸å¿…凿…¢æ•°æ®å…¥å£è€Œå¾—以实现。首先,我们调用request.open()-它用æœåŠ¡å™¨æ‰“å¼€å¥—æŽ¥å—频é“,使用一个HTTP动è¯(GET或POST)ä½œäØ“½W¬ä¸€ä¸ªå‚æ•°åÆˆä¸”ä»¥æ•°æ®æä¾›è€…çš„URLä½œäØ“½W¬äºŒä¸ªå‚数。request.open()的最åŽä¸€ä¸ªå‚数被讄¡½®ä¸ºtrue-它指½Cø™¯¥è¯äh±‚的异æ¥ç‰¹æ€§ã€‚注æ„,该请求还没有被æäº¤ã€‚éšç€å¯¹request.send()的调用,开始æäº?˜q™å¯ä»¥äØ“POSTæä¾›ä»ÖM½•å¿…è¦çš„æœ‰æ•ˆè²è—÷€‚在使用异æ¥è¯äh±‚æ—Óž¼Œæˆ‘们必须使用request.onreadystatechanged属性æ¥åˆ†é…è¯äh±‚的回调函数ã€?如果è¯äh±‚æ˜¯åŒæ¥çš„è¯ï¼Œæˆ‘们应该能够在调用request.send之åŽç«‹å³å¤„熾l“æžœåQŒä½†æ˜¯æˆ‘们也有å¯èƒ½é˜»æ–ç”¨æˆøP¼Œç›´åˆ°è¯¥è¯·æ±‚完æˆäØ“æ¢ã€?
HTTPRequest = function () {
 var xmlhttp=null;
 try {
  xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
 } catch (_e) {
  try {
   xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
  } catch (_E) { }
 }
 if (!xmlhttp && typeof XMLHttpRequest != 'undefined') {
  try {
   xmlhttp = new XMLHttpRequest();
  } catch (e) {
   xmlhttp = false;
  }
 }
 return xmlhttp;
}
function ask(urlåQ?fieldToFillåQ?lookupField) {
 var http = new HTTPRequest();
 http.open("GET"åQ?urlåQ?true);
 http.onreadystatechange = function (){ handleHttpResponse(httpåQ?fieldToFillåQŒlookupField)};
 http.send(null);
}
function handleHttpResponse(httpåQ?fieldToFillåQ?lookupField) {
 if (http.readyState == 4) {
  result = http.responseText;
  if ( -1 != result.search("null") ) {
   lookupField.style.borderColor = "red";
   fieldToFill.value = "";
  } else {
   lookupField.style.borderColor = "";
   fieldToFill.value = result;
  }
 }
}
  为ask()所使用的HttpRequest()函数(è§ä¸Š)是一跨æµè§ˆå™¨çš„XMLHTTPRequestçš„ä¸€ä¸ªå®žä¾‹çš„æž„é€ å™¨;½EåŽæˆ‘们ž®†åˆ†æžå®ƒã€‚到目å‰ä¸ºæ¢åQŒè¯·æ³¨æ„对于handleResponse()的调用是如何用一匿å函数包装çš?˜q™ä¸ªå‡½æ•°æ˜¯function(){handleHttpResponse(httpåQŒfieldToFillåQ?lookupField)}ã€?/FONT>
ã€€ã€€è¯¥å‡½æ•°çš„ä»£ç æ˜¯åЍæ€åˆ›å»ºçš„òq¶ä¸”在毋ơ我们给http.onreadstatechange属性赋值时被编译。结果,JavaScript创å¾ä¸€ä¸ªæŒ‡å‘上下文(所有的å˜é‡éƒ½å¯ä»¥å˜å–æ£åœ¨ç»“æŸçš„æ–ÒŽ³•-ask())çš„æŒ‡é’ˆã€‚è¿™æ ·ä»¥æ¥ï¼ŒåŒ¿å函数和handleResponse()ž®Þpƒ½å¤Ÿè¢«ä¿è¯å……分å˜å–所有的上下文宿ä¸Èš„å˜é‡åQŒç›´è‡›_ˆ°åŒ¿å函数的å‚è€ƒè¢«åžƒåœ¾å›žæ”¶ç«™æ”¶é›†äØ“æ¢ã€‚æ¢å¥è¯è¯ß_¼Œæ— 论何时我们的匿å函数被调用åQŒå®ƒéƒ½èƒ½æ— ç¼åœ°å‚考requeståQŒfieldToFillå’ŒlookupFieldå˜é‡åQŒå°±è±¡å®ƒä»¬æ˜¯å…¨å±€çš„ä¸€æ —÷€‚而且åQŒæ¯‹Æ¡ask()调用都将创å¾çŽ¯å¢ƒçš„ä¸€ä¸ªç‹¬ç«‹æ‹·è´ï¼Œòq¶ä¸”æ¤æ—¶˜q™äº›å˜é‡ä¸ä¿å˜æœ‰è¯¥å‡½æ•°å°†¾l“æŸæ—¶çš„倹{€?/FONT>
  现在åQŒè®©æˆ‘们分æžä¸€ä¸‹å‡½æ•°handleResponse()。既然它能够在请求处ç†çš„ä¸åŒçжæ€ä¸‹‹È€‹z»ï¼Œé‚£ä¹ˆè¯¥å‡½æ•°å°†å¿½ç•¥æ‰€æœ‰çš„æƒ…åÅž-除了该请求处ç†å®Œæˆä¹‹å¤?˜q™ç›¸åº”于request.readyState属性ç‰äº?("Completed")ã€‚æ¤æ—Óž¼Œè¯¥å‡½æ•°è¯»å–æœåŠ¡å™¨çš„å“应文本。与它的åå—æ‰€æš—示的相å,XmlHttpRequest的输入和输出都ä¸å¿…é™äºŽXMLæ ¼å¼ã€‚特别地åQŒæˆ‘们的resolveZip.jsp(è§æºç ä¸çš„列è¡?)˜q”回普通文本。如果返回å€égØ“"unknown"åQŒé‚£ä¹ˆè¯¥å‡½æ•°ž®†å‡å®šé‚®æ”¿åŒºåäh˜¯æ— æ•ˆçš„åÆˆä¸”æŠŠæŸ¥æ‰¾å—æ®µ(zip)边界颜色¾|®äØ“¾U¢è‰²ã€‚å¦åˆ™ï¼Œ˜q”å›žå€ÆD¢«ç”¨äºŽå¡«å……å—æ®µstate或cityåQŒåƈ且zip的边界被赋予一¿U缺çœé¢œè‰ŒÓ€?BR>
XMLHttpRequest-ä¼ è¾“å¯¹è±¡
  让我们返回到我们的XMLHTTPRequest的跨‹¹è§ˆå™¨å®žçŽ°ã€‚æœ€åŽä¸€ä¸ªåˆ—表包å«ä¸€ä¸ªHttpRequest()函数-它å‘上兼容于IE5.0å’ŒMozilla 1.8/FireFoxã€‚äØ“½Ž€åŒ–è“vè§ï¼Œæˆ‘们åªåˆ›å»ÞZ¸€ä¸ªå¾®è½¯XMLHTTPRequest对象åQŒè€Œä¸”如果创å¾å¤ÞpÓ|åQŒæˆ‘们å‡å®šå®ƒæ˜¯Firefox/Mozillaã€?/FONT>
ã€€ã€€è¯¥å‡½æ•°çš„æ ¸å¿ƒæ˜¯XMLHTTPRequest-˜q™æ˜¯ä¸€ä¸ªæœ¬æœºæµè§ˆå™¨å¯¹è±¡åQŒå®ƒä¸ºåŒ…括HTTPå议的ä“Q何东西与æœåŠ¡å™¨ä¹‹é—´çš„é€šè®¯æä¾›æ–¹ä¾¿ã€‚它å…许指定ä»ÖM½•HTTP动è¯åQŒå¤´éƒ¨å’Œæœ‰æ•ˆè½½è·åQŒåÆˆä¸”èƒ½å¤Ÿä»¥å¼‚æ¥æˆ–åŒæ¥æ–¹å¼å·¥ä½œã€‚ä¸éœ€è¦ä¸‹è½½ä¹Ÿä¸éœ€è¦å®‰è£…ä“Q何æ’ä»?ž®½ç®¡åœ¨IE的情形下åQŒXMLHTTPRequest是一个集æˆåˆ°‹¹è§ˆå™¨å†…部的ActiveXã€‚å› è€Œï¼Œ"Run ActiveX Control and Plugins"默认IEæƒé™åº”该æ£å¥½é€‚åˆä½¿ç”¨å®ƒã€?/FONT>
  最é‡è¦çš„æ˜¯åQŒXMLHTTPRequestå…许一个到æœåŠ¡å™¨çš„RPCé£Žæ ¼çš„ç¼–½E‹æŸ¥è¯¢è€Œä¸éœ€è¦ä“Q何页é¢åˆ·æ–°ã€‚它以一¿Uå¯é¢„æµ‹çš„ï¼Œå¯æŽ§åˆ¶çš„æ–¹å¼æ¥å®žçްæ¤-æä¾›äº†åˆ°HTTPå议的所有细节的完整å˜å–-包括头部和数æ®çš„ä»ÖM½•å®šåˆ¶æ ¼å¼ã€‚在以åŽçš„æ–‡ç« ä¸åQŒæˆ‘们将å‘ä½ å±•ç¤ºå…¶å®ƒä¸€äº›ä¸šç•Œåè®?ä½ å¯ä»¥åœ¨˜q™äº›ä¼ 输åè®®(如WebæœåŠ¡å’ŒXML-RPC)之上˜q行-它们æžå¤§åœ°ç®€åŒ–大规模应用½E‹åºçš„å¼€å‘å’Œ¾l´æŠ¤ã€?/FONT>
  äº?æœåŠ¡å™¨ç«¯é€»è¾‘
  最åŽï¼ŒæœåŠ¡å™¨ç«¯çš„resolveZip.jsp被从函数ask()ä¸è°ƒç”?è§æ‰€é™„æºç ä¸çš„列è¡?)。这个resolveZip.jsp在两¿U由当å‰çš„邮政区å·é•¿åº¦æ‰€åŒºåˆ†çš„独立的场所下被调用(è§zipChanged()函数)ã€‚è¯·æ±‚å‚æ•°lookupType的值或者是state或者是cityã€‚äØ“½Ž€åŒ–è“vè§ï¼Œæˆ‘们ž®†å‡å®šï¼Œä¸¤ä¸ªæ–‡äšgstate.propertieså’Œcity.properties都ä½äºŽæœåС噍ä¸Cé©±åŠ¨å™¨çš„æ ¹ç›®å½•ä¸‹ã€‚resolveZip.jsp逻辑负责用适当的预装è²çš„æ–‡ä»¶è¿”回查扑ր¹{€?/FONT>
  我们的支æŒAJAX的页é¢çŽ°åœ¨å·²¾l准备好了ã€?/FONT>
  å…?˜qœç¨‹è„šæœ¬æŠ€æœ?一¿Uå¯é€‰æ–¹æ³?/STRONG>
  一些更旧的AJAX实现是基于所谓的˜qœç¨‹è„šæœ¬æŠ€æœ¯ã€‚è¿™¿Uæ€æƒ³æ˜¯ï¼Œç”¨æˆ·çš„行为导致ç»ç”±IFRAMEå¯ÒŽœåŠ¡å™¨˜q›è¡ŒæŸ¥è¯¢åQŒè€ŒæœåŠ¡å™¨ç”¨JavaScript作出å“应åQŒè¯¥è„šæœ¬ä¸€æ—¦åˆ°è¾‘Ö®¢æˆïL«¯ç«‹å³è¢«æ‰§è¡Œã€‚这与XMLHttpRequestæ–ÒŽ³•相比å˜åœ¨è¾ƒå¤§çš„区别,在åŽè€…情况下åQŒæœåС噍å“应数æ®è€Œå®¢æˆïL«¯è§£é‡Šæ•°æ®ã€‚其好处是这¿Uè§£å†Ïx–¹æ¡ˆæ”¯æŒæ›´æ—§çš„‹¹è§ˆå™¨ã€?/FONT>
  åŸÞZºŽIFRAME½CÞZ¾‹çš„HTML部分(è§æ‰€é™„æºç ä¸çš„列è¡?)与我们在XMLHTTPRequest场åˆä¸‹æ‰€ç”¨çš„æžç›¸ä¼û|¼Œä½†æ˜¯˜q™æ¬¡æˆ‘们ž®†å¼•å…¥å¦å¤–一个IFRAMEå…ƒç´ -controller:
Zip:åQœinput id="zipcode" type="text" maxlength="5" onKeyUp="zipChanged()"
style="width:60" size="20"/åQ?BR>City: åQœinput id="city" disabled maxlength="32" style="width:160" size="20"/åQ?BR>State:åQœinput id="state" disabled maxlength="2" style="width:30" size="20"/åQ?BR>åQœiframe id="controller" style="visibility:hidden;width:0;height:0"åQžï¼œ/iframeåQ?/FONT>
ã€€ã€€æˆ‘ä»¬ä¿æŒæ¯æ¬¡å‡»é”®éƒ½è°ƒç”¨zipChanged()一‹Æ¡ï¼Œä½†æ˜¯˜q™ä¸€‹Æ¡ï¼Œä»ŽzipChanged()ä¸è¢«è°ƒç”¨çš„函数ask()(è§æ‰€é™„æºç ä¸çš„列è¡?)负责讄¡½®IFRAMEçš„srcå±žæ€§ï¼Œè€Œä¸æ˜¯è°ƒç”¨ä¸€ä¸ªXMLHTTPRequest:
function ask(urlåQ?fieldToFillåQ?lookupField){
 var controller = document.getElementById("controller");
 controller.src= url+"&field="+fieldToFill.id+"&zip="+lookupField.id;
}
  æœåŠ¡å™¨ç«¯é€»è¾‘ç”׃¸€ä¸ªç²—略的resolveZip.jsp(è§æ‰€é™„æºç ä¸çš„列è¡?)所æè¿°ã€‚它与它的XMLHTTPRequest对应物相区别-它返回JavaScriptè¯å¥åQŒè¿™äº›è¯å¥è®¾¾|®å˜é‡å—ŒDµlookupå’Œcity的全局å€û|¼Œè€Œä¸”一旦它到达‹¹è§ˆå™¨å³ä»Žå…¨å±€½H—å£çš„æ‰§è¡Œä¸Šä¸‹æ–‡ä¸è°ƒç”¨å‡½æ•°response()ã€?/FONT>
  函数response()是一修改版本的handleResponse()-˜q™ä¸€å‡½æ•°å¯ä»¥å…äºŽå¤„ç†æœªå®Œæˆçš„è¯äh±‚(è¯¦è§æœ¬æ–‡æ‰€é™„æºç ä¸çš„列è¡?)ã€?/FONT>
  ä¸? éšùN¢˜
  为简化è“vè§ï¼Œè®©æˆ‘ä»?俯看"一下在我们的示例代ç ä¸çš„一些é‡è¦çš„问题:
  1.事实-XMLHTTPRequest对象实例和回调函数调用在被ä‹É用以åŽåÆˆæ²¡è¢«ç ´å-在毋ơ调用厘q™æœ‰å¯èƒ½å¯ÆD‡´å†…å˜æ³„æ¼ã€‚适当¾~–写的代ç åº”è¯¥ç ´åæˆ–é‡ç”¨å¯¹è±¡æ± ä¸çš„这些实例。而且åQŒå®¢æˆïL«¯å¿…须使用与æœåŠ¡å™¨è½¯äšg相åŒçš„å¯¹è±¡ç®¡ç†æŠ€æœ¯ã€?/FONT>
  2.在大多数情况下,错误往往得ä¸åˆ°æœ‰æ•ˆå¤„ç†ã€‚例如,在方法ask()ä¸å¯¹request.open()的调用å¯èƒ½å¼•å‘一个异常,˜q™æ˜¯å¿…é¡»è¦æ•获和处ç†çš„,å³ä‹É在æµè§ˆå™¨ä¸æ²¡æœ‰è®¾¾|®JavaScript异常自动æ•获功能。而handleResponse()å‡½æ•°åˆæ˜¯å¦å¤–一个例å。它必须è¦äØ“å¯èƒ½çš„æœåŠ¡å™¨ç«¯å’Œé€šè®¯é”™è¯¯è€Œæ£€æŸ¥headerså’ŒresponseText倹{€‚在å‘生错误的情况下åQŒå®ƒå¿…é¡»ž®½åŠ›æ¢å¤òq?或者报告错误。棼‹®å¼€å‘çš„AJAX应用½E‹åºè¦å°½å¯èƒ½é¿å…"æäº¤"æ¾æ•£çš„æ•°æ®ï¼Œå› 䨓往往å˜åœ¨¾U¿èµ\æ–开和其它低¾U§é€šè®¯çš„é—®é¢?所以这些程åºå¿…™åÕd¾ç«‹ä¸€ä¸ªå¼ºå£®çš„和自æ¢å¤çš„æ¡†æž¶äØ“æ¤æä¾›æ”¯æŒã€?/FONT>
  3.当剿œåŠ¡å™¨ç«¯æ¡†æž¶æä¾›ç›¸å½“多的功能-它们å¯ä»¥ä¸Žä¸€¿U自由刷新方法和è°ç›¸å¤„。例如,让我们考虑一个定制的在指定时间内的æœåŠ¡å™¨ç«¯è®¤è¯çš„问题。在˜q™ç§æƒ…况下,我们必须拦截到XMLHTTPRequest调用的安全系¾lŸå“应,昄¡¤ºç™Õd½•å±å¹•åQŒç„¶åŽåœ¨ç”¨æˆ·è¢«è®¤è¯åŽé‡æ–°å‘出è¯äh±‚ã€?/FONT>
  所有的˜q™äº›é—®é¢˜åªæ˜¯ä¸€äº›å…¸åž‹çš„用低¾U§API工作的ä“Q何应用程åºä»£ç ï¼Œè€Œä¸”æ‰€æœ‰è¿™äº›é—®é¢˜éƒ½èƒ½è¢«è§£å†³ã€‚å¥½æ¶ˆæ¯æ˜¯ï¼Œè§£å†³˜q™äº›é—®é¢˜æ‰€éœ€è¦çš„æŠ€æœ¯å分相ä¼égºŽå¤§å¤šæ•°Javaå¼€å‘æŠ€æœ¯ï¼Œå¦‚WebæœåŠ¡åQŒå®šåˆ¶æ ‡½{‘Ö’ŒXML/XSLT。唯一的区别在于,现在˜q™äº›æŠ€æœ¯ä»¥ä¸‹åˆ—å½¢å¼ç”¨äºŽå®¢æˆ·ç«?
  ·WebæœåŠ¡-使用SOAP/REST/RPC½{‰ç®€å•é€šè®¯æ ‡å‡†
ã€€ã€€Â·å®¢æˆ·ç«¯å®šåˆ¶æ ‡½{?打包丰富的客æˆïL«¯æŽ§äšgòq‰™›†æˆAJAX功能
ã€€ã€€Â·æ•°æ®æ“作-åŸÞZºŽXML和基于XSLT技æœ?/FONT>
  å…? ž®ç»“
  AJAXæ–ÒŽ³•能够å‘äh们æä¾›ä¸€¿U与桌é¢åº”用½E‹åºç›¸åŒçš„丰富的互蔾|‘体验。但是,我们必须有选择åœîC‹É用AJAXæŠ€æœ¯ï¼Œå¦‚å½“ä½ ä»åœ¨çº¿è´ç‰©æ—Óž¼Œä½ ç»å¯¹ä¸æƒŒ™®©ä½ 的信用å¡é€šè¿‡åŽå°å¤„熞®±æ‚„悄地开始付‹Æ¾ã€‚AJAX会æˆä¸ÞZ¸€¿U挾l的动力å?我们当然希望˜q™æ ·ã€‚在˜q‡åŽ»çš„äº”òq´æ—¶é—´å†…我们一直在努力开å‘AJAX应用½E‹åºòq¶ä¸”èƒ½è¯æ˜Žå®ƒæ˜¯å¥å…¨åÆˆä¸”å¾ˆæœ‰æ•ˆçš„ã€‚ç„¶è€Œï¼Œå®ƒè¦æ±‚一个开å‘者必™åȲ¾é€šå¤§é‡æŠ€æœ¯è€Œä¸æ˜¯åœ¨ä¼ 统çš?click-refresh"Web应用½E‹åºä¸æ‰€ä½¿ç”¨çš„那些ã€?/FONT>
  Ajaxå¼€å‘者é¢å¯¹çš„一个最大问题是当XMLHttpRequestä¸å¯ç”¨æ—¶å¦‚何å应。虽然大部分çŽîC»£‹¹è§ˆå™¨æ”¯æŒXMLHttpRequeståQŒä½†˜q˜æ˜¯æœ‰å°‘é‡çš„用户åQŒä»–们的‹¹è§ˆå™¨ä¸èƒ½æ”¯æŒï¼Œæˆ–由于æµè§ˆå™¨å®‰å…¨è®„¡½®è€Œé˜»æ¢å¯¹XMLHttpRequestçš„ä‹Éç”¨ã€‚è‹¥ä½ çš„Web应用å‘布于公å¸å†…部的 Intranetä¸Šï¼Œä½ å¾ˆå¯èƒ½å¯ä»¥æŒ‡å®šæ”¯æŒå“ªç§‹¹è§ˆå™¨ï¼Œòq¶å¯ä»¥ç¡®ä¿XMLHttpRequest是å¯ç”¨çš„ã€‚è‹¥ä½ åœ¨å…¬å…±WEB上å‘å¸ƒï¼Œåˆ™ä½ å¿…é¡»æ„识到由于å‡å®šXMLHttpRequest是å¯ç”¨çš„åQŒæ‰€æœ‰å°±é˜ÀL¢äº†è€æµè§ˆå™¨ã€æ‰‹æŒè®¾å¤‡æµè§ˆå™¨½{‰ç‰ç”¨æˆ·æ¥ä‹Éç”¨ä½ çš„ç³»¾lŸã€?/FONT>
ã€€ã€€ç„¶è€Œï¼Œä½ åº”è¯¥å°½åŠ›ä¿è¯åº”用系¾lŸâ€œæ£å¸”R™¾U§â€ä‹É用,在系¾lŸä¸ä¿ç•™é€‚ç”¨äºŽä¸æ”¯æŒXMLHttpRequestçš„æµè§ˆå™¨çš„功能。在è´ç‰©è½¦ä¾‹åä¸åQŒæœ€å¥½çš„æ–ÒŽ³•是有一个Add to Cart按钮åQŒå¯ä»¥è¿›è¡Œå¸¸è§„çš„æäº¤å¤„ç†åQŒåƈåˆäh–°™åµé¢æ¥åæ˜ è´ç‰©èžR状æ€çš„å˜åŒ–。Ajax行å«å¯ä»¥åœ¨é¡µé¢è¢«è½½å…¥æ—‰™€šè¿‡JavaScriptæ·ÕdŠ åˆ°é¡µé¢ä¸åQŒåªåœ?XMLHttpRequestå¯ç”¨çš„æƒ…况下åQŒäØ“æ¯ä¸ªAdd to CartæŒ‰é’®åŠ ä¸ŠJavaScript处ç†å‡½æ•°ã€‚å¦ä¸€ä¸ªæ–¹æ³•是在用æˆïL™»å½•æ—¶‹‚€‹¹‹XMLHttpRequeståQŒå†å†›_®šæ˜¯æä¾›Ajax版本˜q˜æ˜¯å¸¸è§„åŸÞZºŽ formæäº¤çš„版本ã€?/FONT>
  2ã€å¯ç”¨æ€§è€ƒè™‘
  围绕ç€Ajax应用的大部分问题都是很普通的问题。例如,让用æˆïLŸ¥é“他们的输入已ç»è¢«æ³¨å†Œåƈ处ç†åQŒæ˜¯å¾ˆé‡è¦çš„åQŒå› 为在XMLHttpRequest处熘q‡ç¨‹ä¸åƈä¸èƒ½æä¾›é€šå¸¸çš„æ¼æ–—æ—‹è½¬å…‰æ ‡ã€‚ä¸€¿U方法是ž®†â€œç¡®è®¤â€æŒ‰æ‰ä¸Šçš„æ–‡æœ¬æ›¿æ¢äؓ“æ£åœ¨æ›´æ–îC¸â€¦â€ï¼Œä»¥é¿å…用户在½{‰å¾…å“应时多‹Æ¡ç‚¹å‡ÀLŒ‰é’®ã€?/FONT>
  å¦ä¸€ä¸ªé—®é¢˜æ˜¯åQŒç”¨æˆ·å¯èƒ½æ²¡æœ‰æ³¨æ„到他们æ£åœ¨è§‚看的页é¢å·²¾l被更新。å¯ä»¥é€šè¿‡ä½¿ç”¨å„ç§è§†è§‰æŠ€å·§æ¥ž®†ç”¨æˆïLš„眼光å¸å¼•到页é¢çš„æ›´æ–°åŒºåŸŸã€‚还有一个问题是通过 Ajaxæ›´æ–°™åµé¢æ‰“æ–了æµè§ˆå™¨â€œé€€å›žå‰™åµâ€æŒ‰é’®çš„æ£å¸¸å·¥ä½œåQŒåœ°å€æ ä¸çš„URLä¸èƒ½åæ˜ ™åµé¢çš„全部状æ€ï¼Œòq¶ä¸”ä¸èƒ½ä½¿ç”¨ä¹¦ç¾åŠŸèƒ½ã€‚å‚è§Resourceç« èŠ‚ä¸åˆ—出的¾|‘站地å€ä¸Šçš„æ–‡ç« æ¥äº†è§£æ›´å¤šAjax应用关于å¯ç”¨æ€§æ–¹é¢çš„问题ã€?/FONT>
  3ã€æœåŠ¡å™¨è´Ÿè²
  使用Ajax界é¢ä»£æ›¿ä¼ 统的基于form的界é¢å¯èƒ½æˆå‰§æ€§åœ°å¢žåŠ ä¼ é€’åˆ°æœåŠ¡å™¨çš„è¯äh±‚æ•°é‡ã€‚例如,一个普通的Googleæœçƒ¦¾l™æœåŠ¡å™¨é€ æˆä¸€‹Æ¡å‘½ä¸ï¼Œòq¶åœ¨ç”¨æˆ·¼‹®è®¤æœçƒ¦è¡¨å•æ—¶å‘生。然而,Google SuggeståQŒå°†ä¼šè¯•图自动完æˆä½ çš„æœç´¢è¯åQŒåœ¨ç”¨æˆ·æ‰“å—æ—¶å°†ä¼šå¾€æœåС噍å‘é€å¤šä¸ªè¯·æ±‚。在开å‘一个Ajax应用æ—Óž¼Œè¦æ³¨æ„åˆ°ä½ å°†ä¼šå‘é€å¤šž®‘请求到用户器端åQŒä»¥åŠæœåŠ¡å™¨çš„è´Ÿè½½æŒ‡æ ‡ã€‚ä½ å¯ä»¥é€šè¿‡åœ¨å®¢æˆïL«¯é€‚当地缓å˜è¯·æ±‚ã€ä¸ŽæœåС噍å“应楾~“å‡è´Ÿè²åŽ‹åŠ›ã€‚ä½ ä¹Ÿåº”è¯¥åœ¨è®¾è®¡Ajax应用时尽é‡åœ¨å®¢æˆ·ç«¯å¤„ç†æ›´å¤šçš„逻辑åQŒè€Œä¸ç”¨ä¸ŽæœåŠ¡å™¨ç«¯é€šè®¯ã€?/FONT>
  4ã€å¤„ç†å¼‚æ?/STRONG>
  一定è¦è®îC½åQŒæ²¡æœ‰ä“Q何东西å¯ä»¥ä¿è¯XMLHttpRequestž®†ä¼šæŒ‰ç…§å®ƒä»¬è¢«å‘é€çš„™åºåºæ¥ä¾‹Æ¡ç»“æŸã€‚实际上åQŒä½ 在设计系¾lŸæ—¶åQŒè„‘å里应该始终å‡å®šå®ƒä»¬ä¸ä¼šæŒ‰åŽŸæ¥é¡ºåºç»“æŸã€‚在è´ç‰©è½¦ä¾‹åä¸åQŒä‹Éç”¨äº†ä¸€ä¸ªæœ€åŽæ›´æ–°çš„æ—‰™—´æˆÏx¥ä¿è¯æœ€æ–°çš„æ•°æ®ä¸ä¼šè¢«æ”¹å†™ã€‚这个éžå¸¸åŸºæœ¬çš„æ–ÒŽ³•å¯ä»¥åœ¨è´ç‰©èžR场景ä¸å·¥ä½œï¼Œä½†å¯èƒ½ä¸èƒ½åœ¨å…¶å®ƒæƒ…况下工作。在设计时刻ž®Þp¦è€ƒè™‘ä½ è¯¥å¦‚ä½•å¤„ç†å¼‚æ¥æœåС噍å“应ã€?/FONT>
  ¾l“论
ã€€ã€€ä½ çŽ°åœ¨åº”è¯¥å¯¹äºŽAjax的基本原则有了一个良好的了解åQŒå¦å¤–ï¼Œä½ åº”è¯¥ç†è§£ä¸€äº›æ›´é«˜çñ”çš„éšAjaxæ–ÒŽ³•而æ¥çš„设计问题。创å»ÞZ¸€ä¸ªæˆåŠŸçš„Ajax应用需è¦ä¸€¾pÕdˆ—的方法—从JavaScript UI设计到æœåŠ¡å™¨ç«¯æž¶æž„â€”ä½†æ˜¯ä½ çŽ°åœ¨åº”è¯¥å·²ç»å…·å¤‡äº†éœ€è¦ä‹É用到的Ajaxæ ¸å¿ƒçŸ¥è¯†ã€?/FONT>
Javaçš„å †æ˜¯ä¸€ä¸ªè¿è¡Œæ—¶æ•°æ®åŒ?SPAN lang=EN-US>,¾cÈš„实例(对象)从ä¸åˆ†é…½Iºé—´ã€?SPAN lang=EN-US>Java虚拟æœ?SPAN lang=EN-US>(JVM)çš„å †ä¸å‚¨å˜ç€æ£åœ¨˜qè¡Œçš„åº”ç”¨ç¨‹åºæ‰€å»ºç«‹çš„æ‰€æœ‰å¯¹è±¡ï¼Œ˜q™äº›å¯¹è±¡é€šè¿‡newã€?SPAN lang=EN-US>newarrayã€?SPAN lang=EN-US>anewarrayå’?SPAN lang=EN-US>multianewarray½{‰æŒ‡ä»¤å¾ç«‹ï¼Œä½†æ˜¯å®ƒä»¬ä¸éœ€è¦ç¨‹åºä»£ç æ¥æ˜‘ּ地释放。一般æ¥è¯ß_¼Œå †çš„æ˜¯ç”±åžƒåœ¾å›žæ”¶ æ¥è´Ÿè´£çš„åQŒå°½½Ž?SPAN lang=EN-US>JVM规范òq¶ä¸è¦æ±‚ç‰ÒŽ®Šçš„垃圑֛žæ”¶æŠ€æœ¯ï¼Œç”šè‡³æ ÒŽœ¬ž®×ƒ¸éœ€è¦åžƒåœ‘Ö›žæ”Óž¼Œä½†æ˜¯ç”׃ºŽå†…å˜çš„æœ‰é™æ€§ï¼ŒJVM在实现的时候都有一个由垃圾回收所½Ž¡ç†çš„å †ã€‚åžƒåœ‘Ö›žæ”¶æ˜¯ä¸€¿U动æ€å˜å‚¨ç®¡ç†æŠ€æœ¯ï¼Œå®ƒè‡ªåŠ¨åœ°é‡Šæ”¾ä¸å†è¢«ç¨‹åºå¼•用的对象åQŒæŒ‰ç…§ç‰¹å®šçš„垃圾攉™›†½Ž—法æ¥å®žçŽ°èµ„æºè‡ªåŠ¨å›žæ”¶çš„åŠŸèƒ½ã€?SPAN lang=EN-US>
垃圾攉™›†çš„æ„ä¹?SPAN lang=EN-US>
åœ?SPAN lang=EN-US>C++ä¸ï¼Œå¯¹è±¡æ‰€å 的内å˜åœ¨ç¨‹åºç»“æŸè¿è¡Œä¹‹å‰ä¸€ç›´è¢«å 用åQŒåœ¨æ˜Žç¡®é‡Šæ”¾ä¹‹å‰ä¸èƒ½åˆ†é…¾l™å…¶å®ƒå¯¹è±¡ï¼›è€Œåœ¨Javaä¸ï¼Œå½“没有对象引用指å‘原先分é…ç»™æŸä¸ªå¯¹è±¡çš„å†…å˜æ—¶åQŒè¯¥å†…å˜ä¾¿æˆä¸ºåžƒåœ¾ã€?SPAN lang=EN-US>JVM的一个系¾lŸçñ”¾U¿ç¨‹ä¼šè‡ªåŠ¨é‡Šæ”¾è¯¥å†…å˜å—。垃圾收集æ„味瀽E‹åºä¸å†éœ€è¦çš„对象æ˜?SPAN lang=EN-US>"æ— ç”¨ä¿¡æ¯"åQŒè¿™äº›ä¿¡æ¯å°†è¢«ä¸¢å¼ƒã€‚当一个对象ä¸å†è¢«å¼•用的时候,内å˜å›žæ”¶å®ƒå 领的½Iºé—´åQŒä»¥ä¾¿ç©ºé—´è¢«åŽæ¥çš„æ–°å¯¹è±¡ä½¿ç”¨ã€‚事实上åQŒé™¤äº†é‡Šæ”¾æ²¡ç”¨çš„对象åQŒåžƒåœ¾æ”¶é›†ä¹Ÿå¯ä»¥æ¸…除内å˜è®°å½•¼„Žç‰‡ã€‚由于创建对象和垃圾攉™›†å™¨é‡Šæ”¾ä¸¢å¼ƒå¯¹è±¡æ‰€å 的内嘽Iºé—´åQŒå†…å˜ä¼šå‡ºçް¼„Žç‰‡ã€‚碎片是分酾l™å¯¹è±¡çš„内å˜å—之间的½Iºé—²å†…嘋zžã€‚碎片整ç†å°†æ‰€å ç”¨çš„å †å†…å˜¿UÕdˆ°å †çš„一端,JVMž®†æ•´ç†å‡ºçš„内å˜åˆ†é…给新的对象ã€?SPAN lang=EN-US>
垃圾攉™›†èƒ½è‡ªåŠ¨é‡Šæ”‘Ö†…å˜ç©ºé—ß_¼Œå‡è½»¾~–程的负担。这ä½?SPAN lang=EN-US>Java 虚拟机具有一些优ç‚V€‚首先,它能使编½E‹æ•ˆçއæé«˜ã€‚在没有垃圾攉™›†æœºåˆ¶çš„æ—¶å€™ï¼Œå¯èƒ½è¦èŠ±è®¸å¤šæ—‰™—´æ¥è§£å†³ä¸€ä¸ªé𾿇‚çš„å˜å‚¨å™¨é—®é¢˜ã€‚在ç”?SPAN lang=EN-US>Javaè¯è¨€¾~–程的时候,é 垃圾收集机制å¯å¤§å¤§¾~©çŸæ—‰™—´ã€‚å…¶‹Æ¡æ˜¯å®ƒä¿æŠ¤ç¨‹åºçš„完整æ€?SPAN lang=EN-US>, 垃圾攉™›†æ˜?SPAN lang=EN-US>Javaè¯è¨€å®‰å…¨æ€§ç–略的一个é‡è¦éƒ¨ä»½ã€?SPAN lang=EN-US>
垃圾攉™›†çš„一个潜在的¾~ºç‚¹æ˜¯å®ƒçš„开销影哽E‹åºæ€§èƒ½ã€?SPAN lang=EN-US>Java虚拟机必™å»è¿½ítªè¿è¡Œç¨‹åºä¸æœ‰ç”¨çš„对è±?SPAN lang=EN-US>, 而且最¾lˆé‡Šæ”¾æ²¡ç”¨çš„对象。这一个过½E‹éœ€è¦èŠ±è´¹å¤„ç†å™¨çš„æ—¶é—´ã€‚å…¶‹Æ¡åžƒåœ¾æ”¶é›†ç®—法的ä¸å®Œå¤‡æ€§ï¼Œæ—©å…ˆé‡‡ç”¨çš„æŸäº›åžƒåœ¾æ”¶é›†ç®—æ³•å°±ä¸èƒ½ä¿è¯100%攉™›†åˆ°æ‰€æœ‰çš„废弃内å˜ã€‚当焉™šç€åžƒåœ¾æ”‰™›†½Ž—æ³•çš„ä¸æ–改˜q›ä»¥åŠèÊY¼‹¬äšg˜qè¡Œæ•ˆçŽ‡çš„ä¸æ–æå‡ï¼Œ˜q™äº›é—®é¢˜éƒ½å¯ä»¥è¿Žåˆƒè€Œè§£ã€?SPAN lang=EN-US>
垃圾攉™›†çš„算法分æž?SPAN lang=EN-US>
Javaè¯è¨€è§„范没有明确地说æ˜?SPAN lang=EN-US>JVM使用哪ç§åžƒåœ¾å›žæ”¶½Ž—法åQŒä½†æ˜¯ä“Q何一¿U垃圾收集算法一般è¦å?SPAN lang=EN-US>2件基本的事情åQšï¼ˆ1åQ‰å‘çŽ°æ— ç”¨ä¿¡æ¯å¯¹è±¡ï¼›åQ?SPAN lang=EN-US>2åQ‰å›žæ”¶è¢«æ— 用对象å 用的内å˜ç©ºé—ß_¼Œä½¿è¯¥½Iºé—´å¯è¢«½E‹åºå†æ¬¡ä½¿ç”¨ã€?SPAN lang=EN-US>
大多数垃圑֛žæ”¶ç®—法ä‹Éç”¨äº†æ šw›†(root set)˜q™ä¸ªæ¦‚念åQ›æ‰€è°“æ ¹é›†å°±é‡æ£åœ¨æ‰§è¡Œçš„Java½E‹åºå¯ä»¥è®‰K—®çš„引用å˜é‡çš„集åˆ(包括局部å˜é‡ã€å‚æ•°ã€ç±»å˜é‡)åQŒç¨‹åºå¯ä»¥ä‹É用引用å˜é‡è®¿é—®å¯¹è±¡çš„属性和调用对象的方法。垃圾收集首选需è¦ç¡®å®šä»Žæ ¹å¼€å§‹å“ªäº›æ˜¯å¯è¾¾çš„和哪些是ä¸å¯è¾¾çš„ï¼Œä»Žæ ¹é›†å¯è¾„¡š„对象都是‹zÕdŠ¨å¯¹è±¡åQŒå®ƒä»¬ä¸èƒ½ä½œä¸ºåžƒåœ¾è¢«å›žæ”¶åQŒè¿™ä¹ŸåŒ…æ‹¬ä»Žæ šw›†é—´æŽ¥å¯è¾¾çš„å¯¹è±¡ã€‚è€Œæ ¹é›†é€šè¿‡ä»ÀL„路径ä¸å¯è¾„¡š„对象½W¦åˆåžƒåœ¾æ”‰™›†çš„æ¡ä»Óž¼Œåº”该被回收。下é¢ä»‹¾lå‡ ä¸ªå¸¸ç”¨çš„½Ž—法ã€?SPAN lang=EN-US>
1�SPAN style="FONT: 7pt 'Times New Roman'"> 引用计数�/SPAN>(Reference Counting Collector)
å¼•ç”¨è®¡æ•°æ³•æ˜¯å”¯ä¸€æ²¡æœ‰ä½¿ç”¨æ šw›†çš„垃圑֛žæ”¶çš„æ³•,该算法ä‹É用引用计数器æ¥åŒºåˆ†å˜‹zÕd¯¹è±¡å’Œä¸å†ä½¿ç”¨çš„对象。一般æ¥è¯ß_¼Œå †ä¸çš„æ¯ä¸ªå¯¹è±¡å¯¹åº”ä¸€ä¸ªå¼•ç”¨è®¡æ•°å™¨ã€‚å½“æ¯ä¸€‹Æ¡åˆ›å»ÞZ¸€ä¸ªå¯¹è±¡åƈ赋给一个å˜é‡æ—¶åQŒå¼•用计数器¾|®äØ“1。当对象被赋¾l™ä“Qæ„å˜é‡æ—¶åQŒå¼•ç”¨è®¡æ•°å™¨æ¯æ¬¡åŠ?SPAN lang=EN-US>1当对象出了作用域å?SPAN lang=EN-US>(该对象丢弃ä¸å†ä‹Éç”?SPAN lang=EN-US>)åQŒå¼•用计数器å‡?SPAN lang=EN-US>1åQŒä¸€æ—¦å¼•用计数器ä¸?SPAN lang=EN-US>0åQŒå¯¹è±¡å°±æ»¡èƒö了垃圾收集的æ¡äšgã€?/SPAN>
åŸÞZºŽå¼•用计数器的垃圾攉™›†å™¨è¿è¡Œè¾ƒå¿«ï¼Œä¸ä¼šé•¿æ—¶é—´ä¸æ–ç¨‹åºæ‰§è¡Œï¼Œé€‚宜地必™å?实时˜q行的程åºã€‚ä½†å¼•ç”¨è®¡æ•°å™¨å¢žåŠ äº†½E‹åºæ‰§è¡Œçš„开销åQŒå› 为毋ơ对象赋¾l™æ–°çš„å˜é‡ï¼Œè®¡æ•°å™¨åŠ 1åQŒè€Œæ¯‹Æ¡çŽ°æœ‰å¯¹è±¡å‡ºäº†ä½œç”¨åŸŸç”Ÿï¼Œè®¡æ•°å™¨å‡1ã€?/SPAN>
2ã€?SPAN lang=EN-US style="COLOR: red">tracing½Ž—法(Tracing Collector)
tracing½Ž—æ³•æ˜¯äØ“äº†è§£å†›_¼•用计数法的问题而æå‡ºï¼Œå®ƒä‹Éç”¨äº†æ šw›†çš„æ¦‚å¿üc€‚基äº?SPAN lang=EN-US>tracing½Ž—æ³•çš„åžƒåœ¾æ”¶é›†å™¨ä»Žæ ¹é›†å¼€å§‹æ‰«æï¼Œè¯†åˆ«å‡ºå“ªäº›å¯¹è±¡å¯è¾¾ï¼Œå“ªäº›å¯¹è±¡ä¸å¯è¾¾ï¼Œòq¶ç”¨æŸç§æ–¹å¼æ ‡è®°å¯è¾¾å¯¹è±¡åQŒä¾‹å¦‚对æ¯ä¸ªå¯è¾¾å¯¹è±¡è®„¡½®ä¸€ä¸ªæˆ–多个ä½ã€‚在扫æè¯†åˆ«˜q‡ç¨‹ä¸ï¼ŒåŸÞZºŽtracing½Ž—法的垃圾收集也¿UîCØ“æ ‡è®°å’Œæ¸…é™?SPAN lang=EN-US>(mark-and-sweep)垃圾攉™›†å™?SPAN lang=EN-US>.
3ã€?SPAN lang=EN-US style="COLOR: red">compacting½Ž—法(Compacting Collector)
ä¸ÞZº†è§£å†³å †ç¢Žç‰‡é—®é¢˜ï¼ŒåŸÞZºŽtracing的垃圑֛žæ”¶å¸æ”¶äº†Compacting½Ž—æ³•çš„æ€æƒ³åQŒåœ¨æ¸…除的过½E‹ä¸åQŒç®—法将所有的对象¿UÕdˆ°å †çš„ä¸€ç«¯ï¼Œå †çš„å¦ä¸€ç«¯å°±å˜æˆäº†ä¸€ä¸ªç›¸é‚Èš„½Iºé—²å†…å˜åŒºï¼Œæ”‰™›†å™¨ä¼šå¯¹å®ƒ¿UÕdŠ¨çš„æ‰€æœ‰å¯¹è±¡çš„æ‰€æœ‰å¼•ç”¨è¿›è¡Œæ›´æ–ŽÍ¼Œä½¿å¾—˜q™äº›å¼•用在新的佾|®èƒ½è¯†åˆ«åŽŸæ¥ çš„å¯¹è±¡ã€‚åœ¨åŸÞZºŽCompacting½Ž—法的收集器的实çŽîC¸åQŒä¸€èˆ¬å¢žåР奿Ÿ„å’Œå¥æŸ„表。  
4ã€?SPAN lang=EN-US style="COLOR: red">copying½Ž—法(Coping Collector)
该算法的æå‡ºæ˜¯äؓ了克æœå¥æŸ„的开销和解军_ †¼„Žç‰‡çš„垃圑֛žæ”¶ã€‚å®ƒå¼€å§‹æ—¶æŠŠå †åˆ†æˆ ä¸€ä¸ªå¯¹è±?é¢å’Œå¤šä¸ª½Iºé—²é¢ï¼Œ ½E‹åºä»Žå¯¹è±¡é¢ä¸ºå¯¹è±¡åˆ†é…空é—ß_¼Œå½“对象满了,åŸÞZºŽcoping½Ž—法的垃åœ?攉™›†ž®×ƒ»Žæ šw›†ä¸æ‰«ææ´»åŠ¨å¯¹è±¡ï¼Œòq¶å°†æ¯ä¸ª ‹zÕdŠ¨å¯¹è±¡å¤åˆ¶åˆ°ç©ºé—²é¢(使得‹zÕdŠ¨å¯¹è±¡æ‰€å 的内å˜ä¹‹é—´æ²¡æœ‰½Iºé—²‹z?SPAN lang=EN-US>)åQŒè¿™æ ïL©ºé—²é¢å˜æˆäº†å¯¹è±¡é¢åQŒåŽŸæ¥çš„对象é¢å˜æˆäº†½Iºé—²é¢ï¼Œ½E‹åºä¼šåœ¨æ–°çš„对象é¢ä¸åˆ†é…内å˜ã€?SPAN lang=EN-US>
一¿U典型的åŸÞZºŽcoping½Ž—法的垃圑֛žæ”¶æ˜¯stop-and-copy½Ž—法åQŒå®ƒž®†å †åˆ†æˆå¯¹è±¡é¢å’Œ½Iºé—²åŒºåŸŸé¢ï¼Œåœ¨å¯¹è±¡é¢ä¸Žç©ºé—²åŒºåŸŸé¢çš„切æ¢è¿‡½E‹ä¸åQŒç¨‹åºæš‚åœæ‰§è¡Œã€?SPAN lang=EN-US>
5ã€?SPAN lang=EN-US style="COLOR: red">generation½Ž—法(Generational Collector)
  stop-and-copy垃圾攉™›†å™¨çš„一个缺é™äh˜¯æ”‰™›†å™¨å¿…™åÕd¤åˆ¶æ‰€æœ‰çš„‹zÕdŠ¨å¯¹è±¡åQŒè¿™å¢žåŠ äº†ç¨‹åºç‰å¾…æ—¶é—ß_¼Œ˜q™æ˜¯coping½Ž—æ³•ä½Žæ•ˆçš„åŽŸå› ã€‚åœ¨½E‹åºè®¾è®¡ä¸æœ‰˜q™æ ·çš„规律:多数对象å˜åœ¨çš„æ—¶é—´æ¯”较çŸåQŒå°‘æ•°çš„å˜åœ¨æ—‰™—´æ¯”较é•Ñ€‚å› æ¤ï¼Œgeneration½Ž—法ž®†å †åˆ†æˆä¸¤ä¸ªæˆ–多个,æ¯ä¸ªåå †ä½œäØ“å¯¹è±¡çš„ä¸€ä»?SPAN lang=EN-US>(generation)。由于多数对象å˜åœ¨çš„æ—‰™—´æ¯”较çŸï¼Œéšç€½E‹åºä¸¢å¼ƒä¸ä‹É用的对象åQŒåžƒåœ¾æ”¶é›†å™¨ž®†ä»Žæœ€òq´è½»çš„åå †ä¸æ”‰™›†˜q™äº›å¯¹è±¡ã€‚在分代å¼çš„垃圾攉™›†å™¨è¿è¡ŒåŽåQŒä¸Š‹Æ¡è¿è¡Œå˜‹zÖM¸‹æ¥çš„对象¿UÕdˆ°ä¸‹ä¸€æœ€é«˜ä»£çš„åå †ä¸åQŒç”±äºŽè€ä¸€ä»£çš„åå †ä¸ä¼š¾l常被回æ”Óž¼Œå› 而节çœäº†æ—‰™—´ã€?SPAN lang=EN-US>
6ã€?SPAN lang=EN-US style="COLOR: red">adaptive½Ž—法(Adaptive Collector)
在特定的情况下,一些垃圾收集算法会优于其它½Ž—法。基äº?SPAN lang=EN-US>Adaptive½Ž—法的垃圾收集器ž®±æ˜¯ç›‘控当å‰å †çš„使用情况åQŒåƈž®†é€‰æ‹©é€‚当½Ž—法的垃圾收集器ã€?SPAN lang=EN-US>
é€è§†Java垃圾回收
1ã€å‘½ä»¤è¡Œå‚æ•°é€è§†åžƒåœ¾æ”‰™›†å™¨çš„˜q行
2ã€ä‹Éç”?SPAN lang=EN-US>System.gc()å¯ä»¥ä¸ç®¡JVM使用的是哪一¿U垃圑֛žæ”¶çš„½Ž—法åQŒéƒ½å¯ä»¥è¯äh±‚Java的垃圑֛žæ”¶ã€‚在命ä×oè¡Œä¸æœ‰ä¸€ä¸ªå‚æ•?SPAN lang=EN-US>-verbosegcå¯ä»¥æŸ¥çœ‹Javaä½¿ç”¨çš„å †å†…å˜çš„æƒ…å†µï¼Œå®ƒçš„æ ¼å¼å¦‚下åQ?SPAN lang=EN-US>
java -verbosegc classfile
  å¯ä»¥çœ‹ä¸ªä¾‹ååQ?/SPAN>
class TestGC
{
 public static void main(String[] args)
 {
  new TestGC();
  System.gc();
  System.runFinalization();
 }
}
  在这个例åä¸åQŒä¸€ä¸ªæ–°çš„对象被创å¾åQŒç”±äºŽå®ƒæ²¡æœ‰ä½¿ç”¨åQŒæ‰€ä»¥è¯¥å¯¹è±¡˜q…速地å˜äØ“å¯è¾¾åQŒç¨‹åºç¼–译åŽåQŒæ‰§è¡Œå‘½ä»¤ï¼š java -verbosegc TestGC åŽç»“æžœäØ“åQ?SPAN lang=EN-US>
[Full GC 168K->97K(1984K), 0.0253873 secs]
ã€€ã€€æœºå™¨çš„çŽ¯å¢ƒäØ“åQ?SPAN lang=EN-US>Windows 2000 + JDK
  2ã€?SPAN lang=EN-US>finalizeæ–ÒŽ³•é€è§†åžƒåœ¾æ”‰™›†å™¨çš„˜q行
  åœ?SPAN lang=EN-US>JVM垃圾攉™›†å™¨æ”¶é›†ä¸€ä¸ªå¯¹è±¡ä¹‹å‰?åQŒä¸€èˆ¬è¦æ±‚程åºè°ƒç”¨é€‚当的方法释放资æºï¼Œä½†åœ¨æ²¡æœ‰æ˜Žç¡®é‡Šæ”¾èµ„æºçš„æƒ…况下åQ?SPAN lang=EN-US>Javaæä¾›äº†ç¼ºçœæœºåˆ¶æ¥¾lˆæ¢åŒ–该对象心释放资æºï¼Œ˜q™ä¸ªæ–ÒŽ³•ž®±æ˜¯finalizeåQˆï¼‰ã€‚å®ƒçš„åŽŸåž‹äØ“åQ?SPAN lang=EN-US>
protected void finalize() throws Throwable
  åœ?SPAN lang=EN-US>finalize()æ–ÒŽ³•˜q”回之åŽåQŒå¯¹è±¡æ¶ˆå¤±ï¼Œåžƒåœ¾æ”‰™›†å¼€å§‹æ‰§è¡Œã€‚原型ä¸çš?SPAN lang=EN-US>throws Throwable表示它å¯ä»¥æŠ›å‡ÞZ“Q何类型的异常ã€?SPAN lang=EN-US>
  之所以è¦ä½¿ç”¨finalize()åQŒæ˜¯ç”׃ºŽæœ‰æ—¶éœ€è¦é‡‡å–与Java的普通方法ä¸åŒçš„一¿U方法,通过分é…å†…å˜æ¥åšä¸€äº›å…·æœ?SPAN lang=EN-US>Cé£Žæ ¼çš„äº‹æƒ…ã€‚è¿™ä¸»è¦å¯ä»¥é€šè¿‡"固有æ–ÒŽ³•"æ¥è¿›è¡Œï¼Œå®ƒæ˜¯ä»?SPAN lang=EN-US>Java里调用éžJavaæ–ÒŽ³•的一¿Uæ–¹å¼ã€?SPAN lang=EN-US>Cå’?SPAN lang=EN-US>C++是目å‰å”¯ä¸€èŽ·å¾—å›ºæœ‰æ–ÒŽ³•支æŒçš„è¯a€ã€‚但ç”׃ºŽå®ƒä»¬èƒ½è°ƒç”¨é€šè¿‡å…¶ä»–è¯è¨€¾~–写的å½E‹åºåQŒæ‰€ä»¥èƒ½å¤Ÿæœ‰æ•ˆåœ°è°ƒç”¨ä»ÖM½•东西。在é?SPAN lang=EN-US>Java代ç 内部åQŒä¹Ÿè®¸èƒ½è°ƒç”¨Cçš?SPAN lang=EN-US>malloc()¾pÕdˆ—函数åQŒç”¨å®ƒåˆ†é…å˜å‚¨ç©ºé—´ã€‚而且除éžè°ƒç”¨äº?SPAN lang=EN-US>free()åQŒå¦åˆ™å˜å‚¨ç©ºé—´ä¸ä¼šå¾—åˆ°é‡Šæ”¾ï¼Œä»Žè€Œé€ æˆå†…å˜"æ¼æ´ž"的出现。当ç„Óž¼Œfree()是一ä¸?SPAN lang=EN-US>Cå’?SPAN lang=EN-US>C++函数åQŒæ‰€ä»¥æˆ‘们需è¦åœ¨finalize()内部的一个固有方法ä¸è°ƒç”¨å®ƒã€‚也ž®±æ˜¯è¯´æˆ‘们ä¸èƒ½è¿‡å¤šåœ°ä½¿ç”¨finalize()åQŒå®ƒòq¶ä¸æ˜¯è¿›è¡Œæ™®é€šæ¸…é™¤å·¥ä½œçš„ç†æƒ³åœºæ‰€ã€?SPAN lang=EN-US>
  在普通的清除工作ä¸ï¼Œä¸ºæ¸…除一个对象,那个对象的用户必™åÕdœ¨å¸Œæœ›˜q›è¡Œæ¸…除的地点调用一个清除方法。这ä¸?SPAN lang=EN-US>C++"ç ´åå™?SPAN lang=EN-US>"的概å¿ëŠ¨æœ‰æŠµè§¦ã€‚åœ¨C++ä¸ï¼Œæ‰€æœ‰å¯¹è±¡éƒ½ä¼šç ´å(清除åQ‰ã€‚或者æ¢å¥è¯è¯ß_¼Œæ‰€æœ‰å¯¹è±¡éƒ½"应该"ç ´å。若ž®?SPAN lang=EN-US>C++å¯¹è±¡åˆ›å¾æˆä¸€ä¸ªæœ¬åœ°å¯¹è±¡ï¼Œæ¯”å¦‚åœ¨å †æ ˆä¸åˆ›å¾åQˆåœ¨Java䏿˜¯ä¸å¯èƒ½çš„åQ‰ï¼Œé‚£ä¹ˆæ¸…é™¤æˆ–ç ´å工作就会在"¾l“æŸèŠ±æ‹¬å?SPAN lang=EN-US>"所代表的ã€åˆ›å»ø™¿™ä¸ªå¯¹è±¡çš„作用域的末尾˜q›è¡Œã€‚若对象是用new创å¾çš„(¾cÖM¼¼äº?SPAN lang=EN-US>JavaåQ‰ï¼Œé‚£ä¹ˆå½“程åºå‘˜è°ƒç”¨C++çš?SPAN lang=EN-US>delete命ä×oæ—Óž¼ˆJava没有˜q™ä¸ªå‘½ä×oåQ‰ï¼Œž®×ƒ¼šè°ƒç”¨ç›¸åº”çš„ç ´å器。若½E‹åºå‘˜å¿˜è®îCº†åQŒé‚£ä¹ˆæ°¸˜qœä¸ä¼šè°ƒç”¨ç ´å器åQŒæˆ‘们最¾lˆå¾—到的ž®†æ˜¯ä¸€ä¸ªå†…å?SPAN lang=EN-US>"æ¼æ´ž"åQŒå¦å¤–还包括对象的其他部分永˜qœä¸ä¼šå¾—到清除ã€?SPAN lang=EN-US>
  相ååQ?SPAN lang=EN-US>Javaä¸å…许我们创建本圎ͼˆå±€éƒ¨ï¼‰å¯¹è±¡--æ— è®ºå¦‚ä½•éƒ½è¦ä½¿ç”¨new。但åœ?SPAN lang=EN-US>Javaä¸ï¼Œæ²¡æœ‰"delete"命ä×oæ¥é‡Šæ”‘Ö¯¹è±¡ï¼Œå› äØ“åžƒåœ¾æ”‰™›†å™¨ä¼šå¸®åŠ©æˆ‘ä»¬è‡ªåŠ¨é‡Šæ”¾å˜å‚¨½Iºé—´ã€‚所以如果站在比较简化的立场åQŒæˆ‘们å¯ä»¥è¯´æ£æ˜¯ç”׃ºŽå˜åœ¨åžƒåœ¾æ”‰™›†æœºåˆ¶åQŒæ‰€ä»?SPAN lang=EN-US>Javaæ²¡æœ‰ç ´å器。然而,éšç€ä»¥åŽå¦ä¹ 的深入,ž®×ƒ¼šçŸ¥é“垃圾攉™›†å™¨çš„å˜åœ¨òq¶ä¸èƒ½å®Œå…¨æ¶ˆé™¤å¯¹ç ´å器的需è¦ï¼Œæˆ–者说ä¸èƒ½æ¶ˆé™¤å¯¹ç ´å器代表的那¿U机制的需è¦ï¼ˆè€Œä¸”¾l对ä¸èƒ½ç›´æŽ¥è°ƒç”¨finalize()åQŒæ‰€ä»¥åº”ž®½é‡é¿å…用它åQ‰ã€‚若希望执行除释攑֘储空间之外的其他æŸç§å½¢å¼çš„æ¸…除工作,ä»ç„¶å¿…须调用Javaä¸çš„一个方法。它½{‰ähäº?SPAN lang=EN-US>C++çš„ç ´å器åQŒåªæ˜¯æ²¡åŽè€…æ–¹ä¾Ñ€?SPAN lang=EN-US>
  下题q™ä¸ªä¾‹åå‘大家展½CÞZº†åžƒåœ¾æ”‰™›†æ‰€¾l历的过½E‹ï¼Œòq¶å¯¹å‰é¢çš„陈˜q°è¿›è¡Œäº†æ€È»“ã€?SPAN lang=EN-US>
class Chair {
 static boolean gcrun = false;
 static boolean f = false;
 static int created = 0;
 static int finalized = 0;
 int i;
 Chair() {
  i = ++created;
  if(created == 47)
   System.out.println("Created 47");
 }
 protected void finalize() {
  if(!gcrun) {
   gcrun = true;
   System.out.println("Beginning to finalize after " + created + " Chairs have been created");
  }
  if(i == 47) {
   System.out.println("Finalizing Chair #47, " +"Setting flag to stop Chair creation");
   f = true;
  }
  finalized++;
  if(finalized >= created)
   System.out.println("All " + finalized + " finalized");
 }
}
public class Garbage {
 public static void main(String[] args) {
  if(args.length == 0) {
   System.err.println("Usage: \n" + "java Garbage before\n or:\n" + "java Garbage after");
   return;
  }
  while(!Chair.f) {
   new Chair();
   new String("To take up space");
  }
  System.out.println("After all Chairs have been created:\n" + "total created = " + Chair.created +
", total finalized = " + Chair.finalized);
  if(args[0].equals("before")) {
    System.out.println("gc():");
    System.gc();
    System.out.println("runFinalization():");
    System.runFinalization();
  }
  System.out.println("bye!");
  if(args[0].equals("after"))
   System.runFinalizersOnExit(true);
 }
}
  上题q™ä¸ª½E‹åºåˆ›å¾äº†è®¸å¤?SPAN lang=EN-US>Chair对象åQŒè€Œä¸”在垃圾收集器开始è¿è¡ŒåŽçš„æŸäº›æ—¶å€™ï¼Œ½E‹åºä¼šåœæ¢åˆ›å»?SPAN lang=EN-US>Chair。由于垃圾收集器å¯èƒ½åœ¨ä“Q何时间è¿è¡Œï¼Œæ‰€ä»¥æˆ‘们ä¸èƒ½å‡†¼‹®çŸ¥é“它在何时å¯åŠ¨ã€‚å› æ¤ï¼Œ½E‹åºç”¨ä¸€ä¸ªåä¸?SPAN lang=EN-US>gcrunçš„æ ‡è®°æ¥æŒ‡å‡ºåžƒåœ¾æ”‰™›†å™¨æ˜¯å¦å·²¾l开始è¿è¡Œã€‚åˆ©ç”¨ç¬¬äºŒä¸ªæ ‡è®°fåQ?SPAN lang=EN-US>Chairå¯å‘Šè¯?SPAN lang=EN-US>main()å®ƒåº”åœæ¢å¯¹è±¡çš„生æˆã€‚è¿™ä¸¤ä¸ªæ ‡è®°éƒ½æ˜¯åœ?SPAN lang=EN-US>finalize()内部讄¡½®çš„,它调用于垃圾攉™›†æœŸé—´ã€‚å¦ä¸¤ä¸ªstaticå˜é‡--created以åŠfinalized--分别用于跟踪已创建的对象数é‡ä»¥åŠåžƒåœ¾æ”‰™›†å™¨å·²˜q›è¡Œå®Œæ”¶ž®‘Ö·¥ä½œçš„对象数é‡ã€‚最åŽï¼Œæ¯ä¸ªChair都有它自å·Þqš„åQˆéžstaticåQ?SPAN lang=EN-US>int iåQŒæ‰€ä»¥èƒ½è·Ÿè¸ªäº†è§£å®ƒå…·ä½“çš„¾~–å·æ˜¯å¤šž®‘。编å·äØ“47çš?SPAN lang=EN-US>Chair˜q›è¡Œå®Œæ”¶ž®‘Ö·¥ä½œåŽåQŒæ ‡è®îC¼šè®¾äØ“trueåQŒæœ€¾lˆç»“æ?SPAN lang=EN-US>Chairå¯¹è±¡çš„åˆ›å»ø™¿‡½E‹ã€‚(关于˜q™ä¸ªä¾‹å的更具体的分æžå’Œè¯´æ˜Žè¯·å‚看ã€?SPAN lang=EN-US>Java¾~–ç¨‹æ€æƒ³ã€‹çš„½W¬å››ç« )
  关于垃圾攉™›†çš„å‡ ç‚¹è¡¥å…?/B>
  ¾l过上述的说明,å¯ä»¥å‘çŽ°åžƒåœ¾å›žæ”¶æœ‰ä»¥ä¸‹çš„å‡ ä¸ªç‰¹ç‚¹åQ?SPAN lang=EN-US>
  åQ?SPAN lang=EN-US>1åQ‰åžƒåœ¾æ”¶é›†å‘生的ä¸å¯é¢„知性:ç”׃ºŽå®žçŽ°äº†ä¸åŒçš„垃圾攉™›†½Ž—法和采用了ä¸åŒçš„æ”¶é›†æœºåˆÓž¼Œæ‰€ä»¥å®ƒæœ‰å¯èƒ½æ˜¯å®šæ—¶å‘生åQŒæœ‰å¯èƒ½æ˜¯å½“出现¾pÈ»Ÿ½Iºé—²CPUèµ„æºæ—¶å‘生,也有å¯èƒ½æ˜¯å’ŒåŽŸå§‹çš„åžƒåœ¾æ”¶é›†ä¸€æ øP¼Œ½{‰åˆ°å†…å˜æ¶ˆè€—出现æžé™æ—¶å‘生åQŒè¿™ä¸Žåžƒåœ¾æ”¶é›†å™¨çš„选择和具体的讄¡½®éƒ½æœ‰å…³ç³»ã€?SPAN lang=EN-US>
  åQ?SPAN lang=EN-US>2åQ‰åžƒåœ¾æ”¶é›†çš„¾_„¡¡®æ€§ï¼šä¸»è¦åŒ…括2 个方é¢ï¼šåQ?SPAN lang=EN-US>aåQ‰åžƒåœ¾æ”¶é›†å™¨èƒ½å¤Ÿ¾_„¡¡®æ ‡è®°‹zȀ的对象;åQ?SPAN lang=EN-US>båQ‰åžƒåœ¾æ”¶é›†å™¨èƒ½å¤Ÿ¾_„¡¡®åœ°å®šä½å¯¹è±¡ä¹‹é—´çš„引用关系。å‰è€…æ˜¯å®Œå…¨åœ°å›žæ”¶æ‰€æœ‰åºŸå¼ƒå¯¹è±¡çš„å‰æåQŒå¦åˆ™å°±å¯èƒ½é€ æˆå†…å˜æ³„æ¼ã€‚而åŽè€…则是实现归òq¶å’Œå¤åˆ¶½{‰ç®—æ³•çš„å¿…è¦æ¡äšg。所有ä¸å¯è¾¾å¯¹è±¡éƒ½èƒ½å¤Ÿå¯é 地得到回收åQŒæ‰€æœ‰å¯¹è±¡éƒ½èƒ½å¤Ÿé‡æ–°åˆ†é…åQŒå…许对象的å¤åˆ¶å’Œå¯¹è±¡å†…å˜çš„¾~©åƈåQŒè¿™æ ·å°±æœ‰æ•ˆåœ°é˜²æ¢å†…å˜çš„æ”¯ç¦»ç ´ç¢Žã€‚(3åQ‰çŽ°åœ¨æœ‰è®¸å¤š¿Uä¸åŒçš„垃圾攉™›†å™¨ï¼Œæ¯ç§æœ‰å…¶½Ž—法且其表现å„异åQŒæ—¢æœ‰å½“垃圾攉™›†å¼€å§‹æ—¶ž®±åœæ¢åº”用程åºçš„˜q行åQŒåˆæœ‰å½“垃圾攉™›†å¼€å§‹æ—¶ä¹Ÿå…许应用程åºçš„¾U¿ç¨‹˜q行åQŒè¿˜æœ‰åœ¨åŒä¸€æ—‰™—´åžƒåœ¾æ”‰™›†å¤šçº¿½E‹è¿è¡Œã€?SPAN lang=EN-US>
  åQ?SPAN lang=EN-US>4åQ‰åžƒåœ¾æ”¶é›†çš„实现和具体的JVM 以åŠJVMçš„å†…å˜æ¨¡åž‹æœ‰éžå¸¸ç´§å¯†çš„å…³¾p…R€‚ä¸åŒçš„JVM å¯èƒ½é‡‡ç”¨ä¸åŒçš„垃圾收集,è€?SPAN lang=EN-US>JVM çš„å†…å˜æ¨¡åž‹å†³å®šç€è¯?SPAN lang=EN-US>JVMå¯ä»¥é‡‡ç”¨å“ªäº›¾cÕdž‹åžƒåœ¾æ”‰™›†ã€‚现在,HotSpot ¾pÕdˆ—JVMä¸çš„内嘾pÈ»Ÿéƒ½é‡‡ç”¨å…ˆ˜q›çš„é¢å‘对象的框架设计,˜q™ä‹É得该¾pÕdˆ—JVM都å¯ä»¥é‡‡ç”¨æœ€å…ˆè¿›çš„垃圾收集ã€?SPAN lang=EN-US>
  åQ?SPAN lang=EN-US>5åQ‰éšç€æŠ€æœ¯çš„å‘展åQŒçŽ°ä»£åžƒåœ¾æ”¶é›†æŠ€æœ¯æä¾›è®¸å¤šå¯é€‰çš„垃圾攉™›†å™¨ï¼Œè€Œä¸”在酾|®æ¯¿U收集器的时候åˆå¯ä»¥è®„¡½®ä¸åŒçš„傿•ŽÍ¼Œ˜q™å°±ä½¿å¾—æ ÒŽ®ä¸åŒçš„应用环境获得最优的应用性能æˆäØ“å¯èƒ½ã€?SPAN lang=EN-US>
  针对以上特点åQŒæˆ‘ä»¬åœ¨ä½¿ç”¨çš„æ—¶å€™è¦æ³¨æ„åQ?SPAN lang=EN-US>
  åQ?SPAN lang=EN-US>1åQ‰ä¸è¦è¯•囑֎»å‡å®šåžƒåœ¾æ”‰™›†å‘生的时é—ß_¼Œ˜q™ä¸€åˆ‡éƒ½æ˜¯æœªçŸ¥çš„。比如,æ–ÒŽ³•ä¸çš„一个äÍæ—¶å¯¹è±¡åœ¨æ–ÒŽ³•调用完毕åŽå°±å˜æˆäº†æ— 用对象,˜q™ä¸ªæ—¶å€™å®ƒçš„内å˜å°±å¯ä»¥è¢«é‡Šæ”¾ã€?SPAN lang=EN-US>
  åQ?SPAN lang=EN-US>2åQ?SPAN lang=EN-US>Javaä¸æä¾›äº†ä¸€äº›å’Œåžƒåœ¾æ”‰™›†æ‰“交é“çš„¾c»ï¼Œè€Œä¸”æä¾›äº†ä¸€¿U强行执行垃圾收集的æ–ÒŽ³•--调用System.gc()åQŒä½†˜q™åŒæ äh˜¯ä¸ªä¸¼‹®å®šçš„æ–¹æ³•ã€?SPAN lang=EN-US>Java ä¸åƈä¸ä¿è¯æ¯‹Æ¡è°ƒç”¨è¯¥æ–ÒŽ³•ž®×ƒ¸€å®šèƒ½å¤Ÿå¯åŠ¨åžƒåœ¾æ”¶é›†ï¼Œå®ƒåªä¸è¿‡ä¼šå‘JVMå‘出˜q™æ ·ä¸€ä¸ªç”³è¯øP¼Œåˆ°åº•是å¦çœŸæ£æ‰§è¡Œåžƒåœ¾æ”‰™›†åQŒä¸€åˆ‡éƒ½æ˜¯ä¸ªæœªçŸ¥æ•°ã€?SPAN lang=EN-US>
  åQ?SPAN lang=EN-US>3åQ‰æŒ‘选适åˆè‡ªå·±çš„垃圾收集器。一般æ¥è¯ß_¼Œå¦‚æžœ¾pÈ»Ÿæ²¡æœ‰ç‰ÒŽ®Šå’Œè‹›åˆÈš„æ€§èƒ½è¦æ±‚åQŒå¯ä»¥é‡‡ç”?SPAN lang=EN-US>JVM的缺çœé€‰é¡¹ã€‚å¦åˆ™å¯ä»¥è€ƒè™‘使用有针å¯ÒŽ€§çš„垃圾攉™›†å™¨ï¼Œæ¯”å¦‚å¢žé‡æ”‰™›†å™¨å°±æ¯”较适åˆå®žæ—¶æ€§è¦æ±‚较高的¾pÈ»Ÿä¹‹ä¸ã€‚ç³»¾lŸå…·æœ‰è¾ƒé«˜çš„é…ç½®åQŒæœ‰æ¯”较多的闲置资æºåQŒå¯ä»¥è€ƒè™‘使用òq¶è¡Œæ ‡è®°/清除攉™›†å™¨ã€?SPAN lang=EN-US>
  åQ?SPAN lang=EN-US>4åQ‰å…³é”®çš„也是难把æ¡çš„é—®é¢˜æ˜¯å†…å˜æ³„æ¼ã€‚良好的¾~–ç¨‹ä¹ æƒ¯å’Œä¸¥è°¨çš„¾~–程æ€åº¦æ°¸è¿œæ˜¯æœ€é‡è¦çš„,ä¸è¦è®©è‡ªå·Þqš„一个å°é”™è¯¯å¯ÆD‡´å†…å˜å‡ºçŽ°å¤§æ¼‹zžã€?SPAN lang=EN-US>
  åQ?SPAN lang=EN-US>5åQ‰å°½æ—©é‡Šæ”¾æ— 用对象的引用。大多数½E‹åºå‘˜åœ¨ä½¿ç”¨ä¸´æ—¶å˜é‡çš„æ—¶å€™ï¼Œéƒ½æ˜¯è®©å¼•用å˜é‡åœ¨é€€å‡ºæ´»åŠ¨åŸŸ(scope)åŽï¼Œè‡ªåŠ¨è®„¡½®ä¸?SPAN lang=EN-US>nullåQŒæš—½Cºåžƒåœ¾æ”¶é›†å™¨æ¥æ”¶é›†è¯¥å¯¹è±¡åQŒè¿˜å¿…须注æ„该引用的对象是å¦è¢«ç›‘å¬ï¼Œå¦‚果有,则è¦åŽÀLŽ‰ç›‘å¬å™¨ï¼Œç„¶åŽå†èµ‹½Iºå€¹{€?SPAN lang=EN-US>
  ¾l“æŸè¯?/B>
  一般æ¥è¯ß_¼ŒJavaå¼€å‘äh员å¯ä»¥ä¸é‡è§†JVMä¸å †å†…å˜çš„分é…å’Œåžƒåœ¾å¤„ç†æ”‰™›†åQŒä½†æ˜¯ï¼Œå……分ç†è§£Java的这一ç‰ÒŽ€§å¯ä»¥è®©æˆ‘们更有效地利用资æºã€‚åŒæ—¶è¦æ³¨æ„finalize()æ–ÒŽ³•æ˜?SPAN lang=EN-US>Javaçš„ç¼ºçœæœºåˆÓž¼Œæœ‰æ—¶ä¸ºç¡®ä¿å¯¹è±¡èµ„æºçš„æ˜Žç¡®é‡Šæ”¾åQŒå¯ä»¥ç¼–写自å·Þqš„finalizeæ–ÒŽ³•ã€?SPAN lang=EN-US>