建站论坛,福建凭祥建设工程有限公司网站,深圳十大景观设计公司排名,开发一款手机app的步骤Java中类的加载过程#xff08;如Dog类#xff09;#xff1a; 通过类型信息定位Dog.class文件。载入Dog.class文件#xff0c;创建相应的Class对象。执行父类的静态字段定义时初始化语句和父类的静态初始化块。执行子类的静态字段定义时初始化语句和子类的静态初始化块。当… Java中类的加载过程如Dog类 通过类型信息定位Dog.class文件。载入Dog.class文件创建相应的Class对象。执行父类的静态字段定义时初始化语句和父类的静态初始化块。执行子类的静态字段定义时初始化语句和子类的静态初始化块。当使用new Dog()方式时在堆上为Dog对象分配存储空间并清零分配的存储空间。执行父类的字段定义时初始化语句和父类的构造函数。执行子类的字段定义时初始化语句和子类的构造函数。参考Java编程思想部分是自己测试的结果还没有看到相关资料这个顺序和C#的顺序好像有比较大的差别 我们知道每个Java类编译后会生成一个.class文件里面除了存储了类的字节码之外还存储了和该类对应的Class对象的信息包含一些用于反射的信息。在JVM中通过类加载器ClassLoader来实现Class对象的创建。 在Object类中有public的getClass()方法我们可以通过该方法获取与之对应的Class对象。在获取类对应的Class对象后我们就可以通过newInstance()方法或者通过获取其Constructor的方法来创建该类的实例也可以通过Class对象获取类或实例相关的更多信息如方法字段等即反射的功能。另外我们也可以通过Class.forName()方法通过传入类字符串的方式来创建类的实例。通过Class对象创建类实例和通过forName方法创建类实例是否有联系呢这两种创建类的实例和直接通过new创建类实例是否也有联系呢 然而Dog.class文件是如何定位的Dog.class文件是如何被加载并解析的Class对象又是如何生成的呢这就是ClassLoader需要解决的问题也是这篇文章中接下来要讲述的。 ClassLoader的工作原理 在Java内部实现了三种类型的ClassLoaderBootstrap ClassLoaderExtension ClassLoader System ClassLoader。这三个ClassLoader通过parent形成一条单向链其中Bootstrap处于链尾而System ClassLoader处于链头。 Bootstrap ClassLoader Bootstrap ClassLoader用于在启动JVM时加载类以使JVM能正常工作因而它是用Native代码实现的最早被创建出来处于最底层。 Bootstrap ClassLoader将搜索Java核心库%JAVA_HOME%\jre\lib如rt.jar、i18n.jar等在这些核心库中包含了Java的核心类即Bootstrap ClassLoader用于加载Java的核心类包括java.lang、java.io等包中的类。 Extension ClassLoader Extension ClassLoader位于链的中间层它将搜索特定的标准扩展目录。该标准扩展目录在不同的JVM实现中不一定相同在sun的JVM中它是%JRE_HOME% \lib\ext具体路径可以通过java.ext.dirs系统属性值获取。该标准扩展目录存在的目的在于扩展和共享应用程序厂商可以将部分共享库放置于此而不是各自程序的目录下的多份拷贝。在开发过程中我们也可以把部分常用的库放置于此而不必每次都去配置环境。 System ClassLoader System ClassLoader位于链的最顶层它将搜索CLASSPATH中配置的目录和jar文件。 三种ClassLoader的协同工作 既然系统中有三种不同的ClassLoader那么一个类的加载是用那个ClassLoader呢在Java中是通过“代理模型delegation model”来决定使用哪个ClassLoader来加载类的读取.class文件并创建相应的Class对象。当一个类需要被加载的时候系统默认通过System ClassLoader来加载该类然而System ClassLoader并不立即加载该类它会将加载的行为代理给其parent去加载只有当其parent不能加载该类的时System ClassLoader才去搜索CLASSPATH中的目录和jar文件以加载该类若找到对应的.class文件则加载该类否则抛出ClassNotFoundException。当它将加载的行为代理给Extension ClassLoader并最终代理给Bootstrap ClassLoader的时候他们也做的是相似的事情。从设计的角度这其实就是一种职责链模式Chain of Responsibility Pattern。 那么Java为什么需要这种代理模型呢答案是出于安全的考虑。Java是一种安全的编程语言它会对每个加载的类执行安全检查但是对Java核心库中的类是不执行安全检查的即他们是受JVM信赖的。什么是安全检查以我现在所知就是用户可以通过security manager来控制特定目录的访问权限如何使用这些控制将会是另一个主题。对安全检查是否还有其他的呢那么假如用户可以加载自己编写的和核心库同名的类如java.lang.Object那么这些用户编写的类就可以绕过安全检查从而为一些恶意用户提供了一种破坏的途径。然而在使用这种代理模型后类的加载首先会代理到Bootstrap ClassLoader中实行加载如果它发现当前核心类库中可以加载对应的类系统会加载核心库中的类而不会加载用户编写的类。 但是如果只是这样还不足以保证类的加载的安全。因为用户完全可以定义自己的ClassLoader在自己的ClassLoader中破坏这种代理模型那么用户自己写的java.lang.Object就可以被加载了。为了解决这个问题在Java中认为两个类名相同的实例如果加载他们的ClassLoader不同那么他们是不同的类型即他们之间不能转换而且用instanceof操作符返回的是false。这样的话即使用户加载了自己的java.lang.Object类它也不是系统认为可以信赖的java.lang.Object那么它就绕不过安全检查机制。以上的描述只是我的猜想我还没有看到相关的资料提到该问题因而有待验证。 有人说使用这种机制可以实现兼容性的升级在软件的旧版本中使用某个旧版本的类在升级的某些新部分中可以使用相同类的新版本即实现内存中保留一个类的两个版本。我认为这种不应该是一种推荐的做法在内存中保留一个类的两个版本极易在运行是引起一些莫名其妙的错误。 很可惜我没能找到以上三种ClassLoader的源码看不了内部的实现。在Java中它们都是通过ClassLoader这个抽象类来表示的。以下简单的介绍一下ClassLoader内部的成员 其中Extension ClassLoader的实现类为sun .misc.Launcher$ExtClassLoader 来自 http://dlevin.iteye.com/blog/772604转载于:https://www.cnblogs.com/hellocyc/p/4409722.html