Discussion:
Patch-module with dynamic layer creating.
(too old to reply)
Alex Sviridov
2018-10-11 09:57:45 UTC
Permalink
Hi all,

I create ModuleLayer this way

ModuleFinder finder = ModuleFinder.of(dir1, dir2, dir3);
ModuleLayer parent = ModuleLayer.boot();
Configuration cf = parent.configuration().resolve(finder, ModuleFinder.of(), Set.of("myapp"));
ClassLoader scl = ClassLoader.getSystemClassLoader();
ModuleLayer layer = parent.defineModulesWithOneLoader(cf, scl);
Class<?> c = layer.findLoader("myapp").loadClass("app.Main");

And I need for newly created layer make the following:
-patch-module java.xml.ws.annotation=jsr305-3.0.2.jar

Could anyone say, how I can do it, taking into consideration that when I start JVM I don't
know what layers I will create and what patch module I will need to use, so
I can not use for it JVM parameters.
--
Best reg
Alan Bateman
2018-10-11 11:27:18 UTC
Permalink
Post by Alex Sviridov
Hi all,
I create ModuleLayer this way
ModuleFinder finder = ModuleFinder.of(dir1, dir2, dir3);
ModuleLayer parent = ModuleLayer.boot();
Configuration cf = parent.configuration().resolve(finder, ModuleFinder.of(), Set.of("myapp"));
ClassLoader scl = ClassLoader.getSystemClassLoader();
ModuleLayer layer = parent.defineModulesWithOneLoader(cf, scl);
Class<?> c = layer.findLoader("myapp").loadClass("app.Main");
-patch-module java.xml.ws.annotation=jsr305-3.0.2.jar
Could anyone say, how I can do it, taking into consideration that when I start JVM I don't
know what layers I will create and what patch module I will need to use, so
I can not use for it JVM parameters.
The --patch-module option is for patching modules in the boot layer,
there is no API support for patching modules when creating module layers
with the API. If you want to patch modules in custom module layers then
you need a create a ModuleFinder that will find the patched module -
it's not too hard to do, it's essentially scanning the patch locations
to find additional packages and then pre-pending the patch so that
resources are found in the patch before looking in the unpatched module.

-Alan
Alex Sviridov
2018-10-12 12:16:15 UTC
Permalink
Hi Alan

Maybe it is necessary to add possibility to have equal control for boot layer and
other layers. Because layers are graph but at this moment we can do for boot layer
more then for others -> if we work with non boot layers we must use another
solutions -> different solutions within one technology is not good.

For example we could pass something like String[] args when we create custom layer.

Alex
Post by Alan Bateman
Post by Alex Sviridov
Hi all,
I create ModuleLayer this way
ModuleFinder finder = ModuleFinder.of(dir1, dir2, dir3);
ModuleLayer parent = ModuleLayer.boot();
Configuration cf = parent.configuration().resolve(finder, ModuleFinder.of(), Set.of("myapp"));
ClassLoader scl = ClassLoader.getSystemClassLoader();
ModuleLayer layer = parent.defineModulesWithOneLoader(cf, scl);
Class<?> c = layer.findLoader("myapp").loadClass("app.Main");
-patch-module java.xml.ws.annotation=jsr305-3.0.2.jar
Could anyone say, how I can do it, taking into consideration that when I start JVM I don't
know what layers I will create and what patch module I will need to use, so
I can not use for it JVM parameters.
The --patch-module option is for patching modules in the boot layer,
there is no API support for patching modules when creating module layers
with the API. If you want to patch modules in custom module layers then
you need a create a ModuleFinder that will find the patched module -
it's not too hard to do, it's essentially scanning the patch locations
to find additional packages and then pre-pending the patch so that
resources are found in the patch before looking in the u
Alan Bateman
2018-10-12 14:49:56 UTC
Permalink
Post by Alex Sviridov
Hi Alan
Maybe it is necessary to add possibility to have equal control for boot layer and
other layers. Because layers are graph but at this moment we can do for boot layer
more then for others -> if we work with non boot layers we must use another
solutions -> different solutions within one technology is not good.
For example we could pass something like String[] args when we create custom layer.
I don't know if that is really feasible as you would somehow need to
identify the layer and then somehow interpose on the ModuleFinders that
the container creates. Instead, I think it needs the container to create
a ModuleFinder that finds the patched modules. Yes, this means doing
something similar to patch support that the JDK does for the modules in
the boot layer but it would be under the control of the container. It
shouldn't be a lot of code to this do.

-Alan
Alex Sviridov
2018-10-12 15:00:11 UTC
Permalink
I am speaking not only about patch-module but about all possible options:
--add-exports, --add-opens, --patch-module, --add-modules, --add-reads etc.

Agree that "custom" support for them is not a good way.

Alex
Post by Alan Bateman
Post by Alex Sviridov
Hi Alan
Maybe it is necessary to add possibility to have equal control for boot layer and
other layers. Because layers are graph but at this moment we can do for boot layer
more then for others -> if we work with non boot layers we must use another
solutions -> different solutions within one technology is not good.
For example we could pass something like String[] args when we create custom layer.
I don't know if that is really feasible as you would somehow need to
identify the layer and then somehow interpose on the ModuleFinders that
the container creates. Instead, I think it needs the container to create
a ModuleFinder that finds the patched modules. Yes, this means doing
something similar to patch support that the JDK does for the modules in
the boot layer but it would be under the control of the container. It
shouldn't be a lot of code
Alan Bateman
2018-10-12 16:24:05 UTC
Permalink
Post by Alex Sviridov
--add-exports, --add-opens, --patch-module, --add-modules, --add-reads etc.
ModuleLayer defines static variants of the defineModuleXXX methods that
return a Controller object that you can use to do the equivalent of
--add-reads or --add-exports/-add-opens to export/open a package to
specific modules. The equivalent of --add-modules is to add module name
to the set of modules to resolve.

For patching then it does mean writing code and creating your own
ModuleFinder but it shouldn't be too difficult.

-Alan.
Alex Sviridov
2018-10-12 20:57:16 UTC
Permalink
Hi Alan,

Thank you for detailed explanation. It is great that we have API that allows to implement
such features. However, what I suggest is a little different. I am speaking about using
existing code for such features.

I think this way - firstly, we can do write the same code many times. We can, but we
don't want. Secondly if we pass parameters to JPMS via JVM options to configure boot
layer, it would be great if we had possibility to pass the same parameters to configure a
custom layer without writing a line of code and use existing JDK code.

Of course this is my person opinion. It is interesting to hear what other developers think.
Post by Alan Bateman
Post by Alex Sviridov
--add-exports, --add-opens, --patch-module, --add-modules, --add-reads etc.
ModuleLayer defines static variants of the defineModuleXXX methods that
return a Controller object that you can use to do the equivalent of
--add-reads or --add-exports/-add-opens to export/open a package to
specific modules. The equivalent of --add-modules is to add module name
to the set of modules to resolve.
For patching then it does mean writing code and creating your own
ModuleFinder but it shouldn't be too difficult.
-Alan.
--
Alex Svirid
Alan Bateman
2018-10-13 07:43:23 UTC
Permalink
Post by Alex Sviridov
Hi Alan,
Thank you for detailed explanation. It is great that we have API that allows to implement
such features. However, what I suggest is a little different. I am speaking about using
existing code for such features.
I think this way - firstly, we can do write the same code many times. We can, but we
don't want. Secondly if we pass parameters to JPMS via JVM options to configure boot
layer, it would be great if we had possibility to pass the same parameters to configure a
custom layer without writing a line of code and use existing JDK code.
Of course this is my person opinion. It is interesting to hear what other developers think.
I'm skeptical on both the feasibility and desirability of going there.
If a container is creating module layers at runtime then it is arranging
which modules are observable, e.g. it may choose one version of JAX-RS
for one configuration/layer, and another version for another
configuration/layer. In your scenario it may want to patch or augment
one of these modules. I don't think you can easily express this on the
command line as there isn't anything to identify the layer than you want
to adjust. Also module names may not be sufficient in the face of a
container wanting to make available different versions. It's also
possible that a container would want to opt out from this as it would
want full control of which modules to resolve.

-Alan
Alex Sviridov
2018-10-13 07:54:10 UTC
Permalink
Post by Alan Bateman
Post by Alex Sviridov
Hi Alan,
Thank you for detailed explanation. It is great that we have API that allows to implement
such features. However, what I suggest is a little different. I am speaking about using
existing code for such features.
I think this way - firstly, we can do write the same code many times. We can, but we
don't want. Secondly if we pass parameters to JPMS via JVM options to configure boot
layer, it would be great if we had possibility to pass the same parameters to configure a
custom layer without writing a line of code and use existing JDK code.
Of course this is my person opinion. It is interesting to hear what other developers think.
I'm skeptical on both the feasibility and desirability of going there.
If a container is creating module layers at runtime then it is arranging
which modules are observable, e.g. it may choose one version of JAX-RS
for one configuration/layer, and another version for another
configuration/layer. In your scenario it may want to patch or augment
one of these modules. I don't think you can easily express this on the
command line as there isn't anything to identify the layer than you want
to adjust.
I am sorry, maybe I didn't express this very clear: I mean something like this:
ModuleLayer layer = parent.defineModulesWithOneLoader(cf, scl, args); Where args are for example String[] and we pass the same --add-exports, --add-opens, --patch-module,
--add-modules, --add-reads etc that we pass to configure boot layer. The disadvantage of such way
is using String. However, there are two main advantages: 1) no line of code 2) use the same parameters
that we use to configure boot layer - one solution within one technology.
--
Alex S
Alan Bateman
2018-10-13 08:25:34 UTC
Permalink
Post by Alex Sviridov
ModuleLayer layer = parent.defineModulesWithOneLoader(cf, scl, args); Where args are for example String[] and we pass the same --add-exports, --add-opens, --patch-module,
--add-modules, --add-reads etc that we pass to configure boot layer. The disadvantage of such way
is using String. However, there are two main advantages: 1) no line of code 2) use the same parameters
that we use to configure boot layer - one solution within one technology.
I don't think this is the right approach either. It would mean
standardizing what is currently JDK specific command line options. In
addition it impacts Configuration resolve and resolveAndBind because
--add-modules adds to the set of root modules to resolve (also you need
the patched modules to be observable at this time too).

If it helps, I think this is what you need to do:

--add-modules
Add the names of the modules to the root set that you specify to
Configuration resolve and resolveAndBind.

--patch-module
Provide a ModuleFinder that interposes on the unpatched module to
override or augment its resources. This should be the only case where
you need to write a lot of code (mundane rather than hard). There may be
an opportunity to develop this as its own project in the event that
there is wider interest in patching modules.

--add-reads, --add-exports, --add-opens
Are you sure you need these? If you then use the static
ModuleLayer.defineModulesWithOneLoader method to specify the parent
layer as a parameter rather than the receiver. This will return you a
ModuleLayer.Controller object that you can use to do the equivalent of
these CLI options, at least for the cases where the target is a specific
module.

-Alan.

Loading...