Java Class Loader
Reference:
[1] http://www.cnblogs.com/kevin2chen/p/6714214.html
当调用 java命令运行一个java程序时,会启动一个java虚拟机进程。同一个jvm的所有线程、所有变量都处于同一个进程里,都使用该jvm进程的内存区。 jvm进程终止,jvm内存中的数据将全部丢失。
jvm进程终止的情况:
1.程序运行到最后正常结束。
2.遇到System.exit()或Runtime.getRuntime.exit()。
3.遇到未捕获的异常或错误
4.程序所在的平台强制结束了JVM进程
类的加载
当程序主动使用某个类时,如果该类还未被加载到内存中,系统会进行类加载。类加载指的是将类的class文件读入内存,并为之创建一个java.lang.Class的实例。因为java中万物皆为对象,类也是java.lang.Class类型的对象。
类加载具体有加载、连接和初始化3个步骤,加载阶段需要完成的事情有:
1)通过一个类的全限定名来获取定义此类的二进制字节流。
2)将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构。
3)在java堆中生成一个代表这个类的Class对象,作为访问方法区中这些数据的入口。
类的加载,是由类加载器来完成的,类加载器通常由JVM提供。通过使用不同的类加载器,可以加载以下不同来源的类的二进制数据:
1.从本地文件系统加载class文件
2.从jar包中直接加载class文件
3.通过网络加载class文件
4.把一个java源文件动态编译并加载
类的连接
负责把类的二进制数据合并到JRE(java运行环境)中
1.验证:检测被加载的类是否有正确的内部结构,是否被破坏或包含不良代码,并和其他类协调一致
2.准备:负责为类的静态属性分配内存,并设置默认初始值
3.解析:将类的二进制数据中的符号引用替换成直接引用
类初始化
主要对类的静态属性进行初始化。可以在声明静态属性时指定初始值和通过静态初始化块指定初始值,JVM会按照这些语句在程序中的顺序依次执行。
类加载器
每个类加载器(除了根类加载器)都是java.lang.ClassLoader的实例,负责将.class文件加载到内存中,并为之生成对应的java.lang.Class对象。
同一个.class不会被同一个类加载器加载两次,如何判断是同一个类: java中,一个类用其全限定类名标识--包名+类名;jvm中,一个类用其全限定类名+其类加载器标识---包名+类名+类加载器名
加载器层次结构:
JVM启动时,会形成由三个类加载器组成的初始类加载器层次结构:
1.Bootstrap ClassLoader 根类加载器(引导类加载器),加载java的核心类(限定的加载路径:jdk1.8_02/jre/lib/rt.jar)。它不是java.lang.ClassLoader的子类,而是由JVM自身实现的。虚拟机为了安全性以及功能的完整性,并不是任何存在于启动类加载器路径下的jar都会被加载,只有可信类(trusted classes )会被加载,所以开发者不要将自定义的类放在此目录。
2.Extension ClassLoader 扩展类加载器,加载JRE的扩展目录中JAR的类包(限定的加载路径:%JAVA_HOME%/jre/lib/ext/或java.ext.dirs系统属性指定的目录)
3.System ClassLoader 系统类加载器,加载java.class.path系统属性或CLASSPATH环境变量所指定的jar包和类路径,可通过ClassLoader的静态方法ClassLoader.getSystemClassLoader()获取系统类加载器。如果没有特别指定,用户自定义的类加载器以该类加载器作为它的父加载器。也可以通过Class实例的getClassLoader()方法当前类的类加载器。
4.自定义类加载器
JVM系统自带的类加载器在程序运行中只能加载对应路径的.class文件,无法改变其搜索路径。如果想在运行时从其他路径加载类,就要编写自定义的类加载器。
类加载的机制
1.全盘负责:某类所依赖及其引用的所有类,都由同一个加载器负责加载,除非显示使用另外一个加载器。
2.双亲委托: 当一个类加载器收到类加载的请求,首先将请求委派给父类加载器,递归到Bootstrap ClassLoader。然后加载器根据请求尝试搜索和加载类,若无法加载该类时则向子类加载器反馈信息(抛出ClassNotFoundException),由子类加载器自己去加载。
类加载期之间的父子关系并不是类继承上的父子关系,是采用组合的方式实现双亲委派模型的。
根类加载器是由c++实现的,不是由java语言实现,没有继承ClassLoader,所以扩展类加载器调用parent()返回的是null。但扩展类加载器实际上仍可以委派给根类加载器。
使用双亲委托模式的原因:被父类加载器加了的类可以避免避免被子类重新加载,因为在JVM中由全限定名+类加载器名标识类。另外可以避免加载到同sun公司核心API同名的恶意类。
自定义类加载器
JVM中除了根加载器之外,所有类加载器都是ClassLoader子类的实例,开发者通过扩展ClassLoader并重写ClassLoader所包含的方法来实现自定义的类加载器。
如上源码所示,loadClass()方法内部主要是双亲委派模型的实现,在最后调用findClass()方法加载类,所以自定义类加载器重写findClass()比重写loadClass()方便,可以避免覆盖默认类加载器的父类委托和缓冲机制两种策略。
ClassLoader类的核心方法:
protected synchronized Class<?> loadClass(String name, boolean resolve)根据指定的binary name(由两个不同部分组成的名字,即全限定类名)来加载类,返回Class对象。
protected Class<?> findClass(String name)根据二进制名称来查找类,返回Class对象。此方法应该被自定义类加载器的实现重写,在通过父类加载器检查所请求的类后,被loadClass方法调用。
final defineClass(String name,byte[] b,int off,int len)将指定类的字节码文件读入字节数组内,并把它转为Class实例,该字节码文件可以来源于网络或本地。
findLoadedClass(String name)返回jvm装载的name类的Class实例,若无返回null。
static getSystemClassLoader()返回系统类加载器。
findSystemClass(String name)从本地文件系统加载class文件,并生成Class对象。
使用自定义类加载器可以实现如下功能:
执行代码前自动验证数字签名;
根据用户提供的密码解密代码,从而可以实现代码混淆器来避免反编译class文件;
根据用户需求来动态的加载类;
根据应用需求把其他数据以字节码的形式加载到应用中;
URLClassLoader 类
java 为ClassLoader提供了一个实现类URLClassLoader ,该类也是系统类加载器和扩展类加载器的父类,它可以从本地文件系统和远程主机获取二进制文件来加载类。
URLClassLoader的两个构造器
URLClassLoader(URL[] urls):使用默认的父类加载器创建一个ClassLoader对象,该对象将从urls所指定的系列路径来查询并加载类。
URLClassLoader(URL[] urls, ClassLoader parent):使用指定的父类加载器创建。。。
一旦获得URLClassLoader对象后,就可以调用类加载器的 loadClass()方法来加载指定的类。
加载图片、视频、文本等非类资源
ClassLoader除了用于加载类外,还可以用于加载图片、视频等非类资源,也是采用双亲委派模型将加载资源的请求传递到顶层的Bootstrap ClassLoader,在其对应的目录下搜索资源,若失败才逐层返回并搜索。
相关的实例方法:
URL getResource(String name):资源名称name是以 '/' 分隔的标识资源的路径名称,返回资源的 URL 对象的枚举。
InputStream getResourceAsStream(String name):返回读取指定资源的输入流。
Enumeration<URL> getResources(String name)
1)class.getResource(String path):返回URL对象
path以'/'开头时,'/'表示ClassPath,从项目的classpath下查询资源;
path不以'/'开头时,是从此类所在的包下查询资源;
步骤:先递归在所有parent classLoader的classpath里查找resource,如果未找到,则在JVM内置的calss loader的路径中查找。
2)class.getClassLoader().getResource(String name):返回URL对象
The name of a resource is a '/'-separated path name that identifies the resource.
name不能以'/'开头,指资源标识符(即相对于classpath的路径)。一般web项目的classpath路径为……/webapps/appName/WEB-INF/classes/。如果资源不在此目录下,需要用使用相对路径做调整。
String path= MyService.class.getClassLoader().getResource("config.properties").getPath();
Properties prop = new Properties();
prop.load(new FileReader(path));
Java Class Loader的更多相关文章
- Java Class Loader Retrospect
- Java: some learning note for Java calssloader and Servlet
1. Java Classloader 链接: https://en.wikipedia.org/wiki/Java_Classloader 摘要: The Java Classloader is a ...
- java 运行指定类的main函数
运行jar文件的方法是: java -jar xxx.jar 但是有时,我们希望运行里面的具体某个类,这时可以通过: java -cp xxx.jar xxx.com.xxxx 它会找到这个类的ma ...
- Tomcat从零开始(十)Loader
第十课: 不知不觉就10篇blog了,说实话,我是第一次更这么长时间的Blog. 嗯,今天说说Loader,在以前的课程中,也就是内个能使用最初级的servlet的那一节,我们使用了URLClassL ...
- Java 9 揭秘(8. JDK 9重大改变)
Tips 做一个终身学习的人. 在本章,主要介绍以下内容: 新的JDK版本控制方案是什么 如何使用Runtime.Version类解析JDK版本字符串 JDK JRE 9的新目录布局是什么 JDK 9 ...
- 详解Java内存区域?虚拟机类加载机制?
一.Java运行时数据区域 1.程序计数器 “线程私有”的内存,是一个较小的内存空间,它可以看做当前线程所执行的字节码的行号指示器.Java虚拟机规范中唯一一个没有OutOfMemoryError情况 ...
- 探秘 Java 热部署三(Java agent agentmain)
前言 让我们继续探秘 Java 热部署.在前文 探秘 Java 热部署二(Java agent premain)中,我们介绍了 Java agent premain.通过在main方法之前通过类似 A ...
- 探秘 Java 热部署
# 前言 在之前的 深入浅出 JVM ClassLoader 一文中,我们说可以通过修改默认的类加载器实现热部署,但在 Java 开发领域,热部署一直是一个难以解决的问题,目前的 Java 虚拟机只能 ...
- 探秘 Java 热部署二(Java agent premain)
# 前言 在前文 探秘 Java 热部署 中,我们通过在死循环中重复加载 ClassLoader 和 Class 文件实现了热部署的功能,但我们也指出了缺点-----不够灵活.需要手动修改文件等操作. ...
随机推荐
- 一步操作配置Word环境
我们在开始编辑Word文档的时候,会发现有些事情我们总需要预先操作一下,比如100%普通视图.显示隐藏特殊标记.显示标尺.最大化窗口.显示导航窗格啥的,每次去操作,感觉很烦,那么通过下面这个宏代码可以 ...
- php Redis常用命令
redis是一个很好的缓存工具,下面我们就来介绍一下他怎么使用 启动 Redis 服务src/redis-server或者src/redis-server redis.conf src/Redis-s ...
- Learning to Rank简介
Learning to Rank是采用机器学习算法,通过训练模型来解决排序问题,在Information Retrieval,Natural Language Processing,Data Mini ...
- SEO -- WordPress怎设置百度站长链接自动提交
百度站长平站更新了主动推送(实时)推送的方式,受到了广大站长的好评,但是对于使用WordPress的网站来说怎么设置自动提交呢,在这里介绍一种比较简单且有效的方法.我们可以使用 WP BaiDu Su ...
- 易汇金在线支付接口实例。ecshop和shopex,shopnc,iwebshop下完美无错(最新)
最近为客户的一个在线商城做了一个易汇金在线支付的接口.跟大家分享一下. 1 首先可以模仿其他的接口,比如支付宝,财付通等的接口,构建模块功能文件和语言文件. 功能模块构建: /includes/mod ...
- Jquery对复选框CheckBox的操作
checkbox: 多选框 //获取选中值 checkbox:$("#checkbox_id").attr("value"): 多选框checkbox,打勾: ...
- 【C和指针】笔记1
数据 基本数据类型 整型家族:包含字符,短整型,整型和长整型 整型相互之间大小规定如下: 长整型至少和整型一样长,而整型至少应该和短整型一样长. short int至少16位,long int至少32 ...
- MTK elian(smartlink)在WIN32下的实现
先说明一下调试技巧:该程序需无线网卡实现功能,由于PC端有可能是多网卡的(有线网卡.无线网卡.虚拟网卡),所以在发包的时候数据包不一定会从无线网卡出,lib库应该也没处理多网卡的选择吧.所以在调试的时 ...
- AngularJs 4大核心
放弃了IE8, 4大核心: MVC: 数据模型,视图层,业务逻辑和控制模式(控制器), 为何MVC不是设计模式呢?(23种设计模式里没有MVC,MVC模式的目的就是实现Web系统的职能分工,超越了设计 ...
- 使用Block传值
使用Block的地方很多,其中传值只是其中的一小部分,下面介绍Block在两个界面之间的传值: 先说一下思想: 首先,创建两个视图控制器,在第一个视图控制器中创建一个UILabel和一个UIButto ...