java創建對象new后面為啥可以傳入參數_你有認真了解過自己的“Java對象”嗎?渣男...

對象在 JVM 中是怎么存儲的
對象頭里有什么?

作為一名 Javaer,生活中的我們可能暫時沒有對象,但是工作中每天都會創建大量的 Java 對象,你有試著去了解下自己的“對象”嗎?

我們從四個方面重新認識下自己的“對象”

  1. 創建對象的 6 種方式
  2. 創建一個對象在 JVM 中都發生了什么
  3. 對象在 JVM 中的內存布局
  4. 對象的訪問定位

一、創建對象的方式

  • 使用 new 關鍵字這是創建一個對象最通用、常規的方法,同時也是最簡單的方式。通過使用此方法,我們可以調用任何要調用的構造函數(默認使用無參構造函數)Person p = new Person();
  • 使用 Class 類的 newInstance(),只能調用空參的構造器,權限必須為 public//獲取類對象 Class aClass = Class.forName("priv.starfish.Person"); Person p1 = (Person) aClass.newInstance();
  • Constructor 的 newInstance(xxx),對構造器沒有要求Class aClass = Class.forName("priv.starfish.Person"); //獲取構造器 Constructor constructor = aClass.getConstructor(); Person p2 = (Person) constructor.newInstance();
  • clone()深拷貝,需要實現 Cloneable 接口并實現 clone(),不調用任何的構造器Person p3 = (Person) p.clone();
  • 反序列化通過序列化和反序列化技術從文件或者網絡中獲取對象的二進制流。每當我們序列化和反序列化對象時,JVM 會為我們創建了一個獨立的對象。在 deserialization 中,JVM 不使用任何構造函數來創建對象。(序列化的對象需要實現 Serializable)//準備一個文件用于存儲該對象的信息 File f = new File("person.obj"); FileOutputStream fos = new FileOutputStream(f); ObjectOutputStream oos = new ObjectOutputStream(fos); //序列化對象,寫入到磁盤中 oos.writeObject(p); //反序列化 FileInputStream fis = new FileInputStream(f); ObjectInputStream ois = new ObjectInputStream(fis); //反序列化對象 Person p4 = (Person) ois.readObject();
  • 第三方庫 ObjeneslsJava已經支持通過 Class.newInstance() 動態實例化 Java 類,但是這需要Java類有個適當的構造器。很多時候一個Java類無法通過這種途徑創建,例如:構造器需要參數、構造器有副作用、構造器會拋出異常。Objenesis 可以繞過上述限制

二、創建對象的步驟

這里討論的僅僅是普通 Java 對象,不包含數組和 Class 對象(普通對象和數組對象的創建指令是不同的。創建類實例的指令:new,創建數組的指令:newarray,anewarray,multianewarray)

1. new指令

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

2. 分配內存

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

  • 如果內存是規整的,就采用“指針碰撞”來為對象分配內存。意思是所有用過的內存在一邊,空閑的內存在另一邊,中間放著一個指針作為分界點的指示器,分配內存就僅僅是把指針指向空閑那邊挪動一段與對象大小相等的距離罷了。如果垃圾收集器采用的是 Serial、ParNew 這種基于壓縮算法的,就采用這種方法。(一般使用帶整理功能的垃圾收集器,都采用指針碰撞)
  • 如果內存是不規整的,虛擬機需要維護一個列表,這個列表會記錄哪些內存是可用的,在為對象分配內存的時候從列表中找到一塊足夠大的空間劃分給該對象實例,并更新列表內容,這種分配方式就是“空閑列表”。使用CMS 這種基于Mark-Sweep 算法的收集器時,通常采用空閑列表。
我們都知道堆內存是線程共享的,那在分配內存的時候就會存在并發安全問題,JVM 是如何解決的呢?

一般有兩種解決方案:

  1. 對分配內存空間的動作做同步處理,采用 CAS 機制,配合失敗重試的方式保證更新操作的原子性
  2. 每個線程在 Java 堆中預先分配一小塊內存,然后再給對象分配內存的時候,直接在自己這塊"私有"內存中分配,當這部分區域用完之后,再分配新的"私有"內存。這種方案稱為 TLAB(Thread Local Allocation Buffer),這部分 Buffer 是從堆中劃分出來的,但是是本地線程獨享的。這里值得注意的是,我們說 TLAB 是線程獨享的,只是在“分配”這個動作上是線程獨占的,至于在讀取、垃圾回收等動作上都是線程共享的。而且在使用上也沒有什么區別。另外,TLAB 僅作用于新生代的 Eden Space,對象被創建的時候首先放到這個區域,但是新生代分配不了內存的大對象會直接進入老年代。因此在編寫 Java 程序時,通常多個小的對象比大的對象分配起來更加高效。虛擬機是否使用 TLAB 是可以選擇的,可以通過設置 -XX:+/-UseTLAB 參數來指定,JDK8 默認開啟。

3. 初始化

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

4. 對象的初始設置(設置對象的對象頭)

接下來虛擬機要對對象進行必要的設置,例如這個對象是哪個類的實例、如何才能找到類的元數據信息、對象的哈希碼、對象的GC分代年齡等信息。這些信息存放在對象的對象頭(Object Header)之中。根據虛擬機當前的運行狀態的不同,如對否啟用偏向鎖等,對象頭會有不同的設置方式。

5. <init>方法初始化

在上面的工作都完成了之后,從虛擬機的角度看,一個新的對象已經產生了,但是從 Java 程序的角度看,對象創建才剛剛開始,<init>方法還沒有執行,所有的字段都還為零。初始化成員變量,執行實例化代碼塊,調用類的構造方法,并把堆內對象的地址賦值給引用變量。

所以,一般來說,執行 new 指令后接著執行 init 方法,把對象按照程序員的意愿進行初始化(應該是將構造函數中的參數賦值給對象的字段),這樣一個真正可用的對象才算完全產生出來。

三、對象的內存布局

在 HotSpot 虛擬機中,對象在內存中存儲的布局可以分為 3 塊區域:對象頭(Header)、實例數據(Instance Data)、對其填充(Padding)。

對象頭

HotSpot 虛擬機的對象頭包含兩部分信息。

  • 第一部分用于存儲對象自身的運行時數據,如哈希碼(HashCode)、GC分代年齡、鎖狀態標志、線程持有的鎖、偏向線程ID、偏向時間戳等。
  • 對象的另一部分類型指針,即對象指向它的類元數據的指針,虛擬機通過這個指針來確定這個對象是哪個類的實例(并不是所有的虛擬機實現都必須在對象數據上保留類型指針,也就是說,查找對象的元數據信息并不一定要經過對象本身)。

如果對象是一個 Java 數組,那在對象頭中還必須有一塊用于記錄數組長度的數據。

元數據:描述數據的數據。對數據及信息資源的描述信息。在 Java 中,元數據大多表示為注解。

實例數據

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

規則:

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

對齊填充

對齊填充部分并不是必然存在的,也沒有特別的含義,它僅僅起著占位符的作用。由于 HotSpot VM 的自動內存管理系統要求對象的起始地址必須是 8 字節的整數倍,也就是說,對象的大小必須是 8 字節的整數倍。而對象頭部分正好是 8 字節的倍數(1倍或者2倍),因此,當對象實例數據部分沒有對齊時,就需要通過對齊填充來補全。

我們通過一個簡單的例子加深下理解

public class PersonObject {public static void main(String[] args) {Person person = new Person();}
}public class Person {int id = 1008;String name;Department department;{name = "匿名用戶";   //name賦值為字符串常量}
}public class Department {int id;String name;
}

526998135af9fd0d06cc3d6079deada7.png

四、對象的訪問定位

我們創建對象的目的,肯定是為了使用它,那 JVM 是如何通過棧幀中的對象引用訪問到其內存的對象實例呢?

由于 reference 類型在 Java 虛擬機規范里只規定了一個指向對象的引用,并沒有定義這個引用應該通過哪種方式去定位,以及訪問到 Java 堆中的對象的具體位置,因此不同虛擬機實現的對象訪問方式會有所不同,主流的訪問方式有兩種:

  • 句柄訪問如果使用句柄訪問方式,Java堆中會劃分出一塊內存來作為句柄池,reference中存儲的就是對象的句柄地址,而句柄中包含了對象實例數據和類型數據各自的具體地址信息。使用句柄方式最大的好處就是reference中存儲的是穩定的句柄地址,在對象被移動(垃圾收集時移動對象是非常普遍的行為)時只會改變句柄中的實例數據指針,而reference本身不需要被修改。
  • 直接指針(Hotspot 使用該方式)如果使用該方式,Java堆對象的布局就必須考慮如何放置訪問類型數據的相關信息,reference中直接存儲的就是對象地址。使用直接指針方式最大的好處就是速度更快,他節省了一次指針定位的時間開銷

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/455768.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/455768.shtml
英文地址,請注明出處:http://en.pswp.cn/news/455768.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【技術+某度面經】Jenkins 內容+百度面經分享

后臺可回復【1024】即可獲取相關寶藏內容分享 :&#xff09; Q1: Jenkins是什么&#xff1f;&#xff1f; A:Jenkins是一款開源 CI&CD 軟件&#xff0c;用于自動化各種任務&#xff0c;包括構建、測試和部署軟件。 今天文章分為兩部分 :) PART1 Jenkins技術分享 / PART2 關…

xcode多工程聯編 - 詳細教程

2019獨角獸企業重金招聘Python工程師標準>>> 一、創建workspace (MyProject)放入MyProject文件夾內 二、先 打開workspace 創建app1工程 點擊next之后注意選擇 workspace 同理創建app2 或者更多的工程 完成之后的工作 重新打開workspace的樣子 三、使用pod 庫 首先…

動態規劃入門 合并石子 COGS1660 石子合并

1660. 石子合并&#xff08;加強版&#xff09; ★★ 輸入文件&#xff1a;stone3.in 輸出文件&#xff1a;stone3.out 簡單對比時間限制&#xff1a;1 s 內存限制&#xff1a;256 MB 【題目描述】 在一個圓形操場的四周擺放N堆石子,現要將石子有次序地合并成一堆.規定…

python實現百錢買百雞

個人博客點這里 Python語言基礎(百元買百雞) 需求分析 百錢買百雞的問題算是一套非常經典的不定方程的問題&#xff0c;題目很簡單&#xff1a; 公雞5文錢一只&#xff0c;母雞3文錢一只&#xff0c;小雞3只一文錢&#xff0c; 用100文錢買一百只雞,其中公雞&#xff0c;母雞…

實數是不是python數據類型_python 基本數據類型

一、數據類型及操作 #整數類型&#xff0c;和數學中整數的一樣&#xff0c;可正可負 *十進制&#xff1a;210 *二進制&#xff1a;以0B或者0b開頭&#xff1a;0b1010 *八進制&#xff1a;以0O或者0o開頭&#xff1a;0o123 *十六進制&#xff1a;以0x或者0X開頭&#xff1a;0x9a…

python之用循環實現五子棋小程序

在python中我們學過流程控制中的循環結構,現在我們來進行一個小應用的練習 本程序是通過循環控制結構來實現五子棋小程序的 游戲規則 五子棋的規則如下: 對局雙方各執一色棋子。空棋盤開局。黑先、白后&#xff0c;交替下子&#xff0c;每次只能下一子。棋子下在棋盤的空白點…

Principle of Computing (Python)學習筆記(7) DFS Search + Tic Tac Toe use MiniMax Stratedy

1. Trees Tree is a recursive structure. 1.1 math nodes https://class.coursera.org/principlescomputing-001/wiki/view?pagetrees 1.2 CODE無parent域的樹 http://www.codeskulptor.org/#poc_tree.py class Tree:"""Recursive definition for tree…

C#線程篇---Task(任務)和線程池不得不說的秘密

我們要知道的是&#xff0c;QueueUserWorkItem這個技術存在許多限制。其中最大的問題是沒有一個內建的機制讓你知道操作在什么時候完成&#xff0c;也沒有一個機制在操作完成是獲得一個返回值&#xff0c;這些問題使得我們都不敢啟用這個技術。 Microsoft為了克服這些限制&…

關于編譯FFMPEG的初級教程

關于編譯FFMPEG的初級教程1.首先我們要下載相關工具&#xff0c;這里不多說&#xff0c;大家按照我的地址去下載文件就好了 MINGW下載地址&#xff1a;http://prdownloads.sourceforge.net/mingw/MinGW-3.1.0-1.exe?download 然后在下載MSYS &#xff1a;http://prdownloads.…

電子科學與技術相關索引匯總

電子科學與技術相關索引匯總 關于安裝deepinwindow10雙系統有時沒有聲音的問題關于deepin系統安裝design compiler的問題解答基于51單片機的交通燈控制設計基于物聯網的智能垃圾桶設計基于FPGA 的8b10b編解碼電路前端電路設計金屬磁記憶傳感器封裝集成電路版圖與工藝課程設計之…

【百度面試】閘機測試場景

面試被問到這一題思路想法&#xff1a; 自己找了相關內容充實自我。內容分享如下&#xff1a; 隨著人臉識別技術的成熟&#xff0c;閘機行業大量應用人臉識別算法&#xff0c;只因現今的人臉識別算法也已經能夠保證識別率、識別速度、誤識率和拒識率等各項指標的優異性&#x…

前后端分離項目如何部署_前后端分離項目,如何解決跨域問題?

跨域資源共享(CORS)是前后端分離項目很常見的問題&#xff0c;本文主要介紹當SpringBoot應用整合SpringSecurity以后如何解決該問題。01 什么是跨域問題&#xff1f;CORS全稱Cross-Origin Resource Sharing&#xff0c;意為跨域資源共享。當一個資源去訪問另一個不同域名或者同…

使用模板引擎artTemplate的幾個問題總結

一、Template not found 有的時候模板寫的并沒有問題&#xff0c;可就是找不到。這時候可能是<script>加載順序問題&#xff0c;模板渲染在模板加載完成之前先執行了&#xff0c;調整<script>的順序。 二、模板中將字符串轉化成數字 利用html中的表單來轉化&#x…

Android報“android.content.res.Resources$NotFoundException: String resource ID #0x2”錯誤

Android報“android.content.res.Resources$NotFoundException: String resource ID #0x2”錯誤 當調用setText()方法時如果傳入int型是不會被當成內容而是resourceID來使用&#xff01; 所以報錯&#xff01; 解決方法&#xff1a;TextView.setText("" arg) 轉為St…

時間戳問題匯總

大家好 我剛接觸流媒體不久&#xff0c; 現在遇到一個非常奇怪的問題&#xff0c;向各位大俠請假&#xff0c;請你們指點。 問題是這樣的 用一個 VLC(流媒體客戶端) 去請求流媒體服務器上的數據&#xff0c; 但是獲得的數據播放速度明顯快于1倍速&#xff0c;大概是 timest…

如何實現 C/C++ 與 Python 的通信?

如何實現 C/C 與 Python 的通信&#xff1f; 想在 C 中用 Python 進行數值計算&#xff0c;Python 需要訪問 C 的變量并計算后返回數值。有什么好辦法呢&#xff1f; 參考https://www.zhihu.com/question/23003213

前端相關索引匯總

前端相關索引匯總 HTML相關 HTML概述和基本結構HTML中Head頭HTML標題 HTML段落,換行,字符實體HTML塊,含樣式的標簽HTML中的圖片HTML中的鏈接HTML中的列表HTML中的表格HTML中的表單 CSS相關 Css基本語法及頁面引用Css中的選擇器Css顏色和文本字體CSS邊框,背景,邊距,溢出CSS中的…

nginx反向代理配置 多個_實例分享:Nginx學習之反向代理WebSocket配置實例

寫在開始去年&#xff0c;做過一款競賽打分的APP。具體需求&#xff0c;同組教師之間可以相互通信&#xff0c;及時通知同組人員&#xff0c;其他組員做了那些操作(當然&#xff0c;這只是針對特定操作)。實現方案采用目前比較成熟的WebSocket技術&#xff0c;WebSocket協議為創…

性能測試總結(一)---基礎理論篇

隨著軟件行業的快速發展&#xff0c;現代的軟件系統越來越復雜&#xff0c;功能越來越多&#xff0c;測試人員除了需要保證基本的功能測試質量&#xff0c;性能也隨越來越受到人們的關注。但是一提到性能測試&#xff0c;很多人就直接連想到Loadrunner。認為LR就等于性能測試&a…