??xml version="1.0" encoding="utf-8" standalone="yes"?> Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=1448910
]]>
]]>
当应用服务器初始化servlet实例之后Qؓ(f)客户端请求提供服务之前,它会(x)调用q个servlet的init()Ҏ(gu)。在一个servlet的生命周
期中Qinit()Ҏ(gu)只会(x)被调用一ơ。通过在init()Ҏ(gu)中缓存一些静(rn)态的数据或完成一些只需要执行一ơ的、耗时的操作,可大大地提高系l性能?br />
例如Q通过在init()Ҏ(gu)中徏立一个JDBCq接池是一个最佳例子,假设我们是用jdbc2.0的DataSource接口来取得数据库q接Q在?
常的情况下,我们需要通过JNDI来取得具体的数据源。我们可以想象在一个具体的应用中,如果每次SQLh都要执行一ơJNDI查询的话Q那pȝ性能?
?x)急剧下降。解x法是如下代码Q它通过~存DataSourceQ得下一ơSQL调用时仍然可以l利用它Q?br />
public class ControllerServlet extends HttpServlet
{
private javax.sql.DataSource testDS = null;
public void init(ServletConfig config) throws ServletException
{
super.init(config);
Context ctx = null;
try
{
ctx = new InitialContext();
testDS = (javax.sql.DataSource)ctx.lookup("jdbc/testDS");
}
catch(NamingException ne)
{
ne.printStackTrace();
}
catch(Exception e)
{
e.printStackTrace();
}
}
public javax.sql.DataSource getTestDS()
{
return testDS;
}
...
...
}
Ҏ(gu) 2:止servlet和JSP 自动重蝲(auto-reloading)
Servlet/JSP提供?jin)一个实用的技术,卌动重载技术,它ؓ(f)开发h员提供了(jin)一个好的开发环境,当你改变servlet和JSP面后而不必重?
应用服务器。然而,q种技术在产品q行阶段对系l的资源是一个极大的损耗,因ؓ(f)它会(x)lJSP引擎的类装蝲?classloader)带来极大的负担。因
此关闭自动重载功能对pȝ性能的提升是一个极大的帮助?br />
Ҏ(gu) 3: 不要滥用HttpSession
在很多应
用中Q我们的E序需要保持客L(fng)的状态,以便面之间可以怺联系。但不幸的是׃HTTPh天生无状态性,从而无法保存客L(fng)的状态。因此一般的应用
服务器都提供?jin)session来保存客L(fng)状态。在JSP应用服务器中Q是通过HttpSession对像来实现session的功能的Q但在方便的?
Ӟ它也l系l带来了(jin)不小的负担。因为每当你获得或更新sessionӞpȝ者要对它q行Ҏ(gu)的序列化操作。你可以通过对HttpSession的以?
几种处理方式来提升系l的性能Q?br />
? 如果没有必要Q就应该关闭JSP面中对HttpSession的缺省设|:(x) 如果你没有明指定的话,每个JSP面都会(x)~省地创Z个HttpSession。如果你的JSP中不需要用session的话Q那可以通过如下的JSP面指示W来止它:(x)
Q?@ page session="false"%Q?
?
不要在HttpSession中存攑֤的数据对像:(x)如果你在HttpSession中存攑֤的数据对像的话,每当对它q行dӞ应用服务器都对其进?
序列化,从而增加了(jin)pȝ的额外负担。你在HttpSession中存攄数据对像大Q那pȝ的性能׃降得快?br />
? 当你不需要HttpSessionӞ快地释攑֮Q当你不再需要sessionӞ你可以通过调用HttpSession.invalidate()Ҏ(gu)来释攑֮?br />
?
量session的超时时间设得短一点:(x)在JSP应用服务器中Q有一个缺省的session的超时时间。当客户在这个时间之后没有进行Q何操作的话,
pȝ?x)将相关的session自动从内存中释放。超时时间设得越大,pȝ的性能׃(x)低Q因此最好的Ҏ(gu)是量使得它的g持在一个较低的水^?br />
Ҏ(gu) 4: 页面输?gu)行压~?br />
压羃是解x据冗余的一个好的方法,特别是在|络带宽不够发达的今天。有的浏览器支持gzip(GNU
zip)q行来对HTML文gq行压羃Q这U方法可以戏剧性地减少HTML文g的下载时间。因此,如果你将servlet或JSP面生成的HTML面
q行压羃的话Q那用户׃(x)觉得面览速度?x)非常快。但不幸的是Q不是所有的览器都支持gzip压羃Q但你可以通过在你的程序中(g)查客L(fng)览器是否支
持它。下面就是关于这U方法实现的一个代码片D:(x)
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException
{
OutputStream out = null
String encoding = request.getHeader("Accept-Encoding");
if (encoding != null && encoding.indexOf("gzip") != -1)
{
request.setHeader("Content-Encoding" , "gzip");
out = new GZIPOutputStream(request.getOutputStream());
}
else if (encoding != null && encoding.indexOf("compress") != -1)
{
request.setHeader("Content-Encoding" , "compress");
out = new ZIPOutputStream(request.getOutputStream());
}
else
{
out = request.getOutputStream();
}
...
...
}
Ҏ(gu) 5: 使用U程?br />
应用服务器缺省地为每个不同的客户端请求创Z个线E进行处理,qؓ(f)它们分派service()Ҏ(gu)Q当service()Ҏ(gu)调用完成后,与之相应?
U程也随之撤消。由于创建和撤消U程?x)耗费一定的pȝ资源Q这U缺省模式降低了(jin)pȝ的性能。但所q的是我们可以通过创徏一个线E池来改变这U状c(din)另外,
我们q要个线E池讄一个最线E数和一个最大线E数。在应用服务器启动时Q它?x)创建数量等于最线E数的一个线E池Q当客户有请求时Q相应地从池?
取出一个线E来q行处理Q当处理完成后,再将U程重新攑օ到池中。如果池中的U程不够地话Q系l会(x)自动地增加池中线E的数量Q但总量不能过最大线E数?
通过使用U程池,当客L(fng)h急剧增加Ӟpȝ的负载就?x)呈现的qx的上升曲U,从而提高的pȝ的可伸羃性?br />
Ҏ(gu) 6: 选择正确的页面包含机?br />
在JSP中有两种Ҏ(gu)可以用来包含另一个页面:(x)1、用include指示W?Q?@ includee file=”test.jsp”
%Q??、用jsp指示W?Qjsp:includee page=”test.jsp”
flush=”true”/Q?。在实际中我发现Q如果用第一U方法的话,可以使得pȝ性能更高?br />
Ҏ(gu) 7:正确地确定javabean的生命周?br />
JSP的一个强大的地方是对javabean的支持。通过在JSP面中用<jsp:useBeanQ标{,可以javabean直接插入C个JSP面中。它的用方法如下:(x)
Qjsp:useBean id="name" scope="page|request|session|application" class=
"package.className" type="typeName"Q?br />
Q?jsp:useBeanQ?
其中scope属性指Z(jin)q个bean的生命周期。缺省的生命周期为page。如果你没有正确地选择bean的生命周期的话,它将影响pȝ的性能?br />
举例来说Q如果你只想在一ơ请求中使用某个beanQ但你却这个bean的生命周期设|成?jin)sessionQ那当这ơ请求结束后Q这个bean仍?
保留在内存中Q除非session时或用户关闭浏览器。这样会(x)耗费一定的内存Qƈ无谓的增加了(jin)JVM垃圾攉器的工作量。因此ؓ(f)bean讄正确的生?
周期Qƈ在bean的命结束后快地清理它们,?x)用系l性能有一个提?br />
其它一些有用的Ҏ(gu)
?
在字W串q接操作中尽量不使用“Q?#8221;操作W:(x)在java~程中,我们常常使用“Q?#8221;操作W来几个字W串q接hQ但你或总来没有想到过它居然会(x)对系l?
性能造成影响吧?׃字符串是帔RQ因此JVM?x)生一些(f)时的对像。你使用?#8220;Q?#8221;多Q生成的临时对像p多,q样也会(x)l系l性能带来一些媄(jing)响。解?
的方法是用StringBuffer对像来代?#8220;Q?#8221;操作W?br />
?
避免使用System.out.println()Ҏ(gu)Q由于System.out.println()是一U同步调用,卛_调用它时Q磁盘I(y)/O操作?
ȝ待它的完成,因此我们要尽量避免对它的调用。但我们在调试程序时它又是一个必不可的方便工具Qؓ(f)?jin)解册个矛盾,我徏议你最好用Log4j工具
(http://Jakarta.apache.org )Q它既可以方便调试,而不?x)生System.out.println()q样的方法?br />
? ServletOutputStream ?
PrintWriter的权?使用PrintWriter可能?x)带来一些小的开销Q因为它?yu)所有的原始输出都{换ؓ(f)字符来输出Q因此如果用它来作?
面输出的话Q系l要负担一个{换过E。而用ServletOutputStream作ؓ(f)面输出的话׃存在一个问题,但它是以二进制进行输出的。因
此在实际应用中要权衡两者的利弊?br />
ȝ
本文的目的是通过对servlet和JSP的一些调优技术来极大地提高你
的应用程序的性能Qƈ因此提升整个J2EE应用的性能。通过q些调优技术,你可以发现其实ƈ不是某种技术^収ͼ比如J2EE?NET之争Q决定了(jin)你的?
用程序的性能Q重要是你要对这U^台有一个较为深入的?jin)解Q这样你才能从根本上对自q应用E序做一个优化!
]]>
]]>
public final class index_jsp extends HttpJspBase
implements JspSourceDependent
//上述cMؓ(f)index.jsp被编译后得到的类
//HttpJspBase是extends HttpServlet的一个类
//JspSourceDependent是一个接口,只声明了(jin)一个方法、、getDependants(),q回当前page所依赖的文件的名称Q文件包括以下几U?br />
//1) files that are included by page directives
//2) files that are included by include-prelude and include-coda in jsp:config
//3) files that are tag files and referenced
//4) TLDs referenced
其核?j)方法?f)Q?br />
throws IOException, ServletException{
.
}
]]>
annotation实际上就是给一些特定的cd其属性,Ҏ(gu){加上一些注?annotation),q些注释是以属性name,valueq行讄的,q些属性在Annotation Class中以Ҏ(gu)的Ş式存在,如下Q?
@Target(java.lang.annotation.ElementType.METHOD) //应用目标Q这里是应用到field属性上?br />
@Retention(RetentionPolicy.RUNTIME) //该策略指明该注释?x)被加蝲到jvm中,卛_q行Ӟ我们可以得到该注释的内容Q另外两个策略,SOURCE, CLASS都不?x)加载到jvm?br />
public @interface TestAnnoation {
String value(); //属性value
String time(); //属性time
}
@TestAnnoation(time="12:30",value="20")
public String test(){
System.out.println("test!");
return null;
};
}
可以使用java的反来q行获取Q通过Q?br />
cls.isAnnotationPresent(AnnotationClass.class);//判断是否存在annotation
TestAnnotation ta = (TestAnnotation)cls.getAnnotation(AnnotationClass.class);//获得AnnotationClass实例Q后调用q个实例可以获得在AnnotationClass中定义的一些属?/span>
System.out.println(ta.time()); //输出注释time内容
System.out.println(ta.value()); //输出注释value内容
我个为annotation的好处是一些配|直接写在代码上Q很直观Q以前在使用hibernate的时候,PO对象和对应的mapping xml是分开的,不够直观Q若是用annotation׃(x)很直观的看出q个对象的映属性以?qing)它的一些特D属性(如lazy=trueQ之cȝQ在JPA中就把这U配|方式换成了(jin)annotation?br />
在JE上有很多关于使用annotation和xml的争论,我认为在规模用上可以使用annotationQ就像JPAq种Q每个PO上面都需要进行配|,即使用XML也不能简化;而在大规模用,如spring所l护的一些service的事务配|上避免使用annotationQ因为每个servicecM都需要配|,而用AOPҎ(gu)XML配置可以一下就搞定?br />
关于ElementType的其他属性:(x)
TYPE(cd), FIELD(属?, METHOD(Ҏ(gu)), PARAMETER(参数),
CONSTRUCTOR(构造函?,LOCAL_VARIABLE(局部变?,
ANNOTATION_TYPE,PACKAGE(?,其中的TYPE(cd)是指可以用在Class,Interface,Enum?
Annotationcd?
]]>
?a keyid="1414" class="keyword_ad">l石的Ş成,主要原因是饮食。它是由饮食中可形成l石的有x分摄入过多引L(fng)。再l一点解释是Q?
草酸U存q多。体内草酸的大量U存Q是D肑ְl石?
因素之一。如菠菜、豆cR葡萄、可可、茶叶、桔子、番茄、土豆、李子、竹W等q些Z普遍爱吃的东西,正是含草酸较高的食物。医生通过研究发现Q?00?
菠菜中,含草?25.6毫克Q如果一Zơ将200克菠菜全部吃掉,食后8时Q检查尿中草酸排泄量?0-25毫克Q相当于正常?4时排出的草?
q_总量?
嘌呤代谢失常。动物内脏、v产食品、花生、豆角、菠菜等Q均含有较多的嘌呤成分。嘌呤进入体内后Q要q行新陈代谢Q它代谢的最l物是K。尿酸可?j)ɞ中草酸盐沉淀(wn)。如果,一ơ过多地食用?jin)含嘌呤丰富的食物,嘌呤的代谢又失常Q草酸盐便在中沉积而Ş成尿l石?
脂肪摄取太多。各U动物的肉类Q尤其是肥猪肉,都是脂肪多的食品。多吃了(jin)体内脂肪必然增高Q脂肪会(x)减少肠道中可l合的钙Q因而引起对草酸盐的吸收增多Q如果一旦出现排泄功能故障,如出汗多、喝水少Q尿量少Q肾l石很可能就在这U情况下形成。所以,ȝ们常ԌZ(jin)预防?a keyid="1414" class="keyword_ad">l石病,热天要多喝点_(d)吃了(jin)Ҏ(gu)多的食物Ӟ也要多喝Ҏ(gu)Q以?j)进排尿畅通,E释尿液成分,减了(jin)?a keyid="1414" class="keyword_ad">l石的危险?
p分增高。糖是h体的重要dQ要l常适量增补Q但一下子增加太多Q尤其是乳糖Q也?x)?a keyid="1414" class="keyword_ad">l石形成创造条件。专家们发现Q不论正思h?a keyid="1414" class="keyword_ad">l石病hQ在食用100克蔗p后Q过2时L查他们的,发现中的钙和草酸浓度均上升Q若是服用^p,它更能促(j)q钙的吸Ӟ更可能导致草酔R在体内的U存而Ş成尿l石?
蛋白质过量。对?a keyid="1414" class="keyword_ad">l石成分q行化验分析Q发?a keyid="1414" class="keyword_ad">l石中的草酸钙占87.5Q。这么大比重的草酔R的来源就是因白质里除含有草酸的原料——甘氨酸、羟脯}怹外,蛋白质还能促(j)q肠道功能对钙的吸收。如果经常过量食用高蛋白质的食物Q便使肾脏和中的钙、草酸、尿酸的成分普遍增高。如果不能及(qing)时有效地通过肾脏功能把多余的钙、草酸、尿酸排Z外,q样Q得肾脏l石、输管l石症的条gŞ成了(jin)。当今世界经发辑֛家肾l石发病?a keyid="1570" class="keyword_ad">增高的主要原因就是如此?
从以上几U易形成?a keyid="1414" class="keyword_ad">l石的因素来看,要预防肾l石?
的发生,必L变只֍求一U营dq求营养q甚的观c(din)这是_(d)在hcȝ日常饮食中,不能因ؓ(f)某种食物好吃、营Mh(hun)值高Q就一呛_只顾dq种?
物。必L意食物的搭配Q各U食物都适量q食Q即使是(g)查出w体~Z某种营养素需要某U食物来补充Ӟ也不宜一ơ大量进食,因ؓ(f)Z?a keyid="1526" class="keyword_ad">消化、吸收功能是有限的?a keyid="1526" class="keyword_ad">消化、吸收不?jin)的dp通过排泄器官排泄出去Q这样也?x)增?a keyid="1446" class="keyword_ad">泌尿p?/a>l的负担Q即便不(zhn)肾l石病,也对健康不利。特别是当检查出认是肾l石症时Q在(zhn)病期间Q要限制病h吃那些易?j)?a keyid="1414" class="keyword_ad">l石形成的食物?
?a keyid="1414" class="keyword_ad">l石是尿石症的一U,多在炎热的夏天Ş成,因ؓ(f)夏天大量出汗Q甚至体内脱_(d)使排减,再加之夏季暴露于阛_下时间长Q外线照射皮肤有助于体内维生素D和维生素A合成增多Q维生素D和维生素A可促(j)q小肠吸攉dQ尿液中排泄钙增多,内l石物质易生结晶核Q从而Ş?a keyid="1414" class="keyword_ad">l石。冬季天气寒P人的K增多Q已形成的小l石被尿液冲P向下UdQ此时引赯l痛症状。所以,?a keyid="1414" class="keyword_ad">l石ؓ(f)“夏季形成冬季发病”?
Z的饮食品U是多样的,Z新陈代谢是复杂的Q所以肾l石的成分也是多L(fng)。常?a keyid="1414" class="keyword_ad">l石按成分可分ؓ(f)五种Q一草酸?a keyid="1414" class="keyword_ad">l石Q最为常见,占肾l石?0以上Q在酸性或中性尿中Ş成,发病多ؓ(f)青壮q_(d)?a keyid="1448" class="keyword_ad">h?/a>多见。二酸?a keyid="1414" class="keyword_ad">l石Q占l石?-9Q在性尿中Ş成,也以h?/a>青壮q多发。三Kl石Q占l石?Q在酸性尿中Ş成,当尿PH值大?.7?a keyid="1414" class="keyword_ad">l石溶解Q以h?/a>多见。四酸镁胺l石Q占l石?0Q在性尿中Ş成,PH值小?.2?a keyid="1414" class="keyword_ad">l石溶解Q以x?/a>多见。五胱}?a keyid="1414" class="keyword_ad">l石Q少见,U占l石?-2Q在酸性尿中Ş成,PH值大?.0?a keyid="1414" class="keyword_ad">l石溶解?
大量饮水Ҏ(gu)有成分尿石都有防M用。在炎热的夏天,每日K于1200毫升Ӟ石生长的危险性显著增大。如能每日饮水量在2000-4000毫升Q这样可l持每日K?000毫升以上。磁化水寚w治草酔Rl石更有效,可将全日饮水量分别于晨v、餐间、睡前给予。清晨饮水量可达500-1000毫升。ؓ(f)?jin)保持夜间尿量,睡前饮?00毫升Q睡眠中起床排尿后再饮水300-500毫升Q余下水分别于餐间饮服。大量饮水可?j)ɞ?a keyid="1414" class="keyword_ad">l石排出Q稀释尿液可防止石l晶形成Qƈ能g~?a keyid="1414" class="keyword_ad">l石增长速度?
1985q国外学者Vehlensieck认ؓ(f)Q多饮水和饮食疗法可?/3复发l石病h不再生新l石。下面介l几U肾l石的饮食疗法?
⑴草酔Rl石Q宜低钙?qing)低草酸饮食。少食牛奶及(qing)乛_品、豆制品、肉cR动物内?如肝?a keyid="1538" class="keyword_ad">?j)?/a>、肾、肠{?Q还有y克力、浓茶、芝麻酱、蛋黄、香菇、菠菜、虾皮、萝卜、可可、芹菜、土豆等。近q来发现食物中纤l素可减尿钙的形成Q如麦麸食品中的麦麸面包、米p也有同样作用,对复发性高钙尿l石有效Q维生素B1、维生素B6~Z使尿草酸增多Q应增加富含此类l生素的食物Q如L(fng)、干果、硬果等?
늣酔Rl石?qing)磷酔R?a keyid="1414" class="keyword_ad">l石Q其低钙饮食同草酔Rl石相同。在低磷食物中,宜少食肉cR鱼cd(qing)骨头汤?
⑶尿l石Q?
应限制蛋白质的摄入量Q每日蛋白质的L入量应在48-80克(0.8-1.0?公斤/日)(j)之间。一般带叶的蔬菜每市(jng)斤约?0克蛋白质、瘦肉类?0
克约含蛋白质10克、谷cL?jng)斤含蛋白?5-60克。要增加新鲜蔬菜和水果的食量。蔬菜和水果含维生素B1?qing)维生素CQ它们在体内最后代谢物是?
的,K在碱性尿内易于溶解,故有利于ȝ。常规治疗:(x)每隔1-2日用一ơ清凉饮食(生水果、果汁及(qing)生菜Q,臛_每周1ơ清凉饮食。少食或忌用肉类、动?
内脏、肉汤、肉汁、沙丁鱼、蟹、菠菜、浓茶、咖啡,烈性的香料?qing)调呛_也宜用?
现实生活中很?a keyid="1398" class="keyword_ad">疄的发生和日常饮食是密切相关的Q如果能做到起居有时Q饮食有节,甚至大部?a keyid="1589" class="keyword_ad">癌症也可能避免。现在就?a keyid="1414" class="keyword_ad">l石病这一症来提醒大家如何用饮食来预Ԍ或已经(zhn)了(jin)?a keyid="1414" class="keyword_ad">l石者,l石增大的速度减慢Q甚至羃?yu)、溶解而排Z外?
Q一Q多饮白开?多饮水ɞ液得到E释,钙离子和草酸根的度׃(x)降低QŞ成不?jin)草酔Rl石。研I表明,增加50Q的KQ可使肾l石发病率下?6Q?
Q二Q合理补钙,其饮食上补??a keyid="1414" class="keyword_ad">l石(zhn)者往往“谈钙色变”Q错误地认ؓ(f)?a keyid="1414" class="keyword_ad">l石的元凶是钙,其实不然Q肾l石(zhn)者也需要补钙。目前医学界从两个不同的角度来解释,?a keyid="1414" class="keyword_ad">l石(zhn)者ؓ(f)什么要补钙?
W一是补充钙能与胃肠道中蔬菜含有的草酸结合成不溶性的草酸钙,随粪便排Z外,减少?jin)部分被肠胃吸收和经肾脏排出体外的草酸,从而减了(jin)形成?a keyid="1414" class="keyword_ad">l石的几率?
W二是日本学者提出的“酸碱q学说”。即血液呈酸性时Q?a keyid="1414" class="keyword_ad">l石Ҏ(gu)形成。呈性时Q抑?a keyid="1414" class="keyword_ad">l石形成。缺钙时血液偏酸性,合理补钙Q血液偏,q样反而有利于抑制l石形成?
Q三Q限量摄入糖c?国U学家最C研I结果表明,高糖食品的摄入,可以使?zhn)?a keyid="1414" class="keyword_ad">l石的机?x)增加,因此Q要注意吃甜食?
Q四Q少吃草酸盐含量高的食物 含草酸盐高的食物有番茄、菠菜、草莓、甜菜、y克力{,q高的草酸盐摄入也是D?a keyid="1414" class="keyword_ad">l石的主要原因之一?
Q五Q少吃豆制品 大豆食品含草酸盐和磷酸盐都高Q能同肾脏中的钙融合QŞ?a keyid="1414" class="keyword_ad">l石?
Q六Q睡前慎喝牛?睡眠不好的hQ睡前喝杯牛奶有助于睡眠。但在睡眠后Q尿量减、浓~,中各种有Ş物质增加。而饮牛奶?~3时Q正是钙通过肾脏排泄的高峰。钙通过肾脏在短旉内骤然增多,Ҏ(gu)形成l石。因此肾l石(zhn)者,睡前׃应喝含钙高的牛奶?
Q七Q勿q量服用D?D油富含维生素DQ有?j)进肠膜寚w吸收的功能Q骤然增加尿液中钙磷的排泄,势必产生沉淀(wn)Q容易Ş?a keyid="1414" class="keyword_ad">l石?
Q八Q多食黑木?黑木耳中富含多种矿物质和微量元素Q能对各U?a keyid="1414" class="keyword_ad">l石产生强烈的化学反应,?a keyid="1414" class="keyword_ad">l石剥脱、分化、溶解,排出体外?
]]>
2 <xsl:if test="not(position() = 1)"><xsl:text>,</xsl:text></xsl:if><xsl:value-of select="@roleName"/>
3 </xsl:for-each>
q有一个函数current()是负责取到当前节点对象的?br />
]]>
̔ pȝcd载器或叫作应用类加蝲?/span> (system classloader or application classloader)
̔ 当前cd载器
̔ 当前U程cd载器
上面的问题指的是最后一U类加蝲?/span> . 哪种cd载器是正的选择?/span> ?
W一U选择可以很容易地排除 : pȝcd载器 (system classloader). q个cd载器处理 -classpath 下的cd载工?/span> , 可以通过 ClassLoader.getSystemClassLoader() Ҏ(gu)调用 . ClassLoader 下所有的 getSystemXXX() 的静(rn)态方法都是通过q个Ҏ(gu)定义?/span> . 在你的代码中 , 你应该尽量少地调用这个方?/span> , 以其它的cd载器作ؓ(f)代理 . 否则你的代码只能工作在单的命o(h)行应用中 , q个时候系l类加蝲?/span> (system classloader) ?/span> JVM 最后创建的cd载器 . 一但你把代码移?/span> EJB, Web 应用?/span> Java Web Start 应用?/span> , 一定会(x)出问?/span> .
所以我们来看第二种选择
:
当前上下文环境下的类加蝲?/span>
.
Ҏ(gu)定义
,
当前cd载器是你当前方法所属的cȝ加蝲?/span>
.
在运行时cM间动态联~?/span>
,
?qing)调?/span>
Class.forName,() Class.getResource()
{类似方法时
,
q个cd载器?x)被隐含C?/span>
.
It is also used by syntactic constructs like X.class class literals.
U程上下文类型加载器是在Java 2q_上被引入?span lang="EN-US">. 每一个线E都有一个类加蝲器与之对?span lang="EN-US">(除非q个U程是被本地代码创徏?span lang="EN-US">). q个cd载器是通过Thread.setContextClassLoaser()Ҏ(gu)讄?span lang="EN-US">. 如果你不在线E构造后调用q个Ҏ(gu), q个U程从它的父线E中l承相应的上下文cd载器. 如果在整个应用中你不做Q何特D设|?span lang="EN-US">, 所有的U程都以系l类加蝲?span lang="EN-US">(system classloader)作ؓ(f)自己的线E上下文cd载器. 自从Web?span lang="EN-US">J2EE应用服务器用成熟的cd载器机制来实现诸?span lang="EN-US">JNDI, U程?span lang="EN-US">, lg热部|等功能以来, q种在整个应用中不做MU程cd载器讄的情况就很少?span lang="EN-US">.
Z么线E上下文cd载器存在于如此重要的位置?span lang="EN-US">? q个概念?span lang="EN-US">J2SE中的引入q不引h注目. 很多开发h员对q一概念qh的原因是Sun公司在这斚w~Z适当的指引和文.
事实?span lang="EN-US">, 上下文类加蝲器提供了(jin)cd载机制的后门, q一点也?span lang="EN-US">J2SE中被引入?span lang="EN-US">. 通常, ?span lang="EN-US">JVM中的所有类加蝲器被l织成了(jin)有承层ơ的l构, 每一个类加蝲?span lang="EN-US">(除了(jin)引导JVM的原始类加蝲?span lang="EN-US">)都有一个父加蝲?span lang="EN-US">. 每当被请C加载类?span lang="EN-US">, cd载器都会(x)首先h其父cd载器, 只有当父cd载器不能加蝲?span lang="EN-US">, 才会(x)自己q行cd?span lang="EN-US">.
有时候这U类加蝲的顺序安排不能正常工?span lang="EN-US">, 通常当必d态加载应用程序开发h员提供的资源的时?span lang="EN-US">. ?span lang="EN-US">JNDIZ: 它的内容(?span lang="EN-US">J2SE1.3开?span lang="EN-US">)在rt.jar中的引导cM实现?span lang="EN-US">, 但是q些JNDI核心(j)c需要动态加载由独立厂商实现q|在应用E序?span lang="EN-US">classpath下的JNDI提供?span lang="EN-US">. q种情况p求一个父classloader(本例, 是引导cd载器)d载对于它其中一个子classloader(本例, pȝcd载器)可见的类. q时通常的类加蝲代理机制不能实现q个要求. 解决的办?span lang="EN-US">(workaround)是, ?span lang="EN-US">JNDI核心(j)cM用当前线E上下文的类加蝲?span lang="EN-US">, q样, 基本的cd载代理机制的相反方向建立?jin)一条有效的途径.
另外, 上面一D可能让你想起一些其它的事情: XML解析Java API(JAXP). 是的, ?span lang="EN-US">JAXP只是J2SE的扩展进, 它很自然地用当前cd载器来引D析器的实?span lang="EN-US">. 而当JAXP被加入到J2SE1.4的核?j)类库中?span lang="EN-US">, 它的cd载也改成了(jin)用当前线E类加蝲?span lang="EN-US">, ?span lang="EN-US">JNDI的情况完全类?span lang="EN-US">(也很多E序员很qh). 明白Z么我说来?span lang="EN-US">Sun的指导很~Z?jin)?span lang="EN-US">?
在以上的介绍之后, 我们来看关键问题: q两U选择(当前cd载器和当前线E类加蝲?span lang="EN-US">)都不是在所有环境下都适用. 有些为当前线E类加蝲器应该成为新的标准策?span lang="EN-US">. 但是, 如果q样, 当多个线E通过׃n数据q行交互的时, 会(x)呈现Zq极其复杂的cd载的画面, 除非它们全部使用?jin)同一个上下文的类加蝲?span lang="EN-US">. q一步说, 在某些遗留下来的解决Ҏ(gu)?span lang="EN-US">, 委派到当前类加蝲器的Ҏ(gu)已经是标?span lang="EN-US">. 比如?span lang="EN-US">Class.forName(String)的直接调?span lang="EN-US">(q也是我Z么推荐尽量避免对q个Ҏ(gu)q行调用的原?span lang="EN-US">). 即你努力去只调用上下文相关的类加蝲?span lang="EN-US">, 仍然?x)有一些代码会(x)不由你控?span lang="EN-US">. q种不受控制的类加蝲委派机制是入是很危险的.
更严重的问题, 某些应用服务器把环境上下文及(qing)当前cd载器讄C同的cd载器实例?span lang="EN-US">, 而这些类加蝲器有相同的类路径但却没有委派机制中的父子关系. xqؓ(f)什么十分可?span lang="EN-US">. 要知道类加蝲器定义ƈ加蝲的类实例?x)带有一?span lang="EN-US">JVM内部?span lang="EN-US">ID?span lang="EN-US">. 如果当前cd载器加蝲一个类X的实?span lang="EN-US">, q个实例调用JNDI查找c?span lang="EN-US">Y的实?span lang="EN-US">, 些时的上下文的类加蝲器也可以定义?jin)加载?span lang="EN-US">Y实例. q个c?span lang="EN-US">Y的定义就与当前类加蝲器看到的c?span lang="EN-US">Y的定义不?span lang="EN-US">. 如果q行强制cd转换, 则生异?span lang="EN-US">.
q种混ؕ的情况还在Java中存在一D|?span lang="EN-US">. 对于那些需要动态加载资源的J2SE?span lang="EN-US">API, 我们来猜惛_们的cd{略. 例如:
Ø
JNDI
使用U程上下文类加蝲?span lang="EN-US">
Ø
Class.getResource()
?span lang="EN-US">Class.forName()使用当前cd载器
Ø
JAXP(J2SE 1.4
?qing)之?span lang="EN-US">)使用U程上下文类加蝲?span lang="EN-US">
Ø
java.util.ResourceBundle
使用调用者的当前cd载器
Ø
URL protocol handlers specified via java.protocol.handler.pkgs system property are looked up in the bootstrap and system classloaders only
Ø
Java
序列?span lang="EN-US">API默认使用调用者当前的cd载器
q些cd(qing)资源的加载策略问?span lang="EN-US">, 肯定?span lang="EN-US">J2SE领域中文档最?qing)说明最~Z的部分了(jin).