All 15 Java Platform Module System (JPMS) questions
More in Java Platform Module System (JPMS)
Advertisement
Java › Java Platform Module System (JPMS)

What is the difference between 'exports' and 'opens' in a module-info.java file, and why does reflection-heavy code (like many dependency injection or serialization frameworks) specifically require the latter?

Intermediate

Answer

exports makes a package's public types accessible to other modules at COMPILE time and normal runtime method calls, but does NOT permit deep reflective access (like calling setAccessible(true) to bypass normal access control checks on private members) from outside the module; opens specifically permits this deep reflective access at runtime (needed by frameworks like Spring, Hibernate, or Jackson that use reflection to inspect and manipulate even PRIVATE fields/constructors of your classes, a common technique for dependency injection, ORM mapping, or JSON deserialization) -- a package can be both exported AND opened if it needs regular compile-time access as well as deep reflective access, or a module can use 'opens' without 'exports' if it needs to permit reflection but doesn't want to expose the package for normal compile-time linking.
// module-info.java
module com.example.myapp {
    requires com.fasterxml.jackson.databind;

    exports com.example.myapp.api;           // normal compile-time access for consumers
    opens com.example.myapp.model to com.fasterxml.jackson.databind;  // deep reflection specifically for Jackson
}

// Without 'opens', Jackson's attempt to reflectively access private fields on
// classes in com.example.myapp.model would throw an InaccessibleObjectException at RUNTIME
Real-world example A Spring Boot application using JPA entities in a non-exported package encounters InaccessibleObjectException at runtime when Hibernate attempts reflective field access for ORM mapping, resolved by adding an explicit 'opens' directive for that specific package to Hibernate's module, granting the deep reflective access the ORM framework genuinely needs.

Common follow-ups: Why did the module system designers create this distinction rather than just having a single access-granting directive?;What is 'opens ... to' with a specific target module, versus a plain unqualified 'opens' -- what's the security trade-off between them?