Java类加载和类反射回顾
今天学习Spring,突然想重新复习一下Java类加载和类反射的。巩固一下底层原理。部分参考了李刚老师的《疯狂Java讲义》和陈雄华、林开雄的《Spring3.x企业应用开发实战》。
一、一个命令对应一个进程。
当我们启动一个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路径下的类包。
测试如下:
package com.stopTalking.crazy;
public class TestClassLoader {
public static void main(String[] args) {
//获取当前线程的类装载器
ClassLoader loader = Thread.currentThread().getContextClassLoader();
//获取System类的类装载器
ClassLoader loader1 = System.class.getClassLoader();
//获取本类TestClassLoader的类装载器loader2
ClassLoader loader2 = TestClassLoader.class.getClassLoader();
//获取loader2的父类
ClassLoader loader3 = loader2.getParent();
//获取loader2的父类的父类
ClassLoader loader4 = 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
四、类加载机制。
JVM的类加载机制主要有如下三种机制:
1、全盘负责:当一个类加载器负责加载某个Class的时候,该Class所依赖的和引用的其他Class也将由该类加载器负责载入。
2、父类委托:先委托父加载器试图加载该类,只有在父加载器无法加载该类时才从自己的类路径中查找并装载该类。
3、缓存机制:缓存机制保证所有被家加载过的类都会被缓存,当程序中需要使用某个Class时,类加载器先从缓存中搜寻。缓存中搜寻不到,才会重新读取该类对应的二进制数据,并创建对应的Class对象。
(注意:类加载器之间的父子关系,并不是类继承上的父子关系,而是类加载器实例之间的关系)
五、反射
以下是反射简单用法。
1、ClassLoader对象。
可以通过2种方式获得当前ClassLoader对象,一种是通过当前线程:
ClassLoader loader = Thread.currentThread().getContextClassLoader();
若已经有了Class对象,那么可以通过Class对象的getClassLoader()方法:
ClassLoader loader2 = Xxx.class.getClassLoader();
2、Class对象。
获得Class对象有3种方式:
a)、Class类的forName方法,传入全限定类名。需要抛出异常ClassNotFoundException
b)、调用该类的class属性。
c)、调用某对象的getClass()方法。
3、通过Class对象创建对象:
例如有一个Apple类。Class clazz = Class.forName(“com.stopTalking.crazy.Apple”);
该Apple类有一个默认构造器、一个String类型参数的构造器、一个String类型、int类型的构造器。
获得Apple对象有2种方式:
a)、用Apple类默认构造器:Object o1 = clazz.newInstance();
b)、用一个String类型参数的构造器:Object 02 = clazz.getConstructor(String.class).newInstance(“apple”);
c)、用一个String类型、int类型的构造器:Object 02 = clazz.getConstructor(String.class,int.class).newInstance(“apple”,”3”);
4、调用方法:
Method m = clazz.getMethod(方法名,参数类型);//根据方法名和参数类型创建Method对象。
m.invokej(对象,属性值);//根据对象和方法参数调用方法。
若需调用private方法,先调用Method对象的setAccessible(true);
5、访问属性:
Field f = clazz.getDeclaredField(属性名);//根据属性名获取Field对象
f.get(对象);//根据对象得到属性值。
6、操作数组:
Object arr = Array.newInstance(String.class,10);//创建一个简单的String数组。
Array.set(arr,5,”abc”);//给该数组下标为5的元素赋值
Object name = Array.get(arr,5);//获取该元素
Java类加载和类反射回顾的更多相关文章
- Java中的类反射
一.反射的概念 : 反射的概念是由Smith在1982年首次提出的,主要是指程序可以访问.检测和修改它本身状态或行为的一种能力.这一概念的提出很快引发了计算机科学领域关于应用反射性的研究.它首先被程序 ...
- 【转】两道面试题,带你解析Java类加载机制(类初始化方法 和 对象初始化方法)
本文转自 https://www.cnblogs.com/chanshuyi/p/the_java_class_load_mechamism.html 关键语句 我们只知道有一个构造方法,但实际上Ja ...
- java -类加载器与反射
类加载器 类的加载 当程序要使用某个类时,如果该类还未被加载到内存中,则系统会通过加载,连接,初始化三步来实现对这个类进行初始化. l 加载 就是指将class文件读入内存,并为之创建一个Class ...
- java类加载及类初始化
1.前言 java是跨平台语言,主要是因为它的java虚拟机的存在,java有事编译语言,所以需要将编写的java文件编译成jvm可运用的class字节码文件.在java中一切皆对象.对于Java虚拟 ...
- java 类加载机制和反射机制
一.类的加载机制 jvm把class文件加载到内存,并对数据进行校验.解析和初始化,最终形成jvm可以直接使用的java类型的过程.(1)加载 将class文件字节码内容加载到内存中, ...
- Java 类反射机制分析
Java 类反射机制分析 一.反射的概念及在Java中的类反射 反射主要是指程序可以访问.检测和修改它本身状态或行为的一种能力.在计算机科学领域,反射是一类应用,它们能够自描述和自控制.这类应用通过某 ...
- 一文读懂Java类加载机制
Java 类加载机制 Java 类加载机制详解. @pdai Java 类加载机制 类的生命周期 类的加载:查找并加载类的二进制数据 连接 验证:确保被加载的类的正确性 准备:为类的静态变量分配内存, ...
- java学习:用反射构造bean
先贴一些反射的基本知识:-------------------------------------------------------------------- 一.什么是反射:反射的概念是由Smit ...
- ClassLoader类加载器 & Java类加载机制 & 破坏双亲委托机制
ClassLoader类加载器 Java 中的类加载器大致可以分成两类: 一类是系统提供的: 引导类加载器(Bootstrap classloader):它用来加载 Java 的核心库(如rt.jar ...
随机推荐
- 什么是XMLA-- XML for Analysis
在我刚开始接触OLAP时,同事就告诉我 XMLA会让他使用更方便. 什么是XMLA? Providers 供应商 ActivePivot Hyperion Essbase IBM Infosphere ...
- CYQ.Data 数据框架 使用篇一 入门指南
快速使用帮助 | 回贴(13) | 浏览(11303) | 发表日期 :2010-12-20 20:12:29 #楼主 本文针对V5版本进行修改于(2016-07-04) 下面是使用步骤: 一 ...
- 写在复习MVC后
MVC的一些 今天把MVC复习了下,包括官方文档以及各种中文博客. 官方文档里面最能说明的问题的图片,相对于传统的MVC,苹果分离了View和Model之间的通信,实现了更好的复用性.我觉得MVC更 ...
- 在MVC中处理异常的总结
无论是桌面程序还是web程序,异常处理都是必须的. 一般的处理方式是, 捕获异常,然后记录异常的详细信息到文本文件或者数据库中.在Asp.net MVC中可以使用内建的filter——HandleEr ...
- ORACLE SQL Developer日期显示格式设置
ORACLE的SQL Developer工具默认的日期格式DD-MON-RR,在SQL查询中往往你看不到时间信息,此时你必须修改日期格式.具体如下所示 工具->首选项->数据库->N ...
- CentOS 6.5 生产环境编译安装LNMP
一.环境准备 1.操作系统安装:CentOS 6.5 64位最小化安装. 2.配置好IP.DNS.网关.主机名 3.配置防火墙,开启80.3306端口 vim /etc/sysconfig/iptab ...
- mac 安装 php nginx mysql
mac下面安装php nginx mysql根linux下面差不多,建议大家使用brew管理工具包安装. 1,安装homebrew http://brew.sh/index_zh-cn.html 安装 ...
- Windows自动关机命令
winxp中自带了自动关机功能,在开始→运行中使用SHUTDOWN命令 1. 延迟关机关机 shutdown -s -t 120 -s为关机:-t为时间,以秒为单位,120表示2分钟 表示两分钟后关机 ...
- 实现如下类之间的继承关系,并编写Music类来测试这些类。
实现如下类之间的继承关系,并编写Music类来测试这些类. package com.hanqi.test; public class Instrument { //输出弹奏乐器 public void ...
- 在eclipse中使用maven创建springMVC项目
一.在eclipse中创建maven-archetype-webapp项目: 1.新建项目选择maven项目 2.默认,下一步 3.选择maven-archetype-webapp,其他保持默认即可 ...