maven-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Stephen Connolly <stephen.alan.conno...@gmail.com>
Subject Re: javac bootclasspath and java8
Date Mon, 01 Dec 2014 10:10:43 GMT
On 1 December 2014 at 09:23, Mark Struberg <struberg@yahoo.de> wrote:

> > The issue is that there are classes which generate a different signature
>
> > when compiled with the Java 8 RT vs when compiled with the Java 7 RT.
>
>
> +1
>
>
> > I think what we - as a community - are learning is that we no longer
>
> > have the luxury of compiling with a newer JDK against an older target...
>
>
> +1
>
>
>
> I don't fully agree with the other summary though.
>

So right now, most of the dependencies that you can pull in via central are
compiled with Java < 8.

Most people compiling with -target < 8 are probably being (relatively) good
citizens and using Java 7

But as we move forward, once Oracle Java 7 goes EOS next year, it is
reasonable to expect that people may start switching to Java 8 as their
primary JDK.

For example, from my day job as of a few days ago, our support window moves
such that the versions of Jenkins that cannot run on Java 8 are no longer
supported... and my colleague Jesse threw out the suggestion of moving the
primary JDK that people run on their machines to Java 8 to give Java 8 more
testing by default

> On Wed, Nov 26, 2014 at 7:09 PM, Jesse Glick wrote:

> > On Wed, Nov 26, 2014 at 1:04 PM, Robert Sandell wrote:
> > > I think it should be run with Java7 for reasons.
> > Which reasons?
> I believe most of our customers hasn't moved to Java 8 yet
>

>
I think there is a change in the mindset - which I believe Oracle wants to
encourage - that everyone should be moving to the latest JDK rather than
holding off running old JDKs

That is in some ways a good thing... but there are issues that -target masks

Because JDK 8 supports -target, you can cheat and build a library that
works on Java 1.2... you can also build a library that has 1.2 compatible
bytecode and would compile with Java 1.2 but when compiled against the JDK
8 RT with target 1.2 you end up with a lib that won't work on Java 1.2

Now I don't think there are much people writing new code and wanting to
using new dependencies and building code that runs on Java 1.2

But here's the rub.

Suppose you work in a bank, there may be some systems that are running Java
1.4 or perhaps some more "modern" ones running Java 1.5...

How do we help those people know that the dependencies they are consuming
were compiled against the right JVM RT?

Until recently you can get a first approximation check with:

http://mojo.codehaus.org/extra-enforcer-rules/enforceBytecodeVersion.html

That's a nice quick check... but it won't catch it all any more as the
compiler may record widened scope method references behind your back... all
those StringBuffer.append("a string") calls will now be looking for
StringBuffer.append(CharSequence) and not StringBuffer.append(String)
methods all because the RT argument type was widened.

So even though the developer of the library was trying to be helpful and
compiling with -target 1.4 unless you run animal sniffer on every single
dependency you could well be screwed... and if you are not able to install
a Java 1.4 on your development Mac, you won't find the problem until the
code hits your CI server and the tests hit that code... if you have tests
hitting that code.

What we need from central is a way to record what runtime an artifact was
built against... this used to be a .NET and native code issue and the Java
world was insulated... I think that it is fast becoming our problem too...
so guess what... we'll have to step up and solve it!



> I think we have a better option but we need to work it out a bit.
>
> The ToolchainManager really looks like a nice way we could probably do
> that. Usually a project would not care much which JDK version is installed,
> but by using the toolchains.xml we have a way to declare the exact
> environment one likes to use. That way one can define that a certain Java7
> and Java8 JDK should be used. Currently this needs an explicit
> configuration of the maven-toolchain-plugin, and there is also no way to
> 'enforce' a specific setup to be done. E.g. that someone needs to have the
> toolchains.xml and the 1.6 and 1.8 JDKs needs to be in there.
>
> There are 2 things I like to improve:
>
> 1.) enhance enforcer rules to include toolchains.xml or make maven itself
> handle it
> 2.) enhance the ToolchainManager to let lookup configured Toolchains and
> use this in maven-compiler-plugin and maven-test-plugin to use a
> 'preferred' Toolchain version. E.g. if target=1.7 is defined it should try
> to resolve this Toolchain.
>

I think that having m-c-p use the best fit JDK from the toolchains *by
default* and with a flag to turn it off (with a WARNING logged) and falling
back to the current JDK (with a WARNING logged) is probably the way to go.


>
>
> I also like to give you a sample usage what I like to be able.
> In Apache OpenJPA we currently have an issue with Entities using Java8
> Lambdas and Streaming API. The enhancement is broken for them. But I'm
> currently not able to define an additional module which uses Java8 and
> contains those Java8 feature tests. If I would add such a Java8 test module
> then I would today need to build the whole application with Java8. But then
> the aforementioned bytecode issues would appear.
>
>
> Most of this is already possible today with Toolchains. Just explicitly
> use the maven-toolchains-plugin in your pom and make sure the
> toolchains.xml is setup correctly. Of course both of it should just be one
> or two lines in the poms in the future. And I would love to have a switch
> in my project to make the toolchains.xml and some well specified Toolchains
> mandatory for it. And ideally with a link to our page describing how to
> setup toolchains.xml...
>
>
> LieGrue,
> strub
>
>
>
>
> On Sunday, 30 November 2014, 12:58, Stephen Connolly <
> stephen.alan.connolly@gmail.com> wrote:
> >
> >Jochen,
> >
> >
> >I think you misunderstand the problem.
> >
> >
> >The issue is that there are classes which generate a different signature
> when compiled with the Java 8 RT vs when compiled with the Java 7 RT.
> >
> >
> >For example, you could have a method that takes a String parameter in
> Java 7 and was widened to take a CharSequence in Java 8.
> >
> >
> >If your code calls that method with a String, you'd think you'd be ok...
> >
> >
> >Compiling against Java 7 will embed the call to the String parameter
> method
> >
> >
> >Compiling against Java 8, even with -target 7  will embed a call to the
> CharSequence parameter method and you will get a method not found when
> running against Java 7.
> >
> >
> >Now this could be viewed a bug in the Java 8 runtime, as to retain strict
> support for compiling against 8 and running on 7 you would need to add the
> wider method, not widen the parameter of the existing method... but Java
> does not make such a promise... the -target is a convenience only.
> >
> >
> >Now animalsniffer would catch the kind of issue I describe above... but
> there are more subtle issues, e.g. where there are methods moved to default
> methods on an interface, etc.
> >
> >
> >These all affect the bytecode.
> >
> >
> >I think what we - as a community - are learning is that we no longer have
> the luxury of compiling with a newer JDK against an older target... we will
> have to stick to compiling with the oldest JDK that we support as a
> runtime... yes we can fall back to -target, animalsniffer and friends, but
> realistically we need to switch to either aggressively upping the minimum
> or we need to get better protections in place with regards to central and
> the java runtime that was used on the compile classpath.
> >
> >We may need to push POM 5.0.0 sooner or risk Central becoming unusable
> with anything other than the latest JDK (as you have no way of knowing if
> you'll get bitten with your dependencies compiled using a newer JDK and an
> old -target and thus embedding the bad usage)
> >
> >
> >Or maybe we can improve animal sniffer to help us detect those issues
> >
> >
> >On 30 November 2014 at 11:33, Jochen Wiedmann <jochen.wiedmann@gmail.com>
> wrote:
> >
> >I'd solve your problem like this, Mark:
> >>
> >>- Create an interface for a component, which is internally using the
> >>JDK code in question, (say IRTUser).
> >>- Create three implementations, each of which are targeting a
> >>particular JDK. In what follows, I'll assume that they throw an
> >>exception when being instantiated on the wrong JDK.
> >>- Ideally, these implementations must be compilable with different
> >>JDK'S. (If required, use Java reflection internally to find the right
> >>methods, etc. (The above method would be a MethodNotFoundException, or
> >>the like.)
> >>- Have a factory class, with code like the following:
> >>
> >>    private static final IRTUser instance = newRTUser();
> >>
> >>    private static IRTUser newInstance() {
> >>      try {
> >>        return new JDK18RTUser();
> >>      } catch (Throwable t0) {
> >>        try {
> >>          return new JDK17RTUser();
> >>        } catch (Throwable t1) {
> >>          return new JDK16RTUser();
> >>        }
> >>     }
> >>
> >>   public static IRTUser getInstance() { return instance; }
> >>
> >>This approach has worked fine for me on multiple occasions.
> >>
> >>
> >>Jochen
> >>
> >>
> >>
> >>
> >>On Thu, Nov 27, 2014 at 9:39 PM, Mark Struberg <struberg@yahoo.de>
> wrote:
> >>> Hi!
> >>>
> >>> Today I had a discussion with Robert about how we can solve a problem
> I had over at Apache OpenWebBeans:
> >>>
> >>> https://issues.apache.org/jira/browse/OWB-952
> >>>
> >>> As a short summary: the classes provided in rt.jar of Java8 are
> slightly different than the ones from Java7 and 6. Similar big differences
> have been seen in the Java4 to 5 transition.
> >>> Thus if you compile your project with Java8 you might get different
> bytecode than when compiling with Java7 JDK. Even if you use target=1.7 in
> both cases.
> >>>
> >>> There are 2 options: either use javac -bootclasspath and point it to
> the 'correct' rt.jar + other jdk libs, or just switch the whole environment.
> >>>
> >>> Roberts suggestion was to use the Maven Toolchain system:
> http://maven.apache.org/plugins/maven-toolchains-plugin/
> >>>
> http://maven.apache.org/plugins/maven-toolchains-plugin/toolchains/jdk.html
> >>>
> >>>
> >>> We also elaborated about improving the Toolchain lookup in our
> maven-compiler-plugin:
> >>>
> http://maven.apache.org/plugins/maven-compiler-plugin/xref/org/apache/maven/plugin/compiler/AbstractCompilerMojo.html#427
> >>>
> >>> This could get improved to first check if a toolchain is registered
> for the <target> version used in the m-compiler-p. And if there is no
> toolchain configured especially for this version then we fallback to the
> one if we don't specify a version.
> >>> The effective lookup path would then be
> >>> 1.) toolchain configured via maven-toolchain-plugin
> >>> 2.) toolchain with specified target version
> >>> 3.) default toolchain
> >>>
> >>>
> >>> I think we would need to slightly enhance the ToolchainManager, but
> first would like to get some feedback.
> >>>
> >>>
> >>> LieGrue,
> >>> strub
> >>>
> >>> ---------------------------------------------------------------------
> >>> To unsubscribe, e-mail: dev-unsubscribe@maven.apache.org
> >>> For additional commands, e-mail: dev-help@maven.apache.org
> >>>
> >>
> >>
> >>
> >>--
> >>Our time is just a point along a line that runs forever with no end.
> >>(Al Stewart, Lord Grenville)
> >>
> >>
> >>---------------------------------------------------------------------
> >>To unsubscribe, e-mail: dev-unsubscribe@maven.apache.org
> >>For additional commands, e-mail: dev-help@maven.apache.org
> >>
> >>
> >
> >
> >
>

Mime
  • Unnamed multipart/alternative (inline, None, 0 bytes)
View raw message