JVM


title: JVM必知必会


1. JVM是啥?

JVM(Java Virtual Machine) Java虚拟机

虚拟机有两种:

系统虚拟机: VirtualBox ,VMware 是对硬件的模拟

程序虚拟机:jvm ,是为了执行单个程序设计的

我们都知道java具有跨平台特性,为什么?

write once , run anywhere

解释 —>

java源程序先经过javac编译器编译成二进制的.class字节码文件(java的跨平台指的就是.class字节码文件的跨平台,.class字节码文件是与平台无关的),.class文件再运行在jvm上,java解释器(jvm的一部分)会将其解释成对应平台的机器码执行,所以java所谓的跨平台就是在不同平台上安装了不同的jvm,而在不同平台上生成的.class文件都是一样的,而.class文件再由对应平台的jvm解释成对应平台的机器码执行 。

JVM是最强大的虚拟机,是比 java更优秀的产品;请注意,JVM不仅仅面向Java

JVM直接运行的是字节文件,是二进制格式。意思是,不管是什么语言,只要你可以变成字节码,更准确地说:只要你给我的是Jvm字节码(Java字节码这个名词,其实可以换成Jvm字节码), 那么Jvm都可以运行

例如: Java,Jruby, Groovy,JavaScript, Kotlin 等等

上面的语言都会被编译成字节码文件从而通过jvm在机器上执行,这些字节码文件必须遵守一定的规则

也正因为如此, 我们才有了多语言混合编程,上面几个语言,终究会编译成相同规则的字节码文件, 不同语言之间可以相互调用了。

试想一下: 如果我们自己开发个语言,我们自己写点语法在向下运行时,我们只用考虑到如何让咱的语言转换成 字节码就ok了, 我们借助JVM,来运行我们的语言。 事实上 Groovy, Kotlin 也都是这样弄的

1.1 JVM位置

我们第一次下载JDK的时候,肯定之根据不同的操作系统来下载不同的jdk , 本质是不同版本jdk的

jvm不同,jvm是运行在操作系统上的,意思就是, mac下载的jdk, 肯定和 windows jdk不一样,因为 他俩的JVM不同(别忘了,jvm是要运行字节码文件,你给他字节码,他帮你运行。他一定是要和硬件打交道的,这也解释了,为啥他能帮助我们跨平台,他下面和操作系统的接口是不同的,但是上层和字节码的交互是相同的,这就叫跨平台,跨硬件)

1.2 JVM 的整体结构

说了这么多, 我们最好在整体上了解一下JVM的解释运行的整个流程:

先看第一个图:



我们主要以第二张图为例:



(先是 java文件通过编译器成为ClassFile!,图上就不画了,此处的编译器也就是我们常常听说的编译器,我们把这个编译器成为前端编译器, 因为是比较上层的一个编译器)

ClassFiles : 字节码文件, jvm的原材料,诡异的是,每个字节码文件都是一个 ! 这个类可不是你的java 程序里面的类啊,不要搞混。 这一块在内存中的字节码,就是一个类,是存放在物理磁盘上的 文件, claassFiles被称为DNA元数据模板,放在方法区。


类装载器子系统: 把 字节码 加载到 内存当中

​ 以下三个加载器是 父子继承关系:

​ 启动类加载器 :又叫根加载器, rt.jar通跟加载器加载到内存中,rt.jar是java的底子,有很多基本的类

​ 拓展类加载器: 所有在1.0版本之后拓展的java类,都叫拓展的java类,都是用拓展类加载器加载的。

​ 应用程序类加载器: 咱们自己写的类,使用这个加载器加载

请看懂如下代码

 Object object  = new Object();
        System.out.println(object.getClass().getClassLoader());
        //null  根加载器,也叫BootStrap加载器

        testCode testcode = new testCode();
        System.out.println(testcode.getClass().getClassLoader());
        // sun.misc.Launcher$AppClassLoader@18b4aac2   应用程序类加载器
        System.out.println(testcode.getClass().getClassLoader().getParent());
        //sun.misc.Launcher$ExtClassLoader@1b6d3586     拓展类加载器
        System.out.println(testcode.getClass().getClassLoader().getParent().getParent());
        //null 根加载器,也叫BootStrap加载器

双亲委派机制:

​ 如果你要用一个类,一定要从上向下找,先找根加载器, 再拓展类加载器,再应用程序类加载器

从下面的代码你就知道,明明我们自己手写了一个java.lang.String类, 含有main方法,但是由于是从从上往下找的,在第一层的 根加载器中的 rt.jar 就存在一个java.lang.String了,因此一定会使用那个,而不是我们是这个,

这也正好保证了,我们写的这些代码不会污染上层的java类, 这也就是沙箱安全

例子代码:

package java.lang;


/**
 * 错误: 在类 java.lang.String 中找不到 main 方法, 请将 main 方法定义为:
 *    public static void main(String[] args)
 * 否则 JavaFX 应用程序类必须扩展javafx.application.Application
 */
public class String {
    public static void main(String[] args) {
        System.out.println("这是我写的");
    }
}

无论多少个线程,有且仅有一份的

方法区:

​ 方法区就是模板工厂

​ 方法区绝对不是存放方法的的地方,存放 类的结构信息, 也就是模板

​ 方法区装的是类的模板 , 应用程序类(也就是自己写的类)的模板啦等

​ 存放的是模板!模板! 而不是一个一个类的实例, 实例在堆中


栈管运行,堆管存储

​ [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QFsmervO-1579602465244)(https://s2.ax1x.com/2020/01/21/1FxJqx.png)]

堆存放的是一个一个类的实例!就是new 之后的实例!

新生区:

养老区:

永久存储区: rt.jar 在这儿

Java7:

Java8


无论多少个线程, 每个线程都有一份的
Java栈:

​ 栈负责运行 , 但仅仅存储8个基本变量,对象引用变量,实例方法

​ 也就是学习 java栈 时常说的“栈”

​ 也就是跑各种方法的地方,线程结束生命周期也就结束了。

​ 栈没有垃圾回收机制 ,一个线程一块栈,线程结束代表栈消失

本地方法栈: 就是放 native 方法的地方 !!!

只要是 标有native的java源码,意思就是 这块代码要和底层操作系统打交道

但是java只是一个语言,她并不具能力操控硬件系统,因此, 很多native的存在就是表示终止

这意味着她要求助于外部语言

因此! 但凡是标有native的java源码,意味着要调用和java无关的系统级别库,比如c函数库啦等

​ 因此native方必须存放在native栈里面

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Tvx4V5yU-1579602465249)(https://s2.ax1x.com/2020/01/21/1Fdi1f.png)]


程序计数器:

​ 寄存器


执行引擎:

真真正正地把字节码 转换成 机器码

包含三部分
1. 解释器
2.JIT即时编译器(和上面对应,我们叫后端编译器)
3.垃圾回收器

本地方法接口

本地方法库


1.3 JVM的架构模型
指令集的架构模型分为两种:
1. 基于栈的指令集架构
	指令集小, 指令多
	实现简单,适用于资源受限的设备(嵌入式设备: 打印机,机顶盒)
	0地址指令:无地址,仅有操作数,只牵扯栈顶
	性能不如寄存器
2. 基于寄存器的指令集架构
	和栈架构相反

那么:

由于跨平台特性,Java的字节码文件都是根据栈来设计的 ,因为不同的cpu的寄存器是不同的, 为了做到跨平台,我们必须保证,字节码文件能够做到不同硬件的通用,因此使用栈作为架构模型。

1.4 JVM的生命周期

虚拟机启动

JVM的启动是 通过引导类加载器(bootstrap class loader) 创建一个初始类(intial class)来完成的,这个类是根据虚拟机的具体实现指定的。

虚拟机的执行

是为了执行java程序

执行一个java程序的进程,本质上是一个执行jvm进程

虚拟机的退出

一个java程序结束,意味着一个jvm进程的结束

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值