Index Page : Link
Donate : Link
Medium Blog : Link
Applications : Link

JPMS vs NoClassDefFoundError:
In Java 9 Platform Modular System, JVM will check all dependencies at the beginning only. If any dependent module is missing then JVM won’t start its execution. Hence there is no chance of NoClassDefFoundError in the middle of Program execution.
Demo Program:

Components of moduleA:
A.java
package pack1;
public class A
{
public void m1()
{
System.out.println("Module m1() of moduleA");
}
}
module-info.java
module moduleA
{
exports pack1;
}
Components of moduleB:
B.java
package pack2;
import pack1.A;
public class B
{
public void m2()
{
System.out.println("moduleB accessing members of moduleA");
A a = new A();
a.m1();
}
}
module-info.java
module moduleB
{
requires moduleA;
exports pack2;
}
Components of moduleC:
Test.java
package pack3;
import pack2.B;
public class Test
{
public static void main (String... args)
{
System.out.println("main method");
B b = new B();
b.m2();
}
}
module-info.java
module moduleC
{
requires moduleB;
}
Compilation and Execution:
D:\CodeFactory>javac --module-source-path src -d out -m moduleA,moduleB,moduleC
D:\CodeFactory>java --module-path out -m moduleC/pack3.Test
main method
moduleB accessing members of moduleA
Module m1() of moduleA
If we delete compiled code of module (inside out folder), then JVM will raise error at the beginning only and JVM won’t start program execution.
D:\CodeFactory>java --module-path out -m moduleC/pack3.Test
Error occurred during initialization of boot layer
java.lang.module.FindException: Module moduleC not found
But in Non Modular programming, JVM will start execution and in the middle, it will raise NoClassDefFoundError.
Hence in Java Platform Module System, there is no chance of getting NoClassDefFoundError in the middle of program execution.
Transitive Dependencies (requires with transitive Keyword):
A -> B, B -> C ==> A -> C
This property in mathematics is called Transitive Property.
Student1 requires Material, only for himself, if any other person asking he won’t share.
module student1
{
requires material;
}
Student1 requires material not only for himself, if any other person asking him, he will share it.
module student1
{
requires transitive material;
}
Sometimes module requires the components of some other module not only for itself and for the modules that requires that module also. For this requirement we can use transitive keyword.
The transitive keyword says that “Whatever I have will be given to a module that asks me.”
Case 1:
module moduleA
{
exports pack1;
}
module moduleB
{
requires moduleA;
}
module moduleC
{
requires moduleB;
}

In this case only moduleB is available to moduleC and moduleA is not available. Hence moduleC cannot use the members of moduleA directly.
Case 2:
module moduleA
{
exports pack1;
}
module moduleB
{
requires transitive moduleA;
}
module moduleC
{
requires moduleB;
}

In this both moduleB and moduleA are available to moduleC. Now moduleC can use members of both modules directly.
Case Study:
Assume Modules C1, C2,….C10 requires Module B and Module B requires A.

If we write “requires transitive A” inside module B
module B
{
requires transitive A;
}
Then module A is by default available to C1, C2,.., C10 automatically. Inside every module of C, we are not required to use “requires A” explicitly. Hence transitive keyword promotes code reusability.
Note: Transitive means implied readability i.e., Readability will be continues to the next level.
Demo Program for transitive keyword:

moduleA components:
A.java
package pack1;
public class A
{
public void m1()
{
System.out.println("A.m1() of moduleA");
}
}
module.info.java
module moduleA
{
exports pack1;
}
moduleB components:
B.java
package pack2;
import pack1.A;
public class B
{
public A m2()
{
System.out.println("B.m2() of moduleB");
return new A();
}
}
module-info.java
module moduleB
{
requires transitive moduleA;
exports pack2;
}
moduleC components:
Test.java
package pack3;
import pack2.B;
public class Test
{
public static void main (String... args)
{
System.out.println("Test class main method");
B b = new B();
b.m2().m1();
}
}
module-info.java
module moduleC
{
requires moduleB;
}
D:\CodeFactory>javac --module-source-path src -d out -m moduleA,moduleB,moduleC
D:\CodeFactory>java --module-path out -m moduleC/pack3.Test
Test class main method
B.m2() of moduleB
A.m1() of moduleA
In the above program if we are not using transitive keyword then we will get compile time error
because moduleA is not available to moduleC.
D:\CodeFactory>javac --module-source-path src -d out -m moduleA,moduleB,moduleC
src\moduleC\pack3\Test.java:10: error: A.m1() in package pack1 is not accessible
b.m2().m1();
^
(package pack1 is declared in module moduleA, but module moduleC does not read it)
1 error
Optional Dependencies (Requires Directive with static keyword):
If Dependent Module should be available at compile time but optional at runtime, then such type of dependency is called Otional Dependency. We can specify optional dependency by using static keyword.
Syntax: requires static <modulename>
The static keyword is used to say that, “This dependency check is mandatory at compile time and optional at runtime.”
Eg1:
module moduleB
{
requires moduleA;
}
moduleA should be available at the time of compilation and runtime. It is not optional dependency.
Eg2:
module moduleB
{
requires static moduleA;
}
At the time of compilation moduleA should be available, but at runtime it is optional. i.e., at runtime even moduleA is not available JVM will execute code.
Demo Program for Optional Dependency:

moduleA components:
A.java
package pack1;
public class A
{
public void m1()
{
System.out.println("A.m1() of moduleA");
}
}
module-info.java
module moduleA
{
exports pack1;
}
moduleB components:
Test.java
package pack2;
public class Test
{
public static void main (String... args)
{
System.out.println("Optional dependencies demo!");
}
}
module-info.java
module moduleB
{
requires static moduleA;
}
At the time of compilation both modules should be available. But at runtime, we can run moduleB Test class, even moduleA compiled classes are not available i.e., moduleB having optional dependency with moduleA.
D:\CodeFactory>javac --module-source-path src -d out -m moduleA,moduleB
D:\CodeFactory>java --module-path out -m moduleB/pack2.Test
Optional dependencies demo!
If we remove static keyword and at runtime if we delete compiled classes of moduleA, then we will get error.
// remove static from /src/moduleB/module-info.java
D:\CodeFactory>javac --module-source-path src -d out -m moduleA,moduleB
// delete /out/moduleA folder
D:\CodeFactory>java --module-path out -m moduleB/pack2.Test
Error occurred during initialization of boot layer
java.lang.module.FindException: Module moduleA not found, required by moduleB
Use cases of Optional Dependencies:
Usage of optional dependencies is very common in Programming world.
Sometimes we can develop library with optional dependencies.
- If apache http Client is available use it, otherwise use HttpURLConnection.
- : If oracle module is available use it, otherwise use mysql module.
Why we should do this? For various reasons –
- When distributing a library and we may not want to force a big dependency to the client.
- On the other hand, a more advanced library may have performance benefits, so whatever module client needs, he can use.
- We may want to allow easily pluggable implementations of some functionality. We may provide implementations using all of these, and pick the one whose dependency is found.
Cyclic Dependencies:
If moduleA depends on moduleB and moduleB depends on moduleA, such type of dependency is called cyclic dependency.
Cyclic Dependencies between the modules are not allowed in java 9.
Demo Program:

moduleA components:
module-info.java
module moduleA
{
requires moduleB;
}
moduleB components:
module moduleB
{
requires moduleA;
}
D:\CodeFactory>javac --module-source-path src -d out -m moduleA,moduleB
src\moduleA\module-info.java:3: error: cyclic dependence involving moduleB
requires moduleB;
^
1 error
There may be a chance of cyclic dependency between more than 2 modules also.
moduleA requires moduleB
moduleB requires moduleC
moduleC requires moduleA

Note: In all predefined modules also, there is no chance of cyclic dependency
Qualified Exports:
Sometimes a module can export its package to specific module instead of every module. Then the specified module only can access. Such type of exports are called Qualified Exports.
Syntax:
exports <pack1> to <module1>,<module2>,…
Eg:
module moduleA
{
exports pack1; // to export pack1 to all modules
exports pack1 to moduleB; // to export pack1 only for moduleB
exports pack1 to moduleB,moduleC; // to export pack1 for moduleB,moduleC
}
Demo Program for Qualified Exports:

Components of exportermodule:
A.java:
package pack1;
public class A
{
}
B.java
package pack2;
public class B
{
}
C.java
package pack3;
public class C
{
}
module-info.java
module exportermodule
{
exports pack1;
exports pack2 to moduleA;
exports pack3 to moduleA,moduleB;
}

Components of moduleA:
Test.java
package packA;
import pack1.A;
import pack2.B;
import pack3.C;
public class Test
{
public static void main(String... args)
{
System.out.println("Qualified exports demo");
}
}
module-info.java
module moduleA
{
requires exportermodule;
}
Explanation:
For moduleA, all 3 packages are available. Hence we can compile and run moduleA successfully.
D:\CodeFactory>javac --module-source-path src -d out -m exportermodule,moduleA
D:\CodeFactory>java --module-path out -m moduleA/packA.Test
Qualified exports demo
Components of moduleB:
Test.java
package packB;
import pack1.A;
import pack2.B;
import pack3.C;
public class Test
{
public static void main (String... args)
{
System.out.println("Qualified exports demo");
}
}
module-info.java
module moduleB
{
requires exportermodule
}
Explanation:
For moduleB, only pack1 and pack3 are available. pack2 is not available. But in moduleB we are trying to access pack2 and hence we will get compile time error.
D:\CodeFactory>javac --module-source-path src -d out -m exportermodule,moduleB
src\moduleB\packB\Test.java:3: error: cannot find symbol
import pack2.B;
^
symbol: class B
location: package pack2
1 error
Q. Which of the following directives are valid inside module-info.java:
- requires moduleA;
- requires moduleA,moduleB;
- requires moduleA.pack1;
- requires moduleA.pack1.A;
- requires static moduleA;
- requires transitive moduleA;
- exports pack1;
- exports pack1,pack2;
- exports moduleA;
- exports moduleA.pack1.A;
- exports pack1 to moduleA;
- exports pack1 to moduleA,moduleB;
Answers: 1,5,6,7,11,12
