OCP Java Platform Module System Questions and Answers 1 — Questions and Answers
Question 1: A module named `com.app.main` requires a dependency on the `java.sql` module and needs to make its `com.app.ui` package available for other modules to use. Which of the following `module-info.java` files correctly declares these requirements?
- module com.app.main { imports java.sql; exports com.app.ui; }
- module com.app.main { requires java.sql; opens com.app.ui; }
- module com.app.main { requires java.sql; exports com.app.ui; } (Correct answer)
- module com.app.main { needs java.sql; provides com.app.ui; }
Correct answer: module com.app.main { requires java.sql; exports com.app.ui; }
In a `module-info.java` file, the `requires` keyword is used to declare a dependency on another module, making its exported packages available. The `exports` keyword is used to make the public types within a specific package of the current module accessible to other modules at both compile time and runtime.
Question 2: Consider the following module declarations: ```java // In module com.api module com.api { exports com.api.data; } // In module com.service module com.service { exports com.service.util; // This package contains types from com.api.data in its public method signatures requires com.api; } // In module com.client module com.client { requires com.service; // Code here that uses com.service.util fails to compile } ``` The code in `com.client` fails to compile because it cannot access types from `com.api.data` that are returned by methods in `com.service.util`. What is the best way to fix this issue?
- In `com.client`'s module-info, add `requires com.api;`.
- In `com.service`'s module-info, change `requires com.api;` to `requires transitive com.api;`. (Correct answer)
- In `com.api`'s module-info, change `exports com.api.data;` to `exports com.api.data to com.client;`.
- In `com.service`'s module-info, add `exports com.api.data;`.
Correct answer: In `com.service`'s module-info, change `requires com.api;` to `requires transitive com.api;`.
When a module's public API exposes types from a dependency, it should declare that dependency as `requires transitive`. This creates 'implied readability,' meaning any module that requires `com.service` will now automatically be able to read `com.api` without needing its own explicit `requires` directive. This is the intended mechanism for propagating dependencies through a module graph.
Question 3: A legacy JAR file named `legacy-utils.jar`, which does not contain a `module-info.class` descriptor, is placed on the module path at runtime. How will the Java Platform Module System treat this JAR?
- The application will fail to start because a JAR on the module path must contain a `module-info.class`.
- It will be part of the 'unnamed module' and its packages will be available to all other modules.
- It will be ignored by the module system, and its classes will be unavailable.
- It will be treated as an 'automatic module' with a name derived from the JAR file, and it will export all of its packages. (Correct answer)
Correct answer: It will be treated as an 'automatic module' with a name derived from the JAR file, and it will export all of its packages.
To support migration and backward compatibility, any non-modular JAR placed on the module path becomes an automatic module. The module system derives a module name from the JAR's filename (e.g., `legacy.utils`), and this module automatically exports all of its packages and can read every other module on the path.
Question 4: A developer is building an application that uses a service provider interface. The module `com.app.drawing.api` defines the interface `com.app.drawing.api.Shape`. The module `com.app.drawing.impl` provides an implementation named `com.app.drawing.impl.Circle`. Which set of module directives correctly sets up the service relationship for discovery via `ServiceLoader`?
- In `com.app.drawing.api`: `uses com.app.drawing.api.Shape;` In `com.app.drawing.impl`: `provides com.app.drawing.api.Shape with com.app.drawing.impl.Circle;`
- In `com.app.drawing.api`: `exports com.app.drawing.api;` In `com.app.drawing.impl`: `requires com.app.drawing.api; exports com.app.drawing.impl;`
- In `com.app.drawing.api`: `exports com.app.drawing.api;` In `com.app.drawing.impl`: `requires com.app.drawing.api; provides com.app.drawing.api.Shape with com.app.drawing.impl.Circle;` (Correct answer)
- In `com.app.drawing.api`: `provides com.app.drawing.api.Shape;` In `com.app.drawing.impl`: `uses com.app.drawing.api.Shape with com.app.drawing.impl.Circle;`
Correct answer: In `com.app.drawing.api`: `exports com.app.drawing.api;` In `com.app.drawing.impl`: `requires com.app.drawing.api; provides com.app.drawing.api.Shape with com.app.drawing.impl.Circle;`
The API module must `export` the package containing the service interface. The implementation module must `require` the API module and use the `provides <interface> with <implementation>` clause to register its service implementation. A client module that consumes the service would use the `uses <interface>` directive.
Question 5: A module `com.framework` needs to use reflection at runtime to access all members, including private fields and methods, of classes within the `com.app.model` package from the `com.app` module. The framework does NOT need to compile against any types in `com.app.model`. Which directive in `com.app`'s `module-info.java` provides the necessary access while adhering to the principle of least privilege?
- `exports com.app.model to com.framework;`
- `opens com.app.model;`
- `exports com.app.model;`
- `opens com.app.model to com.framework;` (Correct answer)
Correct answer: `opens com.app.model to com.framework;`
The `opens` keyword is used to permit deep reflection at runtime, allowing access to all members (public, protected, and private). Unlike `exports`, it does not make the package's types available at compile time. A qualified `opens...to` clause is the most restrictive option, granting this powerful capability only to the specified module (`com.framework`), thus following the principle of least privilege.
Question 6: An application is launched with `app.jar` on the module path and a required `lib.jar` on the classpath. The module within `app.jar` does not have any special command-line flags applied. What is the expected outcome at runtime when code in `app.jar` attempts to access a class from `lib.jar`?
- The access will succeed, as the classpath content is automatically available to all modules.
- The access will fail with a `NoClassDefFoundError` or similar error. (Correct answer)
- The access will succeed, but the JVM will issue a warning about an 'unnamed module' being accessed.
- The access will succeed only if `lib.jar` is also an automatic module.
Correct answer: The access will fail with a `NoClassDefFoundError` or similar error.
By default, explicit modules (those on the module path with a `module-info.class`) cannot read from the classpath. The content of the classpath is placed in a special 'unnamed module'. Strong encapsulation in JPMS prevents modules from accessing types in the unnamed module unless permission is explicitly granted via command-line flags like `--add-reads`. Without such flags, the class loading will fail.
A module named `com.app.main` requires a dependency on the `java.sql` module and needs to make its `com.app.ui` package available for other modules to use.
Which of the following `module-info.java` files correctly declares these requirements?