1

I am currently trying to extract from the jdk the preview class files such as java.lang.Record from jrt-fs.jar (in libs folder), but it does not find the preview classes such as Record when iterating over it. This is the code I am using:

Path jrtFsJar = jdk15Home.resolve("lib").resolve("jrt-fs.jar");
jrtFsJarLoader = new URLClassLoader(new URL[] {jrtFsJar.toUri().toURL()});
FileSystem jrtFs = FileSystems.newFileSystem(
    URI.create("jrt:/"), 
    Collections.emptyMap(), 
    jrtFsJarLoader);
Files.walk(jrtFs.getPath("/modules")).forEach(path -> 
   // Here is walks over classes such as "modules/java.base/java/lang/Object.class"
   // but not over "modules/java.base/java/lang/Record.class"
)

I have also tried a more direct approach:

FileSystem fs = FileSystems.getFileSystem(URI.create("jrt:/"));
// Object works, I get the bytes.
byte[] object = Files.readAllBytes(jrtFs.getPath("modules", "java.base",
                                          "java/lang/Object.class"));
// Record fails, NoSuchFile.  
byte[] object = Files.readAllBytes(jrtFs.getPath("modules", "java.base",
                                          "java/lang/Record.class"));

Now when I'm running the exact same jdk with --enable-preview, I can use records.

How do I extract the Record class from the jdk linux/lib? Are the preview class inside of it or should I look for them elsewhere? Do I need a specific flag to access them?

Any help is appreciated.

  • using macOS and placing this code under a test class I could not reproduce with `/Library/Java/JavaVirtualMachines/jdk-15.jdk/Contents/Home/bin/java --enable-preview -p /Users/naman.nigam/Desktop/namannigam/a-bit-of-problemsolving/target/classes -m a.bit.of.problem.solving/edu.bit.problemsolving.basic.AccessTest` – Naman Feb 02 '21 at 17:24
  • Now that you mention it may be the problem is that I am reading the jdk-15 jrt-fs.jar using jdk-9. The problem is that the app I work on is on jdk-9, while I need to analyse all java code including now jdk-15 code. I've updated the bug with the exact code I'm using. – clementbera Feb 03 '21 at 08:53
  • the preview feature support was introduced in JDK starting version 12, so that seems to justify why it would fail for you at present with JDK-9. that said, I am not sure about the compatibility further in terms of the classes that you seek to resolve. i.e with JDK-12, would you be able to identify `Record` or not. (but yeah, if I could give it a try, I would share the result.) – Naman Feb 03 '21 at 09:16
  • 1
    Ok I understood what is happening. As far as I can tell, the JDK can only read the jrt:/ of the runtime jdk (so jdk9 for me) and not from a file from another JDK. So what I'll do instead is to start an OS process which starts JDK-15 and collects the list locally. Thanks for your help. – clementbera Feb 04 '21 at 08:27

1 Answers1

3

When you are running on a JDK that has a jrt file system already, you can access the jrt file system of another JDK much easier.

FileSystem jrtFs = FileSystems.newFileSystem(
    URI.create("jrt:/"), Map.of("java.home", jdk15Home.toString()));
byte[] object = Files.readAllBytes(
    jrtFs.getPath("modules", "java.base", "java/lang/Record.class"));

The built-in file system will create a special class loader for the foreign JDK’s jrt-fs.jar that does not delegate to the parent loader for the classes of this jar. So it does not end up at its own imple­men­tation again.

Since it uses the implementation provided by the other JDK, it will be able to handle newer features or even JDKs using an entirely different data format for its module storage.

Holger
  • 285,553
  • 42
  • 434
  • 765