JVM入門

面試問題:

請談談你對JVM的理解?java8版有什麼瞭解?java

談談JVM中你對ClassLoader類加載器的認識?面試

什麼是OOM?寫代碼使得分別出現StackOverflowError和OutOfMemoryError編程

package com.mikey.demo;

/**
 * @Program: TestJvm
 * @Author: 麥奇
 * @Email: 1625017540@qq.com
 * @Create: 2019-04-06 11:19
 * @Describe:
 **/
public class TestDemoSteakOverFlow {
    public static void main(String[] args){

        sayHello();

    }

    private static void sayHello() {
        sayHello();
    }
}
TestDemoSteakOverFlow
package com.mikey.demo;

import java.util.Random;

/**
 * @Program: TestJvm
 * @Author: 麥奇
 * @Email: 1625017540@qq.com
 * @Create: 2019-04-06 12:12
 * @Describe:
 **/
public class TestOutOfMemoryErrorDemo {
    public static void main(String[] args){

        String str="mikey";

        while (true){
            str+=str+new Random().nextInt(88888)+new Random().nextInt(999999999);
        }

    }
}
TestOutOfMemoryErrorDemo
2019-04-06 12:16:12
Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.201-b09 mixed mode):

"Service Thread" #9 daemon prio=9 os_prio=0 tid=0x00007f8f5c1f3000 nid=0x776d runnable [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"C1 CompilerThread2" #8 daemon prio=9 os_prio=0 tid=0x00007f8f5c1ee000 nid=0x776c waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"C2 CompilerThread1" #7 daemon prio=9 os_prio=0 tid=0x00007f8f5c1ec800 nid=0x776b waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"C2 CompilerThread0" #6 daemon prio=9 os_prio=0 tid=0x00007f8f5c1ea800 nid=0x776a waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"Monitor Ctrl-Break" #5 daemon prio=5 os_prio=0 tid=0x00007f8f5c1e8800 nid=0x7769 runnable [0x00007f8f40f9d000]
   java.lang.Thread.State: RUNNABLE
    at java.net.SocketInputStream.socketRead0(Native Method)
    at java.net.SocketInputStream.socketRead(SocketInputStream.java:116)
    at java.net.SocketInputStream.read(SocketInputStream.java:171)
    at java.net.SocketInputStream.read(SocketInputStream.java:141)
    at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:284)
    at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:326)
    at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:178)
    - locked <0x00000006c99cbbd0> (a java.io.InputStreamReader)
    at java.io.InputStreamReader.read(InputStreamReader.java:184)
    at java.io.BufferedReader.fill(BufferedReader.java:161)
    at java.io.BufferedReader.readLine(BufferedReader.java:324)
    - locked <0x00000006c99cbbd0> (a java.io.InputStreamReader)
    at java.io.BufferedReader.readLine(BufferedReader.java:389)
    at com.intellij.rt.execution.application.AppMainV2$1.run(AppMainV2.java:64)

"Signal Dispatcher" #4 daemon prio=9 os_prio=0 tid=0x00007f8f5c181800 nid=0x7768 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"Finalizer" #3 daemon prio=8 os_prio=0 tid=0x00007f8f5c14f000 nid=0x7767 in Object.wait() [0x00007f8f41b6e000]
   java.lang.Thread.State: WAITING (on object monitor)
    at java.lang.Object.wait(Native Method)
    - waiting on <0x00000006c99d9920> (a java.lang.ref.ReferenceQueue$Lock)
    at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:144)
    - locked <0x00000006c99d9920> (a java.lang.ref.ReferenceQueue$Lock)
    at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:165)
    at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:216)

"Reference Handler" #2 daemon prio=10 os_prio=0 tid=0x00007f8f5c14c800 nid=0x7766 in Object.wait() [0x00007f8f41c6f000]
   java.lang.Thread.State: WAITING (on object monitor)
    at java.lang.Object.wait(Native Method)
    - waiting on <0x00000006c99d9b50> (a java.lang.ref.Reference$Lock)
    at java.lang.Object.wait(Object.java:502)
    at java.lang.ref.Reference.tryHandlePending(Reference.java:191)
    - locked <0x00000006c99d9b50> (a java.lang.ref.Reference$Lock)
    at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:153)

"main" #1 prio=5 os_prio=0 tid=0x00007f8f5c00d800 nid=0x7756 runnable [0x00007f8f6329b000]
   java.lang.Thread.State: RUNNABLE
    at java.util.Arrays.copyOf(Arrays.java:3332)
    at java.lang.AbstractStringBuilder.ensureCapacityInternal(AbstractStringBuilder.java:124)
    at java.lang.AbstractStringBuilder.append(AbstractStringBuilder.java:448)
    at java.lang.StringBuilder.append(StringBuilder.java:136)
    at com.mikey.demo.TestOutOfMemoryErrorDemo.main(TestOutOfMemoryErrorDemo.java:18)

"VM Thread" os_prio=0 tid=0x00007f8f5c142800 nid=0x7765 runnable 

"GC task thread#0 (ParallelGC)" os_prio=0 tid=0x00007f8f5c023000 nid=0x775b runnable 

"GC task thread#1 (ParallelGC)" os_prio=0 tid=0x00007f8f5c025000 nid=0x775c runnable 

"GC task thread#2 (ParallelGC)" os_prio=0 tid=0x00007f8f5c026800 nid=0x775d runnable 

"GC task thread#3 (ParallelGC)" os_prio=0 tid=0x00007f8f5c028800 nid=0x7761 runnable 

"VM Periodic Task Thread" os_prio=0 tid=0x00007f8f5c1f6000 nid=0x776e waiting on condition 

JNI global references: 12

Heap
 PSYoungGen      total 139264K, used 121149K [0x000000076d180000, 0x000000077e180000, 0x00000007c0000000)
  eden space 129024K, 93% used [0x000000076d180000,0x00000007747cf630,0x0000000774f80000)
  from space 10240K, 0% used [0x0000000774f80000,0x0000000774f80000,0x0000000775980000)
  to   space 10240K, 0% used [0x000000077d780000,0x000000077d780000,0x000000077e180000)
 ParOldGen       total 2103808K, used 2050101K [0x00000006c7400000, 0x0000000747a80000, 0x000000076d180000)
  object space 2103808K, 97% used [0x00000006c7400000,0x000000074460d688,0x0000000747a80000)
 Metaspace       used 3023K, capacity 4496K, committed 4864K, reserved 1056768K
  class space    used 330K, capacity 388K, committed 512K, reserved 1048576K

Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
    at java.util.Arrays.copyOf(Arrays.java:3332)
    at java.lang.AbstractStringBuilder.ensureCapacityInternal(AbstractStringBuilder.java:124)
    at java.lang.AbstractStringBuilder.append(AbstractStringBuilder.java:674)
    at java.lang.StringBuilder.append(StringBuilder.java:208)
    at com.mikey.demo.TestOutOfMemoryErrorDemo.main(TestOutOfMemoryErrorDemo.java:18)

Process finished with exit code 1
Error Message

JVM的經常使用參數調優你瞭解嗎?app

內存快照抓取和MAT分析hprof文件幹過嗎?dom

JVM體系結構概述

jvm位置:

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

JVM體系結構概覽:

類裝載器ClassLoader

負責加載class文件,class文件在文件開頭有特定的文件標示,而且ClassLoader只負責class文件的加載,至於它是否能夠運行,則由Execution Engine決定 

類裝載器ClassLoader2

虛擬機自帶的加載器
啓動類加載器(Bootstrap)C++
擴展類加載器(Extension)Java
應用程序類加載器(App)Java
也叫系統類加載器,加載當前應用的classpath的全部類

用戶自定義加載器  Java.lang.ClassLoader的子類,用戶能夠定製類的加載方式

 

 

類裝載器ClassLoader3

Code案例

sun.misc.Launcher
它是一個java虛擬機的入口應用

某個特定的類加載器在接到加載類的請求時,首先將加載任務委託給父類加載器,依次遞歸,若是父類加載器能夠完成類加載任務,就成功返回;只有父類加載器沒法完成此加載任務時,才本身去加載。

 

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

 

 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等等,很少作介紹。

 

Native Method Stack

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

PC寄存器

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

 

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

 

 

Exception in thread "main" java.lang.StackOverflowError

方法區

1:方法區是線程共享的,一般用來保存裝載的類的元結構信息。
好比:運行時常量池+靜態變量+常量+字段+方法字節碼+在類/實例/接口初始化用到的特殊方法等。

2:一般和永久區關聯在一塊兒(Java7以前),但具體的跟JVM的實現和版本有關。

 

堆體系結構概述

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)代碼中建立了大量大對象,而且長時間不能被垃圾收集器收集(存在被引用)。
新生區

 

堆參數調優入門

 Java7

 

 

 Java8

 JDK 1.8以後將最初的永久代取消了,由元空間取代。編程語言

(堆內存調優簡介01)

 

 

 

public static void main(String[] args){
long maxMemory = Runtime.getRuntime().maxMemory() ;//返回 Java 虛擬機試圖使用的最大內存量。
long totalMemory = Runtime.getRuntime().totalMemory() ;//返回 Java 虛擬機中的內存總量。
System.out.println("MAX_MEMORY = " + maxMemory + "(字節)、" + (maxMemory / (double)1024 / 1024) + "MB");
System.out.println("TOTAL_MEMORY = " + totalMemory + "(字節)、" + (totalMemory / (double)1024 / 1024) + "MB");
}
View Code

 (堆內存調優簡介02)

發現默認的狀況下分配的內存是總內存的「1 / 4」、而初始化的內存爲「1 / 64」ide

VM參數:    -Xms1024m -Xmx1024m -XX:+PrintGCDetails

(堆內存調優簡介03)此圖爲java7,演示爲8

 

(堆內存調優簡介04)

 

String str = "www.atguigu.com" ;
while(true) 
{
str += str + new Random().nextInt(88888888) + new Random().nextInt(999999999) ;
}
View Code

 

VM參數:-Xms8m -Xmx8m -XX:+PrintGCDetails

 

 

 

 

 

 

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

 

 

-Xms1m -Xmx8m -XX:+HeapDumpOnOutOfMemoryError

相關文章
相關標籤/搜索