How Do Ignition Modules Load Third-Party Libraries?

Karen Mitchell6 min read
HMI / SCADAOther ManufacturerTutorial / How-to
Licensed PE Working through this on a live machine? A Maine-licensed engineer can take it from here — included with IMD hardware, by the hour for everything else. Book an engineer

What the screen is telling you: a custom feature can disappear, fail to initialize, or leave dependent tags unusable even while the controller and network remain healthy. When the module's Java classes load but their native dependency does not, troubleshoot the Gateway runtime before changing tag addresses or driver settings.

Which library-loading approach fits this module?

Two configurations can make the dependency available, but only one avoids repeating work after an Ignition update.

Approach Location or setting Effect Decision
Copy libraries into the Ignition installation /usr/local/bin/ignition/lib on the reported Linux installation The Gateway can find the files, but an Ignition update overwrites the directory and removes the added libraries. Useful only as a temporary diagnostic.
Package Java dependencies in the module Inside the module package Keeps appropriately licensed .jar files with the module and protects them from installation-directory replacement. Preferred for ordinary Java dependencies.
Extract packaged native dependencies to a persistent directory A directory included in java.library.path through ignition.conf Keeps .so or .dll files outside the overwritten installation library folder. Recommended for Gateway-scoped native dependencies.
Dynamically add a JAR through the module hook classloader The module hook classloader and its .addJarFile() method obtained through reflection Can load Java archives dynamically, but requires careful class-reference ordering and does not by itself solve native-library placement. Reserve for cases that cannot package the JAR normally.

Use the packaged-and-extracted design for native dependencies. It gives the module ownership of its files while ignition.conf gives the Gateway JVM a stable search location. Modifying ignition.conf applies to Gateway-scoped dependencies; it is not a general solution for code running in other scopes.

Why does the JAR load while the native library fails?

A .jar and a native library pass through different loaders. The module classloader resolves Java classes from packaged archives. The JVM and operating-system native loader resolve compiled platform binaries such as Linux .so files or Windows .dll files. Putting the JAR in the module therefore does not automatically expose its native companion.

The native binary must land in a directory named by the Gateway process's java.library.path. The operating-system loader must also be able to resolve any native libraries that binary itself requires. A correct file location cannot compensate for a binary built for the wrong operating system, processor architecture, or application binary interface.

Treat this as two separate gates:

  1. Confirm that the module classloader can resolve the Java dependency from the module package.
  2. Confirm that the Gateway process can resolve the associated native binary and its native dependency chain.

How should the native files be deployed?

Ignition has no built-in module mechanism that automatically extracts native libraries. Implement extraction in the module's startup handling, and make the destination a stable directory that is not replaced by an Ignition update.

  1. Review the third-party license before redistributing either the .jar or native binaries. Add required notices or acknowledgements to the module's EULA.
  2. Package the required Java archive and platform-native files with the module. Keep platform variants distinguishable so the startup logic selects the correct file rather than loading an arbitrary binary.
  3. Select a persistent extraction directory outside /usr/local/bin/ignition/lib. The Gateway service account needs permission to create or replace the extracted file and permission to read it at runtime.
  4. Add that directory to java.library.path in ignition.conf. Preserve existing entries when editing the property; the module may not be the only component using the current search paths.
  5. Extract the native file during module startup before any Java class attempts to initialize or call the native dependency.
  6. Restart the Gateway process after changing ignition.conf, because the JVM receives the property when its process starts.

If module startup can run more than once, make extraction repeatable. Compare the packaged and installed artifact before replacement, write complete files before exposing them to the loader, and avoid leaving a partially written native binary after an interrupted startup.

How do you trace the failure from screen to controller?

The tag may be right; the binding may only be reporting a failed upstream module. Trace the display in the same order that data reaches it.

Check Location What the result means
Screen binding and displayed quality Operator-facing project A valid binding with unusable data moves the investigation upstream; changing the address first can hide the real fault.
Underlying tag value and quality Gateway tag system Healthy unrelated tags indicate that the broad Gateway-to-controller path still operates.
Custom module or driver state Gateway status and logs A startup failure associated with Java or native loading points to packaging, search-path, permission, or binary compatibility.
Controller communication Driver and controller diagnostics Healthy communication separates a module-runtime failure from a network or controller outage.
Effective native search path Gateway JVM configuration The extraction directory must appear in the effective java.library.path, not merely exist on disk.
  1. Record the screen symptom without editing the binding.
  2. Open the underlying tag and compare its quality with tags supplied by unaffected drivers or modules.
  3. Inspect Gateway startup diagnostics for the first library-loading failure rather than later secondary errors.
  4. Verify that the native file exists in the configured extraction directory and is readable by the Gateway service account.
  5. Confirm that the configured path belongs to the Gateway process and that the native binary matches its operating system and architecture.
  6. After restart, exercise the custom module function that actually invokes the native code; a successful module install alone does not prove that the native entry points can load.

What classloading pitfalls recur?

Loading a JAR dynamically through the module hook classloader introduces an ordering constraint. Obtain the classloader's .addJarFile() method through reflection and add the archive before Ignition resolves classes that directly reference its contents. Keep those dependent classes behind an indirect call from the module lifecycle methods; an eager field, method signature, or initialization path can trigger class resolution too early.

That technique changes the Java classpath only. A JAR that wraps native code still needs its .so or .dll extracted into a directory available through java.library.path.

Other recurring faults are operational: placing files back in an update-managed directory, replacing the entire native path instead of adding a directory, extracting after dependent code initializes, installing a platform-incompatible binary, overlooking a native binary's own dependencies, or testing only module installation rather than the function that crosses into native code.

How do you verify upgrade-safe operation?

  1. Restart the Gateway and confirm that the module reaches its normal running state without a library-loading failure.
  2. Confirm that the extraction directory appears in the effective java.library.path.
  3. Invoke the exact module feature that uses the native library, then verify the associated tag quality, screen value, and controller communication.
  4. Perform the applicable Ignition update procedure and confirm that the persistent native directory remains intact.
  5. Restart again and repeat the native function test. This proves that the solution survives both the update and a clean JVM start.

FAQ

Why does my Ignition module work until an update?

Files copied into /usr/local/bin/ignition/lib are inside an update-managed location and can be overwritten. Extract native files to a persistent directory and add that directory to java.library.path through ignition.conf.

Why does Ignition find the JAR but not the .so or .dll?

The module classloader handles the .jar, while the JVM and operating system load .so and .dll files through the native search path. The native file and its dependency chain must be available to the Gateway process.

How do I verify an Ignition native-library fix?

Restart the Gateway, confirm the extraction directory is in the effective java.library.path, and invoke the module function that enters native code. Finish by checking the affected tag quality, operator-screen value, and controller communication after the restart.

Back to blog