-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathMemoryLeak.java
129 lines (111 loc) · 4.36 KB
/
MemoryLeak.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
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
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
package com.ezlippi;
import java.io.ByteArrayOutputStream;
import java.io.Closeable;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
public class MemoryLeak {
public static void main(String[] args) {
new Thread(new Runnable() {
@Override
public void run() {
while (true) {
CustomClassLoader classLoader = new CustomClassLoader
("load1", MemoryLeak.class.getClassLoader(), "com.ezlippi.MemoryLeak$Inner", "com.ezlippi.MemoryLeak$Inner$1");
try {
Class<?> innerClass = classLoader.loadClass("com.ezlippi.MemoryLeak$Inner");
innerClass.newInstance();
innerClass = null;
classLoader = null;
Thread.sleep(10);
} catch (ClassNotFoundException | IllegalAccessException | InstantiationException | InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
}
public static class Inner {
private static byte[] MB = new byte[1024 * 1024];
static ThreadLocal<Inner> threadLocal = new ThreadLocal<Inner>() {
@Override
protected Inner initialValue() {
return new Inner();
}
};
static {
threadLocal.get();
}
public Inner() {
}
}
private static class CustomClassLoader extends ClassLoader {
private Set<String> urls;
private String label;
/**
* 自定义类加载器,加载指定包名的类,其他的委托父类加载器加载
* @param name 类加载器名称
* @param parent 父类加载器
* @param url 要加载的包名
*/
public CustomClassLoader(String name, ClassLoader parent, String... url) {
super(parent);
this.label = name;
this.urls = new HashSet<String>(Arrays.asList(url));
}
@Override
public Class<?> findClass(String name) throws ClassNotFoundException {
InputStream inputStream = null;
ByteArrayOutputStream outputStream = null;
if (urls.contains(name)) {
try {
String location = name.replace('.', '/') + ".class";
inputStream = MemoryLeak.class.getClassLoader().getResourceAsStream(location);
byte[] buf = new byte[2000];
outputStream = new ByteArrayOutputStream();
int length;
while ((length = inputStream.read(buf)) != -1) {
outputStream.write(buf, 0, length);
}
// System.out.println(label + ": Loading " + name + " in " +label + " classloader");
byte[] data = outputStream.toByteArray();
return defineClass(name, data, 0, data.length);
} catch (IOException e) {
throw new ClassNotFoundException(name, e);
} finally {
closeStream(inputStream);
closeStream(outputStream);
}
}
throw new ClassNotFoundException(name);
}
public Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
//查看是否已经加载过
if (findLoadedClass(name) != null) {
// System.out.println(label + ": already loaded(" + name + ")");
return findLoadedClass(name);
}
if (urls.contains(name)) {
return findClass(name);
} else {
// System.out.println(label + ": super.loadclass(" + name + ")");
//委托给父类加载器加载
return super.loadClass(name, resolve);
}
}
private void closeStream(Closeable closeable) {
if (closeable != null) {
try {
closeable.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public String toString() {
return label;
}
}
}