導航:首頁 > 源碼編譯 > java8gc演算法

java8gc演算法

發布時間:2023-05-09 15:06:23

Ⅰ 在java中如何主動的去釋放無用對象,從而使得系統GC可以盡早釋放內存在編程上需要注意些什麼

1、與C語言相比,垃圾回收器是JAVA的一大優勢。其功能在於自動釋放舉余衫違背佔用的內存,但何時去釋放有其自身的演算法,不支持使用者直接釋放內存。
2、使用者所能做的只是使用System.gc()通知JAVA垃圾回收器在「合適」的時間逐個使用Object.finalize()清除未為程序引用的各個對象。
3、使用著調用Object的finalize()方法不會啟動任何作用,只能是重寫該方法執行寫對象銷毀前應做的操作,如關閉IO等。
4、使用者還可以做到的就是指定那些對象正腔佔用的毀鍵內存會被釋放,方法就是將對象的值賦為NULL。
5、編程用使用者應做的就是提高對象的復用性,盡量少的聲明對象。

Ⅱ Java垃圾回收:GC在什麼時候對什麼做了什麼

GC在什麼時候對什麼做了什麼?
要回答這個問題,先了解下GC的發展史、jvm運行時數據區的劃分、jvm內存分配策略、jvm垃圾收集演算法等知識。
先說下jvm運行時數據的劃分,粗暴的分可以分為堆區(Heap)和棧區(Stack),但jvm的分法實際上比這復雜得多,大概分為下面幾塊:
1、程序計數器(Program Conuter Register)
程序計數器是一塊較小的內存空間,它是當前線程執行位元組碼的行號指示器,位元組碼解釋工作器就是通過改變這個計數器的值來選取下一條需要執行的指令。它是線程私有的內存,也是唯一一個沒有OOM異常的區域。
2、Java虛擬機棧區(Java Virtual Machine Stacks)
也就是通常所說的棧區,它描述的是Java方法執行的內存模型,每個方法被執行的時候都創建一個棧幀(Stack Frame),用於存儲局部變數表、操作數棧、動態鏈接、方法出口等。每個方法被調用到完成,相當於一個棧幀在虛擬機棧中從入棧到出棧的過程。此區域也是線程私有的內存,可能拋出兩種異常:如果線程請求的棧深度大於虛擬機允許的深度將拋出StackOverflowError;如果虛擬機棧可以動態的擴展,擴展到無法動態的申請到足夠的內存時會拋出OOM異常。
3、本地方法棧(Native Method Stacks)
本地方法棧與虛擬機棧發揮的作用非常相似,區別就是虛擬機棧為虛擬機執行Java方法,本地方法棧則是為虛擬機使用到的Native方法服務。
4、堆區(Heap)
所有對象實例和數組都在堆區上分配,堆區是GC主要管理的區域。堆區還可以細分為新生代、老年代,新生代還分為一個Eden區和兩個Survivor區。此塊內存為所有線程共享區域,當堆中沒有足夠內存完成實例分配時會拋出OOM異常。
5、方法區(Method Area)
方法區也是所有線程共享區,用於存儲已被虛擬機載入的類信息、常量、靜態變數、即時編譯後的代碼等數據。GC在這個區域很少出現,這個區域內存回收的目標主要是對常量池的回收和類型的卸載,回收的內存比較少,所以也有稱這個區域為永久代(Permanent Generation)的。當方法區無法滿足內存分配時拋出OOM異常。
6、運行時常量池(Runtime Constant Pool)
運行時常量池是方法區的一部分,用於存放編譯期生成的各種字面量和符號引用。

垃圾收集(Garbage Collection)並不是Java獨有的,最早是出現在Lisp語言中,它做的事就是自動管理內存,也就是下面三個問題:
1、什麼時候回收
2、哪些內存需要回收
3、如何回收

1、什麼時候回收?
上面說到GC經常發生的區域是堆區,堆區還可以細分為新生代、老年代,新生代還分為一個Eden區和兩個Survivor區。
1.1 對象優先在Eden中分配,當Eden中沒有足夠空間時,虛擬機將發生一次Minor GC,因為Java大多數對象都是朝生夕滅,所以Minor GC非常頻繁,而且速度也很快;
1.2 Full GC,發生在老年代的GC,當老年代沒有足夠的空間時即發生Full GC,發生Full GC一般都會有一次Minor GC。大對象直接進入老年代,如很長的字元串數組,虛擬機提供一個-XX:PretenureSizeThreadhold參數,令大於這個參數值的對象直接在老年代中分配,避免在Eden區和兩個Survivor區發生大量的內存拷貝;
1.3 發生Minor GC時,虛擬機會檢測之前每次晉升到老年代的平均大小是否大於老年代的剩餘空間大小,如果大於,則進行一次Full GC,如果小於,則查看HandlePromotionFailure設置是否允許擔保失敗,如果允許,那隻會進行一次Minor GC,如果不允許,則改為進行一次Full GC。

2、哪些內存需要回收
jvm對不可用的對象進行回收,哪些對象是可用的,哪些是不可用的?Java並不是採用引用計數演算法來判定對象是否可用,而是採用根搜索演算法(GC Root Tracing),當一個對象到GC Roots沒有任何引用相連接,用圖論的來說就是從GC Roots到這個對象不可達,則證明此對象是不可用的,說明此對象可以被GC。對於這些不可達對象,也不是一下子就被GC,而是至少要經歷兩次標記過程:如果對象在進行根搜索演算法後發現沒有與GC Roots相連接的引用鏈,那它將會第一次標記並且進行一次篩選,篩選條件是此對象有沒有必要執行finalize()方法,當對象沒有覆蓋finalize()方法或者finalize()方法已經被虛擬機調用執行過一次,這兩種情況都被視為沒有必要執行finalize()方法,對於沒有必要執行finalize()方法的將會被GC,對於有必要有必要執行的,對象在finalize()方法中可能會自救,也就是重新與引用鏈上的任何一個對象建立關聯即可。

3、如何回收
選擇不同的垃圾收集器,所使用的收集演算法也不同。
在新生代中,每次垃圾收集都發現有大批對象死去,只有少量存活,則使用復制演算法,新生代內存被分為一個較大的Eden區和兩個較小的Survivor區,每次只使用Eden區和一個Survivor區,當回收時將Eden區和Survivor還存活著的對象一次性的拷貝到另一個Survivor區上,最後清理掉Eden區和剛才使用過的Survivor區,Eden和Survivor的默認比例是8:1,可以使用-XX:SurvivorRatio來設置該比例。
而老年代中對象存活率高,沒有額外的空間對它進行分配擔保,必須使用「標記-清理」或「標記-整理」演算法。

Ⅲ 深入理解GC垃圾回收機制

在我們程序運行中會不斷創建新的對象,這些對象會存儲在內存中,如果沒有一套機制來回收這些內存,那麼被佔用的內存會越來越多,可用內存會越來越少,直至內存被消耗完。於是就有了一套垃圾回收機制來做這件維持系統平衡的任務。

1.確保被引用對象的內存不被錯誤的回收
2.回收不再被引用的對象的內存空間

給對象中添加一個引用計數器,每當有一個地方引用它時,計數器值就加1;當引用失效時, 計數器值就減1;任何時刻計數器為0的對象就是不可能再被使用的。

優點:引用計數收集器可以很快地執行,交織在程序的運行之中。
缺點:很難處理循環引用,比如上圖中相互引用的兩個對象,計數器不為0,則無法釋放,但是這樣的對象存在是沒有意義的,空占內存了。

引用計數法處理不了的相互引用的問題,那麼就有了可達性分析來解決了這個問題。

從GC Roots作為起點,向下搜索它們引用的對象,可以生成一棵引用樹,樹的節點視為可達對象,反之最終不能與GC Roots有引用關系的視為不可達,不可達對象即為垃圾回收對象。

我自己的理解是,皇室家族每過一段時間,會進行皇室成員排查,從皇室第一代開始往下找血緣關系的後代,如果你跟第一代皇室沒有關系,那麼你就會被剔除皇室家族。

1.虛擬機棧中引用的對象(正在運行的方法使用到的變數、參數等)
2.方法區中類靜態屬性引用的對象(static關鍵字聲明的欄位)
3.方法區中常量引用的對象,(也就是final關鍵字聲明的欄位)
4.本地方法棧中引用的對象(native方法)

1.顯示地賦予某個對象為null,切斷可達性

在main方法中創建objectA、objectB兩個局部變數,而且相互引用。相互引用直接調System.gc()是回收不了的。而將兩者都置為null,切斷相互引用,切斷了可達性,與GCRoots無引用,那麼這兩個對象就會被回收調。

2.將對象的引用指向另一個對象

這里將one的引用也指向了two引用指向的對象,那麼one原本指向的對象就失去了GCRoots引用,這里就判斷該對象可被回收。

3.局部對象的使用

當方法執行完,局部變數object對象會被判定為可回收對象。

4.只有軟、弱、虛引用與之關聯
new出來的對象被強引用了,就需要去掉強引用,改為弱引用。被弱引用之後,需要置空來幹掉強引用,達到隨時可回收的效果。

只被軟引用的對象在內存不足的情況,可能會被GC回收掉。

只被弱引用持有的對象,隨時都可能被GC回收,該對象就為可回收對象。

是不是被判定為了可回收對象,就一定會被回收了呢。其實Ojbect類中還有一個finalize方法。這個方法是對象在被GC回收之前會被觸發的方法。

該方法翻譯過來就是:當垃圾回收確定不再有對該對象的引用時,由垃圾回收器在對象上調用。子類重寫finalize方法以處置系統資源或執行其他清除。說人話就是對象死前會給你一個迴光返照,讓你清醒一下,想干什麼就干什麼,甚至可以把自己救活。我們可以通過重寫finalize方法,來讓對象復活一下。

示例:

執行的結果:

這里我們重寫FinalizeGC類的finalize方法, 使用FinalizeGC.instance = this語句,讓對象又有了引用,不再被判定為可回收對象,這里就活了。然後再置空再回收一下,這個對象就死了,沒有再被救活了。所以finalize方法只能被執行一次,沒有再次被救活的機會。

在JDK1.8版本廢棄了永久代,替代的是元空間(MetaSpace),元空間與永久代上類似,都是方法區的實現,他們最大區別是:元空間並不在JVM中,而是使用本地內存。
元空間有注意有兩個參數:

MetaspaceSize :初始化元空間大小,控制發生GC閾值
MaxMetaspaceSize : 限制元空間大小上限,防止異常佔用過多物理內存
為什麼移除永久代?
移除永久代原因:為融合HotSpot JVM與JRockit VM(新JVM技術)而做出的改變,因為JRockit沒有永久代。
有了元空間就不再會出現永久代OOM問題了!

1.Generational Collection(分代收集)演算法
分代收集演算法是GC垃圾回收演算法的總綱領。現在主流的Java虛擬機的垃圾收集器都採用分代收集演算法。Java 堆區基於分代的概念,分為新生代(Young Generation)和老年代(Tenured Generation),其中新生代再細分為Eden空間、From Survivor空間和To Survivor空間。 (Survivor:倖存者)

分代收集演算法會結合不同的收集演算法來處理不同的空間,因此在學習分代收集演算法之前我們首先要了解Java堆區的空間劃分。Java堆區的空間劃分在Java虛擬機中,各種對象的生命周期會有著較大的差別。因此,應該對不同生命周期的對象採取不同的收集策略,根據生命周期長短將它們分別放到不同的區域,並在不同的區域採用不同的收集演算法,這就是分代的概念。

當執行一次GC Collection時,Eden空間的存活對象會被復制到To Survivor空間,並且之前經過一次GC Collection並在From Survivor空間存活的仍年輕的對象也會復制到To Survivor空間。

對象進入到From和To區之後,對象的GC分代年齡ege的屬性,每經過GC回收存活下來,ege就會+1,當ege達到15了,對象就會晉級到老年代。

2.Mark-Sweep(標記-清除)演算法
標記清除:標記階段的任務是標記出所有需要被回收的對象,清除階段就是回收被標記的對象所佔用的空間。標記-清除演算法主要是運用在Eden區,該區對象很容易被回收掉,回收率很高。

3.Copying(復制)演算法
復制演算法的使用在From區和To區,每次只使用其中的一塊。當這一塊的內存用完了,就將還存活著的對象復制到另外一塊上面,然後再把已使用的內存空間一次清理掉,這樣一來就不容易出現內存碎片的問題。

缺點:可使用內存縮減為一半大小。

那麼復制演算法使可使用內存大小會減半,設計上是怎麼解決這個問題的呢。就是給From和To區劃分盡可能小的區域。經過大數據統計之後,對象在第一次使用過後,絕大多數都會被回收,所以能進入第一次復制演算法的對象只佔10%。那麼設計上,Eden、From、To區的比例是8:1:1,絕大多數對象會分配到Eden區,這樣就解決了復制演算法縮減可用內存帶來的問題。

4.Mark-Compact (標記—整理)演算法
在新生代中可以使用復制演算法,但是在老年代就不能選擇復制演算法了,因為老年代的對象存活率會較高,這樣會有較多的復制操作,導致效率變低。標記—清除演算法可以應用在老年代中,但是它效率不高,在內存回收後容易產生大量內存碎片。因此就出現了一種標記—整理演算法,與標記—清除演算法不同的是,在標記可回收的對象後將所有存活的對象壓縮到內存的一端,使它們緊湊地排列在一起,然後對邊界以外的內存進行回收,回收後,已用和未用的內存都各自一邊。

垃圾收集演算法是內存回收的方法論,那麼垃圾收集器就是內存回收的具體實現:
Serial 收集器(復制演算法): 新生代單線程收集器,標記和清理都是單線程,
優點是簡單高效;
Serial Old 收集器 (標記-整理演算法): 老年代單線程收集器,Serial 收集器
的老年代版本;
ParNew 收集器 (復制演算法): 新生代收並行集器,實際上是 Serial 收集器
的多線程版本,在多核 CPU 環境下有著比 Serial 更好的表現;
CMS(Concurrent Mark Sweep)收集器(標記-清除演算法): 老年代並行
收集器,以獲取最短回收停頓時間為目標的收集器,具有高並發、低停頓
的特點,追求最短 GC 回收停頓時間。

Ⅳ 各種gc觸發條件統計

Minor GC:當Eden區所剩空間,不枯擾敏滿足分配需求時,就會觸發Minor GC。

題外話:在segmentfault上看到過一個問題,我認為非常有意思,# JAVA垃圾回收:HandlePromotionFailure不打開的話,是不是就永不會發生minor gc?
如果在JDK1.6之前,我認為是這樣的。所以JDK在1.7及以後,更改了邏輯,默認是一定打開的,
JDK6 Hotpot擔保機制源碼: http://hg.openjdk.java.net/jdk6/jdk6/hotspot/file/b69c41ea1764/src/share/vm/memory/tenuredGeneration.cpp#l422

JDK7 Hotpot擔保機制源碼: http://hg.openjdk.java.net/jdk7/jdk7/hotspot/file/9b0ca45cd756/src/share/vm/memory/tenuredGeneration.cpp#l431

JDK8 Hotpot擔保機制源碼: http://hg.openjdk.java.net/jdk8/jdk8/hotspot/file/87ee5ee27509/src/share/vm/memory/tenuredGeneration.cpp#l289

對比可以看出,從JDK7以後,就不再使用 younger_handles_promotion_failure 變數李此,並且邏輯默認是沒枝打開的。

其實取這個名字不是很合適,只是為了突出是CMS的GC。因為CMS是老年代回收器,所以對應的GC應該是Old GC。CMS GC的監控條件是老年代的使用率,對應的配置是

G1回收器獨有的回收方式

Major GC和Full GC的區別是什麼?觸發條件呢?

Ⅳ JAVA和C++有什麼區別

java的三大特性是封裝、繼承和多態。**
總結如下:
1、 JAVA的應用在高層,C++在中間件和底層
2、 JAVA離不開業務邏輯,而C++可以離開業務為JAVA們服務
3、 java語言給開發人員提供了更為簡潔的語法;取消了指針帶來更高的代碼質量;完全面向對象,獨特的運行機制是其具有天然的可移植性。
4、 java 是運行在JVM上的,之所以說它的可移植性強,是因為jvm可以安裝到任何的系統
5、 c++不是不能在其他系統運行,而是c++在不同的系統上運行,需要不同的編碼(這一點不如java,只編寫一次代碼,到處運行)。java程序一般都是生成位元組碼,在JVM裡面運行得到結果。
6、 java 在web 應用上具有c++ 無可比擬的優勢
7、 java在桌面程序上不如c++實用,C++可以直接編譯成exe文件,指針是c++的優勢,可以直接對內存的操作,但同時具有危險性 。(操作內存的確是一項非常危險的事情,一旦指針指向的位置發生錯誤,或者誤刪除了內存中某個地址單元存放的重要數據,後果是可想而知的)。
8、 垃圾回收機制的區別。c++用析構函數回收垃圾,java自動回收(GC演算法),寫C和C++程序時一定要注意內存的申請和釋放。
9、 java 豐富判辯余的插件是java 發展如此迅速的原因
10、 java 很大的沿襲了c++的一些實用結構
11、 對於底層程序的編程以及控制方面的編程,c++很靈活,因為有句柄的存在。
Java並不僅僅是C++語言的一個變種,它們在某些本質問題上有根本的不同:
(1)Java比C++程序可靠性更高。有人曾估計每50行C++程序中至少有一個BUG。姑且不去討論這個數字是否誇張,但是任何一個C++程序員都不得不承認C++語言在提供強大的功能的同時也提高了程序含BUG的可能性。Java語言通過改變語言的特性大大提掘滾高了程序的可靠性。
(2)Java語言不需要程序對內存進行分配和回收。Java丟棄了C++ 中很少使用的、很難理解的、令人迷惑的那些特性,如操作符重載、多繼承、自動的強制類型轉換。特別地,Java語言不使用指針,並提供了自動的廢料收集,在Java語言中,內存的分配和灶緩回收都是自動進行的,程序員無須考慮內存碎片的問題。
(3)Java語言中沒有指針的概念,引入了真正的數組。不同於C++中利用指針實現的「偽數組」,Java引入了真正的數組,同時將容易造成麻煩的指針從語言中去掉,這將有利於防止在c++程序中常見的因為數組操作越界等指針操作而對系統數據進行非法讀寫帶來的不安全問題。
(4)Java用介面(Interface)技術取代C++程序中的多繼承性。介面與多繼承有同樣的功能,但是省卻了多繼承在實現和維護上的復雜性。
Java和C++各有各的優勢,無需爭論那種語言好,哪種語言不好,能夠存在就一定有它的優勢,只要你決定了要學編程就扎實的學好,編程語言都是相同的,學會一種,其他的學起來就很容易了。

Ⅵ java8和java11的gc處理

Java垃圾回收概況_ava_C(Garbage Collection,垃圾回收)機制,是Java與C++/C的主要區別之一,作為Java開發者。
當前使用量最大的_ava版本是 8,所以測試者用_ava?8與_ava?11進行對比測試。

Ⅶ java常見gc演算法有哪些

1:標記—清除 Mark-Sweep
過程:標記可回收對象,進行清除
缺點:標記和清除效率低,清除後會產生內存碎片
2:復制演算法
過程:將內存劃分為相等的兩塊,將存活的對象復制到另一塊內存,把已經使用的內存清理掉
缺點:使用的內存變為了原來的一半
進化:將一塊內存按8:1的比例分為一塊Eden區(80%)和兩塊Survivor區(10%)
每次使用Eden和一塊Survivor,回收時,將存活的對象一次性復制到另一塊Survivor上,如果另一塊Survivor空間不足,則使用分配擔保機制存入老年代
3:標記—整理 Mark—Compact
過程:所有存活的對象向一端移動,然後清除掉邊界以外的內存

4:分代收集演算法
過程:將堆分為新生代和老年代,根據區域特點選用不同的收集演算法,如果新生代朝生夕死,則採用復制演算法,老年代採用標記清除,或標記整理
面試的話說出來這四種足夠了

Ⅷ Java編程常見面試題目,要求正確答案

第一,談談final, finally, finalize的區別。

final?修飾符(關鍵字)如果一個類被聲明為final,意味著它不能再派生出新的子類,不能作為父類被繼承。因此一個類不能既被聲明為 abstract的,又被聲明為final的。將變數或方法聲明為final,可以保證它們在使用中不被改變。被聲明為final的變數必須在聲明時給定初值,而在以後的引用中只能讀取,不可修改。被聲明為final的方法也同樣只能使用,不能重載finally?再異常處理時提供 finally 塊來執行任何清除操作。如果拋出一個異常,那麼相匹配的 catch 子句就會執行,然後控制就會進入 finally 塊(如果有的話)。

finalize?方法名。Java 技術允許使用 finalize() 方法在垃圾收集器將對象從內存中清除出去之前做必要的清理工作。這個方法是由垃圾收集器在確定這個對象沒有被引用時對這個對象調用的。它是在 Object 類中定義的,因此所有的類都繼承了它。子類覆蓋 finalize() 方法以整理系統資源或者執行其他清理工作。finalize() 方法是在垃圾收集器刪除對象之前對這個對象調用的。

第二,Anonymous Inner Class (匿名內部類) 是否可以extends(繼承)其它類,是否可以implements(實現)interface(介面)?

匿名的內部類是沒有名字的內部類。不能extends(繼承) 其它類,但一個內部類可以作為一個介面,由另一個內部類實現。

第三,Static Nested Class 和 Inner Class的不同,說得越多越好(面試題有的很籠統)。

Nested Class (一般是C++的說法),Inner Class (一般是JAVA的說法)。Java內部類與C++嵌套類最大的不同就在於是否有指向外部的引用上。具體可見http: //www.frontfree.net/articles/services/view.ASP?id=704&page=1

註: 靜態內部類(Inner Class)意味著1創建一個static內部類的對象,不需要一個外部類對象,2不能從一個static內部類的一個對象訪問一個外部類對象

第四,&和&&的區別。

&是位運算符。&&是布爾邏輯運算符。

第五,HashMap和Hashtable的區別。

都屬於Map介面的類,實現了將惟一鍵映射到特定的值上。

HashMap 類沒有分類或者排序。它允許一個 null 鍵和多個 null 值。

Hashtable 類似於 HashMap,但是不允許 null 鍵和 null 值。它也比 HashMap 慢,因為它是同步的。

第六,Collection 和 Collections的區別。

Collections是個java.util下的類,它包含有各種有關集合操作的靜態方法。
Collection是個java.util下的介面,它是各種集合結構的父介面。

第七,什麼時候用assert。

斷言是一個包含布爾表達式的語句,在執行這個語句時假定該表達式為 true。如果表達式計算為 false,那麼系統會報告一個 AssertionError。它用於調試目的:

assert(a > 0); // throws an AssertionError if a <= 0

斷言可以有兩種形式:

assert Expression1 ;
assert Expression1 : Expression2 ;

Expression1 應該總是產生一個布爾值。
Expression2 可以是得出一個值的任意表達式。這個值用於生成顯示更多調試信息的 String 消息。
斷言在默認情況下是禁用的。要在編譯時啟用斷言,需要使用 source 1.4 標記:

Javac -source 1.4 Test.java

要在運行時啟用斷言,可使用 -enableassertions 或者 -ea 標記。
要在運行時選擇禁用斷言,可使用 -da 或者 -disableassertions 標記。
要系統類中啟用斷言,可使用 -esa 或者 -dsa 標記。還可以在包的基礎上啟用或者禁用斷言。

可以在預計正常情況下不會到達的任何位置上放置斷言。斷言可以用於驗證傳遞給私有方法的參數。不過,斷言不應該用於驗證傳遞給公有方法的參數,因為不管是否啟用了斷言,公有方法都必須檢查其參數。不過,既可以在公有方法中,也可以在非公有方法中利用斷言測試後置條件。另外,斷言不應該以任何方式改變程序的狀態。

第八,GC是什麼? 為什麼要有GC? (基礎)。

GC是垃圾收集器。Java 程序員不用擔心內存管理,因為垃圾收集器會自動進行管理。要請求垃圾收集,可以調用下面的方法之一:

System.gc()
Runtime.getRuntime().gc()

第九,String s = new String("xyz");創建了幾個String Object?

兩個對象,一個是「xyx」,一個是指向「xyx」的引用對象s。

第十,Math.round(11.5)等於多少? Math.round(-11.5)等於多少?

Math.round(11.5)返回(long)12,Math.round(-11.5)返回(long)-11;

第十一,short s1 = 1; s1 = s1 + 1;有什麼錯? short s1 = 1; s1 += 1;有什麼錯?

short s1 = 1; s1 = s1 + 1;有錯,s1是short型,s1+1是int型,不能顯式轉化為short型。可修改為s1 =(short)(s1 + 1) 。short s1 = 1; s1 += 1正確。

第十二,sleep() 和 wait() 有什麼區別? 搞線程的最愛

sleep()方法是使線程停止一段時間的方法。在sleep 時間間隔期滿後,線程不一定立即恢復執行。這是因為在那個時刻,其它線程可能正在運行而且沒有被調度為放棄執行,除非(a)「醒來」的線程具有更高的優先順序,(b)正在運行的線程因為其它原因而阻塞。

wait()是線程交互時,如果線程對一個同步對象x 發出一個wait()調用,該線程會暫停執行,被調對象進入等待狀態,直到被喚醒或等待時間到。

第十三,Java有沒有goto?

Goto?java中的保留字,現在沒有在java中使用。

第十四,數組有沒有length()這個方法? String有沒有length()這個方法?

數組沒有length()這個方法,有length的屬性。
String有有length()這個方法。

第十五,Overload和Override的區別。Overloaded的方法是否可以改變返回值的類型?

方法的重寫Overriding和重載Overloading是Java多態性的不同表現。重寫Overriding是父類與子類之間多態性的一種表現,重載Overloading是一個類中多態性的一種表現。如果在子類中定義某方法與其父類有相同的名稱和參數,我們說該方法被重寫 (Overriding)。子類的對象使用這個方法時,將調用子類中的定義,對它而言,父類中的定義如同被「屏蔽」了。如果在一個類中定義了多個同名的方法,它們或有不同的參數個數或有不同的參數類型,則稱為方法的重載(Overloading)。Overloaded的方法是可以改變返回值的類型。

第十六,Set里的元素是不能重復的,那麼用什麼方法來區分重復與否呢? 是用==還是equals()? 它們有何區別?

Set里的元素是不能重復的,那麼用iterator()方法來區分重復與否。equals()是判讀兩個Set是否相等。

equals()和==方法決定引用值是否指向同一對象equals()在類中被覆蓋,為的是當兩個分離的對象的內容和類型相配的話,返回真值。

第十七,給我一個你最常見到的runtime exception。

ArithmeticException, ArrayStoreException, BufferOverflowException, BufferUnderflowException, CannotRedoException, CannotUndoException, ClassCastException, CMMException, , DOMException, EmptyStackException, IllegalArgumentException, IllegalMonitorStateException, IllegalPathStateException, IllegalStateException,
ImagingOpException, IndexOutOfBoundsException, MissingResourceException, NegativeArraySizeException, NoSuchElementException, NullPointerException, ProfileDataException, ProviderException, RasterFormatException, SecurityException, SystemException, UndeclaredThrowableException, UnmodifiableSetException, UnsupportedOperationException

第十八,error和exception有什麼區別?

error 表示恢復不是不可能但很困難的情況下的一種嚴重問題。比如說內存溢出。不可能指望程序能處理這樣的情況。

exception 表示一種設計或實現問題。也就是說,它表示如果程序運行正常,從不會發生的情況。

第十九,List, Set, Map是否繼承自Collection介面?

List,Set是

Map不是。

第二十,abstract class和interface有什麼區別?

聲明方法的存在而不去實現它的類被叫做抽象類(abstract class),它用於要創建一個體現某些基本行為的類,並為該類聲明方法,但不能在該類中實現該類的情況。不能創建abstract 類的實例。然而可以創建一個變數,其類型是一個抽象類,並讓它指向具體子類的一個實例。不能有抽象構造函數或抽象靜態方法。Abstract 類的子類為它們父類中的所有抽象方法提供實現,否則它們也是抽象類為。取而代之,在子類中實現該方法。知道其行為的其它類可以在類中實現這些方法。

介面(interface)是抽象類的變體。在介面中,所有方法都是抽象的。多繼承性可通過實現這樣的介面而獲得。介面中的所有方法都是抽象的,沒有一個有程序體。介面只可以定義static final成員變數。介面的實現與子類相似,除了該實現類不能從介面定義中繼承行為。當類實現特殊介面時,它定義(即將程序體給予)所有這種介面的方法。然後,它可以在實現了該介面的類的任何對象上調用介面的方法。由於有抽象類,它允許使用介面名作為引用變數的類型。通常的動態聯編將生效。引用可以轉換到介面類型或從介面類型轉換,instanceof 運算符可以用來決定某對象的類是否實現了介面。

第二十一,abstract的method是否可同時是static,是否可同時是native,是否可同時是synchronized?

都不能

第二十二,介面是否可繼承介面? 抽象類是否可實現(implements)介面? 抽象類是否可繼承實體類(concrete class)?

介面可以繼承介面。抽象類可以實現(implements)介面,抽象類是否可繼承實體類,但前提是實體類必須有明確的構造函數。

第二十三,啟動一個線程是用run()還是start()?

啟動一個線程是調用start()方法,使線程所代表的虛擬處理機處於可運行狀態,這意味著它可以由JVM調度並執行。這並不意味著線程就會立即運行。run()方法可以產生必須退出的標志來停止一個線程。

第二十四,構造器Constructor是否可被override?

構造器Constructor不能被繼承,因此不能重寫Overriding,但可以被重載Overloading。

第二十五,是否可以繼承String類?

String類是final類故不可以繼承。

第二十六,當一個線程進入一個對象的一個synchronized方法後,其它線程是否可進入此對象的其它方法?

不能,一個對象的一個synchronized方法只能由一個線程訪問。

第二十七,try {}里有一個return語句,那麼緊跟在這個try後的finally {}里的code會不會被執行,什麼時候被執行,在return前還是後?

會執行,在return前執行。

第二十八,編程題: 用最有效率的方法算出2乘以8等於幾?

有C背景的程序員特別喜歡問這種問題。

2 << 3

第二十九,兩個對象值相同(x.equals(y) == true),但卻可有不同的hash code,這句話對不對?

不對,有相同的hash code。

第三十,當一個對象被當作參數傳遞到一個方法後,此方法可改變這個對象的屬性,並可返回變化後的結果,那麼這里到底是值傳遞還是引用傳遞?

是值傳遞。Java 編程語言只由值傳遞參數。當一個對象實例作為一個參數被傳遞到方法中時,參數的值就是對該對象的引用。對象的內容可以在被調用的方法中改變,但對象的引用是永遠不會改變的。

第三十一,swtich是否能作用在byte上,是否能作用在long上,是否能作用在String上?

switch(expr1)中,expr1是一個整數表達式。因此傳遞給 switch 和 case 語句的參數應該是 int、 short、 char 或者 byte。long,string 都不能作用於swtich。

第三十二,編程題: 寫一個Singleton出來。

Singleton模式主要作用是保證在Java應用程序中,一個類Class只有一個實例存在。

一般Singleton模式通常有幾種種形式:

第一種形式: 定義一個類,它的構造函數為private的,它有一個static的private的該類變數,在類初始化時實例話,通過一個public的getInstance方法獲取對它的引用,繼而調用其中的方法。

public class Singleton {
private Singleton(){}
//在自己內部定義自己一個實例,是不是很奇怪?
//注意這是private 只供內部調用
private static Singleton instance = new Singleton();
//這里提供了一個供外部訪問本class的靜態方法,可以直接訪問
public static Singleton getInstance() {
return instance;
}
}

第二種形式:

public class Singleton {
private static Singleton instance = null;
public static synchronized Singleton getInstance() {
//這個方法比上面有所改進,不用每次都進行生成對象,只是第一次
//使用時生成實例,提高了效率!
if (instance==null)
instance=new Singleton();
return instance; }
}

其他形式:

定義一個類,它的構造函數為private的,所有方法為static的。

一般認為第一種形式要更加安全些

第三十三 Hashtable和HashMap

Hashtable繼承自Dictionary類,而HashMap是Java1.2引進的Map interface的一個實現

HashMap允許將null作為一個entry的key或者value,而Hashtable不允許

還有就是,HashMap把Hashtable的contains方法去掉了,改成containsvalue和containsKey。因為contains方法容易讓人引起誤解。

最大的不同是,Hashtable的方法是Synchronize的,而HashMap不是,在多個線程訪問Hashtable時,不需要自己為它的方法實現同步,而HashMap就必須為之提供外同步。

Hashtable和HashMap採用的hash/rehash演算法都大概一樣,所以性能不會有很大的差異。

閱讀全文

與java8gc演算法相關的資料

熱點內容
找漫畫看應該下載什麼app 瀏覽:180
如何在vps上搭建自己的代理伺服器 瀏覽:744
nginxphp埠 瀏覽:403
內臟pdf 瀏覽:152
怎麼看雲伺服器架構 瀏覽:85
我的世界國際服為什麼登不進伺服器 瀏覽:996
微盟程序員老婆 瀏覽:930
intellij創建java 瀏覽:110
java連接odbc 瀏覽:38
啟動修復無法修復電腦命令提示符 瀏覽:359
手機編程是什麼 瀏覽:98
山東移動程序員 瀏覽:163
蘇州java程序員培訓學校 瀏覽:479
單片機液晶驅動 瀏覽:855
魔拆app里能拆到什麼 瀏覽:132
新預演算法的立法理念 瀏覽:144
wdcpphp的路徑 瀏覽:134
單片機p0口電阻 瀏覽:926
瀏覽器中調簡訊文件夾 瀏覽:594
五菱宏光空調壓縮機 瀏覽:70