JAVA中的ClassLoader

反射是JAVA中的一个重要特性,使得JAVA 可以在运行时加载、探知、使用编译期间完全未知的classes。JAVA通过反射,可以在运行时获取一个未知的Class,并获取该Class种的方法、变量,甚至改变这些方法的访问权限,这些功能使得JAVA表现的像一个动态语言。

初窥ClassLoader

反射机制中一份非常重要的角色是ClassLoader,从名字可以知道,ClassLoader的作用时加载Class,下面是一个简单的例子,使用ClassLoader加载一个类,并创建一个实例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
public class ClassReflection {
private int className;
private String description;

public ClassReflection() {
}

public int getClassName() {
return className;
}

public void setClassName(int className) {
this.className = className;
}

public String getDescription() {
return description;
}

public void setDescription(String description) {
this.description = description;
}

private String saySomething() {
return "I am a private method!";
}

public String sayHello() {
return "Hello World.";
}

public static void main(String[] args) throws Exception {
//Class clazz = Class.forName("com.yflog.reflection.ClassReflection");
Class clazz = ClassReflection.class.getClassLoader().loadClass("com.yflog.reflection.ClassReflection");
Object instance = clazz.newInstance(); // create a new instance
Method sayHello = clazz.getMethod("sayHello"); // 获取public方法使用getMethod
Object hello = sayHello.invoke(instance);
System.out.println("Invoke Say Hello: " + hello);

Method saySomething = clazz.getDeclaredMethod("saySomething");//使用getDeclaredMethod获取private方法
saySomething.setAccessible(true); //设置可访问
Object something = saySomething.invoke(instance);
System.out.println("Invoke Say Something: " + something);
}

}

程序输出结果如下:

1
2
Invoke Say Hello: Hello World.
Invoke Say Something: I am a private method!

在上面的程序中,使用ClassLoader加载了ClassRefelection类,并调用newInstance方法创建了一个对象,并分别使用getMethod和getDeclaredMethod获取public和private的方法,再通过invoke完成对方法的调用。对于private方法,在invoke之前需要设置起Accessible为true。

Java中的ClassLoader

JVM中自带了三个层次的ClassLoader: bootstrap classloader, extension classloader, system classloader。

Bootstrap classloader:

该加载起作用于JVM启动时,负责将JAVAde核心类加载到内存中,比如java.lang.Object以及其他的运行时代码。由于该classloader是用java native code实现的,我们在JAVA代码中不能找到关于bootstrap classloader的具体实现,因此,在不同的JVM之间,bootstrap classloader的实现有所不同。

Extension ClassLoader

Extension ClassLoader用语搜索特定的标准扩展目录。不同的JVM之间实现同样可能存在差异,对于常用的SUN公司的JVM,他是%JRE_HOME%/lib/ext,具体的路径通过java.ext.dirs系统属性获取。使用标准扩展目录的目的是便于扩展和共享,应用程序厂商可以将部分共享库放到这里,而不需要再各自的程序的目录下多次拷贝。再开发的过程中,我们可以将部分常用的库放置于此,而不用每次都去配置环境。

System ClassLoader

System ClasLoader用语搜索CLASSPATH中配置的目录和jar文件。

三种ClassLoader的加载顺序。

上述的三种ClassLoader,用从左到右的结构来描述,Bootstrap CL <- Extension CL <- System CL, <-左边的ClassLoader是右边的ClassLoader的Parent。在加载一个Class时,首先使用Syste ClassLoader来加载;但是System ClassLoader并不会立即进行加载操作,而是首先将加载操作交给其parent classloader(Extentsion ClassLoader),只有当起Parent ClassLoader不能加载该类时,SystemClasLoader才会去搜索CLASSPATH中制定的路径和jar;Extention ClassLoader加载类的操作和System ClassLoader一样,都会首先将加载操作交给Parent ClassLoader。

kafka, storm集成DEMO Git修改已经提交的Comment

评论

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×