Skip to content

Convert to named modules for native library access permission #476

@justadreamer

Description

@justadreamer

Background: What Are Named Modules?

Since Java 9, JARs can declare themselves as named modules by including a module-info.java file. This file explicitly declares:

  • The module's name
  • What other modules it depends on
  • What packages it exposes to other modules

Without module-info.java, a JAR is an unnamed module - it just goes on the classpath like traditional Java.

// Example module-info.java
module fiftyone.pipeline.engines.fiftyone {
    requires fiftyone.pipeline.core;
    exports fiftyone.pipeline.engines.fiftyone.flowelements;
}

The Problem

Our LibLoader class calls System.load() to load native libraries. Starting with Java 16+, this is a "restricted method" and produces warnings:

WARNING: java.lang.System::load has been called by ...LibLoader in an unnamed module
WARNING: Use --enable-native-access=ALL-UNNAMED to avoid a warning
WARNING: Restricted methods will be blocked in a future release unless native access is enabled

The warning is not critical for now, but can only be suppressed with: --enable-native-access=ALL-UNNAMED
Problem: This grants native access to ALL JARs - overly permissive and will eventually be deprecated.

Better solution: Name our module, so users can grant access to just our code:
--enable-native-access=fiftyone.pipeline.engines.fiftyone

Dependency Constraint

Named modules can only depend on other named modules. This is contagious to dependencies.

pipeline.engines.fiftyone      ← we want to name this (contains LibLoader)
    ├── pipeline.engines       ← must also be named (dependency)
    └── pipeline.core          ← must also be named (dependency)

Downstream consumers (device-detection, customer code) can stay unnamed - they'll still work.

Think of it as: "Named modules can only see other named modules, but unnamed modules can see everything."

Implementation

Modules to Convert

Add module-info.java to these modules in pipeline-java:

| Module                             | Artifact ID               | Why                            |
|------------------------------------|---------------------------|--------------------------------|
| fiftyone.common                    | pipeline.common           | Dependency of core             |
| fiftyone.caching                   | pipeline.caching          | Dependency of engines          |
| fiftyone.pipeline.core             | pipeline.core             | Dependency of engines          |
| fiftyone.pipeline.engines          | pipeline.engines          | Dependency of engines.fiftyone |
| fiftyone.pipeline.engines.fiftyone | pipeline.engines.fiftyone | Contains LibLoader             |
module fiftyone.pipeline.engines.fiftyone {
    requires fiftyone.pipeline.engines;

    exports fiftyone.pipeline.engines.fiftyone;
    exports fiftyone.pipeline.engines.fiftyone.data;
    exports fiftyone.pipeline.engines.fiftyone.flowelements;
    exports fiftyone.pipeline.engines.fiftyone.flowelements.interop;
}

The exports and requires statements are standard module plumbing for compilation. There is no special directive for native access - the module just needs a name so users can reference it with: --enable-native-access=fiftyone.pipeline.engines.fiftyone

Steps

  • Analyze full dependency tree to identify all modules requiring conversion (see the table above)
  • Create module-info.java for each module with correct requires and exports
  • Update Maven build configuration for module compilation
  • Test on Java 17, 21 with --enable-native-access=fiftyone.pipeline.engines.fiftyone
  • Verify downstream unnamed consumers still work

Documentation Updates

Add to READMEs in pipeline-java, device-detection-java, and device-detection-java-examples:

Native Library Access (Java 16+)

Enable native access for the 51Degrees module:

Command line:

java --enable-native-access=fiftyone.pipeline.engines.fiftyone -jar your-app.jar

Maven exec plugin:

<configuration>
    <arguments>
        <argument>--enable-native-access=fiftyone.pipeline.engines.fiftyone</argument>
        ...
    </arguments>
</configuration>

Acceptance Criteria

  • No warnings when running with --enable-native-access=fiftyone.pipeline.engines.fiftyone
  • Existing functionality preserved
  • Unnamed downstream consumers work without changes
  • Documentation updated with clear instructions

References

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions