ï»??xml version="1.0" encoding="utf-8" standalone="yes"?>日韩精品一区二区三区视频在线观看,国产欧美精品,亚洲女人小视频在线观看http://www.aygfsteel.com/kyanite/archive/2005/12/29/25906.htmlkyanitekyaniteThu, 29 Dec 2005 09:10:00 GMThttp://www.aygfsteel.com/kyanite/archive/2005/12/29/25906.htmlhttp://www.aygfsteel.com/kyanite/comments/25906.htmlhttp://www.aygfsteel.com/kyanite/archive/2005/12/29/25906.html#Feedback0http://www.aygfsteel.com/kyanite/comments/commentRss/25906.htmlhttp://www.aygfsteel.com/kyanite/services/trackbacks/25906.html一. 什么是AJAX?

  ˜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的挑�zz)http://www.aygfsteel.com/kyanite/archive/2005/12/29/25893.htmlkyanitekyaniteThu, 29 Dec 2005 08:01:00 GMThttp://www.aygfsteel.com/kyanite/archive/2005/12/29/25893.htmlhttp://www.aygfsteel.com/kyanite/comments/25893.htmlhttp://www.aygfsteel.com/kyanite/archive/2005/12/29/25893.html#Feedback0http://www.aygfsteel.com/kyanite/comments/commentRss/25893.htmlhttp://www.aygfsteel.com/kyanite/services/trackbacks/25893.html  1、XMLHttpRequest的有效�/STRONG>

  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回收机制分析http://www.aygfsteel.com/kyanite/archive/2005/12/27/25554.htmlkyanitekyaniteTue, 27 Dec 2005 04:10:00 GMThttp://www.aygfsteel.com/kyanite/archive/2005/12/27/25554.htmlhttp://www.aygfsteel.com/kyanite/comments/25554.htmlhttp://www.aygfsteel.com/kyanite/archive/2005/12/27/25554.html#Feedback0http://www.aygfsteel.com/kyanite/comments/commentRss/25554.htmlhttp://www.aygfsteel.com/kyanite/services/trackbacks/25554.html引言

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 + JDK1.3.1,½Ž­å¤´å‰åŽçš„æ•°æ?SPAN lang=EN-US>168Kå’?SPAN lang=EN-US>97K分别表示垃圾攉™›†GC前后所有存‹zÕd¯¹è±¡ä‹É用的内存定w‡åQŒè¯´æ˜Žæœ‰168K-97K=71K的对象容量被回收åQŒæ‹¬å·å†…的数æ?SPAN lang=EN-US>1984K为堆内存的æ€Õd®¹é‡ï¼Œæ”‰™›†æ‰€éœ€è¦çš„æ—‰™—´æ˜?SPAN lang=EN-US>0.0253873¿U’(˜q™ä¸ªæ—‰™—´åœ¨æ¯‹Æ¡æ‰§è¡Œçš„æ—¶å€™ä¼šæœ‰æ‰€ä¸åŒåQ‰ã€?SPAN lang=EN-US>

  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>



]]>
struts中文ä¹Þq é—®é¢˜è§£å†³http://www.aygfsteel.com/kyanite/archive/2005/08/20/10586.htmlkyanitekyaniteSat, 20 Aug 2005 05:52:00 GMThttp://www.aygfsteel.com/kyanite/archive/2005/08/20/10586.htmlhttp://www.aygfsteel.com/kyanite/comments/10586.htmlhttp://www.aygfsteel.com/kyanite/archive/2005/08/20/10586.html#Feedback0http://www.aygfsteel.com/kyanite/comments/commentRss/10586.htmlhttp://www.aygfsteel.com/kyanite/services/trackbacks/10586.html      ˜q‘æ—¥åQŒä‹É用struts 1.1åQŒå‘现讨厌的中文ä¹Þq é—®é¢˜åQŒåœ¨form的传送过½E‹å’Œå…¥åº“时候出现。就我在¾|‘络上找的方法罗列如下:
åQˆTomcat 5.0.28+struts 1.1+hibernate 2.1+sqlserver2kåQ?BR>1.直接转编码public static String isoToGB(String src){   
String strRet=null;   
try{    
  strRet = new String(src.getBytes("ISO_8859_1"),"GB2312");  
  }catch(Exception e)    {         
}    return strRet;
}通过一个函数è{¾~–码åQŒæˆ‘没有成功åQŒä¸çŸ¥äؓ何!

2.˜q‡æ×ofilter讄¡½®æ³?BR>
package yourbean;

import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;
import java.util.*;

public class servfilter extends HttpServlet implements Filter {  private FilterConfig filterConfig;  //Handle the passed-in FilterConfig  public void init(FilterConfig filterConfig) {    this.filterConfig = filterConfig;  }  //Process the request/response pair  public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) {    try {      request.setCharacterEncoding("GB2312");       ((HttpServletResponse)response).setHeader("Cache-control","no-cache");      response.setHeader("Pragma","No-cache"); response.setHeader("Cache-Control","no-cache"); response.setHeader("Expires","0");       ((HttpServletResponse)response).setHeader("Pragram","no-cache");      filterChain.doFilter(request, response);    }    catch(ServletException sx) {      filterConfig.getServletContext().log(sx.getMessage());    }    catch(IOException iox) {      filterConfig.getServletContext().log(iox.getMessage());    }  }  //Clean up resources  public void destroy() {  }}下面是一个web.xmlæ–‡äšg你用jbuilder写上面的bean的时候会生成一ä¸?lt;?xml version="1.0" encoding="ISO-8859-1"?>

<!DOCTYPE web-app    PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"    "http://java.sun.com/dtd/web-app_2_3.dtd">

<web-app>  <display-name>Welcome to Tomcat</display-name>  <description>     Welcome to Tomcat  </description>  <filter>    <filter-name>servfilter</filter-name>    <filter-class>yourbean.servfilter</filter-class>  </filter>  <filter-mapping>    <filter-name>servfilter</filter-name>    <url-pattern>/*</url-pattern>  </filter-mapping></web-app>把上面的servfilter¾~–译攑֜¨ä½ çš„web-inf/classes/yourbean/下web.xml攑֜¨web-inf/下和classes在一个目录下在每个jsp™åµé¢ä¸ŠåŠ ä¸?lt;%@page contentType="text/html;charset=GBK"%>

也不是很方便åQŒè€Œä¸”在tomcat也没有成功,¾l§ç®‹éƒé—·åQ?BR>
3.我现在ä‹É用方法,推荐åQï¼

写一个myActionServletæ¥åÆˆè¦†ç›–ActionServlet中的processåQˆï¼‰æ–ÒŽ³•ã€?BR>
  protected void process(HttpServletRequest request, HttpServletResponse response) throws java.io.IOException, javax.servlet.ServletException {    /**@todo Override this org.apache.struts.action.ActionServlet method*/    request.setCharacterEncoding("GB2312");//ž®±åŠ ç€ä¸€è¡Œä¸€åˆ‡éƒ½è§£å†³äº?nbsp;   super.process(request, response);  }

当然别忘了改一下web.xml里面的配¾|?nbsp; <servlet>    <servlet-name>action</servlet-name>    <servlet-class>strutsdemo.myActionServlet</servlet-class>    <init-param>      <param-name>debug</param-name>      <param-value>2</param-value>    </init-param>    <init-param>      <param-name>config</param-name>      <param-value>/WEB-INF/struts-config.xml</param-value>    </init-param>    <load-on-startup>2</load-on-startup>  </servlet>

改一下servlet-class标签中的内容ž®±å¯ä»¥ï¼

真的可以åQŒä¸€åŠ³ç”¨yiåQ?BR>
具体¾~–码的理论就不说了,google上已¾lå¤Ÿå¤šäº†ã€?BR>
另外åQŒå¦‚果不用struts的话åQŒhibernate也可能碰åˆîC¸­æ–‡äؕ码问题,只要在hibernate.cfg.xml配置中如下:

<property name="hibernate.connection.url">   jdbc:microsoft:sqlserver://Localhost:1433;SelectMethod=cursor;characterEncoding=GBK;DatabaseName=myDatabase.  </property>

characterEncoding=GBKåQå°±å¯ä»¥äº†ã€?BR>


]]>JNI调用˜q‡ç¨‹http://www.aygfsteel.com/kyanite/archive/2005/08/10/9702.htmlkyanitekyaniteWed, 10 Aug 2005 02:30:00 GMThttp://www.aygfsteel.com/kyanite/archive/2005/08/10/9702.htmlhttp://www.aygfsteel.com/kyanite/comments/9702.htmlhttp://www.aygfsteel.com/kyanite/archive/2005/08/10/9702.html#Feedback0http://www.aygfsteel.com/kyanite/comments/commentRss/9702.htmlhttp://www.aygfsteel.com/kyanite/services/trackbacks/9702.html æœ€˜q‘在公司里做了一个手机的™å¹ç›®åQŒéœ€è¦JAVA½E‹åºåœ¨å‘送短信的时候和½W¬ä¸‰æ–¹çš„短信服务器连接。短信接口是用C++写的。琢¼‚¨äº†ä¸‰å¤©åQŒå¤§è‡´æžæ‡‚了JNI的主体部分。先ž®†å¿ƒå¾—整理,希望各位朋友ž®‘走弯èµ\ã€?BR>    é¦–先引用一½‹‡æ–‡ç« ï¼Œä»‹ç»ä¸€ä¸ªç®€å•çš„JNI的调用的˜q‡ç¨‹ã€?BR>    JAVA以其跨åã^台的ç‰ÒŽ€§æ·±å—äh们喜爱,而又正由于它的跨òq›_°çš„目的,使得它和本地机器的各¿Uå†…部联¾pÕd˜å¾—很ž®‘,¾U¦æŸäº†å®ƒçš„功能。解决JAVAå¯ÒŽœ¬åœ°æ“ä½œçš„一¿Uæ–¹æ³•就是JNIã€?nbsp;
    JAVA通过JNI调用本地æ–ÒŽ³•åQŒè€Œæœ¬åœ°æ–¹æ³•是以库文äšgçš„åŞ式存攄¡š„åQˆåœ¨WINDOWSòq›_°ä¸Šæ˜¯DLLæ–‡äšg形式åQŒåœ¨UNIX机器上是SOæ–‡äšg形式åQ‰ã€‚通过调用本地的库文äšg的内部方法,使JAVA可以实现和本地机器的紧密联系åQŒè°ƒç”¨ç³»¾lŸçñ”的各接口æ–ÒŽ³•ã€?nbsp;
    ½Ž€å•介¾låŠåº”用如下åQ?nbsp;
    ä¸€ã€JAVA中所需要做的工ä½?nbsp;
        åœ¨JAVA½E‹åºä¸­ï¼Œé¦–先需要在¾cÖM¸­å£°æ˜Žæ‰€è°ƒç”¨çš„库名称åQŒå¦‚下: 
  1.         static { 
  2.                  System.loadLibrary(“goodluckâ€?; 
  3.                }
 
        åœ¨è¿™é‡Œï¼Œåº“的扩展名字可以不用写出来,½I¶ç«Ÿæ˜¯DLL˜q˜æ˜¯SOåQŒç”±¾pȝ»Ÿè‡ªå·±åˆ¤æ–­ã€?nbsp;
        ˜q˜éœ€è¦å¯¹ž®†è¦è°ƒç”¨çš„æ–¹æ³•做本地声明åQŒå…³é”®å­—为nativeã€‚åÆˆä¸”åªéœ€è¦å£°æ˜Žï¼Œè€Œä¸éœ€è¦å…· ä½“实现。如下: 
        public native static void set(int i); 
        public native static int get(); 
        ç„¶åŽ¾~–译该JAVA½E‹åºæ–‡äšgåQŒç”ŸæˆCLASSåQŒå†ç”¨JAVAH命ä×oåQŒJNIž®×ƒ¼šç”ŸæˆC/C++的头文äšgã€?nbsp;
        ä¾‹å¦‚½E‹åºtestdll.javaåQŒå†…容䨓åQ?nbsp;
  1.         public class testdll 
  2.          { 
  3.            static 
  4.                  { 
  5.                   System.loadLibrary("goodluck"); 
  6.                  } 
  7.            public native static int get(); 
  8.            public native static void set(int i); 
  9.            public static void main(String[] args) 
  10.                 { 
  11.                   testdll test = new testdll(); 
  12.                   test.set(10); 
  13.                   System.out.println(test.get()); 
  14.                  } 
  15.            }
 
    ç”¨javac testdll.java¾~–译它,会生成testdll.classã€?nbsp;
    å†ç”¨javah testdllåQŒåˆ™ä¼šåœ¨å½“前目录下生成testdll.hæ–‡äšgåQŒè¿™ä¸ªæ–‡ä»‰™œ€è¦è¢«C/C++½E‹åºè°ƒç”¨æ¥ç”Ÿæˆæ‰€éœ€çš„库文äšgã€?nbsp;
    äºŒã€C/C++中所需要做的工ä½?nbsp;
    å¯¹äºŽå·²ç”Ÿæˆçš„.h头文ä»Óž¼ŒC/C++所需要做的,ž®±æ˜¯æŠŠå®ƒçš„各个方法具体的实现。然后编译连接成库文件即可。再把库文äšg拯‚´åˆ°JAVA½E‹åºçš„èµ\径下面,ž®±å¯ä»¥ç”¨JAVA调用C/C++所实现的功能了ã€?nbsp;
    æŽ¥ä¸Šä¾‹å­ã€‚我们先看一下testdll.hæ–‡äšg的内容: 
    /* DO NOT EDIT THIS FILE - it is machine generated */ 
    #include <jni.h> 
    /* Header for class testdll */ 
    #ifndef _Included_testdll 
    #define _Included_testdll 
    #ifdef __cplusplus 
    extern "C" { 
    #endif 
     /* 
      * Class: testdll 
      * Method: get 
      * Signature: ()I 
      */ 
    JNIEXPORT jint JNICALL Java_testdll_get (JNIEnv *, jclass); 
      /* 
       * Class: testdll 
       * Method: set 
       * Signature: (I)V 
       */ 
    JNIEXPORT void JNICALL Java_testdll_set (JNIEnv *, jclass, jint); 
    #ifdef __cplusplus 
                } 
    #endif 
    #endif 
    åœ¨å…·ä½“实现的时候,我们只关心两个函数原åž?nbsp;
    JNIEXPORT jint JNICALL Java_testdll_get (JNIEnv *, jclass); å’?nbsp;
    JNIEXPORT void JNICALL Java_testdll_set (JNIEnv *, jclass, jint); 
    ˜q™é‡ŒJNIEXPORTå’ŒJNICALL都是JNI的关键字åQŒè¡¨½Cºæ­¤å‡½æ•°æ˜¯è¦è¢«JNI调用的。而jint是以JNIä¸ÞZ¸­ä»‹ä‹ÉJAVAçš„int¾cÕdž‹ä¸Žæœ¬åœ°çš„int沟通的一¿Uç±»åž‹ï¼Œæˆ‘们可以视而不见,ž®±å½“做int使用。函数的名称是JAVA_再加上java½E‹åºçš„package路径再加函数名组成的。参æ•îC¸­åQŒæˆ‘们也只需要关心在JAVA½E‹åºä¸­å­˜åœ¨çš„参数åQŒè‡³äºŽJNIEnv*å’Œjclass我们一般没有必要去¼„°å®ƒã€?nbsp;
    å¥½ï¼Œä¸‹é¢æˆ‘们用testdll.cppæ–‡äšg具体实现˜q™ä¸¤ä¸ªå‡½æ•ŽÍ¼š 
    #include "testdll.h" 
    int i = 0; 
    JNIEXPORT jint JNICALL Java_testdll_get (JNIEnv *, jclass) 
      { 
       return i; 
      } 
    JNIEXPORT void JNICALL Java_testdll_set (JNIEnv *, jclass, jint j) 
      { 
       i = j; 
      } 
    ¾~–译˜qžæŽ¥æˆåº“æ–‡äšgåQŒæœ¬ä¾‹æ˜¯åœ¨WINDOWS下做的,生成的是DLLæ–‡äšgã€‚åÆˆä¸”å¿U°è¦ä¸ŽJAVA中需要调用的一è‡ß_¼Œ˜q™é‡Œž®±æ˜¯goodluck.dll ã€‚把goodluck.dll拯‚´åˆ°testdll.class的目录下åQŒjava testdll˜qè¡Œå®ƒï¼Œž®±å¯ä»¥è§‚察到¾l“果了ã€?nbsp;
我的™å¹ç›®æ¯”较复杂åQŒéœ€è¦è°ƒç”¨åŠ¨æ€é“¾æŽ¥åº“åQŒè¿™æ ·åœ¨JNI传送参数到C½E‹åºæ—Óž¼Œéœ€è¦å¯¹å‚æ•°˜q›è¡Œå¤„理转换。才可以被C½E‹åºè¯†åˆ«ã€?BR>大体½E‹åºå¦‚下åQ?BR>
  1. public class SendSMS {
  2. static
  3.     {
  4.       System.out.println(System.getProperty("java.library.path"));
  5.       System.loadLibrary("sms");
  6.     }
  7.     public native static int SmsInit();
  8.     public native static int SmsSend(byte[] mobileNo, byte[] smContent);
  9. }

在这里要注意的是åQŒpath里一定要包含¾cÕdº“çš„èµ\径,否则在程序运行时会抛出异常:
java.lang.UnsatisfiedLinkError: no sms in java.library.path
    at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1491)
         at java.lang.Runtime.loadLibrary0(Runtime.java:788)
         at java.lang.System.loadLibrary(System.java:834)
         at com.mobilesoft.sms.mobilesoftinfo.SendSMS.<clinit>(SendSMS.java:14)
    at com.mobilesoft.sms.mobilesoftinfo.test.main(test.java:18)
Exception in thread "main"
指引的èµ\径应该到.dllæ–‡äšg的上一¾U§ï¼Œå¦‚果指到.dllåQŒåˆ™ä¼šæŠ¥åQ?BR>java.lang.UnsatisfiedLinkError: C:\sms.dll: Can't find dependent libraries
         at java.lang.ClassLoader$NativeLibrary.load(Native Method)
at java.lang.ClassLoader.loadLibrary0(ClassLoader.java:1560)
         at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1485)
         at java.lang.Runtime.loadLibrary0(Runtime.java:788)
         at java.lang.System.loadLibrary(System.java:834)
         at com.mobilesoft.sms.mobilesoftinfo.SendSMS.<clinit>(SendSMS.java:14)
         at com.mobilesoft.sms.mobilesoftinfo.test.main(test.java:18)
Exception in thread "main"
通过¾~–译åQŒç”Ÿæˆcom_mobilesoft_sms_mobilesoftinfo_SendSMS.hå¤´æ–‡ä»¶ã€‚ï¼ˆå»ø™®®ä½¿ç”¨Jbuilder˜q›è¡Œ¾~–译åQŒæ“ä½œæ¯”较简单!åQ‰è¿™ä¸ªå¤´æ–‡äšgž®±æ˜¯Javaå’ŒC之间的纽带。要特别注意的是æ–ÒŽ³•中传递的参数jbyteArrayåQŒè¿™åœ¨æŽ¥ä¸‹æ¥çš„过½E‹ä¸­ä¼šé‡ç‚¹ä»‹¾lã€?BR>
  1. /* DO NOT EDIT THIS FILE - it is machine generated */
  2. #include <jni.h>
  3. /* Header for class com_mobilesoft_sms_mobilesoftinfo_SendSMS */
  4. #ifndef _Included_com_mobilesoft_sms_mobilesoftinfo_SendSMS
  5. #define _Included_com_mobilesoft_sms_mobilesoftinfo_SendSMS
  6. #ifdef __cplusplus
  7. extern "C" {
  8. #endif
  9. /*
  10.  * Class:     com_mobilesoft_sms_mobilesoftinfo_SendSMS
  11.  * Method:    SmsInit
  12.  * Signature: ()I
  13.  */
  14. JNIEXPORT jint JNICALL Java_com_mobilesoft_sms_mobilesoftinfo_SendSMS_SmsInit
  15.   (JNIEnv *, jclass);
  16. /*
  17.  * Class:     com_mobilesoft_sms_mobilesoftinfo_SendSMS
  18.  * Method:    SmsSend
  19.  * Signature: ([B[B)I
  20.  */
  21. JNIEXPORT jint JNICALL Java_com_mobilesoft_sms_mobilesoftinfo_SendSMS_SmsSend
  22.   (JNIEnv *, jclass, jbyteArray, jbyteArray);
  23. #ifdef __cplusplus
  24. }
  25. #endif
  26. #endif

对于我要调用的C½E‹åºçš„动态链接库åQŒC½E‹åºä¹Ÿè¦æä¾›ä¸€ä¸ªå¤´æ–‡äšgåQŒsms.h。这个文件将要调用的æ–ÒŽ³•¾|—列了出来ã€?BR>
  1. /*
  2.  * SMS API 
  3.  * Author: yippit
  4.  * Date: 2004.6.8
  5.  */
  6. #ifndef MCS_SMS_H
  7. #define MCS_SMS_H
  8. #define DLLEXPORT __declspec(dllexport)
  9. /*sms storage*/
  10. #define SMS_SIM        0
  11. #define SMS_MT        1
  12. /*sms states*/
  13. #define SMS_UNREAD        0
  14. #define SMS_READ            1
  15. /*sms type*/
  16. #define SMS_NOPARSE        -1
  17. #define SMS_NORMAL        0
  18. #define SMS_FLASH            1
  19. #define SMS_MMSNOTI        2
  20. typedef struct tagSmsEntry {
  21.     int index;        /*index, start from 1*/
  22.     int status;        /*read, unread*/
  23.     int type;            /*-1-can't parser 0-normal, 1-flash, 2-mms*/
  24.     int storage;    /*SMS_SIM, SMS_MT*/
  25.     char date[24];
  26.     char number[32];
  27.     char text[144];
  28. } SmsEntry;
  29. DLLEXPORT int SmsInit(void);
  30. DLLEXPORT int SmsSend(char *phonenum, char *content);
  31. DLLEXPORT int SmsSetSCA(char *sca);
  32. DLLEXPORT int SmsGetSCA(char *sca);
  33. DLLEXPORT int SmsSetInd(int ind);
  34. DLLEXPORT int SmsGetInd(void);
  35. DLLEXPORT int SmsGetInfo(int storage, int *max, int *used);
  36. DLLEXPORT int SmsSaveFlash(int flag);
  37. DLLEXPORT int SmsRead(SmsEntry *entry, int storage, int index); 
  38. DLLEXPORT int SmsDelete(int storage, int index);
  39. DLLEXPORT int SmsModifyStatus(int storage, int index); /*unread -> read*/
  40. #endif

在有了这两个头文件之后,ž®±å¯ä»¥è¿›è¡ŒC½E‹åºçš„编写了。也ž®±æ˜¯å®žçް坹JNI调用的两个方法。在¾|‘上的资料中åQŒç”±äºŽè°ƒç”¨çš„æ–ÒŽ³•实现的都比较½Ž€å•,åQˆå¤§å¤šæ˜¯æ‰“印字符串等åQ‰æ‰€ä»¥é¿å¼€äº†JNI中最éºÈƒ¦çš„部分,也是最关键的部分,参数的传递。由于Javaå’ŒC的编码是不同的,所以传递的参数是要˜q›è¡Œå†å¤„理,否则C½E‹åºæ˜¯ä¼šå¯¹å‚数在¾~–译˜q‡ç¨‹ä¸­æå‡ø™­¦å‘Šï¼Œä¾‹å¦‚åQ›warning C4024: 'SmsSend' : different types for formal and actual parameter 2½{‰ã€?BR>Sms.c的程序如下:
  1. #include "sms.h"
  2. #include "com_mobilesoft_sms_mobilesoftinfo_SendSMS.h"
  3. JNIEXPORT jint JNICALL Java_com_mobilesoft_sms_mobilesoftinfo_SendSMS_SmsInit(JNIEnv * env, jclass jobject)
  4. {
  5.     return SmsInit();
  6. }
  7. JNIEXPORT jint JNICALL Java_com_mobilesoft_sms_mobilesoftinfo_SendSMS_SmsSend(JNIEnv * env, jclass jobject, jbyteArray mobileno, jbyteArray smscontent)
  8. {
  9.     char * pSmscontent ;
  10.     //jsize theArrayLengthJ = (*env)->GetArrayLength(env,mobileno);
  11.     jbyte * arrayBody = (*env)->GetByteArrayElements(env,mobileno,0);
  12.     char * pMobileNo = (char *)arrayBody;
  13.     printf("[%s]\n ", pMobileNo);
  14.     //jsize size = (*env)->GetArrayLength(env,smscontent);
  15.     arrayBody = (*env)->GetByteArrayElements(env,smscontent,0);
  16.     pSmscontent = (char *)arrayBody;
  17.     printf("<%s>\n", pSmscontent);
  18.     return SmsSend(pMobileNo,pSmscontent); 
  19. }

对于C或C++åQŒåœ¨½E‹åºä¸Šæ˜¯ä¼šæœ‰½Eå¾®çš„不同,˜q™å¯ä»¥ç”±è¯»è€…对其进行适当的修攏V€‚这里要注意的是GetArrayLengthåQŒGetByteArrayElements½{‰è¿™äº›JNI中已¾låŒ…含的æ–ÒŽ³•åQŒè¿™äº›æ–¹æ³•是专门对è{换参数类型而提供的。具体的æ–ÒŽ³•有很多,在下一½‹‡ä¸­ä¼šåšä¸“门的介¾lã€?BR>在完成了上述的文件后åQŒå¯ä»¥å¯¹sms.c˜q›è¡Œ¾~–译åQŒç”Ÿæˆ?dllæ–‡äšgåQˆå¾è®®åœ¨release中编译,˜q™æ ·åŠ¨æ€é“¾æŽ¥åº“çš„å®¹¿U¯ä¼šæ¯”较ž®ï¼åQ?BR>完成.dllæ–‡äšg的编译后åQŒå°±å¯ä»¥åœ¨Java中调用C½E‹åºä¸­çš„æ–ÒŽ³•了。例如文件test.java
  1. public class test {
  2.   public test() {
  3.   }
  4.   public static void main(String[] args) {
  5.     byte[] mobileno = {
  6.         0x31, 0x33, 0x36, 0x36, 0x31, 0x36, 0x33, 0x30, 0x36, 0x36, 0x37, 0x00};
  7.     String smscontentemp = "早上å¥?;
  8.     byte[] temp = {0};
  9.    try {
  10.       byte[] smscontentdb = smscontentemp.getBytes("gbk");
  11.       byte[] smscontent = new byte[smscontentdb.length + temp.length];
  12.       System.arraycopy(smscontentdb, 0, smscontent, 0, smscontentdb.length);
  13.       System.arraycopy(temp, 0, smscontent, smscontentdb.length, temp.length);
  14.       SendSMS sendSMS = new SendSMS();
  15.       sendSMS.SmsInit();
  16.       if (sendSMS.SmsSend(mobileno, smscontent) >= 0) {
  17.         System.out.println("chenggong !");
  18.       }
  19.       else {
  20.         System.out.println("shibai !");
  21.       }
  22.     }catch (Exception ex) {}
  23.   }
  24. }

在这个文件中要注意的有一点,ž®±æ˜¯åœ¨ä¼ é€’字节数¾l„到C½E‹åºä¸­æ—¶åQŒæœ€åŽçš„¾l“尾一定要ä»?¾l“束。这是一个偷懒的做法åQŒä¸˜q‡æ˜¯ä¸ªæœ‰æ•ˆçš„做法。因为大多数情况下,接口是由½W¬ä¸‰æ–ÒŽä¾›çš„。所以我们一般是不知道在C的方法里åQŒå…·ä½“是怎么处理参数的。而C又是要求数组是有长度。所以,在Java中,如果你不惛_†™½E‹åºä¼ æ•°¾l„的长度åQŒé‚£ä¹ˆåœ¨æ•°ç»„中以0¾l“å°¾ž®±æ˜¯æœ€æ–¹ä¾¿çš„æ–¹æ³•了。当ç„Óž¼Œå¦‚果有更好的æ–ÒŽ³•也希望大家提出ã€?BR>到这里,一个完整的Java通过JNI调用动态链接库的程序就完成了。实际上也不是很复杂。只要多注意一下细节,是很å®ÒŽ˜“得出来的ã€?BR>

]]>
个äh½Ž€åŽ?/title><link>http://www.aygfsteel.com/kyanite/archive/2005/08/01/8953.html</link><dc:creator>kyanite</dc:creator><author>kyanite</author><pubDate>Mon, 01 Aug 2005 12:36:00 GMT</pubDate><guid>http://www.aygfsteel.com/kyanite/archive/2005/08/01/8953.html</guid><wfw:comment>http://www.aygfsteel.com/kyanite/comments/8953.html</wfw:comment><comments>http://www.aygfsteel.com/kyanite/archive/2005/08/01/8953.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.aygfsteel.com/kyanite/comments/commentRss/8953.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/kyanite/services/trackbacks/8953.html</trackback:ping><description><![CDATA[     摘要: 个äh½Ž€ä»?  个äh基本½Ž€åŽ†ã€€ã€€î—¥î—¥î—¥ã€€ã€€ã€€ã€€ã€€ã€€ã€€ã€€ã€€î—¥î—¥ã€€ã€€ã€€ã€€ã€€ã€€                          ...  <a href='http://www.aygfsteel.com/kyanite/archive/2005/08/01/8953.html'>阅读全文</a><img src ="http://www.aygfsteel.com/kyanite/aggbug/8953.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/kyanite/" target="_blank">kyanite</a> 2005-08-01 20:36 <a href="http://www.aygfsteel.com/kyanite/archive/2005/08/01/8953.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Company's URLhttp://www.aygfsteel.com/kyanite/archive/2005/08/01/8952.htmlkyanitekyaniteMon, 01 Aug 2005 12:35:00 GMThttp://www.aygfsteel.com/kyanite/archive/2005/08/01/8952.htmlhttp://www.aygfsteel.com/kyanite/comments/8952.htmlhttp://www.aygfsteel.com/kyanite/archive/2005/08/01/8952.html#Feedback0http://www.aygfsteel.com/kyanite/comments/commentRss/8952.htmlhttp://www.aygfsteel.com/kyanite/services/trackbacks/8952.htmlhttp://www.ea.com.cn/
http://www.novemsoft.com/
http://www.novemsoft.com/
http://www30.sap.com/china/index.aspx
http://default.baosight.com/Baosight/frontpages/Main.baosight
http://www.sunsystems.cn/
http://www.worksoft.com.cn/
http://www.accenture.com/xd/xd.asp?it=cnweb&xd=locations/china/china_home.xml
http://www.altigen.com.cn/DEFAULT.ASP
http://www.alcatel-sbell.com.cn/index.asp
http://www.shifang.com.cn/
https://www.ubisoft.com.cn/index/index.aspx
http://www.sysmex.com.cn/
http://www.symbio.com.cn/index.html

]]>
准备研究一下jsp的上传下载了http://www.aygfsteel.com/kyanite/archive/2005/07/01/7014.htmlkyanitekyaniteFri, 01 Jul 2005 14:09:00 GMThttp://www.aygfsteel.com/kyanite/archive/2005/07/01/7014.htmlhttp://www.aygfsteel.com/kyanite/comments/7014.htmlhttp://www.aygfsteel.com/kyanite/archive/2005/07/01/7014.html#Feedback5http://www.aygfsteel.com/kyanite/comments/commentRss/7014.htmlhttp://www.aygfsteel.com/kyanite/services/trackbacks/7014.html潇湘子的开发包和jakata 开源项目的fileupload开发包。由于项目开发需要,准备èŠ×ƒ¸‰å¤©æ—¶é—ß_¼Œç ”ç©¶˜q™ä¸ªæœºåˆ¶åQŒå¯æƒœæ²¡æœ‰æºä»£ç åQŒå‘µå‘µï¼ŒokåQŒå¥½å¥½çœ‹äº?img src ="http://www.aygfsteel.com/kyanite/aggbug/7014.html" width = "1" height = "1" />

]]>
一些往äº?/title><link>http://www.aygfsteel.com/kyanite/archive/2005/06/25/6707.html</link><dc:creator>kyanite</dc:creator><author>kyanite</author><pubDate>Sat, 25 Jun 2005 08:46:00 GMT</pubDate><guid>http://www.aygfsteel.com/kyanite/archive/2005/06/25/6707.html</guid><wfw:comment>http://www.aygfsteel.com/kyanite/comments/6707.html</wfw:comment><comments>http://www.aygfsteel.com/kyanite/archive/2005/06/25/6707.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.aygfsteel.com/kyanite/comments/commentRss/6707.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/kyanite/services/trackbacks/6707.html</trackback:ping><description><![CDATA[ç”׃ºŽæœ€˜q‘事情比较多åQŒæ¢äº†æ–°çš„环境,不过很快ž®±é€‚应了!前几天我的几个兄弟,准备åŽÀLµ™æ±Ÿæ…ˆæºªï¼Œåƒæ¨æ¢…!åŽÕd¹´çš„äÍ˜q‘毕业的时候,那可是每天晚上都åŽÕd¤œå®µï¼Œå¾ˆæ˜¯happy。è{眼毕业一òqß_¼Œæ™šä¸Šå’Œä¸€å¸®å…„弟通了电话åQŒä¹Ÿè®¸ç”Ÿ‹z»è¿˜æ˜¯ä¾æ—§ï¼½Hç„¶æåˆ°ä»¥å‰çš„é‚£ä½ã€‚æ˜¯å•Šï¼Œå¥½ä¹…æ²¡æœ‰è”ç³»äº†ï¼Œä¸çŸ¥é“å¥¹çŽ°åœ¨æ€Žä¹ˆæ øP¼Œž®±åœ¨˜q™é‡Œ¼œç¦å¥¹ï¼é€šå®Œç”µè¯åQŒå°±æ€Žä¹ˆä¹Ÿç¡ä¸ç€è§‰äº†åQåœ¨å¤–面的日子很自由åQŒä½†æœ‰æ—¶å€™ä¹Ÿå¾ˆæ— å¥ˆï¼Œ˜q™å°±æ˜¯ç”Ÿ‹zÕd§åQŒäؓ了梦æƒ?.....<img src ="http://www.aygfsteel.com/kyanite/aggbug/6707.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/kyanite/" target="_blank">kyanite</a> 2005-06-25 16:46 <a href="http://www.aygfsteel.com/kyanite/archive/2005/06/25/6707.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>¾lˆäºŽå¼€å§‹è¦åšé¡¹ç›®äº†http://www.aygfsteel.com/kyanite/archive/2005/06/24/6664.htmlkyanitekyaniteFri, 24 Jun 2005 05:29:00 GMThttp://www.aygfsteel.com/kyanite/archive/2005/06/24/6664.htmlhttp://www.aygfsteel.com/kyanite/comments/6664.htmlhttp://www.aygfsteel.com/kyanite/archive/2005/06/24/6664.html#Feedback0http://www.aygfsteel.com/kyanite/comments/commentRss/6664.htmlhttp://www.aygfsteel.com/kyanite/services/trackbacks/6664.html˜q™æ®µæ—‰™—´å¿™æ´»äº†å‡ å¤©ï¼Œ¾lˆäºŽæŠŠé¡¹ç›®éœ€è¦ç”¨çš„资源申请到了。开始努力做™å¹ç›®åQŒæˆ‘们现在的™å¹ç›®å‡†å¤‡é‡‡ç”¨eclipse开发,刚开始接触,以后多来˜q™é‡Œå‘ç‰›äºø™¯·æ•™äº†åQ?/P>

]]>
Ö÷Õ¾Ö©Öë³ØÄ£°å£º ½»³ÇÏØ| Î÷ÇàÇø| ÌØ¿ËË¹ÏØ| ÐóÇÏØ| ÓñÁú| Ô«ÇúÏØ| ±¦É½Çø| ÉîÔóÏØ| ÍþÐÅÏØ| ¾²º£ÏØ| ÃÉ×ÔÏØ| ¸·ÄÏÏØ| ·áÌ¨Çø| ÒÁ´¨ÏØ| ÄôÀ­Ä¾ÏØ| »ñ¼ÎÏØ| ³Ç¿ÚÏØ| ÓÀ¾¸ÏØ| ±±´¨| ´óÆÒÇø| ÒÁÄþÊÐ| ÇßÔ´ÏØ| ÓݳÇÏØ| ÉîÛÚÊÐ| Óà¸ÉÏØ| ÆÖ¶«ÐÂÇø| ÓÀµÇÏØ| Æ½Ì¶ÏØ| SHOW| ¹þÃÜÊÐ| »ªÆºÏØ| Ã÷Ë®ÏØ| ¸ßÒªÊÐ| Ä®ºÓÏØ| ½ðÌÃÏØ| ³¤×ÓÏØ| ÒÊÄÏÏØ| ÓàÇìÏØ| ÐÁ¼¯ÊÐ| ÉÐÖ¾ÊÐ| ÔæÑôÊÐ|