1. 程式人生 > >JVM相關知識

JVM相關知識

圖片 mit import etc sta 分享圖片 color 啟動 技術

1.概述

JVM是運行在操作系統之上的,它與硬件沒有直接的交互

技術分享圖片

技術分享圖片

1.1類裝載器ClassLoader

負責加載class文件,class文件在文件開頭有特定的文件標示,

並且ClassLoader只負責class文件的加載,至於它是否可以運行,則由Execution Engine決定

技術分享圖片

1.2類加載器分類

虛擬機自帶的加載器
  啟動類加載器(Bootstrap)C++
  擴展類加載器(Extension)Java
  應用程序類加載器(App)Java,也叫系統類加載器,加載當前應用的classpath的所有類
用戶自定義加載器

  Java.lang.ClassLoader的子類,用戶可以定制類的加載方式,

技術分享圖片

package com.zy;

import org.junit.Test;

public class JvmDemo01 {

    @Test
    public void fn01(){
        Object obj = new Object();
        ClassLoader classLoader = obj.getClass().getClassLoader();
        System.out.println("Object對象的類加載器即BootstrapClassLoader是:"+classLoader);
        JvmDemo01 jvm 
= new JvmDemo01(); ClassLoader classLoader1 = jvm.getClass().getClassLoader(); System.out.println("應用程序類加載器即ApplicationClassLoader是:"+classLoader1); System.out.println("應用程序類加載器的父類加載器即ExtensionClassLoader是:"+classLoader1.getParent()); System.out.println("擴展類加載器的父類加載器即BootstrapClassLoader是:"+classLoader1.getParent().getParent()); } }

1.3雙親委派模型

sun.misc.Launcher
它是一個java虛擬機的入口應用
某個特定的類加載器在接到加載類的請求時,首先將加載任務委托給父類加載器,依次遞歸,
如果父類加載器可以完成類加載任務,就成功返回;
只有父類加載器無法完成此加載任務時,才自己去加載。

2.Execution Engine

Execution Engine執行引擎負責解釋命令,提交操作系統執行。

3.Native Interface本地接口
Java語言本身不能對操作系統底層進行訪問和操作,但是可以通過JNI接口調用其他語言來實現對底層的訪問。
本地接口的作用是融合不同的編程語言為Java所用,它的初衷是融合 C/C++程序,Java誕生的時候是C/C++橫行的時候,
要想立足,必須有調用C/C++程序,於是就在內存中專門開辟了一塊區域處理標記為Native的代碼,它的具體做法是Native Method Stack中登記Native方法,
在Execution Engine 執行時加載Native libraries。
目前該方法使用的越來越少了,除非是與硬件有關的應用,比如通過Java程序驅動打印機或者Java系統管理生產設備,在企業級應用中已經比較少見。
因為現在的異構領域間的通信很發達,比如可以使用Socket通信,也可以使用WebService等等。

4.Native Method Stack
它的具體做法是Native Method Stack中登記native方法,在Execution Engine執行時加載本地方法庫。

5.PC寄存器
每個線程都有一個程序計數器,是線程私有的,就是一個指針,指向方法區中的方法字節碼(用來存儲指向下一條指令的地址,也即將要執行的指令代碼),
由執行引擎讀取下一條指令,是一個非常小的內存空間,幾乎可以忽略不記。

6.棧

棧也叫棧內存,主管Java程序的運行,是在線程創建時創建,它的生命期是跟隨線程的生命期,
線程結束棧內存也就釋放,對於棧來說不存在垃圾回收問題,只要線程一結束該棧就Over,生命周期和線程一致,是線程私有的。
基本類型的變量、實例方法、引用類型變量都是在函數的棧內存中分配。

7.方法區
7.1方法區是線程共享的,通常用來保存裝載的類的元結構信息。
比如:運行時常量池+靜態變量+常量+字段+方法字節碼+在類/實例/接口初始化用到的特殊方法等。
7.2通常和永久區關聯在一起(Java7之前),但具體的跟JVM的實現和版本有關。

8.Heap堆(Java7之前)
一個JVM實例只存在一個堆內存,堆內存的大小是可以調節的。
類加載器讀取了類文件後,需要把類、方法、常變量放到堆內存中,保存所有引用類型的真實信息,以方便執行器執行。
堆內存邏輯上分為三部分:新生+養老+永久

技術分享圖片

新生區是類的誕生、成長、消亡的區域,一個類在這裏產生,應用,最後被垃圾回收器收集,結束生命。
新生區又分為兩部分: 伊甸區(Eden space)幸存者區(Survivor pace) ,所有的類都是在伊甸區被new出來的。
幸存區有兩個: 0區(Survivor 0 space)1區(Survivor 1 space)
當伊甸園的空間用完時,程序又需要創建對象,JVM的垃圾回收器將對伊甸園區進行垃圾回收(Minor GC),將伊甸園區中的不再被其他對象所引用的對象進行銷毀。
然後將伊甸園中的剩余對象移動到幸存0區.若幸存0區也滿了,再對該區進行垃圾回收,然後移動到1區。
那如果1區也滿了呢?再移動到養老區。
若養老區也滿了,那麽這個時候將產生MajorGC(FullGC),進行養老區的內存清理。
若養老區執行了Full GC之後發現依然無法進行對象的保存,就會產生OOM異常“OutOfMemoryError”。

如果出現java.lang.OutOfMemoryError: Java heap space異常,說明Java虛擬機的堆內存不夠。原因有二:
(1)Java虛擬機的堆內存設置不夠,可以通過參數-Xms、-Xmx來調整。
(2)代碼中創建了大量大對象,並且長時間不能被垃圾收集器收集(存在被引用)。

9.Java堆內存參數調優

jdk-7如下:

技術分享圖片

jdk-8如下:

技術分享圖片

8.1jvm中默認堆內存

技術分享圖片

    @Test
    public void fn02(){
        double maxMemory = Runtime.getRuntime().maxMemory();
        double totalMemory = Runtime.getRuntime().totalMemory();
        System.out.println("JVM中默認totalMemory(初始內存分配大小)的值(-Xms)是:"+totalMemory / 1024 / 1024 + "MB");
        System.out.println("JVM中默認maxMemory(最大內存分配大小)的值(-Xmx)是:"+maxMemory / 1024 / 1024 + "MB");
    }

設置VM參數

-Xmx1024m -Xms200m -XX:+PrintGCDetails

技術分享圖片

打印效果如下:(此處是JDK-8)

JVM中默認totalMemory(初始內存分配大小)的值(-Xms)是:192.0MB
JVM中默認maxMemory(最大內存分配大小)的值(-Xmx)是:910.5MB
Heap
 PSYoungGen      total 59904K, used 8297K [0x00000000eab00000, 0x00000000eed80000, 0x0000000100000000)
  eden space 51712K, 16% used [0x00000000eab00000,0x00000000eb31a640,0x00000000edd80000)
  from space 8192K, 0% used [0x00000000ee580000,0x00000000ee580000,0x00000000eed80000)
  to   space 8192K, 0% used [0x00000000edd80000,0x00000000edd80000,0x00000000ee580000)
 ParOldGen       total 136704K, used 0K [0x00000000c0000000, 0x00000000c8580000, 0x00000000eab00000)
  object space 136704K, 0% used [0x00000000c0000000,0x00000000c0000000,0x00000000c8580000)
 Metaspace       used 5239K, capacity 5424K, committed 5632K, reserved 1056768K
  class space    used 610K, capacity 659K, committed 768K, reserved 1048576K

8.2out of memory問題解決(OOM)

VM參數設置:

-XX:+HeapDumpOnOutOfMemoryError
OOM時導出堆到hprof文件。

JVM相關知識