iis服务器助手广告广告
返回顶部
首页 > 资讯 > 精选 >类的加载、链接和初始化是什么
  • 220
分享到

类的加载、链接和初始化是什么

2023-06-16 00:06:04 220人浏览 八月长安
摘要

本篇内容介绍了“类的加载、链接和初始化是什么”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!Java 类的加载Java类的加载是由类加载器来完

本篇内容介绍了“类的加载、链接和初始化是什么”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!

Java 类的加载

Java类的加载是由类加载器来完成的。

一般来说,类加载器分成两类:启动类加载器(bootstrap)和用户自定义的类加载器(user-defined)。

两者的区别在于启动类加载器是由JVM的原生代码实现的,而用户自定义的类加载器都继承自Java中的  java.lang.ClassLoader类。在用户自定义类加载器的部分,一般JVM都会提供一些基本实现。应用程序的开发人员也可以根据需要编写自己的类加载器。JVM中最常使用的是系统类加载器(system),它用来启动  Java应用程序的加载。通过java.lang.ClassLoader的 getSystemClassLoader()方法可以获取到该类加载器对象。

类加载器需要完成的最终功能是定义一个Java类,即把Java字节代码转换成JVM中的java.lang.Class类的对象。但是类加载的过程并不是这么简单。

Java类加载器有两个比较重要的特征:层次组织结构和代理模式。

层次组织结构指的是每个类加载器都有一个父类加载器,通过  getParent()方法可以获取到。类加载器通过这种父亲-后代的方式组织在一起,形成树状层次结构。代理模式则指的是一个类加载器既可以自己完成Java类的定义工作,也可以代理给其它的类加载器来完成。由于代理模式的存在,启动一个类的加载过程的类加载器和最终定义这个类的类加载器可能并不是一个。前者称为初始类加载器,  而后者称为定义类加载器。

两者的关联在于:一个Java类的定义类加载器是该类所导入的其它Java类的初始类加载器。比如类A通过import导入了类  B,那么由类A的定义类加载器负责启动类B的加载过程。一般的类加载器在尝试自己去加载某个Java类之前,会首先代理给其父类加载器。当父类加载器找不到的时候,才会尝试自己加载。这个逻辑是封装在java.lang.ClassLoader类的  loadClass()方法中的。一般来说,父类优先的策略就足够好了。在某些情况下,可能需要采取相反的策略,即先尝试自己加载,找不到的时候再代理给父类加载器。这种做法在Java的WEB容器中比较常见,也是  Servlet规范推荐的做法。比如,Apache Tomcat为每个Web应用都提供一个独立的类加载器,使用的就是自己优先加载的策略。IBM WebSphere  Application Server则允许Web应用选择。

类加载器使用的策略

类加载器的一个重要用途是在JVM中为相同名称的Java类创建隔离空间。在JVM中,判断两个类是否相同,不仅是根据该类的二进制名称  ,还需要根据两个类的定义类加载器。只有两者完全一样,才认为两个类是相同的。因此,即便是同样的Java字节代码,被两个不同的类加载器定义之后,所得到的Java类也是不同的。如果试图在两个类的对象之间进行赋值操作,会抛出  java.lang.ClassCastException。这个特性为同样名称的Java类在JVM中共存创造了条件。在实际的应用中,可能会要求同一名称的Java类的不同版本在JVM中可以同时存在。通过类加载器就可以满足这种需求。这种技术在  OSGi中得到了广泛的应用

Java 类的链接

Java类的链接指的是将Java类的二进制代码合并到JVM的运行状态之中的过程。在链接之前,这个类必须被成功加载。类的链接包括验证、准备和解析等几个步骤。验证是用来确保Java类的二进制表示在结构上是完全正确的。如果验证过程出现错误的话,会抛出  java.lang.VerifyError错误。

准备过程则是创建Java类中的静态域,并将这些域的值设为默认值。准备过程并不会执行代码。在一个Java类中会包含对其它类或接口的形式引用,包括它的父类、所实现的接口、方法的形式参数和返回值的Java类等。解析的过程就是确保这些被引用的类能被正确的找到。解析的过程可能会导致其它的  Java类被加载。不同的 JVM 实现可能选择不同的解析策略。

一种做法是在链接的时候,就递归的把所有依赖的形式引用都进行解析。而另外的做法则可能是只在一个形式引用真正需要的时候才进行解析。也就是说如果一个 Java  类只是被引用了,但是并没有被真正用到,那么这个类有可能就不会被解析。考虑下面的代码:

public class LinkTest {  public static void main(String[] args) {   ToBeLinked toBeLinked = null;   System.out.println("Test link.");  } }

类LinkTest 引用了类 ToBeLinked,但是并没有真正使用它,只是声明了一个变量,并没有创建该类的实例或是访问其中的静态域。

oraclejdk 6 中,如果把编译好的 ToBeLinked 的 Java 字节代码删除之后,再运行  LinkTest,程序不会抛出错误。这是因为 ToBeLinked 类没有被真正用到,而 Oracle 的 JDK 6 所采用的链接策略使得ToBeLinked  类不会被加载,因此也不会发现 ToBeLinked 的 Java 字节代码实际上是不存在的。如果把代码改成 ToBeLinked toBeLinked =  new ToBeLinked();之后,再按照相同的方法运行,就会抛出异常了。因为这个时候 ToBeLinked  这个类被真正使用到了,会需要加载这个类。

Java 类的初始化

当一个 Java 类第一次被真正使用到的时候,JVM  会进行该类的初始化操作。初始化过程的主要操作是执行静态代码块和初始化静态域。在一个类被初始化之前,它的直接父类也需要被初始化。但是,一个接口的初始化,不会引起其父接口的初始化。在初始化的时候,会按照源代码中从上到下的顺序依次执行静态代码块和初始化静态域。考虑下面的代码:

public class StaticTest {  public static int X = 10;  public static void main(String[] args) {   System.out.println(Y); //输出60  }  static {   X = 30;  }  public static int Y = X * 2; }

在上面的代码中,在初始化的时候,静态域的初始化和静态代码块的执行会从上到下依次执行。因此变量 X 的值首先初始化成 10,后来又被赋值成 30;而变量 Y  的值则被初始化成 60。

Java类和接口的初始化时机

Java 类和接口的初始化只有在特定的时机才会发生,这些时机包括:

创建一个 Java 类的实例。如

MyClass obj = new MyClass()

调用一个 Java 类中的静态方法。如

MyClass.sayHello()

给 Java 类或接口中声明的静态域赋值。如

MyClass.value = 10

访问 Java 类或接口中声明的静态域,并且该域不是常值变量。如

int value = MyClass.value

在顶层 Java 类中执行 assert 语句。

assert true;

通过 Java 反射 api 也可能造成类和接口的初始化。需要注意的是,当访问一个  Java类或接口中的静态域的时候,只有真正声明这个域的类或接口才会被初始化。如下面的代码所示。

package io.mykit.binghe.test;   class B {  static int value = 100;  static {   System.out.println("Class B is initialized."); // 输出  } }   class A extends B {  static {   System.out.println("Class A is initialized."); // 不会输出  } }   public class InitTest {  public static void main(String[] args) {   System.out.println(A.value); // 输出100  } }

在上述代码中,类 InitTest 通过 A.value 引用了类 B 中声明的静态域 value。由于 value是在类 B 中声明的,只有类 B  会被初始化,而类 A 则不会被初始化。

创建自己的类加载器

在 Java 应用开发过程中,可能会需要创建应用自己的类加载器。典型的场景包括实现特定的 Java 字节代码查找方式、对字节代码进行加密/解密以及实现同名  Java 类的隔离等 。创建 自己的 类加载 器并不 是 一件复杂 的事情 ,只需要继承自java.lang.ClassLoader  类并覆写对应的方法即可。java.lang.ClassLoader 中提供的方法有不少,下面介绍几个创建类加载器时需要考虑的:

  • defineClass():这个方法用来完成从Java字节代码的字节数组到java.lang.Class的转换。这个方法是不能被覆写的,一般是用原生代码来实现的。

  • findLoadedClass():这个方法用来根据名称查找已经加载过的Java类。一个类加载器不会重复加载同一名称的类。

  • findClass():这个方法用来根据名称查找并加载Java类。

  • loadClass():这个方法用来根据名称加载Java类。

  • resolveClass():这个方法用来链接一个Java类。

这里比较 容易混淆的是 findClass()方法和 loadClass()方法的作用。前面提到过,在Java 类的链接过程中,会需要对 Java  类进行解析,而解析可能会导致当前 Java 类所引用的其它 Java 类被加载。在这个时候,JVM 就是通过调用当前类的定义类加载器的  loadClass()方法来加载其它类的。findClass()方法则是应用创建的类加载器的扩展点。应用自己的类加载器应该覆写  findClass()方法来添加自定义的类加载逻辑。loadClass()方法的默认实现会负责调用  findClass()方法。前面提到,类加载器的代理模式默认使用的是父类优先的策略。这个策略的实现是封装在  loadClass()方法中的。如果希望修改此策略,就需要覆写 loadClass()方法。

下面的代码给出了自定义的类加载的常见实现模式

public class MyClassLoader extends ClassLoader {  protected Class<?> findClass(String name) throws ClassNotFoundException {   byte[] b = null; //查找或生成Java类的字节代码   return defineClass(name, b, 0, b.length);  } }

“类的加载、链接和初始化是什么”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注编程网网站,小编将为大家输出更多高质量的实用文章!

--结束END--

本文标题: 类的加载、链接和初始化是什么

本文链接: https://www.lsjlt.com/news/281998.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • 类的加载、链接和初始化是什么
    本篇内容介绍了“类的加载、链接和初始化是什么”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!Java 类的加载Java类的加载是由类加载器来完...
    99+
    2023-06-16
  • 浅谈JVM之类的加载链接和初始化
    目录加载运行时常量池类加载器链接验证准备解析初始化总结加载 JVM可以分为三大部分,五大空间和三大引擎,要讲起来也不是特别复杂,先看下面的总体的JVM架构图。 从上面的图中,我们可...
    99+
    2024-04-02
  • 浅谈Java类的加载,链接及初始化
    一 类生命周期 Loading Linking(Verification、Preparation、Resolution) Initializing 二 类加载器...
    99+
    2024-04-02
  • JVM中加载、链接、初始化的示例分析
    这篇文章主要为大家展示了“JVM中加载、链接、初始化的示例分析”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“JVM中加载、链接、初始化的示例分析”这篇文章吧。基本概念:类加载的过程大致分为三个阶...
    99+
    2023-05-31
    jvm
  • spring加载过程和初始化方法是什么
    Spring加载过程分为以下几个阶段: 资源定位:Spring框架会根据配置文件或注解扫描的方式,定位到配置文件或类文件的位置。 ...
    99+
    2023-10-26
    spring
  • 详解Java中类的加载与其初始化
    目录java内存分析类加载的过程类的初始化java内存分析 类加载的过程 类的加载与ClassLoader的理解 类的初始化 package Collections; publ...
    99+
    2022-12-15
    Java 类加载 初始化 Java 类加载 Java类 初始化
  • Java类的初始化顺序是什么
    这篇文章主要讲解了“Java类的初始化顺序是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Java类的初始化顺序是什么”吧!Java类的初始化顺序 多...
    99+
    2024-04-02
  • Java类的初始化过程是什么
    Java类的初始化过程包括以下几个步骤: 加载类:当程序中使用到某个类时,Java虚拟机会先通过类加载器将该类的字节码文件加载到...
    99+
    2023-10-26
    java
  • c#静态类初始化的方法是什么
    在C#中,静态类的初始化方法是使用静态构造函数。静态构造函数在类被加载时自动调用,无需手动调用。静态构造函数一般用于初始化静态变量和...
    99+
    2024-03-02
    c#
  • hive连接mysql初始化的方法是什么
    在Hive中连接MySQL需要进行以下初始化步骤: 1、首先,需要在Hive的配置文件hive-site.xml中配置MySQL的连...
    99+
    2024-04-09
    hive mysql
  • hashmap初始化直接赋值的方法是什么
    在Java中,可以使用如下方法直接初始化一个HashMap并赋值: Map<String, Integer> map =...
    99+
    2024-03-11
    hashmap
  • JDK15类的后半生:准备、解析、初始化、卸载过程是什么
    这篇文章主要介绍“JDK15类的后半生:准备、解析、初始化、卸载过程是什么”,在日常操作中,相信很多人在JDK15类的后半生:准备、解析、初始化、卸载过程是什么问题上存在疑惑,小编查阅了各式资料,整理出简单...
    99+
    2024-04-02
  • linux初始化的方法是什么
    Linux的初始化方法可以通过执行以下步骤来完成:1. 启动计算机并进入BIOS设置,在启动选项中选择从可引导介质(如硬盘或USB驱...
    99+
    2023-08-30
    linux
  • 初始化css的原因是什么
    今天小编给大家分享一下初始化css的原因是什么的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧...
    99+
    2024-04-02
  • pycharm初始化的方法是什么
    PyCharm的初始化方法是通过安装并打开PyCharm,在首次打开时,会出现一个“Welcome to PyCharm”界面,用户...
    99+
    2023-09-13
    pycharm
  • 中项目启动时实现初始化方法的加载参数是什么
    中项目启动时实现初始化方法的加载参数是什么,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。springboot项目启动,初始化方法加载参数今天我看到项目中用到了 ...
    99+
    2023-06-22
  • css初始化是什么意思
    这篇文章给大家分享的是有关css初始化是什么意思的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。CSS初始化是指重设浏览器的样式。不同的浏览器默认的样式可能不尽相同,所以开发时的第一件事可能就是如何把它们统一。如果...
    99+
    2023-06-14
  • SpringMVC初始化流程是什么
    本篇内容主要讲解“SpringMVC初始化流程是什么”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“SpringMVC初始化流程是什么”吧!框架源码是我们 Cod...
    99+
    2024-04-02
  • Git初始化命令是什么
    这篇文章给大家分享的是有关Git初始化命令是什么的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。 初始化命令命令作用git init初始化 git,创建 .git 文件感...
    99+
    2024-04-02
  • Vue初始化是什么意思
    Vue 是一款非常流行的 JavaScript 框架,广泛用于构建现代化的 Web 应用程序。在开始学习 Vue 之前,你需要先了解 Vue 的初始化过程,以便正确地使用 Vue 并创建可重复的代码。初始化 Vue 是指在页面中创建一个 V...
    99+
    2023-05-14
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作