一篇文章详解JVM

2020-02-02  本文已影响0人  zain丶月下

在学习Java中,JVM到底是什么呢?可能带有很多的疑问。在这里给大家详细的讲解一下什么是JVM。这个也是小编在最近自己学习总结。

1、什么是JVM

JVM是Java Virtual Machine(Java[虚拟机])的缩写,JVM是一种用于计算设备的规范,它是一个虚构出来的计算机,是通过在实际的计算机上仿真模拟各种计算机功能来实现的。java常见三种JVM:HotSpot,JRockit,j9vm

查看本地jvm

2、JVM在什么位置

先给大家看一张关于jvm图


jvm位置.png

在JVM中,我们可以看到JVM处于操作系统之上。老师在教我们编写第一行代码的时候,就先教我们安装环境。在图中我们可以看到。平时我们开发的软件都是基于jvm的环境上运行的。

3、class类运行执行过程

在给大家看一张关于jvm的图片


java文件执行过程

这张图对于学习java的人应该很熟悉。这就是完整的.java文件运行的过程



在这里我们可以看到运行时数据区中。各个模块的执行具体细节。
  1. 类加载器
    顾名思义类加载器就是加载class类。在类加载器中


    类加载器

    平时我们为什么能够得到类。是由于类加载器的作用


    类加载器.png
测试.png
代码中我们可以看到。得到类的加载器时,先查找本地系统的类加载器,如果没有就向上一层查看。直到最后根系统加载器。这就是双亲委派机制。
双亲委派机制:主要是保证类的安全,所有的类,加载的时候,都会先委托父类,直到最顶层,如果有这个类,就直接加载顶层的这个类如果没有,就向下找,直到找到位置。
  1. 本地方法栈
    JVM调用本地方法
    在本地库接口中,本地方法接口JNI(Java Native Interface)。 java本地方法接口凡是带了native关键字,说明java程序触及不到,就会进入本地方法栈。本地方法栈中即可调用本地方法接口中的接口
  2. 虚拟机栈
    存放方法运行时所需的数据,成为栈帧。
public class TestDemo2 {
    public static void main(String[] args) {
        test();
    }
    public static void test() {
        System.out.println("1");
    }
}

在上面的例子中,就是一个压栈的过程

栈和队列
栈(数据结构):先进后出,后进先出
队列:先进先出
在这里借用老师的一句话:喝多了吐就是栈,吃多了拉就是队列
如果在压栈的过程中出现了无限压栈会有什么情况呢?

image.png
这就是我们常说的栈溢出:java.lang.StackOverflowError
而压栈过程就如下图
栈帧

  1. 用于存储对象实例,在讲解堆时要联合方法区和栈一起讲解


    堆,栈,方法区

    在我们new对象时,我们会产生一个对象。就会存在一个压栈的过程和调用对象的实例的过程

注意:
(1) 基本数据类型的存储原理:所有的简单数据类型不存在“引用”的概念,基本数据类型都是直接存储在内存中的内存栈上的,数据本身的值就是存储在栈空间里面,Java语言里面八种数据类型是这种存储模型;

(2) 引用类型的存储原理:引用类型继承于Object类(也是引用类型)都是按照Java里面存储对象的内存模型来进行数据存储的,使用Java内存堆和内存栈来进行这种类型的数据存储,简单地讲,“引用”(存储对象在内存堆上的地址)是存储在有序的内存栈上的,而对象本身的值存储在内存堆上的;

  1. 方法区
    存储运行时常量池,已被虚拟机加载的类信息,常量,静态变量,即时编译器编译后的代码等数据

4、GC垃圾回收

在讲解GC时,应该理解GC发生在什么地方。我们常说的GC100%发生在数据共享区,也就是方法区和堆。而百分之99%的GC又发生在堆中。

4.1 GC中的分区
  1. 次数最频繁:Young区
  2. 次数较少:old区(Young区常用的放入old区)
  3. 基本不动:perm永久区


    GC
4.2 GC中的算法
  1. 引用计数法
    引用计数法
    在引用计数法:当赋值对象时,就给对象一个标识,如果之前这个对象在引用则加一,当为零时及未引用。 清除为零的对象。即按照是否引用进行清除
    缺点:循环引用时,无法清除(对象1引用对象2,对象2引用对象1,则一直会引用)。所以JVM一般不用这个方法
  2. 复制算法
    复制算法
    在Eden区,存放所有的数据,经过GC清理,复制到to区,from区的数据也会复制到to区。清空from区。并且from变为to区。之前的to区变为了from区。当Young区满了后,就会引发一次轻GC。 如果在引用Young区的数据超过5次。则会把数据放入old区(常用)。如果old区站满。则会引发一次重GC。当Young区和old区都满了后。就会引发OOM。
    缺点:内存空间多浪费一半,需要双倍的空间
    极端情况:当数据100%需要清理时,浪费时间。假设在一片区域对象存活极低,则复制算法实用。结论表明:99%的会被GC回收
    优点:不会存在内存的碎片
  3. 标记清除
    标记清除
    3.1 在未引用的数据上面。给一个标记。
    3.2 清除标记后的数据。
    缺点:二次扫描数据,会产生内存碎片(清理不连续)
  4. 标记压缩(整理)
    标记压缩
    缺点:移动标记清除后的数据需要成本
    优点:把标记清除后的数据压缩到一起。就不会产生垃圾碎片。
在所有的算法中?难道没有最优的算法嘛?

没有最优的算法。只有最合适的算法。比如在Young区采用复制算法。在old区采用标记压缩方法。这种在不同区域引用不同的算法叫:分带收集算法

上一篇下一篇

猜你喜欢

热点阅读