`
cloud21
  • 浏览: 397441 次
  • 性别: Icon_minigender_2
  • 来自: 北京
社区版块
存档分类
最新评论

自定义classLoader+erlang tcp通信

阅读更多
自定义了个ClassLoader,用socket从一个server上获取class文件内容,然后创建一个类。tcp server是用erlang写的,只负责从硬盘读数据,然后传到自定义ClassLoader。特别注意的是,要想erlang socket跟java socket通信,gen_tcp:listen(Port,[binary,{packet,0}]),这里packet一定要为0,这个是erlang数据包的包头,通信的时候客户端跟服务端加的额外数据,跟java通信,是不能加的,否则会出现error msgsize这类的错误。
-module(class_file_server).
-export([start/0,start/1,process_request/1]).
-define(PORT,7777).
-define(CLASS_NOT_FOUND,"class_not_found_exception").
start() ->
 start(?PORT).
start(Port) ->
 case gen_tcp:listen(Port,[binary,{packet,0},{active,true}]) of
  {ok,Socket} -> process_request(Socket);
  {error,Reason} -> io:format("Fail to create socket: ~s ~n",[Reason])
 end.

process_request(Socket) ->
 case gen_tcp:accept(Socket) of
  {ok,From} -> 
   spawn(class_file_server,process_request,[Socket]),
   receive_data_then_send_file(From);
  {error,closed} ->
   io:format("Failed to accept, for {error,closed}~n");
  {error,Reason} ->
   io:format("Failed to accept: ~s~n",[Reason]);
  Other ->
   io:format("accept Other ~p~n",[Other])
 end.

receive_data_then_send_file(FromSocket) ->
 receive
  {tcp,FromSocket,Bin} ->
   io:format("receive some raw data: ~p ~n from ~p~n",[Bin,inet:peername(FromSocket)]),
   send_file(FromSocket,binary_to_list(Bin)),
   gen_tcp:close(FromSocket);
  {tcp_closed,FromSocket} ->
   io:format("processed one request:~p~n",[FromSocket]),
   gen_tcp:close(FromSocket);
  Other ->
   io:format("Invalid data: ~p~n",[Other])
 end.

send_file(FromSocket,FileName) ->
 case file:read_file(FileName) of
  {ok,Bin} ->
   gen_tcp:send(FromSocket,Bin);
  {error,Why} ->
   gen_tcp:send(FromSocket,?CLASS_NOT_FOUND),
   io:format("Failed to load class: ~p ~n because ~p~n",[FileName,Why])
 end.

package classloader;

public class RemoteClassLoader extends ClassLoader {

 protected Class<?> findClass(String name) throws ClassNotFoundException {
  DownloadManager manager = new DownloadManager(7777);
  try {
   byte[] data = manager.download(name);
   return defineClass(name, data, 0, data.length);
  } catch (ClassNotFoundException e) {
   return super.findClass(name);
  }
 }
 @SuppressWarnings("unchecked")
 public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException{
  RemoteClassLoader loader = new RemoteClassLoader();
  Thread.currentThread().setContextClassLoader(loader);
//  Class clazz = loader.loadClass("com.kingdee.eas.LoadedClazz");
  Class clazz = Class.forName("com.kingdee.eas.LoadedClazz",true,loader);
  clazz.newInstance();
  //  clazz.newInstance();
 }
}


package classloader;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Arrays;

public class DownloadManager {
 private static final String CLASS_NOT_FOUND = "class_not_found_exception";
 private static final byte[] BYTES_CLASS_NOT_FOUND = CLASS_NOT_FOUND.getBytes();
 private static final int SIZE = 204800;
 private int port;
 private byte[] result = new byte[SIZE * 10];
 private byte[] buffer = new byte[SIZE];

 public DownloadManager(int port) {
  super();
  this.port = port;
 }

 public byte[] download(String name) throws ClassNotFoundException {
  // E:\\develop\\workspaces\\workspace-java\\jdbcdriver\\test\\com\\kingdee\eas\LoadedClazz.java
  String classFile = "E:\\develop\\workspaces\\workspace-java\\jdbcdriver\\bin\\" + name.replaceAll("\\.", "/")
    + ".class";

  Socket socket = null;
  OutputStream out = null;
  InputStream in = null;
  int count = 0, totalCount = 0;
  try {
   socket = new Socket("192.168.18.27", this.port);
   // write to socket
   out = new BufferedOutputStream(socket.getOutputStream());
   out.write(classFile.getBytes());
   out.flush();
   // read from socket
   in = new BufferedInputStream(socket.getInputStream());
   while ((count = in.read(buffer)) > 0) {
    if (isEqual(BYTES_CLASS_NOT_FOUND, buffer, count)) {
     throw new ClassNotFoundException(classFile);
    }
    System.arraycopy(buffer, 0, result, totalCount, count);
    totalCount += count;
   }
   for (int i = 0; i < totalCount; i++) {
    System.out.print(String.format("%02X", result[i]));
    if ((i + 1) % 100 == 0)
     System.out.println();
   }
   System.out.println();

   return Arrays.copyOfRange(result, 0, totalCount);
  } catch (UnknownHostException e) {
   throw new ClassNotFoundException(classFile);
  } catch (IOException e) {
   throw new ClassNotFoundException(classFile);
  } finally {
   try {
    if (out != null)
     out.close();
    if (in != null)
     in.close();
    if (socket != null)
     socket.close();
   } catch (IOException e) {
    e.printStackTrace();
   }
  }
 }

 private static boolean isEqual(byte[] dest, byte[] buffer, int size) {
  if (dest.length != size)
   return false;
  for (int i = 0; i < size; i++) {
   if (dest[i] != buffer[i])
    return false;
  }
  return true;
 }

 /**
  * @param args
  * @throws IOException 
  * @throws UnknownHostException 
  * @throws ClassNotFoundException 
  */
 public static void main(String[] args) throws UnknownHostException, IOException, ClassNotFoundException {
  DownloadManager manager = new DownloadManager(7777);
  manager.download("");
 }

}

这里写死了类路径的,你也可自己写自己的。另外需要指明的是,自定义的类装载的的双亲装载器是在ClassLoader类的默认构造函数里设置的,通过getSystemClassLoader()得到的AppClassLoader。而自定义的ClassLoader只实现findClass方法,可以保留loadClass方法原先的双亲委派模型,不用自己去加载所有的类。
分享到:
评论

相关推荐

    自定义classloader的使用

    自定义Classloader允许开发者根据特定需求定制类的加载逻辑,例如加密类文件、隔离不同版本的库或者动态加载代码。本文将深入探讨自定义Classloader的使用。 一、Classloader的工作原理 Java的类加载机制遵循双亲...

    定义ClassLoader调用外部jar包

    这篇博文"定义ClassLoader调用外部jar包"探讨了如何创建一个自定义的ClassLoader,以便能够灵活地加载不在应用主类路径(ClassPath)中的jar包中的类。 首先,我们需要理解ClassLoader的工作原理。默认情况下,Java...

    Java实现热加载完整代码;Java动态加载class;Java覆盖已加载的class;Java自定义classloader

    让Java支持热加载是个不错的想法。如何做到的呢? 1. 定义好接口和实现类 2. 让代理类通过反射的方式调用实现类,对外暴露的是代理类。 3. 自定义URLClassLoader。检查实现类.class文件的...Java自定义classloader;

    使用自定义ClassLoader解决反序列化serialVesionUID不一致问题 _ 回忆飘如雪1

    标题和描述中提到的解决方案是通过自定义`ClassLoader`来处理`serialVersionUID`不一致的问题。以下是几种常见方法的优缺点以及自定义`ClassLoader`的详细解释: 1. **修改序列化byte数据**: 这种方法直接修改已...

    ClassLoader运行机制 自己写的

    这里我们将详细讨论ClassLoader的运行机制,特别是自定义ClassLoader的设计与实现。 ClassLoader的基本职责是根据类名动态加载对应的类文件。在Java中,类加载过程遵循双亲委派模型(Parent Delegation Model)。这...

    classloader

    创建自定义类加载器需要继承ClassLoader类,并重写findClass()方法。在这个方法里,你可以编写代码来从指定的位置(例如,网络、文件系统或内存)读取类的字节码,并通过defineClass()方法将其转换为Class对象。 在...

    关于Android中自定义ClassLoader耗时问题的追查

    在Android开发中,自定义ClassLoader是一项关键技能,尤其在实现热修复和插件化技术时。本文主要探讨了Android中自定义ClassLoader导致的性能问题,特别是冷启动速度的影响。问题的核心在于,通过插入自定义的...

    ClassLoader 案例

    自定义ClassLoader允许开发者根据特定需求加载类,比如动态加载或更新类文件,这在某些高级应用场景中非常有用,如插件系统、热部署等。本案例将深入探讨如何创建一个自定义的ClassLoader,利用Java反射和注解技术...

    java自定义类加载classloader文档,包括代码

    上述代码展示了如何创建一个自定义类加载器`MyClassLoader`,该类继承自`java.lang.ClassLoader`。`MyClassLoader`的主要功能是从文件系统中加载指定类的二进制数据。 - **构造函数**:接受一个父类加载器和基础...

    ClassLoader小例子

    下面我们将详细讨论ClassLoader的基本概念、工作流程以及如何自定义ClassLoader。 1. **ClassLoader的基本概念** - 类加载器是Java中的一个核心组件,它负责将类的.class文件加载到JVM中,并转换为可执行的Java...

    MyCLRepl:自定义 Scala REPL 示例以添加自定义 ClassLoader 和自定义 REPL 命令

    自定义 ClassLoader 加载任何类时的类名。 ":myCommand" 命令位于默认 REPL 命令之上。 scala &gt; val hello = " hello " MyClassLoader loads classOf &lt; root&gt;.$line3 &lt;&lt;中略&gt;&gt; MyClassLoader loads classOf ...

    Java ClassLoader定制实例

    在某些特定场景下,比如动态加载代码、插件系统或者安全隔离等,我们需要自定义ClassLoader来实现特定的加载逻辑。例如,我们可能希望加载网络上的类,或者从数据库中读取类的字节码。 以...

    Understanding the Java ClassLoader

    为了更好地理解和利用Java的这一特性,本篇将详细介绍Java ClassLoader的作用及其工作原理,并通过构建一个示例ClassLoader来帮助读者深入理解如何自定义ClassLoader,从而扩展JVM的功能。 #### 二、ClassLoader...

    ClassLoader类加载器

    了解和掌握ClassLoader的工作原理以及如何自定义ClassLoader对于深入理解Java应用程序的运行机制非常有帮助。以下是对ClassLoader API的使用和自定义的详细说明。 首先,我们来看ClassLoader的基本概念。在Java中,...

    ClassLoader类加载机制和原理详解

    但有时我们可能需要打破这种模型,比如实现类的版本控制或插件系统,这时可以通过自定义ClassLoader来实现。 5. 类加载器的关系图 Java中的ClassLoader形成了一个树状结构,Bootstrap ClassLoader位于顶端,其他类...

    3-7Tomcat中自定义类加载器的使用与源码实现(1).mp4

    3-7Tomcat中自定义类加载器的使用与源码实现(1).mp4

    ClassLoader的 一些测试

    通过阅读给出的博文链接,我们可以深入理解ClassLoader的功能、分类以及如何进行自定义。 首先,ClassLoader的基本职责是加载.class文件,将字节码转化为运行时的Java对象。这个过程分为三个步骤:加载、验证和初始...

    理解Java ClassLoader机制

    理解ClassLoader的工作原理对于优化应用性能、处理类加载问题以及实现自定义加载器至关重要。 首先,我们来了解一下ClassLoader的基本层次结构。在Java中,ClassLoader分为三个主要层次:Bootstrap ClassLoader、...

    ClassLoader 详解.doc

    深入理解ClassLoader的工作原理对于优化应用性能、解决类加载问题以及实现自定义加载策略至关重要。 首先,JVM启动时,会构建一个类加载器的层次结构,主要包括三个基本类加载器: 1. Bootstrap ClassLoader:引导...

Global site tag (gtag.js) - Google Analytics