目录
相关视频:
深入理解Java虚拟机(JVM性能调优+内存模型+虚拟机原理)
相关文章:
JDK(Java Development Kit) 是 Java 语言的软件开发工具包(SDK)。
JRE是Java Runtime Environment缩写,指Java运行环境。
JVM是Java Virtual Machine(Java虚拟机)的缩写
(基于King的视频)
Java SE体系架构
JVM整体介绍:
java(javac)--> class文件(JVM把class文件翻译成机器码) --> Linux、Windows等平台(只认识机器码101010)。
JVM可以理解为一个翻译,把class文件翻译成机器码,所以JVM具有跨平台性。
运行时数据区:
程序计数器:
虚拟机栈:
虚拟机栈图解:
JavaStack.java
public class JavaStack {
//静态变量
static String Ls = "xxx洗浴中心";
//常量
final String Fs = "所有服务只要80元";
public void king() {
//13号技师
Object tech13 = new Object();
//我又两个账户
//局部变量,支付宝余额
int zhifubao = 50;
//局部变量,微信余额
int weixin = 50;
//判断逻辑,如果金额大于80
if (zhifubao + weixin > 80) {
//调用一次非常特殊的服务
tech13.hashCode();
zhifubao = zhifubao - 50;
weixin = weixin - 30;
}
}
public static void main(String[] args) {
JavaStack javaStack = new JavaStack();
javaStack.king();
}
}
在IDEA中,找到对应的编译的class文件
进行如上反编译,得到一个TXT文件,打开后得到:
Classfile /D:/idea_ws/.../JavaStack.class
Last modified 2019-5-21; size 930 bytes
MD5 checksum ...
Compiled from "JavaStack.java"
public class com.ph.jvm.JavaStack
minor version: 0
major version: 52
flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
#1 = Methodref #4.#38 // java/lang/Object."<init>":()V
#2 = String #39 // 所有服务只要80元
#3 = Fieldref #6.#40 // com/ph/jvm/JavaStack.Fs:Ljava/lang/String;
#4 = Class #41 // java/lang/Object
#5 = Methodref #4.#42 // java/lang/Object.hashCode:()I
#6 = Class #43 // com/ph/jvm/JavaStack
#7 = Methodref #6.#38 // com/ph/jvm/JavaStack."<init>":()V
#8 = Methodref #6.#44 // com/ph/jvm/JavaStack.king:()V
#9 = String #45 // xxx洗浴中心
#10 = Fieldref #6.#46 // com/ph/jvm/JavaStack.Ls:Ljava/lang/String;
#11 = Utf8 Ls
#12 = Utf8 Ljava/lang/String;
#13 = Utf8 Fs
#14 = Utf8 ConstantValue
#15 = Utf8 <init>
#16 = Utf8 ()V
#17 = Utf8 Code
#18 = Utf8 LineNumberTable
#19 = Utf8 LocalVariableTable
#20 = Utf8 this
#21 = Utf8 Lcom/ph/jvm/JavaStack;
#22 = Utf8 king
#23 = Utf8 tech13
#24 = Utf8 Ljava/lang/Object;
#25 = Utf8 zhifubao
#26 = Utf8 I
#27 = Utf8 weixin
#28 = Utf8 StackMapTable
#29 = Class #41 // java/lang/Object
#30 = Utf8 main
#31 = Utf8 ([Ljava/lang/String;)V
#32 = Utf8 args
#33 = Utf8 [Ljava/lang/String;
#34 = Utf8 javaStack
#35 = Utf8 <clinit>
#36 = Utf8 SourceFile
#37 = Utf8 JavaStack.java
#38 = NameAndType #15:#16 // "<init>":()V
#39 = Utf8 所有服务只要80元
#40 = NameAndType #13:#12 // Fs:Ljava/lang/String;
#41 = Utf8 java/lang/Object
#42 = NameAndType #47:#48 // hashCode:()I
#43 = Utf8 com/ph/jvm/JavaStack
#44 = NameAndType #22:#16 // king:()V
#45 = Utf8 xxx洗浴中心
#46 = NameAndType #11:#12 // Ls:Ljava/lang/String;
#47 = Utf8 hashCode
#48 = Utf8 ()I
{
static java.lang.String Ls;
descriptor: Ljava/lang/String;
flags: ACC_STATIC
final java.lang.String Fs;
descriptor: Ljava/lang/String;
flags: ACC_FINAL
ConstantValue: String 所有服务只要80元
public com.ph.jvm.JavaStack();
descriptor: ()V
flags: ACC_PUBLIC
Code:
stack=2, locals=1, args_size=1
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: aload_0
5: ldc #2 // String 所有服务只要80元
7: putfield #3 // Field Fs:Ljava/lang/String;
10: return
LineNumberTable:
line 3: 0
line 7: 4
LocalVariableTable:
Start Length Slot Name Signature
0 11 0 this Lcom/ph/jvm/JavaStack;
public void king();
descriptor: ()V
flags: ACC_PUBLIC
Code:
stack=2, locals=4, args_size=1
0: new #4 // class java/lang/Object
3: dup
4: invokespecial #1 // Method java/lang/Object."<init>":()V
7: astore_1
8: bipush 50
10: istore_2
11: bipush 50
13: istore_3
14: iload_2
15: iload_3
16: iadd
17: bipush 80
19: if_icmple 37
22: aload_1
23: invokevirtual #5 // Method java/lang/Object.hashCode:()I
26: pop
27: iload_2
28: bipush 50
30: isub
31: istore_2
32: iload_3
33: bipush 30
35: isub
36: istore_3
37: return
LineNumberTable:
line 11: 0
line 14: 8
line 16: 11
line 18: 14
line 20: 22
line 21: 27
line 22: 32
line 25: 37
LocalVariableTable:
Start Length Slot Name Signature
0 38 0 this Lcom/ph/jvm/JavaStack;
8 30 1 tech13 Ljava/lang/Object;
11 27 2 zhifubao I
14 24 3 weixin I
StackMapTable: number_of_entries = 1
frame_type = 254 /* append */
offset_delta = 37
locals = [ class java/lang/Object, int, int ]
public static void main(java.lang.String[]);
descriptor: ([Ljava/lang/String;)V
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=2, locals=2, args_size=1
0: new #6 // class com/ph/jvm/JavaStack
3: dup
4: invokespecial #7 // Method "<init>":()V
7: astore_1
8: aload_1
9: invokevirtual #8 // Method king:()V
12: return
LineNumberTable:
line 28: 0
line 29: 8
line 30: 12
LocalVariableTable:
Start Length Slot Name Signature
0 13 0 args [Ljava/lang/String;
8 5 1 javaStack Lcom/ph/jvm/JavaStack;
static {};
descriptor: ()V
flags: ACC_STATIC
Code:
stack=1, locals=0, args_size=0
0: ldc #9 // String xxx洗浴中心
2: putstatic #10 // Field Ls:Ljava/lang/String;
5: return
LineNumberTable:
line 5: 0
}
SourceFile: "JavaStack.java"
上图红框中就是程序计数器所记录的东西。 之所以是不连续的,是因为jvm在加载方法的同时还会做一些其他不可见的操作。
开启HSDB工具:
sa-jdi.jar
打开cmd命令:
java -cp .\sa-jdi.jar sun.jvm.hotspot.HSDB
输入该命令后,显示一个界面:
说明启动成功。
运行代码:
public class JVMObject {
public final static String MAN_TYPE = "man"; // 常量
public static String WOMAN_TYPE = "woman"; // 静态变量
public static void main(String[] args)throws Exception {//栈帧
Teacher T1 = new Teacher();//堆中 T1 是局部变量
T1.setName("Mark");
T1.setSexType(MAN_TYPE);
T1.setAge(36);
for (int i=0;i<15;i++){//进行15次垃圾回收
System.gc();//垃圾回收
}
Teacher T2 = new Teacher();
T2.setName("King");
T2.setSexType(MAN_TYPE);
T2.setAge(18);
Thread.sleep(Integer.MAX_VALUE);//线程休眠很久很久
}
}
class Teacher{
String name;
String sexType;
int age;//堆
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSexType() {
return sexType;
}
public void setSexType(String sexType) {
this.sexType = sexType;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
运行时数据区:
找到进程ID:
继续使用HSDB工具:
输入ID:16028
然后就可以看到JVM启动的所有线程:
查看main线程:
如下:
虚拟机栈和本地方法栈
可以看到sleep方法,这个是native方法,是本地方法栈的东西:
可以看到main线程,这个是main的栈帧,这是虚拟机栈的东西:
从上面也可以看出:HotSpot直接把本地方法栈和虚拟机栈合二为一。
寻找本地方法区:
接下来在HSDB工具中找到方法区,即找到 .class
入口:
视图:
根据路径:
点进去就可以找到 Teacher.class的两个对象:
详细信息:
堆内存区域:
Heap Parameters:
ParallelScavengeHeap [PSYoungGen [
eden = [0x00000000d5c00000,0x00000000d5f40070,0x00000000d7c80000] ,
from = [0x00000000d7c80000,0x00000000d7c80000,0x00000000d8180000] ,
to = [0x00000000d8180000,0x00000000d8180000,0x00000000d8680000]
]
PSOldGen [ [0x0000000081400000,0x00000000814c4510,0x0000000086980000] ]
]
深入辨析堆和栈: