java - Generics and ReadObject -


i have simple server uses generics , object serialization. (t input format, u output format). simplified version deals input shown below:

public class server <t, u> implements runnable {      @override     public void run () {      try (objectinputstream inreader = new objectinputstream (this.connection.getinputstream ())) {         t   lastobj;         while (true) {             lastobj = (t) inreader.readobject ();             system.out.println (lastobj.getclass ().getname ());             if (null != lastobj) {                 this.acceptmessage (lastobj);             }         } catch (ioexception | classnotfoundexception ex) {             logger.getlogger (this.getclass ().getname ()).log (level.severe, ex.getmessage (), ex);         }     } } 

if start server

server <integer, string> thisserver = new server (); 

then expect accept integer objects , return strings output.

however, using simple client read system.in testing , sending strings server. surprise, server accepted input. make sure accepting object wasn't of type t added line echo out class last object was.

system.out.println (lastobj.getclass ().getname ()); 

this did in fact output java.lang.string.

this totally unexpected. thought generics supposed allow pass objects of type wasn't specified in class without having cast objects? cast t doesn't seem have effect either.

this means in theory attack server (or consumer) feeding java objects of type wasn't expecting. whilst doesn't have super-robust (because it's academic project , not production software) think knowing object got readobject wasn't 1 wanted can deal important.

i tried adding following, got flagged compile time error.

if (lastobj instanceof t) { } 

how handle correctly?

as others have pointed out, issue related type erasure. @ runtime, t has been erased upper bound, object.

when cast t, that's known unchecked cast because doesn't exist @ runtime. instead, other casts have been inserted compiler in places instances of t assigned reified type integer. when run consumes unexpected type string, jvm can't tell difference, , doesn't fail fast. if there method t getlastobject, caller of method might fail instead:

server<integer, string> thisserver = ...; thisserver.run(); // consumes string, doesn't fail integer = thisserver.getlastobject(); // classcastexception thrown here 

the workaround provide server class<t> object representing type of object consumed , use cast method:

public class server <t, u> implements runnable {     private final class<t> readobjecttype;     public server(final class<t> readobjecttype) {        this.readobjecttype = readobjecttype;    }      @override     public void run () {      try (objectinputstream inreader = new objectinputstream (this.connection.getinputstream ())) {         t   lastobj;         while (true) {             lastobj = readobjecttype.cast(inreader.readobject());             system.out.println (lastobj.getclass ().getname ());             if (null != lastobj) {                 this.acceptmessage (lastobj);             }         } catch (ioexception | classnotfoundexception ex) {             logger.getlogger (this.getclass ().getname ()).log (level.severe, ex.getmessage (), ex);         }     } } 

readobjecttype.cast(inreader.readobject()) fail fast when wrong type of object has been read.


Popular posts from this blog

php - How should I create my API for mobile applications (Needs Authentication) -

5 Reasons to Blog Anonymously (and 5 Reasons Not To)

Google AdWords and AdSense - A Dynamic Small Business Marketing Duo