JVM基本知识

JVM的基本知识

0.JVM的预知知识

  • JVM是用c语言写的,在操作系统之上。
  • java在jre里面运行。

1.JVM的位置

JVM基本知识_第1张图片

2.JVM的体系结构

JVM基本知识_第2张图片

  • 文件一开始为.java文件,用过javac编译为Class File(.class字节码文件),再到达类加载器Class Loader.
  • 栈Stack、本地方法栈、程序计数器里面不可能有垃圾,有垃圾的话,程序就会报错了.
  • 方法区属于特殊的堆,所谓的JVM调优就是在调堆和方法区,大部分在调堆.
  • 执行引擎包含:解释器、编译器、垃圾回收器.

3.类加载器

JVM基本知识_第3张图片

  • 作用:加载Class文件
  • 四类加载器:
    • 虚拟机自带的加载器
    • 启动类(根)加载器(Bootstrap):负责java平台核心库,用来装载核心类库(该加载器无法直接获取),用c写的。
    • 扩展类加载器(Extension)
    • 应用程序加载器(App)
public class Car {

    public int age;

    public static void main(String[] args) {
        //类是模板,对象是具体的
        Car car1 = new Car();

        Class<? extends Car> aClass1 = car1.getClass();

        ClassLoader classLoader = aClass1.getClassLoader();
        System.out.println(classLoader);   //AppClassLoader

        System.out.println(classLoader.getParent());   //ExtClassLoader

        System.out.println(classLoader.getParent().getParent());   //null
        // 为null的可能: 1.不存在 2.java程序获取不到

    }

}

4.双亲委派机制

  • 定义:双亲委派机制是当类加载器需要加载某一个.class字节码文件时,则首先会把这个任务委托给他的上级类加载器,递归这个操作,如果上级没有加载该.class文件,自己才会去加载这个.class。
  • 作用:
    • 防止加载同一个.class。通过委托去询问上级是否已经加载过该.class,如果加载过了,则不需要重新加载。保证了数据安全。
    • 保证核心.class不被篡改。通过委托的方式,保证核心.class不被篡改,即使被篡改也不会被加载,即使被加载也不会是同一个class对象,因为不同的加载器加载同一个.class也不是同一个Class对象。这样则保证了Class的执行安全。

JVM基本知识_第4张图片

JVM基本知识_第5张图片

  • 这段代码执行不了。
  • 原因是:
    • 类加载器收到类记载的请求。
    • 将这个请求向上委托给父类加载器去完成,一直向上委托,直到启动类加载器(Boot)。
    • 启动类加载器检查是否能够加载当前这个类,能加载就结束,使用当前的加载器,否则,抛出异常,通知子加载器进行加载。
    • 重复步骤3。
    • 都找不到就报出Class Not Found错误。

5.沙箱安全机制

  • 沙箱:一个限制程序运行的环境。
  • 沙箱机制:将java代码限定在虚拟机(JVM)特定的运行范围中,并且严格限制代码对本地系统资源访问,通过这样的措施来保证对代码的有效隔离,防止对本地系统造成破话。
  • 主要限制系统资源访问,例如 CPU、内存、文件系统、网络。

组成沙箱的基本组件:

  • 字节码校验器(bytecode verifier):确保java类文件遵循java语言规范。但并不是所有的类文件都会经过字节码校验,比如核心类。
  • 类装载器(class loader): 类装载器在三个方面对java沙箱起作用
    • 防止恶意代码去干涉善意的代码。 (双亲委派机制)
    • 守护了被信任的类库边界。(双亲委派机制)
    • 将代码归入保护域,确定了代码可以进行哪些操作。(沙箱安全机制)

6.Native

  • 凡是带了native关键字的,说明java的作用范围达不到了,会去调用底层c语言的库,进入本地方法栈,调用本地方法本地接口( JNI(JNI作用为:扩展java的使用,融合不同的编程语言为java所用,最初想融合c、c++。) )。

7.PC寄存器

程序计数器:Program Counter Register

​ 每个线程都有一个程序计数器,是线程私有的,就是一个指针,指向方法区中的方法字节码(用来存储指向像一条指令的地址,也即将要执行的指令代码),在执行引擎读取下一条指令,是一个非常小的内存空间,几乎可以忽略不计。

8.方法区

Method Area 方法区

  • 方法区是被所有线程共享,所有字段和方法字节码,以及一些特殊方法,如构造函数,接口代码也在此定义,简单说,所有定义的方法的信息都保存在该区域,此区域属于共享区间

  • 静态变量(static)、常量(final)、类信息(Class)(构造方法、接口定义)、运行时的常量池存在方法区中,但是 实例变量存在堆内存中,和方法区无关。

9.栈

  • 主要存储 8大基本类型 + 对象引用 + 实例方法,栈不可能存在垃圾
  • 栈运行原理:栈帧
  • 栈满了就会出现StackOverflowError
  • 问题:
    • 栈怎么存东西
    • 画一个对象实例化的过程在内存中

10.三种JVM

  • Sun公司 HotSpot (在cmd中 Java -version看当前用哪个虚拟机)
  • BEA
  • IBM

11.堆

  • Heap,一个JVM只有一个堆内存,堆内存的大小是可以调节的。

  • 类加载器读取类文件之后,会把类实例、方法、常量、变量放堆中,保存我们所有引用类型的真实对象。

  • 堆内存分为三个区域

    • 新生区(伊甸(dian)园区)

    • 养老区

    • 永久区(在JDK8以后,永久区改名字为元空间,本质没什么区别)

      JVM基本知识_第6张图片

      JVM基本知识_第7张图片

      • 元空间在逻辑上存在,物理上不存在。
  • GC垃圾回收主要在伊甸园区和养老区,垃圾回收分为轻量级(针对新生区来的)和重量级。

  • 假设内存满了,就会报OOM错误,堆内存不够(java.lang.OutOfMemoryError: Java heap space)。

    • 报OOM时:
      1. 尝试扩大堆内存看结果。
      2. 分析内存,看一下哪个地方出现了问题(专业工具)
    import java.util.Random;
    
    public class oom {
        public static void main(String[] args) {
            String str = "dongdongdong";
            //在java中,String可以无限长,但堆内存会满
    
            while (true){
                str += str + new Random().nextInt(888888888);
            }
        }
    }
    
    

12.新生区,老年区

  1. 新生区
    • 类诞生和成长的地方、甚至死亡。
    • 分为伊甸园区和幸存者0区、幸存者1区。
      • 所有的对象都是在伊甸园区new出来的。
  2. 老年区

13.永久区

这个区域是常驻内存的,用来存放JDK自身携带的Class对象、interface元数据,存储的是java运行时的一些环境,这个区域不存在垃圾回收,当关闭虚拟机就会释放这个区域的内存。

14.堆内存调优

15.GC:垃圾回收器

  • GC的作用区域:

    JVM基本知识_第8张图片

  • GC题目:

    • JVM的内存模型和分区
    • 堆里面的Eden、from、to、老年区,各有什么特点?
    • GC的算法有哪些? 标记清除法、标记压缩、复制算法、引用计数器
    • 轻GC和重GC分别在什么时候发生?

16.JMM

  • Java Memory Model:java内存模型

  • 作用:缓存一致性协议,用于定义数据读写的规则(是规则就该遵守)。

    JMM定义了线程工作内存和主内存之间的抽象关系:线程之间的共享变量存储在主内存(Main Memory)中,每个线程都有一个私有的本地内存(Local Memory)。

    JVM基本知识_第9张图片

    解决共享对象可见性这个问题:voliate

MM

  • Java Memory Model:java内存模型

  • 作用:缓存一致性协议,用于定义数据读写的规则(是规则就该遵守)。

    JMM定义了线程工作内存和主内存之间的抽象关系:线程之间的共享变量存储在主内存(Main Memory)中,每个线程都有一个私有的本地内存(Local Memory)。

    [外链图片转存中…(img-mer25vCy-1635465740926)]

    解决共享对象可见性这个问题:voliate

17.总结

你可能感兴趣的:(JVM,java,开发语言,后端)