漫畫:對象是如何被找到的?句柄 OR 直接指針?

{"type":"doc","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/e9/e99198029aaf372b2706e0bfedf2ec19.png","alt":"1.png","title":"1.png","style":null,"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/e9/e99198029aaf372b2706e0bfedf2ec19.png","alt":null,"title":null,"style":null,"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/12/127f5fdc85036ae0b1ab2daeb55e116a.png","alt":"2.png","title":"2.png","style":null,"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/6f/6f34435c599f95aa888f6a71d39aa3e7.png","alt":"3.png","title":"3.png","style":null,"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/fa/faa3b6398916b4f0403e19b1afe6a9c6.png","alt":"4.png","title":"4.png","style":null,"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/68/68098f014cb8f922581c7913e75b6af0.png","alt":"5.png","title":"5.png","style":null,"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/3a/3a1a81d3b3949c6605be25ba1084b80a.png","alt":"6.png","title":"6.png","style":null,"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/c8/c82fe14e6e99ff1fcef894aeba1aea7e.png","alt":"111.png","title":"111.png","style":null,"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/ca/ca77792d49ac8b45cf6817cbc0f16cef.png","alt":"888.png","title":"888.png","style":null,"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/d5/d5075ec2c6e7ae5f4379806c9e050971.png","alt":"444.png","title":"444.png","style":null,"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/ed/edeb41039d9b9f35f982a00576c1131a.png","alt":"10.png","title":"10.png","style":null,"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/34/348589f5610faaf6d46e5cddbd506516.png","alt":"555.png","title":"555.png","style":null,"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/f8/f8da16a560afaecad9eed262737bd94d.png","alt":"12.png","title":"12.png","style":null,"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/38/38f9e465e3d0e30ce4a862ddecd18e8a.png","alt":"image.png","title":"image.png","style":null,"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/8a/8a2e5bcf967d4946ddc2b86401497574.png","alt":"13.png","title":"13.png","style":null,"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/19/19677c385c95c92d27a60b0da14fcb3a.png","alt":"14.png","title":"14.png","style":null,"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/74/74800f24f63537fd8226818d3a658169.png","alt":"15.png","title":"15.png","style":null,"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/62/6204107680f697f62f76102fe920bec0.png","alt":"16.png","title":"16.png","style":null,"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/8c/8c07862978f14baa960f8310f247be3c.png","alt":"17.png","title":"17.png","style":null,"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/f5/f5bb17ef624a04018f7294775ae77cfe.png","alt":"666.png","title":"666.png","style":null,"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"blockquote","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#616161","name":"user"}},{"type":"bgcolor","attrs":{"color":"#FBF9FD","name":"user"}}],"text":"小貼士:想要使用並定位 Java 對象,就要用到 Java 虛擬機棧(Java Virtual Machine Stack),它描述的是 Java 方法執行的線程內存模型:每個方法被執行的時候,Java 虛擬機都會同步創建一個棧幀(Stack Frame)用於存儲局部變量表、操作數棧、動態連接、方法出口等信息。每一個方法被調用直至執行完畢的過程,就對應着一個棧幀在虛擬機棧中從入棧到出棧的過程。"}]}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#35b378","name":"user"}}],"text":"代碼解讀"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"以下面代碼爲例,來說明對象定位的過程:"}]},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"class Bus extends Car {\n private String code;\n private String color;\n Bus(String code, String color) {\n this.code = code;\n this.color = color;\n }\n // 省略其他方法...\n}\npublic class ReferenceTest {\n Bus myBus = new Bus(\"Java中文社羣\", \"藍色\");\n}\n"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"以官方默認的 HotSpot 虛擬機來說, "},{"type":"codeinline","content":[{"type":"text","text":"myBus"}],"marks":[{"type":"color","attrs":{"color":"#35b378","name":"user"}}]},{"type":"text","text":" 就是存儲在本地變量表中 reference 類型的變量, "},{"type":"codeinline","content":[{"type":"text","text":"new Bus(\"Java中文社羣\", \"藍色\")"}],"marks":[{"type":"color","attrs":{"color":"#35b378","name":"user"}}]},{"type":"text","text":" 就是存儲在 Java 堆中的對象實例數據,它存儲了此實體類的所有字段信息,例如 "},{"type":"codeinline","content":[{"type":"text","text":"code=\"Java中文社羣\""}],"marks":[{"type":"color","attrs":{"color":"#35b378","name":"user"}}]},{"type":"text","text":" 以及 "},{"type":"codeinline","content":[{"type":"text","text":"color=\"藍色\""}],"marks":[{"type":"color","attrs":{"color":"#35b378","name":"user"}}]},{"type":"text","text":" 等信息,而 Java 堆中的還存儲着對象類型數據的地址,它存儲的是對象的類型信息,還有它的父類信息等。"}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#35b378","name":"user"}}],"text":"總結"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"由於 reference 類型在《Java虛擬機規範》裏面只規定了它是一個指向對象的引用,並沒有定義這個引用應該通過什麼方式去定位、訪問到堆中對象的具體位置,所以對象訪問方式也是由虛擬機實現而定的,主流的訪問方式主要有使用句柄和直接指針兩種:"}]},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"如果使用句柄訪問的話,Java 堆中將可能會劃分出一塊內存來作爲句柄池,reference 中存儲的就是對象的句柄地址,而句柄中包含了對象實例數據與類型數據各自具體的地址信息;"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"如果使用直接指針訪問的話,Java 堆中對象的內存佈局就必須考慮如何放置訪問類型數據的相關信息,reference 中存儲的直接就是對象地址,如果只是訪問對象本身的話,就不需要多一次間接訪問的開銷。"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"因此使用句柄來訪問的最大好處就是 reference 中存儲的是穩定句柄地址,在對象被移動(垃圾收集時移動對象是非常普遍的行爲)時只會改變句柄中的實例數據指針,而 reference 本身不需要被修改。使用直接指針訪問速度更快,但如果對象被移動則需要修改 reference 本身。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"由於對象訪問在 Java 中非常頻繁,因此這類開銷積少成多也是一項極爲可觀的執行成本,所以官方默認的 HotSpot 虛擬機採用的就是「"},{"type":"text","marks":[{"type":"color","attrs":{"color":"#35b378","name":"user"}},{"type":"strong"}],"text":"直接指針"},{"type":"text","text":"」來定位對象的。"}]},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"參考 & 鳴謝"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"周志明《深入理解Java虛擬機》第 3 版"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}}]}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章