JAVA虚拟机JVM工作原理

提起JAVA,都知道它有个虚拟机,因此可以跨平台,一次编写,到处运行。但具体原理是咋样的?身为JAVA小白,岂可不知!

一、原理
二、结构
1、类加载器
2、执行引擎
3、运行时数据区域

一、原理
JVM实现了JAVA语言最重要的特征:平台无关性。其原理:java程序并不直接在操作系统上执行,而是由JVM执行。JVM屏蔽了与具体平台相关的信息,使得JAVA程序只需编译成适应JVM,可以在JVM上运行的目标代码(.class)就行,JVM再负责解释成具体平台的机器指令执行。同时,JVM还会进行安全检查,是java程序的安全检验引擎。

二、结构
JVM由三大部分组成:

1、类加载器
2、执行引擎
3、运行时数据区域

在这里插入图片描述
也有说法是包括本地库接口的。
在这里插入图片描述
首先通过编译器把 Java源代码转换成字节码,Class loader(类装载)再把字节码加载到内存
中,将其放在运行时数据区的方法区内,而字节码文件只是 JVM 的一套指令集规范,并不能直
接交给底层操作系统去执行,因此需要特定的命令解析器执行引擎(Execution Engine),将
字节码翻译成底层系统指令,再交由 CPU 去执行,而这个过程中需要调用其他语言的本地库
接口(Native Interface)来实现整个程序的功能。

1、类加载器
具体作用就是将.class文件加载到jvm虚拟机中去,程序就可以正确运行了。但是,jvm启动的时候,并不会一次性加载所有的.class文件,而是根据需要去动态加载。

类的加载过程采用双亲委派模型:

1)当前类加载器首先检查自己的加载清单,如果存在该类,则返回之;

2)如果没找到,委托父类加载器去加载;父类加载器重复动作1,递归至祖宗bootstrap ClassLoder(我靠,bootstrap,还以为是前端框架呢。bootstrap,引导之意);

3)都没有,仍然由当前类加载器加载,并纳入自己缓存中。

采用双亲委派模型,目的在于更好的保证Java平台的安全。所谓的安全,是指java的核心类不被用户自己编写的类所替换。由于核心类在虚拟机初始化时就已加载,而每次加载类前先检查是否存在,所以可以避免核心类被替换。

各种类加载器:
在这里插入图片描述
Bootstrap class loader: 启动类加载器(或曰父类加载器)
当运行 java 虚拟机时,这个类加载器被创建,它负责加载虚拟机的核心类库,如 java.lang.* 等。例如 java.lang.Object 就是由根类加载器加载的。需要注意的是,这个类加载器不是用 java 语言写的,而是用 C/C++ 写的。

这个类加载器负责将存放在<JAVA_HOME>lib目录中的,或者被-Xbootclasspath参数所指定的路径中的,并且是虚拟机识别的(仅按照文件名识别,如rt.jar,名字不符合的类库即使放在lib目录中也不会被加载)类库加载到虚拟机内存中。

Extension class loader:扩展类加载器
这个加载器加载出了基本 API 之外的一些拓展类。

这个加载器由sun.misc.Launcher$ExtClassLoader实现,它负责加载<JAVA_HOME>libext目录中的,或者被java.ext.dirs系统变量所指定的路径中的所有类库,开发者可以直接使用扩展类加载器。

AppClass Loader(SystemAppClass):
加载应用程序和程序员自定义的类。

2、执行引擎
作用: 执行java编译好的字节码,或者执行本地方法

3、运行时数据区域
JVM 运行时数据区域 (JVM Runtime Area) 其实就是指 JVM 在运行期间,其对JVM内存空间的划分和分配。JVM在运行时将数据划分为6个区域来存储:

Program Counter (PC) Register:程序计数器

Java Virtual Machine Stacks:Java虚拟机栈

Heap Memory:堆内存

Method Area:方法区

Run-time Constant Pool:运行时常量池

Native Method Stacks:本地方法栈

在这里插入图片描述

我们写的所有程序都被加载到这里,按不同类别存放在

堆内存
Java虚拟机栈
本地方法栈
程序计数器
方法区

1)从线程的角度理解Java Runtime Area

a.线程私有:
程序计数器 Java虚拟机栈 本地方法栈,生命周期与线程一致;

这3个内存区域是不需要进行垃圾回收的。因为他们的生命周期是和线程同步的,随着线程的销毁,他们占用的内存会自动释放。

b.线程共享:
堆内存,方法区,运行时常量池,生命周期与JVM一致。

方法区堆内存需要进行垃圾回收,回收的对象就是那些不存在任何引用的对象。

2)从存储内容理解Java Runtime Area

方法区常量池存储类的信息

堆内存存储对象信息

程序计数器Java虚拟机栈本地方法栈存储线程的信息

3)堆内存、方法区和运行时常量
方法区的作用是存储 Java 类的结构信息,当我们创建对象实例后,对象的类型信息存储在方法区之中,实例数据存放在堆内存中;

运行时常量池是方法区的一部分,所以也是全局共享的。其作用是存储 Java 类文件常量池中的符号信息。

运行时常量池就是将编译后的类信息放入方法区中,也就是说它是方法区的一部分。 运行时常量池用来动态获取类信息,包括:class文件元信息描述、编译后的代码数据、引用类型数据、类文件常量池等。 运行时常量池是在类加载完成之后,将每个class常量池中的符号引用值转存到运行时常量池中。

4)直接内存(Direct Memory)
直接内存并不是JVM管理的内存,而是JVM以外的机器内存。比如,你有4G的内存,JVM占用了1G,则其余的3G就是直接内存。

JDK中有一种基于通道(Channel)和缓冲区(Buffer)的内存分配方式,将由C语言实现的native函数库分配在直接内存中,用存储在JVM堆中的DirectByteBuffer来引用。由于直接内存收到本机器内存的限制,所以也可能出现OutOfMemoryError的异常。

=====================================
2022.09.18

【什么是永久代?它和方法区有什么关系呢?】
如果在HotSpot虚拟机上开发、部署,很多程序员都把方法区称作永久代。可以说方法区是规
范,永久代是Hotspot针对该规范进行的实现。在Java7及以前的版本,方法区都是永久代实现
的。

【什么是元空间?它和方法区有什么关系呢?】
对于Java8,HotSpots取消了永久代,取而代之的是元空间(Metaspace)。换句话说,就是方
法区还是在的,只是实现变了,从永久代变为元空间了。

【HotSpot】
SUN的JDK版本从1.3.1开始运用HotSpot虚拟机, 2006年底开源,主要使用C++实现,JNI接口部分用C实现。

HotSpot是较新的Java虚拟机,用来代替JIT(Just in Time),可以大大提高Java运行的性能。

Java原先是把源代码编译为字节码在虚拟机执行,这样执行速度较慢。而HotSpot将常用的部分代码编译为本地(原生,native)代码,这样显着提高了性能。 HotSpot JVM 参数可以分为规则参数(standard options)和非规则参数(non-standard options)。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值