java类加载器和类反射使用示例
一、一个命令对应一个进程。
当我们启动一个Java程序,即启动一个main方法时,都将启动一个Java虚拟机进程,不管这个进程有多么复杂。而不同的JVM进程之间是不会相互影响的。这也就是为什么说,Java程序只有一个入口——main方法,让虚拟机调用。而两个mian方法,对应的是2个JVM进程,启动的是两个不同的类加载器,操作的实际上是不同的类。故而不会互相影响。
二、类加载。
当我们使用一个类,如果这个类还未加载到内存中,系统会通过加载、连接、初始化对类进行初始化。
1、类加载:指的是将类的class文件读入JVM,并为之创建一个Class对象。
2、类连接:指的是把类的二进制数据合并到JRE中,这又分为3个阶段:
a)、校验:检查载入Class文件数据的正确性。
b)、准备:给类的静态变量分配存储空间,并进行默认初始化。
c)、解析:将类的二进制数据中的符号引用替换成直接引用。
3、初始化:对类的静态变量、静态初始化块进行初始化。
(注意:一个final类型的静态属性,如果在编译时已经得到了属性值,那么调用该属性时,不会导致该类初始化,因为这个相当于使用常量;
使用ClassLoader()方法,只是加载该类,并未初始化。)
三、类加载器。
类加载器就是负责将.class文件加载到内存中,并为之生成对应的java.lang.Class对象,它负责加载所有的类,而一旦一个类被加载入JVM中,就不会被再次载入了。
在Java中,一个类用其全限定类名(即包名+类名)作为标识。
而在JVM中,一个类用其全限定类名和其类加载器作为标识。
JVM运行时会产生3个ClassLoader,分别为:BootstrapClassLoader(根类加载器)、ExtClassLoader(扩展类加载器)和AppClassLoader(系统类加载器)。UML结构如下:
其中,BootstrapClassLoader负责加载JRE的核心类库,它不是ClassLoader的子类,使用C++编写,因此我们在Java中看不到它,通过其子类的getParent()方法获取时,将返回null。BootstrapClassLoader负责装载JRE目标下的rt.jar、charsets.jar等Java核心类库。
如图可知,ExtClassLoader和AppClassLoader为ClassLoader的子类。在API中看不到它们,他们位于rt.jar文件中。全限定类名分别为:
sun.misc.Launcher$ExtClassLoader和sun.misc.Launcher$AppClassLoader.
其中,ExtClassLoader负责装载JRE扩展目录ext中JAR包,而AppClassLoader负责装载Classpath路径下的类包。
测试如下:
packagecom.stopTalking.crazy;
publicclassTestClassLoader{
publicstaticvoidmain(String[]args){
//获取当前线程的类装载器
ClassLoaderloader=Thread.currentThread().getContextClassLoader();
//获取System类的类装载器
ClassLoaderloader1=System.class.getClassLoader();
//获取本类TestClassLoader的类装载器loader2
ClassLoaderloader2=TestClassLoader.class.getClassLoader();
//获取loader2的父类
ClassLoaderloader3=loader2.getParent();
//获取loader2的父类的父类
ClassLoaderloader4=loader3.getParent();
System.out.println(loader);
System.out.println(loader1);
System.out.println(loader2);
System.out.println(loader3);
System.out.println(loader4);
}
}
控制台输出:
//当前线程类获取的类加载器是AppClassLoader
sun.misc.Launcher$AppClassLoader@6b97fd
//System类为根装载器加载,java中访问不到,所以为null
null
//本类的类加载器当然也是AppClassLoader
sun.misc.Launcher$AppClassLoader@6b97fd
sun.misc.Launcher$ExtClassLoader@1c78e57
null
相关文章
- fileinputstream java,使用url的Java fileinputstream
- java分层打印二叉树_基于Java的二叉树层序遍历打印实现
- java 104规约_IEC104规约,Java开发主站程序
- java 图片识别 tess4j_JAVA使用Tess4J进行ocr识别
- Java 反射 -超详细讲解(附源码)「建议收藏」
- 学java用什么编译器_学习Java用什么编译软件好
- java pfx 证书_Java将pfx证书转换为jks[通俗易懂]
- java怎么用_如何使用Java编写程序
- java有什么作用_Java有什么用「建议收藏」
- java生成license_使用truelicense实现用于JAVA工程license机制(包括license生成和验证)…
- java验证手机号正则表达式_Java使用正则表达式验证手机号和电话号码的方法「建议收藏」
- java运行环境配置(jdk配置)Java博客 2 年前 桃李Taoli
- java 异或加密_Java异或技操作给任意的文件加密原理及使用详解
- JAVA外文参考文献_java参考文献近五年
- Java比较两个对象中属性值是否相同【使用反射实现】
- 数据如何使用Java读取MySQL数据(java读取mysql)
- Java 与 Linux 的结合:开启新时代(java和linux)
- 实现使用Java实现Redis消息队列(redis消息队列java)
- 使用Java操作MySQL数据库快速精准查询(java查询mysql数据库)
- 更新LINUX下的Java版本(linux更新java)
- Java下使用Redis进行高效缓存优化(Redis缓存java)
- 使用Java轻松导出MySQL数据(java导出mysql)
- Java文件在Linux系统中的使用(java文件linux)
- 使用Redis优化Java开发的关键技巧(redis与java开发)
- java使用Weka、Linux和Java构建强大的数据分析系统(weka linux)
- Java实现Linux:跨平台解决方案(java 实现linux)
- Novice:学习Java 7 在Linux上的简单入门(java 7 linux)
- 合Java与Oracle联手打造崭新未来(java和oracle联)