JVM与JAVA

Java跨平台的语言

Java是一门面向对象编程语言,不仅吸收了C++语言的各种有点,还摒弃了C++里难以理解的多继承、指针等概念;因此Java语言具有功能强大和简单易用两个特征。Java语言作为静态面向对象编程语言的 代表,极好地实现了面向对象理论,允许程序员以优雅的思维方式进行复杂的编程。

一次编译,到处运行。

JVM与JAVA关系

Java是一门计算机编程语言

Jvm是一个跨平台的运行环境

Java生成的字节码可以在JVM平台上运行

JVM可以理解为Java的底层原理实现。

java运行流程

JVM运行架构

JVM:

类加载子系统---->运行时数据区--->理解两个对象--->执行引擎+GC--->监控与参数--->高级案例

类加载子系统---->程序计数器--->虚拟机栈--->本地方法栈--->Heap堆--->方法区--->String对象

--->Object对象--->执行引擎--->垃圾回收--->监控命令--->图形监控--->GC日志--->运行参数

--->常见故障--->性能调优--->真实案例--->生态优化

JVM类加载流程

class字节码

javap -c demo.class

Compiled from "demo.java" public class demo { static int a; public demo(); Code: 0: aload_0 1: invokespecial #1 // Method java/lang/Object."<init>":()V 4: return public static void main(); Code: 0: return static {}; Code: 0: iconst_1 1: putstatic #7 // Field a:I 4: return }

class与字节码

(a) class文件是一种字节码体现形式,但字节码不局限于class文件,它本质是一段二进制流,可以以其它形式存在;

(b)字节码是一种通用的、与平台无关的存储格式。理论上任何编程语言,只要能被编译成字节码,就可以交付给JVM去跨平台的运行

(c)Java语言在诞生之初喊出的口号"write once,Run anywhere",正是基于字节码(byte code)设计,java能够做到平台无关性,字节码功不可没

(d)从结构角度上讲,class字节码包括了魔幻数、版本好、常量池等信息

魔幻数: 0xCAFEBABE

版本信息:class文件的次要版本和主要版本

Constant Pool:类的常量池

Access Flags:例如类是否为抽象类、静态类等

This class: 当前类的名称

Super Class: 超类的名称

Interfaces:类中的任何接口

Fields: 类中的任何字段

Methods: 类中的任何方法

Attributes:类的任何属性

类加载子系统:

|-------------------------------|-------------|
| 加载阶段Loading | 链接阶段Linking |
| 引导类加载 BootStrap ClassLoader | 验证 Verify |
| 扩展类加载 ExtenSion ClassLoader | 准备 Prepare |
| 应用类加载 Application ClassLoader | 解析 Resolve |

类加载器是将字节码文件转换为JVM内存Class对象的工具

(1) 类在使用之前,首先要调用类加载子系统进行加载

(2)类加载子系统负责从文件或者网络中加载字节码文件

(3)类加载的过程是按照二进制流的方式进行加载,并且遵循class字节码规范

(4)类加载子系统只负责确保类的正确加载,是否允许,则由执行引擎决定

(5)加载的类信息存放于方法区,除了类信息外,字节码中的常量池,会加载至方法区,形成运行时常量池。

类加载流程:

class文件-->加载-->验证-->准备-->解析-->初始化-->卸载

加载:通过类全名获取类二进制流,并将静态的存储结构,加载到运行时数据区中的方法区(生成class类对象),加载的来源常见有本地文件,网络流,压缩包,动态代理等等。

验证:确保class文件的字节流中包含信息符合当前虚拟机要求,保证被加载类的正确性,不会危害虚拟机自身安全,主要包括四种验证,文件格式验证,元数据验证,字节码验证,符合引用验证。

准备:为static变量/类变量分配内存(方法区),并且设置该变量的初始值为(不包括final和实例变量)

解析:主要是将常量池中的符号引用替换为直接引用,比如类、接口、方法、字段等等。

初始化:真正执行初始化类阶段;若该类具有超类,先对超类进行初始化,在单个类内部,初始化包括:类变量/静态初成员初始化,初始化代码块,静态构造函数初始化。

双亲委派机制

(1)当一个类加载器收到了类加载的请求的时候,他不会直接区加载指定的类,而是把这个请求委托给自己的父加载器去加载;

(2)如果父类加载器,还存在父类加载器,则进一步向上委托,直到引导类加载器;

(3)如果父类加载器,可以完成加载,则因为加载完成,否则,则反向采用子类依次加载,直到成功;

(4)父类加载器永远优先于子类加载器加载。

双亲委派的优势:

(1)避免类的重复加载,确保一个类的全局唯一性

(2)Java类随着它的类加载器一起具备了一种带有优先级的层次关系,通过这种层级关可以避免类的重复加载,当父亲已经加载了该类时,就没有必要子classloader再加载一次

(3)保护程序安全,防止核心API被随意篡改。

弊端:

检查类是否加载的委托过程是单向的,这个方式虽然从结构上说比较清晰,使各个classLoader的职责非常明确,但是同时会带来一个问题,即顶层的classloader无法访问底层的classloader所加载的类。

如何破坏:

(1)双亲委派的核心实现在classloader中的loadclass(String name, boolean resolve)

(2)自定义一个类加载器,重写其中的loadclass方法,使其不进行双亲委派即可。

相关推荐
Mr__Miss2 小时前
JMM中的工作内存实际存在吗?
java·前端·spring
Gary董2 小时前
内存泄漏和溢出
java·jvm
独隅2 小时前
本地大模型训练与 API 服务部署全栈方案:基于 Ubuntu 22.04 LTS 的端到端实现指南
服务器·python·语言模型
Elieal2 小时前
SpringBoot 中处理接口传参时常用的注解
java·spring boot·后端
程序员侠客行2 小时前
Spring集成Mybatis原理详解
java·后端·spring·架构·mybatis
程序员miki2 小时前
训练yolo11检测模型经验流程
python·yolo
摇滚侠2 小时前
在 IDEA 中,GIT 合并分支时选择远程的 dev 分支和本地的 dev 分支,有区别吗
java·git·intellij-idea
夏了茶糜2 小时前
Python中生成器表达式(generator expression)和列表推导式(list comprehension)的区别
python·列表推导式·生成器表达式
fanruitian2 小时前
k8s 更新镜像
java·服务器·kubernetes