有哪些虚拟机器
HotSpot JRockit
java -version
虚拟机作用:
去编译并解释 字节码文件(class、等待)
好处:
一处编译到处运行
共享 方法区、堆内存
单线程—》本地方法区、栈、程序计数器
执行引擎:将字节码文件编译成机器指令。再将反复执行的字节码文件缓存起来。共二次调用。
Java文件先编译 编译后 查看栈内存的指令集合
先看一下代码
public class Test1 {
public static void main(String[] args) {
int i = 1;
int j = 2;
int z = i+j;
}
}
查看编译后的文件Java指令:javap -v 类名.class
查看进程:jps 指令
加载-----》 连接–验证(咖啡北北)—准备(赋值初始化)----解析(解析二进制码)—》初始化
类加载的信息 放在方法区里面
clinit:类变量赋值和静态代码快(子类一定要晚于父类)
init:该类的构造器
在类的加载过程中,应用程序类加载器是非常客气的(自己先不加载,一直向上委托)如果顶级父加载器能加载,默认加载。顶级父类加载不了,就开始向下委托。直到一个加载器完成对类的加载。
安全防止恶意篡改。
主动使用 :是否被初始化
一个线程有且只有一个程序计数器。作用:用来存放当前线程的行号(也称行号指示器)。
多个线程来回切换执行,每个线程中的计数器行号很有可能不同。表示下一次执行该线程,表示从哪一行指令读起。至上而下
主要存放的就是栈帧,每一个方法就是一个栈帧。保持先进后出的原则。
局部变量在被加载的时候:就会初始化最大的局部变量表:
他到底是个啥!
位于存放在栈帧中的单元。后进先出原则。int类型 布尔、字符、浮点、 占一个操作数。long、duppo类型 占 两个操作数。
最大操作数栈
/**
* 功能描述:程序计数器
*
* @author Songxianyang
* @date 2022-11-16 21:53
*/
public class PCTest {
public static final String SSS = "宋先阳";
public static void main(String[] args) {
int i = 99;
int d = 11;
int c = i+d;
String name = "song";
System.out.println(name);
System.out.println(c);
System.out.println(SSS);
}
public void test1() {
int test = test();
System.out.println(test);
}
public int test() {
int i=2;
int j=4;
int n= i+j;
return n;
}
}
Classfile /D:/work/project/huatech/yqmm-boot/spring-study/target/classes/com/song/boot/springstudy/jvm/PCTest.class
Last modified 2022-11-22; size 1045 bytes
MD5 checksum 6edd6ce518224237160d6f0a7a8db1c6
Compiled from "PCTest.java"
public class com.song.boot.springstudy.jvm.PCTest
minor version: 0
major version: 52
flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
#1 = Methodref #9.#37 // java/lang/Object."":()V
#2 = String #38 // song
#3 = Fieldref #39.#40 // java/lang/System.out:Ljava/io/PrintStream;
#4 = Methodref #41.#42 // java/io/PrintStream.println:(Ljava/lang/String;)V
#5 = Methodref #41.#43 // java/io/PrintStream.println:(I)V
#6 = Class #44 // com/song/boot/springstudy/jvm/PCTest
#7 = String #45 // 宋先阳
#8 = Methodref #6.#46 // com/song/boot/springstudy/jvm/PCTest.test:()I
#9 = Class #47 // java/lang/Object
#10 = Utf8 SSS
#11 = Utf8 Ljava/lang/String;
#12 = Utf8 ConstantValue
#13 = Utf8 <init>
#14 = Utf8 ()V
#15 = Utf8 Code
#16 = Utf8 LineNumberTable
#17 = Utf8 LocalVariableTable
#18 = Utf8 this
#19 = Utf8 Lcom/song/boot/springstudy/jvm/PCTest;
#20 = Utf8 main
#21 = Utf8 ([Ljava/lang/String;)V
#22 = Utf8 args
#23 = Utf8 [Ljava/lang/String;
#24 = Utf8 i
#25 = Utf8 I
#26 = Utf8 d
#27 = Utf8 c
#28 = Utf8 name
#29 = Utf8 MethodParameters
#30 = Utf8 test1
#31 = Utf8 test
#32 = Utf8 ()I
#33 = Utf8 j
#34 = Utf8 n
#35 = Utf8 SourceFile
#36 = Utf8 PCTest.java
#37 = NameAndType #13:#14 // "":()V
#38 = Utf8 song
#39 = Class #48 // java/lang/System
#40 = NameAndType #49:#50 // out:Ljava/io/PrintStream;
#41 = Class #51 // java/io/PrintStream
#42 = NameAndType #52:#53 // println:(Ljava/lang/String;)V
#43 = NameAndType #52:#54 // println:(I)V
#44 = Utf8 com/song/boot/springstudy/jvm/PCTest
#45 = Utf8 宋先阳
#46 = NameAndType #31:#32 // test:()I
#47 = Utf8 java/lang/Object
#48 = Utf8 java/lang/System
#49 = Utf8 out
#50 = Utf8 Ljava/io/PrintStream;
#51 = Utf8 java/io/PrintStream
#52 = Utf8 println
#53 = Utf8 (Ljava/lang/String;)V
#54 = Utf8 (I)V
{
public static final java.lang.String SSS;
descriptor: Ljava/lang/String;
flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL
ConstantValue: String 宋先阳
public com.song.boot.springstudy.jvm.PCTest();
descriptor: ()V
flags: ACC_PUBLIC
Code:
stack=1, locals=1, args_size=1
0: aload_0
1: invokespecial #1 // Method java/lang/Object."":()V
4: return
LineNumberTable:
line 18: 0
LocalVariableTable:
Start Length Slot Name Signature
0 5 0 this Lcom/song/boot/springstudy/jvm/PCTest;
public static void main(java.lang.String[]);
descriptor: ([Ljava/lang/String;)V
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=2, locals=5, args_size=1
0: bipush 99
2: istore_1
3: bipush 11
5: istore_2
6: iload_1
7: iload_2
8: iadd
9: istore_3
10: ldc #2 // String song
12: astore 4
14: getstatic #3 // Field java/lang/System.out:Ljava/io/PrintStream;
17: aload 4
19: invokevirtual #4 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
22: getstatic #3 // Field java/lang/System.out:Ljava/io/PrintStream;
25: iload_3
26: invokevirtual #5 // Method java/io/PrintStream.println:(I)V
29: getstatic #3 // Field java/lang/System.out:Ljava/io/PrintStream;
32: ldc #7 // String 宋先阳
34: invokevirtual #4 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
37: return
LineNumberTable:
line 21: 0
line 22: 3
line 23: 6
line 25: 10
line 26: 14
line 27: 22
line 28: 29
line 30: 37
LocalVariableTable:
Start Length Slot Name Signature
0 38 0 args [Ljava/lang/String;
3 35 1 i I
6 32 2 d I
10 28 3 c I
14 24 4 name Ljava/lang/String;
MethodParameters:
Name Flags
args
public void test1();
descriptor: ()V
flags: ACC_PUBLIC
Code:
stack=2, locals=2, args_size=1
0: aload_0
1: invokevirtual #8 // Method test:()I
4: istore_1
5: getstatic #3 // Field java/lang/System.out:Ljava/io/PrintStream;
8: iload_1
9: invokevirtual #5 // Method java/io/PrintStream.println:(I)V
12: return
LineNumberTable:
line 33: 0
line 34: 5
line 35: 12
LocalVariableTable:
Start Length Slot Name Signature
0 13 0 this Lcom/song/boot/springstudy/jvm/PCTest;
5 8 1 test I
public int test();
descriptor: ()I
flags: ACC_PUBLIC
Code:
stack=2, locals=4, args_size=1
0: iconst_2
1: istore_1
2: iconst_4
3: istore_2
4: iload_1
5: iload_2
6: iadd
7: istore_3
8: iload_3
9: ireturn
LineNumberTable:
line 38: 0
line 39: 2
line 40: 4
line 41: 8
LocalVariableTable:
Start Length Slot Name Signature
0 10 0 this Lcom/song/boot/springstudy/jvm/PCTest;
2 8 1 i I
4 6 2 j I
8 2 3 n I
}
SourceFile: "PCTest.java"
针对每一个栈帧(一个方法)指向常量池中引用地址(常量池在类得初始化后就确定下来啦)
常量池
Constant pool:
#1 = Methodref #9.#37 // java/lang/Object."":()V
#2 = String #38 // song
#3 = Fieldref #39.#40 // java/lang/System.out:Ljava/io/PrintStream;
#4 = Methodref #41.#42 // java/io/PrintStream.println:(Ljava/lang/String;)V
#5 = Methodref #41.#43 // java/io/PrintStream.println:(I)V
#6 = Class #44 // com/song/boot/springstudy/jvm/PCTest
#7 = String #45 // 宋先阳
#8 = Methodref #6.#46 // com/song/boot/springstudy/jvm/PCTest.test:()I
#9 = Class #47 // java/lang/Object
#10 = Utf8 SSS
#11 = Utf8 Ljava/lang/String;
#12 = Utf8 ConstantValue
#13 = Utf8 <init>
#14 = Utf8 ()V
#15 = Utf8 Code
#16 = Utf8 LineNumberTable
#17 = Utf8 LocalVariableTable
#18 = Utf8 this
#19 = Utf8 Lcom/song/boot/springstudy/jvm/PCTest;
#20 = Utf8 main
#21 = Utf8 ([Ljava/lang/String;)V
#22 = Utf8 args
#23 = Utf8 [Ljava/lang/String;
#24 = Utf8 i
#25 = Utf8 I
#26 = Utf8 d
#27 = Utf8 c
#28 = Utf8 name
#29 = Utf8 MethodParameters
#30 = Utf8 test1
#31 = Utf8 test
#32 = Utf8 ()I
#33 = Utf8 j
#34 = Utf8 n
#35 = Utf8 SourceFile
#36 = Utf8 PCTest.java
#37 = NameAndType #13:#14 // "":()V
#38 = Utf8 song
#39 = Class #48 // java/lang/System
#40 = NameAndType #49:#50 // out:Ljava/io/PrintStream;
#41 = Class #51 // java/io/PrintStream
#42 = NameAndType #52:#53 // println:(Ljava/lang/String;)V
#43 = NameAndType #52:#54 // println:(I)V
#44 = Utf8 com/song/boot/springstudy/jvm/PCTest
#45 = Utf8 宋先阳
#46 = NameAndType #31:#32 // test:()I
#47 = Utf8 java/lang/Object
#48 = Utf8 java/lang/System
#49 = Utf8 out
#50 = Utf8 Ljava/io/PrintStream;
#51 = Utf8 java/io/PrintStream
#52 = Utf8 println
#53 = Utf8 (Ljava/lang/String;)V
#54 = Utf8 (I)V
看一下test1方法编译后得结果,然后去常量池中找对应得符号引用(#什么得)
public void test1();
descriptor: ()V
flags: ACC_PUBLIC
Code:
stack=2, locals=2, args_size=1
0: aload_0
1: invokevirtual #8 // Method test:()I
4: istore_1
5: getstatic #3 // Field java/lang/System.out:Ljava/io/PrintStream;
8: iload_1
9: invokevirtual #5 // Method java/io/PrintStream.println:(I)V
12: return
LineNumberTable:
line 33: 0
line 34: 5
line 35: 12
LocalVariableTable:
Start Length Slot Name Signature
0 13 0 this Lcom/song/boot/springstudy/jvm/PCTest;
5 8 1 test I
指向常量池中引用(#8)地址 。。。。。为什么着说
1: invokevirtual #8 // Method test:()I
#8 = Methodref #6.#46 // com/song/boot/springstudy/jvm/PCTest.test:()I
#6 = Class #44 // com/song/boot/springstudy/jvm/PCTest 那个类
#46 = NameAndType #31:#32 // test:()I 那个方法
#31 = Utf8 test 方法名
#32 = Utf8 ()I 返回值类型
虚方法:在编译过程中无法确定的方法(多态、重写、抽象方法)。实方法:编译过程中可以确定下来的方法(私有方法、final修饰、静态方法、构造器)
返回程序计数器地址(执行引擎执行),给调用者。A调用B B执行完了 把地址给A,A继续执行。有异常中断程序,或者被捕获。
12: return
9: ireturn
面试题
堆主要用来存什么:
存:您new出来的对象和数组。
对象的引用存在:栈帧中的本地变量表中。
类信息存在方法区中。
jps:查询Java进程
这个地方是抄 :参考地址
-XX:+PrintGCDetails :查看GC的详情
-XX:NewSize:设置年轻代最小空间大小
-XX:MaxNewSize:设置年轻代最大空间大小
-XX:PermSize:设置永久代最小空间大小
-XX:MaxPermSize:设置永久代最大空间大小
-XX:NewRatio:设置年轻代和老年代的比值。默认值-XX:NewRatio=2,表示年轻代与老年代比值为1:2,年轻代占整个堆大小的1/3
-XX:SurvivorRatio:设置年轻代中Eden区Survivor区的容量比值。默认值-XX:SurvivorRatio=8,表示Eden : Survivor0 : Survivor1 = 8 : 1 : 1
-XX:-OmitStackTraceInFastThrow:关闭(省略异常栈从而快速抛出),默认开启。如果想将所有异常信息都抛出,建议关闭。
-XX:+HeapDumpOnOutOfMemoryError:表示当JVM发生OOM时,自动生成DUMP文件。
-XX:HeapDumpPath=/usr/local/dump:dump文件路径或者名称。如果不指定文件名,默认为:java___
打印GC详情:-XX:+PrintGCDetails
打印GC详情:-XX:+PrintGCDetails
Heap
PSYoungGen total 75776K, used 6503K [0x000000076bb80000, 0x0000000771000000, 0x00000007c0000000)
eden space 65024K, 10% used [0x000000076bb80000,0x000000076c1d9f90,0x000000076fb00000)
from space 10752K, 0% used [0x0000000770580000,0x0000000770580000,0x0000000771000000)
to space 10752K, 0% used [0x000000076fb00000,0x000000076fb00000,0x0000000770580000)
ParOldGen total 173568K, used 0K [0x00000006c3200000, 0x00000006cdb80000, 0x000000076bb80000)
object space 173568K, 0% used [0x00000006c3200000,0x00000006c3200000,0x00000006cdb80000)
Metaspace used 3174K, capacity 4496K, committed 4864K, reserved 1056768K
class space used 349K, capacity 388K, committed 512K, reserved 1048576K
学习视频
实战一下:设置参数
代码
只是监控 并看不出来 什么问题 导致的OOM。继续往下学习。哈哈哈
分为:新生代(伊甸园区,幸存者from区,幸存者to区)、老年代 。比例1:2,新生代8:1:1
创建的对象首先他会创建在伊甸园区,伊甸园满了之后处罚YGC,将没有具体引用指向的对象给回收掉。剩下的去到幸存者from区。依此类推。from区与to区来回赋值(并给一个标记age+1,当age到达15(默认值)去到老年代)
可以借鉴的文章
总结:复制并交换,谁空谁是to。
在推荐一篇 讲的还行
YGC\Minor GC 在伊甸园区满的时候,进行垃圾回收。
OGC\magor GC 老年代垃圾收集器
full GC 整堆收集器
不知道他说的对不对
用户线程:那个一直在往堆里面创建对象
优先放到伊甸园区
大对象提前放到老年代
幸存者区对象大于或等于提前放到老年代(有点不明白)如果survivor 区中相同年龄的所有对象大小的总和大于survivor空间的一半,年龄大于或等于该年龄的对象可以直接进入老年代,无须等到MaxTenuringThreshold 中要求的年龄。
主要针对,方法内对象是否逃逸。未逃逸就直接在栈上分配。内部创建内部使用成为未逃逸,外部使用称为逃逸。
开发中能使用局部变量的,就不要使用在方法外定义。