Java面試題、面試經(jīng)驗(yàn)_第1頁(yè)
Java面試題、面試經(jīng)驗(yàn)_第2頁(yè)
Java面試題、面試經(jīng)驗(yàn)_第3頁(yè)
Java面試題、面試經(jīng)驗(yàn)_第4頁(yè)
Java面試題、面試經(jīng)驗(yàn)_第5頁(yè)
已閱讀5頁(yè),還剩138頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶(hù)提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

基礎(chǔ)篇1Java語(yǔ)言有哪些特點(diǎn)1、簡(jiǎn)單易學(xué)、有豐富的類(lèi)庫(kù)2、面向?qū)ο螅↗ava最重要的特性,讓程序耦合度更低,內(nèi)聚性更高)3、與平臺(tái)無(wú)關(guān)性(JVM是Java跨平臺(tái)使用的根本)4、可靠安全5、支持多線(xiàn)程2、面向?qū)ο蠛兔嫦蜻^(guò)程的區(qū)別面向過(guò)程:是分析解決問(wèn)題的步驟,然后用函數(shù)把這些步驟一步一步地實(shí)現(xiàn),然后在使用的時(shí)候一一調(diào)用則可。性能較高,所以單片機(jī)、嵌入式開(kāi)發(fā)等一般采用面向過(guò)程開(kāi)發(fā)面向?qū)ο螅菏前褬?gòu)成問(wèn)題的事務(wù)分解成各個(gè)對(duì)象,而建立對(duì)象的目的也不是為了完成一個(gè)個(gè)步驟,而是為了描述某個(gè)事物在解決整個(gè)問(wèn)題的過(guò)程中所發(fā)生的行為。面向?qū)ο笥蟹庋b、繼承、多態(tài)的特性,所以易維護(hù)、易復(fù)用、易擴(kuò)展。可以設(shè)計(jì)出低耦合的系統(tǒng)。但是性能上來(lái)說(shuō),比面向過(guò)程要低。3、八種基本數(shù)據(jù)類(lèi)型的大小,以及他們的封裝類(lèi)基本類(lèi)型大?。ㄗ止?jié))默認(rèn)值封裝類(lèi)byte1(byte)0Byteshort2(short)0Shortint40Integerlong80LLong?oat40.0fFloatdouble80.0dDoubleboolean-falseBooleanchar2\u0000(null)Character注:int是基本數(shù)據(jù)類(lèi)型,Integer是int的封裝類(lèi),是引用類(lèi)型。int默認(rèn)值是0,而Integer默認(rèn)值是null,所以Integer能區(qū)分出0和null的情況。一旦java看到null,就知道這個(gè)引用還沒(méi)有指向某個(gè)對(duì)象,再任何引用使用前,必須為其指定一個(gè)對(duì)象,否則會(huì)報(bào)錯(cuò)?;緮?shù)據(jù)類(lèi)型在聲明時(shí)系統(tǒng)會(huì)自動(dòng)給它分配空間,而引用類(lèi)型聲明時(shí)只是分配了引用空間,必須通過(guò)實(shí)例化開(kāi)辟數(shù)據(jù)空間之后才可以賦值。數(shù)組對(duì)象也是一個(gè)引用對(duì)象,將一個(gè)數(shù)組賦值給另一個(gè)數(shù)組時(shí)只是復(fù)制了一個(gè)引用,所以通過(guò)某一個(gè)數(shù)組所做的修改在另一個(gè)數(shù)組中也看的見(jiàn)。雖然定義了boolean這種數(shù)據(jù)類(lèi)型,但是只對(duì)它提供了非常有限的支持。在Java虛擬機(jī)中沒(méi)有任何供boolean值專(zhuān)用的字節(jié)碼指令,Java語(yǔ)言表達(dá)式所操作的boolean值,在編譯之后都使用Java虛擬機(jī)中的int數(shù)據(jù)類(lèi)型來(lái)代替,而boolean數(shù)組將會(huì)被編碼成Java虛擬機(jī)的byte數(shù)組,每個(gè)元素boolean元素占8位。這樣我們可以得出boolean類(lèi)型占了單獨(dú)使用是4個(gè)字節(jié),在數(shù)組中又是1個(gè)字節(jié)。使用int的原因是,對(duì)于當(dāng)下32位的處理器(CPU)來(lái)說(shuō),一次處理數(shù)據(jù)是32位(這里不是指的是32/64位系統(tǒng),而是指CPU硬件層面),具有高效存取的特點(diǎn)。4、標(biāo)識(shí)符的命名規(guī)則。標(biāo)識(shí)符的含義:是指在程序中,我們自己定義的內(nèi)容,譬如,類(lèi)的名字,方法名稱(chēng)以及變量名稱(chēng)等等,都是標(biāo)識(shí)符。命名規(guī)則:(硬性要求)標(biāo)識(shí)符可以包含英文字母,0-9的數(shù)字,$以及_標(biāo)識(shí)符不能以數(shù)字開(kāi)頭標(biāo)識(shí)符不是關(guān)鍵字命名規(guī)范:(非硬性要求)類(lèi)名規(guī)范:首字符大寫(xiě),后面每個(gè)單詞首字母大寫(xiě)(大駝峰式)。變量名規(guī)范:首字母小寫(xiě),后面每個(gè)單詞首字母大寫(xiě)(小駝峰式)。方法名規(guī)范:同變量名。5、instanceof關(guān)鍵字的作用instanceof嚴(yán)格來(lái)說(shuō)是Java中的一個(gè)雙目運(yùn)算符,用來(lái)測(cè)試一個(gè)對(duì)象是否為一個(gè)類(lèi)的實(shí)例,用法為:booleanbooleanresult=objinstanceofClass其中obj為一個(gè)對(duì)象,Class表示一個(gè)類(lèi)或者一個(gè)接口,當(dāng)obj為Class的對(duì)象,或者是其直接或間接子類(lèi),或者是其接口的實(shí)現(xiàn)類(lèi),結(jié)果result都返回true,否則返回false。注意:編譯器會(huì)檢查obj是否能轉(zhuǎn)換成右邊的class類(lèi)型,如果不能轉(zhuǎn)換則直接報(bào)錯(cuò),如果不能確定類(lèi)型,則通過(guò)編譯,具體看運(yùn)行時(shí)定。intinti=0;System.out.println(iinstanceofInteger);//編譯不通過(guò)i必須是引用類(lèi)型,不能是基本類(lèi)型System.out.println(iinstanceofObject);//編譯不通過(guò)Integerinteger=newInteger(1);instanceofInteger);//true//false ,//false ,JavaSEinstanceofobjnull,那么將返回false。instanceofObject);6、Java自動(dòng)裝箱與拆箱裝箱就是自動(dòng)將基本數(shù)據(jù)類(lèi)型轉(zhuǎn)換為包裝器類(lèi)型(int-->Integer);調(diào)用方法:Integer的valueOf(int)方法拆箱就是自動(dòng)將包裝器類(lèi)型轉(zhuǎn)換為基本數(shù)據(jù)類(lèi)型(Integer-->int)。調(diào)用方法:Integer的intValue方法在JavaSE5之前,如果要生成一個(gè)數(shù)值為10的Integer對(duì)象,必須這樣進(jìn)行:IntegerIntegeri=newInteger(10);而在從JavaSE5開(kāi)始就提供了自動(dòng)裝箱的特性,如果要生成一個(gè)數(shù)值為10的Integer對(duì)象,只需要這樣就可以了:IntegerIntegeri=10;面試題1以下代碼會(huì)輸出什么?publicpublicclassMain{publicstaticvoidmain(String[]args){Integeri1=100;Integeri2=100;Integeri3=200;Integeri4=200;System.out.println(i1==i2);System.out.println(i3==i4);}}運(yùn)行結(jié)果:truefalse為什么會(huì)出現(xiàn)這樣的結(jié)果?輸出結(jié)果表明i1和i2指向的是同一個(gè)對(duì)象,而i3和i4指向的是不同的對(duì)象。此時(shí)只需一看源碼便知究竟,下面這段代碼是Integer的valueOf方法的具體實(shí)現(xiàn):publicpublicstaticIntegervalueOf(inti){if(i>=-128&&i<=IntegerCache.high)returnIntegerCache.cache[i+128];elsereturnnewInteger(i);}其中IntegerCache類(lèi)的實(shí)現(xiàn)為:privateprivatestaticclassIntegerCache{staticfinalinthigh;staticfinalIntegercache[];static{finalintlow=-128;//highvaluemaybeconfiguredbypropertyinth=127;if(integerCacheHighPropValue!=null){//UseLong.decodeheretoavoidinvokingmethodsthat//requireInteger'sautoboxingcachetobeinitializedi=Math.max(i,127);//MaximumarraysizeisInteger.MAX_VALUEh=Math.min(i,Integer.MAX_VALUE--low);}high=h;cache=newInteger[(high-low)+1];intj=low;for(intk=0;k<cache.length;k++)cache[k]=newInteger(j++);}privateIntegerCache(){}}從這2段代碼可以看出,在通過(guò)valueOf方法創(chuàng)建Integer對(duì)象的時(shí)候,如果數(shù)值在[-128,127]之間,便返回指向IntegerCache.cache中已經(jīng)存在的對(duì)象的引用;否則創(chuàng)建一個(gè)新的Integer對(duì)象。上面的代碼中i1和i2的數(shù)值為100,因此會(huì)直接從cache中取已經(jīng)存在的對(duì)象,所以i1和i2指向的是同一個(gè)對(duì)象,而i3和i4則是分別指向不同的對(duì)象。面試題2:以下代碼輸出什么publicpublicclassMain{publicstaticvoidmain(String[]args){Doublei1=100.0;Doublei2=100.0;Doublei3=200.0;Doublei4=200.0;System.out.println(i1==i2);System.out.println(i3==i4);}}運(yùn)行結(jié)果:falsefalsefalse原因:在某個(gè)范圍內(nèi)的整型數(shù)值的個(gè)數(shù)是有限的,而浮點(diǎn)數(shù)卻不是。7、重載和重寫(xiě)的區(qū)別重寫(xiě)(Override)從字面上看,重寫(xiě)就是重新寫(xiě)一遍的意思。其實(shí)就是在子類(lèi)中把父類(lèi)本身有的方法重新寫(xiě)一遍。子類(lèi)繼承了父類(lèi)原有的方法,但有時(shí)子類(lèi)并不想原封不動(dòng)的繼承父類(lèi)中的某個(gè)方法,所以在方法名,參數(shù)列表,返回類(lèi)型(除過(guò)子類(lèi)中方法的返回值是父類(lèi)中方法返回值的子類(lèi)時(shí))都相同的情況下,對(duì)方法體進(jìn)行修改或重寫(xiě),這就是重寫(xiě)。但要注意子類(lèi)函數(shù)的訪問(wèn)修飾權(quán)限不能少于父類(lèi)的。publicpublicclassFather{publicstaticvoidmain(String[]args){//TODOAuto-generatedmethodstubSons=newSon();s.sayHello();}publicvoidsayHello(){System.out.println("Hello");}}classSonextendsFather{@OverridepublicvoidsayHello(){//TODOAuto-generatedmethodstubSystem.out.println("helloby");}}重寫(xiě)總結(jié):發(fā)生在父類(lèi)與子類(lèi)之間方法名,參數(shù)列表,返回類(lèi)型(除過(guò)子類(lèi)中方法的返回類(lèi)型是父類(lèi)中返回類(lèi)型的子類(lèi))必須相同3.訪問(wèn)修飾符的限制一定要大于被重寫(xiě)方法的訪問(wèn)修飾符(public>protected>default>private)4.重寫(xiě)方法一定不能拋出新的檢查異常或者比被重寫(xiě)方法申明更加寬泛的檢查型異常重載(Overload)在一個(gè)類(lèi)中,同名的方法如果有不同的參數(shù)列表(參數(shù)類(lèi)型不同、參數(shù)個(gè)數(shù)不同甚至是參數(shù)順序不同)則視為重載。同時(shí),重載對(duì)返回類(lèi)型沒(méi)有要求,可以相同也可以不同,但不能通過(guò)返回類(lèi)型是否相同來(lái)判斷重載。publicpublicclassFather{publicstaticvoidmain(String[]args){//TODOAuto-generatedmethodstubFathers=newFather();s.sayHello();s.sayHello("wintershii");}publicvoidsayHello(){System.out.println("Hello");}publicvoidsayHello(Stringname){System.out.println("Hello"+""+name);}}重載總結(jié):重載Overload是一個(gè)類(lèi)中多態(tài)性的一種表現(xiàn)重載要求同名方法的參數(shù)列表不同(參數(shù)類(lèi)型,參數(shù)個(gè)數(shù)甚至是參數(shù)順序)重載的時(shí)候,返回值類(lèi)型可以相同也可以不相同。無(wú)法以返回型別作為重載函數(shù)的區(qū)分標(biāo)準(zhǔn)8、equals與==的區(qū)別==:==比較的是變量(棧)內(nèi)存中存放的對(duì)象的(堆)內(nèi)存地址,用來(lái)判斷兩個(gè)對(duì)象的地址是否相同,即是否是指相同一個(gè)對(duì)象。比較的是真正意義上的指針操作。1、比較的是操作符兩端的操作數(shù)是否是同一個(gè)對(duì)象。2、兩邊的操作數(shù)必須是同一類(lèi)型的(可以是父子類(lèi)之間)才能編譯通過(guò)。3、比較的是地址,如果是具體的阿拉伯?dāng)?shù)字的比較,值相等則為true,如:inta=10longb=10Ldoublec=10.0都是相同的(為true),因?yàn)樗麄兌贾赶虻刂窞?0的堆。equals:equals用來(lái)比較的是兩個(gè)對(duì)象的內(nèi)容是否相等,由于所有的類(lèi)都是繼承自java.lang.Object類(lèi)的,所以適用于所有對(duì)象,如果沒(méi)有對(duì)該方法進(jìn)行覆蓋的話(huà),調(diào)用的仍然是Object類(lèi)中的方法,而Object中的equals方法返回的卻是==的判斷??偨Y(jié):所有比較是否相等時(shí),都是用equals并且在對(duì)常量相比較時(shí),把常量寫(xiě)在前面,因?yàn)槭褂胦bject的equalsobject可能為null則空指針在阿里的代碼規(guī)范中只使用equals,阿里插件默認(rèn)會(huì)識(shí)別,并可以快速修改,推薦安裝阿里插件來(lái)排查老代碼使用“==”,替換成equals9、Hashcode的作用java的集合有兩類(lèi),一類(lèi)是List,還有一類(lèi)是Set。前者有序可重復(fù),后者無(wú)序不重復(fù)。當(dāng)我們?cè)趕et中插入的時(shí)候怎么判斷是否已經(jīng)存在該元素呢,可以通過(guò)equals方法。但是如果元素太多,用這樣的方法就會(huì)比較滿(mǎn)。于是有人發(fā)明了哈希算法來(lái)提高集合中查找元素的效率。這種方式將集合分成若干個(gè)存儲(chǔ)區(qū)域,每個(gè)對(duì)象可以計(jì)算出一個(gè)哈希碼,可以將哈希碼分組,每組分別對(duì)應(yīng)某個(gè)存儲(chǔ)區(qū)域,根據(jù)一個(gè)對(duì)象的哈希碼就可以確定該對(duì)象應(yīng)該存儲(chǔ)的那個(gè)區(qū)域。hashCode方法可以這樣理解:它返回的就是根據(jù)對(duì)象的內(nèi)存地址換算出的一個(gè)值。這樣一來(lái),當(dāng)集合要添加新的元素時(shí),先調(diào)用這個(gè)元素的hashCode方法,就一下子能定位到它應(yīng)該放置的物理位置上。如果這個(gè)位置上沒(méi)有元素,它就可以直接存儲(chǔ)在這個(gè)位置上,不用再進(jìn)行任何比較了;如果這個(gè)位置上已經(jīng)有元素了,就調(diào)用它的equals方法與新元素進(jìn)行比較,相同的話(huà)就不存了,不相同就散列其它的地址。這樣一來(lái)實(shí)際調(diào)用equals方法的次數(shù)就大大降低了,幾乎只需要一兩次。10、String、StringStringBu?er和StringBuilder的區(qū)別是什么?String是只讀字符串,它并不是基本數(shù)據(jù)類(lèi)型,而是一個(gè)對(duì)象。從底層源碼來(lái)看是一個(gè)?nal類(lèi)型的字符數(shù)組,所引用的字符串不能被改變,一經(jīng)定義,無(wú)法再增刪改。每次對(duì)String的操作都會(huì)生成新的String對(duì)象。privateprivatefinalcharvalue[];每次+操作:隱式在堆上new了一個(gè)跟原字符串相同的StringBuilder對(duì)象,再調(diào)用append方法拼接+后面的字符。StringBu?er和StringBuilder他們兩都繼承了AbstractStringBuilder抽象類(lèi),從AbstractStringBuilder抽象類(lèi)中我們可以看到/**/***Thevalueisusedforcharacterstorage.*/char[]value;他們的底層都是可變的字符數(shù)組,所以在進(jìn)行頻繁的字符串操作時(shí),建議使用StringBu?er和StringBuilder來(lái)進(jìn)行操作。另外StringBu?er對(duì)方法加了同步鎖或者對(duì)調(diào)用的方法加了同步鎖,所以是線(xiàn)程安全的。StringBuilder并沒(méi)有對(duì)方法進(jìn)行加同步鎖,所以是非線(xiàn)程安全的。11、ArrayList和linkedList的區(qū)別Array(數(shù)組)是基于索引(index)的數(shù)據(jù)結(jié)構(gòu),它使用索引在數(shù)組中搜索和讀取數(shù)據(jù)是很快的。Array獲取數(shù)據(jù)的時(shí)間復(fù)雜度是O(1),但是要?jiǎng)h除數(shù)據(jù)卻是開(kāi)銷(xiāo)很大,因?yàn)檫@需要重排數(shù)組中的所有數(shù)據(jù),(因?yàn)閯h除數(shù)據(jù)以后需要把后面所有的數(shù)據(jù)前移)intanewintanewint[4];//推介使用int[]這種方式初始化長(zhǎng)度:4,索引范圍:[0,3]List—是一個(gè)有序的集合,可以包含重復(fù)的元素,提供了按索引訪問(wèn)的方式,它繼承Collection。List有兩個(gè)重要的實(shí)現(xiàn)類(lèi):ArrayList和LinkedListArrayList:可以看作是能夠自動(dòng)增長(zhǎng)容量的數(shù)組ArrayList的toArray方法返回一個(gè)數(shù)組ArrayList的asList方法返回一個(gè)列表ArrayList底層的實(shí)現(xiàn)是Array,數(shù)組擴(kuò)容實(shí)現(xiàn)LinkList是一個(gè)雙鏈表,在添加和刪除元素時(shí)具有比ArrayList更好的性能.但在get與set方面弱于ArrayList.當(dāng)然,這些對(duì)比都是指數(shù)據(jù)量很大或者操作很頻繁。12、HashMap和HashTable的區(qū)別1、兩者父類(lèi)不同是繼承自AbstractMap類(lèi),而Hashtable是繼承自Dictionary類(lèi)。不過(guò)它們都實(shí)現(xiàn)了同時(shí)實(shí)現(xiàn)了map、Cloneable(可復(fù)制)、Serializable(可序列化)這三個(gè)接口。2、對(duì)外提供的接口不同Hashtable比HashMap多提供了elments()和contains()兩個(gè)方法。elments()方法繼承自Hashtable的父類(lèi)Dictionnary。elements()方法用于返回此Hashtable中的value的枚舉。contains()方法判斷該Hashtable是否包含傳入的value。它的作用與containsValue()一致。事實(shí)上,contansValue()就只是調(diào)用了一下contains()方法。3、對(duì)null的支持不同Hashtable:key和value都不能為null。HashMap:key可以為null,但是這樣的key只能有一個(gè),因?yàn)楸仨毐WCkey的唯一性;可以有多個(gè)key值對(duì)應(yīng)的value為null。4、安全性不同HashMap是線(xiàn)程不安全的,在多線(xiàn)程并發(fā)的環(huán)境下,可能會(huì)產(chǎn)生死鎖等問(wèn)題,因此需要開(kāi)發(fā)人員自己處理多線(xiàn)程的安全問(wèn)題。Hashtable是線(xiàn)程安全的,它的每個(gè)方法上都有synchronized關(guān)鍵字,因此可直接用于多線(xiàn)程中。雖然HashMap是線(xiàn)程不安全的,但是它的效率遠(yuǎn)遠(yuǎn)高于Hashtable,這樣設(shè)計(jì)是合理的,因?yàn)榇蟛糠值氖褂脠?chǎng)景都是單線(xiàn)程。當(dāng)需要多線(xiàn)程操作的時(shí)候可以使用線(xiàn)程安全的ConcurrentHashMap。ConcurrentHashMap雖然也是線(xiàn)程安全的,但是它的效率比Hashtable要高好多倍。因?yàn)镃oncurrentHashMap使用了分段鎖,并不對(duì)整個(gè)數(shù)據(jù)進(jìn)行鎖定。5、初始容量大小和每次擴(kuò)充容量大小不同6、計(jì)算hash值的方法不同13、Collection包結(jié)構(gòu),與Collections的區(qū)別Collection是集合類(lèi)的上級(jí)接口,子接口有Set、List、LinkedList、ArrayList、Vector、Stack、Set;Collections是集合類(lèi)的一個(gè)幫助類(lèi),它包含有各種有關(guān)集合操作的靜態(tài)多態(tài)方法,用于實(shí)現(xiàn)對(duì)各種集合的搜索、排序、線(xiàn)程安全化等操作。此類(lèi)不能實(shí)例化,就像一個(gè)工具類(lèi),服務(wù)于Java的Collection框架。14、Java的四種引用,強(qiáng)弱軟虛強(qiáng)引用強(qiáng)引用是平常中使用最多的引用,強(qiáng)引用在程序內(nèi)存不足(OOM)的時(shí)候也不會(huì)被回收,使用方式:StringStringstr=newString("str");軟引用軟引用在程序內(nèi)存不足時(shí),會(huì)被回收,使用方式:////注意:wrf這個(gè)引用也是強(qiáng)引用,它是指向SoftReference這個(gè)對(duì)象的,這里的軟引用指的是指向newString("str")的引用,也就是SoftReference類(lèi)中TwrfnewSoftReference<String>(newString("str"));可用場(chǎng)景:創(chuàng)建緩存的時(shí)候,創(chuàng)建的對(duì)象放進(jìn)緩存中,當(dāng)內(nèi)存不足時(shí),JVM就會(huì)回收早先創(chuàng)建的對(duì)象。弱引用弱引用就是只要JVM垃圾回收器發(fā)現(xiàn)了它,就會(huì)將之回收,使用方式:WeakReferenceWeakReference<String>wrf=newWeakReference<String>(str);可用場(chǎng)景:Java源碼中的java.util.WeakHashMap中的key就是使用弱引用,我的理解就是,一旦我不需要某個(gè)引用,JVM會(huì)自動(dòng)幫我處理它,這樣我就不需要做其它操作。虛引用虛引用的回收機(jī)制跟弱引用差不多,但是它被回收之前,會(huì)被放入ReferenceQueue中。注意哦,其它引用是被JVM回收后才被傳入ReferenceQueue中的。由于這個(gè)機(jī)制,所以虛引用大多被用于引用銷(xiāo)毀前的處理工作。還有就是,虛引用創(chuàng)建的時(shí)候,必須帶有ReferenceQueue,使用例子:prf=newPhantomReference<String>(newString("str"),newReferenceQueue<>());可用場(chǎng)景:對(duì)象銷(xiāo)毀前的一些操作,比如說(shuō)資源釋放等。**Object.finalize()雖然也可以做這類(lèi)動(dòng)作,但是這個(gè)方式即不安全又低效上訴所說(shuō)的幾類(lèi)引用,都是指對(duì)象本身的引用,而不是指Reference的四個(gè)子類(lèi)的引用(SoftReference等)。15、泛型常用特點(diǎn)泛型是JavaSE1.5之后的特性,《Java核心技術(shù)》中對(duì)泛型的定義是:“泛型”意味著編寫(xiě)的代碼可以被不同類(lèi)型的對(duì)象所重用?!胺盒汀?,顧名思義,“泛指的類(lèi)型”。我們提供了泛指的概念,但具體執(zhí)行的時(shí)候卻可以有具體的規(guī)則來(lái)約束,比如我們用的非常多的ArrayList就是個(gè)泛型類(lèi),ArrayList作為集合可以存放各種元素,如Integer,String,自定義的各種類(lèi)型等,但在我們使用的時(shí)候通過(guò)具體的規(guī)則來(lái)約束,如我們可以約束集合中只存放Integer類(lèi)型的元素,如ListList<Integer>iniData=newArrayList<>()使用泛型的好處?以集合來(lái)舉例,使用泛型的好處是我們不必因?yàn)樘砑釉仡?lèi)型的不同而定義不同類(lèi)型的集合,如整型集合類(lèi),浮點(diǎn)型集合類(lèi),字符串集合類(lèi),我們可以定義一個(gè)集合來(lái)存放整型、浮點(diǎn)型,字符串型數(shù)據(jù),而這并不是最重要的,因?yàn)槲覀冎灰训讓哟鎯?chǔ)設(shè)置了Object即可,添加的數(shù)據(jù)全部都可向上轉(zhuǎn)型為Object16、Java創(chuàng)建對(duì)象有幾種方式?java中提供了以下四種創(chuàng)建對(duì)象的方式:new創(chuàng)建新對(duì)象通過(guò)反射機(jī)制采用clone機(jī)制通過(guò)序列化機(jī)制17、有沒(méi)有可能兩個(gè)不相等的對(duì)象有相同的hashcode有可能.在產(chǎn)生hash沖突時(shí),兩個(gè)不相等的對(duì)象就會(huì)有相同的hashcode值.當(dāng)hash沖突產(chǎn)生時(shí),一般有以下幾種方式來(lái)處理:拉鏈法:每個(gè)哈希表節(jié)點(diǎn)都有一個(gè)next指針,多個(gè)哈希表節(jié)點(diǎn)可以用next指針構(gòu)成一個(gè)單向鏈表,被分配到同一個(gè)索引上的多個(gè)節(jié)點(diǎn)可以用這個(gè)單向鏈表進(jìn)行存儲(chǔ).開(kāi)放定址法:一旦發(fā)生了沖突,就去尋找下一個(gè)空的散列地址,只要散列表足夠大,空的散列地址總能找到,并將記錄存入再哈希:又叫雙哈希法,有多個(gè)不同的Hash函數(shù).當(dāng)發(fā)生沖突時(shí),使用第二個(gè),第三個(gè)….等哈希函數(shù)計(jì)算地址,直到無(wú)沖突.18、深拷貝和淺拷貝的區(qū)別是什么?淺拷貝:被復(fù)制對(duì)象的所有變量都含有與原來(lái)的對(duì)象相同的值,而所有的對(duì)其他對(duì)象的引用仍然指向原來(lái)的對(duì)象.換言之,淺拷貝僅僅復(fù)制所考慮的對(duì)象,而不復(fù)制它所引用的對(duì)象.深拷貝:被復(fù)制對(duì)象的所有變量都含有與原來(lái)的對(duì)象相同的值.而那些引用其他對(duì)象的變量將指向被復(fù)制過(guò)的新對(duì)象.而不再是原有的那些被引用的對(duì)象.換言之.深拷貝把要復(fù)制的對(duì)象所引用的對(duì)象都復(fù)制了一遍.19、?nal有哪些用法??nal也是很多面試喜歡問(wèn)的地方,但我覺(jué)得這個(gè)問(wèn)題很無(wú)聊,通常能回答下以下5點(diǎn)就不錯(cuò)了:被?nal修飾的類(lèi)不可以被繼承被?nal修飾的方法不可以被重寫(xiě)被?nal修飾的變量不可以被改變.如果修飾引用,那么表示引用不可變,引用指向的內(nèi)容可變.被?nal修飾的方法,JVM會(huì)嘗試將其內(nèi)聯(lián),以提高運(yùn)行效率被?nal修飾的常量,在編譯階段會(huì)存入常量池中.除此之外,編譯器對(duì)?nal域要遵守的兩個(gè)重排序規(guī)則更好:在構(gòu)造函數(shù)內(nèi)對(duì)一個(gè)?nal域的寫(xiě)入,與隨后把這個(gè)被構(gòu)造對(duì)象的引用賦值給一個(gè)引用變量,這兩個(gè)操作之間不能重排序初次讀一個(gè)包含?nal域的對(duì)象的引用,與隨后初次讀這個(gè)?nal域,這兩個(gè)操作之間不能重排序.20、static都有哪些用法?所有的人都知道static關(guān)鍵字這兩個(gè)基本的用法:靜態(tài)變量和靜態(tài)方法.也就是被static所修飾的變量/方法都屬于類(lèi)的靜態(tài)資源,類(lèi)實(shí)例所共享.除了靜態(tài)變量和靜態(tài)方法之外,static也用于靜態(tài)塊,多用于初始化操作:publicpubliccalssPreCache{static{//執(zhí)行相關(guān)操作}}此外static也多用于修飾內(nèi)部類(lèi),此時(shí)稱(chēng)之為靜態(tài)內(nèi)部類(lèi).最后一種用法就是靜態(tài)導(dǎo)包,即importstatic.importstatic是在JDK1.5之后引入的新特性,可以用來(lái)指定導(dǎo)入某個(gè)類(lèi)中的靜態(tài)資源,并且不需要使用類(lèi)名,可以直接使用資源名,比如:importimportstaticjava.lang.Math.*;publicclassTest{publicstaticvoidmain(String[]args){//System.out.println(Math.sin(20));傳統(tǒng)做法System.out.println(sin(20));}}21、3*0.10.3返回值是什么false,因?yàn)橛行└↑c(diǎn)數(shù)不能完全精確的表示出來(lái).22、a=a+b與a+=b有什么區(qū)別嗎?+=操作符會(huì)進(jìn)行隱式自動(dòng)類(lèi)型轉(zhuǎn)換,此處a+=b隱式的將加操作的結(jié)果類(lèi)型強(qiáng)制轉(zhuǎn)換為持有結(jié)果的類(lèi)型,而a=a+b則不會(huì)自動(dòng)進(jìn)行類(lèi)型轉(zhuǎn)換.如:bytebytea=127;byteb=127;bab報(bào)編譯錯(cuò)誤:cannotconvertfrominttobyteb+=a;以下代碼是否有錯(cuò),有的話(huà)怎么改?shortshorts1=1;s1=s1+1;有錯(cuò)誤.short類(lèi)型在進(jìn)行運(yùn)算時(shí)會(huì)自動(dòng)提升為int類(lèi)型,也就是說(shuō)s1+1的運(yùn)算結(jié)果是int類(lèi)型,而s1是short類(lèi)型,此時(shí)編譯器會(huì)報(bào)錯(cuò).正確寫(xiě)法:shortshorts1=1;s1+=1;+=操作符會(huì)對(duì)右邊的表達(dá)式結(jié)果強(qiáng)轉(zhuǎn)匹配左邊的數(shù)據(jù)類(lèi)型,所以沒(méi)錯(cuò).23、trycatch?nally,try里有return,?nally還執(zhí)行么?執(zhí)行,并且?nally的執(zhí)行早于try里面的return結(jié)論:1、不管有木有出現(xiàn)異常,?nally塊中代碼都會(huì)執(zhí)行;2、當(dāng)try和catch中有return時(shí),?nally仍然會(huì)執(zhí)行;3、?nally是在return后面的表達(dá)式運(yùn)算后執(zhí)行的(此時(shí)并沒(méi)有返回運(yùn)算后的值,而是先把要返回的值保存起來(lái),管?nally中的代碼怎么樣,返回的值都不會(huì)改變,任然是之前保存的值),所以函數(shù)返回值是在?nally執(zhí)行前確定的;4、?nally中最好不要包含return,否則程序會(huì)提前退出,返回值不是try或catch中保存的返回值。24、Excption與Error包結(jié)構(gòu)Java可拋出(Throwable)的結(jié)構(gòu)分為三種類(lèi)型:被檢查的異常(CheckedException),運(yùn)行時(shí)異常(RuntimeException),錯(cuò)誤(Error)。1、運(yùn)行時(shí)異常定義:RuntimeException及其子類(lèi)都被稱(chēng)為運(yùn)行時(shí)異常。特點(diǎn):Java編譯器不會(huì)檢查它。也就是說(shuō),當(dāng)程序中可能出現(xiàn)這類(lèi)異常時(shí),倘若既"沒(méi)有通過(guò)throws聲明拋出它",也"沒(méi)有用try-catch語(yǔ)句捕獲它",還是會(huì)編譯通過(guò)。例如,除數(shù)為零時(shí)產(chǎn)生的ArithmeticException異常,數(shù)組越界時(shí)產(chǎn)生的IndexOutOfBoundsException異常,fail-fast機(jī)制產(chǎn)生的ConcurrentModi?cationException異常(java.util包下面的所有的集合類(lèi)都是快速失敗的,“快速失敗”也就是fail-fast,它是Java集合的一種錯(cuò)誤檢測(cè)機(jī)制。當(dāng)多個(gè)線(xiàn)程對(duì)集合進(jìn)行結(jié)構(gòu)上的改變的操作時(shí),有可能會(huì)產(chǎn)生fail-fast機(jī)制。記住是有可能,而不是一定。例如:假設(shè)存在兩個(gè)線(xiàn)程(線(xiàn)程1、線(xiàn)程2),線(xiàn)程1通過(guò)Iterator在遍歷集合A中的元素,在某個(gè)時(shí)候線(xiàn)程2修改了集合A的結(jié)構(gòu)(是結(jié)構(gòu)上面的修改,而不是簡(jiǎn)單的修改集合元素的內(nèi)容),那么這個(gè)時(shí)候程序就會(huì)拋出ConcurrentModi?cationException異常,從而產(chǎn)生fail-fast機(jī)制,這個(gè)錯(cuò)叫并發(fā)修改異常。Fail-safe,java.util.concurrent包下面的所有的類(lèi)都是安全失敗的,在遍歷過(guò)程中,如果已經(jīng)遍歷的數(shù)組上的內(nèi)容變化了,迭代器不會(huì)拋出ConcurrentModi?cationException異常。如果未遍歷的數(shù)組上的內(nèi)容發(fā)生了變化,則有可能反映到迭代過(guò)程中。這就是ConcurrentHashMap迭代器弱一致的表現(xiàn)。ConcurrentHashMap的弱一致性主要是為了提升效率,是一致性與效率之間的一種權(quán)衡。要成為強(qiáng)一致性,就得到處使用鎖,甚至是全局鎖,這就與Hashtable和同步的HashMap一樣了。)等,都屬于運(yùn)行時(shí)異常。常見(jiàn)的五種運(yùn)行時(shí)異常:ClassCastException(類(lèi)轉(zhuǎn)換異常)IndexOutOfBoundsException(數(shù)組越界)NullPointerException(空指針異常)ArrayStoreException(數(shù)據(jù)存儲(chǔ)異常,操作數(shù)組是類(lèi)型不一致)Bu?erOver?owException2、被檢查異常定義:Exception類(lèi)本身,以及Exception的子類(lèi)中除了"運(yùn)行時(shí)異常"之外的其它子類(lèi)都屬于被檢查異常。特點(diǎn):Java編譯器會(huì)檢查它。此類(lèi)異常,要么通過(guò)throws進(jìn)行聲明拋出,要么通過(guò)try-catch進(jìn)行捕獲處就屬于被檢查異常。當(dāng)通過(guò)clone()接口去克隆一個(gè)對(duì)象,而該對(duì)象對(duì)應(yīng)的類(lèi)沒(méi)有實(shí)現(xiàn)Cloneable接口,就會(huì)拋出CloneNotSupportedException異常。被檢查異常通常都是可以恢復(fù)的。如:IOExceptionFileNotFoundExceptionSQLException被檢查的異常適用于那些不是因程序引起的錯(cuò)誤情況,比如:讀取文件時(shí)文件不存在引發(fā)的FileNotFoundException。然而,不被檢查的異常通常都是由于糟糕的編程引起的,比如:在對(duì)象引用時(shí)沒(méi)有確保對(duì)象非空而引起的NullPointerException。3、錯(cuò)誤定義:Error類(lèi)及其子類(lèi)。特點(diǎn):和運(yùn)行時(shí)異常一樣,編譯器也不會(huì)對(duì)錯(cuò)誤進(jìn)行檢查。當(dāng)資源不足、約束失敗、或是其它程序無(wú)法繼續(xù)運(yùn)行的條件發(fā)生時(shí),就產(chǎn)生錯(cuò)誤。程序本身無(wú)法修復(fù)這些錯(cuò)誤的。例如,VirtualMachineError就屬于錯(cuò)誤。出現(xiàn)這種錯(cuò)誤會(huì)導(dǎo)致程序終止運(yùn)行。OutOfMemoryError、ThreadDeath。Java虛擬機(jī)規(guī)范規(guī)定JVM的內(nèi)存分為了好幾塊,比如堆,棧,程序計(jì)數(shù)器,方法區(qū)等25、OOM你遇到過(guò)哪些情況,SOF你遇到過(guò)哪些情況OOM:1,OutOfMemoryError異常除了程序計(jì)數(shù)器外,虛擬機(jī)內(nèi)存的其他幾個(gè)運(yùn)行時(shí)區(qū)域都有發(fā)生OutOfMemoryError(OOM)異常的可能。JavaHeap溢出:heapspacess。java堆用于存儲(chǔ)對(duì)象實(shí)例,我們只要不斷的創(chuàng)建對(duì)象,并且保證GCRoots到對(duì)象之間有可達(dá)路徑來(lái)避免垃圾回收機(jī)制清除這些對(duì)象,就會(huì)在對(duì)象數(shù)量達(dá)到最大堆容量限制后產(chǎn)生內(nèi)存溢出異常。出現(xiàn)這種異常,一般手段是先通過(guò)內(nèi)存映像分析工具(如EclipseMemoryAnalyzer)對(duì)dump出來(lái)的堆轉(zhuǎn)存快照進(jìn)行分析,重點(diǎn)是確認(rèn)內(nèi)存中的對(duì)象是否是必要的,先分清是因?yàn)閮?nèi)存泄漏(MemoryLeak)還是內(nèi)存溢出(MemoryOver?ow)。如果是內(nèi)存泄漏,可進(jìn)一步通過(guò)工具查看泄漏對(duì)象到GCRoots的引用鏈。于是就能找到泄漏對(duì)象是通過(guò)怎樣的路徑與GCRoots相關(guān)聯(lián)并導(dǎo)致垃圾收集器無(wú)法自動(dòng)回收。如果不存在泄漏,那就應(yīng)該檢查虛擬機(jī)的參數(shù)(-Xmx與-Xms)的設(shè)置是否適當(dāng)。2,虛擬機(jī)棧和本地方法棧溢出如果線(xiàn)程請(qǐng)求的棧深度大于虛擬機(jī)所允許的最大深度,將拋出StackOver?owError異常。如果虛擬機(jī)在擴(kuò)展棧時(shí)無(wú)法申請(qǐng)到足夠的內(nèi)存空間,則拋出OutOfMemoryError異常這里需要注意當(dāng)棧的大小越大可分配的線(xiàn)程數(shù)就越少。3,運(yùn)行時(shí)常量池溢出異常信息:java.lang.OutOfMemoryError:PermGenspace如果要向運(yùn)行時(shí)常量池中添加內(nèi)容,最簡(jiǎn)單的做法就是使用Sern()這個(gè)Native方法。該方法的作用是:如果池中已經(jīng)包含一個(gè)等于此String的字符串,則返回代表池中這個(gè)字符串的String對(duì)象;否則,將此String對(duì)象包含的字符串添加到常量池中,并且返回此String對(duì)象的引用。由于常量池分配在方法區(qū)內(nèi),我們可以通過(guò)-XX:PermSize和-XX:MaxPermSize限制方法區(qū)的大小,從而間接限制其中常量池的容量。4,方法區(qū)溢出方法區(qū)用于存放Class的相關(guān)信息,如類(lèi)名、訪問(wèn)修飾符、常量池、字段描述、方法描述等。也有可能是方法區(qū)中保存的class對(duì)象沒(méi)有被及時(shí)回收掉或者class信息占用的內(nèi)存超過(guò)了我們配置。異常信息:java.lang.OutOfMemoryError:PermGenspace方法區(qū)溢出也是一種常見(jiàn)的內(nèi)存溢出異常,一個(gè)類(lèi)如果要被垃圾收集器回收,判定條件是很苛刻的。在經(jīng)常動(dòng)態(tài)生成大量Class的應(yīng)用中,要特別注意這點(diǎn)。SOF(堆棧溢出StackOver?ow):StackOver?owError的定義:當(dāng)應(yīng)用程序遞歸太深而發(fā)生堆棧溢出時(shí),拋出該錯(cuò)誤。因?yàn)闂R话隳J(rèn)為1-2m,一旦出現(xiàn)死循環(huán)或者是大量的遞歸調(diào)用,在不斷的壓棧過(guò)程中,造成棧容量超過(guò)1m而導(dǎo)致溢出。棧溢出的原因:遞歸調(diào)用,大量循環(huán)或死循環(huán),全局變量是否過(guò)多,數(shù)組、List、map數(shù)據(jù)過(guò)大。26、簡(jiǎn)述線(xiàn)程、程序、進(jìn)程的基本概念。以及他們之間關(guān)系是什么?線(xiàn)程與進(jìn)程相似,但線(xiàn)程是一個(gè)比進(jìn)程更小的執(zhí)行單位。一個(gè)進(jìn)程在其執(zhí)行的過(guò)程中可以產(chǎn)生多個(gè)線(xiàn)程。與進(jìn)程不同的是同類(lèi)的多個(gè)線(xiàn)程共享同一塊內(nèi)存空間和一組系統(tǒng)資源,所以系統(tǒng)在產(chǎn)生一個(gè)線(xiàn)程,或是在各個(gè)線(xiàn)程之間作切換工作時(shí),負(fù)擔(dān)要比進(jìn)程小得多,也正因?yàn)槿绱?,線(xiàn)程也被稱(chēng)為輕量級(jí)進(jìn)程。程序是含有指令和數(shù)據(jù)的文件,被存儲(chǔ)在磁盤(pán)或其他的數(shù)據(jù)存儲(chǔ)設(shè)備中,也就是說(shuō)程序是靜態(tài)的代碼。進(jìn)程是程序的一次執(zhí)行過(guò)程,是系統(tǒng)運(yùn)行程序的基本單位,因此進(jìn)程是動(dòng)態(tài)的。系統(tǒng)運(yùn)行一個(gè)程序即是一個(gè)進(jìn)程從創(chuàng)建,運(yùn)行到消亡的過(guò)程。簡(jiǎn)單來(lái)說(shuō),一個(gè)進(jìn)程就是一個(gè)執(zhí)行中的程序,它在計(jì)算機(jī)中一個(gè)指令接著一個(gè)指令地執(zhí)行著,同時(shí),每個(gè)進(jìn)程還占有某些系統(tǒng)資源如CPU時(shí)間,內(nèi)存空間,文件,輸入輸出設(shè)備的使用權(quán)等等。換句話(huà)說(shuō),當(dāng)程序在執(zhí)行時(shí),將會(huì)被操作系統(tǒng)載入內(nèi)存中。線(xiàn)程是進(jìn)程劃分成的更小的運(yùn)行單位。線(xiàn)程和進(jìn)程最大的不同在于基本上各進(jìn)程是獨(dú)立的,而各線(xiàn)程則不一定,因?yàn)橥贿M(jìn)程中的線(xiàn)程極有可能會(huì)相互影響。從另一角度來(lái)說(shuō),進(jìn)程屬于操作系統(tǒng)的范疇,主要是同一段時(shí)間內(nèi),可以同時(shí)執(zhí)行一個(gè)以上的程序,而線(xiàn)程則是在同一程序內(nèi)幾乎同時(shí)執(zhí)行一個(gè)以上的程序段。27、線(xiàn)程有哪些基本狀態(tài)?Java線(xiàn)程在運(yùn)行的生命周期中的指定時(shí)刻只可能處于下面6種不同狀態(tài)的其中一個(gè)狀態(tài)(圖源《Java并發(fā)編程藝術(shù)》4.1.4節(jié))。線(xiàn)程在生命周期中并不是固定處于某一個(gè)狀態(tài)而是隨著代碼的執(zhí)行在不同狀態(tài)之間切換。Java線(xiàn)程狀態(tài)變遷如下圖所示(圖源《Java并發(fā)編程藝術(shù)》4.1.4節(jié)):Java虛擬機(jī)(JVM)RUNNABLERUNNINGRUNNABLE狀態(tài)(圖源:HowToDoInJava:JavaThreadLifeCycleandThreadStates),所以Java系統(tǒng)一般將這兩RUNNABLE(運(yùn)行中)Java虛擬機(jī)(JVM)RUNNABLERUNNING狀態(tài),它只能看到RUNNABLE狀態(tài)(圖源:HowToDoInJava:JavaThreadLifeCycleandThreadStates),所以Java系統(tǒng)一RUNNABLE(運(yùn)行中)當(dāng)線(xiàn)程執(zhí)行wait()方法之后,線(xiàn)程進(jìn)入WAITING(等待)狀態(tài)。進(jìn)入等待狀態(tài)的線(xiàn)程需要依靠其他線(xiàn)程的通知才能夠返回到運(yùn)行狀態(tài),而TIME_WAITING(超時(shí)等待)狀態(tài)相當(dāng)于在等待狀態(tài)的基礎(chǔ)上增加了超時(shí)限制,比如通過(guò)sleep(longmillis)方法或wait(longmillis)方法可以將Java線(xiàn)程置于TIMEDWAITING狀態(tài)。當(dāng)超時(shí)時(shí)間到達(dá)后Java線(xiàn)程將會(huì)返回到RUNNABLE狀態(tài)。當(dāng)線(xiàn)程調(diào)用同步方法時(shí),在沒(méi)有獲取到鎖的情況下,線(xiàn)程將會(huì)進(jìn)入到BLOCKED(阻塞)狀態(tài)。線(xiàn)程在執(zhí)行Runnable的run()TERMINATED(終止)28、Java序列化中如果有些字段不想進(jìn)行序列化,怎么辦?對(duì)于不想進(jìn)行序列化的變量,使用transient關(guān)鍵字修飾。transient關(guān)鍵字的作用是:阻止實(shí)例中那些用此關(guān)鍵字修飾的的變量序列化;當(dāng)對(duì)象被反序列化時(shí),transient修飾的變量值不會(huì)被持久化和恢復(fù)。transient只能修飾變量,不能修飾類(lèi)和方法。29、JavaIO流JavaIO流分為幾種?按照流的流向分,可以分為輸入流和輸出流;按照操作單元?jiǎng)澐?,可以劃分為字?jié)流和字符流;按照流的角色劃分為節(jié)點(diǎn)流和處理流。JavaIo流共涉及40多個(gè)類(lèi),這些類(lèi)看上去很雜亂,但實(shí)際上很有規(guī)則,而且彼此之間存在非常緊密的JavaI0404個(gè)抽象類(lèi)基類(lèi)中派生出來(lái)的。InputStream/Reader:所有的輸入流的基類(lèi),前者是字節(jié)輸入流,后者是字符輸入流。OutputStream/Writer:所有輸出流的基類(lèi),前者是字節(jié)輸出流,后者是字符輸出流。按操作方式分類(lèi)結(jié)構(gòu)圖:按操作對(duì)象分類(lèi)結(jié)構(gòu)圖:IO-操作對(duì)象分類(lèi)30、JavaIO與NIO的區(qū)別推薦閱讀:s://mp.weixin./s/N1ojvByYmary65B6JM1ZWA31、java反射的作用于原理1、定義:反射機(jī)制是在運(yùn)行時(shí),對(duì)于任意一個(gè)類(lèi),都能夠知道這個(gè)類(lèi)的所有屬性和方法;對(duì)于任意個(gè)對(duì)象,都能夠調(diào)用它的任意一個(gè)方法。在java中,只要給定類(lèi)的名字,就可以通過(guò)反射機(jī)制來(lái)獲得類(lèi)的所有信息。這種動(dòng)態(tài)獲取的信息以及動(dòng)態(tài)調(diào)用對(duì)象的方法的功能稱(chēng)為Java語(yǔ)言的反射機(jī)制。2、哪里會(huì)用到反射機(jī)制?jdbc就是典型的反射ClassClass.forName('com.mysql.jdbc.Driver.class');//加載MySQL的驅(qū)動(dòng)類(lèi)這就是反射。如hibernate,struts等框架使用反射實(shí)現(xiàn)的。3、反射的實(shí)現(xiàn)方式:第一步:獲取Class對(duì)象,有4中方法:1)Class.forName(“類(lèi)的路徑”);2)類(lèi)名.class對(duì)象名.getClass()基本類(lèi)型的包裝類(lèi),可以調(diào)用包裝類(lèi)的Type屬性來(lái)獲得該包裝類(lèi)的Class對(duì)象4、實(shí)現(xiàn)Java反射的類(lèi):Class:表示正在運(yùn)行的Java應(yīng)用程序中的類(lèi)和接口注意:所有獲取對(duì)象的信息都需要Class類(lèi)來(lái)實(shí)現(xiàn)。Field:提供有關(guān)類(lèi)和接口的屬性信息,以及對(duì)它的動(dòng)態(tài)訪問(wèn)權(quán)限。Constructor:提供關(guān)于類(lèi)的單個(gè)構(gòu)造方法的信息以及它的訪問(wèn)權(quán)限Method:提供類(lèi)或接口中某個(gè)方法的信息5、反射機(jī)制的優(yōu)缺點(diǎn):優(yōu)點(diǎn):能夠運(yùn)行時(shí)動(dòng)態(tài)獲取類(lèi)的實(shí)例,提高靈活性;與動(dòng)態(tài)編譯結(jié)合缺點(diǎn):1)使用反射性能較低,需要解析字節(jié)碼,將內(nèi)存中的對(duì)象進(jìn)行解析。解決方案:1、通過(guò)setAccessible(true)關(guān)閉JDK的安全檢查來(lái)提升反射速度;2、多次創(chuàng)建一個(gè)類(lèi)的實(shí)例時(shí),有緩存會(huì)快很多3、Re?ectASM工具類(lèi),通過(guò)字節(jié)碼生成的方式加快反射速度相對(duì)不安全,破壞了封裝性(因?yàn)橥ㄟ^(guò)反射可以獲得私有方法和屬性)32、說(shuō)說(shuō)List,Set,Map三者的區(qū)別?List(對(duì)付順序的好幫手):List接口存儲(chǔ)一組不唯一(可以有多個(gè)元素引用相同的對(duì)象),有序的對(duì)象Set(注重獨(dú)一無(wú)二的性質(zhì)):不允許重復(fù)的集合。不會(huì)有多個(gè)元素引用相同的對(duì)象。Map(用Key來(lái)搜索的專(zhuān)家):使用鍵值對(duì)存儲(chǔ)。Map會(huì)維護(hù)與Key有關(guān)聯(lián)的值。兩個(gè)Key可以引用相同的對(duì)象,但Key不能重復(fù),典型的Key是String類(lèi)型,但也可以是任何對(duì)象。JVM篇1、知識(shí)點(diǎn)匯總JVM是Java運(yùn)行基礎(chǔ),面試時(shí)一定會(huì)遇到JVM的有關(guān)問(wèn)題,內(nèi)容相對(duì)集中,但對(duì)只是深度要求較高.其中內(nèi)存模型,類(lèi)加載機(jī)制,GC是重點(diǎn)方面.性能調(diào)優(yōu)部分更偏向應(yīng)用,重點(diǎn)突出實(shí)踐能力.編譯器優(yōu)化和執(zhí)行模式部分偏向于理論基礎(chǔ),重點(diǎn)掌握知識(shí)點(diǎn).需了解內(nèi)存模型各部分作用,保存哪些數(shù)據(jù).類(lèi)加載雙親委派加載機(jī)制,常用加載器分別加載哪種類(lèi)型的類(lèi).GC分代回收的思想和依據(jù)以及不同垃圾回收算法的回收思路和適合場(chǎng)景.性能調(diào)優(yōu)常有JVM優(yōu)化參數(shù)作用,參數(shù)調(diào)優(yōu)的依據(jù),常用的JVM分析工具能分析哪些問(wèn)題以及使用方法.執(zhí)行模式解釋/編譯/混合模式的優(yōu)缺點(diǎn),Java7提供的分層編譯技術(shù),JIT即時(shí)編譯技術(shù),OSR棧上替換,C1/C2編譯器針對(duì)的場(chǎng)景,C2針對(duì)的是server模式,優(yōu)化更激進(jìn).新技術(shù)方面Java10的graal編譯器編譯器優(yōu)化javac的編譯過(guò)程,ast抽象語(yǔ)法樹(shù),編譯器優(yōu)化和運(yùn)行器優(yōu)化.2、知識(shí)點(diǎn)詳解:1、JVM內(nèi)存模型:線(xiàn)程獨(dú)占:棧,本地方法棧,程序計(jì)數(shù)器線(xiàn)程共享:堆,方法區(qū)2、棧:又稱(chēng)方法棧,線(xiàn)程私有的,線(xiàn)程執(zhí)行方法是都會(huì)創(chuàng)建一個(gè)棧陣,用來(lái)存儲(chǔ)局部變量表,操作棧,動(dòng)態(tài)鏈接,方法出口等信息.調(diào)用方法時(shí)執(zhí)行入棧,方法返回式執(zhí)行出棧.3、本地方法棧與棧類(lèi)似,也是用來(lái)保存執(zhí)行方法的信息.執(zhí)行Java方法是使用棧,執(zhí)行Native方法時(shí)使用本地方法棧.4、程序計(jì)數(shù)器保存著當(dāng)前線(xiàn)程執(zhí)行的字節(jié)碼位置,每個(gè)線(xiàn)程工作時(shí)都有獨(dú)立的計(jì)數(shù)器,只為執(zhí)行Java方法服務(wù),執(zhí)行Native方法時(shí),程序計(jì)數(shù)器為空.5、堆JVM內(nèi)存管理最大的一塊,對(duì)被線(xiàn)程共享,目的是存放對(duì)象的實(shí)例,幾乎所欲的對(duì)象實(shí)例都會(huì)放在這里,當(dāng)堆沒(méi)有可用空間時(shí),會(huì)拋出OOM異常.根據(jù)對(duì)象的存活周期不同,JVM把對(duì)象進(jìn)行分代管理,由垃圾回收器進(jìn)行垃圾的回收管理6、方法區(qū):又稱(chēng)非堆區(qū),用于存儲(chǔ)已被虛擬機(jī)加載的類(lèi)信息,常量,靜態(tài)變量,即時(shí)編譯器優(yōu)化后的代碼等數(shù)據(jù).1.7的永久代和1.8的元空間都是方法區(qū)的一種實(shí)現(xiàn)7、JVM內(nèi)存可見(jiàn)性JMM是定義程序中變量的訪問(wèn)規(guī)則,線(xiàn)程對(duì)于變量的操作只能在自己的工作內(nèi)存中進(jìn)行,而不能直接對(duì)主內(nèi)存操作.由于指令重排序,讀寫(xiě)的順序會(huì)被打亂,因此JMM需要提供原子性,可見(jiàn)性,有序性保證.3、類(lèi)加載與卸載加載過(guò)程其中驗(yàn)證,準(zhǔn)備,解析合稱(chēng)鏈接加載通過(guò)類(lèi)的完全限定名,查找此類(lèi)字節(jié)碼文件,利用字節(jié)碼文件創(chuàng)建Class對(duì)象.驗(yàn)證確保Class文件符合當(dāng)前虛擬機(jī)的要求,不會(huì)危害到虛擬機(jī)自身安全.準(zhǔn)備進(jìn)行內(nèi)存分配,為static修飾的類(lèi)變量分配內(nèi)存,并設(shè)置初始值(0或null).不包含?nal修飾的靜態(tài)變量,因?yàn)?nal變量在編譯時(shí)分配.解析將常量池中的符號(hào)引用替換為直接引用的過(guò)程.直接引用為直接指向目標(biāo)的指針或者相對(duì)偏移量等.初始化主要完成靜態(tài)塊執(zhí)行以及靜態(tài)變量的賦值.先初始化父類(lèi),再初始化當(dāng)前類(lèi).只有對(duì)類(lèi)主動(dòng)使用時(shí)才會(huì)初始化.觸發(fā)條件包括,創(chuàng)建類(lèi)的實(shí)例時(shí),訪問(wèn)類(lèi)的靜態(tài)方法或靜態(tài)變量的時(shí)候,使用Class.forName反射類(lèi)的時(shí)候,或者某個(gè)子類(lèi)初始化的時(shí)候.Java自帶的加載器加載的類(lèi),在虛擬機(jī)的生命周期中是不會(huì)被卸載的,只有用戶(hù)自定義的加載器加載的類(lèi)才可以被卸.1、加載機(jī)制-雙親委派模式雙親委派模式,即加載器加載類(lèi)時(shí)先把請(qǐng)求委托給自己的父類(lèi)加載器執(zhí)行,直到頂層的啟動(dòng)類(lèi)加載器.父類(lèi)加載器能夠完成加載則成功返回,不能則子類(lèi)加載器才自己嘗試加載.*優(yōu)點(diǎn):避免類(lèi)的重復(fù)加載避免Java的核心API被篡改2、分代回收分代回收基于兩個(gè)事實(shí):大部分對(duì)象很快就不使用了,還有一部分不會(huì)立即無(wú)用,但也不會(huì)持續(xù)很長(zhǎng)時(shí)間.年輕代->標(biāo)記-復(fù)制老年代->標(biāo)記-清除3、回收算法a、G1算法1.9后默認(rèn)的垃圾回收算法,特點(diǎn)保持高回收率的同時(shí)減少停頓.采用每次只清理一部分,而不是清理全部的增量式清理,以保證停頓時(shí)間不會(huì)過(guò)長(zhǎng)其取消了年輕代與老年代的物理劃分,但仍屬于分代收集器,算法將堆分為若干個(gè)邏輯區(qū)域(region),一部分用作年輕代,一部分用作老年代,還有用來(lái)存儲(chǔ)巨型對(duì)象的分區(qū).同CMS相同,會(huì)遍歷所有對(duì)象,標(biāo)記引用情況,清除對(duì)象后會(huì)對(duì)區(qū)域進(jìn)行復(fù)制移動(dòng),以整合碎片空間.年輕代回收:并行復(fù)制采用復(fù)制算法,并行收集,會(huì)StopTheWorld.老年代回收:會(huì)對(duì)年輕代一并回收StopTheWorld.GC線(xiàn)程和應(yīng)用線(xiàn)程并發(fā)執(zhí)行.最終標(biāo)記完成三色標(biāo)記周期,會(huì)StopTheWorld.復(fù)制/清楚會(huì)優(yōu)先對(duì)可回收空間加大的區(qū)域進(jìn)行回收b、ZGC算法前面提供的高效垃圾回收算法,針對(duì)大堆內(nèi)存設(shè)計(jì),可以處理TB級(jí)別的堆,可以做到10ms以下的回收停頓時(shí)間.著色指針讀屏障并發(fā)處理基于region內(nèi)存壓縮(整理)roots標(biāo)記:標(biāo)記root對(duì)象,會(huì)StopTheWorld.并發(fā)標(biāo)記:利用讀屏障與應(yīng)用線(xiàn)程一起運(yùn)行標(biāo)記,可能會(huì)發(fā)生StopTheWorld.清除會(huì)清理標(biāo)記為不可用的對(duì)象.roots重定位:是對(duì)存活的對(duì)象進(jìn)行移動(dòng),以騰出大塊內(nèi)存空間,減少碎片產(chǎn)生.重定位最開(kāi)始會(huì)StopTheWorld,卻決于重定位集與對(duì)象總活動(dòng)集的比例.并發(fā)重定位與并發(fā)標(biāo)記類(lèi)似.4、簡(jiǎn)述一下JVM的內(nèi)存模型1.JVM內(nèi)存模型簡(jiǎn)介JVM定義了不同運(yùn)行時(shí)數(shù)據(jù)區(qū),他們是用來(lái)執(zhí)行應(yīng)用程序的。某些區(qū)域隨著JVM啟動(dòng)及銷(xiāo)毀,另外一些區(qū)域的數(shù)據(jù)是線(xiàn)程性獨(dú)立的,隨著線(xiàn)程創(chuàng)建和銷(xiāo)毀。jvm內(nèi)存模型總體架構(gòu)圖如下:(摘自oracle官方網(wǎng)站)JVM在執(zhí)行Java程序時(shí),會(huì)把它管理的內(nèi)存劃分為若干個(gè)的區(qū)域,每個(gè)區(qū)域都有自己的用途和創(chuàng)建銷(xiāo)毀時(shí)間。如下圖所示,可以分為兩大部分,線(xiàn)程私有區(qū)和共享區(qū)。下圖是根據(jù)自己理解畫(huà)的一個(gè)JVM內(nèi)存模型架構(gòu)圖:JVM內(nèi)存分為線(xiàn)程私有區(qū)和線(xiàn)程共享區(qū)線(xiàn)程私有區(qū)1、程序計(jì)數(shù)器當(dāng)同時(shí)進(jìn)行的線(xiàn)程數(shù)超過(guò)CPU數(shù)或其內(nèi)核數(shù)時(shí),就要通過(guò)時(shí)間片輪詢(xún)分派CPU的時(shí)間資源,不免發(fā)生線(xiàn)程切換。這時(shí),每個(gè)線(xiàn)程就需要一個(gè)屬于自己的計(jì)數(shù)器來(lái)記錄下一條要運(yùn)行的指令。如果執(zhí)行的是JAVA方法,計(jì)數(shù)器記錄正在執(zhí)行的java字節(jié)碼地址,如果執(zhí)行的是native方法,則計(jì)數(shù)器為空。2、虛擬機(jī)棧線(xiàn)程私有的,與線(xiàn)程在同一時(shí)間創(chuàng)建。管理JAVA方法執(zhí)行的內(nèi)存模型。每個(gè)方法執(zhí)行時(shí)都會(huì)創(chuàng)建一個(gè)楨棧來(lái)存儲(chǔ)方法的的變量表、操作數(shù)棧、動(dòng)態(tài)鏈接方法、返回值、返回地址等信息。棧的大小決定了方法調(diào)用的可達(dá)深度(遞歸多少層次,或嵌套調(diào)用多少層其他方法,-Xss參數(shù)可以設(shè)置虛擬機(jī)棧大?。5拇笮】梢允枪潭ǖ?,或者是動(dòng)態(tài)擴(kuò)展的。如果請(qǐng)求的棧深度大于最大可用深度,則拋出stackOver?owError;如果棧是可動(dòng)態(tài)擴(kuò)展的,但沒(méi)有內(nèi)存空間支持?jǐn)U展,則拋出OutofMemoryError。使用jclasslib工具可以查看class類(lèi)文件的結(jié)構(gòu)。下圖為棧幀結(jié)構(gòu)圖:3、本地方法棧與虛擬機(jī)棧作用相似。但它不是為Java方法服務(wù)的,而是本地方法(C語(yǔ)言)。由于規(guī)范對(duì)這塊沒(méi)有強(qiáng)制要求,不同虛擬機(jī)實(shí)現(xiàn)方法不同。線(xiàn)程共享區(qū)1、方法區(qū)線(xiàn)程共享的,用于存放被虛擬機(jī)加載的類(lèi)的元數(shù)據(jù)信息,如常量、靜態(tài)變量和即時(shí)編譯器編譯后的代碼。若要分代,算是永久代(老年代),以前類(lèi)大多“static”的,很少被卸載或收集,現(xiàn)回收廢棄常量和無(wú)用的類(lèi)。其中運(yùn)行時(shí)常量池存放編譯生成的各種常量。(如果hotspot虛擬機(jī)確定一個(gè)類(lèi)的定義信息不會(huì)被使用,也會(huì)將其回收?;厥盏幕緱l件至少有:所有該類(lèi)的實(shí)例被回收,而且裝載該類(lèi)的ClassLoader被回收)2、堆存放對(duì)象實(shí)例和數(shù)組,是垃圾回收的主要區(qū)域,分為新生代和老年代。剛創(chuàng)建的對(duì)象在新生代的Eden區(qū)中,經(jīng)過(guò)GC后進(jìn)入新生代的S0區(qū)中,再經(jīng)過(guò)GC進(jìn)入新生代的S1區(qū)中,15次GC后仍存在就進(jìn)入老年代。這是按照一種回收機(jī)制進(jìn)行劃分的,不是固定的。若堆的空間不夠?qū)嵗峙?,則OutOfMemoryError。EdenSurvivorSpaceOldGeneration即圖中的EdenFromSpace(s0)ToSpace(s1)存放新生的對(duì)象有兩個(gè),存放每次垃圾回收后存活的對(duì)象(s0+s1)TenuredGeneration即圖中的OldSpace主要存放應(yīng)用程序中生命周期長(zhǎng)的存活對(duì)象5、堆和棧的區(qū)別棧是運(yùn)行時(shí)單位,代表著邏輯,內(nèi)含基本數(shù)據(jù)類(lèi)型和堆中對(duì)象引用,所在區(qū)域連續(xù),沒(méi)有碎片;堆是存儲(chǔ)單位,代表著數(shù)據(jù),可被多個(gè)棧共享(包括成員中基本數(shù)據(jù)類(lèi)型、引用和引用對(duì)象),所在區(qū)域不連續(xù),會(huì)有碎片。1、功能不同棧內(nèi)存用來(lái)存儲(chǔ)局部變量和方法調(diào)用,而堆內(nèi)存用來(lái)存儲(chǔ)Java中的對(duì)象。無(wú)論是成員變量,局部變量,還是類(lèi)變量,它們指向的對(duì)象都存儲(chǔ)在堆內(nèi)存中。2、共享性不同棧內(nèi)存是線(xiàn)程私有的。堆內(nèi)存是所有線(xiàn)程共有的。3、異常錯(cuò)誤不同如果棧內(nèi)存或者堆內(nèi)存不足都會(huì)拋出異常。堆空間不足:java.lang.OutOfMemoryError。4、空間大小棧的空間大小遠(yuǎn)遠(yuǎn)小于堆的。6、什么時(shí)候會(huì)觸發(fā)FullGC除直接調(diào)用System.gc外,觸發(fā)FullGC執(zhí)行的情況有如下四種。舊生代空間不足舊生代空間只有在新生代對(duì)象轉(zhuǎn)入及創(chuàng)建為大對(duì)象、大數(shù)組時(shí)才會(huì)出現(xiàn)不足的現(xiàn)象,當(dāng)執(zhí)行FullGC后空間仍然不足,則拋出如下錯(cuò)誤:java.lang.OutOfMemoryError:Javaheapspace為避免以上兩種狀況引起的FullGC,調(diào)優(yōu)時(shí)應(yīng)盡量做到讓對(duì)象在MinorGC階段被回收、讓對(duì)象在新生代多存活一段時(shí)間及不要?jiǎng)?chuàng)建過(guò)大的對(duì)象及數(shù)組。PermanetGeneration空間滿(mǎn)PermanetGeneration中存放的為一些class的信息等,當(dāng)系統(tǒng)中要加載的類(lèi)、反射的類(lèi)和調(diào)用的方法較多時(shí),PermanetGeneration可能會(huì)被占滿(mǎn),在未配置為采用CMSGC的情況下會(huì)執(zhí)行FullGC。如果經(jīng)過(guò)FullGC仍然回收不了,那么JVM會(huì)拋出如下錯(cuò)誤信息:java.lang.OutOfMemoryError:PermGenspace為避免PermGen占滿(mǎn)造成FullGC現(xiàn)象,可采用的方法為增大PermGen空間或轉(zhuǎn)為使用CMSGC。CMSGC時(shí)出現(xiàn)promotionfailed和concurrentmodefailure對(duì)于采用CMS進(jìn)行舊生代GC的程序而言,尤其要注意GC日志中是否有promotionfailed和concurrentmodefailure兩種狀況,當(dāng)這兩種狀況出現(xiàn)時(shí)可能會(huì)觸發(fā)FullGC。promotionfailed是在進(jìn)行MinorGC時(shí),survivorspace放不下、對(duì)象只能放入舊生代,而此時(shí)舊生代也放不下造成的;concurrentmodefailure是在執(zhí)行CMSGC的過(guò)程中同時(shí)有對(duì)象要放入舊生代,而此時(shí)舊生代空間不足造成的。應(yīng)對(duì)措施為:增大survivorspace、舊生代空間或調(diào)低觸發(fā)并發(fā)GC的比率,但在JDK5.0+、6.0+的版本中有可能會(huì)由于JDK的bug29導(dǎo)致CMS在remark完畢后很久才觸發(fā)sweeping動(dòng)作。對(duì)于這種狀況,可通過(guò)設(shè)置-XX:CMSMaxAbortablePrecleanTime=5(單位為ms)來(lái)避免。統(tǒng)計(jì)得到的MinorGC晉升到舊生代的平均大小大于舊生代的剩余空間這是一個(gè)較為復(fù)雜的觸發(fā)情況,Hotspot為了避免由于新生代對(duì)象晉升到舊生代導(dǎo)致舊生代空間不足的現(xiàn)象,在進(jìn)行MinorGC時(shí),做了一個(gè)判斷,如果之前統(tǒng)計(jì)所得到的MinorGC晉升到舊生代的平均大小大于舊生代的剩余空間,那么就直接觸發(fā)FullGC。例如程序第一次觸發(fā)MinorGC后,有6MB的對(duì)象晉升到舊生代,那么當(dāng)下一次MinorGC發(fā)生時(shí),首先檢查舊生代的剩余空間是否大于6MB,如果小于6MB,則執(zhí)行FullGC。當(dāng)新生代采用PSGC時(shí),方式稍有不同,PSGC是在MinorGC后也會(huì)檢查,例如上面的例子中第一次MinorGC后,PSGC會(huì)檢查此時(shí)舊生代的剩余空間是否大于6MB,如小于,則觸發(fā)對(duì)舊生代的回收。除了以上4種狀況外,對(duì)于使用RMI來(lái)進(jìn)行RPC或管理的SunJDK應(yīng)用而言,默認(rèn)情況下會(huì)一小時(shí)執(zhí)行一次FullGC。可通過(guò)在啟動(dòng)時(shí)通過(guò)-java-Dsun.rmi.dgc.client.gcInterval=3600000來(lái)設(shè)置FullGC執(zhí)行的間隔時(shí)間或通過(guò)-XX:+DisableExplicitGC來(lái)禁止RMI調(diào)用System.gc。虛擬機(jī)?為什么Java被稱(chēng)作是“平臺(tái)無(wú)關(guān)的編程語(yǔ)言”?Java虛擬機(jī)是一個(gè)可以執(zhí)行Java字節(jié)碼的虛擬機(jī)進(jìn)程。Java源文件被編譯成能被Java虛擬機(jī)執(zhí)行的字節(jié)碼文件。Java被設(shè)計(jì)成允許應(yīng)用程序可以運(yùn)行在任意的平臺(tái),而不需要程序員為每一個(gè)平臺(tái)單獨(dú)重寫(xiě)或者是重新編譯。Java虛擬機(jī)讓這個(gè)變?yōu)榭赡埽驗(yàn)樗赖讓佑布脚_(tái)的指令長(zhǎng)度和其他特性。8、Java內(nèi)存結(jié)構(gòu)《24個(gè)Jvm面試題總結(jié)及答案》方法區(qū)和對(duì)是所有線(xiàn)程共享的內(nèi)存區(qū)域;而java棧、本地方法棧和程序員計(jì)數(shù)器是運(yùn)行是線(xiàn)程私有的內(nèi)存區(qū)域。Java堆(Heap),是Java虛擬機(jī)所管理的內(nèi)存中最大的一塊。Java堆是被所有線(xiàn)程共享的一塊內(nèi)存區(qū)域,在虛擬機(jī)啟動(dòng)時(shí)創(chuàng)建。此內(nèi)存區(qū)域的唯一目的就是存放對(duì)象實(shí)例,幾乎所有的對(duì)象實(shí)例都在這里分配內(nèi)存。方法區(qū)(MethodArea),方法區(qū)(MethodArea)與Java堆一樣,是各個(gè)線(xiàn)程共享的內(nèi)存區(qū)域,它用于存儲(chǔ)已被虛擬機(jī)加載的類(lèi)信息、常量、靜態(tài)變量、即時(shí)編譯器編譯后的代碼等數(shù)據(jù)。程序計(jì)數(shù)器(ProgramCounterRegister),程序計(jì)數(shù)器(ProgramCounterRegister)是一塊較小的內(nèi)存空間,它的作用可以看做是當(dāng)前線(xiàn)程所執(zhí)行的字節(jié)碼的行號(hào)指示器。JVM棧(JVMStacks),與程序計(jì)數(shù)器一樣,Java虛擬機(jī)棧(JavaVirtualMachineStacks)也是線(xiàn)程私有的,它的生命周期與線(xiàn)程相同。虛擬機(jī)棧描述的是Java方法執(zhí)行的內(nèi)存模型:每個(gè)方法被執(zhí)行的時(shí)候都會(huì)同時(shí)創(chuàng)建一個(gè)棧幀(StackFrame)用于存儲(chǔ)局部變量表、操作棧、動(dòng)態(tài)鏈接、方法出口等信息。每一個(gè)方法被調(diào)用直至執(zhí)行完成的過(guò)程,就對(duì)應(yīng)著一個(gè)棧幀在虛擬機(jī)棧中從入棧到出棧的過(guò)程。本地方法棧(NativeMethodStacks),本地方法棧(NativeMethodStacks)與虛擬機(jī)棧所發(fā)揮的作用是非常相似的,其區(qū)別不過(guò)是虛擬機(jī)棧為虛擬機(jī)執(zhí)行Java方法(也就是字節(jié)碼)服務(wù),而本地方法棧則是為虛擬機(jī)使用到的Native方法服務(wù)。9、對(duì)象分配規(guī)則對(duì)象優(yōu)先分配在Eden區(qū),如果Eden區(qū)沒(méi)有足夠的空間時(shí),虛擬機(jī)執(zhí)行一次MinorGC。大對(duì)象直接進(jìn)入老年代(大對(duì)象是指需要大量連續(xù)內(nèi)存空間的對(duì)象)。這樣做的目的是避免在Eden區(qū)和兩個(gè)Survivor區(qū)之間發(fā)生大量的內(nèi)存拷貝(新生代采用復(fù)制算法收集內(nèi)存)。長(zhǎng)期存活的對(duì)象進(jìn)入老年代。虛擬機(jī)為每個(gè)對(duì)象定義了一個(gè)年齡計(jì)數(shù)器,如果對(duì)象經(jīng)過(guò)了1次MinorGC那么對(duì)象會(huì)進(jìn)入Survivor區(qū),之后每經(jīng)過(guò)一次MinorGC那么對(duì)象的年齡加1,知道達(dá)到閥值對(duì)象進(jìn)入老年區(qū)。動(dòng)態(tài)判斷對(duì)象的年齡。如果Survivor區(qū)中相同年齡的所有對(duì)象大小的總和大于Survivor空間的一半,年齡大于或等于該年齡的對(duì)象可以直接進(jìn)入老年代。空間分配擔(dān)保。每次進(jìn)行MinorGC時(shí),JVM會(huì)計(jì)算Survivor區(qū)移至老年區(qū)的對(duì)象的平均大小,如果這個(gè)值大于老年區(qū)的剩余值大小則進(jìn)行一次FullGC,如果小于檢查HandlePromotionFailure設(shè)置,如果true則只進(jìn)行MonitorGC,如果false則進(jìn)行FullGC。10、描述一下JVM加載class文件的原理機(jī)制?JVM中類(lèi)的裝載是由類(lèi)加載器(ClassLoader)和它的子類(lèi)來(lái)實(shí)現(xiàn)的,Java中的類(lèi)加載器是一個(gè)重要的Java運(yùn)行時(shí)系統(tǒng)組件,它負(fù)責(zé)在運(yùn)行時(shí)查找和裝入類(lèi)文件中的類(lèi)。由于Java的跨平臺(tái)性,經(jīng)過(guò)編譯的Java源程序并不是一個(gè)可執(zhí)行程序,而是一個(gè)或多個(gè)類(lèi)文件。當(dāng)Java程序需要使用某個(gè)類(lèi)時(shí),JVM會(huì)確保這個(gè)類(lèi)已經(jīng)被加載、連接(驗(yàn)證、準(zhǔn)備和解析)和初始化。類(lèi)的加載是指把類(lèi)的.class文件中的數(shù)據(jù)讀入到內(nèi)存中,通常是創(chuàng)建一個(gè)字節(jié)數(shù)組讀入.class文件,然后產(chǎn)生與所加載類(lèi)對(duì)應(yīng)的Class對(duì)象。加載完成后,Class對(duì)象還不完整,所以此時(shí)的類(lèi)還不可用。當(dāng)類(lèi)被加載后就進(jìn)入連接階段,這一階段包括驗(yàn)證、準(zhǔn)備(為靜態(tài)變量分配內(nèi)存并設(shè)置默認(rèn)的初始值)和解析(將符號(hào)引用替換為直接引用)三個(gè)步驟。最后JVM對(duì)類(lèi)進(jìn)行初始化,包括:1)如果類(lèi)存在直接的父類(lèi)并且這個(gè)類(lèi)還沒(méi)有被初始化,那么就先初始化父類(lèi);2)如果類(lèi)中存在初始化語(yǔ)句,就依次執(zhí)行這些初始化語(yǔ)句。類(lèi)的加載是由類(lèi)加載器完成的,類(lèi)加載器包括:根加載器(BootStrap)、擴(kuò)展加載器(Extension)、系統(tǒng)加載器(System)和用戶(hù)自定義類(lèi)加載器(java.lang.ClassLoader的子類(lèi))。從Java2(JDK1.2)開(kāi)始,類(lèi)加載過(guò)程采取了父親委托機(jī)制(PDM)。PDM更好的保證了Java平臺(tái)的安全性,在該機(jī)制中,JVM自帶的Bootstrap是根加載器,其他的加載器都有且僅有一個(gè)父類(lèi)加載器。類(lèi)的加載首先請(qǐng)求父類(lèi)加載器加載,父類(lèi)加載器無(wú)能為力時(shí)才由其子類(lèi)加載器自行加載。JVM不會(huì)向Java程序提供對(duì)Bootstrap的引用。下面是關(guān)于幾個(gè)類(lèi)加載器的說(shuō)明:Bootstrap:一般用本地代碼實(shí)現(xiàn),負(fù)責(zé)加載JVM基礎(chǔ)核心類(lèi)庫(kù)(rt.jar);Extension:從java.ext.dirs系統(tǒng)屬性所指定的目錄中加載類(lèi)庫(kù),它的父加載器是Bootstrap;System:又叫應(yīng)用類(lèi)加載器,其父類(lèi)是Extension。它是應(yīng)用最廣泛的類(lèi)加載器。它從環(huán)境變量classpath或者系統(tǒng)屬性java.class.path所指定的目錄中記載類(lèi),是用戶(hù)自定義加載器的默認(rèn)父加載器。11、Java對(duì)象創(chuàng)建過(guò)程JVM遇到一條新建對(duì)象的指令時(shí)首先去檢查這個(gè)指令的參數(shù)是否能在常量池中定義到一個(gè)類(lèi)的符號(hào)引用。然后加載這個(gè)類(lèi)(類(lèi)加載過(guò)程在后邊講)為對(duì)象分配內(nèi)存。一種辦法“指針碰撞”、一種辦法“空閑列表”,最終常用的辦法“本地線(xiàn)程緩沖分配(TLAB)”將除對(duì)象頭外的對(duì)象內(nèi)存空間初始化為0對(duì)對(duì)象頭進(jìn)行必要設(shè)置12、類(lèi)的生命周期類(lèi)的生命周期包括這幾個(gè)部分,加載、連接、初始化、使用和卸載,其中前三部是類(lèi)的加載的過(guò)程,如下圖;《24個(gè)Jvm面試題總結(jié)及答案》加載,查找并加載類(lèi)的二進(jìn)制數(shù)據(jù),在Java堆中也創(chuàng)建一個(gè)java.lang.Class類(lèi)的對(duì)象連接,連接又包含三塊內(nèi)容:驗(yàn)證、準(zhǔn)備、初始化。1)驗(yàn)證,文件格式、元數(shù)據(jù)、字節(jié)碼、符號(hào)引用驗(yàn)證;2)準(zhǔn)備,為類(lèi)的靜態(tài)變量分配內(nèi)存,并將其初始化為默認(rèn)值;3)解析,把類(lèi)中的符號(hào)引用轉(zhuǎn)換為直接引用初始化,為類(lèi)的靜態(tài)變量賦予正確的初始值使用,new出對(duì)象程序中使用卸載,執(zhí)行垃圾回收13、簡(jiǎn)述Java的對(duì)象結(jié)構(gòu)Java對(duì)象由三個(gè)部分組成:對(duì)象頭、實(shí)例數(shù)據(jù)、對(duì)齊填充。對(duì)象頭由兩部分組成,第一部分存儲(chǔ)對(duì)象自身的運(yùn)行時(shí)數(shù)據(jù):哈希碼、GC分代年齡、鎖標(biāo)識(shí)狀態(tài)、線(xiàn)程持有的鎖、偏向線(xiàn)程ID(一般占32/64bit)。第二部分是指針類(lèi)型,指向?qū)ο蟮念?lèi)元數(shù)據(jù)類(lèi)型(即對(duì)象代表哪個(gè)類(lèi))。如果是數(shù)組對(duì)象,則對(duì)象頭中還有一部分用來(lái)記錄數(shù)組長(zhǎng)度。實(shí)例數(shù)據(jù)用來(lái)存儲(chǔ)對(duì)象真正的有效信息(包括父類(lèi)繼承下來(lái)的和自己定義的)對(duì)齊填充:JVM要求對(duì)象起始地址必須是8字節(jié)的整數(shù)倍(8字節(jié)對(duì)齊)14、如何判斷對(duì)象可以被回收?判斷對(duì)象是否存活一般有兩種方式:引用計(jì)數(shù):每個(gè)對(duì)象有一個(gè)引用計(jì)數(shù)屬性,新增一個(gè)引用時(shí)計(jì)數(shù)加1,引用釋放時(shí)計(jì)數(shù)減1,計(jì)數(shù)為0時(shí)可以回收。此方法簡(jiǎn)單,無(wú)法解決對(duì)象相互循環(huán)引用的問(wèn)題。可達(dá)性分析(ReachabilityAnalysis):從GCRoots開(kāi)始向下搜索,搜索所走過(guò)的路徑稱(chēng)為引用鏈。當(dāng)一個(gè)對(duì)象到GCRoots沒(méi)有任何引用鏈相連時(shí),則證明此對(duì)象是不可用的,不可達(dá)對(duì)象。15、JVM的永久代中會(huì)發(fā)生垃圾回收么?垃圾回收不會(huì)發(fā)生在永久代,如果永久代滿(mǎn)了或者是超過(guò)了臨界值,會(huì)觸發(fā)完全垃圾回收(FullGC)。如果你仔細(xì)查看垃圾收集器的輸出信息,就會(huì)發(fā)現(xiàn)永久代也是被回收的。這就是為什么正確的永久代大小對(duì)避免FullGC是非常重要的原因。請(qǐng)參考下Java8:從永久代到元數(shù)據(jù)區(qū)(注:Java8中已經(jīng)移除了永久代,新加了一個(gè)叫做元數(shù)據(jù)區(qū)的native內(nèi)存區(qū))16、垃圾收集算法GC最基礎(chǔ)的算法有三種:標(biāo)記-清除算法、復(fù)制算法、標(biāo)記-壓縮算法,我們常用的垃圾回收器一般都采用分代收集算法。標(biāo)記-清除算法,“標(biāo)記-清除”(Mark-Sweep)算法,如它的名字一樣,算法分為“標(biāo)記”和“清除”兩個(gè)階段:首先標(biāo)記出所有需要回收的對(duì)象,在標(biāo)記完成后統(tǒng)一回收掉所有被標(biāo)記的對(duì)象。復(fù)制算法,“復(fù)制”(Copying)的收集算法,它將可用內(nèi)存按容量劃分為大小相等的兩塊,每次只使用其中的一塊。當(dāng)這一塊的內(nèi)存用完了,就將還存活著的對(duì)象復(fù)制到另外一塊上面,然后再把已使用過(guò)的內(nèi)存空間一次清理掉。標(biāo)記-壓縮算法,標(biāo)記過(guò)程仍然與“標(biāo)記-清除”算法一樣,但后續(xù)步驟不是直接對(duì)可回收對(duì)象進(jìn)行清理,而是讓所有存活的對(duì)象都向一端移動(dòng),然后直接清理掉端邊界以外的內(nèi)存分代收集算法,“分代收集”(GenerationalCollection)算法,把Java堆分為新生代和老年代,這樣就可以根據(jù)各個(gè)年代的特點(diǎn)采用最適當(dāng)?shù)氖占惴ā?7、調(diào)優(yōu)命令有哪些?SunJDK監(jiān)控和故障處理命令有jpsjstatjmapjhatjstackjinfojps,JVMProcessStatusTool,顯示指定系統(tǒng)內(nèi)所有的HotSpot虛擬機(jī)進(jìn)程。jstat,JVMstatisticsMonitoring是用于監(jiān)視虛擬機(jī)運(yùn)行時(shí)狀態(tài)信息的命令,它可以顯示出虛擬機(jī)進(jìn)程中的類(lèi)裝載、內(nèi)存、垃圾收集、JIT編譯等運(yùn)行數(shù)據(jù)。jmap,JVMMemoryMap命令用于生成heapdump文件jhat,JVMHeapAnalysisTool命令是與jmap搭配使用,用來(lái)分析jmap生成的dump,jhat內(nèi)置了一個(gè)微型的/HTML服務(wù)器,生成dump的分析結(jié)果后,可以在瀏覽器中查看jstack,用于生成java虛擬機(jī)當(dāng)前時(shí)刻的線(xiàn)程快照。jinfo,JVMCon?gurationinfo這個(gè)命令作用是實(shí)時(shí)查看和調(diào)整虛擬機(jī)運(yùn)行參數(shù)。18、調(diào)優(yōu)工具常用調(diào)優(yōu)工具分為兩類(lèi),jdk自帶監(jiān)控工具:jconsole和jvisualvm,第三方有:MAT(MemoryAnalyzerTool)、GChisto。jconsole,JavaMonitoringandManagementConsole是從java5開(kāi)始,在JDK中自帶的java監(jiān)控和管理控制臺(tái),用于對(duì)JVM中內(nèi)存,線(xiàn)程和類(lèi)等的監(jiān)控jvisualvm,jdk自帶全能工具,可以分析內(nèi)存快照、線(xiàn)程快照;監(jiān)控內(nèi)存變化、GC變化等。MAT,MemoryAnalyzerTool,一個(gè)基于Eclipse的內(nèi)存分析工具,是一個(gè)快速、功能豐富的Javaheap分析工具,它可以幫助我們查找內(nèi)存泄漏和減少內(nèi)存消耗GChisto,一款專(zhuān)業(yè)分析gc日志的工具19、MinorGC與FullGC分別在什么時(shí)候發(fā)生?新生代內(nèi)存不夠用時(shí)候發(fā)生MGC也叫YGC,JVM內(nèi)存不夠的時(shí)候發(fā)生FGC20、你知道哪些JVM性能調(diào)優(yōu)設(shè)定堆內(nèi)存大小-Xmx:堆內(nèi)存最大限制。設(shè)定新生代大小。新生代不宜太小,否則會(huì)有大量對(duì)象涌入老年代-XX:NewSize:新生代大小-XX:NewRatio新生代和老生代占比-XX:SurvivorRatio:伊甸園空間和幸存者空間的占比設(shè)定垃圾回收器年輕代用-XX:+UseParNewGC年老代用-XX:+UseConcMarkSweepGC21、JVM內(nèi)存分哪幾個(gè)區(qū),每個(gè)區(qū)的作用是什么?Java虛擬機(jī)主要分為以下一個(gè)區(qū):方法區(qū):有時(shí)候也成為永久代,在該區(qū)內(nèi)很少發(fā)生垃圾回收,但是并不代表不發(fā)生GC,在這里進(jìn)行的GC主要是對(duì)方法區(qū)里的常量池和對(duì)類(lèi)型的卸載方法區(qū)主要用來(lái)存儲(chǔ)已被虛擬機(jī)加載的類(lèi)的信息、常量、靜態(tài)變量和即時(shí)編譯器編譯后的代碼等數(shù)據(jù)。該區(qū)域是被線(xiàn)程共享的。方法區(qū)里有一個(gè)運(yùn)行時(shí)常量池,用于存放靜態(tài)編譯產(chǎn)生的字面量和符號(hào)引用。該常量池具有動(dòng)態(tài)性,也就是說(shuō)常量并不一定是編譯時(shí)確定,運(yùn)行時(shí)生成的常量也會(huì)存在這個(gè)常量池中。虛擬機(jī)棧:虛擬機(jī)棧也就是我們平常所稱(chēng)的棧內(nèi)存,它

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶(hù)所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶(hù)上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶(hù)上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶(hù)因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論