您好,登錄后才能下訂單哦!
這篇文章將為大家詳細講解有關Java程序的運行原理是什么,文章內容質量較高,因此小編分享給大家做個參考,希望大家閱讀完這篇文章后對相關知識有一定的了解。
class文件包含Java程序執行的字節碼
數據嚴格按照格式緊湊排列在class文件的二進制流,中間無分割符
文件開頭有一個0xcafebabe(16進制)特殊的標志
線程獨占: 每個線程都會有它獨立的空間,隨線程的生命周期而創建和銷毀
線程共享: 所有線程都能訪問這塊內存數據,隨虛擬機或GC而創建和銷毀
方法區是各個線程共享的內存區域
用于存儲已被虛擬機加載的類信息, 常量,靜態變量, 即時編譯后的代碼等數據
雖然Java虛擬機規范把方法區描述為堆的一個邏輯部分, 但它卻有一個別名叫Non-Heap, 目的應該是與Java堆區分開來
Oracle的Hotspot虛擬機在Java7中方法區放在’永久代’(Permanent Generation), Java8放在元數據空間, 并且通過GC機制對這個區域進行管理
運行時常量池是方法區的一部分
Java堆是被所有共享的一塊內存區域, 在虛擬機啟動時創建
存放對象的實例
垃圾收集器的主要管理區域
Java堆還可以細分為: 新生代和老年代, 新生代又可以細分為Eden 空間, From Survivor空間 和To Survivor空間
空間滿了會拋OutOfMemoryError
Java虛擬機棧是線程私有的, 它的生命周期與線程相同
Java虛擬機棧描述的是Java方法執行的內存模型: 每個方法被執行的的時候都會同時創建一個棧幀(棧幀是方法運行時的基礎數據結構)用于存儲局部變量表, 操作棧, 動態鏈接, 方法出口等信息.
棧內存默認最大是1M, 超出則拋出StackOverFlowError
本地方法棧與虛擬機棧的功能類似, 虛擬機棧是為虛擬機執行Java方法而準備的, 本地方法棧是為虛擬機使用Native本地方法而準備的
Hotspot虛擬機中虛擬機棧與本地方法棧的實現方式一樣, 超出大小后也會拋StackOverFlowError
程序計數器是線程私有的一塊較小的內存空間
記錄當前線程執行的字節碼位置, 存儲的是字節碼指令地址, 如果執行Native方法, 則計數器為空
CPU同一時間, 只會執行一條線程的指令. JVM多線程會輪流切換并分配CPU的執行時間的方式. 為了線程切換后, 需要通過程序計數器來恢復正確的執行位置
使用Demo.Java進行測試, 運行javac Demo.java
編譯成class文件, 然后運行javap -v Demo.class > Demo.txt
查看class文件內容
Demo.Java
public class Demo{
public static void main(String[] args){
int x = 500;
int y = 100;
int a = x / y;
int b = 50;
System.out.println(a + b);
}
}
Demo.txt
Classfile /E:/*/Demo.class
Last modified 2019-6-30; size 412 bytes
MD5 checksum efd785af33e58aa9fc9834110b74b87b
Compiled from "Demo.java"
public class Demo
minor version: 0 //次版本號 major version: 52 //主版本號 版本號規則: JDK5,6,7,8分別對應49,50,51,52
flags: ACC_PUBLIC, ACC_SUPER //訪問標志Constant pool: // 常量池 類信息包含的靜態常量, 編譯之后就能確認 #1 = Methodref #5.#14 // java/lang/Object."<init>":()V
#2 = Fieldref #15.#16 // java/lang/System.out:Ljava/io/PrintStream;
#3 = Methodref #17.#18 // java/io/PrintStream.println:(I)V
#4 = Class #19 // Demo
#5 = Class #20 // java/lang/Object
#6 = Utf8 <init>
#7 = Utf8 ()V
#8 = Utf8 Code
#9 = Utf8 LineNumberTable
#10 = Utf8 main
#11 = Utf8 ([Ljava/lang/String;)V
#12 = Utf8 SourceFile
#13 = Utf8 Demo.java
#14 = NameAndType #6:#7 // "<init>":()V
#15 = Class #21 // java/lang/System
#16 = NameAndType #22:#23 // out:Ljava/io/PrintStream;
#17 = Class #24 // java/io/PrintStream
#18 = NameAndType #25:#26 // println:(I)V
#19 = Utf8 Demo
#20 = Utf8 java/lang/Object
#21 = Utf8 java/lang/System
#22 = Utf8 out
#23 = Utf8 Ljava/io/PrintStream;
#24 = Utf8 java/io/PrintStream
#25 = Utf8 println
#26 = Utf8 (I)V
{
public Demo(); // 默認隱式無參的構造函數 descriptor: ()V
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 1: 0
public static void main(java.lang.String[]); //程序的入口main方法 descriptor: ([Ljava/lang/String;)V
flags: ACC_PUBLIC, ACC_STATIC //訪問控制 Code:
stack=3, locals=5, args_size=1 //方法棧棧幀中操作數棧的深度,本地變量數量,參數數量 0: sipush 500 //Jvm執行引擎執行這些源碼編譯過后的指令碼, javap翻譯出來的 3: istore_1 //是操作符, class 文件內存儲的是指令碼, 前面的數據是偏移量,
4: bipush 100 //Jvm根據這個去區分不同的指令. 詳情參照'JVM指令碼表'
6: istore_2
7: iload_1
8: iload_2
9: idiv
10: istore_3
11: bipush 50
13: istore 4
15: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
18: iload_3
19: iload 4
21: iadd
22: invokevirtual #3 // Method java/io/PrintStream.println:(I)V
25: return
LineNumberTable:
line 3: 0
line 4: 4
line 5: 7
line 6: 11
line 7: 15
line 8: 25
}
SourceFile: "Demo.java"
關于Java程序的運行原理是什么就分享到這里了,希望以上內容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。