当前位置: 首页 > news >正文

JavaSE丨深入剖析:从JVM类加载到反射编程的核心机制

一、JVM虚拟机

        JVM(Java Virtual Machine) 是Java平台的核心组件,它提供了跨平台的能力,使得Java程序可以在不同的操作系统上运行。JDK中的JVM负责解释和执行Java字节码文件,同时还提供了内存管理、垃圾回收等功能,使得Java程序能够高效、安全地运行。

JVM内存结构:

类加载器(Class Loader):类加载器负责加载Java字节码文件(.class文件), 并将其转换为可执行的代码。它将类加载到JVM的运行时数据区域中,并解析类的依赖关系

运行时数据区(Runtime Data Area):运行时数据区域是JVM用于存储程序运时数据的区域。它包括以下几个部分:

  • 方法区(Method Area):用于存储类的结构信息、常量池、静态变量等
  • 堆(Heap):用于存储对象实例和数组内存
  • 栈(Stack):也叫做虚拟机栈,方法调用执行、局部变量所需内存由它提供
  • 本地方法栈(Native Method Stack):本地方法栈与虚拟机栈所发挥的作用非常相似, 其区别是虚拟机栈为虚拟机执行Java方法服务, 而本地方法栈则是为虚拟机使用到的本地(Native)方法服务
  • 程序计数器(Program Counter):用于存储当前线程执行的字节码指令的地址

执行引擎(Execution Engine):执行引擎负责执行编译后的字节码指令,将其转换为机器码并执行。它包括解释器和即时编译器(Just-In-Time Compiler, JIT)两个部分,用于提高程序的执行效率。

垃圾回收器(Garbage Collector):垃圾回收器负责自动回收不再使用的对象释放内存空间。它通过标记-清除、复制、标记-整理等算法来进行垃圾回收。

本地方法接口(Native Method Interface):本地方法接口允许Java程序调用本地方法,即使用其他语言编写的代码。

二、类加载

通过上文大家已大致了解JVM内部构成,下面我们来讨论类加载具体细节及JVM详细构成。

JVM架构及执行流程如下:

解释执行

class文件内容,需要交给JVM进行解释执行,简单理解就是JVM解释一行就执行一行代码。所以如果Java代码全是这样的运行方式的话,效率会稍低一 些。

JIT(Just In Time)即时编译

执行代码的另一种方式,JVM可以把Java中的热点代码直接编译成计算机可以运行的二进制指令,这样后续再调用这个热点代码的时候,就可以直接运行编译好的指令,大大提高运行效率。

2.1 类加载器

类加载器可以将编译得到的 .class文件 (存储在磁盘上的物理文件)加载在到内存中。

2.2 加载时机

当第一次使用到某个类时,该类的class文件会被加载到内存方法区。

  • 使用 java 命令来运行某个主类
  • 创建类的实例(对象)
  • 调用类的 static方法
  • 访问类或接口的 static成员 ,或者为该类static成员赋值
  • 初始化某个类时,其父类会被自动加载
  • 使用反射方式(下文讲解)来获取类的字节码对象时,会加载某个类或接口的 class文件

2.3 加载过程

类加载的过程:加载、验证、准备、解析、初始化

具体加载步骤:

类加载小结:

JVM的类加载过程包括加载、验证、准备、解析和初始化等阶段,它们共同完成将Java类加载到内存中,并为类的静态变量分配内存、解析符号引用、执行静态代码块等操作,最终使得类可以被正确地使用和执行。

2.4 加载器分类

JDK8类加载器可以分为以下四类:

  • Bootstrap ClassLoader 根类加载器

也被称为引导类加载器,通常表示为null 。

它是Java虚拟机的一部分,负责加载Java核心类库,比如 rt.jar 等,根加载器是所有类加载器的顶级加载器,它不是一个Java对象,而是由 JVM 实现的一部分。

类一般存在 %JAVA_HOME%\jre\lib\rt.jar 中

  • Extension ClassLoader 扩展类加载器

负责加载Java的扩展类库,也可以通过 java.ext.dirs 系统属性来指定扩展类库的路径

这些类一般存在 %JAVA_HOME%\jre\lib\ext\ 下的jar包中

  • System ClassLoader 系统类加载器

它负责加载应用程序的类,包括用户自定义的类和第三方库等。

它是大多数 Java应用程序默认的类加载器。

系统类加载器的搜索路径包括当前工作目录和CLASSPATH环境变量指定的路径

  • User ClassLoader 自定义类加载器

自定义类加载器可以用于加载特定的类或实现类加载的特殊需求,目前应用很少,可忽略。

2.5 双亲委托

        双亲委托机制是Java类加载器的一种工作机制,通过层级加载和委托父类加载器来加载类,确保类的唯一性、安全性和模块化。

        如果一个类加载器收到类加载请求,它并不会自己先去加载,而是把这个请求委托给父类的加载器去执行,如果父类加载器还存在其父类加载器,则进一步向上委托,最终加载请求会到达顶层的启动类加载器 Bootstrap ClassLoader 。

        如果顶层类加载器可以完成加载任务,则进行class文件类加载,加载成功后返回。如果当前类加载器无法加载,则向下委托给子类加载器,此时子类加载器才会尝试加载,成功则返回,失败则继续往下委托,如果所有的加载器都无法加载该类,则会抛出ClassNotFoundException,这就是双亲委托机制。

三、反射

3.1 反射概述

Java反射机制是指在Java程序在运行状态下,动态地获取、检查和操作类的信息和对象的能力。

反射机制作用:

对于任意一个类,都能够知道这个类的所有属性和方法

对于任意一个对象,都能够调用它的任意一个方法和属性

这种动态获取信息以及动态调用对象方法的功能称为Java语言的反射机制。

当一个类被使用的时候,类加载器会把该类的字节码文件装入内存(类加载), 同时在堆空间创建一个字节码对象( Class 类对象) ,这个对象是Java反射机制的核心,它包含了一个类运行时信息。

3.2 反射核心类

在Java中, Class 类是一个重要的核心类,它用于表示一个类或接口的运行时信息。每个类在Java虚拟机中都有一个对应的 Class 对象,可以通过该对象获取类的构造函数、方法、属性等信息,并且可以进行实例化对象、方法调用和数据成员访问等操作。

Class核心类JavaSE源码:
package java.lang;// 字节码类
public final class Class<T> implements java.io.Serializable,GenericDeclaration,Type,AnnotatedElement {// 省略...// 获取类的所有构造方法@CallerSensitivepublic Constructor<?>[] getConstructors() throws SecurityException {checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), true);return copyConstructors(privateGetDeclaredConstructors(true));}// 获取类的所有数据成员@CallerSensitivepublic Field[] getFields() throws SecurityException {checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), true);return copyFields(privateGetPublicFields(null));}// 获取类的所有成员方法@CallerSensitivepublic Method[] getMethods() throws SecurityException {checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), true);return copyMethods(privateGetPublicMethods());}
}

在Java反射中,Class 、Constructor 、Method 和 Field 是表示类的不同部分的关键类。它们提供了访问和操作类的构造函数、方法和字段的方法。

Class 类:表示一个类的运行时信息。通过 Class 类可以获取类的构造函数、方法和字段等信息。可以使用 Class.forName() 方法获取一个类的 Class 对象,也可以通过对象的 getClass() 方法获取其对应的 class 对象。

Constructor 类:表示一个类的构造函数。通过 Constructor 类可以创建类的实例。可以使用 Class 对象的 getConstructors() 或 getConstructor() 方法获取构造函数的对象。

Method 类:表示一个类的方法。通过 Method 类可以调用类的方法。可以使用 Class 对象的 getMethods() 或 getMethod() 方法获取方法的对象。

Field 类:表示一个类的字段。通过 Field 类可以访问和修改类的字段的值。可以使用 Class 对象的 getFields() 或 getField() 方法获取字段的对象。

3.3 字节码对象

JVM虚拟机对类进行加载时,会在堆空间创建一个字节码对象( Class 类对象) 。

通过该字节码对象程序员可以获取类的构造函数、方法、属性等信息,并且可以进行实例化、方法调用和属性访问等操作。

简单来说:如果要用反射机制,则必须先获取类的字节码对象 ,那么如何获取呢?

获取 Class 对象方式:

1.使用类字面常量: 类名.class

2.Object类中方法: 对象.getClass()

public final native Class getClass();

3.借助Class类中方法:`Class.forName("类的全包名")``

public static Class forName(String className);

案例展示1:

使用前两种方式获取同一个类的字节码对象,并验证一个类的字节码对象是否唯一。

public class Test_Class {public static void main(String[] args) {String s = "hello";//1. 对象.getClass()Class<? extends String> c1 = s.getClass();//2. 类.classClass c2 = String.class;System.out.println("c1: " + c1);System.out.println("c2: " + c2);//验证同一个类的字节码对象是否唯一System.out.println("c1 == c2 : " + (c1 == c2));}
}//结果为true
案例展示2:

自定义Student类,然后使用三种方式获取该类的字节码对象,并验证字节码对象是否唯一。

自定义Student类:

public class Student {public String id;private String name;private int age;public Student() {}private Student(String id) {System.out.println("in private Student(id) ...");this.id = id;}public Student(String id, String name, int age) {this.id = id;this.name = name;this.age = age;}public String getId() {return id;}private void setId(String id) {this.id = id;}public String getName() {return name;}public int getAge() {return age;}@Overridepublic String toString() {return "Student [id=" + id + ", name=" + name + ", age=" + age + "]";}
}

测试类:

//使用3种不同方式,获取自定义类的字节码对象,并验证是否唯一
public class Test_Class {public static void main(String[] args) throws Exception {//第三种方式获取字节码对象,注意:参数为类的全包名Class<?> c1 = Class.forName("com.briup.chap13.bean.Student");Class c2 = Student.class;Student s = new Student();Class<? extends Student> c3 = s.getClass();System.out.println("c1: " + c1);System.out.println("c1 == c2 : " + (c1 == c2));System.out.println("c2 == c3 : " + (c3 == c2));}
}

注意事项:一个类的字节码对象,有且只有一个!

4.4 构造方法

通过反射可以获取类的构造方法(含private)对象,并借助其实例化对象。

1)构造器相关方法

2)Constructor类创建对象方法

4.5 成员变量

通过反射可以获取类的所有数据成员(含private)对象,进而实现数据成员值的获取与设置

1)Filed相关方法

2)属性获取及设置方法

4.6 成员方法

通过反射可以获取类里面所有的成员(含私有)方法,并调用。

1)Method获取相关方法

2)Method对象调用方法

4.7 综合案例

现有一个集合定义如下:

List list = new ArrayList<>();

要求,往list集合中添加元素:"hello"、123、3.14 请编码实现。

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;public class Test047_Question {public static void main(String[] args) throws Exception {List<Integer> list = new ArrayList<>();//1.获取字节码对象Class<? extends List> clazz = list.getClass();//2.获取add方法Method m = clazz.getDeclaredMethod("add", Object.class);//3.设置可以访问,添加元素m.setAccessible(true);m.invoke(list, "hello");m.invoke(list, 123);m.invoke(list, 3.14);//4.遍历集合Iterator<Integer> it = list.iterator();while(it.hasNext())System.out.println(it.next());}
}

注意:泛型只在编译阶段做语法检查,运行期间会被自动忽略


文章转载自:

http://inSRRlVQ.jfnLj.cn
http://g7waxSOK.jfnLj.cn
http://z5qJE5eZ.jfnLj.cn
http://6QKc3JmQ.jfnLj.cn
http://lJP2X7Vk.jfnLj.cn
http://Gi8o0yfq.jfnLj.cn
http://FBG30rO8.jfnLj.cn
http://95f2bqWw.jfnLj.cn
http://YRRCbORZ.jfnLj.cn
http://N367XF4Z.jfnLj.cn
http://2ZIN8Kav.jfnLj.cn
http://XetTbuMS.jfnLj.cn
http://NNYZ08FD.jfnLj.cn
http://Wk3oicEH.jfnLj.cn
http://zgNsshyZ.jfnLj.cn
http://ZzuYHmev.jfnLj.cn
http://Zqc9Puzz.jfnLj.cn
http://D6q6iXgM.jfnLj.cn
http://Yq1vcwop.jfnLj.cn
http://k56LTUlB.jfnLj.cn
http://L1e465yR.jfnLj.cn
http://TM0Z1GEE.jfnLj.cn
http://ZqbgHOZp.jfnLj.cn
http://bfc8iFFF.jfnLj.cn
http://hWOCbSTF.jfnLj.cn
http://hUvUZfCT.jfnLj.cn
http://OdvBsPzI.jfnLj.cn
http://tqi91HAB.jfnLj.cn
http://0y7tApZS.jfnLj.cn
http://et8suVnH.jfnLj.cn
http://www.dtcms.com/a/377159.html

相关文章:

  • eclipse中web项目编译后的lib里面jar为空问题处理
  • 非阻塞式等待和进程程序替换
  • 科技信息差(9.10)
  • Laya使用VideoNode动态加载视频,可以自定义播放视频此处以及位置
  • AWStats 网站日志分析工具简单介绍和常见问题
  • 在Windows 11上配置Cursor IDE进行Java开发
  • iOS App 混淆与反编译防护 iOS代码保护、ipa文件安全加固与应用逆向分析对抗全流程指南
  • 【Android】设置让输入框只能输入数字
  • 大数据探索性分析——抽样技术应用
  • 2010-2022 同等学力申硕国考:软件工程简答题真题汇总
  • 在FreeSSL上申请免费证书,将http改成https
  • micropython的属性式GPIO控制
  • 华为FreeBuds 7i没有弹窗如何解决?
  • 循环+函数
  • leetcode-hot100 11.盛水最多容器
  • pyspark 从postgresql读取数据
  • Spring Cloud Alibaba快速入门03-OpenFeign
  • Chrome 插件开发入门技术文章大纲
  • 小说写作中的时间轴管理:基于 Vue 3 的事序图技术实现
  • 计算机视觉与深度学习 | 计算机视觉中线特征提取与匹配算法综述
  • DAPP智能合约系统:技术解析与实现指南
  • AutoTrack-IR-DR200仿真导航实验详解:为高校打造的机器人学习实践平台
  • [模块教学]VK16K33_8×16LED矩阵屏的驱动以及技术文档,矩阵屏, 详细配置说明
  • BMT-370:开启智能楼宇通信新时代
  • stm32中 中断和事件的区别
  • Android开发入门系列教程
  • CSS 权重(优先级规则)
  • 快速搭建open-webui
  • Qt 信号-槽函数(signal - slot)
  • 机器学习算法之Boosting