JVM
Java从编码到执行

Java是一种编译与解释都有的编程语言,其中大部分的代码时通过编译为字节码执行的,而一些特定的次数较多的代码将使用JIT做本地编译,直接交给操作系统调用。
编译器可以修改编译模式,共三种:
-Xint,纯解释模式,编译极快,启动较慢-Comp,纯编译模式,编译很慢,启动很快-Xmixed,混合模,开始解释执行,启动速度较快,对热点代码实时检测和编译多次被调用的方法
多次被调用的循环
什么是JVM
JVM是一种跨语言的平台,是一种规范。可以在JVM上运行的语言多大一百多种。JVM本身不是跨平台的,每种操作系统都有对应的实现。只要编程语言可以编译为class文件,就可以运行在JVM中。

可以使用 java -version 命令查看当前使用的jvm类型,目前市面上主要的集中jvm实现有:
Hotspot,Oracle官方提供
Jrockit,BEA公司,曾号称最快的JVM,现被Oracle收购,合并到Hotspot中
J9,IBM公司
Microsoft VM
TaobaoVM
LiquidVM,普通虚拟机运行于操作系统上,而LiquidVM直接运行在物理机上,作为一个操作系统
zing,azul 公司,商业软件,垃圾回收业界标杆(Hotspot参考了该虚拟机,提供了新的ZGC)
Class文件格式
查看Class文件的16进制形式,使用IDEA插件BinEd,打开.class文件并使用如下操作:

有如下类:
他的字节码信息如下;

使用javap命令查看class文件信息
使用IDEA Show ByteCode 查看class文件信息


在IDEA内部配置javap工具

重启IDEA:

类加载机制

一个class文件被初始化到JVM通常要经过下面几个过程:
Loading,将class加载到内存中
Linking,链接
Verification,校验字节码
Preparation,将class文件的静态变量赋默认值(注意不是代码设置的初始值)
Resolution,class文件中使用的常量池的符号引用转换为内存地址
Initializing,静态变量赋代码设置的初始值,调用静态代码块
1. Loading:ClassLoader
加载Class文件到内存的步骤由ClassLoader来完成:

可以在java代码中通过如下方式查询类加载器之间的关系,以及当前类是由哪个类加载器加载进来的:
双亲委派机制
类加载符合双亲委派机制
当一个class需要被load到内存时,会自顶向上寻找class是否已经被load到内存了:CustomClassLoader、AppClassLoader、ExtensionClassLoader、BootstrapClassLoader的顺序
如果某个ClassLoader已经加载这个类,那么会直接返回
如果直到BootstrapClassLoader都没有加载这个类,那么Bootstrap会尝试load这个class
这个load的操作会自顶向上的进行,会以 BootstrapClassLoader、ExtensionClassLoader、AppClassLoader、CustomClassLoader的顺序进行load
双亲委派就是从子到父的查找过程,又有一个从父到子的load过程
为什么需要双亲委派?
主要是为了安全问题:如果没有双亲委派,假设第三方代码重写JDK中的核心类,对引用第三方代码的java程序造成破坏
次要问题:可以解决类加载缓存的问题,放置二次加载损耗资源
使用类加载器
什么时候需要手动加载一个类:
动态代理生成了一个新的class,此时需要程序手动load
目标class在网络上,需要先下载,再手动load
热部署加载,class文件修改后,手动load
使用加载器加载一个资源为流:
loadClass的源码
findInCache -> parent.loadClass -> findClass()
自定义类加载器
继承ClassLoader类并重写loadClass方法, 参考类sun.misc.Launcher.AppClassLoader:
2. Linking
2.1 Verification
验证文件是否符合JVM规定
2.2 Preparation
静态成员变量赋默认值
2.3 Resolution
将类、方法、属性等符号引用解析为直接引用 常量池中的各种符号引用解析为指针、偏移量等内存地址的直接引用
3. Initialzing
调用初始化代码
指令重排序
有如下代码:
他的main方法生成的指令如下:
因为有可能发生指令重排序,他的字节码指令有可能是如下这样的(astore_1 和 invokespecial有可能被重排):
所以也就有了双重检查锁的问题:
JMM
Java Memory Model,Java内存模型。
硬件层的数据一致性

因为CPU、内存、磁盘的读取速度各不相同,所以存储器按照他们的速度将其划分为了6个层次。当CPU想要读取某个数据时,会先从寄存器开始读取,依次向下查找;如果找到了,会从下到上依次缓存到更高级别的缓存。是一种多级缓存的机制。
最后更新于
这有帮助吗?