21

I'm trying to access the List class from com.sun.tools.javac.util. This works fine with Java 8, but when switching to Java 9 I get the following error: Package 'com.sun.tools.javac.util' is declared in module "jdk.compiler", which does not export it to the unnamed module".

I tried adding requires jdk.compiler; to my module-info file, but this did not solve the issue.

Naman
  • 27,789
  • 26
  • 218
  • 353
bramhaag
  • 628
  • 1
  • 9
  • 24
  • What functionality of the class are you using? – Naman Oct 16 '17 at 15:13
  • 2
    In JDK9 you need to use [`javax.tools`](http://docs.oracle.com/javase/9/docs/api/javax/tools/package-summary.html). Classes from unexported packages are unavailable. – M. le Rutte Oct 16 '17 at 15:14
  • @nullpointer I'm using to for code generation, but I also need other classes from this package – bramhaag Oct 16 '17 at 15:15
  • @M.leRutte using another package is not the solution since they're simply not the same – bramhaag Oct 16 '17 at 15:15
  • 1
    @bramhaag the package has been deprecated in Java 9. you shall migrate to their equivalent implementations which could be depicted looking at your code itself. – Naman Oct 16 '17 at 15:16
  • Well, `com.sun.*` packages have been "forbidden" for a while now since they're elligible for change or even removal (aka deprecation) in every Java version. You still could access them but it's generally not advisable to do so. – Thomas Oct 16 '17 at 15:16
  • @nullpointer I fail to find an equivalent, the compiler is also still using this package internally. – bramhaag Oct 16 '17 at 15:17
  • 5
    I just looked up that class and didn’t see anything that explains why a developer could *need* that list class instead of just using, e.g. `ArrayList` or one of the specialized lists returned by the standard factory methods. – Holger Oct 16 '17 at 15:37
  • 3
    FWIW, this class was written in the 1.2 days by Martin Odersky (designer of Scala). Early versions of Scala's List looked very similar. – Stefan Zobel Oct 16 '17 at 15:47
  • 4
    Comment near the top of the file: "This is NOT part of any supported API. If you write code that depends on this, you do so at your own risk. This code and its internal interfaces are subject to change or deletion without notice." http://hg.openjdk.java.net/jdk9/jdk9/langtools/file/jdk-9+181/src/jdk.compiler/share/classes/com/sun/tools/javac/util/List.java#l48 – Stuart Marks Oct 16 '17 at 17:08

1 Answers1

17

In the longer run, the safe way to be dealing with such situation is to move away from using these internal APIs of the JDK.

One can make use of the jdk.compiler module's APIs as a replacement to the com.sun.tools.javac package.

Defines the implementation of the system Java compiler and its command line equivalent, javac, as well as javah.

Specifically for com.sun.tools.javac.util.List, almost all of its non-overridden, self-defined methods could be derived from the implementation based on the interface java.util.List.


Migration guide's column about Removed java.* APIs state that -

The Java team is committed to backward compatibility. If an application runs in JDK 8, then it will run on JDK 9 as long as it uses APIs that are supported and intended for external use.

These include:

  • JCP standard, java.*, javax.*
  • JDK-specific APIs, some com.sun.*, some jdk.*

Supported APIs can be removed from the JDK, but only with notice. Find out if your code is using deprecated APIs by running the static analysis tool jdeprscan.

Then to add to the highlighted risk above..

Compile Time

Internal APIs that are encapsulated in JDK 9 are not accessible at compile time, but can be made accessible at compile time via the --add-exports command-line option.

In your case :

--add-exports jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED

Run Time

At the runtime, they remain accessible if they were in JDK 8 but in a future release, they will become inaccessible, at which point the --add-exports or --add-opens options can be used to make them accessible at runtime as well.

Michael
  • 41,989
  • 11
  • 82
  • 128
Naman
  • 27,789
  • 26
  • 218
  • 353
  • 3
    These APIs aren't deprecated; they're merely internal interfaces of javac that are now inaccessible by default in JDK 9. Otherwise, yes. – Stuart Marks Oct 16 '17 at 17:10
  • @StuartMarks Agreed. *Internal API* seems a better term than *deprecated*? Just to clarify, I didn't mean `@Deprecated` anyway though. – Naman Oct 16 '17 at 17:13
  • 4
    Yes, *internal* is preferable. None of this stuff has been deprecated. Thanks for updating. – Stuart Marks Oct 16 '17 at 17:16
  • Thanks for the suggestion, @StuartMarks :) – Naman Oct 16 '17 at 17:17
  • where do i type this command "--add-exports jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED"? – motionless570 Dec 25 '21 at 08:57
  • @Derek you need to pass that as a javac argument while compiling and as a JVM argument during runtime. – Naman Dec 26 '21 at 08:37
  • @Osama Jamal, in .idea/compiler.xml if you use IntelliJ Idea or Android Studio (for visibility in source code) and in build.gradle of your module (to work in compile time) – Cool Soft Aug 06 '22 at 13:28