JVM概述和类加载子系统

简介: 我记得当年学java的时候,就很好奇,为什么我在IDEA上写一些代码(其实就是一堆我们人能知道的英文单词的组合加一些运算符),为什么就可以在windows上运行后执行我们的指令,而且还可以打成jar包去linux系统跑起来,为什么一份代码可以在不同平台运行呢?类是如何加载的?对象如何创建的以及都有哪些信息?我创建的对象被分配到哪个内存去了?java是怎么和我们操作系统打交道的又是怎么调用CPU为我们计算的?创建了对象分配了内存,为什么可以不用手动回收就可以自动清理内存等等等,相信你也同样有过这些困惑。

目录

一、前言

大家好,我是苍何。最近思考了一个问题,为什么会出现公司面试造火箭,工作扭螺丝的现象,包括各种八股文的连环大绝杀问到你不会为主,其实这是考察你的知识面以及掌握的深度,而为什么需要这样呢?归其原因,无非是通过筛选找到那些会思考的人,他们需要的并不是CRUD的工具人,而是会思考能创新的工程师。

当你深刻理解到这点,我想不用刻意去学习,在工作中,肯定会吾日三省吾身。

于是乎,这个重新开始学习编程系列文章出来了。

愿与君共勉!

我记得当年学java的时候,就很好奇,为什么我在IDEA上写一些代码(其实就是一堆我们人能知道的英文单词的组合加一些运算符),为什么就可以在windows上运行后执行我们的指令,而且还可以打成jar包去linux系统跑起来,为什么一份代码可以在不同平台运行呢?类是如何加载的?对象如何创建的以及都有哪些信息?我创建的对象被分配到哪个内存去了?java是怎么和我们操作系统打交道的又是怎么调用CPU为我们计算的?创建了对象分配了内存,为什么可以不用手动回收就可以自动清理内存等等等,相信你也同样有过这些困惑。

之前我都是部分在一些博客或者网站上进行查看资料,概念大概能理解,但可能还不够系统的掌握这部分知识,现在我看了几百集的宋红康老师的视频教程,感到收益匪浅,特此总结记录一下。

下面就我的理解以及一些宋红康老师的图形进行一个系统的总结。我做了个系统轮廓的导图:

为了防止文章过于长,我将分几篇文章进行发布。

二、虚拟机的概念

系统虚拟机:
VMware,可运行完整操作系统的软件平台
程序虚拟机:
运行字节码指令,如java虚拟机

三、JVM整体概述

执行字节码的虚拟计算机,所有java程序都运行在java虚拟机内部
一次编译,到处运行,自动内存管理,自动垃圾回收功能

1、JVM整体架构


2、java代码的执行流程

java程序经过前端编译器编译成class文件,也即字节码文件,这些文件我们用文本工具打开,就是这样一串乱码的东东


我们可以用idea的jclasslib Bytecodes viewver打开字节码文件,可以看到其实是包含很多结构的,有方法的信息,字节码指令,局部变量表信息及长度等。

表明这个class文件其实就是一些指定格式的文件,也就是说不光java语言,其他语言,只要按照规范的格式也是可以被JVM虚拟机识别并执行的,所以JVM不仅仅只是java虚拟机。

如下图,不同平台的JVM实现会去运行字节码文件,通过JVM转为各个系统所能识别的操作指令,然后通过CPU执行运算,这就是java代码的执行流程,当然这其中会涉及很多,让我们慢慢看。


3、JVM生命周期

1、虚拟机的启动
是通过引导类加载器创建一个初始类来完成的,这个类是由虚拟机的具体实现指定的
2、虚拟机的执行
程序开始执行,程序结束后就结束,
执行一个所谓的java程序,真正在执行的是一个叫java虚拟机的进程
3、虚拟机的退出
程序正常结束、异常、操作系统出现错误,线程调用System.exit()方法

4、JVM发展历程

1、Sun Classic VM
第一款商用虚拟机,只提供了解释器,现在hotspot内置了此虚拟机
2、exact VM
准确是内存管理
3、HotSpot VM
通过计数器找到最具编译价值代码,触发即时编译或栈上替换
通过边以及与解释器协同工作,在最优化的程序响应时间与最佳执行性能中取得平衡
4、JRockit
专注于服务器端应用数据显示是最快的虚拟机,全部代码都靠即时编译器执行
5、J9
有影响力的三大商用虚拟机之一,

四、类加载子系统

1、概述

类加载子系统是JVM用类加载器将类加载进内存,类的信息会存放于运行时数据区的方法区(后面会细说),加载类的时候也会做一些初始化的操作,如会进行clinit和init等。

2、类的加载过程

相信很多伙伴面试都被问到过这吧,要说好这道题,得仔细理解。

总共分三大快来讲
首先是加载阶段,将.class文件加载到内存
其次是链接阶段,这部分又包含验证、准备和解析阶段
最后最初始化操作

加载阶段:


链接阶段

初始化

clinit其实就是初始化类中静态的变量,如int静态变量会初始化为0,init就是初始化类的构造器。

3、类加载器

分2类,引导类加载器和自定义类加载器,直接或间接继承抽象类ClassLoader的类加载器都划分为自定义类加载器。

这里说几个常用的类加载器,在后面双亲委派机制会用到
1、启动类加载器(Bootstrap ClassLoader)
虚拟机自带的加载器,java的核心类库都是通过该类加载器进行加载的,处于安全,Bootstrap启动类加载器只加载包名为java、javax、sun等开头的类
2、扩展类加载器
加载扩展目录jre/lib/ext子目录下的
3、系统类加载器
用户自定义的类来说,默认用的是系统类加载器进行加载(属于自定义类加载器)

注意:这三个是有层级关系的,123分别是从上到下的关系,这里的层级并不是父子的关系,倒像是目录的那种层级关系

如何获取当前类的类加载器:

4、双亲委派机制

一个类加载器收到了类加载请求,他是不会先去自己加载的,而是会去委托自己的父类去加载,如果父类加载器还存在其父类加载器,则递归一直向上委托,请求其实最终都会到达顶层的启动类加载器(这里不明白层级的可以看第3点讲的层级关系),如果父类加载器可以加载该类就由他来加载,如果做不到,就给子类自己去加载罢了。



优势:
1、避免类重复加载
2、保护程序安全,防止核心类API被篡改。

5、沙箱安全机制

所谓沙箱安全机制,其实就是为了保护java的核心API而设置的,其实和双亲委派机制都是用来保护核心API的,比如,你自定义一个包也叫java.lang,并也定义了一个类也叫String,这时候定义一个main方法,启动,会发现程序报错。

这是因为,类加载器真正去加载的其实是核心API下的String类,根本不是我们自定义的类,也就是我们自定义的类压根没被加载到内存中来,当我们执行main方法,核心包下的String类当然没有该方法。

所以在建包的时候,也不允许建和核心API同名的包,实际公司中,通常都会以公司域名或者标识进行包名命名。

目录
相关文章
|
1月前
|
前端开发 安全 Java
聊聊Java虚拟机(一)—— 类加载子系统
虚拟机就是一款用来执行虚拟计算机指令的计算机软件。它相当于一台虚拟计算机。大体上,虚拟机分为系统虚拟机和程序虚拟机。系统虚拟机就相当于一台物理电脑,里面可以安装操作系统;程序虚拟机是为了执行单个计算机程序而设计出来的虚拟机。其中 Java 虚拟机就是**执行 Java 字节码指令的虚拟机**。
37 2
|
5月前
|
前端开发 安全 Java
JVM类加载和双亲委派机制
JVM类加载和双亲委派机制
102 0
|
28天前
|
Java 应用服务中间件
深入理解JVM - 类加载器概述
深入理解JVM - 类加载器概述
9 0
|
28天前
|
安全 Java 程序员
深入理解jvm - 类加载过程
深入理解jvm - 类加载过程
35 0
|
2月前
|
存储 前端开发 安全
浅谈 JVM 类加载过程
浅谈 JVM 类加载过程
32 0
|
2月前
|
存储 安全 Java
JVM类加载(类加载过程、双亲委派模型)
JVM类加载(类加载过程、双亲委派模型)
|
7月前
|
算法 Java UED
JVM之垃圾回收器概述
JVM之垃圾回收器概述
|
3月前
|
存储 算法 安全
面试~jvm(JVM内存结构、类加载、双亲委派机制、对象分配,了解垃圾回收)
面试~jvm(JVM内存结构、类加载、双亲委派机制、对象分配,了解垃圾回收)
47 0
|
5月前
|
安全 前端开发 Java
JVM(一)JVM概述
JVM(一)JVM概述
35 0
|
6月前
|
存储 安全 前端开发
【jvm系列-02】jvm的类加载子系统以及jclasslib的基本使用
【jvm系列-02】jvm的类加载子系统以及jclasslib的基本使用
49 0