[
https://issues.apache.org/jira/browse/BCEL-373?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17878839#comment-17878839
]
Gary D. Gregory commented on BCEL-373:
--------------------------------------
Data that don't have to be mutable should not, in my opinion. This sounds like
a GraalVM problem to me. Our target is a normal Java VM like OpenJDK. If we
start changing code because of this or that VM vendor, there will be no end to
it.
> Add support for GraalVM
> -----------------------
>
> Key: BCEL-373
> URL: https://issues.apache.org/jira/browse/BCEL-373
> Project: Commons BCEL
> Issue Type: Bug
> Components: Main
> Affects Versions: 6.10.0
> Reporter: Sanel Zukan
> Priority: Major
>
> I'm working on a small tool called "jarbloat" (written in Clojure but should
> work on any JVM language that produces jar files) [1] for inspecting JAR
> files. I'm using BCEL to analyze class dependencies and package names.
> Although I have alternative code for computing package names based on paths,
> sadly, I don't have any alternative for fetching class dependencies outside
> of BCEL.
> Now, jarbloat works fine when compiled usual way (uberjar/fatjar), but when I
> compile it with GraalVM, BCEL code will throw NullPointerException:
> {code:java}
> java.lang.ExceptionInInitializerError
> at
> org.apache.bcel.util.SyntheticRepository.getInstance(SyntheticRepository.java:38)
> at org.apache.bcel.classfile.JavaClass.<init>(JavaClass.java:145)
> at org.apache.bcel.classfile.ClassParser.parse(ClassParser.java:179)
> at
> jarbloat.class_analyzer.BCELAnalyzer.load_class(class_analyzer.clj:64)
> at jarbloat.analyzer$analyze_entry_deps.invokeStatic(analyzer.clj:128)
> at jarbloat.analyzer$analyze_entry_deps.invoke(analyzer.clj:118)
> at jarbloat.analyzer$analyze_jar$fn__706.invoke(analyzer.clj:156)
> at clojure.core$map$fn__4785.invoke(core.clj:2646)
> at clojure.lang.LazySeq.sval(LazySeq.java:40)
> at clojure.lang.LazySeq.seq(LazySeq.java:49)
> at clojure.lang.RT.seq(RT.java:521)
> at clojure.core$seq__4357.invokeStatic(core.clj:137)
> at clojure.core$filter$fn__4812.invoke(core.clj:2700)
> at clojure.lang.LazySeq.sval(LazySeq.java:40)
> at clojure.lang.LazySeq.seq(LazySeq.java:56)
> at clojure.lang.RT.seq(RT.java:521)
> at clojure.core$seq__4357.invokeStatic(core.clj:137)
> at jarbloat.printer$do_print_dot.invokeStatic(printer.clj:13)
> at jarbloat.analyzer$analyze_jar.invokeStatic(analyzer.clj:160)
> at jarbloat.core$handle_args.invokeStatic(core.clj:91)
> at jarbloat.core$_main.invokeStatic(core.clj:105)
> at jarbloat.core$_main.doInvoke(core.clj:99)
> at clojure.lang.RestFn.applyTo(RestFn.java:137)
> at jarbloat.core.main(Unknown Source)
> Caused by: java.lang.NullPointerException
> at [email protected]/java.util.Objects.requireNonNull(Objects.java:208)
> at
> [email protected]/sun.nio.fs.UnixFileSystem.getPath(UnixFileSystem.java:263)
> at [email protected]/java.nio.file.Path.of(Path.java:147)
> at [email protected]/java.nio.file.Paths.get(Paths.java:69)
> at org.apache.bcel.util.ClassPath.getClassPath(ClassPath.java:481)
> at org.apache.bcel.util.ClassPath.<clinit>(ClassPath.java:443)
> {code}
> This happens when I set GraalVM's native-image to use
> _--initialize-at-run-time=org.apache.bcel.util.ClassPath_ argument. Without
> it, GraalVM will complain with the following error:
> {code:java}
> Error: Detected a ZipFile object in the image heap. A ZipFile object contains
> pointers to unmanaged C memory and file descriptors, and these resources are
> no longer available at image runtime. To see how this object got
> instantiated use --trace-object-instantiation=java.util.zip.ZipFile. The
> object was probably created by a class initializer and is reachable from a
> static field. You can request class initialization at image runtime by using
> the option --initialize-at-run-time=<class-name>. Or you can write your own
> initialization methods and call them explicitly from your main entry point.
> Trace: Object was reached by
> reading field org.apache.bcel.util.ClassPath$AbstractZip.zipFile of
> constant
> org.apache.bcel.util.ClassPath$Module@3956260a:
> /opt/graalvm-jdk-17.0.12+8.1/jmods/java.se.jmod
> indexing into array java.lang.Object[]@761be02f:
> [Ljava.lang.Object;@761be02f
> reading field java.util.ArrayList.elementData of constant
> java.util.ArrayList@3eb61e52: [[/modules/jdk.internal.vm.compiler,
> /modules/com.oracle.graal.graal_enterprise,...
> reading field org.apache.bcel.util.ClassPath.paths of constant
> org.apache.bcel.util.ClassPath@2f5aa92f:
> /opt/graalvm-jdk-17.0.12+8.1/lib/modules:/opt/graalvm-jdk-17.0.12+8.1/jmods/java...
> scanning root org.apache.bcel.util.ClassPath@2f5aa92f:
> /opt/graalvm-jdk-17.0.12+8.1/lib/modules:/opt/graalvm-jdk-17.0.12+8.1/jmods/java...
> embedded in
>
> org.apache.bcel.util.SyntheticRepository.getInstance(SyntheticRepository.java:38)
> parsing method
> org.apache.bcel.util.SyntheticRepository.getInstance(SyntheticRepository.java:38)
> reachable via the parsing context
> at static root method.(Unknown Source)
> {code}
> After some digging through the code, I found that BCEL has some variables
> initialized when the class is initialized (e.g. [2], [3], and [4]). I'm
> getting the impression that the problem starts in _ClassPath.getClassPath()_
> [5]. Some values, like _SystemProperties.getJavaHome()_ [6], will be null on
> GraalVM.
> I'm not very familiar with BCEL internals, but after some rough checking
> things, maybe making this [2] repository initialization lazy could solve and
> allowing repository to be null, could solve the issue. Any thoughts?
> Tested with these GraalVM native-image versions:
> {noformat}
> $ /opt/graalvm/bin/native-image --version
> GraalVM 22.0.0.2 Java 17 CE (Java Version 17.0.2+8-jvmci-22.0-b05)
> $ /opt/graalvm-jdk-17.0.12+8.1/bin/native-image --version
> native-image 17.0.12 2024-07-16
> GraalVM Runtime Environment Oracle GraalVM 17.0.12+8.1 (build
> 17.0.12+8-LTS-jvmci-23.0-b41)
> Substrate VM Oracle GraalVM 17.0.12+8.1 (build 17.0.12+8-LTS, serial gc,
> compressed references)
> {noformat}
> [1] https://github.com/sanel/jarbloat
> [2]
> https://github.com/apache/commons-bcel/blob/master/src/main/java/org/apache/bcel/classfile/JavaClass.java#L145
> [3]
> https://github.com/apache/commons-bcel/blob/master/src/main/java/org/apache/bcel/util/SyntheticRepository.java#L38
> [4]
> https://github.com/apache/commons-bcel/blob/master/src/main/java/org/apache/bcel/util/ClassPath.java#L443
> [5]
> https://github.com/apache/commons-bcel/blob/master/src/main/java/org/apache/bcel/util/ClassPath.java#L470
> [6]
> https://github.com/apache/commons-bcel/blob/master/src/main/java/org/apache/bcel/util/ClassPath.java#L481
--
This message was sent by Atlassian Jira
(v8.20.10#820010)