java类加载机制的过程

2019-03-27 20:00|来源: 网络

jvm在初期是将.java文件,编译成.class文件,当程序运行的时候,Java 虚拟机就将编译生成的 . class 文件按照需求和一定的规则加载进内存,组织成为一个完整的 Java 应用程序,jvm会把每个单独的类和接口编译成一个单独的.class文件,这些文件对于 Java 运行环境来说就是一个个可以动态加载的单元。我们可以在不重新编译其它代码的情况下,只编译需要修改的单元,并把修改文件编译后的 . class 文件放到 Java 的路径当中, 等到下次该 Java 虚拟机器重新激活时,这个逻辑上的 Java 应用程序就会因为加载了新修改的 .class 文件,自己的功能也做了更新,这就是 Java 的动态性。
1. 预先加载与依需求加载
Java 运行所需要的基本类采用预先加载,的方法全部加载要内存当中,因为这些单元在 Java 程序运行的过程当中经常要使用的,主要包括 JRE 的 rt.jar 文件里面所有的 .class 文件。
我们在程序中需要使用自己定义的类的时候就要使用依需求加载方法。

2. 隐式加载和显示加载
程序中用 new 关键字来定义一个实例变量, JRE 在执行到 new 关键字的时候就会把对应的实例类加载进入内存,用的也很多, JRE 系统在后台自动的帮助用户加载,减少了用户的工作量,也增加了系统的安全性和程序的可读性。
程序员自己写程序把需要的类加载到内存当中(显示加载)
Class c = Class.forName("TestClass");
 TestClass object = (TestClass)c.newInstance

我们通过 Class 类的 forName (String s) 方法把自定义类 TestClass 加载进来,并通过 newInstance ()方法把实例初始化
Test test = new Test();//Test 类为自定义的一个测试类;

ClassLoader cl = test. getClass().getClassLoader();

 // 获取 test 的类装载器;

Class c = Class.forName("TestClass", true, cl);

   因为一个类要加载就必需要有加载器,这里我们是通过获取加载 Test 类的加载器 cl 当作加载 TestClass 的类加载器来实现加载的。



  3. 自定义类加载机制
URL url = new URL("file:/d:/test/lib/");

 URLClassLoader urlCL = new URLClassLoader(new URL[]{url});

 Class c = urlCL.loadClass("TestClassA");

 TestClassA object = (TestClassA)c.newInstance();

 object.method();



首先定义 URL 指定类加载器从何处加载类, URL 可以指向网际网络上的任何位置,也可以指向我们计算机里的文件系统 ( 包含 JAR 文件 ) .上述范例当中我们从 file:/d:/test/lib/ 处寻找类;然后定义 URLClassLoader 来加载所需的类,最后即可使用该实例了。
 4. 类加载器的阶层体系
当执行hllo.class时候,java.exe会自动找到很显眼的jre位置,接着会在其中找到jvm.dll,(在jdk和jre中都有jvm)有了.dll文件之后激活jvm加载动态库,jvm活后,先做一些初始化的动作,比如说读取系统参数等。
  然后,一旦初始化动作完成之后,就会产生第一个类加载器―― Bootstrap Loader (靴带机制,就是系上鞋带就要走路了), Bootstrap Loader 是由 C++ 所撰写而成,这个 Bootstrap Loader 所做的初始工作中,除了一些基本的初始化动作之外,最重要的就是加载 Launcher.java 之中的 ExtClassLoader ,并设定其 Parent 为 null ,代表其父加载器为 BootstrapLoader .然后 Bootstrap Loader 再要求加载 Launcher.java 之中的 AppClassLoader ,并设定其 Parent 为之前产生的 ExtClassLoader 实体。这两个加载器都是以静态类的形式存在的。这里要请大家注意的是, Launcher$ExtClassLoader.class 与 Launcher$AppClassLoader.class 都是由 Bootstrap Loader 所加载,所以 Parent 和由哪个类加载器加载没有关系。

这三个加载器就构成我们的 Java 类加载体系。他们分别从以下的路径寻找程序所需要的类:

BootstrapLoader : sun.boot.class.path

ExtClassLoader: java.ext.dirs

AppClassLoader: java.class.path

这三个系统参量可以通过 System.getProperty() 函数得到具体对应的路径。大家可以自己编程实现查看具体的路径。


本文链接: java类加载机制的过程 来源:http://liuqimeng1.iteye.com/blog/679078

相关问答

更多
  • 得到三类信息.1.构造函数2.属性3.方法
  • 增加程序的灵活性。 如struts中。请求的派发控制。 当请求来到时。struts通过查询配置文件。找到该请求对应的action。已经方法。 然后通过反射实例化action。并调用响应method。 如果不适用反射,那么你就只能写死到代码里了。 所以说,一个灵活,一个不灵活。 很少情况下是非用反射不可的。大多数情况下反射是为了提高程序的灵活性。 因此一般框架中使用较多。因为框架要适用更多的情况。对灵活性要求较高。
  • JAVA 缓存机制[2022-02-12]

    你这个分数太少了吧,程序到是有,不过给你有点可惜 CacheMgr.java import java.util.*; import cn.javass.framework.cache.vo.CacheConfModel; public class CacheMgr { private static Map cacheMap = new HashMap(); private static Map cacheConfMap = new HashMap(); private CacheMgr(){ } priva ...
  • MessageFormat提供了手段,生产语言无关的方式连接在一起的消息。使用此构造为最终用户显示的消息。 SimpleDateFormat的是用于格式化和解析语言环境敏感的方式日期的具体类。它允许进行格式化(日期 - >“文本),分析(文本 - >”日期),并归 Calendar类是一个抽象类,它提供了在一个特定的时间和瞬间,如年的日历字段集转换方法,月,DAY_OF_MONTH,小时和等,用于操作日历领域,如获取的日期,在未来一周
  • 建议去看看《java反射机制与动态代理模式》系列视频,讲得很好
  • 先说第一个,类你可以把它看成一个工厂,比如这个类它就是一生产手机的流水线,现在你想要个手机,你就直接告诉它new,它这个流水线就开始工作了,最后出来一个手机,这就是实例,而类可以制造出实例,第二个是继承,等你学了就明白了,A是B的爹,比如A是笔,B是铅笔
  • B.getA()这方法怎么实现的?A是接口,所以直接newInstance是不行的。 你总得有个具体的实现A接口的类吧
  • 添加线 package java.lang 在您的代码之上,然后再次检查。 你会发现你现在得到了预期的结果。 原因是,类名始终仅用作完全限定名,包括包名和类名。 因此,在您的情况下, String是一个与java.lang.String不同的类,因此不会在rt.jar找到 add the line package java.lang on top of your code, and check again. You will notice that you get your expected result ...
  • 这两个可以帮助你: 从onjava.com加载类 从ibm.com/developerworks加载类 these 2 can help u: classloading from onjava.com classloading from ibm.com/developerworks
  • 我将从最简单的(这里我假设类定义在类路径中可用,JVM可以加载它): 在代码中引用类名称。 当JVM找到该引用时,该类将被最新加载。 SomeClass someInstance = null; Class.forName(String) ,用于加载和初始化类。它使用当前类的类加载器。 Class.forName("XYZ"); ClassLoader#loadClass(String) ,用于加载类,但不初始化。您可以获取ClassLoader的实例并在该实例上调用loadClass() ,该实例可 ...