国产精品电影_久久视频免费_欧美日韩国产激情_成年人视频免费在线播放_日本久久亚洲电影_久久都是精品_66av99_九色精品美女在线_蜜臀a∨国产成人精品_冲田杏梨av在线_欧美精品在线一区二区三区_麻豆mv在线看

你有認(rèn)真了解過(guò)自己的 “Java 對(duì)象”嗎

開(kāi)發(fā) 后端
作為一名 Javaer,生活中的我們可能暫時(shí)沒(méi)有對(duì)象,但是工作中每天都會(huì)創(chuàng)建大量的 Java 對(duì)象,你有試著去了解下自己的“對(duì)象”嗎?

 作為一名 Javaer,生活中的我們可能暫時(shí)沒(méi)有對(duì)象,但是工作中每天都會(huì)創(chuàng)建大量的 Java 對(duì)象,你有試著去了解下自己的“對(duì)象”嗎?

[[333518]]

我們從四個(gè)方面重新認(rèn)識(shí)下自己的“對(duì)象”

  1. 創(chuàng)建對(duì)象的 6 種方式
  2. 創(chuàng)建一個(gè)對(duì)象在 JVM 中都發(fā)生了什么
  3. 對(duì)象在 JVM 中的內(nèi)存布局
  4. 對(duì)象的訪問(wèn)定位

一、創(chuàng)建對(duì)象的方式

  • 使用 new 關(guān)鍵字

這是創(chuàng)建一個(gè)對(duì)象最通用、常規(guī)的方法,同時(shí)也是最簡(jiǎn)單的方式。通過(guò)使用此方法,我們可以調(diào)用任何要調(diào)用的構(gòu)造函數(shù)(默認(rèn)使用無(wú)參構(gòu)造函數(shù))

  1. Person p = new Person(); 
  • 使用 Class 類(lèi)的 newInstance(),只能調(diào)用空參的構(gòu)造器,權(quán)限必須為 public
  1. //獲取類(lèi)對(duì)象 
  2. Class aClass = Class.forName("priv.starfish.Person"); 
  3. Person p1 = (Person) aClass.newInstance(); 
  • Constructor 的 newInstance(xxx),對(duì)構(gòu)造器沒(méi)有要求
  1. Class aClass = Class.forName("priv.starfish.Person"); 
  2. //獲取構(gòu)造器 
  3. Constructor constructor = aClass.getConstructor(); 
  4. Person p2 = (Person) constructor.newInstance(); 
  • clone()

深拷貝,需要實(shí)現(xiàn) Cloneable 接口并實(shí)現(xiàn) clone(),不調(diào)用任何的構(gòu)造器

  1. Person p3 = (Person) p.clone(); 
  • 反序列化

通過(guò)序列化和反序列化技術(shù)從文件或者網(wǎng)絡(luò)中獲取對(duì)象的二進(jìn)制流。

每當(dāng)我們序列化和反序列化對(duì)象時(shí),JVM 會(huì)為我們創(chuàng)建了一個(gè)獨(dú)立的對(duì)象。在 deserialization 中,JVM 不使用任何構(gòu)造函數(shù)來(lái)創(chuàng)建對(duì)象。(序列化的對(duì)象需要實(shí)現(xiàn) Serializable)

  1. //準(zhǔn)備一個(gè)文件用于存儲(chǔ)該對(duì)象的信息 
  2. File f = new File("person.obj"); 
  3. FileOutputStream fos = new FileOutputStream(f); 
  4. ObjectOutputStream oos = new ObjectOutputStream(fos); 
  5. //序列化對(duì)象,寫(xiě)入到磁盤(pán)中 
  6. oos.writeObject(p); 
  7. //反序列化 
  8. FileInputStream fis = new FileInputStream(f); 
  9. ObjectInputStream ois = new ObjectInputStream(fis); 
  10. //反序列化對(duì)象 
  11. Person p4 = (Person) ois.readObject(); 
  • 第三方庫(kù) Objenesls

Java已經(jīng)支持通過(guò) Class.newInstance() 動(dòng)態(tài)實(shí)例化 Java 類(lèi),但是這需要Java類(lèi)有個(gè)適當(dāng)?shù)臉?gòu)造器。很多時(shí)候一個(gè)Java類(lèi)無(wú)法通過(guò)這種途徑創(chuàng)建,例如:構(gòu)造器需要參數(shù)、構(gòu)造器有副作用、構(gòu)造器會(huì)拋出異常。Objenesis 可以繞過(guò)上述限制

二、創(chuàng)建對(duì)象的步驟

這里討論的僅僅是普通 Java 對(duì)象,不包含數(shù)組和 Class 對(duì)象(普通對(duì)象和數(shù)組對(duì)象的創(chuàng)建指令是不同的。創(chuàng)建類(lèi)實(shí)例的指令:new,創(chuàng)建數(shù)組的指令:newarray,anewarray,multianewarray)

1. new指令

虛擬機(jī)遇到一條 new 指令時(shí),首先去檢查這個(gè)指令的參數(shù)是否能在 Metaspace 的常量池中定位到一個(gè)類(lèi)的符號(hào)引用,并且檢查這個(gè)符號(hào)引用代表的類(lèi)是否已被加載、解析和初始化過(guò)(即判斷類(lèi)元信息是否存在)。如果沒(méi)有,那么須在雙親委派模式下,先執(zhí)行相應(yīng)的類(lèi)加載過(guò)程。

2. 分配內(nèi)存

接下來(lái)虛擬機(jī)將為新生代對(duì)象分配內(nèi)存。對(duì)象所需的內(nèi)存的大小在類(lèi)加載完成后便可完全確定。如果實(shí)例成員變量是引用變量,僅分配引用變量空間即可,即 4 個(gè)字節(jié)大小。分配方式有“指針碰撞(Bump the Pointer)”和“空閑列表(Free List)”兩種方式,具體由所采用的垃圾收集器是否帶有壓縮整理功能決定。

  • 如果內(nèi)存是規(guī)整的,就采用“指針碰撞”來(lái)為對(duì)象分配內(nèi)存。意思是所有用過(guò)的內(nèi)存在一邊,空閑的內(nèi)存在另一邊,中間放著一個(gè)指針作為分界點(diǎn)的指示器,分配內(nèi)存就僅僅是把指針指向空閑那邊挪動(dòng)一段與對(duì)象大小相等的距離罷了。如果垃圾收集器采用的是 Serial、ParNew 這種基于壓縮算法的,就采用這種方法。(一般使用帶整理功能的垃圾收集器,都采用指針碰撞)

 

 

  • 如果內(nèi)存是不規(guī)整的,虛擬機(jī)需要維護(hù)一個(gè)列表,這個(gè)列表會(huì)記錄哪些內(nèi)存是可用的,在為對(duì)象分配內(nèi)存的時(shí)候從列表中找到一塊足夠大的空間劃分給該對(duì)象實(shí)例,并更新列表內(nèi)容,這種分配方式就是“空閑列表”。使用CMS 這種基于Mark-Sweep 算法的收集器時(shí),通常采用空閑列表。

 

 

我們都知道堆內(nèi)存是線程共享的,那在分配內(nèi)存的時(shí)候就會(huì)存在并發(fā)安全問(wèn)題,JVM 是如何解決的呢?

一般有兩種解決方案:

  • 對(duì)分配內(nèi)存空間的動(dòng)作做同步處理,采用 CAS 機(jī)制,配合失敗重試的方式保證更新操作的原子性
  • 每個(gè)線程在 Java 堆中預(yù)先分配一小塊內(nèi)存,然后再給對(duì)象分配內(nèi)存的時(shí)候,直接在自己這塊"私有"內(nèi)存中分配,當(dāng)這部分區(qū)域用完之后,再分配新的"私有"內(nèi)存。這種方案稱(chēng)為T(mén)LAB(Thread Local Allocation Buffer),這部分 Buffer 是從堆中劃分出來(lái)的,但是是本地線程獨(dú)享的。

這里值得注意的是,我們說(shuō) TLAB 是線程獨(dú)享的,只是在“分配”這個(gè)動(dòng)作上是線程獨(dú)占的,至于在讀取、垃圾回收等動(dòng)作上都是線程共享的。而且在使用上也沒(méi)有什么區(qū)別。另外,TLAB 僅作用于新生代的 Eden Space,對(duì)象被創(chuàng)建的時(shí)候首先放到這個(gè)區(qū)域,但是新生代分配不了內(nèi)存的大對(duì)象會(huì)直接進(jìn)入老年代。因此在編寫(xiě) Java 程序時(shí),通常多個(gè)小的對(duì)象比大的對(duì)象分配起來(lái)更加高效。

虛擬機(jī)是否使用 TLAB 是可以選擇的,可以通過(guò)設(shè)置 -XX:+/-UseTLAB 參數(shù)來(lái)指定,JDK8 默認(rèn)開(kāi)啟。

3. 初始化

內(nèi)存分配完成后,虛擬機(jī)需要將分配到的內(nèi)存空間都初始化為零值(不包括對(duì)象頭),這一步操作保證了對(duì)象的實(shí)例字段在 Java 代碼中可以不賦初始值就直接使用,程序能訪問(wèn)到這些字段的數(shù)據(jù)類(lèi)型所對(duì)應(yīng)的零值。如:byte、short、long 轉(zhuǎn)化為對(duì)象后初始值為 0,Boolean 初始值為 false。

4. 對(duì)象的初始設(shè)置(設(shè)置對(duì)象的對(duì)象頭)

接下來(lái)虛擬機(jī)要對(duì)對(duì)象進(jìn)行必要的設(shè)置,例如這個(gè)對(duì)象是哪個(gè)類(lèi)的實(shí)例、如何才能找到類(lèi)的元數(shù)據(jù)信息、對(duì)象的哈希碼、對(duì)象的GC分代年齡等信息。這些信息存放在對(duì)象的對(duì)象頭(Object Header)之中。根據(jù)虛擬機(jī)當(dāng)前的運(yùn)行狀態(tài)的不同,如對(duì)否啟用偏向鎖等,對(duì)象頭會(huì)有不同的設(shè)置方式。

5.<init>方法初始化

 

在上面的工作都完成了之后,從虛擬機(jī)的角度看,一個(gè)新的對(duì)象已經(jīng)產(chǎn)生了,但是從 Java 程序的角度看,對(duì)象創(chuàng)建才剛剛開(kāi)始,方法還沒(méi)有執(zhí)行,所有的字段都還為零。初始化成員變量,執(zhí)行實(shí)例化代碼塊,調(diào)用類(lèi)的構(gòu)造方法,并把堆內(nèi)對(duì)象的地址賦值給引用變量。

所以,一般來(lái)說(shuō),執(zhí)行 new 指令后接著執(zhí)行 init 方法,把對(duì)象按照程序員的意愿進(jìn)行初始化(應(yīng)該是將構(gòu)造函數(shù)中的參數(shù)賦值給對(duì)象的字段),這樣一個(gè)真正可用的對(duì)象才算完全產(chǎn)生出來(lái)。

三、對(duì)象的內(nèi)存布局

在 HotSpot 虛擬機(jī)中,對(duì)象在內(nèi)存中存儲(chǔ)的布局可以分為 3 塊區(qū)域:對(duì)象頭(Header)、實(shí)例數(shù)據(jù)(Instance Data)、對(duì)其填充(Padding)。

對(duì)象頭

HotSpot 虛擬機(jī)的對(duì)象頭包含兩部分信息。

  • 第一部分用于存儲(chǔ)對(duì)象自身的運(yùn)行時(shí)數(shù)據(jù),如哈希碼(HashCode)、GC分代年齡、鎖狀態(tài)標(biāo)志、線程持有的鎖、偏向線程ID、偏向時(shí)間戳等。
  • 對(duì)象的另一部分類(lèi)型指針,即對(duì)象指向它的類(lèi)元數(shù)據(jù)的指針,虛擬機(jī)通過(guò)這個(gè)指針來(lái)確定這個(gè)對(duì)象是哪個(gè)類(lèi)的實(shí)例(并不是所有的虛擬機(jī)實(shí)現(xiàn)都必須在對(duì)象數(shù)據(jù)上保留類(lèi)型指針,也就是說(shuō),查找對(duì)象的元數(shù)據(jù)信息并不一定要經(jīng)過(guò)對(duì)象本身)。

如果對(duì)象是一個(gè) Java 數(shù)組,那在對(duì)象頭中還必須有一塊用于記錄數(shù)組長(zhǎng)度的數(shù)據(jù)。

元數(shù)據(jù):描述數(shù)據(jù)的數(shù)據(jù)。對(duì)數(shù)據(jù)及信息資源的描述信息。在 Java 中,元數(shù)據(jù)大多表示為注解。

實(shí)例數(shù)據(jù)

實(shí)例數(shù)據(jù)部分是對(duì)象真正存儲(chǔ)的有效信息,也是在程序代碼中定義的各種類(lèi)型的字段內(nèi)容,無(wú)論從父類(lèi)繼承下來(lái)的,還是在子類(lèi)中定義的,都需要記錄起來(lái)。這部分的存儲(chǔ)順序會(huì)受虛擬機(jī)默認(rèn)的分配策略參數(shù)和字段在 Java 源碼中定義的順序影響(相同寬度的字段總是被分配到一起)。

規(guī)則:

  • 相同寬度的字段總是被分配在一起
  • 父類(lèi)中定義的變量會(huì)出現(xiàn)在子類(lèi)之前
  • 如果 CompactFields 參數(shù)為 true(默認(rèn)true),子類(lèi)的窄變量可能插入到父類(lèi)變量的空隙

對(duì)齊填充

對(duì)齊填充部分并不是必然存在的,也沒(méi)有特別的含義,它僅僅起著占位符的作用。由于 HotSpot VM 的自動(dòng)內(nèi)存管理系統(tǒng)要求對(duì)象的起始地址必須是 8 字節(jié)的整數(shù)倍,也就是說(shuō),對(duì)象的大小必須是 8 字節(jié)的整數(shù)倍。而對(duì)象頭部分正好是 8 字節(jié)的倍數(shù)(1倍或者2倍),因此,當(dāng)對(duì)象實(shí)例數(shù)據(jù)部分沒(méi)有對(duì)齊時(shí),就需要通過(guò)對(duì)齊填充來(lái)補(bǔ)全。

我們通過(guò)一個(gè)簡(jiǎn)單的例子加深下理解

  1. public class PersonObject { 
  2.     public static void main(String[] args) { 
  3.         Person person = new Person(); 
  4.     } 
  5. public class Person { 
  6.     int id = 1008; 
  7.     String name
  8.     Department department; 
  9.     { 
  10.         name = "匿名用戶(hù)";   //name賦值為字符串常量 
  11.     } 
  12. public class Department { 
  13.     int id; 
  14.     String name

 

 

四、對(duì)象的訪問(wèn)定位

我們創(chuàng)建對(duì)象的目的,肯定是為了使用它,那 JVM 是如何通過(guò)棧幀中的對(duì)象引用訪問(wèn)到其內(nèi)存的對(duì)象實(shí)例呢?

由于 reference 類(lèi)型在 Java 虛擬機(jī)規(guī)范里只規(guī)定了一個(gè)指向?qū)ο蟮囊茫](méi)有定義這個(gè)引用應(yīng)該通過(guò)哪種方式去定位,以及訪問(wèn)到 Java 堆中的對(duì)象的具體位置,因此不同虛擬機(jī)實(shí)現(xiàn)的對(duì)象訪問(wèn)方式會(huì)有所不同,主流的訪問(wèn)方式有兩種:

  • 句柄訪問(wèn)

如果使用句柄訪問(wèn)方式,Java堆中會(huì)劃分出一塊內(nèi)存來(lái)作為句柄池,reference中存儲(chǔ)的就是對(duì)象的句柄地址,而句柄中包含了對(duì)象實(shí)例數(shù)據(jù)和類(lèi)型數(shù)據(jù)各自的具體地址信息。使用句柄方式最大的好處就是reference中存儲(chǔ)的是穩(wěn)定的句柄地址,在對(duì)象被移動(dòng)(垃圾收集時(shí)移動(dòng)對(duì)象是非常普遍的行為)時(shí)只會(huì)改變句柄中的實(shí)例數(shù)據(jù)指針,而reference本身不需要被修改。

 

 

  • 直接指針(Hotspot 使用該方式)

如果使用該方式,Java堆對(duì)象的布局就必須考慮如何放置訪問(wèn)類(lèi)型數(shù)據(jù)的相關(guān)信息,reference中直接存儲(chǔ)的就是對(duì)象地址。使用直接指針?lè)绞阶畲蟮暮锰幘褪撬俣雀欤?jié)省了一次指針定位的時(shí)間開(kāi)銷(xiāo)。

 

 

參考:

  • https://zhuanlan.zhihu.com/p/44948944
  • https://blog.csdn.net/boy1397081650/article/details/89930710
  • https://www.cnblogs.com/lusaisai/p/12748869.html
  • https://juejin.im/post/5d4250def265da03ab422c79

 

責(zé)任編輯:武曉燕 來(lái)源: JavaKeeper
相關(guān)推薦

2022-04-28 08:12:29

函數(shù)調(diào)用進(jìn)程切換代碼

2022-08-02 06:31:32

Java并發(fā)工具類(lèi)

2022-07-26 08:40:42

Java并發(fā)工具類(lèi)

2020-03-11 20:42:34

瀏覽器緩存機(jī)制

2021-07-12 07:59:05

對(duì)象接口編程

2022-07-11 10:47:46

容器JAVA

2023-05-29 08:11:42

@Value注解Bean

2022-01-05 12:03:48

MySQL索引數(shù)據(jù)

2022-06-10 13:56:42

Java

2025-01-13 00:17:49

Java開(kāi)發(fā)對(duì)象

2023-11-01 13:48:00

反射java

2019-10-31 08:36:59

線程內(nèi)存操作系統(tǒng)

2022-06-15 15:14:17

Java公平鎖非公平鎖

2022-07-18 14:18:26

Babel代碼面試

2022-01-17 07:32:34

Java參數(shù)方法

2024-04-15 00:02:00

Java補(bǔ)丁技術(shù)

2020-11-25 07:59:38

網(wǎng)頁(yè)設(shè)計(jì)響應(yīng)式

2012-09-27 10:24:22

監(jiān)控機(jī)房

2022-07-26 00:00:22

HTAP系統(tǒng)數(shù)據(jù)庫(kù)

2012-09-06 17:54:28

點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

国偷自产视频一区二区久| 国产日本精品| 91精品欧美综合在线观看最新| 免费羞羞视频网站| 91麻豆国产福利精品| www亚洲国产| 日韩av二区| 国产成人av网| 国产亚洲精品美女久久| 欧美成人免费小视频| 日本一区二区三区视频在线| 亚洲视频大全| 91久色国产| 在线成人直播| 国产精品夜色7777狼人| 狠狠做六月爱婷婷综合aⅴ| 97视频com| 久久91在线| 欧美大片免费看| 91精品福利观看| 久热国产精品视频| 日本在线一区二区三区| 欧美久久久精品| 成人精品动漫一区二区三区| 欧美—级a级欧美特级ar全黄| 欧美区一区二区| 久久久亚洲成人| 任你躁在线精品免费| 国产成人精品一区二区在线| 欧美日韩性在线观看| 91精品中文在线| 亚洲区第一页| 日韩av电影免费在线观看| 日本欧美在线看| 日韩精品免费一区| 久久久久高清精品| 蜜臀视频一区二区三区| 久久你懂得1024| 久久久久久久久中文字幕| 久久白虎精品| 老鸭窝亚洲一区二区三区| 欧美精品aⅴ在线视频| 天天综合色天天综合色hd| 精品理论电影| 日韩精品一区二区三区中文不卡| 国产情人节一区| www.av毛片| 在线免费观看日本欧美爱情大片| 亚洲第一在线综合网站| 久久精品成人动漫| 天堂av免费观看| 日韩精品2区| 欧美另类第一页| 国产精品久久久久久久美男 | 九九热精品视频| av一区二区高清| 精品国产福利| 成人免费看的视频| 老司机aⅴ毛片免费观看| 欧美日韩亚洲一区二区| 天堂成人av| 久久免费在线观看| 在线成人亚洲| 欧美黄色免费网址| 亚洲精品中文在线观看| 视频国产一区| 国产精品www色诱视频| 国产精品一区亚洲| 日本不卡一区二区三区视频| 国产一区二区三区国产精品| 川上优av一区二区线观看| 9i在线看片成人免费| 又黄又www| 国模精品视频一区二区三区| 不卡视频一二三| 在线看的av网站| 欧美在线一级视频| 91精品久久久久久综合五月天| 凹凸av导航大全精品| 成人情趣片在线观看免费| 极品少妇一区二区| 导航福利在线| 在线播放国产精品| 欧美日本亚洲韩国国产| 黄色动漫网站入口| 欧美一级片免费看| 成人av国产| 少妇高清精品毛片在线视频| 日韩视频国产视频| 婷婷综合在线| 无套内精的网站| 中文字幕欧美日韩| 亚洲人体偷拍| 一级毛片电影| 欧美成人精品在线观看| 日韩国产高清影视| 你懂的视频在线| 91国语精品自产拍在线观看性色 | 玩弄japan白嫩少妇hd| 欧美性猛交xxxx乱大交3| 香蕉久久久久久| 国产亚洲一区二区三区在线播放 | 小说区图片区亚洲| 日韩欧美在线一区二区| 亚洲成人综合视频| 77成人影视| 日韩精品视频在线观看视频| 欧美肥妇毛茸茸| 日韩成人精品一区二区| www成人免费观看网站| 色七七影院综合| 先锋影音久久久| 国产乱理伦片a级在线观看| 国产精品视频久久久| 专区另类欧美日韩| 美国十次av导航亚洲入口| 国产日韩一区二区在线| 一个人看的www久久| 毛片av一区二区| heyzo一区| 视频三区二区一区| 91精品国产色综合久久不卡蜜臀| 欧美日韩一区二区高清| 在线观看黄网| 国产一区玩具在线观看| 亚洲激情成人在线| 蜜臀久久99精品久久一区二区| 狠狠热免费视频| 欧美高清无遮挡| 国产精品青草久久| 国产在线播放精品| 欧美狂欢多p性派对| 日本不卡高字幕在线2019| 亚洲视频1区2区| 欧美日韩国产免费观看视频| 亚色视频在线播放| 成人在线观看视频网站| 一本大道久久a久久综合婷婷 | 欧美亚洲国产日本| 国产精品黄色在线观看| 国产精品欧美三级在线观看| 成视频在线观看免费观看| 国产999精品视频| 亚洲精品视频在线| 图片区亚洲欧美小说区| 精品美女视频在线观看免费软件| 亚洲自拍另类欧美丝袜| 欧美日韩国产综合视频在线观看| 久久久久久久久久久99| 亚洲精品成人久久久998| 国产精品网站在线观看| 阿v免费在线观看| 国内精品久久国产| 精品不卡在线视频| 成人美女视频在线看| 亚洲日本va午夜在线电影| 高清av影院| 999久久久| 日韩美女在线视频| 激情成人亚洲| 色先锋久久影院av| 99久久婷婷这里只有精品| 青青青免费在线视频| 亚洲一卡二卡| 色在人av网站天堂精品| 国产精品视频| 国产在线1区| 亚洲jjzzjjzz在线观看| 日韩小视频网站| 久久久久久99| 超碰成人免费在线| 亚洲va男人天堂| 成人网中文字幕| 日韩视频欧美视频| 欧美日韩一区二区在线| 久久成人av少妇免费| 亚洲理论电影网| 秋霞伦理一区| 国产美女玉足交| 国产素人在线观看| 国产精品久久久久久久9999| 欧美视频国产精品| 国产欧美日产一区| 精品动漫3d一区二区三区免费| 欧美男男freegayvideosroom| 99免在线观看免费视频高清| 在线视频xx| 91传媒在线观看| 色资源网站在线观看| 日本在线中文电影| 免费网站在线观看人| 一级毛片免费视频| 又色又爽又高潮免费视频国产| 国产成人aa精品一区在线播放 | 免费高清不卡av| 国产原创一区| av中文字幕在线| 欧洲免费在线视频| 秋霞a级毛片在线看| 国产女主播在线直播|