图文解析Jvm(一)

目录
一基本结构
二 JVM原理
三 JVM体系结构
四 JVM运行过程
五对象死亡和垃圾回收

基本结构
从Java平台的逻辑结构上看,我们从下图了解jvm
在这里插入图片描述
** 图一JDK/JRE/JVM的关系

JDK/JRE/JVM是什么关系
JDK(Java Development Kit,编译,调试)是程序开发者用来编译.调试java程序用的开发者工具包。JDK工具也是JAVA程序,也需要JRE才能运行。为了保持JDK的独立性和完整性,在JDK的工具也是java程序,也需要JRE才能运行。为了保持JDK的独立性和完整性,在JDK的安装过程中,JRE也是安装的一部分。所以,在JDK的安装目录下有一个名为jre的目录,用于存放JRE文件。
JRE(JavaRuntimeEnvironment,JAVA运行环境)也就是java平台。所有的Java程序都要在JRE才能运行。
JVM(JAVA VIRTURE Machine,Java 虚拟机)是Jre的一部分,它是个虚构出来的计算机,但它屏蔽了底层操作系统的差异,实现了跨平台。JVM有自己的硬件架构,如处理器,堆栈,寄存器等.。还有相应的指令系统。正是有了JVM层,java才有了Write One,Run Anywhere。即:一次编写,到处执行
在这里插入图片描述
二.JVM原理
Jvm是java的核心和基础。在java编译器和os(操作系统的简写)平台之间的虚拟处理器。它是一种利用软件方法实现的抽象的计算机基于下层操作系统和硬件平台。可以在上面执行字节码程序。经编译器编译后的(.class)文件,是运行在JVM上的。两种方式:
1
.解释执行(边解释,边执行
:Jvm边解释,把字节码翻译成对应操作系统的机器码,边调用操作系统接口执行翻译后的机器码。
2**.编译执行**:对于热点代码,也就是经常要执行的代码,通过Jvm的JIT即时编译技术,直接编译成机器码。然后每次直接运行JIT编译后的机器码,以提高性能…
在这里插入图片描述
三JVM的体系结构

1.编译在这里插入图片描述
2. 类加载过程
系统加载class类型的文件主要有五步
:加载—连接(验证—准备—解析)—初始化–使用—卸载。**
类加载器将.class 文件搬过来就是先丢到这一块,方法区存放的是类似于元数据信息方面的数据,比如静态变量 编译后的代码 常量
在这里插入图片描述
1.加载(JVM 提供或自己手写)
在这里插入图片描述
1.1 java类加载器负责动态加载类到java虚拟机的内存空间中。
JVM中有三个默认的类加载器
a.引导(BootStrap,存在于rt.jar包下)类加载器。由(C语言编写)不继承自Java.lang.Classloader.负责存放在<java_home>/jre/lib目录中
b.扩展(Extensions,扩展的jar包)类加载器<java_home>/jre/lib/ext中指明的目录中加载加载java的扩展类库。如:Javax..
c.Apps类加载器(也称系统加载器)根据java应用程序的类路径(CLASSpath)来加载JAVA类
注:每个类都有一个父类装载器
1.2用户自定义类加载器
继承java.lang.ClassLoader来实现自己的类加载器。
2.连接
加载阶段和链接阶段是交叉进行的
链接阶段可以分为3个步骤:验证—准备—解析
a.验证
在这里插入图片描述
b.准备
**准备阶段是正式为类的静态变量分配内存并设置类变量默认初始值的阶段,这些内存都将在方法区中分配内存:**如:
package com.mengdd.classloader;

public class Sample {

private static int a = 1;
private static long b;

static {
    b = 2;
}

}
此程序中int 类型的静态变量a 分配4个字节的内存空间 并赋予默认值为0 为b静态变量分配8个字节的内存空间。
3.类的解析
在解析阶段,JAVA虚拟机会把类的二进制数据的符号替换为直接引用。
public void gotoWork() {

         car.run();// 这段代码在Worker类的二进制数据中表示为符号引用

  }

在Worker类的二进制数据中,包含了一个对Car类的run()方法的符号引用,它由run()方法的全名和相关描述符组成。

在解析阶段,Java虚拟机会把这个符号引用替换为一个指针,该指针指向Car类的run()方法在方法区内的内存位置,这个指针就是直接引用
3.初始化
初始化是类加载的最后一步,也是真正执行java的程序代码(字节码的过程)。
小总结:

  1. java文件经编译后变成.class字节码文件
  2. 字节码文件经类加载被搬到JVM虚拟机中
  3. 虚拟机主要分为5大块
    *方法区
    *堆
    *栈
    *程序计数器
    例子:
    在这里插入图片描述
    在这里插入图片描述
    执行步骤:
    1.编译好的App.java后得到App.class后,执行App.class 系统会启动一个JVM进程,从classpath路径中找到一个名为App.class的二进制文件,将类信息加载到运行数据的方法区中 这个过程概括为.java—.class—类加载
    2.JVM找到java主程序入口,执行main方法
    3.Student s=new Student():就是让JVM创建一个Student对象,并把Student的信息放到方法区中
    4.加载Student类后,JVM在堆中为新的student实例对象分配内存 然后调用构造函数初始化Student实例 这个student实例持有指向方法区的Student类的类型信息的引用
    5.执行student.sayName()时,Jvm根据student对象 然后根据student持有的引用定位到方法区的student类的类型信息的方法表 获得sayName()的字节码地址
    6,执行代码
    7,卸载
    三 运行期

在这里插入图片描述
1.方法区
类加载器将.class文件先丢到这一块
方法区是用于存放类似于元数据信息方面的数据 比如:静态变量 编译后代码
2.堆(存储)
堆内存分为年轻代和老年代 、非堆内存为永久代
堆内存中分配的是对象 垃圾收集就是收集这些对象(对象又分 强引用 弱引用 软引用 虚引用)
在这里插入图片描述

堆主要存放了一些数据,比如对象的实例,数组等 对是属于线程共享,线程不安全
3.栈(运行)
代码的运行空间,线程独享 本地方法和本地
接口他两底层都是用c来进行工作的
虚拟机栈存在的异常:outofmemoryerror
虚拟机栈的生命周期:不存在垃圾回收和所处
线程保持一致
基本数据类型+对象的引用变量+实例方法都是在栈里分配内存
栈中数据都是以栈帧格式存在 压入A1 A2 A3
出栈A3 A2 A1 遵守后进先出
4.程序计算器:
类似于指针,主要是完成一个加载工作,执向下一行我们需要执行的代码,线程独享,线程安全
四 对象死亡和垃圾回收
对象死亡:首先必须提到一个名叫finalize()的方法它是object类中的一个方法 只会被调用一次
垃圾回收算法
1,标记清除算法
在这里插入图片描述
分为两个阶段
标记和清除
优点:方法简单
缺点:效率低
2.复制算法
在这里插入图片描述
过程:内存划分两等分 每次只用一块
优点:效率提高。解决碎片问题
缺点:内存缩水
3 分代收集算法
把java堆分为新生代和老年代。根据各个年代的特点选用最恰当的收集算法。
五 垃圾回收器
在这里插入图片描述
到jdk8为止,默认的垃圾收集器是Parallel Scavenge 和 Parallel Old

从jdk9开始,G1收集器成为默认的垃圾收集器
目前来看,G1回收器停顿时间最短而且没有明显缺点,非常适合Web应用。在jdk8中测试Web应用,堆内存6G,新生代4.5G的情况下,Parallel Scavenge 回收新生代停顿长达1.5秒。G1回收器回收同样大小的新生代只停顿0.2秒

发布了7 篇原创文章 · 获赞 3 · 访问量 254

猜你喜欢

转载自blog.csdn.net/qq_43614498/article/details/104877665