19

Using IDEA-EAP for JDK9 development experiments.

I am getting the following error -

Error:(3, 20) java: package jdk.internal.misc is not visible  
(package jdk.internal.misc is declared in module java.base, which does
not export it to module com.jigsaw.npe)

The class definition is as -

package experiment;
import jdk.internal.misc.Unsafe;

public class CompareAndSwap {

    static Unsafe UNSAFE = Unsafe.getUnsafe();
    ...
}

I've tried including a module-info.java file as well inside the module created using the IDE with the following statements -

module com.jigsaw.npe {
    requires java.base;
}

Directory structure now looks as depicted in the picture -

Directory Structure

The IDE though reflects the module-info.java as unused and probably this is the reason that I am not able to define the module com.jigsaw.npe as tried above.

Looking for some help on to how to correctly place the module-info.java and/or anything other than that which I've missed.

Naman
  • 27,789
  • 26
  • 218
  • 353
  • @StefanZobel what exactly does the command do and are there any prerequisite for it? – Naman Mar 01 '17 at 18:20
  • 3
    Your setup is totally fine and this has nothing to do with IntelliJ. I recommend editing the question (and the tags) to remove that part. – Nicolai Parlog Mar 01 '17 at 20:12

2 Answers2

28

The module java.base does not export the package jdk.internal.misc., so the type jdk.internal.misc.Unsafe is not accessible - as a consequence compilation fails.

You can make it export the package by adding the following command line option:

# if you want to access it from com.jigsaw.npe only:
--add-exports java.base/jdk.internal.misc=com.jigsaw.npe
# if you want to access from all code:
--add-exports java.base/jdk.internal.misc=ALL-UNNAMED

You will have to do that when compiling (javac) and when running (java) the code.

Nicolai Parlog
  • 47,972
  • 24
  • 125
  • 255
  • 1
    `--add-exports` does not exist anymore – madduci Nov 02 '17 at 15:07
  • 6
    Yes, it does. Call `java -X` and take a look: `--add-exports /=(,)*` – Nicolai Parlog Nov 02 '17 at 15:41
  • yes as option on command line, it does exist, but if you set java options with --add-exports, it doesn't work, complaining that it's an unknown command line argument – madduci Nov 03 '17 at 06:46
  • Can we add it in maven build somehow ? – Akshay Hazari Mar 30 '21 at 03:34
  • @AkshayHazari Yes, check the documentation for Maven Compiler Plugin (https://maven.apache.org/plugins/maven-compiler-plugin/examples/pass-compiler-arguments.html) and Maven Surefire Plugin (http://maven.apache.org/surefire/maven-surefire-plugin/examples/fork-options-and-parallel-execution.html#Forked_Test_Execution) for how to add command line flags. – Nicolai Parlog Apr 06 '21 at 10:36
  • `--add-exports` worked for me in Java 11 and should still work [as of Java 17](https://docs.oracle.com/en/java/javase/17/migrate/migrating-jdk-8-later-jdk-releases.html#GUID-2F61F3A9-0979-46A4-8B49-325BA0EE8B66), but after upgrading getting the same error as OP. – Martynas Jusevičius Mar 09 '22 at 09:49
  • @NicolaiParlog any reference to where it says the option should be added when running? – Martynas Jusevičius Mar 09 '22 at 09:59
  • 1
    @MartynasJusevičius "The `exports` directive specifies the name of a package to be exported by the current module. For code in other modules, this grants access at compile time and run time..." (JLS §7.7.2 - https://docs.oracle.com/javase/specs/jls/se18/html/jls-7.html#jls-7.7.2) – Nicolai Parlog Mar 24 '22 at 06:48
  • @MartynasJusevičius There is useful information on this in the ["breaking encapsulation" section of JEP 261: Module System](https://openjdk.org/jeps/261). – jewelsea Dec 14 '22 at 21:17
23

Nicolai's answer is correct regarding the techniques necessary to export an otherwise unexported package from the java.base module or from any other module.

But if the goal is to use Unsafe, the way to do so is to use sun.misc.Unsafe which is exported by the jdk.unsupported module. If you're compiling your code for the unnamed module, you needn't do anything special regarding modules to get access to it. If you're compiling code in a module, you need to add

requires jdk.unsupported;

to your module-info.java file.

To use Unsafe you have to do the reflective setAccessible technique to get access to the field, which is the same as you had to do in previous JDK releases:

import sun.misc.Unsafe;

...

Field theUnsafeField = Unsafe.class.getDeclaredField("theUnsafe");
theUnsafeField.setAccessible(true);
Unsafe theUnsafe = (Unsafe)theUnsafeField.get(null);

Even though Unsafe is in the jdk.unsupported module, this technique is supported in JDK 9, in accordance with JEP 260.

Naman
  • 27,789
  • 26
  • 218
  • 353
Stuart Marks
  • 127,867
  • 37
  • 205
  • 259
  • What about the `warning: Unsafe is internal proprietary API and may be removed in a future release`? Aren't these two same in functionality? – Gayan Weerakutti May 29 '18 at 13:59
  • 1
    @reversiblean No, the "internal proprietary API" warning is actually a different warning. It's been issued by javac since before the module system -- at least I see it when compiling with JDK 7 or JDK 8. Thus, it has nothing to do with module accessibility. It's issued because javac can see that the program is accessing types in the `sun.*` namespace which are internal proprietary APIs, subject to change. – Stuart Marks May 29 '18 at 22:47
  • Yeah I understand. What I meant was, are `jdk.internal.misc.Unsafe` and `sun.misc.Unsafe` same despite the differences in accessibility? – Gayan Weerakutti May 30 '18 at 06:42
  • 3
    No, they're different. `sun.misc.Unsafe` is in the `jdk.unsupported` module, and it *is* exported. `jdk.internal.misc.Unsafe` is in the `java.base` module, and it is *not* exported. `sun.misc.Unsafe` is a minimal subset of the internal one. The idea is to expose the minimal set of unsafe APIs that are in actual use by existing external libraries and frameworks. As public, supported, replacement APIs are added, APIs will be removed from `sun.misc.Unsafe`. The `jdk.internal.misc.Unsafe` continues to be evolved, but it is truly for internal use only. – Stuart Marks May 31 '18 at 00:49