jpmml / jpmml-evaluator

Java Evaluator API for PMML
GNU Affero General Public License v3.0
891 stars 255 forks source link

LoadingModelEvaluatorBuilder not usable on Android due to "java.lang.NoClassDefFoundError: Failed resolution of: Ljava/awt/Image" #270

Closed jye0829 closed 1 month ago

jye0829 commented 1 month ago
InputStream inputStream3 = getResources().getAssets().open("X_test_verify.csv");

Evaluator evaluator = new LoadingModelEvaluatorBuilder()
    .load(inputStream2)
    .build();

E FATAL EXCEPTION: OpenCVCameraBackground Process: com.zhenzhe.javacv, PID: 12163

 java.lang.NoClassDefFoundError: Failed resolution of: Ljava/awt/Image;
   at org.glassfish.jaxb.runtime.v2.model.impl.RuntimeBuiltinLeafInfoImpl.<clinit>(RuntimeBuiltinLeafInfoImpl.java:337)
   at org.glassfish.jaxb.runtime.v2.model.impl.RuntimeTypeInfoSetImpl.<init>(RuntimeTypeInfoSetImpl.java:31)
   at org.glassfish.jaxb.runtime.v2.model.impl.RuntimeModelBuilder.createTypeInfoSet(RuntimeModelBuilder.java:91)
   at org.glassfish.jaxb.runtime.v2.model.impl.RuntimeModelBuilder.createTypeInfoSet(RuntimeModelBuilder.java:46)
   at org.glassfish.jaxb.runtime.v2.model.impl.ModelBuilder.<init>(ModelBuilder.java:119)
   at org.glassfish.jaxb.runtime.v2.model.impl.RuntimeModelBuilder.<init>(RuntimeModelBuilder.java:55)
   at org.glassfish.jaxb.runtime.v2.runtime.JAXBContextImpl.getTypeInfoSet(JAXBContextImpl.java:403)
   at org.glassfish.jaxb.runtime.v2.runtime.JAXBContextImpl.<init>(JAXBContextImpl.java:251)
   at org.glassfish.jaxb.runtime.v2.runtime.JAXBContextImpl.<init>(JAXBContextImpl.java:77)
   at org.glassfish.jaxb.runtime.v2.runtime.JAXBContextImpl$JAXBContextBuilder.build(JAXBContextImpl.java:1111)
   at org.glassfish.jaxb.runtime.v2.ContextFactory.createContext(ContextFactory.java:140)
   at java.lang.reflect.Method.invoke(Native Method)
   at jakarta.xml.bind.ContextFinder.newInstance(ContextFinder.java:274)
   at jakarta.xml.bind.ContextFinder.newInstance(ContextFinder.java:263)
   at jakarta.xml.bind.ContextFinder.find(ContextFinder.java:395)
   at jakarta.xml.bind.JAXBContext.newInstance(JAXBContext.java:691)
   at jakarta.xml.bind.JAXBContext.newInstance(JAXBContext.java:632)
   at org.jpmml.model.JAXBUtil.getContext(JAXBUtil.java:106)
   at org.jpmml.evaluator.LoadingModelEvaluatorBuilder.load(LoadingModelEvaluatorBuilder.java:151)
   at org.jpmml.evaluator.LoadingModelEvaluatorBuilder.load(LoadingModelEvaluatorBuilder.java:138)
   at com.zhenzhe.javacv.JavaCamera2FocusEnabledApp$ImageSaver.run(JavaCamera2FocusEnabledApp.java:556)
   at com.zhenzhe.javacv.JavaCamera2FocusEnabledApp$1.onImageAvailable(JavaCamera2FocusEnabledApp.java:240)
   at android.media.ImageReader$1.run(ImageReader.java:947)
   at android.os.Handler.handleCallback(Handler.java:958)
   at android.os.Handler.dispatchMessage(Handler.java:99)
   at android.os.Looper.loopOnce(Looper.java:230)
   at android.os.Looper.loop(Looper.java:319)
   at android.os.HandlerThread.run(HandlerThread.java:67)
  Caused by: java.lang.ClassNotFoundException: Didn't find class "java.awt.Image" on path: DexPathList[[dex file "/data/data/com.zhenzhe.javacv/code_cache/.overlay/base.apk/classes14.dex", zip file "/data/app/~~NYD5IBEMJQXxXIf2bAwOOw==/com.zhenzhe.javacv-oIrH3gRpKt2wcVh1BVGusw==/base.apk"],nativeLibraryDirectories=[/data/app/~~NYD5IBEMJQXxXIf2bAwOOw==/com.zhenzhe.javacv-oIrH3gRpKt2wcVh1BVGusw==/lib/arm64, /data/app/~~NYD5IBEMJQXxXIf2bAwOOw==/com.zhenzhe.javacv-oIrH3gRpKt2wcVh1BVGusw==/base.apk!/lib/arm64-v8a, /system/lib64, /system/system_ext/lib64]]
   at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:259)
   at java.lang.ClassLoader.loadClass(ClassLoader.java:379)
   at java.lang.ClassLoader.loadClass(ClassLoader.java:312)
   at org.glassfish.jaxb.runtime.v2.model.impl.RuntimeBuiltinLeafInfoImpl.<clinit>(RuntimeBuiltinLeafInfoImpl.java:337) 
   at org.glassfish.jaxb.runtime.v2.model.impl.RuntimeTypeInfoSetImpl.<init>(RuntimeTypeInfoSetImpl.java:31) 
   at org.glassfish.jaxb.runtime.v2.model.impl.RuntimeModelBuilder.createTypeInfoSet(RuntimeModelBuilder.java:91) 
   at org.glassfish.jaxb.runtime.v2.model.impl.RuntimeModelBuilder.createTypeInfoSet(RuntimeModelBuilder.java:46) 
   at org.glassfish.jaxb.runtime.v2.model.impl.ModelBuilder.<init>(ModelBuilder.java:119) 
   at org.glassfish.jaxb.runtime.v2.model.impl.RuntimeModelBuilder.<init>(RuntimeModelBuilder.java:55) 
   at org.glassfish.jaxb.runtime.v2.runtime.JAXBContextImpl.getTypeInfoSet(JAXBContextImpl.java:403) 
   at org.glassfish.jaxb.runtime.v2.runtime.JAXBContextImpl.<init>(JAXBContextImpl.java:251) 
   at org.glassfish.jaxb.runtime.v2.runtime.JAXBContextImpl.<init>(JAXBContextImpl.java:77) 
   at org.glassfish.jaxb.runtime.v2.runtime.JAXBContextImpl$JAXBContextBuilder.build(JAXBContextImpl.java:1111) 
   at org.glassfish.jaxb.runtime.v2.ContextFactory.createContext(ContextFactory.java:140) 
   at java.lang.reflect.Method.invoke(Native Method) 
   at jakarta.xml.bind.ContextFinder.newInstance(ContextFinder.java:274) 
   at jakarta.xml.bind.ContextFinder.newInstance(ContextFinder.java:263) 
   at jakarta.xml.bind.ContextFinder.find(ContextFinder.java:395) 
   at jakarta.xml.bind.JAXBContext.newInstance(JAXBContext.java:691) 
   at jakarta.xml.bind.JAXBContext.newInstance(JAXBContext.java:632) 
   at org.jpmml.model.JAXBUtil.getContext(JAXBUtil.java:106) 
   at org.jpmml.evaluator.LoadingModelEvaluatorBuilder.load(LoadingModelEvaluatorBuilder.java:151) 
   at org.jpmml.evaluator.LoadingModelEvaluatorBuilder.load(LoadingModelEvaluatorBuilder.java:138) 
   at com.zhenzhe.javacv.JavaCamera2FocusEnabledApp$ImageSaver.run(JavaCamera2FocusEnabledApp.java:556) 
   at com.zhenzhe.javacv.JavaCamera2FocusEnabledApp$1.onImageAvailable(JavaCamera2FocusEnabledApp.java:240) 
   at android.media.ImageReader$1.run(ImageReader.java:947) 
   at android.os.Handler.handleCallback(Handler.java:958) 
   at android.os.Handler.dispatchMessage(Handler.java:99) 
   at android.os.Looper.loopOnce(Looper.java:230) 
   at android.os.Looper.loop(Looper.java:319) 
   at android.os.HandlerThread.run(HandlerThread.java:67)
jye0829 commented 1 month ago

In the meanwhile, I use jpmml-model to run the json format of pmml. But I failed all the time. So I wonder can I use the evaluator to run the xgboost classifier model.jar on the evaluator without using jaxb

vruusmann commented 1 month ago

The LoadingModelEvaluatorBuilder cannot be used on Android, because it attempts to load the PMML XML document using Jakarta XML Binding (JAXB) technology.

You should be using its superclass ModelEvaluatorBuilder instead. It is your choice then how you deliver the org.dmg.pmml.PMML object to its constructor.

So I wonder can I use the evaluator to run the xgboost classifier model.jar on the evaluator without using jaxb

I would personally recommend you to transpile the PMML XML document into a Java class using the JPMML-Transpiler library. Then instantiate this class, and pass this instance to ModelEvaluatorBuilder constructor.

In pseudocode:

# The PMML$12345 class was generated from PMML XML document by JPMML-Transpiler
PMML pmml = new PMML$12345();

Evaluator evaluator = new ModelEvaluatorBuilder(pmml)
  .build();