1. 程式人生 > >JVM虛擬機基礎知識

JVM虛擬機基礎知識

java方法 並行 函數調用 bag resources 棧內存 加鎖 ogr 11.2

1. Java的發展

Java之父:詹姆斯·高斯林

2. Java的技術體系

  1. Java 程序設計語言
  2. JVM
  3. class文件格式
  4. 編譯器
  5. Java API
  6. 第三方Java類庫

Java SE(Java Standard edition)
Java ME(Micro Edition)
Java EE(Java Enterprise Edition)

3. JVM的安裝

                                                                                   

4. JDK、JRE、JVM的關系

JDK(Java Development Kit)
JRE(Java Runtime Environment)
JVM(Java Virtual Machine)

官方結構圖:https://docs.oracle.com/javase/8/docs/

5.Java8的新特性

  1. 引入lambda表式式
  2. Nashorn JavaScript引擎,使用Metaspace 代替PermGen space
  3. Date API
  4. 更好的類型判斷

6.Java 虛擬機產品

  1. Sun Classic VM :第一款商用虛擬機,只能使用純解釋器的方式來執行Java代碼。已被淘汰
  2. Exact VM (Exact Memory Management) : 編譯器和解釋器混合工作以及兩級及時編譯器,只在solaris平臺發布
  3. HotSpot VM: Longview Technologies-->SUN-->Oracle
  4. KVM(Kilobyte): 簡單、輕量、高度可移植,在手機平臺運行。運行速度慢
  5. JRockit: BEA--> Oracle,專註服務端應用,優勢:垃圾收集器+MissionControl服務套件
  6. J9( IBM Technology for Java Virtual Machine IT4j ): IBM公司開發,用於IBM的產品
  7. dalvik: Google公司設計,Android平臺核心組成部分之一
  8. Mircosoft JVM:
  9. Azul VM: 高性能,HotSpot 基礎上改進
  10. Liquid VM: 高性能,BEA公司開發,本身相當於一個操作系統
  11. TaobaoVM: 根據OpenJDK深度定制

    7.JVM內存管理

    運行時數據區

    1. 線程共享區

    1.1. 方法區

  12. 保存類的元數據
  13. 元數據包括類型信息、常量池、域信息、方法信息
  14. 在HotSpot虛擬機中,方法區也被成為永久區
  15. 雖然叫做永久區,但是在永久區的對象也可以被GC回收

1.1.1 運行時常量池

  1. 方法區的一部分
  2. 用於存放編譯器生成的各種字面量和符號引用

    1.2. Java堆

  3. 存放對象實例
  4. 垃圾收集器管理的主要區域
  5. 新生代、老年代
  6. OutofMemoryError:內存溢出

    2. 線程獨占區

    2.1. Java虛擬機棧

  7. 描述的是Java方法執行的動態內存模型
  8. Java虛擬機棧主要被用來存放基本類型的變量,如:int、short、long、byte、float、double、boolea、char、對象引用
  9. StackoverflowError: 棧內存溢出,可以使用-XSS指定虛擬機棧的大小,棧的大小決定了函數調用的最大可達深度
  10. 虛擬機棧為虛擬機執行Java方法

    2.2. 本地方法棧(Native Method Stacks)

  11. 本地方法棧用來執行Native方法

    2.3. 程序計數器(Program Counter Register)

  12. 每一個線程都有一個獨立的程序計數器,用來記錄下一條需要執行的計算機指令
  13. 程序計數器是線程獨有的一塊內存空間。這塊內存是線程私有,生命周期與線程保持一致
  14. 如果當前線程正在執行一個Java方法,則程序計數器記錄正在執行的Java字節碼地址,如果當前線程正在執行一個本地方法,則程序計數器為空
  15. 唯一一個在Java虛擬機中內有規定任何OutofMemoryError情況的區域

8. 對象

8.1 對象的創建

1.給對象分配內存的方式

  1. 指針碰撞
  2. 空閑列表

    2. 線程的安全性問題

  3. 線程同步(需要加鎖,效率低)
  4. 本地線程分配緩沖

    3. 初始化對象

    4. 執行構造方法

8.2對象的結構:

1.自身運行時數據(Mark Word)

  • 哈希值
  • GC分代年齡
  • 鎖狀態標識
  • 線程持有的鎖
  • 偏向線程ID
  • 偏向時間戳
    占用的空間:32位機器:32bit;64位機器:64bit
  1. 類型指針

    2.InstanceData

    3.Padding

    8.3 對象的訪問定位

    1.使用句柄
    2.直接指針

9.垃圾回收

9.1 如何判斷對象為垃圾對象?

  1. 引用計數法
    在對象中添加一個引用計數器,當有地方引用這個對象時計數器的值就+1,當引用失效時,計數器的值就-1
    弊端:當對象循環引用時不能識別是否為垃圾對象
    *基本沒有JVM在使用
  2. 可達性分析法
    作為GCroot的對象
    • 虛擬機棧
    • 方法區的類屬性所引用的對象
    • 方法區中常量所引用的對象
    • 本地方法棧中引用的對象

JDK8使用的垃圾回收器: parallel

9.2 回收算法

  1. 標記-清除算法
    通過可達性分析法標記-->清楚
    缺點:效率較低、空間問題(出現很多不連續的內存空間)
  2. 復制算法
    把使用中的內存復制一份重新按順序排列
    缺點:內存只能用一半,不適用於老年代
  3. 標記-整理算法
    讓所有存活的對象都向一端移動,然後清理掉邊界以外的內存
  4. 分代收集算法

  • 新生代
    • Eden 伊甸園
    • Survivor 存活區
    • Tenured Gen
  • 老年代

9.3 垃圾收集器

1. serial收集器

  1. 歷史最悠久
  2. 使用復制算法
  3. 單線程,垃圾收集時必須暫停其他所有的工作線程,直到收集結束
  4. 虛擬機運行在Client模式下的新生代收集器
  5. 用於桌面應用

2. ParNew收集器

  1. 多線程收集
  2. 虛擬機運行在Server模式下首選的新生代收集器

3. parallel Scavenge收集器

  1. 適用復制算法(新生代內存)
  2. 多線程收集器
  3. 達到可控制的吞吐量=運行用戶代碼時間/(運行用戶代碼時間+垃圾收集時間)
  4. -XX:MaxGCPauseMillis 垃圾收集器停頓時間
  5. -XX:GCTimeRatio 吞吐量大小 (0-100)

4. cms(Concurrent Mark Sweep)收集器

  1. 運作步驟
    標記清除--並發標記--重新標記--並發清除
  2. 優點
    • 並發收集
    • 低停頓
  3. 缺點
    • 占用大量的CPU資源
    • 無法處理浮動垃圾
    • 出現Concurrent Mode Failure
    • 基於標記清除算法,會產生大料的空間碎片

      5. G1(Garbage-First)收集器

面向服務端應用的垃圾收集器
優勢:

  1. 並行與並發, 使用多個CPU來縮短Stop-The-Word停頓時間
  2. 分代收集
  3. 空間整合:整體上看基於標記-整理算法,局部上看基於復制算法
  4. 可預測停頓

運作步驟:

  1. 初始標記
  2. 並發標記
  3. 最終標記
  4. 篩選回收 Remembered Set

10 . 內存分配

10.1 優先分配到Eden區

10.2 大對象直接進入老年代

10.3長期存活的對象進入老年代

10.4 空間分配擔保

10.5 動態對象的年齡判斷

11. JVM工具

https://docs.oracle.com/javase/8/docs/technotes/tools/index.html#monitor

11.1 jps (Java Process Status)

jenkins@ubuntu-OptiPlex-7040:~$ jps
13154 Bootstrap
12191 Jps

參數:

# -l :虛擬機執行主類名稱或者jar包的名稱
jenkins@ubuntu-OptiPlex-7040:~$ jps  -l
13154 org.apache.catalina.startup.Bootstrap
12462 sun.tools.jps.Jps
# -m :主類接收的參數
jenkins@ubuntu-OptiPlex-7040:~$ jps  -m
13154 Bootstrap start
12552 Jps -m
# -v :JVM接收的參數
jenkins@ubuntu-OptiPlex-7040:~$ jps  -v
13154 Bootstrap -Djava.util.logging.config.file=/home/jenkins/tomcat/jenkins/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djdk.tls.ephemeralDHKeySize=2048 -Djava.protocol.handler.pkgs=org.apache.catalina.webresources -Dorg.apache.catalina.security.SecurityListener.UMASK=0027 -Dignore.endorsed.dirs= -Dcatalina.base=/home/jenkins/tomcat/jenkins -Dcatalina.home=/home/jenkins/tomcat/jenkins -Djava.io.tmpdir=/home/jenkins/tomcat/jenkins/temp
12675 Jps -Denv.class.path=.:/home/ubuntu/software/jdk/jdk1.8.0_151/lib:/home/ubuntu/software/jdk/jdk1.8.0_151/jre/lib -Dapplication.home=/home/ubuntu/software/jdk/jdk1.8.0_151 -Xms8m

11.2 jstat

虛擬機統計信息監控:類裝載、內存、垃圾收集、JIT編譯等運行數據

11.3 jinfo

實時查看和調整虛擬機各項參數

11.4 jmap

生產堆轉儲快照

$ jmap -dump:format=b,file=jenkins.bin 13154
Dumping heap to /home/jenkins/jenkins.bin ...
Heap dump file created

-XX:+HeapDumpOnOutofMemoryError : 虛擬機在OOM異常出現後自動生成dump文件

# 顯示堆中對象通信信息
$ jmap -histo 13154 | less

11.5 jhat

功能:分析jamp生成的堆轉儲快照
一般不會在生產服務器上進行分析,非常耗CPU和內存,不常用

jenkins@ubuntu-OptiPlex-7040:~$ jhat jenkins.bin 
Reading from jenkins.bin...
Dump file created Thu Feb 14 11:43:45 CST 2019
Snapshot read, resolving...
Resolving 12022774 objects...
Chasing references, expect 2404 
dots
Eliminating duplicate references
Snapshot resolved.
Started HTTP server on port 7000
Server is ready.

瀏覽器訪問http://ip:7000 查看分析結果

11.7 jstack

功能: 生成虛擬機當前時刻的線程快照,用來定位線程出現長時間停頓的原因,如線程見死鎖、死循環、請求外部資源導致的長時間等待等

jstack -l 13154

11.8 jconsole

  1. 內存監控
  2. 線程監控
  3. 死鎖

    11.9 jvisualvm

12. 性能調優

調優需要的技能:

  1. 知識
  2. 工具
  3. 數據
  4. 經驗

JVM虛擬機基礎知識