Java的动态加载及其安全性问题
1.什么是动态加载
Class Loaders是动态加载Java类与Resource的一种机制。它支持Laziness,type-safe linkage,user-defined extensibility和multiple communicating namespaces这4种特性。
Lazy loading:Class只有在需要的时候才加载。这样减少了内存使用量,能提高系统反映速度;
Type-safe linkage:动态类加载不会破坏JVM的类型安全;
User-definable class loading policy:开发者可以自定义的类加载器,控制动态类加载过程;
Multiple namespaces:JVM允许使用不同的类加载器加载相同的Class名称,但不同内容的类。
Class Loaders早在JDK1.0时就已存在,最开始的目的是使HotJava浏览器能加载Applet。从那以后,动态类加载机制被广泛应用到其他方面,例如web application server中Servlets的加载。class loader在JDK 1.0,1.1版本存在的缺陷,已经在JDK 1.2解决,其缺陷主要是编写不正确的Class Loader会造成类型安全问题。
2.Class Loader的工作原理
Class Loader的目的是动态加载Java类和Resource。Java类是平台无关的,标准的,具有规范二进制文件格式的。class文件有编译器生成,可以被任何一中JVM加载。Java类的表现形式不仅只有.class文件,还可以为内存buffer,或是网络数据流。
JVM执行class文件内的Byte code。但是Byte code不是class文件的全部内容,class文件内还包含符号表,表示类,属性和方法名,以及类内引用到其他类,属性,和方法名。例如下面的类
class C{
void f(){
D d=new D();
}
}
类文件内类C引用D。为了能让JVM知道D类是什么,JVM必须要先load D的class file并创建D class对象。
JVM使用类加载器加载类文件,并创建Class对象。类加载器都是ClassLoader的子类实例。ClassLoader.loadClass方法通过获得一个类名,返回一个Class对象,表示该类的类型。上面的代码里,假设C被类加载器L加载,则L是C的加载器。JVM将使用L加载所有被C引用到的其他Java类。
如果D还没有被加载,L将加载D:
L.loadClass(“D”)
当D已经被加载,JVM就可以创建D的一个对象实例。
一个Java应用程序可以使用不同类型的类加载器。例如Web Application Server中,Servlet的加载使用开发商自定义的类加载器, java.lang.String在使用JVM系统加载器,Bootstrap Class Loader,开发商定义的其他类则由AppClassLoader加载。在JVM里由类名和类加载器区别不同的Java类型。因此,JVM允许我们使用不同的加载器加载相同namespace的java类,而实际上这些相同namespace的java类可以是完全不同的类。这种机制可以保证JDK自带的java.lang.String是唯一的。
每个ClassLoader加载Class的过程是:
1.检测此Class是否载入过(即在cache中是否有此Class),如果有到8,如果没有到2
2.如果parent classloader不存在(没有parent,那parent一定是bootstrap classloader了),到4
3.请求parent classloader载入,如果成功到8,不成功到5
4.请求jvm从bootstrap classloader中载入,如果成功到8
5.寻找Class文件(从与此classloader相关的类路径中寻找)。如果找不到则到7.
6.从文件中载入Class,到8.
7.抛出ClassNotFoundException.
8.返回Class.
3.JVM原生类加载器原理
当JVM(Java虚拟机)启动时,会形成由三个类加载器组成的初始类加载器层次结构:
bootstrap classloader-> extension classloader-> system classloader
bootstrap classloader - 引导(也称为原始)类加载器,它负责加载Java的核心类。在Sun的JVM中,在执行java的命令中使用-Xbootclasspath选项或使用-D选项指定sun.boot.class.path系统属性值可以指定附加的类。这个加载器的是非常特殊的,它实际上不是java.lang.ClassLoader的子类,而是由JVM自身实现的。大家可以通过执行以下代码来获得bootstrap classloader加载了那些核心类库:
URL[] urls=sun.misc.Launcher.getBootstrapClassPath().getURLs();
for (int i = 0; i < urls.length; i++) {
System.out.println(urls.toExternalForm());
}
extension classloader - 扩展类加载器,它负责加载JRE的扩展目录(JAVA_HOME/jre/lib/ext或者由java.ext.dirs系统属性指定的)中JAR的类包。这为引入除Java核心类以外的新功能提供了一个标准机制。因为默认的扩展目录对所有从同一个JRE中启动的JVM都是通用的,所以放入这个目录的JAR类包对所有的JVM和system classloader都是可见的。
在这个实例上调用方法getParent()总是返回空值null,因为引导加载器bootstrap classloader不是一个真正的ClassLoader实例。所以当大家执行以下代码时:
System.out.println(System.getProperty("java.ext.dirs"));
ClassLoader extensionClassloader=ClassLoader.getSystemClassLoader().getParent();
System.out.println("the parent of extension classloader : "+extensionClassloader.getParent());
extension classloader是system classloader的parent,而bootstrap classloader是extension classloader的parent,但它不是一个实际的classloader,所以为null。
system classloader - 系统(也称为应用)类加载器,它负责在JVM被启动时,加载来自在命令java中的-classpath或者java.class.path系统属性或者CLASSPATH操作系统属性所指定的JAR类包和类路径。总能通过静态方法ClassLoader.getSystemClassLoader()找到该类加载器。如果没有特别指定,则用户自定义的任何类加载器都将该类加载器作为它的父加载器。执行以下代码即可获得:
System.out.println(System.getProperty("java.class.path"));
输出结果则为用户在系统属性里面设置的CLASSPATH。
4.安全性问题
例如所加载jar文件,与父class loader存在同namespace 的class,但是java version不一致,这时候,就容易导致类安全性问题.
可以通过class loader的加载顺序,进行jar加载,改变”父优先”的法则
public ClassLoader getDSClassLoader(String moudleName) {
if (DSClassLoader == null) {
try {
DSClassLoader = new MCFClassLoader(
new URL[] {
new URL("......xxx.jar"),
new URL("......yyy.jar")},
ConnectorConfigurationParserServiceImpl.class
.getClassLoader());
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return DSClassLoader;
}
public ClassLoader getDSClassLoader(String moudleName) {
if (DSClassLoader == null) {
try {
DSClassLoader = new MCFClassLoader(
new URL[] {
new URL("......xxx.jar"),
new URL("......yyy.jar")},
ConnectorConfigurationParserServiceImpl.class
.getClassLoader());
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return DSClassLoader;
}
Java的动态加载及其安全性问题的更多相关文章
- 透过现象看本质:Java类动态加载和热替换
摘要:本文主要介绍类加载器.自定义类加载器及类的加载和卸载等内容,并举例介绍了Java类的热替换. 最近,遇到了两个和Java类的加载和卸载相关的问题: 1) 是一道关于Java的判断题:一个类被首次 ...
- [改善Java代码]动态加载不适合数组
上一个建议解释了为什么要使用forName,本建议就说说哪些地方不适合使用动态加载. 如果forName要加载一个类,那它必须是一个类------8中基本类型就排除在外.它们不是一个具体的类. 其次它 ...
- [转载] Java中动态加载jar文件和class文件
转载自http://blog.csdn.net/mousebaby808/article/details/31788325 概述 诸如tomcat这样的服务器,在启动的时候会加载应用程序中lib目录下 ...
- java反射动态加载类Class.forName();
1,所有的new出来的对象都是静态加载的,在程序编译的时候就会进行加载.而使用反射机制Class.forName是动态加载的,在运行时刻进行加载. 例子:直接上两个例子 public class Ca ...
- java反射--动态加载
Class.forName("类的全称") 1)不仅表示类的类类型,还表示了动态加载类 2)请区分编译,运行 3)编译时刻加载类是静态加载类,运行时刻加载类是动态加载类 比如下面: ...
- Java实现动态加载读取properties文件
问题: 当我们使用如下语句加载.properties时: ClassLoader classLoader = this.getClass().getClassLoader(); Properties ...
- Java反射、动态加载(将java类名、方法、方法参数当做参数传递,执行方法)
需求:将java类名.方法.方法参数当做参数传递,执行方法.可以用java的动态加载实现 反射的过程如下: 第一步:通过反射找到类并创建实例(classname为要实例化的类名,由pack ...
- java中的动态加载和热替换
https://blog.csdn.net/u010833547/article/details/54312052 ****************************************** ...
- java动态加载机制
假设有一个class,ClassLoader首先把它load到内存里的code segment(内存里存放代码段的),站在ClassLoader的角度,内存里的一个一个的class就是一个一个的对象, ...
随机推荐
- 怎么查看window7的.net framework的版本
第一步.打开控制面板,在大图标查看方式下,点击“程序和功能” 第二步.在程序和功能界面,点击左侧“打开或关闭Windows功能” 第三步.在打开或关闭Windows功能界面,通过拖动滚动条的方式,找到 ...
- Mozilla Firefox的各级版本链接
Mozilla Firefox的各级版本链接 及语言 https://ftp.mozilla.org/pub/firefox/releases/
- CVE-2014-1767 漏洞分析(2015.1)
CVE-2014-1767 漏洞分析 1. 简介 该漏洞是由于Windows的afd.sys驱动在对系统内存的管理操作中,存在着悬垂指针的问题.在特定情况下攻击者可以通过该悬垂指针造成内存的doubl ...
- app.use(express.static)设置静态文件目录小解
app.use(path, function, [, function]) 功能: 为path注册中间函数,即根据path使用不同函数进行处理,默认path是"/",也就是处理任何 ...
- json处理三部曲之第三曲:利用Gson处理json
需要导入gson-xxx.jar包 <dependency> <groupId>com.google.code.gson</groupId> <artifac ...
- CentOS的KVM实践(虚拟机创建、网桥配置、Spice)
最近公司准备上一套基于openstack的虚拟桌面系统,作为该项目的负责人,觉得有必要自己实践一下,该系统的搭建.最基础的就是需要了解基于linux的kvm的实践. 一.基础软件包准备 系统是采用px ...
- 转:JDBC驱动配置相关
1.做JDBC请求 ,首先要了解这个JDBC对象是什么,现在以SQLServer为例来说明 首先下载对应的数据库驱动(百度“jdbc sqlserver驱动”,然后下载). 注意 :下载完成后,直接把 ...
- ASCII码对应表chr(9)、chr(10)、chr(13)、chr(32)、chr(34)、chr(39)
chr(9) tab空格 chr(10) 换行 chr(13) 回车 Chr(13)&chr(10) 回车换行 chr(32) 空格符 ...
- <marquee>,视频和音频的插入,正则表达式
1.marquee 页面的自动滚动效果,不仅可以移动文字,也可以移动图片表格. <marquee></marquee>之间加内容即可. marquee的属性 1.滚动方向dir ...
- 初识beego
beego是一个基于golang的web框架,这里记录些使用中碰到的东西. 输出: this.Ctx.Output.Write([]byte("test")) //这里是作为res ...