【正文】
,而StringBuffer是一個(gè)mutable class,這樣就不需要?jiǎng)?chuàng)建臨時(shí)的對(duì)象來(lái)保存結(jié)果,從而提高了性能。 // create a new object String B2 = new String(A)。 String A2 = A。如果大家理解了不變類,那也就不難理解為什么在做String的concatenate時(shí),應(yīng)當(dāng)用StringBuffer而不是用+的操作符。if (h == 0) { // pute the value hash = h。 }}3) 不變類的某些方法可以緩存計(jì)算的結(jié)果hashCode這個(gè)方法來(lái)自于Object這個(gè)類,這個(gè)方法用來(lái)返回對(duì)象的hashCode,主要用于將對(duì)象放置到hashtable中時(shí),來(lái)確定這個(gè)對(duì)象的存儲(chǔ)位置。JDK中的Boolean類就是一個(gè)不變類,并且對(duì)這兩個(gè)實(shí)例進(jìn)行了緩沖。 不變類有什么好處呢?1) 不變類是線程安全的,由于不變類的狀態(tài)在創(chuàng)建以后不再發(fā)生變化,所以它可以在線程之間共享,而不需要同步。 JVM在運(yùn)行時(shí)會(huì)產(chǎn)生三個(gè)ClassLoader:Bootstrap ClassLoader、Extension ClassLoader和AppClassLoader。Java發(fā)布的程序(JAR包)也多半是一堆class文件,運(yùn)行時(shí)由ClassLoader加載到Java虛擬機(jī)中執(zhí)行。本地方法可以通過(guò)本地方法接口來(lái)訪問(wèn)虛擬機(jī)的運(yùn)行時(shí)數(shù)據(jù)區(qū),不止與此,它還可以做任何它想做的事情。PC寄存器的內(nèi)容總是指向下一條將被執(zhí)行指令的地址。 // Exception in thread main }}class Recursive { public int doit(int t) { if (t = 1) { return 1。棧的大小是有一定的限制,這個(gè)可能出現(xiàn)StackOverFlow問(wèn)題。該類型中的類(靜態(tài))變量同樣也存儲(chǔ)在方法區(qū)中。但是同一java程序的多個(gè)線程都共享著同一個(gè)堆空間,就得考慮多線程訪問(wèn)對(duì)象(堆數(shù)據(jù))的同步問(wèn)題。Heap 和Method Area是被所有線程的共享使用的;而Java stack, Program counter 和Native method stack是以線程為粒度的,每個(gè)線程獨(dú)自擁有。任何JVM specification實(shí)現(xiàn)(JDK)的核心是Execution engine, 換句話說(shuō):Sun 的JDK 和IBM的JDK好壞主要取決于他們各自實(shí)現(xiàn)的Execution Class loader子系統(tǒng)的作用 :根據(jù)給定的全限定名類名(如 )來(lái)裝載class文件的內(nèi)容到 Runtime data area中的method area(方法區(qū)域)。 Javsa程序員可以extends loader。 engine的好壞。 Runtime data area 組件:這個(gè)組件就是JVM中的內(nèi)存。 Heap Java程序在運(yùn)行時(shí)創(chuàng)建的所有類實(shí)或數(shù)組都放在同一個(gè)堆中。 (: Java heap space) Method area 在Java虛擬機(jī)中,被裝載的class的信息存儲(chǔ)在Method area的內(nèi)存中。與Heap 一樣,method area是多線程共享的,因此要考慮多線程訪問(wèn)的同步問(wèn)題。 Java stack以幀為單位保存線程的運(yùn)行狀態(tài)。 下面的程序可以說(shuō)明這個(gè)問(wèn)題。 } return t + doit(t 1)。這里的地址可以是一個(gè)本地指針,也可以是在方法區(qū)中相對(duì)應(yīng)于該方法起始指令的偏移量。比如,可以調(diào)用寄存器,或在操作系統(tǒng)中分配內(nèi)存等。ClassLoader是Java虛擬機(jī)的主要組成部分,由Java語(yǔ)言編寫,用戶可以實(shí)現(xiàn)自定義的ClassLoader來(lái)完成特定的功能。Bootstrap是用C++編寫的,我們?cè)贘ava中看不到它,是null,是JVM自帶的類裝載器,用來(lái)裝載核心類庫(kù),.*等。2) 不變類的instance可以被reuse創(chuàng)建類的實(shí)例需要耗費(fèi)CPU的時(shí)間,當(dāng)這個(gè)實(shí)例不再被引用時(shí),將會(huì)被垃圾回收掉,這時(shí)候,又需要耗費(fèi)CPU的時(shí)間。public final class Boolean implements {/** * The codeBoolean/code object corresponding to the primitive * value codetrue/code. */public static final Boolean TRUE = new Boolean(true)。對(duì)于一個(gè)不變類的實(shí)例,它的hashCode也是不變的,所以就可以緩存這個(gè)計(jì)算的結(jié)果,來(lái)提高性能,避免不必要的運(yùn)算,JDK中的String類就是一個(gè)例子。 // cache the value } return h。如何正確使用String呢?1) 不要用new去創(chuàng)建String對(duì)象。 // It won39。 // creat a new object checkInstance(B1, B2)。4. JAVA Garbage Collection (Vincent)垃圾分代回收算法(Generational Collecting) 基于對(duì)對(duì)象生命周期分析后得出的垃圾回收算法。 1. Young(年輕代)JVM specification中的 Heap的一部份 年輕代分三個(gè)區(qū)。需要注意,Survivor的兩個(gè)區(qū)是對(duì)稱的,沒(méi)先后關(guān)系,所以同一個(gè)區(qū)中可能同時(shí)存在從Eden復(fù)制過(guò)來(lái) 對(duì)象,和從前一個(gè)Survivor復(fù)制過(guò)來(lái)的對(duì)象,而復(fù)制到年老區(qū)的只有從第一個(gè)Survivor去過(guò)來(lái)的對(duì)象。 3. Perm(持久代) JVM specification中的 Method area 用于存放靜態(tài)文件,如今Java類、方法等。永久存儲(chǔ)區(qū)(Permanent Space)和堆空間(The Heap Space)。被裝載進(jìn)此區(qū)域的數(shù)據(jù)是不會(huì)被垃圾回收器回收掉的,關(guān)閉JVM時(shí),釋放此區(qū)域所控制的內(nèi)存。 伊甸園(Eden space):JAVA對(duì)空間中的所有對(duì)象在此出生,該區(qū)的名字因此而得名。同時(shí)將伊甸園中的還有其他對(duì)象引用的對(duì)象移動(dòng)到幸存者0區(qū)。 養(yǎng)老區(qū)(Tenure (Old) generation space):用于保存從新生區(qū)篩選出來(lái)的JAVA對(duì)象。 JVM在伊甸園區(qū)根據(jù)用戶的每次請(qǐng)求創(chuàng)建相應(yīng)的JAVA對(duì)象,當(dāng)伊甸園的空間不足以用來(lái)創(chuàng)建新JAVA對(duì)象的時(shí)候,JVM的垃圾回收器執(zhí)行對(duì)伊甸園區(qū)的垃圾回收工作,銷毀那些不再被其他對(duì)象引用的JAVA對(duì)象(如果該對(duì)象僅僅被一個(gè)沒(méi)有其他對(duì)象引用的對(duì)象引用的話,此對(duì)象也被歸為沒(méi)有存在的必要,依此類推),并將那些被其他對(duì)象所引用的JAVA對(duì)象移動(dòng)到幸存者0區(qū)。如果到最后養(yǎng)老區(qū),幸存者1區(qū),幸存者0區(qū)和伊甸園區(qū)都沒(méi)有空間的話,則JVM會(huì)報(bào)告“JVM堆空間溢出(: Java heap space)”,也即是在堆空間沒(méi)有空間來(lái)創(chuàng)建對(duì)象。Reference跟蹤收集器 跟蹤收集器首先要暫停整個(gè)應(yīng)用程序,然后開(kāi)始從根對(duì)象掃描整個(gè)堆,判斷掃描的對(duì)象是否有對(duì)象引用,這里面有三個(gè)問(wèn)題需要搞清楚:1.如果每次掃描整個(gè)堆,那么勢(shì)必讓GC的時(shí)間變長(zhǎng),從而影響了應(yīng)用本身的執(zhí)行。gc只掃描新生代,但是minorreference,Soft如果一個(gè)對(duì)象沒(méi)有強(qiáng)引用,那么對(duì)象就會(huì)被回收。referentObjectreferentassertNotNull(strongReference)。SofttestSoftReference(){String=()。void=weakReferencestr=null。216。解決循環(huán)引用的問(wèn)題2復(fù)制收集器具體過(guò)程可以參考下圖:優(yōu)點(diǎn):1Markpact策略極大的減少了內(nèi)存碎片,并且不需要像CopyGC的執(zhí)行時(shí)要耗費(fèi)一定的CPU資源和時(shí)間的,JVM引入了分代收集的策略,其中對(duì)新生代采用MarkCompact策略,而對(duì)老生代采用了“MarkSweep的策略。或者M(jìn)ajor框架做的越多,應(yīng)該越能發(fā)現(xiàn)接口在其中起到的作用,而Spring將這種想法,開(kāi)始貫徹到業(yè)務(wù)的開(kāi)發(fā)中了。 被容器中創(chuàng)建的類,看起來(lái)執(zhí)行一個(gè)普通的函數(shù)調(diào)用,因?yàn)楸蝗萜黝A(yù)處理,而會(huì)在方法執(zhí)行前/后進(jìn)行一些其他的、可配置的操作。publicInvocationHandler privatebind(Objectreturn invoke(ObjectObject[] Throwable resulttry clazz//反射得到操作者的Start方法(start,{//反射執(zhí)行start方法{//執(zhí)行要處理對(duì)象的原本方法(,(end,(,methode) result。 classstatic{(IHello)new(DoubleJ)。 2. 4 import 。 public Object bind(Object delegate,Object proxy) { = proxy。 try { //反射得到操作者的實(shí)例 Class clazz = ()。 // 反射得到操作者的end方法 Method end = (end, new Class[] { })。 } } public class Test { public static void main(String[] args) { IHello hello = (IHello)new DynaProxyHello().bind(new Hello(),new LoggerOperation())。 在有些時(shí)候,我們不需要使用Spring,甚至不能使用Spring(比如不用Java開(kāi)發(fā)),但是這種思想和方式是可以復(fù)用的。圖 1. Spring 框架的 7 個(gè)模塊組成 Spring 框架的每個(gè)模塊(或組件)都可以單獨(dú)存在,或者與其他一個(gè)或多個(gè)模塊聯(lián)合實(shí)現(xiàn)。BeanFactory 使用控制反轉(zhuǎn) (IOC) 模式將應(yīng)用程序的配置和依賴性規(guī)范與實(shí)際的應(yīng)用程序代碼分開(kāi)。 通過(guò)使用 Spring AOP,不用依賴 EJB 組件,就可以將聲明性事務(wù)管理集成到應(yīng)用程序中。Spring DAO 的面向 JDBC 的異常遵從通用的 DAO 異常層次結(jié)構(gòu)。 Spring 的核心要點(diǎn)是:支持不綁定到特定 J2EE 服務(wù)的可重用業(yè)務(wù)和數(shù)據(jù)訪問(wèn)對(duì)象。 } Class[] proxiedInterfaces = ()。 if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) { // Evaluate dynamic method matcher here: static part will already have // been evaluated and found to match. InterceptorAndDynamicMethodMatcher dm = (InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice。s an interceptor, so we just invoke it: The pointcut will have // been evaluated statically before this object was constructed. return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this)。 return massageReturnTypeIfNecessary(proxy, target, retVal)。 try { oldProxy = (proxy)。 } } } /** * Interceptor used to invoke a dynamic target without creating a method * invocation or evaluating an advice chain. (We know there was no advice * for this method.) */ private class DynamicUnadvisedInterceptor implements MethodInterceptor, Serializable { public Object intercept(Object pr