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的动态加载及其安全性问题的更多相关文章

  1. 透过现象看本质:Java类动态加载和热替换

    摘要:本文主要介绍类加载器.自定义类加载器及类的加载和卸载等内容,并举例介绍了Java类的热替换. 最近,遇到了两个和Java类的加载和卸载相关的问题: 1) 是一道关于Java的判断题:一个类被首次 ...

  2. [改善Java代码]动态加载不适合数组

    上一个建议解释了为什么要使用forName,本建议就说说哪些地方不适合使用动态加载. 如果forName要加载一个类,那它必须是一个类------8中基本类型就排除在外.它们不是一个具体的类. 其次它 ...

  3. [转载] Java中动态加载jar文件和class文件

    转载自http://blog.csdn.net/mousebaby808/article/details/31788325 概述 诸如tomcat这样的服务器,在启动的时候会加载应用程序中lib目录下 ...

  4. java反射动态加载类Class.forName();

    1,所有的new出来的对象都是静态加载的,在程序编译的时候就会进行加载.而使用反射机制Class.forName是动态加载的,在运行时刻进行加载. 例子:直接上两个例子 public class Ca ...

  5. java反射--动态加载

    Class.forName("类的全称") 1)不仅表示类的类类型,还表示了动态加载类 2)请区分编译,运行 3)编译时刻加载类是静态加载类,运行时刻加载类是动态加载类 比如下面: ...

  6. Java实现动态加载读取properties文件

    问题: 当我们使用如下语句加载.properties时: ClassLoader classLoader = this.getClass().getClassLoader(); Properties ...

  7. Java反射、动态加载(将java类名、方法、方法参数当做参数传递,执行方法)

    需求:将java类名.方法.方法参数当做参数传递,执行方法.可以用java的动态加载实现   反射的过程如下:     第一步:通过反射找到类并创建实例(classname为要实例化的类名,由pack ...

  8. java中的动态加载和热替换

    https://blog.csdn.net/u010833547/article/details/54312052 ****************************************** ...

  9. java动态加载机制

    假设有一个class,ClassLoader首先把它load到内存里的code segment(内存里存放代码段的),站在ClassLoader的角度,内存里的一个一个的class就是一个一个的对象, ...

随机推荐

  1. erlang程序优化点的总结(持续更新)

    转自:http://wqtn22.iteye.com/blog/1820587 转载请注明出处 注意,这里只是给出一个总结,具体性能需要根据实际环境和需要来确定 霸爷指出,新的erlang虚拟机有很多 ...

  2. HTML转PDF

    1)使用工具转换.如:wkhtmltopdf 2)Chrome浏览器打印功能中,有另存为PDF格式文件.(推荐最便捷)

  3. DirectShow音频采集声音不连续问题分析与解决办法经验总结

    最近广州大雨不断,并且多数无前兆,突然就来场大雨,给同学们降降温,说来本也是好事,但有时候下的真不是时候,最近这段时间都是即将下班了,大雨就来了,昨晚快下班前又出现了大雨,北方人总爱忘带雨伞,这不就被 ...

  4. hashMap、hashTable、treeMap的区别

    1.hashTable是线程安全的.hashMap不是线程安全的 hashmap 线程不安全 允许有null的键和值 效率高一点. 方法不是Synchronize的要提供外同步 有containsva ...

  5. 给windows共享 目录付于权限

    1.点右监 共享给 某用户 2.点属性 -> 安全 加入  特定用户 3.域用户的管理 (选择控制面板/用户管理) 第一个用户是本地账户 第2/3个是域用户

  6. DateUtils时间工具类探究

    首先声明一下,这个DateUtils工具类不是自己写的,而是在commons-lang-2.Xjar包或是commons-lang3-3.X.jar包中,具体在哪个jar包中,看程序具体添加了哪个版本 ...

  7. poll机制分析[转]

    所有的系统调用,基于都可以在它的名字前加上"sys_"前缀,这就是它在内核中对应的函数.比如系统调用open.read.write.poll,与之对应的内核函数为:sys_open ...

  8. vmware 安装提示the msi failed

    原因是卸载不干净,使用批处理bat文件卸载,然后重启即可. VMware workstation 10.0序列号:MA491-6NL5Q-AZAM0-ZH0N2-AAJ5A 百度云文件:http:// ...

  9. php项目第三季

    1.百度浏览器路径写相对路径 2.svn--setting中两个勾去掉,第二页一个勾打上.工程上右击update是更新,commit是提交. 3.Deprecated: mysql_connect() ...

  10. cPanel 安装方法

    . 如何安装cPanel/WHM? 答:安装过程较长,建议使用screen或nohupscreen: yum -y install screen perl screen -S cpanel cd /h ...