JVM虚拟机知识总结

    • 什么是虚拟机?

从字面意思上来看,顾名思义即使一台虚拟的计算机,用来执行虚拟的计算机指令,从大体上来看,虚拟机一般分为两种。一种是系统虚拟机,另外一种是程序虚拟机

系统虚拟机:代表为VMware

程序虚拟机:代表为JVM(java虚拟机)

    • JVM的作用?

  1. 负责将字节码加载到内存在中(运行时数据区)

  1. 将字节码转换为机器码,在各个系统中执行

  1. 负责存储数据

  1. 垃圾回收

    • JVM的整体组成部分?

  1. 类加载

  1. 运行时数据区(堆、java虚拟机栈、方法区、程序计数器、本地方法栈)具体了解请点击(java运行时区域分布

  1. 执行引擎(将字节码转换为机器码)

  1. 本地方法接口

  1. 垃圾回收

程序将java代码首先转换为class文件(字节码),jvm通过类加载器用IO的方式将字节码加载到内存中(运行时数据区),但是字节码不能被底层系统所识别,所以需要特定的命令解析器(执行引擎)将字节码翻译成为底层系统指令交给CPU进行执行,在执行的过程中会调用到其他语言的接口(本地方法接口)来实现功能的实现。

    • 类加载

    • 类加载器的作用?
  1. 负责从硬盘|网络中加载节码信息

  1. 将节码信息加载到内存(运行时数据区)中

    • 类加载过程?
    • 加载
  1. 通过类名(地址)获取此类的二进制字节流

  1. 将这个字节流所代表的静态存储结构转换为方法区的运行结构

  1. 在内存中生成一个代表这个类的java.lang.Class对象,作为这个类的各种数据的访问接口

    • 链接

验证:

对字节码文件的格式进行验证,文件是否被污染

对基本的语法格式进行验证

准备:

为静态的变量进行内存分配

静态常量在编译期间就初始化

解析:

将符号引用转为直接引用

将字节码的表现形式转为内存中的表现形式(内存地址)

初始化:

类的初始化,为类中的定义的静态变量进行赋值

3.初始化

为类中的定义的静态变量进行赋值

    • 类什么时候会初始化?

  1. 在类中运行main方法

  1. 创建对象

  1. 使用类中的静态变量以及静态方法

  1. 反射Class.forNname("类的地址")

  1. 初始化子类的同时也会初始化其父类

注意:以下两种情况不会进行类初始化

先创建两个类

public class User {
    static int a=10;
    static final int b=20;

    static{
        System.out.println(a);
    }
public class TestUser {
    public static void main(String[] args) {

    }
  1. 引用该类的静态常量

public class TestUser {
    public static void main(String[] args) {
  System.out.println(User.b);//调用类中的静态常量不会导致类的加载,有时会在常量在进行计算的情况下才会导致类的加载
    }
  1. 构造某一个类的数组时

public class TestUser {
    public static void main(String[] args) {
    User[] users=new User[10];//构造某个类的数组时不会导致该类的初始化
    }

6.类加载器

  1. 引导类加载器 :用c/c++语言进行开发,java底层的开发语言,负责加载java核心类库

  1. 扩展类加载器 :加载jdk下的 jre/lib/ext 子目录下加载类库

  1. 应用程序类加载器:加载程序中自己开发的类

 ClassLoader classLoader=User.class.getClassLoader();
 ClassLoader classLoader1=classLoader.getParent();
 System.out.println(classLoader);//sun.misc.Launcher$AppClassLoader@18b4aac2  程序类加载器
 System.out.println(classLoader1);//sun.misc.Launcher$ExtClassLoader@1b6d3586  扩展类加载器
 ClassLoader classLoader2=String.class.getClassLoader();
 System.out.println(classLoader2);//null  启动类加载器
双亲委派机制:

我们以String类为例,创建一个java.lang.String的一个类

public class String {
    static{
        System.out.println("自己创建的String类");
    }

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

我们在类中添加了一个main方法,按道理启动应该是没有什么大问题的,但是当我们运行之后,idea给我们报了一个错,说是在String这个类中找不到main方法,那发生这样的原因是什么呢

原理:当一个类加载器收到类加载请求时,先会委托给父类加载器加载,如果父类加载器还有其父类,则继续向上委托,直到到根加载器(引导类加载器),如果还是找不到,则向下交给子类进行加载,一次类推,直到加载成功或者报错 ClassNotFoundException 异常。

7.本地方法接口

1.什么是本地方法接口?

用native关键字修饰的方法称为一个本地方法,没有方法体,例如:

2.为什么用本地方法?

java语言需要与外部环境进行交互(例如需要访问内存,硬盘,其他的硬件设备),直接访问操作系统的接口即可。

8.执行引擎

1.作用

将加载到内存中的字节码(不能直接运行的机器码),解释/编译为不同平台的机器码。

2.为什么java是半编译半解释型语言?

解释器:将字节码逐行解释执行,效率低

编译器(JIT):将字节码编译,缓存起来,执行更高效,不会立即使用编译器

因为在java程序启动后,先使用解释器立即执行,省去了编译时间,程序运行一段时间后,对热点的编译缓存,提高了后续执行效率,故采用了解释器和编译器结合的方案

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

吃橘子的Crow

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值