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

大学城网站开发公司电话成都优化网站推广

大学城网站开发公司电话,成都优化网站推广,wordpress获取QQ,怎么做网站推广类加载子系统与加载过程 #x1f604;生命不息#xff0c;写作不止 #x1f525; 继续踏上学习之路#xff0c;学之分享笔记 #x1f44a; 总有一天我也能像各位大佬一样 #x1f3c6; 博客首页 怒放吧德德 To记录领地 #x1f31d;分享学习心得#xff0c;欢迎指正…类加载子系统与加载过程 生命不息写作不止 继续踏上学习之路学之分享笔记 总有一天我也能像各位大佬一样 博客首页   怒放吧德德  To记录领地 分享学习心得欢迎指正大家一起学习成长 文章目录 类加载子系统与加载过程内存结构简介类的加载过程1) 加载(Loading)2) 链接(Linking)① 验证(Verification)② 准备(Preparation)③ 解析(Resolution) 3) *初始化(Initialization)何时促发初始化\init()与\clinit() 类的加载器1) 三个核心类加载器2) 自定义类加载器为什么要自定义加载类如何自定义类加载器 3) 双亲委派机制① 双亲委派的原理② 双亲委派机制优势③ 沙箱安全机制④ 破坏双亲委派机制 总结博客文献 内存结构简介 Java虚拟机会通过类加载器子系统去加载字节码在类加载的过程还包括了将字节码文件加载到内存JVM会验证字节码文件的格式、解析符号引用初始化类、接口等为静态字段分配内存并初始化。会在内存中创建相应的对象以及对一些静态变量进行初始化等操作这部分主要是在方法区中执行。然而真正执行字节码指令的是执行引擎他会根据字节码的顺序去执行这也就涉及了计数器、栈等的操作。 类的加载过程 类加载器包括了加载、链接、初始化三个阶段每个阶段都有各自的处理行为。 类加载器Class Loader是Java虚拟机JVM的一个关键组件它负责将类文件加载到内存中以便在程序中使用。类加载器的主要任务是在运行时查找并加载类文件然后生成类的字节码以供JVM执行。类加载器的主要功能包括加载、链接和初始化类。 类的加载流程如下1) 加载Loading 类加载器查找类文件通常是.class文件然后将它们加载到内存中。加载过程包括查找类文件、读取类文件的字节码数据并创建一个表示类的java.lang.Class对象。2) 链接Linking 链接分为三个阶段验证、准备和解析。① 验证Verification 在这个阶段类加载器确保类文件的字节码是合法、符合规范的并且不包含危险的构造。这是为了确保安全性。② 准备Preparation 在这个阶段类的静态变量分配内存并初始化为默认值。③ 解析Resolution 这个阶段负责将符号引用解析为直接引用以便JVM能够识别和访问其他类和方法。3) 初始化Initialization 在这个阶段类的静态初始化块static initializer被执行静态变量被赋予初始值。这是类加载的最后一个阶段。*类加载器子系统只是负责加载字节码文件至于它能否运行还是得由执行引擎来决定。加载类信息包括类的结构信息、运行时常量池、父类信息并且建立继承和接口实现关系。 需要注意的是在Java 8之前这些信息存储在方法区中而在Java 8及以后方法区被替代为元数据区Metaspace并且元数据区采用了一种不同的内存管理方式它会根据需要动态分配和回收内存而不是采用固定的区域大小。 1) 加载(Loading) 加载时类加载过程的第一个阶段在加载阶段Java虚拟机需要完成以下三件事情 通过一个类的全限定名来获取其定义的二进制字节流。将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构。在Java堆中生成一个代表这个类的java.lang.Class对象作为对方法区中这些数据的访问入口 这个类加载就是加载二进制字节流的动作开发者不仅可以使用系统提供的加载器加载也可以是自己自定义一个类加载器在自己自定义的类加载器中去做一些其他的操作。类加载会将class文件的结构、方法、字段、注解、访问权限等信息加载到方法区/元数据区中堆中会用于存储对象实例的内存区域。 类的加载方式 从本地系统中直接加载通过网络下载.class文件从zipjar等归档文件中加载.class文件从专有数据库中提取.class文件将Java源文件动态编译为.class文件 2) 链接(Linking) 链接阶段又分为三个阶段分别是验证、准备、解析。目的是为了确保类的结构和引用在运行时是有效的和安全的。通过验证、准备和解析JVM可以在类加载时会进行必要的检查和调整以防止潜在的安全问题和运行时错误。这有助于维护Java程序的稳定性和安全性。在链接阶段中类变量静态变量会被分配默认值。对于基本数据类型这个默认值通常是0或0.0。对于对象引用类型这个默认值是null。 ① 验证(Verification) 在验证阶段类加载器需要确保类文件的字节码是否合法、符合规范的并且不会造成危险。简单来说就是确保被加载类的正确性。 验证的方式 格式验证检查字节码文件的格式是否正确。语义验证检查字节码文件中的操作是否符合Java语言规范。字节码验证检查字节码文件中的操作是否与类的结构和继承关系一致。符号引用验证检查符号引用是否有效不引用不存在的类或字段。 类加载的字节码文件字节流数据是以0xCAFEBABE开头。这是一种规范能够来验证字节码文件是否符合Java规范。这里我们可以看一下编译后的Java字节码的二进制数据长什么样。我们可以在idea中安装一个插件【BinEd-binary-hexadecimal-editor】然后我们找到编译后的Java字节码文件然后右键-open in-Binary Editor就可以在界面上看到十六进制/二进制与代码的对应。 从图中我们就能看到0xCAFEBABE这段十六进制数值。 ② 准备(Preparation) 准备阶段主要是用于为类的静态字段分配内存并初始化这些字段。这些字段将在类初始化阶段Initialization中赋予实际的初始值。 当我们在类中定义了一个变量public static int a 1;此时在准备阶段的时候这个值是0并不是1直到初始化阶段的时候才会被赋值为1。 但是这里不包含使用final修饰的static因为final修饰的变量在编译的时候就会分配好内存准备阶段会显式初始化。如果final修饰的变量进行赋值此时会直接报错。 在准备阶段常量字段public static final修饰的字段被视为常量会被分配内存并赋予初始值。对于public static final int c 3; 这个常量字段它的初始值将被设置为3。这是因为public static final字段被认为是编译时常量其值在编译时已经确定。 这里不会为实例变量分配初始化类变量会分配到方法区中而实例变量是会随着对象一起分配到Java堆中。 ③ 解析(Resolution) 解析阶段负责将符号引用解析为直接引用以便JVM能够识别和访问其他类和方法。符号引用是一种符号化的引用它以符号的方式描述了类、字段、方法或接口的引用而不包括直接的内存地址或偏移量。直接引用是实际的内存地址或偏移量它用于直接定位并访问类的实例、字段、方法或接口。解析动作主要针对类或接口、字段、类方法、接口方法、方法类型、方法句柄和调用点限定符7类符号引用进行。 3) *初始化(Initialization) 初始化阶段Initialization是初始化过程的关键步骤。在这个阶段类的静态初始化块static initializer会被执行用于为静态字段分配实际的初始值。静态初始化块可以包含任意Java代码通常用于执行一些静态设置操作。需要注意的是初始化是懒加载的即只有在首次触发初始化时才会执行。一旦类被成功初始化它不会再次初始化除非应用程序中的某些特殊情况强制重新初始化类。 何时促发初始化 创建类的实例当创建类的实例时首先要确保类已经被初始化。访问类的静态字段或静态方法访问静态成员时会触发类的初始化。使用反射操作通过反射方式访问类时也会触发初始化。 init()与clinit() 首先我们需要了解一下init()与clinit()这两个Java编译自动生成的方法。 方法 这是类的构造方法用于对象的初始化。构造方法的名称是它包括在类的字节码中以执行对象初始化操作。不同的构造方法可以接受不同的参数用于初始化对象的各个属性。首先我们通过一个例子来了解一下Java 的方法以下编写了一段两个变量的Java代码a是成员变量b、c是局部变量通过构造方法来对a进行赋值。我们在idea安装 jclasslib-bytecode-viewer 插件可以通过这个插件来查看Java字节码。 public class JVM01 {private int a 1;public JVM01() {a 10;}public static void main(String[] args) {int b 3;int c 4;} }点击view-show byteCode with jclasslib就能够看到字节码 init方法是类的构造方法我们点开init下的code可以清楚的看到字节码执行过程一开始加载变量a初始化1然后进行赋值为10。 0 aload_01 invokespecial #1 java/lang/Object.init : ()V4 aload_05 iconst_16 putfield #2 com/lyd/testboot/jvm/JVM01.a : I9 aload_0 10 bipush 10 12 putfield #2 com/lyd/testboot/jvm/JVM01.a : I 15 return同样我们可以在main#code中看到main中成员变量的赋值情况 0 iconst_3 1 istore_1 2 iconst_4 3 istore_2 4 return我们可以看到开始给b赋值了3后面给c赋值了4。可见字节码的执行也是按照代码的顺序去执行的。 方法 这是类的静态初始化块static initializer用于静态成员的初始化。静态初始化块的名称是它包括在类的字节码中用于执行静态字段的初始化和执行静态初始化块中的代码。静态初始化块在类加载的初始化阶段执行确保静态成员的初始值被正确设置。clinit方法是类的静态初始化我们简单的做个案例定义一个sta静态变量并令其值为1在静态代码块中我又给他赋值了111在main方法再次赋值为11最终静态变量sta的值会是最后的值11接着我们在创建一个变量stb这回我们把变量的赋值放在之前在静态代码块之后去声明变量。 public class JVM01 {private int a 1;public static int sta 1;public JVM01() {a 10;}static {sta 111;stb 222;}public static int stb 2;public static void main(String[] args) {int b 3;int c 4;JVM01.sta 11;} }我们通过jclasslib-bytecode-viewer插件来看一下字节码 stastb在准备阶段的时候默认值是0(因为是int类型)直到分配内存确认值之后分别赋值为1和2接着会执行静态代码块执行的时机是在类被加载到内存中但在类的实例被创建之前。静态代码块在连接阶段执行而不是在类的实例化或初始化阶段执行。此时分别会被赋值为111和222那么sta在main中赋值为11等静态代码块执行完毕之后就会执行main方法在执行main方法就会将sta的值赋值为11所以最终的值也就是11。我们点开main#code来看一下执行流程可见被赋值为11。 0 iconst_3 1 istore_1 2 iconst_4 3 istore_2 4 bipush 11 6 putstatic #3 com/lyd/testboot/jvm/JVM01.sta : I 9 return类的加载器 类的加载器负责将类文件加载到内存中以便在Java程序中使用。类加载器是Java实现动态加载和模块化编程的基础它有助于实现模块化开发、热部署和插件化架构等功能。主要包括引导类加载器Bootstrap Class Loader、扩展类加载器Extension Class Loader、应用程序类加载器Application Class Loader还有自定义类加载器User Class Loader。这些类加载器在jvm启动是自动创建并运行他们的操作都遵循双亲委派机制就是在加载类的时候都会向上委托询问父类加载类知道所有的父类加载器无法加载的情况下当前类加载器才会尝试加载。 1) 三个核心类加载器 简单说一下引导类、扩展类、系统类加载器是什么每个都有特定的职责和加载类的范围。① 引导类加载器Bootstrap Class Loader引导类加载器是负责加载核心的Java类库如java.lang包中的类以及其他Java平台的关键组件。这些类库通常存储在JVM安装目录下的lib目录中。开发人员无法直接访问引导类加载器它主要用于加载Java运行时环境的核心类。引导类加载器只会加载包为java、javax、sun等开头的类。② 扩展类加载器Extension Class Loader扩展类加载器可以通过系统属性java.ext.dirs来指定扩展类库的位置。③ 系统类加载器Application Class Loader系统类加载器负责加载位于类路径Classpath上的类文件包括用户编写的类和第三方库。大多数Java应用程序都是由系统类加载器加载的因为它加载位于类路径上的类。我们可以在代码层面来查看加载器通过java.lang.ClassLoader#getSystemClassLoader()来获取系统类加载器。得到的ClassLoader类可以继续ClassLoader#getParent()获取上层的类加载器也就是扩展加载器直到最上一层的引导类加载器此时我们获取的值是为null由此可见我们是拿不到引导类加载器。 public class ClassLoadShow {public static void main(String[] args) {// 获取系统类加载器ClassLoader classLoader ClassLoader.getSystemClassLoader();System.out.println(classLoader);// 获取上层扩展加载器ClassLoader extClassLoader classLoader.getParent();System.out.println(extClassLoader);// 继续获取上层加载器: null 获取不到引导类加载器ClassLoader bootstrapClassLoader extClassLoader.getParent();System.out.println(bootstrapClassLoader);// 获取当前类ClassLoader nowClassLoader ClassLoadShow.class.getClassLoader();System.out.println(nowClassLoader);// String是根据引导类加载器加载的。Java的核心类库都是System.out.println(String.class.getClassLoader());} }接下来我们通过sun.misc.Launcher#getBootstrapClassPath().getURLs()获取引导类路径Bootstrap Class Path中的URLs。这些路径内的核心Java类库都是引导类加载器里面的任何一个类.class#getClassLoader()都是为null。 public static void main(String[] args) {URL[] urLs Launcher.getBootstrapClassPath().getURLs();for (URL urL : urLs) {System.out.println(urL.toExternalForm());} }2) 自定义类加载器 我们还可以通过自定类加载器来定制加载类的方式。 为什么要自定义加载类 隔离加载类修改类的加载方式扩展加载方式防止源码泄露 如何自定义类加载器 ① 需要继承java.lang.ClassLoader类可以选择扩展ClassLoader的子类以便更容易加载外部类文件。②需要重写findClass(String name)方法这个方法负责查找和加载类的字节码。你需要提供自定义的类加载逻辑。③使用的时候创建一个测试类实例化你的自定义类加载器然后使用它来加载类。 package com.lyd.testboot.jvm;import java.io.File; import java.io.FileInputStream; import java.io.IOException;/*** Author: lyd* Date: 2023/10/17 00:08* Description:*/ public class MyClassLoader extends ClassLoader {// 指定加载类的路径private String classPath;public MyClassLoader(String classPath, ClassLoader parent) {super(parent);this.classPath classPath;}Overrideprotected Class? findClass(String name) throws ClassNotFoundException {try {byte[] classData loadClassData(); // 从文件或其他地方加载类字节码return defineClass(name, classData, 0, classData.length);} catch (Exception e) {e.printStackTrace();}return super.findClass(name);}/*** 使用字节流获取字节数据* return* throws IOException*/private byte[] loadClassData() throws IOException {// 这里要读入.class的字节因此要使用字节流需要转成绝对路径 D:/Code/Fly.classFile file new File(classPath);FileInputStream fis new FileInputStream(file);int length fis.available();byte[] data new byte[length];fis.read(data);fis.close();return data;}}测试的时候Class.forName有一个三个参数的重载方法可以指定类加载器平时我们使用的Class.forName(“XX.XX.XXX”)都是使用的系统类加载器Application ClassLoader。也可以是使用自定义的加载器MyClassLoader#loadClass()。 public class MyClassLoaderTest {public static void main(String[] args) {MyClassLoader myClassLoader new MyClassLoader(D:\\Code\\Fly.class, ClassLoader.getSystemClassLoader().getParent());try {// 输入外部类的绝对路径 // Class? myClass myClassLoader.loadClass(com.lyd.testboot.jvm.Fly);Class? myClass Class.forName(com.lyd.testboot.jvm.Fly, true, myClassLoader);Object o myClass.newInstance();System.out.println(o);System.out.println(o.getClass().getClassLoader());} catch (ClassNotFoundException e) {throw new RuntimeException(e);} catch (InstantiationException e) {throw new RuntimeException(e);} catch (IllegalAccessException e) {throw new RuntimeException(e);}} }我们可以通过打印的信息看到是通过我们自定义的类加载器去实现的 在这里个人出现最头疼的事情是第二行输出一直打印出来的是sun.misc.Launcher$AppClassLoader。这是因为这个Fly类会自动编译到项目的target目录底下这下面自然就是由Application ClassLoader加载的。然而解决方式就是在构造方法加上ClassLoader.getSystemClassLoader().getParent()把自定义ClassLoader的父加载器设置为Extension ClassLoader这样父加载器加载不到Person.class就交由子加载器MyClassLoader来加载了。 3) 双亲委派机制 双亲委派机制Parent Delegation Model是Java类加载机制的一个关键概念它用于描述类加载器在加载类时的工作方式。这个机制的核心思想是类加载器在加载类时首先尝试委派delegate加载请求给其父类加载器只有在父类加载器无法加载该类时才会自己尝试加载。这个机制能够确保类的一致性避免类被重复加载。 ① 双亲委派的原理 简单理解就是逐层委托知道父类加载器加载失败逐层下来直到都失败了最后由当前类加载器加载。那么其原理是什么呢我们可以由几个概念来学习。i 委派链Java类加载器按照层次结构组织每个类加载器都有一个父类加载器直到根加载器。这个层次结构构成了一个委派链。ii 加载类的请求当一个类加载器得到请求的时候并不会自己就尝试去加载类而是不断的委派给父类加载器。iii 双亲优先父类加载器优先加载如果父类加载器能够成功加载请求的类子类加载器就不再尝试加载。iv 检查类已加载在委派链上传递加载请求时每个类加载器都会首先检查是否已经加载了请求的类。如果类已经加载就直接返回该类的Class对象否则继续委派加载请求。v 根加载器根加载器通常是引导类加载器是类加载器层次结构的顶级它不具有父加载器。如果根加载器无法加载请求的类加载请求会向下传递到应用程序类加载器。vi 应用程序类加载器应用程序类加载器是Java应用程序的类加载器它通常是加载应用程序的起点。如果应用程序类加载器无法加载请求的类加载请求会继续向下传递到扩展类加载器然后到引导类加载器。 ② 双亲委派机制优势 防止类的重复加载保护程序防止核心API被篡改 ③ 沙箱安全机制 Java虚拟机 (JVM) 中的沙箱安全机制是一种用于保护系统免受不受信任的Java代码的潜在威胁的措施。这种机制是通过多层安全性措施和类加载机制来实现的以确保Java应用程序在运行时不会执行危险操作或访问敏感资源。就比如说我们自定义了一个String类这个类是lang包下的是由引导类加载器加载引导类会先加载rt.jar中的java\lang\String.class并且会报错说没有新增的方法。 ④ 破坏双亲委派机制 虽然双亲委派机制是默认行为但在某些情况下开发人员可能需要破坏这一机制自定义类加载器以实现特定的类加载行为。通常是在自定义加载器中去重写loadClass或者findClass方法覆盖 在JVM中类的完整类名(全限定名)需要完全一致并且加载器也需要是一样的这样才能说明是同一个类如果完整类名一样但是由不同的类加载器加载那么这两个类对象就不是同一个。 总结 类加载器子系统是JVM中的重要组件它是负责加载类在加载这一过程中还细化了加载、链接、初始化的三个重要阶段。在通过字节码我们可以看出Java的init与clinit方法为静态变量进行初始化与赋值。类的加载是遵循双亲委派机制 博客文献 自定义一个类加载器 - 五月的仓颉 - 博客园【精选】Java双亲委派模型为什么要双亲委派如何打破它破在哪里_为什么要打破双亲委派_徐同学呀的博客-CSDN博客 创作不易可能有些语言不是很通畅如有错误请指正感谢观看记得点赞哦
http://www.eeditor.cn/news/125879/

相关文章:

  • 基本建筑网站做网站和优化共多少钱?
  • 网站建设客户分析调查问卷湖南正规seo公司
  • h5免费网站设计gta5网站建设中
  • 旅游社网站建设规划书宁波小程序网络开发公司
  • 如何设置个人网站本地服务器公网ip wordpress
  • 网站开发和网页上传沈阳关键词seo排名
  • 株洲网站的建设微信公众平台怎样开发
  • 返利网站怎么做有限公司企业网站建设方案
  • 长春站建了多少年外贸php网站源码
  • 东莞网络网站建设网站的风格与布局的设计方案
  • 网站后台管理系统开发初学网站开发
  • 做游戏直播什么游戏视频网站好晋江小学网站建设
  • 甘南网站设计公司做初中物理题目的网站
  • 网站建设和安全管理制度单页设计用什么软件
  • 营销型网站优化企业网站建设流程第一步是什么
  • 选网站建设要注意什么wordpress 超酷主题
  • 电子贺卡在线制作网站湛江做网站哪家专业
  • 京津冀协同发展的首要任务有中国seo
  • 网站建设风险分析六安商务网站建设电话
  • 郑州哪有做网站的网站如何添加浮动窗口
  • 哪家公司网站制作好岑溪网站建设
  • 问什么出现 这个网站正在建设中php网站服务器架设
  • .net网站 还原数据库备份58同城本地网页版
  • 建网站 开发app乐趣浏览器app下载
  • 如皋建设工程局网站wordpress 图片下一页
  • 在线旅游网站昆山规划建设局网站
  • 建设银行贵金属网站常用的设计师网站
  • 电影网站制作教程及步骤聚财洋气三个字公司名字
  • 毕设做网站需要什么技术准备网络营销策划的内容
  • 注册公司域名后如何做网站wordpress盲注