Java类加载机制

合集下载

类加载机制及SPI

类加载机制及SPI

类加载机制及SPI最近重温Java类加载及双亲委派机制,并写了⼀个SPI的例⼦从⽹上找了⼀张图⽚,对着图⽚及课堂笔记来梳理下。

⾸先java⾃带的类加载器分为BootStrapClassLoader(引导\启动类加载器),ExtClassLoader(扩展类加载器),AppClassLoader(应⽤程序类加载器)三种,此外还⽀持⽤户⾃⼰定义的⾃定义类加载器,加载的是⽤户⾃⼰指定的⽬录。

BootStrapClassLoader:jvm中,c++处理类加载的这套逻辑,被称为启动类加载器,是由c++编写的,在java中为null,加载的路径是Jre/lib/rt.jar, 在这个过程中会通过启动类加载器,来加载uncherHelper,并执⾏checkAndLoadMain,以及加载main函数所在的类,并启动扩展类加载器、应⽤类加载器ExtClassLoader: 扩展类加载器,加载的是Jre/lib/ext/*.jar,查看⽅式:public static void main(String[] args) {ClassLoader classLoader = ClassLoader.getSystemClassLoader().getParent();URLClassLoader urlClassLoader = (URLClassLoader) classLoader;URL[] urls = urlClassLoader.getURLs();for (URL url : urls) {System.out.println(url);}}AppClassLoader: 应⽤类加载器,加载⽤户程序的类加载器,加载的是CLASS_PATH中指定的所有jarpublic static void main(String[] args) {String[] urls = System.getProperty("java.class.path").split(":");for (String url : urls) {System.out.println(url);}System.out.println("---------------------------------------------------------");URLClassLoader classLoader = (URLClassLoader) ClassLoader.getSystemClassLoader();URL[] urls1 = classLoader.getURLs();for (URL url : urls1) {System.out.println(url);}}双亲委派机制:类加载时,AppClassLoader 会先查看⾃⾝是否已经加载过当前class⽂件,如果加载过则直接返回,如果没有加载过,则委托他的⽗类(ExtClassLoader)尝试进⾏加载,ExtClassLoader也会先查看⾃⼰是否加载过,加载过则直接返回,没有加载过,则继续委派给BootStrapClassLoader,如果直⾄BootStrapClassLoader都没有加载过,则会AppClassLoader会尝试进⾏加载。

Java高级程序设计认证试卷

Java高级程序设计认证试卷

Java高级程序设计认证试卷(答案见尾页)一、选择题1. Java语言的特性包括哪些?A. 封装B. 多态C. 抽象D. 动态代理2. 在Java中,以下哪个关键字用于定义常量?A. finalB. staticC. constD. var3. Java中的集合框架包含以下哪些接口?A. CollectionB. ListC. SetD. Map4. Java的异常处理机制包括以下哪些关键字?A. tryB. catchC. finallyD. throw5. 以下哪个是Java反射机制中用于获取类信息的方法?A. getDeclaredMethods()B. getGenericSuperclass()C. getAnnotations()D. getComponentType()6. Java的泛型支持以下哪种类型转换?A. 自动装箱/拆箱B. 自动类型转换C. 强制类型转换D. 隐式类型转换7. Java的注解处理器用于执行哪些任务?A. 代码重构B. 类文件生成C. 性能优化D. 错误检查8. 在Java中,以下哪个关键字用于实现接口?A. implementsB. extendsC. implementsD. extends9. Java的序列化机制用于以下哪个目的?A. 恢复内存中的对象状态B. 实现跨平台的数据交换C. 提高数据安全性D. 降低数据存储效率10. Java的线程同步机制使用的关键字是?A. synchronizedB. volatileC. lockD. await11. Java语言有哪些基本数据类型?A. byteB. shortC. intD. long12. 在Java中,以下哪个关键字用于定义方法?A. privateB. staticC. finalD. abstract13. Java中的集合框架包括哪些接口和实现类?A. ListB. SetC. QueueD. Map14. Java中,哪个关键字用于实现继承?A. extendsB. implementsC. interfaceD. override15. 在Java中,什么是垃圾回收机制(Garbage Collection)?A. 一种自动内存管理技术B. 一种手动内存管理技术C. 一种动态数组技术D. 一种静态数组技术16. Java中,哪个关键字用于导入其他包或类库?A. importB. includeC. requireD. uses17. 在Java中,什么是异常处理机制?请简述。

dcevm原理 -回复

dcevm原理 -回复

dcevm原理-回复【dcevm原理】一种支持在运行时替换Java类定义的虚拟机1. 引言dcevm(Dynamic Code Evolution VM)是一种特殊的Java虚拟机,它支持在运行时替换已加载的Java类定义。

传统的Java虚拟机在运行过程中无法修改已加载的类,这使得开发人员在改变类定义时,需要重启应用程序。

然而,dcevm的出现解决了这个问题,使得开发人员可以通过替换类定义而无需重启应用程序,提高了开发效率。

本文将深入探讨dcevm 的原理与实现。

2. Java类加载过程回顾在深入理解dcevm原理之前,我们需要先回顾一下Java类加载的过程。

当Java程序执行时,虚拟机会按照特定的顺序进行类加载,主要包括加载、链接和初始化三个阶段。

在加载阶段,虚拟机会从磁盘读取类的字节码,并生成对应的Class对象;在链接阶段,虚拟机会对类进行验证、准备和解析的操作;最后,在初始化阶段,虚拟机会执行类的静态初始化代码。

3. dcevm的设计理念dcevm的设计目标是支持在运行时替换Java类定义,避免应用程序重启。

为了实现这一目标,dcevm引入了一些新的概念和机制。

其中最重要的是HotSwap机制,即在运行时替换已加载的Java类定义。

通过HotSwap,开发人员可以在调试和测试阶段,及时修复或更新代码,快速迭代应用程序。

4. HotSwap机制的实现流程HotSwap机制的实现主要涉及以下几个步骤:- 备份原始类定义:在替换类定义之前,dcevm会在内部保存原始的类定义,以便需要时恢复。

- 加载新的类定义:开发人员通过一些手段(如IDE等工具)生成新的类定义,并将其加载到虚拟机中。

- 类验证:虚拟机会对新加载的类进行验证,以确保其与原始类定义兼容。

- 类替换:当新的类定义通过验证后,dcevm将会替换原始的类定义,并且在替换完成后,重新初始化该类的实例。

5. 实时调试和代码热部署dcevm的HotSwap机制不仅仅支持简单的类替换,还可以辅助实时调试和代码热部署。

类加载的三种方式

类加载的三种方式

类加载的三种⽅式类加载分为动态加载和静态加载。

动态加载是从外存储器中加载类,⼀般类加载机制分析的也是动态加载。

⽽静态加载本质上是从内存中创建类的实例对象,此时类已经被加载到内存中。

⼀.静态加载通过new关键字来创建Test的实例对象。

⼆.动态加载1.通过Class.forName()来加载类,然后调⽤类的newInstance()⽅法实例化对象。

2.通过类加载器的loadClass()⽅法来加载类,然后调⽤类的newInstance()⽅法实例化对象。

这⾥有⼏个需要⽐较的地⽅:1.通过new关键字实例化类的对象和通过Class.forName()加载类是当前类加载器,即this.getClass.getClassLoader,只能在当前类路径或者导⼊的类路径下寻找类。

⽽⽤指定的classLoader来加载类可以从当前路径外寻找类,这⾥的classLoader甚⾄可以⽤户⾃定义。

2.我们知道类加载机制的三个过程主要是加载-->连接-->初始化。

Class.forName()实际调⽤的是Class.forName(className,true,this.getClass.getClassLoader),第⼆个参数表⽰加载完后是否⽴即初始化,第三个参数即前⽂提到的表⽰是当前类加载器。

classLoader.loadClass()实际调⽤的是classLoader.loadClass(className,false),第⼆个参数表⽰加载完成后是否连接,即⽤此⽅法加载类,加载完成后不会去初始化,⽽⽤Class.forName()加载类加载完成后可以被初始化。

所以有些类如果加载完成后需要⽴即被初始化则必须使⽤Class.forName()。

例如在加载数据库驱动时,⼀般⽤Class.forName("com.mysql.jdbc.Driver")。

这是因为该驱动有⼀个在静态代码块中注册驱动的过程,所以需要被初始化。

java 类里的loadclass用法

java 类里的loadclass用法

java 类里的loadclass用法Java中的loadClass()方法是在Class类中定义的一个方法,用于动态加载类。

在程序运行时可以根据类的全限定名来加载指定的类文件,并返回对应的Class对象。

loadClass()方法的语法如下:`public Class<?> loadClass(String name) throws ClassNotFoundException`这个方法可以在当前的ClassLoader中通过类的全限定名来加载指定的类文件。

如果找不到该类文件,则会抛出ClassNotFoundException异常。

下面将详细介绍loadClass()方法的使用以及相关概念和实例。

1. 理解Java类加载器在介绍loadClass()方法之前,先来了解一下Java类加载器。

类加载器是Java虚拟机(JVM)的一个组件,用于从文件系统、网络或其他来源加载Java类文件。

Java虚拟机通过类加载器来定位并加载类文件,将其转换为一个Class对象,并存放在方法区(即运行时数据区域之一)。

一个Java类加载器通常是由一个ClassLoader类的实例来表示的。

Java 提供了三种内置的ClassLoader:- Bootstrap ClassLoader:负责加载Java核心类库,是虚拟机的一部分,无法直接获取。

- Extension ClassLoader:负责加载Java扩展库,如javax包下的类。

- System ClassLoader:也称为Application ClassLoader,负责加载应用程序的类,可以通过ClassLoader.getSystemClassLoader()来获取。

2. 使用loadClass()方法动态加载类loadClass()方法是ClassLoader类的一个原生方法,可以通过子类来调用。

在调用loadClass()方法时,会按照ClassLoader的委派模型进行类的加载。

classloader加载原理

classloader加载原理

classloader加载原理classloader是java中一个比较重要的类加载器,每一个程序和类都会存在一个classloader,classloader有三种主要的工作:加载类的二进制字节流、连接、初始化。

一、Classloader加载机制1、首先classloader会按照特定的方式去搜索类文件,当它找到了相应的类文件之后,它会将这个类文件转换成为二进制字节流,这里涉及到编译程序,classloader会使用编译程序将源程序编译成可执行文件。

2、接下来classloader会将这些二进制字节流存储在内存中,然后classloader会连接这些字节流,这一步是它将这些字节流组装成一个完整的类文件,这里涉及到类的加载,这些加载的类可以被访问,但是它们的代码还未被执行。

3、最后classloader会初始化这些加载的类,这一步就是它将这些类的代码执行,这里classloader会执行所有类变量的初始化,同时也会执行所有静态代码块的内容,最后我们就可以得到一个完整的类文件。

二、Classloader的三种类型1、Bootstrap Classloader:它是用来加载JRE的核心类的,它的实现是C++语言,它的加载范围是从<JAVA_HOME>lib下面开始,这个类加载器不需要程序员编写任何外部类。

2、Extension Classloader:它是用来加载扩展类的,从<JAVA_HOME>libext开始加载,它继承自Bootstrap Classloader,这种类加载器也不需要程序员手动编写任何外部类。

3、Application Classloader:它是用来加载程序类的,它继承自Extension Classloader,它从ClassPath(来自系统变量或者命令行参数)所指定的路径中加载类,但是它不会加载扩展类。

三、Classloader安全机制1、安全性验证:Classloader在加载类的时候会先验证这个类文件,检查它是否符合class文件格式,其次classloader会过滤掉由它本身加载的不安全的类,这涉及到安全管理器的配置,例如:可以设置它只能加载特定的域名下的类文件。

javaagent加载机制分析

javaagent加载机制分析

javaagent加载机制分析在启动和运⾏期都可以加载agent代理,在启动的时候可通过-javaagent参数来执⾏agent代理,⽽在运⾏期就是通过attach这种机制动态load了。

如果在vm启动过程中加载agent,那么会在vm初始化过程中先执⾏libinstrument.dylib⾥InvocationAdapter.c的Agent_OnLoad⽅法,这⾥主要是实例化agent,解析agent的MF⽂件,将相关属性取出来,并注册jvmti的⼀些回调函数,在vm初始化完成之后,会通过回调函数去实例化Instrumentation实现对象,设置ClassFileLoadHook函数,并调⽤Pre-Main指定类的premain⽅法。

C代码1. JNIEXPORT jint JNICALL2. Agent_OnLoad(JavaVM *vm, char *tail, void * reserved) {3. JPLISInitializationError initerror = JPLIS_INIT_ERROR_NONE;4. jint result = JNI_OK;5. JPLISAgent * agent = NULL;6.7. initerror = createNewJPLISAgent(vm, &agent);8. if ( initerror == JPLIS_INIT_ERROR_NONE ) {9. int oldLen, newLen;10. char * jarfile;11. char * options;12. jarAttribute* attributes;13. char * premainClass;14. char * agentClass;15. char * bootClassPath;16.17. /*18. * Parse <jarfile>[=options] into jarfile and options19. */20. if (parseArgumentTail(tail, &jarfile, &options) != 0) {21. fprintf(stderr, "-javaagent: memory allocation failure.\n");22. return JNI_ERR;23. }24.25. /*26. * Agent_OnLoad is specified to provide the agent options27. * argument tail in modified UTF8. However for 1.5.0 this is28. * actually in the platform encoding - see 5049313.29. *30. * Open zip/jar file and parse archive. If can't be opened or31. * not a zip file return error. Also if Premain-Class attribute32. * isn't present we return an error.33. */34. attributes = readAttributes(jarfile);35. if (attributes == NULL) {36. fprintf(stderr, "Error opening zip file or JAR manifest missing : %s\n", jarfile);37. free(jarfile);38. if (options != NULL) free(options);39. return JNI_ERR;40. }41.42. premainClass = getAttribute(attributes, "Premain-Class");43. if (premainClass == NULL) {44. fprintf(stderr, "Failed to find Premain-Class manifest attribute in %s\n",45. jarfile);46. free(jarfile);47. if (options != NULL) free(options);48. freeAttributes(attributes);49. return JNI_ERR;50. }51.52. /*53. * Add to the jarfile54. */55. appendClassPath(agent, jarfile);56.57. /*58. * The value of the Premain-Class attribute becomes the agent59. * class name. The manifest is in UTF8 so need to convert to60. * modified UTF8 (see JNI spec).61. */62. oldLen = (int)strlen(premainClass);63. newLen = modifiedUtf8LengthOfUtf8(premainClass, oldLen);64. if (newLen == oldLen) {65. premainClass = strdup(premainClass);66. } else {67. char* str = (char*)malloc( newLen+1 );68. if (str != NULL) {69. convertUtf8ToModifiedUtf8(premainClass, oldLen, str, newLen);70. }71. premainClass = str;72. }73. if (premainClass == NULL) {74. fprintf(stderr, "-javaagent: memory allocation failed\n");75. free(jarfile);76. if (options != NULL) free(options);77. freeAttributes(attributes);78. return JNI_ERR;79. }80.81. /*82. * If the Boot-Class-Path attribute is specified then we process83. * each relative URL and add it to the bootclasspath.84. */85. bootClassPath = getAttribute(attributes, "Boot-Class-Path");86. if (bootClassPath != NULL) {87. appendBootClassPath(agent, jarfile, bootClassPath);88. }89.90. /*91. * Convert JAR attributes into agent capabilities92. */93. convertCapabilityAtrributes(attributes, agent);94.95. /*96. * Track (record) the agent class name and options data97. */98. initerror = recordCommandLineData(agent, premainClass, options);99.100. /*101. * Clean-up102. */103. free(jarfile);104. if (options != NULL) free(options);105. freeAttributes(attributes);106. free(premainClass);107. }108.109. switch (initerror) {110. case JPLIS_INIT_ERROR_NONE:111. result = JNI_OK;112. break;113. case JPLIS_INIT_ERROR_CANNOT_CREATE_NATIVE_AGENT:114. result = JNI_ERR;115. fprintf(stderr, "ng.instrument/-javaagent: cannot create native agent.\n"); 116. break;117. case JPLIS_INIT_ERROR_FAILURE:118. result = JNI_ERR;119. fprintf(stderr, "ng.instrument/-javaagent: initialization of native agent failed.\n"); 120. break;121. case JPLIS_INIT_ERROR_ALLOCATION_FAILURE:122. result = JNI_ERR;123. fprintf(stderr, "ng.instrument/-javaagent: allocation failure.\n");124. break;125. case JPLIS_INIT_ERROR_AGENT_CLASS_NOT_SPECIFIED:126. result = JNI_ERR;127. fprintf(stderr, "-javaagent: agent class not specified.\n");128. break;129. default:130. result = JNI_ERR;131. fprintf(stderr, "ng.instrument/-javaagent: unknown error\n");132. break;133. }134. return result;135. }如果在运⾏期通过attach api来load agent,那么会在收到load指令之后,会调⽤InvocationAdapter.c的Agent_OnAttach⽅法,其实现基本和Agent_OnLoad⼀致,只是还会调⽤Agent-Class的agentmain⽅法,还有点不同就是对vmint事件没有再关注(都运⾏期了,关注也没⽤),⽽是直接对ClassFileLoad关注,也不会再调⽤Pre-Main指定的类的premain⽅法(顾名思义,是在执⾏main⽅法之前执⾏的,所以运⾏期搞执⾏Pre-Main的class也不妥)。

classloader运行机制

classloader运行机制

ClassLoader是Java中的类加载器,它的主要工作是将Class加载到JVM中。

以下是其运行机制:
1. 父优先加载机制:ClassLoader采用了一种“父优先”的等级加载机制,也就是说,当一个类需要被加载时,ClassLoader会首先检查它的父类是否已经被加载。

如果父类已经被加载,那么就直接使用父类的类对象;如果父类还没有被加载,那么就先加载父类,然后再加载当前类。

这种机制也适用于同一加载器中加载的类之间的依赖关系。

2. 类加载过程:当一个类需要被加载时,ClassLoader会首先找到这个类的class文件,并把这个文件包含的字节码加载进内存。

然后,它会对这些字节码进行解析和初始化。

在解析过程中,ClassLoader 会将类字节码重新解析成JVM统一要求的对象格式,并生成类的Class对象。

3. 显示和隐式加载:ClassLoader有两种加载方式:显示加载和隐式加载。

隐式加载是指不需要代码调用类加载器加载需要的类,而是通过JVM自动加载。

显示加载则需要调用类加载器来加载类。

比如,使用类Class中的forName()方法、ClassLoader中的loadClass()方法或findSystemClass()方法等来加载类。

总的来说,ClassLoader在Java中扮演着非常重要的角色,它负责将Class加载到JVM中,并审查每个类应该由谁来加载,以及将类字节码重新解析成JVM统一的对象格式。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
} }
或者 public class MyClassLoader extends ClassLoader{
public MyClassLoader(){ super(getClass().getClassLoader());
} }
第一种方法更为常用,因为在构造方法中使用 getClass() 方法是不提倡的,因为对象初 始化仅在构造方法结束后才会完成。因此,如果正确设置了类加载器的父类加载器,不论 什么时候从类加载器实例请求一个类时,如果此类加载器不能加载此类,则首先会交给它 的父类加载器处理。如果此父类加载器也不能加载那个类,则又会交给上一层的父类加载 器,依此类推。但是如果 findBootstrapClass0()方法也未能加载那个类时,就会唤醒 findClass() 去处理。findClass()的默认的实现是抛 ClassNotFoundException 异常。所以开发者需要继承 ng.ClassLoader 来实现用户自编写的类加载器。findClass()默认的实现如下:
Java 类加载机制(一)
译:ayi 译文疏漏,请多多指点
原文:/pub/a/onjava/2005/01/26/classloading.html
注:因内容太多,分为一、二两篇文章
类加载是 java 特性的一个很重要的部分。尽管,java 中“advanced topics”的发展,使 java 的类加载机制地位有所下降。但每位编程者都应该知道这部分的工作机制,以及怎样去配 合其工作。这可以使我们节省很多时间,而不必要浪费在调试ClassNotFoundException, ClassCastException, 等。
设置父类加载器,我们有两种方法,在 ClassLoader 的构造方法中。 public class MyClassLoader extends ClassLoader{
public MyClassLoader(){ super(MyClassLoader.class.getClassLoader());
载器的正常工作来说都非常重要。在这里,最重要的是怎样正确的设置父类加载器。类加 载器的父类加载器实例会负责加载此类加载器类。(记住:一个类加载器本身也是一个类。) 在一个类加载器外部请求一个类时,使用 loadClass() 方法。这个方法的具体工作,我们可 以从源代码来看:
protected synchronized Class<?> loadClass (String name, boolean resolve) throws ClassNotFoundException{
比如,如果我们试图得到一个核心 java 运行时类的一个类加载器,我们将得到 null 值,如 下: log(ng.String.class.getClassLoader()); 下面要说到的是 java 扩展类加载器。在 java.ext.dirs 路径下面,我们可以放 java 扩展类库, 这样我们可以获得超出 java 核心运行时类的特性。扩展类加载器(ExtClassLoader)将会加 载 java.ext.dirs 目录下的所有 .jar 文件。开发者可以为自己的应用增加新的 .jar 文件 或者 类 库,只要他把它们添加到 java.ext.dirs 目录下面以至于能被扩展类加载器找到。
类加载器
在 java 中,每个类都会被 ng.ClassLoader 的一个实例加载。ClassLoader 类处于 ng
包下面,开发者可以自由的创建它的子类,添加自己功能的类加载器。
每当敲入 java MyMainClass,一个新的 JVM 开始时,引导类加载器(bootstrap class loader ) 首先会把 java 中的一些关键类,像 ng.Objent,和运行时的代码载入内存。这些运行 时类打包在 JRE\lib\rt.jar 文件中。因为是一个本地的接口,我们并不能从 java 文档中得到 引 导 类 加 载 器 ( bootstrap class loader ) 信 息 。 也 正 是 这 个 原 因 , 引 导 类 加 载 器 (bootstrap class loader )的表现也根据 JVM 的不同而异。
这篇文章将从最基本的开始,比如代码和数据的关系,以及他们怎么样关系起来形成一 个实例或者对象。然后将会说到,java 中怎样通过类加载器把代码加载到 JVM 中,以及 java 中实现的主要的几种类型的类加载器。在这篇文章中,然后我们将会了解到 java 类加载机 制的内幕,我们将使用最基本的代码来描述,这些代码执行于类加载器之后,但在加载一 个类之前。在接下来的部分将使用一些例子来证实,对于开发者继承和开发自己的类加载 器的必要性。接着将告诉你们怎样编写自己的类加载器,以及怎样使用它们去创建一个一 般的能加载包括远程客户端辅助代码的类加载器引擎,以及怎样把它在 JVM 中定义,实例 化,然后执行。习惯上,把 J2EE­specific components 中说明的作为 java 类加载的规范,这 篇文章正是从这本手册总结来的。
的字段 class,这个字段表示的就是一个 ng.Class 型的实例。因为它是 public 类型的, 我们可以通过标识符来访问它,像这样:
ng.Class klass = Myclass.class;
只要一个类被加载到 JVM,相同的类(强调:相同的类)将不会被重复加载。这将产 生一个问题,什么才是相同的类?一个对象有一种特定状态和标识,对象总是与它所属类 联系在一起,与这种状况相似,一个被加载到 JVM 中类也有特定的标识,接下来我们就阐 述:
在 java 中,一个类通过认证的类全名来唯一标识。认证的类全名是由包名和类名两部 分组成。但是在一个类被加载到 JVM 中则是通过认证的类全名,还有加载这个类的加载器 来唯一标识。因此,一个类的类名为 C1,包名为 Pg,被类加载器类 KClassLoader 的一个 实例 k1 加载,则 C1,也就是 C1.class ,的类实例,在 JVM 中将被解释为(C1,Pg,k1)。 这就意味着两个不同的类加载器实(Cl, Pg, kl1) 和 (Cl, Pg, kl2) ,加载的类在 JVM 中将有不 同的类实例对象,不是类型可比型(type­compatible)的。在 JVM 中有多少个类加载器实 例呢?下面,我们将讲解这个。
图 1 展 示 了 一 个 带 有 main 方 法 的 应 用 程 序 类 MyMainClass 。 正 如 前 面 所 说 的 , MyMainClass.class 将被 AppClassLoader 加载 ,MyMainClass 创建两个加载器类实例, CustomClassLoader1 和 CustomClassLoader2,他们都能从某些资源(比如说:网络)中加载 第四个类 Target 的字节码。这就意味着 Target 这个类的定义超出了应用程序的 class path 或 者扩展 class path 范围。在这种 情况下,如果 MyMainClass 让客户加载器实例去加载 Target 类。Target 将同时被 CustomClassLoader1 和 CustomClassLoader2 加载和定义。在 java 中这样就会有严重的问题。如果在 Target 中包含一段静态(static)的初始化代码,如果我 们要求这段代码执行且仅贝被执行一次,在我们目前的情况下,这段代码将被执行两次。 在两个 CustomClassLoader 中,都执行了一次。如果 Target 被两个 CustomClassLoader 同时 初始化,他将会有两个实例 target1 和 target2 ,正如下面图 1 所示的,target1 和 target2 是不 可比的。也就是说,在 java 中不能执行这段代码:
// First check if the class is already loaded Class c = findLoadedClass(name); if (c == null) {
try { if (parent != null) { c = parent.loadClass(name, false); } else { c = findBootstrapClass0(name); }
在 Sun 的 java 指南中,文章“理解扩展类加载”(Understanding Extension Class Loading) 对以上三个类加载器路径有更详尽的解释,这是其他几个 JDK 中的类加载器
.URLClassLoader java.security.SecureClassLoader java.rmi.server.RMIClassLoader sun.applet.AppletClassLoader
protected Class<?> findClass(String name)
throws ClassNotFoundException {
throw new ClassNotFoundException(name);
}
深入 findClass()方法,类加载器需要从其它资源获取字节码。这些资源可以是文件系统、网 络 URL、数据库、其它的可以把字节码转换为流的应用程序,或者能够产生与 java 特性相 适应的字节码的类似资源。你可以使用BCEL (Byte Code Engineering Library),它能非常方便 的根据运行时的迹象创建类 。BCEL 已经成功的应用在了一些地方,如编译器、优化程序、 模糊程序(ob节码被重新获取,findClass()
类和数据
一个类代表一段要执行的代码,然而数据则代表与这些代码相关联的某种状态。状态可 以改变,代码不能改变。我们把一种特定状态与一个类关联起来时,就得到了这个类的一 个实例。所以同一个类的不同实例有不同的状态,但都参照相同的代码。在 java 中,一个 类通常它的代码就包含在一个 .class 文件中,虽然其中也包括异常。然而,在 java 运行时, 每个类都会构造一个超类对象(first­class object),它们其实是 ng.Class 的实例。不 论何时编译一个 java 文件,编译器都会在编译后的字节码中嵌入一个 public, static, final 型
相关文档
最新文档