工作中,也許我們能夠碰到各種各樣的問題,也許碰不到。這些經歷確實會讓我們成長很多,但是,及時遇到的問題再多,我覺得,那些應是零散的,很難形成體系結構的。
所以,我們很多時候是需要書來建立一些完整的體系的。
前段時間,買了本《深入理解java虛擬機》,花了一周多的時間看了一遍,然后再簡單回顧了下,覺得有必要寫點讀后感。因為,我們只有七秒鍾的記憶,記下來后面翻閱。盡管書上也有,但畢竟不是自己的。轉化是需要時間的。
如下正題!
首先一點,現在的技術呢,更新換代很快,所以,一定要盡可能的接受最新的資料,所以,要買肯定買最新版了。里面介紹的結合了jdk1.7,還算可以吧。
翻開目錄,大概就知道要讀些啥了。
第一部分 走進java
我覺得,都幾十歲的人了,就不要浪費大家的時間了吧。直接跳過,不會去讀了。
第二部分 自動內存管理
這部分就比較重要了,也許你說講的 堆棧內存你都知道,但是,你真的透徹嗎?還是仔細看看的好。如下這個圖,我覺得貼得不多於。
1. 程序計數器。 當前執行的字節碼的行號指示器。和匯編中的 CS IP 相似,通過改變這個值,從而使代碼一步步執行下去。
2. 虛擬機棧。每個方法執行時,都會創建一個棧幀(Current Stack Frame),用於存儲局部變量表(Local Stack Frame)、操作數棧(Operand Stack)、動態鏈接(Dynamic Linking)、返回地址(Return Address)等,每個方法從調用執行到完成,就對應着一棧幀在虛擬機中的入棧和出棧過程。
3. 本地方法棧。與虛擬機棧功能類似,不過是作用於native方法。
4. java堆。java虛擬機中管理的最大的一塊內存。所有線程共享該內存,他的作用就是用來存放對象實例,幾乎所有的對象實例都在這里分配。因是幾乎所有對象的存放區域,所以也是gc的主要區域了。
5. 方法區。他用於存儲已被虛擬機加載的類信息、常量、靜態變量、即時編譯器編譯后的代碼等數據,他是所有線程共享的。
6. 直接內存。這是jdk1.4后,使用native函數直接分配的directbytebuffer。此處的內存不java堆大小的限制。
7. 內存的分配方式有兩種,指針碰撞和空閑列表,采用的分配方式取決於java堆是否規整,而堆是否規整又取決於垃圾回收器是否具有壓縮功能。
雖然都是概念性的東西,但是,當你把個細節都了解后,是需要這么一個總體印象的。
第3單 垃圾收集器與內在分配策略
哪些內存需要回收? 什么時候回收? 如何回收?
回答完這幾個問題,本章就算完成了。
1. 垃圾回收算法。
引用計數器算法。算法簡單,只要計數器值為0就可以進行回收,但是存在相互循環引用時無法進行回收的問題。
可達性分析算法(gc roots)。目前主流的收集方法。
標記-清除算法、復制算法、標記整理算法、分代收集算法。
收集器:serial 收集器、parnew收集器、parallel scavenge收集器、serial old收集器、cms 收集器、G1收集器(據說是最前沿的收集器)
GC日志的查看。
第4章 虛擬機性能監控與故障處理工具
jps 查看虛擬機進程狀況。
jstat (jvm statistics monitoing tool) 用於監視虛擬機各種運行狀態信息,可以顯示本地或遠程虛擬機中的類裝載、內存、垃圾收集、jit編譯等運行參數。
jinfo 查看配置,jhat 快照查看工具,此二命令意義不大。
jmap 用於生成堆轉儲快照。
jstack 用於生成線程快照。
gui工具,jconsole, visual vm(插件可用),btrace。
第三部分 虛擬機執行子系統
第6章 類文件結構
字節碼是虛擬機的,不是java的,虛擬機可以執行其他語言的文件,符合虛擬機規范即可。
class 文件的頭4個字節稱為魔數,值為:0xcafebabe; 第5-6位為次版本號,7-8位為主版本號。根據該版本號來確定,運行的java版本是否是虛擬機支持的版本,向后兼容。
接下來是常量池,它是其他項目關聯最多的數據類型,也是占用class空間最大的項目之一,同時還是第一個出現的表類型數據項目。
類型 | 標志 | 描述 |
CONSTANT_utf8_info | 1 | UTF-8編碼的字符串 |
CONSTANT_Integer_info | 3 | 整形字面量 |
CONSTANT_Float_info | 4 | 浮點型字面量 |
CONSTANT_Long_info | 5 | 長整型字面量 |
CONSTANT_Double_info | 6 | 雙精度浮點型字面量 |
CONSTANT_Class_info | 7 | 類或接口的符號引用 |
CONSTANT_String_info | 8 | 字符串類型字面量 |
CONSTANT_Fieldref_info | 9 | 字段的符號引用 |
CONSTANT_Methodref_info | 10 | 類中方法的符號引用 |
CONSTANT_InterfaceMethodref_info | 11 | 接口中方法的符號引用 |
CONSTANT_NameAndType_info | 12 | 字段或方法的符號引用 |
CONSTANT_MethodHandle_info | 15 | 表示方法句柄 |
CONSTANT_MothodType_info | 16 | 標志方法類型 |
CONSTANT_InvokeDynamic_info | 18 | 表示一個動態方法調用點 |
訪問標志,和類里寫的方法權限是一致的。
標志名
|
標志值
|
標志含義
|
針對的對像
|
ACC_PUBLIC
|
0x0001
|
public類型
|
所有類型
|
ACC_FINAL
|
0x0010
|
final類型
|
類
|
ACC_SUPER
|
0x0020
|
使用新的invokespecial語義
|
類和接口
|
ACC_INTERFACE
|
0x0200
|
接口類型
|
接口
|
ACC_ABSTRACT
|
0x0400
|
抽象類型
|
類和接口
|
ACC_SYNTHETIC
|
0x1000
|
該類不由用戶代碼生成
|
所有類型
|
ACC_ANNOTATION
|
0x2000
|
注解類型
|
注解
|
ACC_ENUM
|
0x4000
|
枚舉類型
|
枚舉
|
描述符標識字符含義
標識字符 含義
B byte
C char
D double
F float
I int
J long
S short
Z boolean
V void
L Object, 例如 Ljava/lang/Object
一維數組用[ 表示,二維數組用 [[ 表示,以此類推。表示方法如,void inc(); -> ()V; int indexof(char s[], int offset) -> ([CI)I;
方法表集合,屬性表集合。
code屬性不是必須的,但是是在絕大多數情況下,占用最多也是最重要的一個屬性。它可以理解class文件的具體數據內容。 javap -verbose testclass 輸出class文件的字節碼。
exceptions屬性,用於異常處理。
linenumbertable屬性,用於描述java源碼行號與字節碼行號,便於排錯。
localveriabletable,用於描述棧幀中局部變量表中的變量與java源碼中定義的變量之間的關系,也用於排錯。
sourcefile屬性,記錄生成這個class文件的源碼文件名稱。
constantvalue,為靜態變量賦值。
stackmaptable,在類加載的字節碼驗證階段,被新類型檢查驗證器使用,用於替代類型推到器。
signature,比如,泛型被擦除后,該標識保留了泛型數據下來。
bootstrapmethods屬性。
字節碼指令,這個就沒多大作用了,稍微理解下就好。
第7章 虛擬機類加載機制
類從被加載到虛擬機內存中開始,到卸載出內存為止,它的整個生命周期包括:加載、驗證、准備、解析、初始化、使用和卸載七個階段。
類加載器。通過一個類的全局限定名來獲取此類的二進制字節流讓用戶自己實現,以便應用程序自己決定如何去獲取所需要的類。
雙親委派模型。簡單的說就是,優先請求父類加載器,再用子加載器加載。
其實東西很多,要用千把個字描寫完內容,還是太唐突了。
下一章,未完待續。。。