layout | toc_group | link_title | permalink |
---|---|---|---|
docs |
truffle |
Truffle Languages and Instruments Migration to Java Modules |
/graalvm-as-a-platform/language-implementation-framework/migration-to-java-modules/ |
Since version 23.1 Truffle uses languages and instruments primarily as Java modules loaded from the Java VM module path. Loading languages and tools from language or tool homes is still supported for compatibility reasons. However, it is deprecated and will be removed in future versions. The motivations for this change are:
- Truffle should be used the same way on all JDKs.
- Truffle is not a part of the Java VM jimage and is used as a regular JVM VM module path library.
- Loading languages and tools from the module path is much easier for the embedder and works right out of the box with tools like Apache Maven.
- The Java module system guarantees strong encapsulation and reliable configuration.
For general information on migrating to Java modules, please refer to development-with-jdk-9. The Truffle module is distributed in two versions: open Truffle and closed Truffle. The open Truffle exports all API packages in its module descriptor. On the other hand, the closed Truffle does not export API packages in the module descriptor. Instead, it dynamically exports API packages at runtime to modules that provide the language or instrument, as well as to modules that the language or instrument module reads. While the open Truffle is intended for testing and compile-time purposes, the closed Truffle must be used in production. To correctly load a language or instrument as a module, the following migration steps need to be applied:
- Define a named Java module that requires the
org.graalvm.truffle
module. - For each Truffle language provided by this module, register a language provider using the
provides TruffleLanguageProvider with <LanguageClass>Provider
directive. - For each Truffle instrument provided by this module, register an instrument provider using the
provides TruffleInstrumentProvider with <InstrumentClass>Provider
directive. - If a library is exported with a default export lookup enabled using
@GenerateLibrary(defaultExportLookupEnabled = true)
, the generated implementation of theDefaultExportProvider
must be registered in the module descriptor using the provides directive for thecom.oracle.truffle.api.library.provider.DefaultExportProvider
service. If you build your language or instrument usingmx
the provides directive is generated automatically. - If an AOT library is exported using
@ExportLibrary(useForAOT = true)
, the generated implementation of theEagerExportProvider
must be registered in the module descriptor using the provides directive for thecom.oracle.truffle.api.library.provider.EagerExportProvider
service. If you build your language or instrument usingmx
the provides directive is generated automatically. - If your language or instrument already has a module descriptor, make sure that it does not provide any implementation
of a deprecated
com.oracle.truffle.api.library.EagerExportProvider
orcom.oracle.truffle.api.library.DefaultExportProvider
interface in the module descriptor. They must be replaced by thecom.oracle.truffle.api.library.provider.EagerExportProvider
andcom.oracle.truffle.api.library.provider.DefaultExportProvider
. Providing these deprecated interfaces in the module descriptor will cause an error during creation of a module layer on the closed Truffle. - Languages or instruments must not provide JDK services or services from third party libraries in the module descriptor. This is needed to avoid languages getting loaded by the JDK or third parties without the necessary dynamic exports.
- Language dependencies that might be commonly used by Java applications, like ICU4J, should be shadowed to avoid conflicts with modules used by the embedding.
- If the language or instrument does not expose any API, it is recommended to keep the module as encapsulated as possible
and avoid exporting any packages. Otherwise, export the API packages. In the case of internal APIs that are exclusively
utilized by known modules, it is advised to use qualified exports with the syntax
export <package> to <module>
.
Here is a sample module descriptor for the simple language.
module org.graalvm.sl {
requires java.base;
requires java.logging;
requires jdk.unsupported;
requires org.antlr.antlr4.runtime;
requires org.graalvm.truffle;
provides com.oracle.truffle.api.provider.TruffleLanguageProvider with
com.oracle.truffle.sl.SLLanguageProvider;
}