Combining -classpath and module-info?

classic Classic list List threaded Threaded
6 messages Options
Reply | Threaded
Open this post in threaded view
|

Combining -classpath and module-info?

Stephan Herrmann
I recently noticed that compilers start to ignore -classpath as soon
as module-info (.java or .class) is found during the compile.
(Incidentally, javac and Eclipse compiler agree in this).

Using a trivial test class this works:
$ javac -classpath junit4.jar -d bin/ src/pkg/TestJUnit4.java

This doesn't (cannot resolve any types from junit4.jar):
$ javac -classpath junit4.jar -d bin/ src/pkg/TestJUnit4.java src/module-info.java

Similarly if -sourcepath is used or module-info.class exists in bin/ .

In my reading, JEP 261 explicitly allows this situation, but before I fix this
on our side, I'd like to know whether this *is* a bug or intended behavior.

thanks,
Stephan
Reply | Threaded
Open this post in threaded view
|

Re: Combining -classpath and module-info?

Alan Bateman
On 07/11/2017 18:56, Stephan Herrmann wrote:

> I recently noticed that compilers start to ignore -classpath as soon
> as module-info (.java or .class) is found during the compile.
> (Incidentally, javac and Eclipse compiler agree in this).
>
> Using a trivial test class this works:
> $ javac -classpath junit4.jar -d bin/ src/pkg/TestJUnit4.java
>
> This doesn't (cannot resolve any types from junit4.jar):
> $ javac -classpath junit4.jar -d bin/ src/pkg/TestJUnit4.java
> src/module-info.java
The module you are compiling doesn't read the unnamed module. You can't
write "requires $CLASSPATH" for example.

If you add `--add-reads <module>=ALL-UNNAMED` to the command line then
it should compile.

-Alan
Reply | Threaded
Open this post in threaded view
|

Re: Combining -classpath and module-info?

Stephan Herrmann
On 07.11.2017 21:43, Alan Bateman wrote:

> On 07/11/2017 18:56, Stephan Herrmann wrote:
>> I recently noticed that compilers start to ignore -classpath as soon
>> as module-info (.java or .class) is found during the compile.
>> (Incidentally, javac and Eclipse compiler agree in this).
>>
>> Using a trivial test class this works:
>> $ javac -classpath junit4.jar -d bin/ src/pkg/TestJUnit4.java
>>
>> This doesn't (cannot resolve any types from junit4.jar):
>> $ javac -classpath junit4.jar -d bin/ src/pkg/TestJUnit4.java src/module-info.java
> The module you are compiling doesn't read the unnamed module. You can't write "requires $CLASSPATH" for example.
>
> If you add `--add-reads <module>=ALL-UNNAMED` to the command line then it should compile.
>
> -Alan

Thanks, Alan, that would work.

But that is not what I meant when referring to JEP 261.

In JEP 261 I see (under "Single-module mode"):
"It is possible to put arbitrary classes and JAR files on the class path in this mode,
  but that is not recommended since it amounts to treating those classes and JAR files as
  part of the module being compiled."

Doesn't this say, my above command line treats junit4.jar as part of the current module,
*not* as an unnamed module?

Is everything referenced via -classpath definitely treated as an unnamed module?
Independent of single-/multi-module modes?

Stephan
Reply | Threaded
Open this post in threaded view
|

Re: Combining -classpath and module-info?

Jonathan Gibbons


On 11/07/2017 12:56 PM, Stephan Herrmann wrote:

> On 07.11.2017 21:43, Alan Bateman wrote:
>> On 07/11/2017 18:56, Stephan Herrmann wrote:
>>> I recently noticed that compilers start to ignore -classpath as soon
>>> as module-info (.java or .class) is found during the compile.
>>> (Incidentally, javac and Eclipse compiler agree in this).
>>>
>>> Using a trivial test class this works:
>>> $ javac -classpath junit4.jar -d bin/ src/pkg/TestJUnit4.java
>>>
>>> This doesn't (cannot resolve any types from junit4.jar):
>>> $ javac -classpath junit4.jar -d bin/ src/pkg/TestJUnit4.java
>>> src/module-info.java
>> The module you are compiling doesn't read the unnamed module. You
>> can't write "requires $CLASSPATH" for example.
>>
>> If you add `--add-reads <module>=ALL-UNNAMED` to the command line
>> then it should compile.
>>
>> -Alan
>
> Thanks, Alan, that would work.
>
> But that is not what I meant when referring to JEP 261.
>
> In JEP 261 I see (under "Single-module mode"):
> "It is possible to put arbitrary classes and JAR files on the class
> path in this mode,
>  but that is not recommended since it amounts to treating those
> classes and JAR files as
>  part of the module being compiled."
>
> Doesn't this say, my above command line treats junit4.jar as part of
> the current module,
> *not* as an unnamed module?
>
> Is everything referenced via -classpath definitely treated as an
> unnamed module?
> Independent of single-/multi-module modes?
>
> Stephan

Stephan,

I think you have identified some outdated text that needs to be fixed.

The text was correct at one point, when the distinction between "single
module mode"
and "multi-module mode" was a bigger deal.

These days, the primary distinction is between "classpath (legacy) mode"
(no modules being compiled)
and "module mode" (one or more modules being compiled.)

Here's how javac treats these modes:

In classpath (legacy) mode ...

* the sourcepath, classpath and output directory behave as previously,
such as in JDK 8.

In module mode ...

* all classes on the classpath (-classpath) are treated as part of the
unnamed module.

* if you are just compiling a single module, you may either put the
source for that module
on the source path (-sourcepath) or in a directory on the module source
path (--module-source-path).

* if you are compiling multiple modules, they must be in separate
directories on the
module source path (--module-source-path).

* javac will implicitly look for previously compiled classes in the
output directory (-d).
(This is in contrast to the usage in classpath/legacy mode, where it has
always been common practice
to explicitly put the output directory on the classpath as well.)

-- Jon


Reply | Threaded
Open this post in threaded view
|

Re: Combining -classpath and module-info?

Stephan Herrmann
Thanks a lot, Jon,

This is very helpful.

As you mention legacy mode as "no modules being compiled", this mode
is still tied to the -source, -target, and --release options, right?

IOW, the fact that the command line without module-info.java succeeds
is not owed to using a different compilation mode, but to compiling
everything in the same unnamed module, right?


Does JEP 261 have a process for correcting the text after it has been delivered?

Which space should I watch for updates?
- http://openjdk.java.net/jeps/261
- https://bugs.openjdk.java.net/browse/JDK-8061972
- any other?

regards,
Stephan

On 07.11.2017 23:03, Jonathan Gibbons wrote:

>
>
> On 11/07/2017 12:56 PM, Stephan Herrmann wrote:
>> On 07.11.2017 21:43, Alan Bateman wrote:
>>> On 07/11/2017 18:56, Stephan Herrmann wrote:
>>>> I recently noticed that compilers start to ignore -classpath as soon
>>>> as module-info (.java or .class) is found during the compile.
>>>> (Incidentally, javac and Eclipse compiler agree in this).
>>>>
>>>> Using a trivial test class this works:
>>>> $ javac -classpath junit4.jar -d bin/ src/pkg/TestJUnit4.java
>>>>
>>>> This doesn't (cannot resolve any types from junit4.jar):
>>>> $ javac -classpath junit4.jar -d bin/ src/pkg/TestJUnit4.java src/module-info.java
>>> The module you are compiling doesn't read the unnamed module. You can't write "requires $CLASSPATH" for example.
>>>
>>> If you add `--add-reads <module>=ALL-UNNAMED` to the command line then it should compile.
>>>
>>> -Alan
>>
>> Thanks, Alan, that would work.
>>
>> But that is not what I meant when referring to JEP 261.
>>
>> In JEP 261 I see (under "Single-module mode"):
>> "It is possible to put arbitrary classes and JAR files on the class path in this mode,
>>  but that is not recommended since it amounts to treating those classes and JAR files as
>>  part of the module being compiled."
>>
>> Doesn't this say, my above command line treats junit4.jar as part of the current module,
>> *not* as an unnamed module?
>>
>> Is everything referenced via -classpath definitely treated as an unnamed module?
>> Independent of single-/multi-module modes?
>>
>> Stephan
>
> Stephan,
>
> I think you have identified some outdated text that needs to be fixed.
>
> The text was correct at one point, when the distinction between "single module mode"
> and "multi-module mode" was a bigger deal.
>
> These days, the primary distinction is between "classpath (legacy) mode" (no modules being compiled)
> and "module mode" (one or more modules being compiled.)
>
> Here's how javac treats these modes:
>
> In classpath (legacy) mode ...
>
> * the sourcepath, classpath and output directory behave as previously, such as in JDK 8.
>
> In module mode ...
>
> * all classes on the classpath (-classpath) are treated as part of the unnamed module.
>
> * if you are just compiling a single module, you may either put the source for that module
> on the source path (-sourcepath) or in a directory on the module source path (--module-source-path).
>
> * if you are compiling multiple modules, they must be in separate directories on the
> module source path (--module-source-path).
>
> * javac will implicitly look for previously compiled classes in the output directory (-d).
> (This is in contrast to the usage in classpath/legacy mode, where it has always been common practice
> to explicitly put the output directory on the classpath as well.)
>
> -- Jon
>
>

Reply | Threaded
Open this post in threaded view
|

Re: Combining -classpath and module-info?

Jonathan Gibbons


On 11/07/2017 02:25 PM, Stephan Herrmann wrote:
> Thanks a lot, Jon,
>
> This is very helpful.
>
> As you mention legacy mode as "no modules being compiled", this mode
> is still tied to the -source, -target, and --release options, right?

Strongly related, yes, but not directly tied together.

Set aside the use of the "legacy" word for a bit.

When -source, -target and/or --release imply compiling for versions of
the platform
preceding JDK 9, there is no concept of modules, and so there is no
concept of
"module mode". Thus, there is only "classpath mode" when compiling for
these
older versions of the platform (JDK 8 and before).

But you can also have "classpath mode" when compiling for JDK 9 (and
later).
For the most part, the same  commands that can be used to compile code
in JDK 8
should also work in JDK 9.(Obviously, there are some differences,
related to the use
of advanced options like -bootclasspath, or to access internal API.)  
But conceptually,
a javac invocation just using -classpath, -sourcepath and -d, and not
using any
module declarations (in either module-info.java or module-info.class)
should work
the same on JDK 9 as on JDK 8. Put another way, an average-Joe developer
wanting
to compile a  simple jar file can use JDK 9 just like he/she previously
used JDK 8.

That is the sense in which I use the term "legacy mode" as an alias for
"classpath mode". Although I don't particularly like the term "legacy mode",
it does carry strong connotations of "the same as before".

Now, when the developer starts working with modules, and introducing
their own module declarations, that's when javac switches to "module mode"
and the rules that I described previously will apply.


>
> IOW, the fact that the command line without module-info.java succeeds
> is not owed to using a different compilation mode, but to compiling
> everything in the same unnamed module, right?

That would be another way of looking at it, and a reasonable way for anyone
already knowledgeable about the terminology of the module system.
Compiling code with --release 8, or compiling code without a module
declaration
with --release 9 should be effectively equivalent.  It's just that you
can't talk about
the unnamed module in the context of --release 8 and earlier.

>
>
> Does JEP 261 have a process for correcting the text after it has been
> delivered?
>
> Which space should I watch for updates?
> - http://openjdk.java.net/jeps/261
> - https://bugs.openjdk.java.net/browse/JDK-8061972
> - any other?

I'll leave it to others to respond on this point, but yes, it does seem
we need an update.

-- Jon

>
> regards,
> Stephan
>
> On 07.11.2017 23:03, Jonathan Gibbons wrote:
>>
>>
>> On 11/07/2017 12:56 PM, Stephan Herrmann wrote:
>>> On 07.11.2017 21:43, Alan Bateman wrote:
>>>> On 07/11/2017 18:56, Stephan Herrmann wrote:
>>>>> I recently noticed that compilers start to ignore -classpath as soon
>>>>> as module-info (.java or .class) is found during the compile.
>>>>> (Incidentally, javac and Eclipse compiler agree in this).
>>>>>
>>>>> Using a trivial test class this works:
>>>>> $ javac -classpath junit4.jar -d bin/ src/pkg/TestJUnit4.java
>>>>>
>>>>> This doesn't (cannot resolve any types from junit4.jar):
>>>>> $ javac -classpath junit4.jar -d bin/ src/pkg/TestJUnit4.java
>>>>> src/module-info.java
>>>> The module you are compiling doesn't read the unnamed module. You
>>>> can't write "requires $CLASSPATH" for example.
>>>>
>>>> If you add `--add-reads <module>=ALL-UNNAMED` to the command line
>>>> then it should compile.
>>>>
>>>> -Alan
>>>
>>> Thanks, Alan, that would work.
>>>
>>> But that is not what I meant when referring to JEP 261.
>>>
>>> In JEP 261 I see (under "Single-module mode"):
>>> "It is possible to put arbitrary classes and JAR files on the class
>>> path in this mode,
>>>  but that is not recommended since it amounts to treating those
>>> classes and JAR files as
>>>  part of the module being compiled."
>>>
>>> Doesn't this say, my above command line treats junit4.jar as part of
>>> the current module,
>>> *not* as an unnamed module?
>>>
>>> Is everything referenced via -classpath definitely treated as an
>>> unnamed module?
>>> Independent of single-/multi-module modes?
>>>
>>> Stephan
>>
>> Stephan,
>>
>> I think you have identified some outdated text that needs to be fixed.
>>
>> The text was correct at one point, when the distinction between
>> "single module mode"
>> and "multi-module mode" was a bigger deal.
>>
>> These days, the primary distinction is between "classpath (legacy)
>> mode" (no modules being compiled)
>> and "module mode" (one or more modules being compiled.)
>>
>> Here's how javac treats these modes:
>>
>> In classpath (legacy) mode ...
>>
>> * the sourcepath, classpath and output directory behave as
>> previously, such as in JDK 8.
>>
>> In module mode ...
>>
>> * all classes on the classpath (-classpath) are treated as part of
>> the unnamed module.
>>
>> * if you are just compiling a single module, you may either put the
>> source for that module
>> on the source path (-sourcepath) or in a directory on the module
>> source path (--module-source-path).
>>
>> * if you are compiling multiple modules, they must be in separate
>> directories on the
>> module source path (--module-source-path).
>>
>> * javac will implicitly look for previously compiled classes in the
>> output directory (-d).
>> (This is in contrast to the usage in classpath/legacy mode, where it
>> has always been common practice
>> to explicitly put the output directory on the classpath as well.)
>>
>> -- Jon
>>
>>
>