git clone https://github.com/tpalkot/java9jigsaw.git
you will be on a detached head - this is okay
git checkout Step1
Note dependency on java logging
export JAVA_HOME=/usr/libexec/java_home -v 9
javac -d moduleConsumer/target/classes moduleConsumer/src/com/consumer/Consumer.java
jar cf moduleConsumer/target/consumerModule.jar -C moduleConsumer/target/classes .
Note Logging warn and sysout messages
java -cp moduleConsumer/target/consumerModule.jar com.consumer.Consumer
du -sh moduleConsumer/target/consumerModule.jar
du -sh /Library/Java/JavaVirtualMachines/jdk1.8.0_40.jdk/Contents/Home/jre/
mkdir -p moduleConsumer/src/com.consumer;
mv moduleConsumer/src/com moduleConsumer/src/com.consumer/com;
vi moduleConsumer/src/com.consumer/module-info.java
module com.consumer {
}
Notice output dir of mods/com.consumer
javac -d moduleConsumer/target/mods/com.consumer moduleConsumer/src/com.consumer/com/consumer/Consumer.java moduleConsumer/src/com.consumer/module-info.java
notice error with loggging
- comment it out of Consumer.java
 - Compile again
 
If you are behind, you can skip to this step with git clean -f -d git checkout Step2
java --module-path moduleConsumer/target/mods -m com.consumer/com.consumer.Consumer
- Add dependency on java logging java --list-modules
 - Export Consumer class so it can be accessed
 
vi moduleConsumer/src/com.consumer/module-info.java
module com.consumer {
    exports com.consumer;
    requires java.logging;
}
mkdir moduleConsumer/target/mlib
jar --create --file moduleConsumer/target/mlib/com.consumer@1.0.jar --module-version=1.0 -C moduleConsumer/target/mods/com.consumer/ .
- new argument -p is module path
 - new argument -m is -m [/] java -p moduleConsumer/target/mlib/ -m com.consumer/com.consumer.Consumer
 
ls ${JAVA_HOME}/bin
${JAVA_HOME}/bin/jlink --module-path $JAVA_HOME/jmods:moduleConsumer/target/mlib/ --add-modules com.consumer --output consumerapp
consumerapp/bin/java --list-modules
consumerapp/bin/java com.consumer.Consumer
- look at size of executable du -sh consumerapp/
 - compared to size of java 8 JRE du -sh /Library/Java/JavaVirtualMachines/jdk1.8.0_40.jdk/Contents/Home/jre/
 
If you are behind, you can skip to this step with git clean -f -d git checkout Step3
- ServiceInterface project
 - ServiceImplementation project
 - Consumer uses ServiceInterface
- ServiceLoader
 
 
mkdir -p moduleService/src/com.service/com/service
vi moduleService/src/com.service/com/service/MyService.java
package com.service;
public interface MyService {
    void printMessage();
}
vi moduleService/src/com.service/module-info.java
module com.service {
    exports com.service;
}
javac -d moduleService/target/mods/com.service moduleService/src/com.service/com/service/MyService.java moduleService/src/com.service/module-info.java;
mkdir moduleService/target/mlib;
jar --create --file moduleService/target/mlib/com.service@1.0.jar --module-version=1.0 -C moduleService/target/mods/com.service/ .;
mkdir -p moduleImplementer/src/com.implementer/com/implementer
vi moduleImplementer/src/com.implementer/com/implementer/MyServiceImplementer.java
package com.implementer;
import com.service.MyService;
public class MyServiceImplementer implements MyService{
    public void printMessage(){
        System.out.println("MyServiceImplementer says Hello World");
    }
    public void secretPublicMethod(){
        System.out.println("You found my secret");
    }
}
vi moduleImplementer/src/com.implementer/module-info.java
module com.implementer {
    requires com.service;
    exports com.implementer;
}
mkdir -p moduleImplementer/src/META-INF/services/
echo "com.implementer.MyServiceImplementer" > moduleImplementer/src/META-INF/services/com.services.MyService
javac --module-path moduleService/target/mlib/ -d moduleImplementer/target/mods/com.implementer moduleImplementer/src/com.implementer/com/implementer/MyServiceImplementer.java moduleImplementer/src/com.implementer/module-info.java;
mkdir moduleImplementer/target/mlib;
jar --create --file moduleImplementer/target/mlib/com.implementer@1.0.jar --module-version=1.0 -C moduleImplementer/target/mods/com.implementer/ . moduleImplementer/src/META-INF/services/com.services.MyService;
jar --update --file moduleImplementer/target/mlib/com.implementer@1.0.jar --module-version=1.0 -C moduleImplementer/src/ META-INF/services/com.services.MyService;
vi moduleConsumer/src/com.consumer/com/consumer/Consumer.java
package com.consumer;
import java.util.logging.Logger;
import java.util.ServiceLoader;
import com.service.MyService;
public class Consumer {
    private final static Logger LOGGER = Logger.getLogger(Consumer.class.getName());
    public static void main(String[] args) {
    
        Consumer c = new Consumer();
        c.doSomething();
        LOGGER.warning("In constructor");
    }
    
    public void doSomething(){
        System.out.println("consumer in doSomething()");
        
        ServiceLoader<MyService> myServiceLoader = ServiceLoader.load(MyService.class);
        MyService myService = myServiceLoader.iterator().next();
        myService.printMessage();
        //com.implementer.MySeviceImplementer implementer = (com.implementer.MySeviceImplementer)myService;
    }
    
}
vi moduleConsumer/src/com.consumer/module-info.java
module com.consumer {
    exports com.consumer;
    requires java.logging;
    requires com.service;
    uses com.service.MyService;
    requires com.implementer;
}
rm -rf consumerapp;
javac --module-path moduleConsumer/target/mlib/:moduleService/target/mlib/:moduleImplementer/target/mlib/ -d moduleConsumer/target/mods/com.consumer moduleConsumer/src/com.consumer/com/consumer/Consumer.java moduleConsumer/src/com.consumer/module-info.java;
jar --create --file moduleConsumer/target/mlib/com.consumer@1.0.jar --module-version=1.0 -C moduleConsumer/target/mods/com.consumer/ .;
java --module-path moduleConsumer/target/mlib/:moduleService/target/mlib/:moduleImplementer/target/mlib/ -m com.consumer/com.consumer.Consumer;
${JAVA_HOME}/bin/jlink --module-path $JAVA_HOME/jmods:moduleConsumer/target/mlib/:moduleService/target/mlib/:moduleImplementer/target/mlib/ --add-modules com.consumer,com.service,com.implementer --output consumerapp;
consumerapp/bin/java com.consumer.Consumer
vi moduleService/src/com.service/com/service/SecretService.java
package com.service;
public interface SecretService {
    void message();
    public static SecretService getService(){
        return new com.service.impl.SecretServiceImpl();
    }
}
mkdir moduleService/src/com.service/com/service/impl/;
vi moduleService/src/com.service/com/service/impl/SecretServiceImpl.java
package com.service.impl;
import com.service.SecretService;
public class SecretServiceImpl implements SecretService{
    public void message(){
        System.out.println("Secret message");
    }
}
javac $(find moduleService/src/ -name *.java) -d moduleService/target/mods/com.service
jar --create --file moduleService/target/mlib/com.service@1.0.jar --module-version=1.0 -C moduleService/target/mods/com.service .;
change consumer: vi moduleConsumer/src/com.consumer/com/consumer/Consumer.java com.service.SecretService.getService().message();
javac --module-path moduleConsumer/target/mlib/:moduleService/target/mlib/:moduleImplementer/target/mlib/ -d moduleConsumer/target/mods/com.consumer moduleConsumer/src/com.consumer/com/consumer/Consumer.java moduleConsumer/src/com.consumer/module-info.java;
jar --create --file moduleConsumer/target/mlib/com.consumer@1.0.jar --module-version=1.0 -C moduleConsumer/target/mods/com.consumer/ .;
java --module-path moduleConsumer/target/mlib/:moduleService/target/mlib/:moduleImplementer/target/mlib/ -m com.consumer/com.consumer.Consumer;