有的面試官會挖這個坑:你說說遇到的錯誤
java
Exception
- 是異常,是代碼裏經常寫的Error
- 是錯誤,像內粗溢出 OOM 這樣的就是壞就壞在你可能沒注意說成另外一個了,的確有這樣壞心眼的傢伙(╯‵□′)╯︵┴─┴面試
類的使用能夠分主動使用、被動使用,區別是被動使用類時,不會致使類的初始化,這會致使不少難以查找的 Bug 的算法
經過new關鍵字、反射、clone、反序列化機制實例化對象
調用類的靜態方法時
使用類的靜態字段或對其賦值時
經過反射調用類的方法時
初始化該類的子類時(初始化子類前其父類必須已經被初始化)
JVM啓動時被標記爲啓動類的類(簡單理解爲具備main方法的類)
new
用new語句bai建立對象,這是最常du用的建立對象的方式。Class.newInstance()
,JDK9 之後過期了,只能使用public的無參構造方法Construtcor.newInstance(xx)
有參無參均可以,也沒有訪問限制,這就是反射的好處clone()
反序列化手段:
好比IO,ObjectInputStream 的readObject() 方法,從本地文件,或者網絡上獲取第三方庫Objenesis
利用字節碼技術,動態生成class信息這個你們瞭解,知道有這麼回事就行,注意反射的2種方式差異,實際場景會用上數據庫
public class Max {
public void run() {
String name = new String();
}
}
複製代碼
字節碼:網絡
public void run();
descriptor: ()V
flags: ACC_PUBLIC
Code:
stack=2, locals=2, args_size=1
0: new #2 // class java/lang/String
3: dup
4: invokespecial #3 // Method java/lang/String."<init>":()V
7: astore_1
8: return
LineNumberTable:
line 11: 0
line 12: 8
複製代碼
一般這個問題是和 volitale 保證有序性、單例模式的雙判斷寫法爲何還要加上 volitale 關鍵字這個問題聯繫在一塊兒問的併發
判斷對象對應的類是否被加載、連接、初始化了
也就是new指令會去方法區常量池中定位到類的符號引用,檢查這個符號引用是否被加載了給對象分配內存空間,計算對象須要佔用多大的內存空間
併發處理
堆內存是共享區域,就會有併發問題
-XX:UseTLAB
來設置初始化分配到的內存空間(默認初始化)
也就是給屬性賦一個初始的默認值,即使該屬性在代碼裏設置值了,在這一步也會先給一個默認值,在以後的步奏裏再賦指定值設置對象頭
對象頭保存有對象的hashcode,GC信息,鎖信息,所屬類(方法區元數據地址)顯示初始化,執行init方法並初始化
具體能夠看下一個問題的解答,init就是類的構造器實際到代碼spa
Dog dog = new Dog();
複製代碼
new 關鍵字能夠理解爲1-5步,Dog() 至關於第6步線程
用過的內存在一邊,沒用過的內存在另外一邊,中間臨界點有一個指針。要是須要新分配內存空間了,只須要把指針移動執定大小便可。不過JVM是否採用這種分配方式,的看採用的垃圾回收器選擇的是否是 Serial、ParNew 這樣的壓縮算法(標記整理)了。核心就是垃圾回收以後新生代伊甸園區的是規整過的才能這麼玩 3d
屬性的默認初始化
顯示初始化/代碼塊初始化
構造器中初始化
上個問題6裏面的init方法對應的就是這裏的二、3部指針
有:句柄式、直接指針
2種
在JVM堆內存中,維護一個列表,存儲每一個對象對應的內存地址,比如咱們在數據庫搞一個索引表出來,你們要理解句柄的含義,就是索引,句柄是C++的內容,可是在java裏好多地方還有她的身影
句柄的好處在這個索引表的內存地址是不變的,不論是對象的地址怎麼變,對於別人來講其實都是不變的
缺點是真用內存,訪問效率低一些
這是目前 htospot 虛擬機訪問對象的方式,不須要索引表,我直接記錄你的內存位置,缺點是地址變了須要通知使用者
這道題仍是知道的好,還真就有人問。具體就是涉及到 GC 的標記清除算法上的優缺點,句柄式的能夠併發的GC垃圾回收,由於句柄是不變的,我恩始終能夠找到對象。直接指針GC咱們就必須中止其餘線程,由於引用地址會變
這是一道常問的面試題,咱們只考慮通常對象,對象實體是空的,Mark Word 佔64位8個字節
類型指針默認是8個字節的,可是在開啓指針壓縮時會變成4個字節,JDK8 是默認開啓的
參考對齊方式,對象的大小必須能被8整除。因此一個空對象默認佔用內存大小是12個字節,算上對齊方法的化是16個字節