首先介绍自定义类的应用场景:
(1)加密:Java代码可以轻易的被反编译,如果你需要把自己的代码进行加密以防止反编译,可以先将编译后的代码用某种加密算法加密,类加密后就不能再用Java的ClassLoader去加载类了,这时就需要自定义ClassLoader在加载类的时候先解密类,然后再加载。
(2)从非标准的来源加载代码:如果你的字节码是放在数据库、甚至是在云端,就可以自定义类加载器,从指定的来源加载类。
(3)以上两种情况在实际中的综合运用:比如你的应用需要通过网络来传输 Java 类的字节码,为了安全性,这些字节码经过了加密处理。这个时候你就需要自定义类加载器来从某个网络地址上读取加密后的字节代码,接着进行解密和验证,最后定义出在Java虚拟机中运行的类。
|
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
|
package
com.test6;
public
class
DataInfo {
private
Long id;
private
String userName;
public
Long getId() {
return
id;
}
public
void
setId(Long id) {
this
.id = id;
}
public
String getUserName() {
return
userName;
}
public
void
setUserName(String userName) {
this
.userName = userName;
}
@Override
public
String toString() {
return
"DataInfo [id="
+
1
+
", userName="
+
"测试"
+
"]"
;
}
}
|
|
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
83
84
85
86
|
package
com.test6;
import
java.io.ByteArrayOutputStream;
import
java.io.File;
import
java.io.FileInputStream;
import
java.nio.ByteBuffer;
import
java.nio.channels.Channels;
import
java.nio.channels.FileChannel;
import
java.nio.channels.WritableByteChannel;
/**
* 自定义加载器
*
* @author sdc
*
*/
public
class
MySelfClassLoader
extends
ClassLoader {
public
MySelfClassLoader() {
}
public
MySelfClassLoader(ClassLoader parent) {
super
(parent);
}
@Override
protected
Class<?> findClass(String name)
throws
ClassNotFoundException {
File file =
new
File(
"D:/DataInfo.class"
);
try
{
byte
[] bytes = getClassBytes(file);
// defineClass方法可以把二进制流字节组成的文件转换为一个java.lang.Class
Class<?> cla =
this
.defineClass(name, bytes,
0
, bytes.length);
return
cla;
}
catch
(Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return
super
.findClass(name);
}
private
byte
[] getClassBytes(File file)
throws
Exception {
// 这里要读入.class的字节,因此要使用字节流
FileInputStream fis =
new
FileInputStream(file);
FileChannel fc = fis.getChannel();
ByteArrayOutputStream baos =
new
ByteArrayOutputStream();
WritableByteChannel wbc = Channels.newChannel(baos);
ByteBuffer by = ByteBuffer.allocate(
1024
);
while
(
true
) {
int
i = fc.read(by);
if
(i ==
0
|| i == -
1
)
break
;
by.flip();
wbc.write(by);
by.clear();
}
fis.close();
return
baos.toByteArray();
}
public
static
void
main(String[] args) {
MySelfClassLoader mcl =
new
MySelfClassLoader();
Class<?> clazz;
try
{
clazz = Class.forName(
"DataInfo"
,
true
, mcl);
Object obj = clazz.newInstance();
System.out.println(obj);
System.out.println(obj.getClass().getClassLoader());
// 打印出我们的自定义类加载器
}
catch
(ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
catch
(InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
catch
(IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
|
版权声明:原创作品,如需转载,请注明出处。否则将追究法律责任
本文转自 豆芽菜橙 51CTO博客,原文链接:http://blog.51cto.com/shangdc/1923781