Add Java 9+ module support (JPMS) for jlink compatibility

pull/196/head
Chris Conlon 2026-02-04 17:02:23 -07:00
parent cb3ea5893e
commit ebf46c1200
4 changed files with 160 additions and 2 deletions

View File

@ -225,6 +225,51 @@ on the current release):
```
### Java 9+ Module Support (JPMS)
---------
wolfCrypt JNI/JCE supports the Java Platform Module System (JPMS) introduced
in Java 9. This enables use with `jlink` for creating custom, minimal Java
runtimes.
**Module Information:**
- Module name: `com.wolfssl.wolfcrypt`
- Exported packages: `com.wolfssl.wolfcrypt`, `com.wolfssl.provider.jce`
- Service provider: `java.security.Provider` (WolfCryptProvider)
**Conditional Compilation:**
The `module-info.java` is conditionally compiled based on the JDK version used
to build:
| JDK Used to Build | Resulting JAR |
|-------------------|---------------|
| Java 8 | Standard JAR (no module-info.class) |
| Java 9+ | Modular JAR (includes module-info.class) |
When building with Java 8, the `module-info.java` is automatically excluded
from compilation, and the resulting JAR works as a standard classpath JAR.
**Using with jlink:**
When built with Java 9+, the wolfCrypt JNI/JCE JAR can be used with `jlink` to
create a custom Java runtime that includes the wolfCrypt module:
```
$ jlink \
--module-path lib/wolfcrypt-jni.jar:$JAVA_HOME/jmods \
--add-modules com.wolfssl.wolfcrypt \
--output custom-runtime \
--no-header-files \
--no-man-pages
$ ./custom-runtime/bin/java --list-modules
```
**Note:** The native wolfCrypt JNI shared library (`libwolfcryptjni.so/dylib`)
must still be available on the native library path at runtime.
### Example / Test Code
---------

View File

@ -23,6 +23,7 @@
<!-- set properties for this build -->
<property name="src.dir" value="src/main/java/" />
<property name="src.java9.dir" value="src/java9/" />
<property name="jni.dir" value="jni/include/" />
<property name="lib.dir" value="lib/" />
<property name="build.dir" value="build" />
@ -48,6 +49,18 @@
<property environment="env" />
<!-- Detect Java 9+ for module-info.java compilation -->
<condition property="isJava9Plus">
<not>
<or>
<equals arg1="${ant.java.version}" arg2="1.5"/>
<equals arg1="${ant.java.version}" arg2="1.6"/>
<equals arg1="${ant.java.version}" arg2="1.7"/>
<equals arg1="${ant.java.version}" arg2="1.8"/>
</or>
</not>
</condition>
<!-- Detect if running on Windows host -->
<condition property="isWindows">
<os family="windows" />
@ -161,8 +174,24 @@
</copy>
</target>
<!-- Compile module-info.java for Java 9+ module support.
Only runs when building with Java 9 or later. When building with
Java 8 or earlier, this target is skipped and the resulting JAR
will be a standard (non-modular) JAR file. -->
<target name="compile-module-info" if="isJava9Plus"
description="Compile module-info.java for Java 9+ (skipped on Java 8)">
<javac srcdir="${src.java9.dir}"
destdir="${build.dir}"
release="9"
modulepath="${build.dir}"
includeantruntime="false">
<include name="module-info.java"/>
</javac>
<echo message="Compiled module-info.java for Java 9+ module support"/>
</target>
<!-- create JAR with ONLY JNI classes, not to be used with JCE -->
<target name="jar-jni" depends="compile-nativeheaderdir, compile-javah">
<target name="jar-jni" depends="compile-nativeheaderdir, compile-javah, compile-module-info">
<jar jarfile="${lib.dir}/wolfcrypt-jni.jar">
<manifest>
<attribute name="Implementation-Title"
@ -174,12 +203,13 @@
</manifest>
<fileset dir="${build.dir}">
<include name="com/wolfssl/wolfcrypt/*.class"/>
<include name="module-info.class"/>
</fileset>
</jar>
</target>
<!-- create JAR with JNI and JCE classes, use this when wanting JCE -->
<target name="jar-jce" depends="compile-nativeheaderdir, compile-javah">
<target name="jar-jce" depends="compile-nativeheaderdir, compile-javah, compile-module-info">
<jar jarfile="${lib.dir}/wolfcrypt-jni.jar" basedir="${build.dir}">
<manifest>
<attribute name="Implementation-Title"

38
pom.xml
View File

@ -69,4 +69,42 @@
</plugin>
</plugins>
</build>
<!-- Profile for Java 9+ module support.
Automatically activates when building with JDK 9 or later.
Compiles module-info.java and includes it in the JAR. -->
<profiles>
<profile>
<id>java9-module</id>
<activation>
<jdk>[9,)</jdk>
</activation>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.11.0</version>
<executions>
<!-- Compile module-info.java with Java 9 release -->
<execution>
<id>compile-module-info</id>
<phase>compile</phase>
<goals>
<goal>compile</goal>
</goals>
<configuration>
<release>9</release>
<compileSourceRoots>
<compileSourceRoot>${project.basedir}/src/java9</compileSourceRoot>
</compileSourceRoots>
<multiReleaseOutput>false</multiReleaseOutput>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
</project>

View File

@ -0,0 +1,45 @@
/* module-info.java
*
* Copyright (C) 2006-2025 wolfSSL Inc.
*
* This file is part of wolfSSL.
*
* wolfSSL is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* wolfSSL is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
*/
/**
* wolfCrypt JNI/JCE Module
*
* This module provides:
* - JNI bindings to the native wolfCrypt cryptography library
* (com.wolfssl.wolfcrypt)
* - A JCE provider implementation (com.wolfssl.provider.jce)
*
* Note: This module-info.java is only compiled when building with Java 9+.
* When building with Java 8, this file is excluded and the resulting JAR
* will be a standard (non-modular) JAR that works on the classpath.
*/
module com.wolfssl.wolfcrypt {
/* Required modules */
requires java.logging;
/* Export public API packages */
exports com.wolfssl.wolfcrypt;
exports com.wolfssl.provider.jce;
/* Register wolfJCE as a security provider */
provides java.security.Provider
with com.wolfssl.provider.jce.WolfCryptProvider;
}