[
https://issues.apache.org/jira/browse/OPENNLP-1954?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=18115825#comment-18115825
]
Kristian Rickert commented on OPENNLP-1954:
-------------------------------------------
Adding dependency - 1937 is subset of this issue. Other work can start though,
but this separation will make the API more natural
> Make OpenNLP jars native-image friendly (reachability metadata, reflection
> fixes, docs, CI smoke test)
> ------------------------------------------------------------------------------------------------------
>
> Key: OPENNLP-1954
> URL: https://issues.apache.org/jira/browse/OPENNLP-1954
> Project: OpenNLP
> Issue Type: Improvement
> Components: Build, Packaging and Test, Documentation
> Reporter: Richard Zowalla
> Priority: Major
> Labels: graalvm, native-image
>
> h2. Description
> OpenNLP is a library, so we don't compile it to native code ourselves.
> Applications that use OpenNLP do that, through the GraalVM
> native-maven-plugin, Quarkus, Spring AOT and similar tools. The goal of this
> ticket is that such an application builds a working image with no extra
> OpenNLP-specific configuration, as long as it only uses built-in components
> and loads models from files or streams.
> Background: dev@ thread "GraalVM native compilation" (Sep 2026): [dev@
> discussion|https://lists.apache.org/thread/5bp2zb15y34wcwo58x6w1ttz7qsnbfts]
> *In scope:* opennlp-api, opennlp-runtime, opennlp-ml-* (without DL),
> opennlp-model-resolver, opennlp-formats.
> *Out of scope (separate proposals if there's demand):*
> * Publishing native binaries of any kind (CLI, gRPC server). These would need
> a LEGAL review first.
> * A native shared library / C API ({{native-image --shared}},
> {{@CEntryPoint}}).
> * Native support for opennlp-dl / ONNX Runtime (JNI). We only document its
> current status.
> * Performance work. Native image improves startup time and memory footprint,
> not peak throughput.
> h2. Known problem areas on main
> # *Loading factories and extensions by class name.* {{ExtensionLoader}},
> {{BaseToolFactory}}, {{TrainerFactory}} and {{DataIndexerFactory}} load
> classes by name. Factory class names also come from model manifests
> ({{BaseModel}}) and from XML feature generator descriptors
> ({{GeneratorFactory}}). Every built-in {{*Factory}}, trainer and
> {{AbstractXmlFeatureGeneratorFactory}} implementation needs to be registered.
> # *Reflective constructors*
> #* {{GenericModelReader}} / {{GenericModelWriter}}: reader and writer class
> looked up by model type
> #* {{ClassPathModelLoader}}: {{modelType.getConstructor(InputStream.class)}}
> #* {{DownloadUtil}}: {{type.getConstructor(Path.class)}}
> #* {{ParallelNegLogLikelihood}}: {{taskClass.getConstructor(...)}}
> #* Where it's cheap, replace these with explicit factories or lambdas (e.g.
> an {{EnumMap}} or {{Function<InputStream, T>}}) instead of adding metadata.
> # *Java serialization.* {{BaseModel}} ({{readObject}}) and {{SvmDoccatModel}}
> ({{ObjectInputStream}}) need serialization metadata, or we document them as
> unsupported.
> # *Snowball stemmers.* {{Among}} uses {{MethodHandles.findVirtual}} on the
> stemmer classes, so we either register those methods or change the generated
> code.
> # *Bundled resources* need a resource config:
> #* stopword lists
> #* {{uax29/*.txt}}
> #* normalizer tables (CaseFolding, confusables, emoji-*)
> #* {{ner-default-features.xml}}, {{pos-default-features.xml}}
> #* {{opennlp.version}}
> # *{{SimpleClassPathModelFinder}}* reads {{jdk.internal.loader.*}} and scans
> the classpath. That can't work in a native image. It should fail fast with a
> clear message: check the {{org.graalvm.nativeimage.imagecode}} system
> property, which avoids a dependency on the Graal SDK. The docs should point
> to file-based model loading instead.
> # *CLI {{ArgumentParser}}* uses {{Proxy.newProxyInstance}}. This is low
> priority because the CLI isn't a target, but proxy metadata for the
> {{*Params}} interfaces is cheap to add.
> h2. Proposed sub-tasks
> # *Reachability metadata.* Add
> {{META-INF/native-image/org.apache.opennlp/<artifactId>/reachability-metadata.json}}
> to each affected module. Generate a baseline with the native-image-agent
> while running the test suite, then trim it by hand to what's actually needed.
> # *Reduce reflection.* Replace reflective constructors in internal code paths
> with explicit factories (item 2 above). Reflection stays only where the class
> name comes from outside, i.e. manifests and descriptors.
> # *Classpath model finder.* Make {{SimpleClassPathModelFinder}} detect
> native-image runtime and fail fast (item 6).
> # *Guard test (JVM).* Add a unit test that fails when a new built-in factory,
> trainer or feature generator is added without a metadata entry, so the
> metadata doesn't silently go stale.
> # *Native smoke test in CI*
> #* Add a {{native}} Maven profile and a non-deployed IT module built with
> {{native-maven-plugin}}.
> #* The test covers sentence detection, tokenization, POS tagging and NER,
> with models loaded from files.
> #* Add a GitHub Actions job on {{graalvm/setup-graalvm}} (CE). It can start
> as non-blocking.
> # *User documentation.* Add a "Using OpenNLP in a native image" section to
> opennlp-docs covering:
> #* what works out of the box
> #* loading models from files or streams instead of classpath scanning
> #* registering custom factories, extensions and feature generators
> #* Java serialization limits
> #* opennlp-dl / ONNX Runtime status
> #* sample {{native-maven-plugin}} config
> #* CE caveats (startup and footprint improve, peak throughput does not)
> h2. Acceptance criteria
> * A sample app using only OpenNLP jars from Maven Central builds with
> {{native-maven-plugin}} and no user-supplied OpenNLP config. The native
> binary correctly runs sentence detection, tokenization, POS tagging and NER
> on models loaded from files.
> * The native smoke test runs in CI.
> * Unsupported paths (classpath model finder, DL module) fail with a clear
> error message and are documented.
> * The documentation is published with the release.
--
This message was sent by Atlassian Jira
(v8.20.10#820010)