今台看了一点关于类加载器的东西,总结一下算作一个小复习吧,尽可能的每天学习一点知识点,积水成渊吧
首先我们如何看当一个类运行的时候相关的加载信息呢 在命令行下可以采用java -verbose:class 类名称 ,如果是在eclipse下(本人其实用的是myeclipse) 设置一下运行参数就可以。如下图
这样你就可以在运行的时候就可以看到相关类是如何加载的
我们运行一下
你会看到类似如下的信息,只是类似并不是雷同。
[Opened D:\Program Files\Genuitec\Common\binary\com.sun.java.jdk.win32.x86_1.6.0.013\jre\lib\rt.jar]
[Loaded java.lang.Object from D:\Program Files\Genuitec\Common\binary\com.sun.java.jdk.win32.x86_1.6.0.013\jre\lib\rt.jar]
[Loaded java.io.Serializable from D:\Program Files\Genuitec\Common\binary\com.sun.java.jdk.win32.x86_1.6.0.013\jre\lib\rt.jar]
[Loaded java.lang.Comparable from D:\Program Files\Genuitec\Common\binary\com.sun.java.jdk.win32.x86_1.6.0.013\jre\lib\rt.jar]
[Loaded java.lang.CharSequence from D:\Program Files\Genuitec\Common\binary\com.sun.java.jdk.win32.x86_1.6.0.013\jre\lib\rt.jar]
[Loaded java.lang.String from D:\Program Files\Genuitec\Common\binary\com.sun.java.jdk.win32.x86_1.6.0.013\jre\lib\rt.jar]
[Loaded java.lang.reflect.GenericDeclaration from D:\Program Files\Genuitec\Common\binary\com.sun.java.jdk.win32.x86_1.6.0.013\jre\lib\rt.jar]
[Loaded java.lang.reflect.Type from D:\Program Files\Genuitec\Common\binary\com.sun.java.jdk.win32.x86_1.6.0.013\jre\lib\rt.jar]
[Loaded java.lang.reflect.AnnotatedElement from D:\Program Files\Genuitec\Common\binary\com.sun.java.jdk.win32.x86_1.6.0.013\jre\lib\rt.jar]
[Loaded java.lang.Class from D:\Program Files\Genuitec\Common\binary\com.sun.java.jdk.win32.x86_1.6.0.013\jre\lib\rt.jar]
从以上信息你基本上可以看到一个在执行的时候加载的相关类及jar,明白类在什么时候被加载。以上都是类加载器classloader的工作(这是一份没有小费的工作),getCallerClassLoader()是类加载器的一个私有方法,所以我们是没办法直接调用的,所以在运行中我们应该通过当前 类的实例.getClass().getClassLoader(); getCallerClassLoader()这个方法的调用其实是暗箱操作如果你玩过地下柳河菜或者都求的话,你懂得! 在new一个实例的时候这个方法会被默认调用。
在这里我纠正一个常识,静态初始化区域并不是在类第一次载入才会被加载,而是在第一次初始化时被加载并且只有一次。我们测试一下,下面是测试代码:
package com.ec.test.classloader.test;
public class C {
/**
* @param args
* @throws ClassNotFoundException
*/
public static void main(String[] args) throws ClassNotFoundException {
// TODO Auto-generated method stub
//将true改成false在测试一下
Class.forName("com.ec.test.classloader.test.B", true, new C().getClass().getClassLoader());
}
}
class B{
static{
System.out.println("test静态初始化区域");
}
}
我们看一下Class.forName()的api
* @param name fully qualified name of the desired class
* @param initialize whether the class must be initialized
* @param loader class loader from which the class must be loaded
* @return class object representing the desired class
第二个参数 initialize 布尔类型,判断该类是否必须初始化。当initialize 为true的时候我们就会看到 ”test静态初始化区域“输出 ,相反没有任何输出,
classloader.loadClass("")与 Class.forName("com.cn.B", false, classLoader);一样都没有对类进行第一次初始化
那么类如果在第一次载入的时候没有被初始化,那么在什么时候会初始化呢,答案是在第一次实例化的时候,如果第一次载入已经初始化,那么第一次实例化还会初始化吗,其实前面我们已经说到了,在第一次初始化时被加载并且只有一次。也就是说第一次载入的话已经被初始化了那么第一次实例化的时候是不会被再次初始化的,下面我们验证一下修改上面的代码
package com.ec.test.classloader.test;
public class C {
/**
* @param args
* @throws ClassNotFoundException
* @throws IllegalAccessException
* @throws InstantiationException
*/
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
// TODO Auto-generated method stub
//将true改成false在测试一下
System.out.println("==========开始载入类B==========");
Class c=Class.forName("com.ec.test.classloader.test.B", true, new C().getClass().getClassLoader());
System.out.println("==========载入类B结束==========");
System.out.println("==========开始实例化B==========");
Object o=c.newInstance();
System.out.println("==========实例化B结束===========");
//new C().getClass().getClassLoader().loadClass("com.ec.test.classloader.test.B");
}
}
class B{
static{
System.out.println("test静态初始化区域");
}
}
下面我们来看一下initialize 为true的时候输出结果为
==========开始载入类B==========
test静态初始化区域
==========载入类B结束==========
==========开始实例化B==========
==========实例化B结束===========
下面我们来看一下initialize 为false的时候输出结果为
==========开始载入类B==========
==========载入类B结束==========
==========开始实例化B==========
test静态初始化区域
==========实例化B结束===========
好了通过结果你懂得。 在这里在说一点我们采用new操作的时候会自动初始化和实例化该类,这个暗箱操作也许是我们长久没发现这个问题的原因。
- 大小: 13.3 KB
分享到:
相关推荐
参考资料-行政裁定书(补正裁判文书笔误用).zip
这是一个找到一篇关于权限设计的教程,写的很好,但是发现给出的代码,有些地方可能有笔误。贴出来供大家和我一起学习。 首先,设置三种要素:用户、群组、角色。 用户为登录用,对应到人。群组对应为用户的集合,是...
的过程中的一些学习笔记,但是为了能够涉及到大部分后端学习所需的技术知识点我也会偶尔引用一些别人的优秀文章的链接。文档大部分内容都是笔者参考书籍以及自己的原创。少部分面试题回答参考了其他人已有答案,上面...
基于JAVA毕业设计-JAVA+SQL离散数学题库管理系统(源代码+论文+外文翻译).rar 题库、试卷建设是教学活动的重要组成部分,传统手工编制的试卷经常出现内容雷同、知识点不合理以及笔误、印刷错误等情况。为了实现离散...
JAVA+SQL离散数学题库管理系统(源代码+论文+外文翻译) 题库、试卷建设是教学活动的重要组成部分,传统手工编制的试卷经常出现内容雷同、知识点不合理以及笔误、印刷错误等情况。为了实现离散数学题库管理的信息化而...
初中语文文摘历史此系笔误
effective-java-3rd-chinese前51条:文章翻译来源地址:about this repository本来以为只是个直接搬运的活,实际上不是。主要工作如下:改进排版,原有博文排版不太优秀,根据markdown 排版指北重新排版。内容修改,...
书中对数据库系统实现原理进行了深入阐述,并具体讨论了数据库管理系统的三个主要成分—存储管理器、查询处理器和事务管理器的实现技术。书中还对信息集成的最新技术,例如数据仓库、OLAP、数据挖掘、Mediator、数据...
根据软件工程学中开发软件的要求,对离散数学题库管理系统全部功能和相关的技术进行具体的分析,分析时采用结构化的分析方法,自顶向下、逐层分解问题。 2.1 项目内容及要求 根据此次项目的要求,主要完成对离散数学...
java8 源码 疾风知劲草,智者必怀仁,时刻学习总结 项目说明: 以下笔记都是自己学习实践后总结出来的,其中不可避免存在笔误或者有理解错误的地方,欢迎指出。 以下列举的笔记都可以在项目中的文件夹中找到。 笔记...
采用计算机信息管理技术与数据库技术,建立合理出题、公正阅卷和科学评价为一体的试题库管理系统,每次考试前由题库中题目随机生成试卷,则可较好地解决教考分离的问题,体现考试的公正性,也可将广大教师从繁重的...
书中对数据库系统实现原理进行了深入阐述,并具体讨论了数据库管理系统的三个主要成分—存储管理器、查询处理器和事务管理器的实现技术。书中还对信息集成的最新技术,例如数据仓库、OLAP、数据挖掘、Mediator、数据...
题库、试卷建设是教学活动的重要组成部分,传统手工编制的试卷经常出现内容雷同、知识点不合理以及笔误、印刷错误等情况。为了实现离散数学题库管理的信息化而开发了离散数学题库管理系统。 该系统采用C/S 模式,...
基于JAVA+SQL离散数学题库管理系统(源代码+外文翻译)还有现成论文在里面。 题库、试卷建设是教学活动的重要组成部分,传统手工编制的试卷经常出现内容雷同、知识点不合理以及笔误、印刷错误等情况。为了实现离散数学...
我们团队最近在 Chrome V8 引擎 3.20 至 4.2 版中发现了一个很有趣的漏洞,由于源代码中的一个笔误, 造成关键对象信息泄露,从而可以导致任意代码执行,我们将该漏洞命名为 BadKernel。Chrome Mobile、Opera Mobile...
题库、试卷建设是教学活动的重要组成部分,传统手工编制的试卷经常出现内容雷同、知识点不合理以及笔误、印刷错误等情况。为了实现离散数学题库管理的信息化而开发了离散数学题库管理系统。 该系统采用C/S 模式,...
java翻牌源码 effective-java-3rd-chinese 前51条:文章翻译来源地址: ...内容修改,原作者在翻译过程中有笔误(可能打字太快了),这里进行修改。 等待内容搬运完成,使用cmd markdown生成 pdf 离线文件 mark
库、试卷建设是教学活动的重要组成部分,传统手工编制的试卷经常出现内容雷同、知识点不合理以及笔误、印刷错误等情况。为了实现离散数学题库管理的信息化而开发了离散数学题库管理系统。 该系统采用C/S 模式,前台...