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<String,Class> 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!");
    }
}

 

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


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM