日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

JVM从入门到精通(五): Java运行时数据区和常用指令

發布時間:2024/2/28 java 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 JVM从入门到精通(五): Java运行时数据区和常用指令 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

JVM Runtime Data Area and JVM Instructions

Java運行時數據區以及JVM指令


i=i++結果為8
i=++i結果為9

一個class的生命周期

以下面的規范為準:

運行時數據區的構成

PC:peogram counter 程序計數器
DirectMemory:直接內存,JVM可以直接訪問內核空間的內存(OS管理的內存),零拷貝(不需要拷貝),NIO用到了,提高效率
MethodArea:方法區,里面有常量池

PC 程序計數器

JVM ??臻g

在每一個線程創建的時候,線程會有自己獨立的JVM棧空間,棧中存放的是棧幀

堆空間

所有線程共享同一個堆空間。
堆空間是用來存放所有類實例數組空間分配運行時數據區

方法區

所有線程共享同一個方法區。
方法區用來存放 per-class structors
Perm Space 與 Meta Space容易混淆,他們只是Method Area的兩的不同版本的實現。

運行時常量池


棧幀

  • 局部變量
  • 操作數棧
  • 動態鏈接
    指向運行時常量池里面的符號鏈接,看有沒有解析,如果沒有解析,就動態解析,如果已經解析了,就拿過來使用。例如,A方法要調用B方法,B方法在哪兒呢?就要去常量池里面找。
  • 返回值地址
    A方法調用了B方法,如果有返回值,要記錄返回值返回到那個地方,也就是記錄繼續執行的位置。

回到面試題

  • 理解局部變量表
  • 理解操作數棧
  • 理解一些常用的指令
package com.mashibing.jvm.c4_RuntimeDataAreaAndInstructionSet;public class TestIPulsPlus {public static void main(String[] args) {int i = 8;i = i++; // i = ++i;System.out.println(i);} }

i=i++ 生成的指令
執行過程分析

i=++i 生成的指令



下面這個 i 因為超過了 127,所以用的是sipush,而不是上圖中的bipush


為什么我們可以在非static方法中使用this?因為this在局部變量表中是已經存在的。
(局部變量表中,0位置是this,1位置是k,2位置是i)


下面這個例子,之前有一道面試題:DCL 單例為什么要加 volitile?因為你看下面的第一條指令,我們知道,剛new出來對象是半初始化的對象,只是賦一個默認值,而involespecial才是調用構造方法,給變量賦初始值,而這兩條指令之間是可能會發生指令重排的。

返回值

遞歸的調用

下面是m方法的執行,沒有把main方法放上來
在這個3層遞歸中,使用到的是3個棧

另外,我們看到指令前面的數字 0,1,2,5,6,…,沒有3,4的原因,是2指令的字節數比較多,占用了后面的字節數

總結

invokeXXX指令

invokestatic

調用一個靜態方法

invokevirtual

new一個對象,調用一個非靜態方法
自帶多態:new 的是哪個對象,調用的就是哪個對象的方法

invokespecial

調用實例方法;對超類、私有和實例初始化方法調用的特殊處理

可以直接定位的,不需要多態的方法

  • private方法
  • 構造方法

final方法不是invokespecial的,它是invokevirtual的。

invokeinterface

調用接口方法

invokedynamic

JVM最難的指令
invokedynamic是lambda表達式或者反射或者其他動態語言scala kotlin,或者CGLib ASM,動態產生的class,會用到的指令

每一個lambda表達式都有一個自己的內部類,java沒有純粹的函數。匿名內部類每次都是動態產生的。

package com.mashibing.jvm.c4_RuntimeDataAreaAndInstructionSet;public class T05_InvokeDynamic {public static void main(String[] args) {I i = C::n;I i2 = C::n;I i3 = C::n;I i4 = () -> {C.n();};System.out.println(i.getClass());System.out.println(i2.getClass());System.out.println(i3.getClass());for(;;) {I j = C::n;} //MethodArea <1.8 Perm Space (FGC不回收)}@FunctionalInterfacepublic interface I {void m();}public static class C {static void n() {System.out.println("hello");}} }

關于Lambda表達式的一個坑
如果你用Lambda表達式寫出了這樣的代碼:

for(;;) {I j = C::n;} //MethodArea <1.8 Perm Space (FGC不回收)

在1.8之前有一個巨大的bug,就是你在里面產生了很多對象,但是Perm Space在FGC的時候是不會回收的。

Perm Space和Meta Space的區別?

  • Perm Space (<1.8)
    字符串常量位于PermSpace
    FGC不會清理
    大小啟動的時候指定,不能變
  • Meta Space (>=1.8)
    字符串常量位于堆
    會觸發FGC清理
    不設定的話,最大就是物理內存
  • 思考:
    如何證明1.7字符串常量位于Perm,而1.8位于Heap?
    提示:結合GC, 一直創建字符串常量,觀察堆,和Metaspace

    總結

    以上是生活随笔為你收集整理的JVM从入门到精通(五): Java运行时数据区和常用指令的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。