Study guide
10.1 Module Architecture and module-info.java Declarations
Oracle Java SE 21 Developer 1Z0-830
Track your progress as you read
Finished sections get a check mark.
1 Chapter 1: Java Basics, Primitive Types, and Operators
1.1 Program Structure, Primitives, Literals, Scopes, and var 1.2 Operators, Precedence, and Type Casting 1.3 Strings, Text Blocks, and StringBuilder 1.4 Date and Time APIs (java.time)
2 Chapter 2: Controlling Program Flow & Pattern Matching
2.1 Conditional Logic: if-else and Ternary Operators 2.2 Switch Statements and Switch Expressions 2.3 Pattern Matching for switch and instanceof 2.4 Loops and Branching Statements
3 Chapter 3: Object-Oriented Design & Class Architecture
3.1 Class Declarations, Constructors, and Object Lifecycle 3.2 Encapsulation and Access Modifiers 3.3 Inheritance, Method Overriding, and Polymorphism 3.4 Abstract Classes and Interfaces 3.5 Nested, Inner, Local, and Anonymous Classes 3.6 Method Overloading, Overload Resolution, and Varargs
4 Chapter 4: Modern Java Data Modeling: Records, Enums, and Sealed Types
4.1 Java Records, Canonical/Compact Constructors, and Component Accessors 4.2 Java Enums: Fields, Methods, and Abstract Constant-Specific Behavior 4.3 Sealed Classes and Interfaces: permits, final, non-sealed, and Hierarchy Architecture 4.4 Advanced Record Patterns (JEP 440), Nested Deconstruction, and Sealed Hierarchy Exhaustiveness
5 Chapter 5: Exception Handling and Annotations
5.1 Exception Hierarchy: Checked vs. Unchecked Exceptions 5.2 Exception Handling: try, catch, finally, and Multi-Catch 5.3 Resource Management: try-with-resources and AutoCloseable 5.4 Custom Exceptions and Best Practices 5.5 Java Annotations: Built-in, Meta-Annotations, and Custom Types
6 Chapter 6: Generics and the Collections Framework
6.1 Generics Fundamentals and Generic Methods 6.2 Wildcards, Type Bounds, and Type Erasure 6.3 Core Collections: Lists, Sets, Queues, and Maps 6.4 Sequenced Collections in Java 21 6.5 Sorting, Comparable, and Comparator 6.6 Arrays: Creation, Multidimensional Forms, and the Arrays Utility Class
7 Chapter 7: Functional Programming & Lambda Expressions
7.1 Built-in Functional Interfaces in java.util.function 7.2 Lambda Expressions, Variable Scopes, and Effectively Final 7.3 Method References: Four Varieties and Edge Cases 7.4 Working with java.util.Optional
8 Chapter 8: The Stream API and Data Pipelines
8.1 Stream Creation and Intermediate Operations 8.2 Terminal Operations and Reductions 8.3 Advanced Collectors, Grouping, Partitioning, and Teeing 8.4 Primitive Streams and Parallel Stream Processing
9 Chapter 9: Concurrency, Multithreading, and Virtual Threads
9.1 Thread Fundamentals, Creation, and Lifecycle 9.2 Thread Safety, Synchronization, and the Java Memory Model 9.3 Concurrency Utilities: ExecutorService, Callable, and Future 9.4 Concurrent Collections, Atomics, and Explicit Locks 9.5 Virtual Threads in Java 21 (Carrier Threads, Pinning, and Best Practices)
10 Chapter 10: The Java Platform Module System (JPMS)
10.1 Module Architecture and module-info.java Declarations 10.2 Module Directives: requires, exports, opens, provides, and uses 10.3 Modular Compilation, Packaging, and CLI Execution 10.4 Module Types, Migration Strategies, ServiceLoader SPI, and JLink
11 Chapter 11: Java I/O, NIO.2, and Object Serialization
11.1 Classic Java I/O Streams and Readers/Writers 11.2 Java NIO.2 File API: Path, Paths, and File System Operations 11.3 Advanced NIO.2 Stream Operations and Directory Traversal 11.4 Java Object Serialization and Record Serialization
12 Chapter 12: Implementing Localization and Internationalization
12.1 Locales and Resource Bundles 12.2 Formatting and Parsing Numbers, Currencies, Dates, Times, and Messages
10.1 Module Architecture and module-info.java Declarations
Key Takeaways Explain This Topic AI
Project Jigsaw restructured the monolithic JDK standard library and runtime into discrete, cohesive modules to enforce strong encapsulation, reliable configuration, and minimal runtime footprints.
The foundational module java.base is implicitly required by every Java module without explicit declaration, exporting essential platform packages including java.lang, java.util, and java.io.
A module descriptor is defined in a root-level module-info.java file using contextual (restricted) keywords like module, open, requires, and exports, which remain valid variable and method identifiers in standard Java code.
Access in JPMS requires both readability (module-to-module graph relationship established via requires) and accessibility (type/member level visibility in an exported package).
An open module permits deep reflective access at runtime to all its private and public types for all other modules, whereas standard named modules strictly encapsulate all unexported and non-opened packages against both compilation and reflection.
Last updated: September 2026
Module Architecture and module-info.java Declarations
Prior to Java 9, Java applications and the Java Virtual Machine itself suffered from architectural limitations rooted in a flat, unencapsulated runtime model. The Java Platform Module System (JPMS) , developed under Project Jigsaw (JSR 376) and codified in Java SE 9 through Java SE 21, established a standardized modular system for the Java platform and application code. For the Oracle Certified Professional: Java SE 21 Developer (1Z0-830) exam, understanding module descriptors, encapsulation boundaries, contextual keywords, readability versus accessibility, and the special status of java.base is foundational.
1. Project Jigsaw Motivations and Core Goals
For over two decades, Java applications relied on two primary deployment and execution mechanisms: the Classpath and monolithic archive files like rt.jar (the runtime JAR file containing the entire standard Java library, often exceeding 60 MB). This legacy architecture exhibited several critical flaws:
Classpath Fragility ("JAR Hell" / "Classpath Hell") :
The runtime classpath is an ordered list of directories and JAR archives. If a required class is missing, the JVM fails at runtime with a NoClassDefFoundError or ClassNotFoundException only when that specific class is first referenced during execution.
If two JAR files contain classes with identical fully qualified names (package and class name), the JVM arbitrarily loads whichever class appears earlier in the classpath string, causing silent runtime incompatibilities and non-deterministic bugs.
Weak Encapsulation Across Package Boundaries :
Standard Java access modifiers ( public , protected , package-private, and private ) lacked a mechanism to expose a public class to helper packages within the same library without exposing it to all external consumers on the classpath.
Developers frequently accessed unstable internal implementation APIs (such as sun.misc.Unsafe or com.sun.* ), creating tight coupling to specific JDK vendor internals that hindered JVM evolution and security hardening.
Monolithic JDK Runtime Footprint :
Small devices, embedded hardware, and microservice cloud containers were forced to bundle the entire Java standard library, including desktop GUI stacks ( java.desktop / AWT / Swing) and legacy enterprise packages, even if only basic console or HTTP logging functionality was needed.
Core JPMS Architectural Goals
Reliable Configuration : Modules explicitly declare their dependencies on other modules. The JVM verifies the presence and consistency of the entire dependency graph at startup, failing immediately with descriptive errors if dependencies are missing or if cyclic dependencies exist.
Strong Encapsulation : A package in a module is completely hidden and inaccessible to other modules unless explicitly exported. Public classes and methods within unexported packages cannot be accessed at compile time, and runtime reflection ( java.lang.reflect ) cannot penetrate private members without explicit permission.
Scalable Platform : The JDK standard library itself is partitioned into modular units ( java.base , java.sql , java.logging , java.desktop , etc.), enabling custom, stripped-down runtime images via jlink .
2. Readability vs. Accessibility
One of the most essential conceptual foundations for the 1Z0-830 exam is the distinction between Readability and Accessibility : +-----------------------------------------------------------------------------+
- | READABILITY |
- | - Module-to-Module graph relationship |
- | - Established when Module A declares 'requires Module B;' |
- | - Without readability, Module A cannot resolve ANY types declared in B |
- +-----------------------------------------------------------------------------+
- +
- +-----------------------------------------------------------------------------+
- | ACCESSIBILITY |
- | - Package and Type/Member visibility relationship |
- | - Established when Module B 'exports' package P, AND type T is 'public', |
- | AND the target member in T is 'public' (or 'protected' to subclasses) |
- +-----------------------------------------------------------------------------+
- ||
- \/
- +-----------------------------------------------------------------------------+
- | LEGAL CODE ACCESS AT RUNTIME |
- | Code in Module A can access type T in package P of Module B if and only |
- | if BOTH Readability AND Accessibility are fully satisfied! |
- +-----------------------------------------------------------------------------+
- The Accessibility Truth Matrix
Scenario Module Readability ( requires ) Package Exported ( exports ) Type Modifier Resulting Access
Case 1 Module A requires Module B Module B exports com.b.api public class Service Permitted (Compile-time and runtime)
Case 2 Module A requires Module B Package com.b.internal NOT exported public class Helper Blocked (Compile error / IllegalAccessError )
Case 3 Module A does NOT require Module B Module B exports com.b.api public class Service Blocked (Module A cannot read Module B)
Case 4 Module A requires Module B Module B exports com.b.api class Secret (package-private) Blocked (Standard Java access control applies)
3. The Core Foundation: java.base
The java.base module is the foundational root of the entire Java module graph. It exports core platform packages and possesses unique architectural rules:
Implicit Readability : Every Java module implicitly requires java.base . You do not need to declare requires java.base; in your module descriptor.
Explicit Declaration : Explicitly writing requires java.base; is syntactically valid and compiles normally; it simply restates the dependency the compiler would have added anyway. Writing requires transitive java.base; , however, is a compile-time error .
Zero Dependencies : java.base does not require any other module; it sits at the root of the acyclic dependency graph.
Essential Packages Included in java.base :
- java.lang , java.lang.invoke , java.lang.reflect
- java.util , java.util.concurrent , java.util.function , java.util.stream
- java.io , java.nio , java.nio.file , java.nio.channels
- java.math , java.net , java.time , java.time.format
- java.security , java.text
Note
Other standard JDK modules like java.sql (JDBC), java.logging (java.util.logging), java.xml (DOM/SAX parsing), and java.desktop (AWT/Swing) are not in java.base and must be explicitly declared with requires directives when used.
4. Module Descriptors: module-info.java Syntax and Structure
A module is defined by creating a module descriptor file named strictly module-info.java .
File Placement and Compilation Rules
Root Placement : module-info.java must be placed in the root directory of the module's source hierarchy (directly above all package subdirectories), not inside any package.
Compiled Output : Compiling module-info.java yields module-info.class located at the root of the output classes directory or modular JAR archive.
One Descriptor per Module : Each module contains exactly one module-info.java descriptor.
Module Naming Conventions :
Module names follow reverse-DNS naming conventions (e.g., com.oracle.cert.orders , org.example.finance ).
Valid characters in module names match standard Java identifier rules joined by periods ( . ): letters, numbers, and underscores.
Hyphens ( - ) are legal in JAR file names on the file system, but cannot be used in module names inside module-info.java because hyphens are minus subtraction operators in Java syntax. Project Source Tree Structure:
- src/
- └── com.example.orders/ <-- Module root directory
- ├── module-info.java <-- Module descriptor at root
- └── com/
- └── example/
- └── orders/
- ├── OrderProcessor.java
- └── model/
- └── Order.java
- Minimal Module Declaration Example // In src/com.example.orders/module-info.java
- module com.example.orders {
- // Implicitly requires java.base;
- exports com.example.orders;
- exports com.example.orders.model;
- }
- 5. Contextual (Restricted) Keywords in JPMS
To ensure backward compatibility with pre-Java 9 codebases, the tokens used in module-info.java are contextual keywords (also called restricted keywords). They are treated as keywords only inside a module-info.java file .
Contextual Keyword Purpose inside module-info.java Legal as variable/method in standard .java ?
- module Declares a named module Yes (e.g., int module = 10; )
- open Declares an open module Yes (e.g., public void open() {} )
- requires Declares a module dependency Yes (e.g., boolean requires = true; )
- exports Exports a package to consumers Yes (e.g., String exports = "data"; )
- opens Opens a package for reflection Yes (e.g., int opens = 0; )
- uses Declares a service interface consumption Yes (e.g., void uses(int count) {} )
- provides Declares a service provider implementation Yes (e.g., int provides = 42; )
- with Pairs with provides to specify provider class Yes (e.g., record with() {} )
- to Restricts exports or opens to target modules Yes (e.g., String to = "user"; )
- transitive Modifier on requires for implied readability Yes (e.g., boolean transitive = false; )
static Modifier on requires for compile-time optional Yes (Existing strict keyword) // Legal regular Java class demonstrating contextual keyword coexistence
package com.example.demo;
- public class ContextualKeywordsDemo {
- public static void main(String[] args) {
- int module = 101;
- String exports = "orders";
- boolean requires = true;
- System.out.println("Module ID: " + module + ", export: " + exports + ", req: " + requires);
- }
- public void open(String to, int with) {
- // 'open', 'to', and 'with' are valid parameter and method names
- }
- }
- 6. Standard Named Modules vs. Open Modules
JPMS strictly enforces encapsulation against both standard compilation/linking and reflective access ( java.lang.reflect ). However, enterprise frameworks (such as Spring, Hibernate, Jackson, and JUnit) rely heavily on reflection to inspect and mutate private fields, invoke private constructors, and inject dependencies.
Java provides two levels of module open-configuration:
- 1. Standard Explicit Named Module
- Declared with the standard module keyword: module com.example.service {
- exports com.example.service.api;
// Unexported packages are completely encapsulated against compilation AND reflection!
}
At compile time: Only types in exported packages are accessible.
At runtime reflection: Calling Field.setAccessible(true) or Method.setAccessible(true) on non-public types or unexported packages throws java.lang.reflect.InaccessibleObjectException .
- 2. Open Module ( open module )
- Declared by prefixing open before module : open module com.example.entities {
- requires java.sql;
- exports com.example.entities.dto;
// All packages in this module are automatically open for runtime deep reflection!
}
Compile-Time Behavior : Public types are accessible to other modules only if explicitly exported using exports . Unexported packages remain inaccessible to javac during compilation.
Runtime Reflection : All packages within the open module are opened for deep reflection to all other modules. Frameworks can invoke setAccessible(true) on private fields and constructors across the entire module.
Syntax Constraint : An open module cannot contain individual opens directives inside its body. Attempting to write an opens statement inside an open module causes a compile-time error .
Module Encapsulation Comparison Matrix
- Capability / Property Standard Named Module ( module ) Open Module ( open module )
- Compile-Time Access Exported packages only Exported packages only
- Runtime Standard Access Exported packages only Exported packages only
Runtime Deep Reflection ( setAccessible ) Only explicitly opened packages ( opens ) All packages across the module
- Allows opens directive in body? Yes (e.g., opens pkg; ) No (Compile-time error)
- Allows exports directive in body? Yes Yes
- Primary Use Case Secure business logic, APIs, libraries Entity modules, domain models, Spring/Hibernate models