Skip to content

native-image : @Delete expects all dependencies of target class to be available? #1725

@jaikiran

Description

@jaikiran

Imagine this original class:

package org.myapp;

public class FooBar {
   public void doSomething(org.otherapp.SomeThirdPartyLibClass arg) {
     ....
   }
}

Now imagine this usage of @Delete:

import com.oracle.svm.core.annotate.Delete;
import com.oracle.svm.core.annotate.TargetClass;

@TargetClass(className = "org.myapp.FooBar")
@Delete
public final class Delete_FooBar {
}

So there's a org.myapp.FooBar which I wanted deleted from the native image and I have a @Delete which tries to achieve that. The org.myapp.FooBar has fields/methods which use types that are part of other (third party) libraries. Those libraries aren't present in the classpath of the native-image generation command. When I run the native-image command which looks something like this:

graalvm/graalvm-ce-19.2.0.1/Contents/Home/bin/native-image 
--report-unsupported-elements-at-runtime --initialize-at-build-time= 
-H:InitialCollectionPolicy=com.oracle.svm.core.genscavenge.CollectionPolicy$BySpaceAndTime 
-jar myfoobarapp.jar -J-Djava.util.concurrent.ForkJoinPool.common.parallelism=1 -H:FallbackThreshold=0
 -H:+ReportExceptionStackTraces -H:+PrintAnalysisCallTree 
 -H:Log=registerResource: -H:-AddAllCharsets -H:EnableURLProtocols=http 
 -H:-JNI --no-server -H:-UseServiceLoaderFeature -H:+StackTrace

This runs into an exception:

Fatal error: java.lang.NoClassDefFoundError
	at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
	at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
	at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
	at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
	at java.util.concurrent.ForkJoinTask.getThrowableException(ForkJoinTask.java:598)
	at java.util.concurrent.ForkJoinTask.get(ForkJoinTask.java:1005)
	at com.oracle.svm.hosted.NativeImageGenerator.run(NativeImageGenerator.java:461)
	at com.oracle.svm.hosted.NativeImageGeneratorRunner.buildImage(NativeImageGeneratorRunner.java:310)
	at com.oracle.svm.hosted.NativeImageGeneratorRunner.build(NativeImageGeneratorRunner.java:448)
	at com.oracle.svm.hosted.NativeImageGeneratorRunner.main(NativeImageGeneratorRunner.java:113)
Caused by: java.lang.NoClassDefFoundError: javax/security/jacc/PolicyContextException
	at java.lang.Class.getDeclaredMethods0(Native Method)
	at java.lang.Class.privateGetDeclaredMethods(Class.java:2701)
	at java.lang.Class.getDeclaredMethods(Class.java:1975)
	at com.oracle.svm.hosted.substitute.AnnotationSubstitutionProcessor.handleDeletedClass(AnnotationSubstitutionProcessor.java:437)
	at com.oracle.svm.hosted.substitute.AnnotationSubstitutionProcessor.handleClass(AnnotationSubstitutionProcessor.java:270)
	at com.oracle.svm.hosted.substitute.AnnotationSubstitutionProcessor.init(AnnotationSubstitutionProcessor.java:230)
	at com.oracle.svm.hosted.NativeImageGenerator.createDeclarativeSubstitutionProcessor(NativeImageGenerator.java:875)
	at com.oracle.svm.hosted.NativeImageGenerator.setupNativeImage(NativeImageGenerator.java:824)
	at com.oracle.svm.hosted.NativeImageGenerator.doRun(NativeImageGenerator.java:524)
	at com.oracle.svm.hosted.NativeImageGenerator.lambda$run$0(NativeImageGenerator.java:444)
	at java.util.concurrent.ForkJoinTask$AdaptedRunnableAction.exec(ForkJoinTask.java:1386)
	at java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:289)
	at java.util.concurrent.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1056)
	at java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1692)
	at java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:157)
Caused by: java.lang.ClassNotFoundException: org.otherapp.SomeThirdPartyLibClass
	at java.net.URLClassLoader.findClass(URLClassLoader.java:382)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
	... 15 more
Error: Image build request failed with exit status 1

So it looks like the usage of @Delete expects the classpath to be complete with all the necessary dependencies, even though the target class is really being removed from the native-image? Is there a way the @Delete can work without expecting the whole dependency graph to be avaiable to native image generation?

I'm on Graal VM version 19.2.0.1.

Metadata

Metadata

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions