Fork me on GitHub

Java类加载器

自定义ClaaLoader加载类文件

类加载器是JVM执行类加载机制的前提,其主要任务为根据一个类的全限定名来读取此类的二进制字节流到JVM内部,然后转换为一个与目标类对应的java.lang.Class对象实例

  1. defineClass();

  defineClass方法 的主要作用是将byte 字节流解析成JVM能够识别的class对象,这个方法意味着 我们不仅仅可以通过class文件去实例化对象,还可以其他方式实例化对象,例如我们通过网络接收到一个类的字节码;defineClass的代码如下:
  
  

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
protected final Class<?> defineClass(String name, byte[] b, int off, int len,
ProtectionDomain protectionDomain)
throws ClassFormatError
{
protectionDomain = preDefineClass(name, protectionDomain);
String source = defineClassSourceLocation(protectionDomain);
Class<?> c = defineClass1(name, b, off, len, protectionDomain, source);
postDefineClass(c, protectionDomain);
return c;
}


protected final Class<?> defineClass(String name, java.nio.ByteBuffer b,
ProtectionDomain protectionDomain)
throws ClassFormatError
{
int len = b.remaining();

// Use byte[] if not a direct ByteBufer:
if (!b.isDirect()) {
if (b.hasArray()) {
return defineClass(name, b.array(),
b.position() + b.arrayOffset(), len,
protectionDomain);
} else {
// no array, or read-only array
byte[] tb = new byte[len];
b.get(tb); // get bytes out of byte buffer.
return defineClass(name, tb, 0, len, protectionDomain);
}
}

protectionDomain = preDefineClass(name, protectionDomain);
String source = defineClassSourceLocation(protectionDomain);
Class<?> c = defineClass2(name, b, b.position(), len, protectionDomain, source);
postDefineClass(c, protectionDomain);
return c;
}

  1. findClass();
      实现类的加载规则,取得要加载类的字节码,通常是和defineClass()一起使用的;查找类,返回java.lang.Class类的实例

  2. loadClass();
      加载类,返回java.lang.Class类的实例

  3. resolveClass();
      连接指定的一个类,如果你想在类被加载到JVM中的时候就被链接(Link),则调用resolveClass()方法;

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
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
package com.test;

import java.io.*;
import java.lang.reflect.Method;

/**
* \* Created with IntelliJ IDEA.
* \* @author:
* \* @date: 2017/12/14
* \* @time: 10:53
* \* Description:
* \
*/
public class MyClassLoader extends ClassLoader {
//类文件在电脑中的路径
private String classPath;

public String getClassPath() {
return classPath;
}

public void setClassPath(String classPath) {
this.classPath = classPath;
}

@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
byte[] bytes =null;

try {
bytes =LoadClassData(name);

} catch (IOException e) {
e.printStackTrace();
}
return super.defineClass(name,bytes,0,bytes.length);
}


//加载类文件二进制流
public byte[] LoadClassData(String name) throws IOException {
File file =getFile(name);
byte[] by =new byte[(int)file.length()];
FileInputStream inputStream =new FileInputStream(file);
inputStream.read(by);
return by;
}

//获取类文件
public File getFile(String name) throws FileNotFoundException {
File dir = new File(classPath);
if(!dir.exists()) throw new FileNotFoundException(classPath+"目录不存在!");
String _classPath = classPath.replaceAll("[//]","/");
int offset = _classPath.lastIndexOf("/");
name = name.replaceAll("[.]","/");
if(offset != -1 && offset < _classPath.length()-1){
_classPath +="/";
}
_classPath += name +".class";
dir = new File(_classPath);
if(!dir.exists()) throw new FileNotFoundException(dir+"不存在!");
return dir;
}
public static void main(String[] args) {
MyClassLoader classLoader =new MyClassLoader();
String classpath="C:\\Users\\Administrator\\Desktop\\ClassLoaderTest\\build\\classes";
classLoader.setClassPath(classpath);
try {
Class c =classLoader.loadClass("com.assist.controller.AssessmentAgenciesController");
Object o=c.newInstance();
Method[] methods =c.getMethods();
for(Method m :methods){
System.out.println(m.getName());
}
System.out.println("obj.class="+o.getClass().getName());
System.out.println("obj.class="+c.getClassLoader().toString());
System.out.println("obj.class="+c.getClassLoader().getParent().toString());
} catch (Exception e) {
e.printStackTrace();
}
}
}

执行结果:

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
AssessmentAgencies
toAgenciesDetails
querySettleService
toAssessmentScheme
queryAssessmentScheme
toAssessmentRecord
toAgencies
queryWaitAudit
passScheme
toAddAgencies
addAgencies
editAgencies
editAgencies
deleteDistrict
uploadFile
checkData
toSettleService
settleUpdate
toNewsList
queryNewsList
assessmentRecord
exportAgencies
wait
wait
wait
equals
toString
hashCode
getClass
notify
notifyAll
obj.class=com.assist.controller.AssessmentAgenciesController
obj.class=sun.misc.Launcher$AppClassLoader@18b4aac2
obj.class=sun.misc.Launcher$ExtClassLoader@73c6c3b2
-------------���Ľ�����л�����Ķ�-------------