From alan.bateman at oracle.com Wed Oct 8 17:39:32 2025 From: alan.bateman at oracle.com (Alan Bateman) Date: Wed, 8 Oct 2025 18:39:32 +0100 Subject: ModuleLayer for java.base only In-Reply-To: <8916454.NyiUUSuA9g@lintel> References: <8916454.NyiUUSuA9g@lintel> Message-ID: <22971ee5-2327-4964-9250-cc0c3b35a2ea@oracle.com> On 08/10/2025 06:19, Jaroslav Tulach wrote: > Dear JPMS experts! > > I am currently working at Enso developing runtime for _dual representation > (visual and textual) programming language_ [Enso](https://urldefense.com/v3/__https://github.com/enso-org/__;!!ACWV5N9M2RV99hQ!MSZoD63gQltbiD0s6RtcgnXj1LJG0hqBQb84MygtZ7LKRGpELc0ZURO2QOh0lZjT8PhyJ4QCjYOv2G3AvcdF32JDTpk$ > enso/). Enso uses JVM for its operating system interoperability - as such we > are packaging our runtime, as well as Enso libraries as modular JAR files. > Basically we need a _modular runtime container_ with JPMS... > > And here comes the question: Is there a way to create `ModuleLayer` for just > `java.base`? > > Enso runtime obviously needs many other JDK & co. modules. However I don't > want to expose them to the Enso library module JARs (possibly coming from 3rd > party sources) - I'd like them to use only `java.base` and not randomly poke > around for other Enso runtime module JAR files. > > Is there a way to do it? I failed to find it. Googling it out yields no > relevant results and I don't like the idea of chatting with an AI. I'd rather > talk to the experts - hence I am writing to you! > > - I can get `ModuleLayer.boot()` - but that contains too many modules - for > example `org.enso.runner` & co. which I' do not want to expose > - I can get `ModuleLayer.empty()` - but that one is a bit "too empty" > - I tried to create own layer with `ModuleLayer.empty()` as parent and put > `ModuleFinder.ofSystem()` and `java.base` module in... > - but I am getting various errors related to classloaders - "java.base must > be loaded by system classloader" - etc. > - in short: I haven't found a way to get thru and construct `java.base` only > layer > > How that is supposed to work? How do I create a `ModuleLayer` with just > `java.base` and control what the Enso library JARs can access? Can I control > that regardless of how the JVM was initialized? There must a a way, right? Or > am I asking for too much encapsulation? I think what you are looking for is to create the Configuration for a child layer in a way that "hides" all but java.base from the modules in the parent configuration. There isn't a way to do this as resolution time. That is, if the configuration for the parent/boot has java.base, enso, and apache.foo (used by enso) then there is no way to have resolution fail if a user module requires enso or requires apache.foo. Who creates the configuration for the child layer? Can it process the Configuration and fail if any module in the configurations reads a module other than java.base? -Alan From michal at kleczek.org Wed Oct 8 18:06:13 2025 From: michal at kleczek.org (=?utf-8?Q?Micha=C5=82_K=C5=82eczek?=) Date: Wed, 8 Oct 2025 20:06:13 +0200 Subject: ModuleLayer for java.base only In-Reply-To: <22971ee5-2327-4964-9250-cc0c3b35a2ea@oracle.com> References: <8916454.NyiUUSuA9g@lintel> <22971ee5-2327-4964-9250-cc0c3b35a2ea@oracle.com> Message-ID: > On 8 Oct 2025, at 19:39, Alan Bateman wrote: > > > > On 08/10/2025 06:19, Jaroslav Tulach wrote: >> >> How that is supposed to work? How do I create a `ModuleLayer` with just >> `java.base` and control what the Enso library JARs can access? Can I control >> that regardless of how the JVM was initialized? There must a a way, right? Or >> am I asking for too much encapsulation? > I think what you are looking for is to create the Configuration for a child layer in a way that "hides" all but java.base from the modules in the parent configuration. There isn't a way to do this as resolution time. That is, if the configuration for the parent/boot has java.base, enso, and apache.foo (used by enso) then there is no way to have resolution fail if a user module requires enso or requires apache.foo. > > Who creates the configuration for the child layer? Can it process the Configuration and fail if any module in the configurations reads a module other than java.base? Another approach would be to have only a closed ?bootstrap" module in module path. It would provide main class, initialize a module layer with all Enzo modules and their dependencies, and pass execution to it. Since bootstrap module does not export anything and is closed, having it in a boot layer would be harmless. The downside is that with such setup there is no way to package Enzo and its dependencies in runtime image generated by jpackage. ? Michal From michal at kleczek.org Thu Oct 9 06:29:16 2025 From: michal at kleczek.org (=?utf-8?Q?Micha=C5=82_K=C5=82eczek?=) Date: Thu, 9 Oct 2025 08:29:16 +0200 Subject: ModuleLayer for java.base only In-Reply-To: <47855697.fMDQidcC6G@lintel> References: <8916454.NyiUUSuA9g@lintel> <22971ee5-2327-4964-9250-cc0c3b35a2ea@oracle.com> <47855697.fMDQidcC6G@lintel> Message-ID: > On 8 Oct 2025, at 20:54, Jaroslav Tulach wrote: > > On st?eda 8. ??jna 2025 20:06:13, st?edoevropsk? letn? ?as, Micha? K?eczek > wrote: >>> On 8 Oct 2025, at 19:39, Alan Bateman wrote: >>> >>> On 08/10/2025 06:19, Jaroslav Tulach wrote: >>>> How that is supposed to work? How do I create a `ModuleLayer` with just >>>> `java.base` and control what the Enso library JARs can access? Can I >>>> control that regardless of how the JVM was initialized? There must a a >>>> way, right? Or am I asking for too much encapsulation? >>> >>> I think what you are looking for is to create the Configuration for a >>> child layer in a way that "hides" all but java.base from the modules in >>> the parent configuration. There isn't a way to do this as resolution >>> time. That is, if the configuration for the parent/boot has java.base, >>> enso, and apache.foo (used by enso) then there is no way to have >>> resolution fail if a user module requires enso or requires apache.foo. >>> >>> Who creates the configuration for the child layer? Can it process the >>> Configuration and fail if any module in the configurations reads a module >>> other than java.base? >> Another approach would be to have only a closed ?bootstrap" module in module >> path. > > Thanks for your reply, Micha?. > > This solution might work for Enso application and yes, I am considering to go > this route. E.g. to alter boootstrap path to > > >> ... provide main class, initialize a module layer with all Enzo >> modules and their dependencies, and pass execution to it. > > However, Enso isn't just an application, but a language component embeddable > into other Java applications. In such situation Enso isn't in control of the > JVM bootstrap and cannot perform this kind of equilibristic. If you make the embedding application link to only the Enso bootstrap module would solve the issue, wouldn?t it? Encapsulating internals of Enso can be achieved by simply putting it in a single module and not exporting anything. (Or you can use ?export ? to ?? if you really need multi-module Enso) So I understand your real goal is to insulate users of Enso from versions of its dependencies. In case of embedding Enso it is then responsibility of the embedding application - it has to make sure its own dependencies do not interfere with modules it loads. ? Michal From michal at kleczek.org Thu Oct 9 06:29:16 2025 From: michal at kleczek.org (=?utf-8?Q?Micha=C5=82_K=C5=82eczek?=) Date: Thu, 9 Oct 2025 08:29:16 +0200 Subject: ModuleLayer for java.base only In-Reply-To: <47855697.fMDQidcC6G@lintel> References: <8916454.NyiUUSuA9g@lintel> <22971ee5-2327-4964-9250-cc0c3b35a2ea@oracle.com> <47855697.fMDQidcC6G@lintel> Message-ID: > On 8 Oct 2025, at 20:54, Jaroslav Tulach wrote: > > On st?eda 8. ??jna 2025 20:06:13, st?edoevropsk? letn? ?as, Micha? K?eczek > wrote: >>> On 8 Oct 2025, at 19:39, Alan Bateman wrote: >>> >>> On 08/10/2025 06:19, Jaroslav Tulach wrote: >>>> How that is supposed to work? How do I create a `ModuleLayer` with just >>>> `java.base` and control what the Enso library JARs can access? Can I >>>> control that regardless of how the JVM was initialized? There must a a >>>> way, right? Or am I asking for too much encapsulation? >>> >>> I think what you are looking for is to create the Configuration for a >>> child layer in a way that "hides" all but java.base from the modules in >>> the parent configuration. There isn't a way to do this as resolution >>> time. That is, if the configuration for the parent/boot has java.base, >>> enso, and apache.foo (used by enso) then there is no way to have >>> resolution fail if a user module requires enso or requires apache.foo. >>> >>> Who creates the configuration for the child layer? Can it process the >>> Configuration and fail if any module in the configurations reads a module >>> other than java.base? >> Another approach would be to have only a closed ?bootstrap" module in module >> path. > > Thanks for your reply, Micha?. > > This solution might work for Enso application and yes, I am considering to go > this route. E.g. to alter boootstrap path to > > >> ... provide main class, initialize a module layer with all Enzo >> modules and their dependencies, and pass execution to it. > > However, Enso isn't just an application, but a language component embeddable > into other Java applications. In such situation Enso isn't in control of the > JVM bootstrap and cannot perform this kind of equilibristic. If you make the embedding application link to only the Enso bootstrap module would solve the issue, wouldn?t it? Encapsulating internals of Enso can be achieved by simply putting it in a single module and not exporting anything. (Or you can use ?export ? to ?? if you really need multi-module Enso) So I understand your real goal is to insulate users of Enso from versions of its dependencies. In case of embedding Enso it is then responsibility of the embedding application - it has to make sure its own dependencies do not interfere with modules it loads. ? Michal From alan.bateman at oracle.com Thu Oct 9 10:07:17 2025 From: alan.bateman at oracle.com (Alan Bateman) Date: Thu, 9 Oct 2025 11:07:17 +0100 Subject: ModuleLayer for java.base only In-Reply-To: <3165226.BEx9A2HvPv@lintel> References: <8916454.NyiUUSuA9g@lintel> <22971ee5-2327-4964-9250-cc0c3b35a2ea@oracle.com> <3165226.BEx9A2HvPv@lintel> Message-ID: On 08/10/2025 20:11, Jaroslav Tulach wrote: > From a rationalistic perspective, I am looking for something very different: > > I'd like to start from scratch - e.g. `ModuleLayer.empty()` and built > something on top of it myself. E.g. create a layer with > `ModuleFinder.ofSystem()` where I include only some JDK modules - like > `java.base` (but certainly not `org.graalvm.collections`). > > Why that isn't possible? > > Is there a technical problem in creating multiple layers that would all > contain `java.base`? > > Or I am just first one who's asking for a feature like this? There can only be one instance of java.base in the runtime, in the same way that there is one java.lang.Object class. You are right that Configuration.empty() and ModuleLayer.empty() are not interesting outside of creating the boot layer or tests. It is possible to start with `--limit-modules java.base` so that the boot layer only contains java.base but you cannot stack module layers that contain the platform modules. There are technical and non-technical issues that prevent the java.* name space being used by custom class loaders, and it's not possible to give away control of the boot or platform class loaders without introducing major security + integrity risk. The original requirements for Project Jigsaw did envisage allowing some means to augment the set of platform modules at runtime but it hasn't been a priority to work on. The mundane cases that have been important is the dynamic loading of the java.instrument and java.management modules, something that is done in a very limited and controlled manner in response to commands that load tool agents. As regards your desire to hide Enso, and the modules that it uses, from applications then it is something that has come once or twice, usually in the context of some container/application server that wants to hide its dependences from applications that it launches. The module system does not provide this type of isolation. -Alan -------------- next part -------------- An HTML attachment was scrubbed... URL: