欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

java虛擬機運行時數(shù)據(jù)區(qū)分析

 更新時間:2017年11月22日 16:57:07   作者:u012941811  
這篇文章主要介紹了java虛擬機運行時數(shù)據(jù)區(qū)分析,具有一定參考價值,需要的朋友可以了解下。

JVMmemorymodel

這篇文章主要介紹在JVM規(guī)范中描述的運行時數(shù)據(jù)區(qū)(RuntimeDataAreas)。這些區(qū)域設(shè)計用來存儲被JVM自身或者在JVM上運行的程序所是用的數(shù)據(jù)。

我們先總覽JVM,然后介紹下字節(jié)碼,最后介紹不同的數(shù)據(jù)區(qū)域。

總覽

JVM作為操作系統(tǒng)的抽象,保證同樣的代碼在不同的硬件或操作系統(tǒng)上的行為一致。

比如:

對于基本類型int,無論在16位/32位/64位操作系統(tǒng)上,都是一個32位有符號整數(shù)。范圍從-2^31到2^31-1

無論操作系統(tǒng)或者硬件是大字節(jié)序還是小字節(jié)序,保證JVM存儲和使用的內(nèi)存中的數(shù)據(jù)都是大字節(jié)序(先讀高位字節(jié))

不同的JVM實現(xiàn)可能會有些區(qū)別,但大體上是相同的。

上圖是一個JVM的總覽

JVM解釋編譯器生成的字節(jié)碼。雖然JVM是Java虛擬機的縮寫,但是只要是能夠編譯為字節(jié)碼的語言,都可以基于JVM運行,比如 scala、groovy<喎�"/kf/ware/vc/" target="_blank" class="keylink">vcD4NCjxwPs6qwcux3MPixrW3sbXEtMXFzEkvT6Os19a92sLru+Gxu2NsYXNzbG9hZGVyvNPU2LKiu7q05rW91MvQ0Mqxyv2+3cf41tC1xNK7uPbH+NPyo6zWqrXAvNPU2Mv8tcRjbGFzc2xvYWRlcrG7z/q72bvy1d9KVk3No9a51MvQ0KGjPC9wPg0KPHA+vNPU2LXE19a92sLrzai5/da00NDS/cfmKGV4ZWN1dGlvbiBlbmdpbmUpvfjQ0L3iys26zda00NA8L3A+DQo8cD7WtNDQ0v3H5tDo0qq05rSis8zQ8snPz8LOxKOsscjI57PM0PLWtNDQtb3ExNK70NCjrLvy1d/K/b7dvMbL47XE1tC85L3hufs8L3A+DQo8cD7WtNDQ0v3H5tKyuLrU8LSmwO3T67XXsuOy2df3z7XNs7XEvbu7pTwvcD4NCjxwPioquty24EpWTba8yrXP1sHLvLTKsbHg0uu5psTcKEpJVD1qdXN0IGluIHRpbWUpoaNKSVS+zcrHsNG+rbOj1rTQ0LXEtPrC6yjIyLXjtPrC6ymx4NLrs8mxvrXYtPrC6yhOYXRpdmUgQ29kZSmho7Tmt8VKSVSx4NLryfqzybT6wuu1xMf40/Kzxs6qPC9wPg0KPHA+tPrC67u6tObH+ChDb2RlIENhY2gpoaO8tMqxseDS67y8yvUoSklUKby2tPO1xMzhuN/By0pWTbXE0NTE3CoqPC9wPg0KPGgyIGlkPQ=="基于棧stack的架構(gòu)">基于棧(stack)的架構(gòu)

JVM使用基于棧的架構(gòu)。雖然棧對于開發(fā)者是透明的,但是棧對于生成的字節(jié)碼和JVM都有很重要的作用或者說影響。

我們開發(fā)的程序,會轉(zhuǎn)換位低級別的操作,存于字節(jié)碼中。在JVM中通過操作數(shù)(operand)映射到操作指令。按照J(rèn)VM規(guī)范,操作指令需要的參數(shù)是從操作數(shù)棧獲得的(the operand stack)。

舉個兩個數(shù)相加的例子。這這個操作稱為 iadd 。下面是在字節(jié)碼中 3+4 的過程

首先把3和4壓入操作數(shù)棧

調(diào)用 iadd 指令

iadd 指令會從操作數(shù)棧頂彈出2個數(shù)

3+4的結(jié)果壓入操作數(shù)棧,供后面使用

這種方式被稱為基于棧的架構(gòu)。還有其他的方式可以處理低級別操作,比如基于寄存器的架構(gòu)(register based architecture)。

字節(jié)碼

java字節(jié)碼是java源碼轉(zhuǎn)換為一系列低級別操作的結(jié)果。每個操作由一個字節(jié)長度的操作碼(opcode or operation code)和零或多個字節(jié)長度的參數(shù)(但是大多數(shù)操作使用的參數(shù)都是通過操作數(shù)棧獲取的)組成。一個字節(jié)可以表示256個數(shù),從0x00到0xff,目前到j(luò)ava8,共使用了204個。

下面列出不同種類的字節(jié)碼操作碼以及其范圍和簡單的描述

Constants: 將常量池的值或者已知的值壓入操作數(shù)棧。 0x00 - 0x14

Loads: 將局部變量值壓入操作數(shù)棧。 0x15 - 0x35

Stores: 從操作數(shù)棧加載值賦給局部變量 0x36 - 0x56

Stack: 處理操作數(shù)棧 0x57 - 0x5f

Math: 從操作數(shù)棧獲取值進(jìn)行基本的數(shù)學(xué)計算 0x60 - 0x84

Conversions: 進(jìn)行類型之間的轉(zhuǎn)換 0x85 - 0x 93

Comaprisons: 兩個值的比較操作 0x94 - 0xa6

Controls: 執(zhí)行g(shù)oto、return、循環(huán)等等控制操作 0xa7 - 0xb1

References: 執(zhí)行分配對象或數(shù)組,獲取或檢查 對象、方法、靜態(tài)方法的引用。也可以調(diào)用靜態(tài)方法。 0xb2 - oxc3

Extended: Extended: operations from the others categories that were added after. From value 0xc4 to 0xc9

(這句說不好什么意思。。。)

Reserved: JVM實現(xiàn)內(nèi)部是用的槽子0xca,oxfe,oxff

這204個操作都很簡單,舉幾個例子

ifeq(0x99) 判斷兩個值是否相等

iadd(0x60) 把兩個數(shù)相加

i2l (0x85) 把一個int 轉(zhuǎn)換位 long

arraylength (0xbe) 返回數(shù)組長度

pop (0x57) 從操作數(shù)棧頂彈出一個值

我們需要編譯器來創(chuàng)建字節(jié)碼文件,標(biāo)準(zhǔn)的java編譯器就是jdk中的 javac。

public class Test {
 
 public static void main(String[] args) {
  int a =1;
  int b = 15;
  int result = add(a,b);
 }
 
 public static int add(int a, int b){
  int result = a + b;
  return result;
 }
}

通過“javac Test.java” 可以得到 “Test.class”的字節(jié)碼文件。字節(jié)碼文件是2進(jìn)制的,我們可以通過javap,把二進(jìn)制的字節(jié)碼文件轉(zhuǎn)換成文本形式

java -verbose Test.class

Classfile /C:/TMP/Test.class
 Last modified 1 avr. 2015; size 367 bytes
 MD5 checksum adb9ff75f12fc6ce1cdde22a9c4c7426
 Compiled from "Test.java"
public class com.codinggeek.jvm.Test
 SourceFile: "Test.java"
 minor version: 0
 major version: 51
 flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
  #1 = Methodref     #4.#15     // java/lang/Object."<init>":()V
  #2 = Methodref     #3.#16     // com/codinggeek/jvm/Test.add:(II)I
  #3 = Class       #17      // com/codinggeek/jvm/Test
  #4 = Class       #18      // java/lang/Object
  #5 = Utf8        <init>
  #6 = Utf8        ()V
  #7 = Utf8        Code
  #8 = Utf8        LineNumberTable
  #9 = Utf8        main
 #10 = Utf8        ([Ljava/lang/String;)V
 #11 = Utf8        add
 #12 = Utf8        (II)I
 #13 = Utf8        SourceFile
 #14 = Utf8        Test.java
 #15 = NameAndType    #5:#6     // "<init>":()V
 #16 = NameAndType    #11:#12    // add:(II)I
 #17 = Utf8        com/codinggeek/jvm/Test
 #18 = Utf8        java/lang/Object
{
 public com.codinggeek.jvm.Test();
  flags: ACC_PUBLIC
  Code:
   stack=1, locals=1, args_size=1
     0: aload_0
     1: invokespecial #1         // Method java/lang/Object."<init>":()V
     4: return
   LineNumberTable:
    line 3: 0
 
 public static void main(java.lang.String[]);
  flags: ACC_PUBLIC, ACC_STATIC
  Code:
   stack=2, locals=4, args_size=1
     0: iconst_1
     1: istore_1
     2: bipush    15
     4: istore_2
     5: iload_1
     6: iload_2
     7: invokestatic #2         // Method add:(II)I
    10: istore_3
    11: return
   LineNumberTable:
    line 6: 0
    line 7: 2
    line 8: 5
    line 9: 11
 
 public static int add(int, int);
  flags: ACC_PUBLIC, ACC_STATIC
  Code:
   stack=2, locals=3, args_size=2
     0: iload_0
     1: iload_1
     2: iadd
     3: istore_2
     4: iload_2
     5: ireturn
   LineNumberTable:
    line 12: 0
    line 13: 4
}

可以看出字節(jié)碼不只是java代碼的簡單翻譯,它包括:

類的常量池(cosntant pool)描述。常量池是用于存儲類元數(shù)據(jù)的JVM數(shù)據(jù)區(qū)域,比如類內(nèi)部的方法名,參數(shù)列表,等等。當(dāng)JVM加載一個類的時候,這些元數(shù)據(jù)就會加載到常量池

通過行號表和或局部變量表來提供函數(shù)和天貓的變量在字節(jié)碼中的具體位置信息

java代碼的翻譯(包括隱藏的父類構(gòu)造)

提供更具體的對于操作數(shù)棧的操作和更完整的傳遞和獲取參數(shù)的方式

下面是一個簡單的字節(jié)碼文件存儲信息的描述

ClassFile {
 u4 magic;
 u2 minor_version;
 u2 major_version;
 u2 constant_pool_count;
 cp_info constant_pool[constant_pool_count-1];
 u2 access_flags;
 u2 this_class;
 u2 super_class;
 u2 interfaces_count;
 u2 interfaces[interfaces_count];
 u2 fields_count;
 field_info fields[fields_count];
 u2 methods_count;
 method_info methods[methods_count];
 u2 attributes_count;
 attribute_info attributes[attributes_count];
}

運行時數(shù)據(jù)區(qū)

運行時數(shù)據(jù)區(qū)是存儲數(shù)據(jù)的內(nèi)存區(qū)域設(shè)計。這些數(shù)據(jù)供開發(fā)者或JVM內(nèi)部使用。

堆(Heap)

堆 在JVM啟動的時候創(chuàng)建,由所有的JVM線程所共享。所有的類實例、數(shù)組都分配到堆(由new所創(chuàng)建的)。

堆必須由一個垃圾收集器來管理,垃圾收集器負(fù)責(zé)釋放被開發(fā)者所創(chuàng)建,并且不會再被使用到的對象。

至于垃圾收集的策略由JVM實現(xiàn)決定(比如HotSpot提供了多種算法).

堆內(nèi)存有一個最大值限制,如果超過這個值 JVM會拋出一個 OutOfMemroy異常

方法區(qū)(Method area)

方法區(qū)也是被JVM的所有線程所共享。同樣的隨JVM啟動被創(chuàng)建。方法區(qū)存儲的數(shù)據(jù)由classloader從字節(jié)碼中加載,這些數(shù)據(jù)會在應(yīng)用運行過程中一致存在,除非加載它們的classloader被銷毀或者JVM停止。

方法區(qū)存儲如下數(shù)據(jù):

類信息(屬性名、方法名、父類名、借口名、版本、等等)

方法和構(gòu)造的字節(jié)碼

加載每個類時創(chuàng)建的運行時常量池

JVM規(guī)范并不強迫在堆中實現(xiàn)方法區(qū)。在java7以前,HotSpot 使用一個稱為永久帶(PermGen)的區(qū)域?qū)崿F(xiàn)方法區(qū)。永久帶與堆相鄰(和堆一樣進(jìn)行內(nèi)存管理),默認(rèn)位64MB

從java8開始,HptSpot使用分離的本地內(nèi)存實現(xiàn)方法區(qū),起名元數(shù)據(jù)區(qū)(Metaspace)。元數(shù)據(jù)區(qū)最大可用空間即整個系統(tǒng)的可用內(nèi)存。

如果方法去申請不到可用內(nèi)存,JVM也會拋出OutOfMemoryError.

運行時常量池(Runtime constant pool)
運行時常量池是方法區(qū)的一部分。因為運行吃常量池對于元數(shù)據(jù)的重要性,java規(guī)范中在方法區(qū)之外單獨對其進(jìn)行了描述。運行時常量池會隨著加載的類和接口而增長。

常量池有點想傳統(tǒng)語言中的語法表。換句話說,當(dāng)調(diào)用一個類、方法或?qū)傩詴r,JVM通過運行時常量池來尋找這些數(shù)據(jù)在內(nèi)存中的真實地址。運行時常量池也包含字符串字面值或基本類型的常量

Stirng myString="This is a string litteral"
 
  static final int MY_CONSTANT = 2 ;

pc(程序計數(shù)器)寄存器(每個線程) The pc Register (Per Thread)
每個線程有自己的pc(程序計數(shù)器)寄存器,與線程創(chuàng)建是一同創(chuàng)建。每個線程在一個時間點上只能執(zhí)行一個方法,稱為該線程的當(dāng)前方法(current method)。pc寄存器包含JVM當(dāng)前在執(zhí)行指令(在方法區(qū))的地址。

如果當(dāng)前執(zhí)行的方法是本地方法(native),pc寄存器的值是undefined

虛擬機棧每個線程-java-virtual-machine-stacks-per-thread">虛擬機棧(每個線程) java virtual machine stacks (per thread)
虛擬機棧存儲多個幀,因此在描述棧前,我們先來看下幀

幀(frames)

幀是一個數(shù)據(jù)結(jié)構(gòu),幀包含表示線程正在執(zhí)行的當(dāng)前方法狀態(tài)的多個數(shù)據(jù):

操作數(shù)棧(Operand Stack): 之前已經(jīng)提到過,字節(jié)碼指令使用操作數(shù)棧來傳遞參數(shù)

局部變量數(shù)組(Local variable array): 這個數(shù)組包含當(dāng)前執(zhí)行方法的一個作用域內(nèi)的所有局部變量。這個數(shù)組可以包含基本類型、引用或者返回地址。局部變量數(shù)組的大小在編譯時就已經(jīng)確定。jvm在方法調(diào)用時使用局部變量傳遞參數(shù),被調(diào)方法的局部變量數(shù)組通過調(diào)用方法的操作數(shù)棧創(chuàng)建。

運行時常量池引用: 引用當(dāng)前類當(dāng)前被執(zhí)行方法的常量池。JVM使用常量池引用傳遞信號給真正的內(nèi)存引用。

棧(stack)

每個JVM線程都有一個私有的JVM棧,與線程同時創(chuàng)建。java虛擬機棧存儲幀。每次調(diào)用一個方法時,都會創(chuàng)建一個幀,并且壓入虛擬機棧。當(dāng)這個方法執(zhí)行完成時,這個幀也會銷毀(無論方法是正常執(zhí)行完成,還是拋出異常)

在一個線程執(zhí)行的過程中只有一個幀是可用的。這個幀稱為當(dāng)前幀(current frame)。

對局部變量和操作數(shù)棧的操作通常和當(dāng)前幀的引用一起。

我們再看一個加法的例子

public int add(int a, int b){
 return a + b;
}
 
public void functionA(){
// some code without function call
 int result = add(2,3); //call to function B
// some code without function call
}

在方法A內(nèi)部,A幀是當(dāng)前幀,位于虛擬機棧頂。在調(diào)用add方法開始時,創(chuàng)建一個新的幀B,并且壓入虛擬機棧。幀B成為新的當(dāng)前幀。

幀B的局部變量數(shù)組通過幀A的操作數(shù)棧中的數(shù)據(jù)填充。當(dāng)add方法結(jié)束在,幀B被銷毀,幀A重新成為當(dāng)前幀。add方法的結(jié)果壓入A幀的操作數(shù)棧,這樣方法A可以通過幀A的操作數(shù)棧獲取add 的結(jié)果.

總結(jié)

以上就是本文關(guān)于java虛擬機運行時數(shù)據(jù)區(qū)分析的全部內(nèi)容,希望對大家有所幫助。

如有不足之處,歡迎留言指出。

相關(guān)文章

  • Java關(guān)鍵字volatile知識點總結(jié)

    Java關(guān)鍵字volatile知識點總結(jié)

    在本篇文章里小編給大家整理的是一篇關(guān)于Java關(guān)鍵字volatile知識點總結(jié)內(nèi)容,有興趣的朋友們可以學(xué)習(xí)參考下。
    2021-01-01
  • Java實現(xiàn)簡易撲克牌游戲的完整實例

    Java實現(xiàn)簡易撲克牌游戲的完整實例

    這篇文章主要介紹了Java實現(xiàn)簡易撲克牌游戲的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-04-04
  • 混亂的Java日志體系及集成jar包梳理分析

    混亂的Java日志體系及集成jar包梳理分析

    這篇文章主要詳細(xì)的為大家梳理分析了剪不斷理還亂的Java日志體系,以及日志系統(tǒng)涉及到的繁雜的各種集成?jar?包,有需要的朋友可以借鑒參考下,希望能夠有所幫助
    2022-03-03
  • 很詳細(xì)的Log4j配置步驟

    很詳細(xì)的Log4j配置步驟

    Log4J的配置文件(Configuration File)就是用來設(shè)置記錄器的級別、存放器和布局的,它可接key=value格式的設(shè)置或xml格式的設(shè)置信息。通過配置,可以創(chuàng)建出Log4J的運行環(huán)境。
    2008-11-11
  • Java9新特性中的模塊化詳解

    Java9新特性中的模塊化詳解

    今天介紹一個Java?9的功能,模塊化(Modular),這可能使Java有史以來最大的Feature,對Java9模塊化相關(guān)知識感興趣的朋友一起看看吧
    2022-03-03
  • Java String類的常用方法匯總

    Java String類的常用方法匯總

    這篇文章主要為大家詳細(xì)匯總了Java String類的常用方法,感興趣的小伙伴們可以參考一下
    2016-07-07
  • 詳解Java中switch的新特性

    詳解Java中switch的新特性

    這篇文章主要介紹了Java中switch的新特性,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-05-05
  • Java 堆內(nèi)存與棧內(nèi)存詳細(xì)介紹

    Java 堆內(nèi)存與棧內(nèi)存詳細(xì)介紹

    這篇文章主要介紹了Java 堆內(nèi)存與棧內(nèi)存詳細(xì)介紹的相關(guān)資料,這里對java 的堆內(nèi)存和棧內(nèi)存進(jìn)行了詳細(xì)的分析,需要的朋友可以參考下
    2016-11-11
  • 圖書管理系統(tǒng)java代碼實現(xiàn)

    圖書管理系統(tǒng)java代碼實現(xiàn)

    這篇文章主要為大家詳細(xì)介紹了java代碼實現(xiàn)的圖書管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-01-01
  • Rocketmq事務(wù)消息之半消息詳解

    Rocketmq事務(wù)消息之半消息詳解

    這篇文章主要介紹了Rocketmq事務(wù)消息之半消息詳解,RocketMQ的事務(wù)消息支持在業(yè)務(wù)邏輯與發(fā)送消息之間提供事務(wù)保證,RocketMQ通過兩階段的方式提供事務(wù)消息的支持,需要的朋友可以參考下
    2023-09-09

最新評論