Skip to content

Class loading issues in DYNAMIC mode #227

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
patrushev opened this issue Mar 12, 2019 · 1 comment
Open

Class loading issues in DYNAMIC mode #227

patrushev opened this issue Mar 12, 2019 · 1 comment

Comments

@patrushev
Copy link

We have defined a simple POJO interface (Address) and need to load its implementation class (AddressImpl) dynamically at run time via separate class loader. The class loaded correctly and proper implementation mapping registered at Jsoniter as "JsoniterSpi.registerTypeImplementation(Address.class, AddressImpl.class);". However, Jsoniter fails on both serialize and deserialize with the following javassist exception: "javassist.CannotCompileException: [source error] no such class: foo.bar.AddressImpl". Jsoniter configured in DYNAMIC mode, but we also checked STATIC, which does not work either.

Below is more detailed description of the use case and the error stack trace:

Class implClass = factory.loadImplementationClass(Address.class); // will load AddressImpl class

JsoniterSpi.registerTypeImplementation(Address.class, implClass);
JsonIterator.setMode(DecodingMode.DYNAMIC_MODE_AND_MATCH_FIELD_WITH_HASH);
JsonStream.setMode(EncodingMode.DYNAMIC_MODE);

Object address1 = implClass.newInstance();
String str = ...;
Object address2 = (Address)JsonIterator.deserialize(str, Address.class);

com.jsoniter.spi.JsonException: failed to generate decoder for: com.jsoniter.spi.ClassInfo@51297528 with [], exception: javassist.CannotCompileException: [source error] no such class: foo.bar.AddressImpl
public static java.lang.Object decode_(com.jsoniter.JsonIterator iter) throws java.io.IOException { java.lang.Object existingObj = com.jsoniter.CodegenAccess.resetExistingObject(iter);
byte nextToken = com.jsoniter.CodegenAccess.readByte(iter);
if (nextToken != '{') {
if (nextToken == 'n') {
com.jsoniter.CodegenAccess.skipFixedBytes(iter, 3);
return null;
} else {
nextToken = com.jsoniter.CodegenAccess.nextToken(iter);
if (nextToken == 'n') {
com.jsoniter.CodegenAccess.skipFixedBytes(iter, 3);
return null;
}
} // end of if null
} // end of if {
nextToken = com.jsoniter.CodegenAccess.readByte(iter);
if (nextToken != '"') {
if (nextToken == '}') {
return (existingObj == null ? new foo.bar.AddressImpl() : (foo.bar.AddressImpl)existingObj);
} else {
nextToken = com.jsoniter.CodegenAccess.nextToken(iter);
if (nextToken == '}') {
return (existingObj == null ? new foo.bar.AddressImpl() : (foo.bar.AddressImpl)existingObj);
} else {
com.jsoniter.CodegenAccess.unreadByte(iter);
}
} // end of if end
} else { com.jsoniter.CodegenAccess.unreadByte(iter); }// end of if not quote
java.lang.String state = null;
java.lang.Long zip = null;
java.lang.String city = null;
java.lang.String street = null;
java.lang.String country = null;
do {
switch (com.jsoniter.CodegenAccess.readObjectFieldAsHash(iter)) {
case -1517218351:
country = (java.lang.String)iter.readString();
continue;
case -1417514060:
zip = (java.lang.Long)(iter.readNull() ? null : java.lang.Long.valueOf(iter.readLong()));
continue;
case 230981954:
city = (java.lang.String)iter.readString();
continue;
case 1986331710:
street = (java.lang.String)iter.readString();
continue;
case 2016490230:
state = (java.lang.String)iter.readString();
continue;
}
iter.skip();
} while (com.jsoniter.CodegenAccess.nextTokenIsComma(iter));
foo.bar.AddressImpl obj = (existingObj == null ? new foo.bar.AddressImpl() : (foo.bar.AddressImpl)existingObj);
obj.setState(state);
obj.setZip(zip);
obj.setCity(city);
obj.setStreet(street);
obj.setCountry(country);
return obj;
}

at com.jsoniter.Codegen.gen(Codegen.java:86)
at com.jsoniter.Codegen.getDecoder(Codegen.java:25)
at com.jsoniter.CodegenImplNative.genReadOp(CodegenImplNative.java:213)
at com.jsoniter.CodegenImplNative.genField(CodegenImplNative.java:191)
at com.jsoniter.CodegenImplObjectHash.appendBindingSet(CodegenImplObjectHash.java:125)
at com.jsoniter.CodegenImplObjectHash.genObjectUsingHash(CodegenImplObjectHash.java:92)
at com.jsoniter.Codegen.genSource(Codegen.java:243)
at com.jsoniter.Codegen.gen(Codegen.java:68)
at com.jsoniter.Codegen.getDecoder(Codegen.java:25)
at com.jsoniter.JsonIterator.read(JsonIterator.java:385)
at com.jsoniter.JsonIterator.read(JsonIterator.java:375)
... 36 more

Caused by: javassist.CannotCompileException: [source error] no such class: foo.bar.AddressImpl
at javassist.CtNewMethod.make(CtNewMethod.java:84)
at javassist.CtNewMethod.make(CtNewMethod.java:50)
at com.jsoniter.DynamicCodegen.gen(DynamicCodegen.java:18)
at com.jsoniter.Codegen.gen(Codegen.java:78)
... 51 more
Caused by: compile error: no such class: foo.bar.AddressImpl
at javassist.compiler.MemberResolver.searchImports(MemberResolver.java:479)
at javassist.compiler.MemberResolver.lookupClass(MemberResolver.java:422)
at javassist.compiler.MemberResolver.lookupClassByName(MemberResolver.java:325)
at javassist.compiler.TypeChecker.atNewExpr(TypeChecker.java:168)
at javassist.compiler.ast.NewExpr.accept(NewExpr.java:75)
at javassist.compiler.TypeChecker.atCondExpr(TypeChecker.java:310)
at javassist.compiler.ast.CondExpr.accept(CondExpr.java:48)
at javassist.compiler.CodeGen.doTypeCheck(CodeGen.java:266)
at javassist.compiler.CodeGen.compileExpr(CodeGen.java:253)
at javassist.compiler.CodeGen.atReturnStmnt2(CodeGen.java:641)
at javassist.compiler.JvstCodeGen.atReturnStmnt(JvstCodeGen.java:443)
at javassist.compiler.CodeGen.atStmnt(CodeGen.java:393)
at javassist.compiler.ast.Stmnt.accept(Stmnt.java:53)
at javassist.compiler.CodeGen.atStmnt(CodeGen.java:381)
at javassist.compiler.ast.Stmnt.accept(Stmnt.java:53)
at javassist.compiler.CodeGen.atIfStmnt(CodeGen.java:428)
at javassist.compiler.CodeGen.atStmnt(CodeGen.java:385)
at javassist.compiler.ast.Stmnt.accept(Stmnt.java:53)
at javassist.compiler.CodeGen.atStmnt(CodeGen.java:381)
at javassist.compiler.ast.Stmnt.accept(Stmnt.java:53)
at javassist.compiler.CodeGen.atIfStmnt(CodeGen.java:428)
at javassist.compiler.CodeGen.atStmnt(CodeGen.java:385)
at javassist.compiler.ast.Stmnt.accept(Stmnt.java:53)
at javassist.compiler.CodeGen.atStmnt(CodeGen.java:381)
at javassist.compiler.ast.Stmnt.accept(Stmnt.java:53)
at javassist.compiler.CodeGen.atMethodBody(CodeGen.java:321)
at javassist.compiler.CodeGen.atMethodDecl(CodeGen.java:303)
at javassist.compiler.ast.MethodDecl.accept(MethodDecl.java:47)
at javassist.compiler.Javac.compileMethod(Javac.java:175)
at javassist.compiler.Javac.compile(Javac.java:102)
at javassist.CtNewMethod.make(CtNewMethod.java:79)
... 54 more

@patrushev
Copy link
Author

We have tried setting context class loader of course with no apparent success.

In our view, Jsoniter should either accept parent class loader explicitly (as part of the configuration or as a parameter for an operation) or it should use some smarter class loading techniques (for instance similarly to org.mapstruct.factory.Mappers#getMapper(java.lang.Class)). Classes not always loaded by the system class loaders.

Jackson works fine in the above use case. No class loading issues observed so far.
Although we found Jsoniter to be noticeably faster than Jackson for our use cases, we have to stick to Jackson until this issue gets resolved somehow.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant