Bug 532283 - --limit-module is not recognized at compile time
Summary: --limit-module is not recognized at compile time
Status: NEW
Alias: None
Product: JDT
Classification: Eclipse Project
Component: Core (show other bugs)
Version: 4.8   Edit
Hardware: PC Windows 10
: P3 major with 1 vote (vote)
Target Milestone: ---   Edit
Assignee: JDT-Core-Inbox CLA
QA Contact:
URL:
Whiteboard: stalebug
Keywords:
Depends on:
Blocks:
 
Reported: 2018-03-11 05:20 EDT by Nir Lisker CLA
Modified: 2023-03-30 19:42 EDT (History)
2 users (show)

See Also:


Attachments
Test case (4.06 KB, application/x-zip-compressed)
2018-03-11 09:32 EDT, Nir Lisker CLA
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description Nir Lisker CLA 2018-03-11 05:20:51 EDT
If --limit-module is used on JDK module 'mod', and a non-JDK module 'mod' is added to the modulepath, the project will compile but not run.
During compile time, the non-JDK module 'mod' will be used (classes which is defines, but are not defined by the JDK module with the same name, will be visible).
During runtime, an error will be thrown for not being able to find classes defined in 'mod'.

From my understanding of JEP 261 and bug 531459 comment 10 compilation should fail as well. Could be related to bug 526110 (I don't quite understand its scope).

Tested versions: 4.8M5 and the March 6th build.

As a side note, I would like to have an "ad-hoc --limit-module" that would work for the above case during runtime as well. This would be a convenient way to swap modules in the JDK, similar to --patch-module, only for modules.
Comment 1 Stephan Herrmann CLA 2018-03-11 09:18:35 EDT
I don't fully follow your description. Can you please attach an small example project with relevant module-info, .classpath and everything needed to reproduce?

Or, when saying "compile", do you actually refer to batch compilation? If so, what exact command line?

When you say "compilation should fail" - what error do you expect to be reported?

For the runtime part, please also include a launch configuration (persisted by defining a "Shared file" location in tab "Common") - or full command line whichever you were using.

TIA
Comment 2 Nir Lisker CLA 2018-03-11 09:32:36 EDT
Created attachment 273080 [details]
Test case
Comment 3 Nir Lisker CLA 2018-03-11 09:46:38 EDT
(In reply to Stephan Herrmann from comment #1)
> I don't fully follow your description. Can you please attach an small
> example project with relevant module-info, .classpath and everything needed
> to reproduce?

Attached an example. Project zjavafx.base contains a javafx.base module.
Project zTest contains a com.ztest module which requires javafx.base. This projects also specifies --limits-modules for the JDK dependency so that javafx.base is removed.

zTest contains the class WhenTest.java which relies on When2.java in project zjavafx.base. There is no compilation or build error after clean and build. However, running the main method gives the error:

Error occurred during initialization of boot layer
java.lang.module.FindException: Module javafx.base not found, required by com.ztest

which is understandable since --limit-modules removed javafx.base. But, I believe that compilation should fail as well since this option is also used in compile time.

> When you say "compilation should fail" - what error do you expect to be
> reported?

Something along the lines of "Module javafx.base cannot be found" or "...has been removed by --limit-module".

Is there any reason for compilation to succeed and runtime to fail?
Comment 4 Stephan Herrmann CLA 2018-03-11 10:14:33 EDT
(In reply to Nir Lisker from comment #3)
> Is there any reason for compilation to succeed and runtime to fail?

You didn't show how you launch the application, so we can't really compare compile time and runtime :)

More fundamentally, you seem to be attempting what JEP 261 handles via --upgrade-module-path, right?

It seems we haven't yet provided any explicit support for --upgrade-module-path, but I'd like to ask, if this is s.t. the user must see, or if we can use the available information from existing classpath attributes etc. and behind the scenes configure compile and runtime as needed.

Wrt compile time, you already gave a (preliminary) answer: just using the "Module properties > Contents" UI you can already configure a conflict-free module graph.

It should be straight forward (I believe) to let JDT/Debug compute a suitable command line for launching, which might translate inclusion of your own javafx.base module into a proper --upgrade-module-path option.

Asked differently: is there a strong reason to represent --upgrade-module-path in the UI?

Thinking aloud some options:
- we could raise a warning/info when a project depends on another project /
  a library that defines a module having the same name as a system module.
- to silence the warning the user could add another flag to the referring
  cp entry in .classpath to signal that the referenced project / library
  upgrades a system module.
- if that cp attribute is set, --limit-modules would no longer be needed
  for this particular module.
- still, --limit-modules on a particular cp entry can be used to filter the
  contents of this particular dependency, without affecting the inclusion
  of a same named module via another path.

Before further diving into details, however, the main question is: do we *need* any of this to surface in the UI? For what purpose?
Comment 5 Nir Lisker CLA 2018-03-11 11:30:46 EDT
(In reply to Stephan Herrmann from comment #4)
> You didn't show how you launch the application, so we can't really compare
> compile time and runtime :)

Well, I just right-clicked on the main method and selected to run it as a Java application. Didn't change anything. Will create the persistent file if needed.

> More fundamentally, you seem to be attempting what JEP 261 handles via
> --upgrade-module-path, right?

I think so. Plainly, I would like to replace JDK modules with my modules (with the same name). Just to be clear, this is not what this bug is strictly about, but it is how I got to it.

> Asked differently: is there a strong reason to represent
> --upgrade-module-path in the UI?
> 
> Thinking aloud some options:
> - we could raise a warning/info when a project depends on another project /
>   a library that defines a module having the same name as a system module.

Related is bug 530697. Shouldn't that just be illegal? Are you suggesting to silently "override"/replace one module with the other? What if more than 2 with the same name are specified?

> --limit-modules on a particular cp entry can be used to filter the
> contents of this particular dependency, without affecting the inclusion
> of a same named module via another path.

From bug 531459 comment 10 I understood this is not correct usage. Anyway, care would need to be taken since only under the JDK/custom image dependency will --limit-modules be converted to --upgrade-module-path in the background, as the latter option is applicable only to system modules.

As another option, what I would find the most intuitive is allowing --patch-module to actually replace one system module with another module (see bug 531459 comment 12).

> Before further diving into details, however, the main question is: do we
> *need* any of this to surface in the UI? For what purpose?

I think it's a tradeoff. Going by the book and adding more UI will let the user be clear about what actually happens in terms of CL, but might be "too many options" and thus confusing. OTOH, computing an --upgrade-module-path from something like --limit-modules might seem intuitive (well, at least to me), but can make people angry as you're doing something they didn't ask for.

I think that in the long run the first option is just safer, even if not simpler.
Comment 6 Stephan Herrmann CLA 2018-03-11 13:10:40 EDT
(In reply to Nir Lisker from comment #5)
> (In reply to Stephan Herrmann from comment #4)
> > Thinking aloud some options:
> > - we could raise a warning/info when a project depends on another project /
> >   a library that defines a module having the same name as a system module.
> 
> Related is bug 530697. Shouldn't that just be illegal? Are you suggesting to
> silently "override"/replace one module with the other? What if more than 2
> with the same name are specified?

Here I was assuming the illegal duplication to be avoided already by use of content filtering on the JRE container.


> > --limit-modules on a particular cp entry can be used to filter the
> > contents of this particular dependency, without affecting the inclusion
> > of a same named module via another path.
> 
> From bug 531459 comment 10 I understood this is not correct usage.

As a JVM argument you're probably right, but as a classpath attribute for JDT we can choose to allow this (and translate appropriately when facing the JVM).

> Anyway,
> care would need to be taken since only under the JDK/custom image dependency
> will --limit-modules be converted to --upgrade-module-path in the
> background, as the latter option is applicable only to system modules.

sure.

> As another option, what I would find the most intuitive is allowing
> --patch-module to actually replace one system module with another module
> (see bug 531459 comment 12).

The purpose of --patch-module (as I understand it) is to replace individual types in a module with your own.  What you suggest, sounds like abusing this for replacing *all* types :)

If a user wants to replace a system module with a variant with fewer classes, then --patch-module would not suffice. Not sure if this is a relevant use case.

> > Before further diving into details, however, the main question is: do we
> > *need* any of this to surface in the UI? For what purpose?
> 
> I think it's a tradeoff. Going by the book and adding more UI will let the
> user be clear about what actually happens in terms of CL, but might be "too
> many options" and thus confusing. OTOH, computing an --upgrade-module-path
> from something like --limit-modules might seem intuitive (well, at least to
> me), but can make people angry as you're doing something they didn't ask for.

That computation could be:
- if a system module is excluded in "Module properties > Content",
- and if a same named module (prj or lib) is on the Module Path
=> then launch the program with this module on the upgrade module path rather than the normal module path.

AFAICS, this would be the only legal interpretation of that situation, so we don't really make an arbitrary choice behind the user's back, we just give necessary permission to the replacing module as needed by the JVM.
 
> I think that in the long run the first option is just safer, even if not
> simpler.

Thanks, let's see what others think.
Comment 7 Nir Lisker CLA 2018-03-18 22:44:06 EDT
(In reply to Stephan Herrmann from comment #6)
> The purpose of --patch-module (as I understand it) is to replace individual
> types in a module with your own.

I went back to do some checking. JavaFX uses an args file, "run.args", with the following content:

--patch-module="javafx.base=/rt/build/modular-sdk/modules/javafx.base"
--patch-module="javafx.controls=rt/build/modular-sdk/modules/javafx.controls"
(etc.)

It is used from the CL with the @ options:

java @run.args -cp "path/to/package" package.Mainclass

and it actually does replace the content of the system module of the name specified on the LHS with the content of module on the path on the RHS. 

I re-read JEP 261 and I think this is intended usage of --patch-module. The packages and resources will be replaced/added, but module-info wouldn't. There is no need to --limit-module (and I think it might just hinder it, unless used with -add-module also...).
Comment 8 Nir Lisker CLA 2018-04-21 11:54:01 EDT
> and it actually does replace the content of the system module of the name
> specified on the LHS with the content of module on the path on the RHS. 

My mistake, the RHS is not a module (it's the same sources, only without module-info), so it does mass-replacement I guess.
Comment 9 Eclipse Genie CLA 2021-04-01 19:28:12 EDT
This bug hasn't had any activity in quite some time. Maybe the problem got resolved, was a duplicate of something else, or became less pressing for some reason - or maybe it's still relevant but just hasn't been looked at yet.

If you have further information on the current state of the bug, please add it. The information can be, for example, that the problem still occurs, that you still want the feature, that more information is needed, or that the bug is (for whatever reason) no longer relevant.

--
The automated Eclipse Genie.
Comment 10 Eclipse Genie CLA 2023-03-30 19:42:10 EDT
This bug hasn't had any activity in quite some time. Maybe the problem got resolved, was a duplicate of something else, or became less pressing for some reason - or maybe it's still relevant but just hasn't been looked at yet.

If you have further information on the current state of the bug, please add it. The information can be, for example, that the problem still occurs, that you still want the feature, that more information is needed, or that the bug is (for whatever reason) no longer relevant.

--
The automated Eclipse Genie.