Modules are defined in a file named module-info.java, named a module descriptor. It should be placed in the source-code root:

|-- module-info.java
|-- com
    |-- example
        |-- foo
            |-- Foo.java
        |-- bar
            |-- Bar.java

Here is a simple module descriptor:

module com.example {
    requires java.httpclient;
    exports com.example.foo;
}

The module name should be unique and it is recommended that you use the same Reverse-DNS naming notation as used by packages to help ensure this.

The module java.base, which contains Java’s basic classes, is implicitly visible to any module and does not need to be included.

The requires declaration allows us to use other modules, in the example the module java.httpclient is imported.

A module can also specify which packages it exports and therefore makes it visible to other modules.

The package com.example.foo declared in the exports clause will be visible to other modules. Any sub-packages of com.example.foo will not be exported, they need their own export declarations.

Conversely, com.example.bar which is not listed in exports clauses will not be visible to other modules.