java 远程加载_java实现自定义的classloader,实现从远程加载类文件

为了了解Classloader,自己实现的一个简易ClassLoader,以下为客户端:

public class Main {

public static void main(String[] args) throws IOException, ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException {

ClassLoader classLoader = new MyClassLoader(new InetSocketAddress(InetAddress.getLocalHost(),8080));

while (true){

Scanner scanner = new Scanner(System.in);

String line = scanner.nextLine();

if( "STOP".equals(line) ){

break;

}

String[] commands = line.split(" ");

System.out.println("waiting...");

if( "send".equals(commands[0]) ){

Class clazz = classLoader.loadClass(commands[1]);

Method ms = clazz.getDeclaredMethod("say");

Object instance = clazz.newInstance();

ms.invoke(instance);

}

System.out.println( "load finish." );

}

}

}

class MyClassLoader extends ClassLoader{

private SocketAddress sa;

public MyClassLoader(SocketAddress sa){

this.sa = sa;

}

private Map cache = new ConcurrentHashMap<>();

@Override

protected Class> findClass(String name) throws ClassNotFoundException {

Class clazz = cache.get(name);

if( clazz != null ){

//因为由ClassLoader加载过了类会进行缓存,所以这里的缓存不是必要的

System.out.println("从缓存中加载");

return clazz;

}else{

System.out.println("从远程服务器加载。");

Socket socket = new Socket();

try {

socket.connect(sa);

OutputStream out = socket.getOutputStream();

out.write(name.getBytes(Charset.forName("utf-8")));

out.flush();

socket.shutdownOutput();

InputStream in = socket.getInputStream();

ByteArrayOutputStream bot = new ByteArrayOutputStream();

byte[] buffer = new byte[1024];

for( int len = 0; (len = in.read(buffer)) != -1; ){

bot.write(buffer,0,len);

}

byte[] bytes = bot.toByteArray();

Class cls = this.defineClass(name,bytes,0,bytes.length);

cache.putIfAbsent(name,cls);

socket.close();

return cls;

} catch (IOException e) {

e.printStackTrace();

}

return null;

}

}

}

客户端代码如下:

public class Main {

private static ServerSocket ss;

private static ExecutorService ex = Executors.newCachedThreadPool();

private static class SoktHandler implements Runnable {

private Socket socket;

public SoktHandler(Socket so){

this.socket = so;

}

@Override

public void run() {

try{

if( socket != null ){

InputStream in = socket.getInputStream();

Reader reader = new InputStreamReader(in, Charset.forName("utf-8"));

char[] buffer = new char[1024];

StringBuilder sb = new StringBuilder();

for( int len = 0; (len = reader.read(buffer)) != -1; ){

sb.append(buffer,0,len);

}

if( "STOP".equals( sb.toString() ) ){

synchronized (SoktHandler.class){

if( !ss.isClosed() ){

ss.close();

}

}

}else{

String resourceName = sb.toString();

resourceName = resourceName.replaceAll("\\.","/");

if(!resourceName.endsWith(".class")){

resourceName += ".class";

InputStream ins = Main.class.getClassLoader().getResourceAsStream(resourceName);

OutputStream out = socket.getOutputStream();

byte[] bytes = new byte[1024];

for( int len = 0; ( len = ins.read(bytes) ) != -1;){

out.write(bytes,0,len);

}

out.flush();

out.close();

ins.close();

}

}

}

}catch (Exception e){

System.out.println("IO异常,连接被关闭。");

}

}

}

public static void main(String[] args) {

try{

ss = new ServerSocket(8080);

while (true){

Socket socket = ss.accept();

ex.execute(new SoktHandler(socket));

}

}catch (IOException e){

if( e instanceof SocketException){

System.out.println( "服务关闭!" );

ex.shutdown();

}

}

}

}

MyClass包下的类

package MyClass;

public class Demo {

public void say(){

System.out.println("hello world!");

}

}

以上,只是为了探索一下自定义的类加载器的扩展用法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值