Skip to content

Instantly share code, notes, and snippets.

@xujiaji
Last active May 16, 2018 02:57
Show Gist options
  • Select an option

  • Save xujiaji/89b9ca0fef178e31d8151bfc018211c1 to your computer and use it in GitHub Desktop.

Select an option

Save xujiaji/89b9ca0fef178e31d8151bfc018211c1 to your computer and use it in GitHub Desktop.
import java.io.*;
public class FileSystemClassLoader extends ClassLoader {
private String rootDir;
public FileSystemClassLoader(String rootDir) {
this.rootDir = rootDir;
}
protected Class<?> findClass(String name) throws ClassNotFoundException {
byte[] classData = getClassData(name);
if (classData == null) {
throw new ClassNotFoundException();
}
else {
return defineClass(name, classData, 0, classData.length);
}
}
private byte[] getClassData(String className) {
String path = classNameToPath(className);
InputStream ins = null;
ByteArrayOutputStream baos = null;
try {
ins = new FileInputStream(path);
baos = new ByteArrayOutputStream();
int bufferSize = 4096;
byte[] buffer = new byte[bufferSize];
int bytesNumRead = 0;
while ((bytesNumRead = ins.read(buffer)) != -1) {
baos.write(buffer, 0, bytesNumRead);
}
return baos.toByteArray();
} catch (IOException e) {
e.printStackTrace();
} finally
{
closeIO(ins);
closeIO(baos);
}
return null;
}
private void closeIO(Closeable closeable)
{
if (closeable == null) return;
try
{
closeable.close();
} catch (IOException e)
{
e.printStackTrace();
}
}
private String classNameToPath(String className) {
return rootDir + File.separatorChar
+ className.replace('.', File.separatorChar) + ".class";
}
}
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.net.URL;
public class NetworkClassLoader extends ClassLoader {
private String rootUrl;
public NetworkClassLoader(String rootUrl) {
this.rootUrl = rootUrl;
}
protected Class<?> findClass(String name) throws ClassNotFoundException {
byte[] classData = getClassData(name);
if (classData == null) {
throw new ClassNotFoundException();
}
else {
return defineClass(name, classData, 0, classData.length);
}
}
private byte[] getClassData(String className) {
String path = classNameToPath(className);
try {
URL url = new URL(path);
InputStream ins = url.openStream();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
int bufferSize = 4096;
byte[] buffer = new byte[bufferSize];
int bytesNumRead = 0;
while ((bytesNumRead = ins.read(buffer)) != -1) {
baos.write(buffer, 0, bytesNumRead);
}
return baos.toByteArray();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
private String classNameToPath(String className) {
return rootUrl + "/"
+ className.replace('.', '/') + ".class";
}
}
@xujiaji
Copy link
Author

xujiaji commented May 16, 2018

  1. 构造参数传入位置,调用loadClass时传入类的全名。
  2. 自定义加载器会先调用父类对象的加载器先去加载,如果加载不到才会调用自定义的加载器。也就是如果调用到了(项目中有这个类),就不会去调用自定义。
  3. 但是我们用findClass方法就可以直接触发子类的方法,而没有第2点的问题。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment