JVM运行机制

JVM运行机制,第1张

JVM运行机制
先了解jdk,jre,jvm 1.什么是JDK?

JDK 是 java development kit(java 开发工具包)的缩写。每个学 java的人都会先在机器上装一个JDK,那让我们看一下 JDK 的安装目录。在目录下面有六个文件夹、一个 src 类库源码压缩包、和其他几个声明文件。其中,真正在运行 java 时起作用的是以下四个文件夹:bin、include、lib、jre。JDK,JRE,JVM 三者关系概括如下:

现在我们可以看出这样一个关系,JDK 包含 JRE,而 JRE 包含 JVM。

  • bin : 最主要的是编译器(javac.exe)

  • include : java 和 JVM 交互用的头文件

  • lib:类库

  • jre:java 运行环境

(注意:这里的 bin、lib 文件夹和 jre 里的 bin、lib 是不同的)总的来说 JDK是用于 java 程序的开发,而 jre 则是只能运行 class 而没有编译的功能。eclipse、idea 等其他 IDE 有自己的编译器而不是用 JDK bin 目录中自带的,所以在安装时你会发现他们只要求你选 jre 路径就 ok 了。

2.什么是jre

JRE 是 JAVA 程序运行时需要的运行环境,就是说如果你光是运行 JAVA 程序而不是去搞开发的话,只安装 JRE 就能运行已经存在的 JAVA 程序了。JDk、JRE 内部都包含 JAVA 虚拟机 JVM,JAVA 虚拟机内部包含许多应用程序的类的解释器和类加载器等等。

3.什么是JVM?

JVM 是 Java Virtual Machine(Java 虚拟机)的缩写,它是由软件技术模拟出计算机运行的一个虚拟的计算机它是整个 java实现跨平台的最核心的部分,所有的 java 程序会首先被编译为.class 的类文件,这种类文件可以在虚拟机上执行,也就是说 class 并不直接与机器的 *** 作系统相对应,而是经过虚拟机间接与 *** 作系统交互,由虚拟机将程序解释给本地系统执行。JVM 是 Java 平台的基础,和实际的机器一样,它也有自己的指令集,并且在运行时 *** 作不同的内存区域。 JVM 通过抽象 *** 作系统和 CPU 结构,提供了一种与平台无关的代码执行方法,即与特殊的实现方法、主机硬件、主机 *** 作系统无关。JVM 的主要工作是解释自己的指令集(即字节码)到 CPU 的指令集或对应的系统调用,保护用户免被恶意程序骚扰。 通俗易懂的理解:JVM就是人与机器的翻译官,沟通的桥梁

JVM的生命周期
  1. JVM在Java程序开始执行的时候,它才运行,程序结束的时它就停止。

  2. 一个Java程序会开启一个JVM进程,如果一台机器上运行三个程序,那么就会有三个运行中的JVM进程。

  3. JVM中的线程分为两种:守护线程和普通线程

  4. 守护线程是JVM自己使用的线程,比如垃圾回收(GC)就是一个守护线程。

  5. 普通线程一般是Java程序的线程,只要JVM中有普通线程在执行,那么JVM就不会停止。

  6. 权限足够的话,可以调用exit()方法终止程序。

JVM的结构体系

方法区

保存装载的类信息

  • 类型的常量池

  • 字段,方法信息

  • 方法字节码 通常和永久区(Perm)关联在一起

    在JDK6的时候字符串常量是放在方法区中,但是JDK7的时候就已经移到了堆中。所以从这方面来说方法区,堆中到底保存的是什么信息和jdk的版本有很大的关系。从一般意义上来说我们的方法区就是保存一些类的原信息。方法区通常和永久区(perm)关联在一起,保存一些相对稳定的数据。
    
PC寄存器
每个线程拥有一个PC寄存器,在线程创建的时候创建,pc寄存器总是指向下一条指令的地址,这样程序就知道下一步该干什么。在执行本地方法的时候,PC的值就是 undefined
java堆
  1. 几乎所有对象都存放在其中,并且java堆完全是自动化管理的,通过垃圾回收机制,垃圾对象会自动清理,不需要时自动释放

  2. 根据垃圾回收机制不同,java堆可能有不同的结构。最为常见的就是将整个java堆分为新生代和老年代。其中新生代存放新生的对象或者年龄不大的对象,老年代则存放老年对象。
    新生代分为eden区、s0区、s1区,s0和s1也被称为from和to区域,它们是两块大小相等并且可以互换角色的空间。(复制算法)
    绝大多数情况下,对象首先分配在eden区,在新生代回收后,如果对象还存活,则会进入s0或者s1区,之后每经过一次新生代回收,如果对象存活,则它的年龄就加1,当对象达到一定年龄后,则进入老年代。

  3. 直接内存
      java的NIO库允许java程序直接使用内存从而提高性能,通常直接内存速度会优于java堆。读写频繁的场合可能会考虑使用。

java栈

java栈是一个线程私有的内存空间,一个栈一般由三个部分组成:局部变量表, *** 作数栈和帧数据区。

  1. 局部变量表:用于保存函数的参数及局部变量。
  2. *** 作数栈:主要保存计算过程的中间结果,同时作为计算过程中变量临时的存储空间。
  3. 帧数据区:除局部变量表和 *** 作数栈,栈还需要一些数据来支持常量池的解析,这里帧数据区保存着访问常量池的指针,方便程序访问常量池。
  4. 另外,当函数返回或者出现异常时,虚拟机必须有一个异常处理表,方便发送异常的时候找到异常的代码,因此异常处理表也是帧数据区的一部分。
本地方法栈

和java栈类似,最大的不同是本地方法栈用于本地方法调用。java虚拟机允许java直接调用本地方法。(通常使用C编写),垃圾收集系统是java的核心,也是必不可少的,java有一套自己进行垃圾清理的机制,开发人员无序手工清理。

垃圾回收机制

详讲地址:https://segmentfault.com/a/1190000038256027

回收机制算法
  1. 标记-清除收集器
      这种收集器首先遍历对象图并标记可到达的对象,然后扫描堆栈以寻找未标记对象并释放它们的内存。这种收集器一般使用单线程工作并停止其他 *** 作。

  2. 标记-压缩收集器
      有时也叫标记-清除-压缩收集器,与标记-清除收集器有相同的标记阶段。在第二阶段,则把标记对象复制到堆栈的新域中以便压缩堆栈。这种收集器也停止其他 *** 作。

  3. 复制收集器
      这种收集器将堆栈分为两个域,常称为半空间。每次仅使用一半的空间,jvm生成的新对象则放在另一半空间中。gc运行时,它把可到达对象复制到另一半空间,从而压缩了堆栈。这种方法适用于短生存期的对象,持续复制长生存期的对象则导致效率降低。

  4. 增量收集器
      增量收集器把堆栈分为多个域,每次仅从一个域收集垃圾。这会造成较小的应用程序中断。

  5. 分代收集器
      这种收集器把堆栈分为两个或多个域,用以存放不同寿命的对象。jvm生成的新对象一般放在其中的某个域中。过一段时间,继续存在的对象将获得使用期并转入更长寿命的域中。分代收集器对不同的域使用不同的算法以优化性能。

jvm启动流程图

1.java虚拟机启动的命令是通过java +xxx(类名,这个类中要有main方法)或者javaw启动的。
2.执行命令后,系统第一步做的就是装载配置,会在当前路径中寻找jvm的config配置文件。
3.找到jvm的config配置文件之后会去定位jvm.dll这个文件。这个文件就是java虚拟机的主要实现。
4.当找到匹配当前版本的jvm.dll文件后,就会使用这个dll去初始化jvm虚拟机。获得相关的接口。之后找到main方法开始运行。

Java类加载机制

类的加载机制:https://zhuanlan.zhihu.com/p/25228545

写不下去了,自闭了

参考文章

  • Java–JVM 运行流程:https://xie.infoq.cn/article/6777b0b7b92adf63c1c8f3c78
  • https://zhuanlan.zhihu.com/p/25713880
  • https://juejin.cn/post/6844903909786402829#heading-0

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/917324.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-16
下一篇 2022-05-16

发表评论

登录后才能评论

评论列表(0条)

保存