DEV Community

loading...
Cover image for How to solve: "Symbol is declared in module X which does not export package Y"

How to solve: "Symbol is declared in module X which does not export package Y"

h3xstream profile image Philippe Arteau Updated on ・3 min read

If you are here, I assume that you have encounter a message like one of these.

Symbol is declared in module 'java.desktop' which does not export package 'sun.awt.image'
Symbol is declared in module 'java.xml' which does not export package 'com.sun.org.apache.xerces.internal.xni.parser'
Symbol is declared in module 'java.base' which does not export package 'sun.net.www.protocol.http'
Enter fullscreen mode Exit fullscreen mode

What is happening?

You accessing a class in a package that was not intended to be used by external library. The class is part of an internal package that is subject to change. When updating the library, it is likely that it will break your application.

These modules restrictions were introduce in Java 9.

Option 1: Long-term fix

If you are working on a project that has long term stability in mind, you should look for an equivalent function that is public. This may required an additional library.

Here is a simple example in Kotlin where Strings.isNullOrEmpty was use by accident. The function call can simply be replace by CharSequence.isNullOrEmpty().

import jdk.internal.joptsimple.internal.Strings.isNullOrEmpty

fun main() {
    print("Enter your name : ")
    val userName = readLine()!!
    if (isNullOrEmpty(userName)) { //FIX: userName.isNullOrEmpty()
        println("Hello, $userName")
    }
}
Enter fullscreen mode Exit fullscreen mode

Example taken from stackoverflow.com

"I know what am doing"

You may still want to use internal API regardless of the recommendation from the compiler. Here are the solution for Java and Kotlin.

Option 2: Java fix

In order to still use the internal API, you will need to pass additional arguments to the compiler (--add-exports ...). This can be configured in your Maven or Gradle build.

Here is an example of Maven configuration:

<build>
    <plugins>
        <plugin>
            <artifactId>maven-compiler-plugin</artifactId>
            <configuration>
                <source>1.9</source>
                <target>1.9</target>
                <compilerArgs>
                    <!-- Few examples ... only pick the ones needed -->
                    <arg>--add-exports</arg><arg>java.xml/com.sun.org.apache.xerces.internal.impl.dtd=ALL-UNNAMED</arg>
                    <arg>--add-exports</arg><arg>java.xml/com.sun.org.apache.xerces.internal.xni.parser=ALL-UNNAMED</arg>
                    <arg>--add-exports</arg><arg>java.base/sun.net.www.protocol.http=ALL-UNNAMED</arg>
                    <arg>--add-exports</arg><arg>jdk.unsupported/sun.misc=ALL-UNNAMED</arg>
                    <arg>--add-exports</arg><arg>java.base/sun.security.ssl=ALL-UNNAMED</arg>
                    <arg>--add-exports</arg><arg>java.base/sun.security.util=ALL-UNNAMED</arg>
                    <arg>--add-exports</arg><arg>java.base/com.sun.net.ssl.internal.ssl=ALL-UNNAMED</arg>
                    <arg>--add-exports</arg><arg>java.base/sun.security.jca=ALL-UNNAMED</arg>
                    <arg>--add-exports</arg><arg>java.base/sun.net.util=ALL-UNNAMED</arg>
                    <arg>--add-exports</arg><arg>java.base/jdk.internal.misc=ALL-UNNAMED</arg>
                    <arg>--add-exports</arg><arg>java.base/sun.security.internal.interfaces=ALL-UNNAMED</arg>
                    <arg>--add-exports</arg><arg>java.base/sun.security.provider.certpath=ALL-UNNAMED</arg>
                    <arg>--add-exports</arg><arg>java.base/sun.security.internal.spec=ALL-UNNAMED</arg>
                    <arg>--add-exports</arg><arg>java.base/sun.security.validator=ALL-UNNAMED</arg>
                    <arg>--add-exports</arg><arg>java.base/sun.security.action=ALL-UNNAMED</arg>
                    <arg>--add-exports</arg><arg>java.base/sun.security.x509=ALL-UNNAMED</arg>
                </compilerArgs>
            </configuration>
        </plugin>
Enter fullscreen mode Exit fullscreen mode

Option 3: Kotlin fix

Kotlin does not have a compiler option to turn off specific module restrictions. You can however add an annotation at the beginning of your file to disable module restriction completely.

@file:Suppress("JAVA_MODULE_DOES_NOT_EXPORT_PACKAGE")

import com.sun.org.apache.xerces.internal.util.SAXInputSource
import com.sun.org.apache.xerces.internal.xni.parser.XMLErrorHandler
import com.sun.org.apache.xerces.internal.xni.parser.XMLParseException
[...]
Enter fullscreen mode Exit fullscreen mode

Conclusion

While those new module restrictions may seems drastic, they are great safe guard that will help long term maintainability. Before adding exception, take the time to investigate if you really need the internal API.

Discussion (1)

pic
Editor guide
Collapse
toxicmushroom profile image
ToxicMushroom

thanks this helped <3