bytearray - Loading custom class loader to load a transferred byte[] in java -


i transfer whole .class file (and it's declared , anonymous classes) byte[] , want able define using class loader on computer receives byte[].

i have found solution @ java: how load class stored byte[] jvm?, however, don't understand how use byteclassloader purpose. post code here again:

public class byteclassloader extends urlclassloader { private final map<string, byte[]> extraclassdefs;  public byteclassloader(url[] urls, classloader parent, map<string, byte[]> extraclassdefs) {     super(urls, parent);     this.extraclassdefs = new hashmap<string, byte[]>(extraclassdefs); }  @override protected class<?> findclass(final string name) throws classnotfoundexception {     byte[] classbytes = this.extraclassdefs.remove(name);     if (classbytes != null) {         return defineclass(name, classbytes, 0, classbytes.length);     }     return super.findclass(name); } 

}

the question is: how have instantiate it?

i tried use instantiating byteclassloader b = new byteclassloader(...); obviously, not working (as expected).

i found way of loading new class loader @ beginning of program @ https://analyzejava.wordpress.com/2014/09/25/java-classloader-loading-a-custom-classloader-on-jvm-start/ using -djava.system.class.loader =...byteclassloader, however, did not work either (it did not find class byteclassloader. helpful me if point me right direction of how use referenced class loader (i'm new class loaders , not yet understand how work).

edit: have class serializeutils method deserialize() instantiate byteclassloader. did not work referenced implementation, tried byteclassloader extends classloader (i did not know url[] from) , change contextclassloader of thread:

public static map<string, class<?>> deserialize(map<string, byte[]> classestodefine) {      // serializeutils.class.getclassloader().     byteclassloader l = new byteclassloader(thread.currentthread().getcontextclassloader(), classestodefine); // todo                                                                 // may                                                                 // problem     thread.currentthread().setcontextclassloader(l);     map<string, class<?>> classes = new hashmap<>();     (string classname : classestodefine.keyset()) {         try {             system.out.println("classname in deserialize: "+ classname);             class<?> c = ((byteclassloader)thread.currentthread().getcontextclassloader()).findclass(classname);             system.out.println("class found : " + c.getname());             classes.put(classname, c);         } catch (classnotfoundexception e) {             e.printstacktrace();         }     }     return classes; } 

what hoped achieve converted byte array available execution, such may able instantiate it. need passing actual data of object serialized byte array using and, right after loaded class, decode object , use using:

public static object decodejavaobject(byte[] me, int offset, int length) throws classnotfoundexception,         ioexception {     bytearrayinputstream bais = new bytearrayinputstream(me, offset, length);     objectinputstream ois = new objectinputstream(bais);     object obj = ois.readobject();     // no need call close of flush since use bytearrayinputstream     return obj; } 

so call serializeutils.deserialize() deserialize .class file in hope of having available afterwards. right after that, call

so complete deserialization process looks follows:

public static job deserialize(jobtransferobject jobtodeserialize) throws classnotfoundexception, ioexception {     job job = new job();     (transferobject tasktransferobject : jobtodeserialize.tasktransferobjects()) {         serializeutils.deserialize(tasktransferobject.classfiles());         task task = (task) utils.decodejavaobject(tasktransferobject.data(), 0, tasktransferobject.data().length);         job.addtask(task);     }      return job; } 

so first call serializeutils.deserialize() deserialize class files in hope of having them available next invocation of utils.decodejavaobject try deserialize byte[] of actual object transferred (so send class files of class want instantiate , decode object of class sent on network). task abstract class class file deserialize extends, task known program needs deserialize implementation of it). btw, transferobject looks this:

public class transferobject implements serializable{ /**  *   */ private static final long serialversionuid = 8971732001157216939l; private byte[] data; private map<string, byte[]> classfiles; private string classname;  public transferobject(byte[] data, map<string, byte[]> classfiles, string classname) {     this.data = data;     this.classfiles = classfiles;     this.classname = classname; }  public byte[] data() {     return this.data; }  public map<string, byte[]> classfiles() {     return this.classfiles; }  public string classname() {     return this.classname; } 

}

(data = serialised object extending task on computer, classfiles = serialised class files of extended object, , classname actual name of extended class)

and extension of task on computer looks e.g. this:

task initshutdown = new task(writetask.currentid(), numberutils.next()) {          /**          *           */         private static final long serialversionuid = -5543401293112052880l;          @override         public void broadcastreceiver(navigablemap<number640, data> input, dhtconnectionprovider dht)                 throws exception {             dht.shutdown();          }      }; 

and task abstract class following code:

public abstract class task implements serializable {  /**  *   */ private static final long serialversionuid = 9198452155865807410l; private final number640 previousid; private final number640 currentid;  public task(number640 previousid, number640 currentid) {     this.previousid = previousid;     this.currentid = currentid; }  public abstract void broadcastreceiver(navigablemap<number640, data> input, dhtconnectionprovider dht)         throws exception;   public number640 currentid() {     return this.currentid; }  public number640 previousid() {     return this.previousid; }} 

sorry complicated explanation...

without having tested it, here suggestion:

create single classloader per definition map:

public static job deserialize(jobtransferobject jobtodeserialize) throws classnotfoundexception, ioexception {     job job = new job();     (transferobject tasktransferobject : jobtodeserialize.tasktransferobjects()) {         classloader cl = new byteclassloader(new url[0], task.class.getclassloader(), tasktransferobject.classfiles());         task task = (task)utils.decodejavaobject(tasktransferobject.data(), 0, tasktransferobject.data().length, cl);         job.addtask(task);     }     return job; } 

and extend objectinputstream use classloader in deserialization:

public static object decodejavaobject(byte[] me, int offset, int length, final classloader cl) throws classnotfoundexception, ioexception {     bytearrayinputstream bais = new bytearrayinputstream(me, offset, length);     objectinputstream ois = new objectinputstream(bais) {         @override         protected class<?> resolveclass(objectstreamclass objectstreamclass)                 throws ioexception, classnotfoundexception {              class<?> clazz = class.forname(objectstreamclass.getname(), false, cl);             if (clazz != null) {                 return clazz;             } else {                 return super.resolveclass(objectstreamclass);             }         }          @override         protected class<?> resolveproxyclass(string[] interfaces) throws ioexception, classnotfoundexception {             class<?>[] interfaceclasses = new class[interfaces.length];             (int = 0; < interfaces.length; i++) {                 interfaceclasses[i] = class.forname(interfaces[i], false, cl);             }             try {                 return proxy.getproxyclass(cl, interfaceclasses);             } catch (illegalargumentexception e) {                 return super.resolveproxyclass(interfaces);             }         }     };     object obj = ois.readobject();     return obj; } 

Comments

Post a Comment

Popular posts from this blog

gridview - Yii2 DataPorivider $totalSum for a column -

java - Suppress Jboss version details from HTTP error response -

Sass watch command compiles .scss files before full sftp upload -