概述
JVM => Java Virtual Machine
JLS => Java Language Specification => Java 语音规范 => 定义 Java 语言的语法
JVMS => Java Virtual Machine Specification => Java 虚拟机规范 => 定义字节码如何在 JVM 中执行
JLS 与 JVMS 没有任何关系
JVM 基本结构
Heap
- 所有的对象都在堆上分配
- 只能操纵对象的引用或者地址
- 只能控制对象的诞生,但是无法控制它的死亡
方法栈
- 线程私有
- 每当一个方法调用发生,方法栈就入栈一个栈帧
- 每当方法退出(放回或异常),栈帧就被弹出 => 栈帧是对方法每一次调用的一个表示,每一次调用会产生一个新的栈帧
- 局部变量在栈帧中分配
- 当栈深度过大时抛出 StackOverflow
栈帧
- 局部变量表 => Local Variable Table
- 操作数栈 => Operand Stack
每当方法调用开始的时候,Local Variable Table 会被初始化成当前方法的参数
Method Area
- 被整个虚拟机所共享的 Class 信息等 =>
new Cat()
的时候,Cat
的类型信息来源于 Method Area => readonly - 运行时常量池 =>
String.intern
=> 常量池存放值,但是每个值都有一个地址,使得每次调用intern
方法时返回的都是值的地址,多次调用对象是不变的,那个值 & 地址都是不变的String s1 = new String("ABCDE"); String s2 = new String("ABCDE"); String s3 = s1.intern(); String s4 = s2.intern(); System.out.println(s1 == s2); // false System.out.println(s3 == s4); // true
- Java 7 之前:永久代(PermGen) => OutOfMemory: perm gen => 永久代和堆放在一起,会和堆抢占内存,OutOfMemory 经常会发生
- Java 8 之后:元空间(Metaspace) => 元空间和 Native 共享内存
Bytecode
Bytecode == IR => Intermediate Representation
JVM 实现跨平台基石 => ByteCode
- 一种基于栈的、与平台无关的计算模型 => 基于栈:所有的计算都是基于栈帧里面的 Operand Stack 执行的
- 可以由多种方式生成 => JVM 上的编程语言 & 直接生成字节码
查看 & 阅读
- javap =>
javap -v -private x.class
=> Java 自带的反编译工具,可以用来查看字节码信息 - classpy
- 反编译器 => IDEA ASM Bytecode Viewer Plugin
加载 & 执行
- Class Loader => 将 class 文件加载成虚拟机内部的 Class 类的表示
- Bytecode Verifier => 验证字节码的合法性
- Java Runtime System
- Native OS
类加载器 Class Loader
Class Loader 打通了代码和数据间的障碍
- 动态加载代码
- 动态生成代码
- 动态替换代码
使用场景
- Mock
- AOP
- 热部署 | 热替换
双亲委派加载模型
Java 8 及之前,Java 9 引入了模块系统
当任何一个类加载器尝试去加载一个类时都会委托给它的父亲,如果它的父亲可以加载的话,就直接返回,否则就自己尝试去加载,并且成为要加载那个类的类加载器
TODO:ClassLoad
文档
- Application ClassLoader => CLASSPATH => 负责加载 classpath 里面的包 => 启动参数中的 -cp(classpath)
- Extension ClassLoader => jre/lib/ext/*.jar => 负责加载 JVM 中程序运行所需要的类
- Bootstrap ClassLoader => jre/lib/*.jar rt.jar(runtime) jce.jar 等 => 负责加载 JVM 启动时的相关类
- 安全性
- 正确性 => 类加载器也被 instanceof 所检查 => instanceof 不仅检查类名,还检查类加载器 =>
cat instanceof Cat
=> 检查类加载器cat.getClass().classLoader
和Cat.class.classLoader
是否一致
JIT Compiler
JIT => Just In Time
AOT => Ahead Of Time
两种执行方式
- JIT => 解释执行 => 方便、跨平台 + 慢
- AOT => 编译执行 => 麻烦、不灵活、编译后的代码非常臃肿 + 快
antlr
显示语法树
GitHub
Quick Start
OS X
cd /usr/local/lib
sudo curl -O https://www.antlr.org/download/antlr-4.9.2-complete.jar
export CLASSPATH=".:/usr/local/lib/antlr-4.9.2-complete.jar:$CLASSPATH"
alias antlr4='java -jar /usr/local/lib/antlr-4.9.2-complete.jar'
alias grun='java org.antlr.v4.gui.TestRig'
# alias grun='java -cp .:antlr-4.9.2-complete.jar org.antlr.v4.gui.TestRig'
知识点
- factorial => 阶乘
- 在 Java 世界中所有的参数传递都是拷贝,都发生了一个拷贝的过程
- 基本数据类型 => 拷贝值
- 引用数据类型 => 拷贝地址
- IDEA Plugin => ASM Bytecode Viewer => 将当前代码编译成字节码查看
- List of Java bytecode instructions
- 对象的地址在栈中何种形式存储?
- 32 位操作系统 => 对象的地址在栈中32位 => 4byte
- 64 位操作系统 => 对象的地址在栈中64位 => 8byte
-
native
关键字 => 该方法没有 Java 代码,是 Java 虚拟机实现的 - String 的
equals
=> 比较两个 String 是否是同一个对象 | 循环比较每个字符
String equals - Java Magic Number => CAFEBABE
- 字节码版本号约定 => Java 虚拟机只能加载低于或等于该版本的字节码 => 加载高于 Java 虚拟机版本的字节码将会报错 => java.lang.UnsupportedClassVersionError: xxx: Unsupported major.minor version
- Java 模式
- mixed mode => 混合模式
- interpreter mode => 解释器模式
- compiled mode => 编译模式
疑问
- 常量池只与 String 有关吗?
网友评论