`

JAVA类的加载

    博客分类:
  • JVM
 
阅读更多

Java类的装载、链接和初始化

加载(Loading)

按如下三步执行

  • 1.通过类的全名产生对应类的二进制数据流。(注意,如果没找到对应类文件,只有在类实际使用时才抛出错误。)
  • 2.分析并将这些二进制数据流转换为方法区(JVM 的架构:方法区、堆,栈,本地方法栈,pc 寄存器)特定的数据结构(这些数据结构是实现有关的,不同 JVM 有不同实现)。这里处理了部分检验,比如类文件的魔数的验证,检查文件是否过长或者过短,确定是否有父类(除了 Obecjt 类)。
  • 3.创建对应类的 java.lang.Class 实例(注意,有了对应的 Class 实例,并不意味着这个类已经完成了加载链链接!)。

链接(Linking)

链接的过程比加载过成复杂不少,这是实现 Java 的动态性的重要一步。分为三部分:验证,准备和解析。

  • 1.验证(verification)

    链接的第三部解析会把类中成员方法、成员变量、类和接口的符号引用替换为直接引用,而在这之前,需要检测被引用的类型正确性和接入属性是否正确(就是 public ,private 的的问题),诸如检查 final class 又没有被继承,检查静态变量的正确性等等。(注意到实际上有一部分验证过程已经在加载的过程中执行了。)

  • 2.准备(preparation)

    对类的成员变量分配空间。虽然有初始值,但这个时候不会对他们进行初始化(因为这里不会执行任何 Java 代码)。具体如下:

    所有原始类型的值都为 0。如 float: 0f, int: 0, boolean: 0(注意 boolean 底层实现大多使用 int),引用类型则为 null。值得注意的是,JVM 可能会在这个时期给一些有助于程序运行效率提高的数据结构分配空间。比如方发表(类似与 C++中的虚函数表,参见另一篇博文《Java:方法的虚分派和方法表》)。

  • 3.解析(Resolution)

    为类、接口、方法、成员变量的符号引用定位直接引用(如果符号引用先到常量池中寻找符号,再找先应的类型,无疑会耗费更多时间),完成内存结构的布局。

    这一步是可选的。可以在符号引用第一次被使用时完成,即所谓的延迟解析(late resolution)。但对用户而言,这一步永远是延迟解析的,即使运行时会执行 early resolution,但程序不会显示的在第一次判断出错误时抛出错误,而会在对应的类第一次主动使用的时候抛出错误!

    另外,这一步与之后的类初始化是不冲突的,并非一定要所有的解析结束以后才执行类的初始化。不同的 JVM 实现不同。详情见另一篇博文《Java 类加载的延迟初始化》

初始化类(Initialization)

开发 Java 时,接触最多的是对象的初始化。实际上类也是有初始化的。相比对象初始化(参见博文 Java 类的实例化),类的初始化机制要简单不少。

类的初始化也是延迟的,直到类第一次被主动使用(active use),JVM 才会初始化类。(参见博文《Java 类加载的延迟初始化》

类的初始化分两步:

  • 1.如果基类没有被初始化,初始化基类。
  • 2.有类构造函数,则执行类构造函数。

    类构造函数是由 Java 编译器完成的。它把类成员变量的初始化和 static 区间的代码提取出,放到一个的方法中。这个方法不能被一般的方法访问(注意,static final 成员变量不会在此执行初始化,它一般被编译器生成 constant 值)。同时,中是不会显示的调用基类的的,因为 1 中已经执行了基类的初始化。类的初始化还必须注意线程安全的问题。

PS:

为什么接口不能定义成员变量,而只能定义 final static 变量。

  • 1.接口是不可实例化,它的所有元素都不必是实例(对象)层面的。static 满足了这一点。
  • 2.如果接口的变量能被修改,那么一旦一个子类实现了这个接口,并修改了接口中的非 final 变量,而该子类的子类再次修改这个非 final 的变量后,造成的结果就是虽然实现了相同的接口,但接口中的变量值是不一样的。

综上述,static final 更适合于接口。

参考:《通过类字面常量解释接口常量为什么只能定义为 static final,类加载过程—Thinking in java》

分享到:
评论

相关推荐

    java类加载器学习三、类加载器的委托模式

    java类加载器学习三、类加载器的委托模式

    java类加载器

    ClassLoader 三种类加载方式 Boostrap Extenxsion 以及Application ClassLoad分别适用的场景

    深入研究Java类加载机制 深入研究Java类加载机制

    深入研究Java类加载机制 深入研究Java类加载机制 深入研究Java类加载机制 深入研究Java类加载机制

    java 类加载器 加密

    java 类加密 使用类加载器解密加载类 反射执行main

    java类加载机制.xmind

    该文件是JVM中关于类加载机制的知识整理的思维导图,包括类加载机制概述、类加载的生命周期、加载时机、加载过程、类加载、类的初始化和实例化等几个大方面进行了讲解,其中类加载中还对JVM三种预定义类加载器进行了...

    Java类加载器.pdf

    Java类加载器.pdf

    Java类加载内幕详细讲解

     类加载是java语言提供的最强大的机制之一,但所有的编程人员都应该了解其工作机制,明白如何做才能让其满足我们的需要。这能有效节省我们的编码时间,从不断调试ClassNotFoundException的工作中解脱出来。

    自定义Java类加载器

    看完一个Java加载原理教程后,写了这个自己的类加载器,作个笔记,以便以且使用

    java类加载器实例

    类加载器是 Java 语言的一个创新,也是 Java 语言流行的重要原因之一。它使得 Java 类可以被动态加载到 Java 虚拟机中并执行。类加载器从 JDK 1.0 就出现了,最初是为了满足 Java Applet 的需要而开发出来的。Java ...

    JAVA类加载机制与动态代理

    类加载机制与动态代理吗,讲得很好对得资源分。

    java类加载原理分析

    java类加载原理分析,引导类加载器,扩展类加载器,系统类加载器(也叫应用类加载器)

    Java类加载机制与反射-PPT

    Java的类加载机制:加载,连接,初始化。JAVA类加载器: Bootstrap ClassLoader : 根类加载器, Extension ClassLoader: 扩展类加载器, System ClassLoader : 系统类加载器, Java反射

    自定义Java类加载器demo

    自定义Java类加载器demo,自定义了一个classLoader,重写了loadClass 和findClass,注意 loadClass打破了双亲委派机制,所有的类都要在自定义的class文件中找到,而findClass遵循了双亲委派机制

    使用Java类加载和类路径实现一个简单的在线购物网站.txt

    这段代码实现了一个简单的购物车类ShoppingCart,其中使用了Java的类加载和类路径机制。在类的构造方法中,首先通过类加载器将购物车类加载到JVM中,然后创建了一个Map对象来存储购物车中的商品及其数量。接着实现了...

    java 类加载器 class loader

    java 类加载器 class loaderjava 类加载器 class loaderjava 类加载器 class loaderjava 类加载器 class loaderjava 类加载器 class loaderjava 类加载器 class loaderjava 类加载器 class loader

    深入探讨 Java 类加载器.wps

    深入探讨 Java 类加载器.wps深入探讨 Java 类加载器.wps深入探讨 Java 类加载器.wps

    java类加载机制

    java 类加载机制,课程笔记。

    Java类加载原理解析

    Java类加载原理解析,深度解剖了java中的类的执行内部机制!

    深入探讨 Java 类加载器

    类加载器(class ...本文首先详细介绍了 Java 类加载器的基本概念,包括代理模式、加载类的具体过程和线程上下文类加载器等,接着介绍如何开发自己的类加载器,最后介绍了类加载器在 Web 容器和 OSGi™ 中的应用。

Global site tag (gtag.js) - Google Analytics