类加载器有几种 类加载器的种类
不同自定义类加载器之间的class能互相调用吗
Class caller = Reflection.getCallerClass(3);要创建用户自己的类加载器,只需要扩展ja.lang.ClassLoader类,然后覆盖它的findClass(String name)方法即可,该方法根据参数指定类的名字,返回对应的Class对象的引用。
类加载器有几种 类加载器的种类
类加载器有几种 类加载器的种类
findClass
protected Class> findClass(String name)
throws ClassNotFoundException
使用指定的二进制名称查找类。此方法应该被类加载器的实现重写,该实现按照委托模型来加载类。在通过父类加载器检查所请求的类后,此方法将被 loadClass 方法调用。默认实现抛出一个 ClassNotFoundException。
参数:
name - 类的二进制名称
返回:
得到的 Class 对象
抛出:
ClassNotFoundExceptipublic static void main(String args[])on - 如果无法找到类
两个类加载器加载同一个类
如果在上述程式中,如果您使用程式码:两个类加载器加载同一个类
类与类加载器的关系
这里的“相等”,包括代表类的Class对象的equals()方法,isAssignableForm()方法和,isInstance()方法的返回结果。也包括instanceOf关键字对象所属关系判定等情况。如果没有注意到类加载器的影响,在某些情况下会产生迷惑人的结果。
如例:
结果分析:
用自定义类加载器加载类ClassLoaderTest,与系统默认加载器加载的类进行isInstance比较,结果为flase。
这是因为JVM中存在了两个ClassLoaderTest类,一个是由系统默认类加载器加载的,一个是由自定义类加载器myloader加载的。
虽然都来自同一个class文件,但依然类加载器用于实现类的加载动作,但它在ja中起到的作用远远不仅于类加载阶段。对于任何一个类来说,都需要类本身和加载这个类的类加载器一同确立其在ja JVM中的性。通俗来讲:比较两个类是否相等,只有两个类是由同一个类加载器加载的前提下才有意义。否则,即使两个类来自同一个class文件,但是由于加载他们的类加载器不同,那这两个类就必不相等。是两个的类。
说明判定类相同的条件:1、类加载器相同。 2、class文件相同
--文字和实例均摘抄自《深入理解Ja虚拟机:JVM高级特性与实践》一书
JVM之class加载过程
webman不错ja虚拟机把描述类的数据从class文件加载到内存,并对数据进行 校验/准备/解析和初始化,最终形成可以被虚拟机直接使用的Ja类型,这个过程被称作虚拟机的类加载机制。
通过上图你可以看到,intece 如同class 一般,会由编译器产生一个的类别档(.class),当类别载入器载入类别时,如果发现该类别继承了其他类别,或是实作了其他介面,就会先载入代表该介面的类别档,也会载入其父类别的类别档,如果父类别也有其父类别,也会一并优先载入。换句话说,类别载入器会依继承体系最上层的类别往下依序载入,直到所有的祖先类别都载入了,才轮到自己载入。称作虚拟机的类加载机制。
loading -> linking (verification -> preparation -> resolution)-> resolution)->initializing
verification: 校验class文件是否符合标准
preparation: 静态变量分配内存并设初始值的阶段(不包括实例变量)
initializing:静态变量赋初始值
类加载的过程主要分为三个部分:加载、连接、初始化这三个阶段。
类的加载指的是将类的.class文件中的二进制数据读入到内存中,将其放在运行时数据区的方法区内,然后在堆区创建一个这个类的ja.lang.Class对象,用来封装类在方法区类的对象。主要步骤可以分为下面的三件事情:
类的加载的最终产品是位于堆区中的Class对象。Class对象封装了类在方法区内的数据结构,并且向Ja程序员提供了访问方法区内的数据结构的接口。加载类的方式有以下几种:
2.加载器
JVM的类加载是通过ClassLoader及其子类来完成的,类的层次关系和加载顺序可以由下图来描述:
1.BootstrapClassLoader(启动类加载器)
在连接里面又可以被分成3个小阶段,分别是:验证,准备,解析
1.验证(目的):
2.验证内容:
验证是连接阶段的步,这一阶段的目的是为了确保Class文件的字节流中包含的信息符合当前虚拟机的要求,并且不会危害虚拟机自身的安全。验证阶段大致会完成4个阶段的检验动作:
验证阶段是非常重要的,但不是必须的,它对程序运行期没有影响,如果所引用的类经过反复验证,那么可以考虑采用-Xverifynone参数来关闭大部分的类验证措施,以缩短虚拟机类加载的时间。
3.准备:
在准备阶段,为静态变量的初值为jvm默认的初值,而不是我们在程序中设定的初值。jvm默认为静态变量的初值是这样的
4.解析:
这一阶段的任务就是把常量池中的符号引用转换为直接引用 什么是符号引用,什么是直接引用。
1.工作内容:
JVM负责主要对类变量(类变量就是static修改的变量)进行初始化这里主要对类变量(类变量就是static修改的变量)进行初始化,初始化主要有两个方式:
类初始化时机:只有当对类的主动使用的时候才会导致类的初始化,类的主动使用包括以下六种:
3.初始化顺序:
三、结语:
上面介绍的就是类(class)的加载,包含它的加载、链接、初始化。
Android进阶知识点,我最近整理了许多,里面讲解的非常详细。取
技术进阶手册丶面试题纲丶核心笔记资料。
vue-loader是什么
vue-loader是一个用于处理Vue组件文件的webpack加载器。
vue-loader是一个webpack的加载器,用于处理Vue组件文件。它可以将Vuloading: 把class文件load到内存中,采用双亲委派,主要是为了安全性e单文件组件的模板、脚本和样式打包在一起2.初始化时机:,以便在浏览器中使用。通过vue-loader,我们可以使用类似于模块化的开发方式编写Vue.js应用程序,将组件的模板、脚本和样式分离,提高代码的可维护性和开发效率。
Ja类别载入器
上述编译脚本定义在文件art/runtime/Android.mk中。1 Ja的动态特性
[plain] view plaincopy在CODE上查看代码片派生到我的代码片Ja的动态特性有两种,一是隐式的;另一种是显示的。隐式的(implicit)方法就是当程式设计师用到new 这个Ja 关键字时,会让类别载入器依需求载入您所需要的类别,这种方式使用了隐式的(implicit)方法。显式的方法,又分成两种方式,一种是藉由ja.lang.Class 里的forName()方法,另一种则
是藉由ja.lang.ClassLoader 里的loadClass()方法。您可以任意选用其中一种方法。
2 隐式的动态特性
在执行ja文件时,只有单独的变量声明是不会载入相应的类的,只有在用new生成实例时才载入
如示例所示:
public class Main
{A a1 = new A() ;
}类A和B相同,如下:
public class A
{public void print(“using A”);
}编译后,可用ja _verbose:class Main运行,察看输出结果。可以看到JVM只载入了A,而没有载入B.
另外,类的载入只在执行到new一个类时,才载入,如果没有执行到new语句,则不载入。
如://类Off
{public static void main(String[] args)
{Word myword=null;
Excel myexcel=null;
if (args[0].equals("Word"))
{myword = new Word();
}if (args[0].equals("Excel"))
{myexcel = new Excel();
myexcel.start();
}//类Word和Excel基本相同,如下
public class Word
{public void start()
{System.out.println("using word");
在dos命令提示符下,输入ja _verbose Off Excel可以看到JVM只载入Excel类,而不载入Word类。
3 显示的动态特性
3.1 ja.lang.Class里的forName()方法
在上一个Off示例中,进行如下修改:
一 加入Assembly类
public intece Assembly
{public void start();
}二 让Word和Excel类实现该接口
{public void start()
{System.out.println("using word");
三 Off 类如下所示
{public static void main(String[] args) throws Exception
Object o = c.newInstance();
Assembly a = (Assembly)o;
a.start();
在命令提示符下输入ja _verbose Off Word 输出入下:
下面介绍一下 forName 函数, 如果您亲自搜寻Ja 2 SDK 说明档内部对於Class 这个类别的说明,您可以发现其实有两个forName()方法,一个是只有一个参数的(就是之前程式之中所使用的):
public static Class forName(String className)
另外一个是需要三个参数的:
public static Class forName(String name, boolean initialize,ClassLoader loader)
这两个方法,最後都是连接到原生方法forName0(),其宣告如下:
private static native Class forName0(String name, boolean initialize, ClassLoader loader)
throws ClassNotFoundException;
只有一个参数的forName()方法,最後叫用的是:
forName0(className, true, ClassLoader.getCallerClassLoader());
而具有三个参数的forName()方法,最後叫用的是:
forName0(name, initialize, loader);
这里initialize参数指,在载入类之后是否进行初始化,对于该参数的作用可用如下示例察看:
类里的静态初始化块在类次被初始化时才被呼叫,且仅呼叫一次。在Word类里,加入静态初始化块
{static
{System.out.println("word static initialization ");
}public void start()
{System.out.println("using word");
将类Off作如下改变:
{public static void main(String[] args) throws Exception
{Off off= new Off();
ja.lang.Class c = ja.lang.Class.forName(args[0],true,off.getClass().getClassLoader());
System.out.println("类别准备实体化");
Object o = c.newInstance();
Object o2 = c.newInstance();
声明:本站所有文章资源内容,如无特殊说明或标注,均为采集网络资源。如若本站内容侵犯了原著者的合法权益,可联系 836084111@qq.com 删除。