[ 
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)

Reply via email to