华为技术面试压轴题,请说明java的类加载机制! 麻烦高手就此题做简明论述,不要过分展开,把问题讲清楚就行!谢谢! 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 此回复为自动发出,仅用于显示而已,并无任何其他特殊作用楼主【Fenglee2008】截止到2008-06-30 22:43:20的历史汇总数据(不包括此帖):发帖数:25 发帖分:536 结贴数:25 结贴分:536 未结数:0 未结分:0 结贴率:100.00% 结分率:100.00% 敬礼! JVM中类的装载是由ClassLoader和它的子类来实现的,Java ClassLoader 是一个重要的Java运行时系统组件。它负责在运行时查找和装入类文件的类。 我博客里有想要更详细的也可以http://blog.csdn.net/lastsweetop/archive/2008/03/14/2182219.aspx总共3篇 ft 好像第一篇被csdn吃掉了我的原创啊 哎 ,类初始化 装载-连接-初始化 类"初始化"阶段,它是一个类或接口被首次使用的前阶段中的最后一项工作,本阶段负责为类变量赋予正确的初始值。 Java 编译器把所有的类变量初始化语句和类型的静态初始化器通通收集到 <clinit> 方法内,该方法只能被 Jvm 调用,专门承担初始化工作。 除接口以外,初始化一个类之前必须保证其直接超类已被初始化,并且该初始化过程是由 Jvm 保证线程安全的。另外,并非所有的类都会拥有一个 <clinit>() 方法,在以下条件中该类不会拥有 <clinit>() 方法: 该类既没有声明任何类变量,也没有静态初始化语句; 该类声明了类变量,但没有明确使用类变量初始化语句或静态初始化语句初始化; 该类仅包含静态 final 变量的类变量初始化语句,并且类变量初始化语句是编译时常量表达式 的初始化时机就是在"在首次主动使用时",那么,哪些情形下才符合首次主动使用的要求呢? 首次主动使用的情形: 创建某个类的新实例时--new、反射、克隆或反序列化; 调用某个类的静态方法时; 使用某个类或接口的静态字段或对该字段赋值时(final字段除外); 调用Java的某些反射方法时 初始化某个类的子类时 在虚拟机启动时某个含有main()方法的那个启动类。 对象初始化 先是static变量和方法(类初始化),由clinit来初始化; 然后是实例变量,实例模块初始化,构造方法初始化,由init来初始化; 如果有继承关系,则先执行父类的初始化,然后才是子类的! 在类被装载、连接和初始化,这个类就随时都可能使用了。对象实例化和初始化是就是对象生命的起始阶段的活动,在这里我们主要讨论对象的初始化工作的相关特点。 Java 编译器在编译每个类时都会为该类至少生成一个实例初始化方法--即 "<init>()" 方法。此方法与源代码中的每个构造方法相对应,如果类没有明确地声明任何构造方法,编译器则为该类生成一个默认的无参构造方法,这个默认的构造器仅仅调用父类的无参构造器,与此同时也会生成一个与默认构造方法对应的 "<init>()" 方法. 通常来说,<init>() 方法内包括的代码内容大概为:调用另一个 <init>() 方法;对实例变量初始化;与其对应的构造方法内的代码。 如果构造方法是明确地从调用同一个类中的另一个构造方法开始,那它对应的 <init>() 方法体内包括的内容为:一个对本类的 <init>() 方法的调用;对应用构造方法内的所有字节码。 如果构造方法不是通过调用自身类的其它构造方法开始,并且该对象不是 Object 对象,那 <init>() 法内则包括的内容为:一个对父类 <init>() 方法的调用;对实例变量初始化方法的字节码;最后是对应构造子的方法体字节码。 如果这个类是 Object,那么它的 <init>() 方法则不包括对父类 <init>() 方法的调用。 谢LS几位兄弟,有没有兄弟愿意从ClassLoader,AppClassLoader,BootStrapClassLoader等角度帮忙解释一下! 类加载的过程,类本身也是保存在文件中(字节码文件保存着类的信息)的,java会通过I/O流把类的文件(字节码文件)读入JVM(java虚拟机),这个过程成为类的加载。JVM(java虚拟机)会通过类路径(CLASSPATH)来找字节码文件。 最简单的来说:把.class文件转化成Class对象。如果说详细的解释就是双亲委派模型:搂住上网搜下有很多。tomcat的再加载servlet的时候采用的就是自定义的classloader但没有采用双亲委派模型。 其实小弟在之前总结的"Java杂谈"第一章里面就曾经解释得很清楚这个问题,楼主可以去原文参考:http://topic.csdn.net/u/20070924/21/18482496-082f-4907-8751-b80ab5d56622.html这里就简单的说一下吧——首先Java的类加载遵循运行时判定原则,即当这个类真正要被实例化的时候才会由某个ClassLoader去加载进JVM,加载类的寻找范围就是JVM默认路径加上Classpath,在Classpath下的所有class文件都可以被JVM加载但未必都要加载(需要谁加载谁)至于由哪一个ClassLoader去加载呢?一般三个级别的ClassLoader遵循双亲委派预模型以此去自己的路径下寻找,依次顺序是BootstrapClassLoader去 "JDK目录\Jre\" 下寻找ExtClassLoader去 "JDK目录\Jre\ext\" 下寻找AppClassLoader去 "classpath环境变量" 下寻找(默认是".",即运行Main Class文件的当前目录)这里就不赘述了,具体的环境变量值楼主可以调用System.getProperty(key)去查看,可以用的key都在JDK API的lang包System类的getProperties方法下 好大的题,<深入JVM>用了很长的篇幅来说明。 《java深度历险》里有比较详细的说明。 在java.lang包里有个ClassLoader类,ClassLoader 的基本目标是对类的请求提供服务。当 JVM 需要使用类时,它根据名称向 ClassLoader 请求这个类,然后 ClassLoader 试图返回一个表示这个类的 Class 对象。通过覆盖对应于这个过程不同阶段的方法,可以创建定制的 ClassLoader。 java运行时会根据需要加载类,而加载类的细节会因JVM实现的不同而有所不同,但是大多数实现都使用类路径机制来搜索在代码中引用的尚未加载到运行时系统中的类.类路径是系统用来寻找类文件的位置列表,这种默认机制在大多数情况下能很好地发挥作用,但JVM的强大之处是它能够从对应用程序有意义的地方加载类,为了让应用程序以非默认方式加载类,必须提供获取类的字节码并把它加载到JAVA运行时的ClassLoader对象. 大学科技立项课题求教 用过SecureCRT 4.1请帮下忙. 真数组是什么意思? 如何用java应用程序打印Excel文档 Vector是不是已经完全被ArrayList或LinkedList取代了呢?在什么情况下还需要使用它? 新手求助 一个基础的问题,怎样计算交互和? 我下栽了borland enterprise application但是缺少序列号密码,谁给我一个, 哪有HTML语法的下载? str="hello world" str += str; 循环20来次就内存溢出了? 使用JGraph在网页上显示拓扑图并添加鼠标事件的问题 java打印螺旋方阵
楼主【Fenglee2008】截止到2008-06-30 22:43:20的历史汇总数据(不包括此帖):
发帖数:25 发帖分:536
结贴数:25 结贴分:536
未结数:0 未结分:0
结贴率:100.00% 结分率:100.00%
敬礼!
总共3篇
我的原创啊 哎
装载-连接-初始化
类"初始化"阶段,它是一个类或接口被首次使用的前阶段中的最后一项工作,本阶段负责为类变量赋予正确的初始值。 Java 编译器把所有的类变量初始化语句和类型的静态初始化器通通收集到 <clinit> 方法内,该方法只能被 Jvm 调用,专门承担初始化工作。 除接口以外,初始化一个类之前必须保证其直接超类已被初始化,并且该初始化过程是由 Jvm 保证线程安全的。另外,并非所有的类都会拥有一个 <clinit>() 方法,在以下条件中该类不会拥有 <clinit>() 方法: 该类既没有声明任何类变量,也没有静态初始化语句;
该类声明了类变量,但没有明确使用类变量初始化语句或静态初始化语句初始化;
该类仅包含静态 final 变量的类变量初始化语句,并且类变量初始化语句是编译时常量表达式
的初始化时机就是在"在首次主动使用时",那么,哪些情形下才符合首次主动使用的要求呢? 首次主动使用的情形:
创建某个类的新实例时--new、反射、克隆或反序列化;
调用某个类的静态方法时;
使用某个类或接口的静态字段或对该字段赋值时(final字段除外);
调用Java的某些反射方法时
初始化某个类的子类时
在虚拟机启动时某个含有main()方法的那个启动类。
先是static变量和方法(类初始化),由clinit来初始化;
然后是实例变量,实例模块初始化,构造方法初始化,由init来初始化;
如果有继承关系,则先执行父类的初始化,然后才是子类的!
在类被装载、连接和初始化,这个类就随时都可能使用了。对象实例化和初始化是就是对象生命的起始阶段的活动,在这里我们主要讨论对象的初始化工作的相关特点。 Java 编译器在编译每个类时都会为该类至少生成一个实例初始化方法--即 "<init>()" 方法。此方法与源代码中的每个构造方法相对应,如果类没有明确地声明任何构造方法,编译器则为该类生成一个默认的无参构造方法,这个默认的构造器仅仅调用父类的无参构造器,与此同时也会生成一个与默认构造方法对应的 "<init>()" 方法. 通常来说,<init>() 方法内包括的代码内容大概为:调用另一个 <init>() 方法;对实例变量初始化;与其对应的构造方法内的代码。 如果构造方法是明确地从调用同一个类中的另一个构造方法开始,那它对应的 <init>() 方法体内包括的内容为:一个对本类的 <init>() 方法的调用;对应用构造方法内的所有字节码。 如果构造方法不是通过调用自身类的其它构造方法开始,并且该对象不是 Object 对象,那 <init>() 法内则包括的内容为:一个对父类 <init>() 方法的调用;对实例变量初始化方法的字节码;最后是对应构造子的方法体字节码。 如果这个类是 Object,那么它的 <init>() 方法则不包括对父类 <init>() 方法的调用。
java会通过I/O流把类的文件(字节码文件)读入JVM(java虚拟机),
这个过程成为类的加载。JVM(java虚拟机)会通过类路径(CLASSPATH)来找字节码文件。
如果说详细的解释就是双亲委派模型:搂住上网搜下有很多。
tomcat的再加载servlet的时候采用的就是自定义的classloader
但没有采用双亲委派模型。
http://topic.csdn.net/u/20070924/21/18482496-082f-4907-8751-b80ab5d56622.html这里就简单的说一下吧——
首先Java的类加载遵循运行时判定原则,即当这个类真正要被实例化的时候才会由某个ClassLoader去加载进JVM,加载类的寻找范围就是JVM默认路径加上Classpath,在Classpath下的所有class文件都可以被JVM加载但未必都要加载(需要谁加载谁)至于由哪一个ClassLoader去加载呢?一般三个级别的ClassLoader遵循双亲委派预模型以此去自己的路径下寻找,依次顺序是
BootstrapClassLoader去 "JDK目录\Jre\" 下寻找
ExtClassLoader去 "JDK目录\Jre\ext\" 下寻找
AppClassLoader去 "classpath环境变量" 下寻找(默认是".",即运行Main Class文件的当前目录)这里就不赘述了,具体的环境变量值楼主可以调用System.getProperty(key)去查看,可以用的key都在JDK API的lang包System类的getProperties方法下
来搜索在代码中引用的尚未加载到运行时系统中的类.类路径是系统用来寻找类文件的位置列表,这种默认机制
在大多数情况下能很好地发挥作用,但JVM的强大之处是它能够从对应用程序有意义的地方加载类,为了让应用程序以非默认方式加载类,必须提供获取类的字节码并把它加载到JAVA运行时的ClassLoader对象.