On 03/02/2015 12:37 AM, Remi Forax wrote:
On 03/01/2015 07:08 PM, Peter Levart wrote:
Hi Peter,
You can see the whole thing in the opposite way which I think is less
disruptive in term of tooling.
You only maintain one module which depend on the latest version.
When you ship the module let say as a jar, you also ship the way to
downgrade it as an executable code.
At install time, when all the modules are known, before trying to
create the images,
the code that downgrades the module is executed if necessary.
This code can rewrite the whole bytecodes of all the classes the
module thus ensure backward compatibility without providing binary
backward compatibility.
It's a win-win-win strategy, your code doesn't live in the past, the
bytecode rewriter can fail saying there is a problem before runtime
(if by example a method is missing), you can break the binary backward
compatibility if this is necessary and still being compatible.
You can see this mechanism as a kind of annotation processor that will
be executed at install time instead of at compile time.
cheers,
Rémi
Such "way to downgrade executable code" is something that doesn't exist
(yet)? Is it planned? I imagine this as a kind of compiler. It has to
understand executable code, identify "problematic platform-dependent
code sequences / API usages" and convert them to semantically equivalent
code targeted at specific platform. Who is going to write and support
such tool? Should it be extensible, so that the application programmer
can extend and "program" it? How are semantically equivalent code
sequences targeting specific platform going to be represented? How are
"problematic platform-dependent code patterns / API usages" going to be
represented? We already have a language-level way to represent
semantically equivalent code sequences targeting specific platforms -
different implementations of the same interface. By choosing the
appropriate implementation at runtime, we can avoid needing a tool that
understands executable code and identifies problematic
platform-dependent code. In terms of tooling, I don't see any problems
as good IDEs and even Maven already support specifying platform
dependencies / compilation for different target platforms at the
module-level in the same project.
But I may be persuaded by a good implementation of such "retroweaver".
There was one such tool in JDK 1.4 -> 1.5 times.
Regards, Peter
On 03/01/2015 12:53 PM, Remi Forax wrote:
Currently, there are two ways to solve the Base64 issue:
- by loading at runtime either the class that use java.util.Base64
or the class sun.misc.BASE64Decoder and use it through an interface
And this, I think, is also the cleanest way to approach a problem
that multi-version JAR wants to solve. The only argument against it
is that it perhaps requires more work and planing, but that doesn't
mean it is less maintainable. In general one has to split the
software into "modules":
- base module (platform independent code) + facade interfaces to
access platform dependent functionality
- platform dependent module(s) that depend on base module and contain
implementations of facade interfaces published as services through
ServiceLoader - one module per "target platform version" / "platform
dependent feature" combination
Base module is compiled 1st (it does not depend on platform version,
so it should be compiled with lowest version javac/rt.jar to be able
to run on any target platform)
Platform dependent module(s) are compiled against classes of base
module and with javac/rt.jar of the desired target platform(s).
Now if module system of JDK9 had a feature that would enable/disable
the deployed module conditionally, then that condition could be an
exact target platform version.
But I know, multi-version JAR wants to solve similar problem for
pre-JDK9 target platforms too which don't yet have modules. The
approach to organizing sources and compiling can be the same as
described, just packaging can then use multi-version JARs instead of
"conditional" modules.
One problem I see with requirering that in multi-version JARs each
version sub-path must have same public classes with same public APIs
is that IDEs don't like that. They don't like to see multiple
versions of same class and they paint them red. Refactoring doesn't
work correctly if IDEs see multiple versions of same class and can
never be made to work correctly as it would have to keep versions
always in sync. I always have problems with IDEA when I present it
the unix/windows versions of classes in JDK build at the same time.
This can be solved nicely by not requirering that and simply relying
on the programmer that (s)he knows what (s)he is doing. With
interfaces as services and implementations locateable via
ServiceLoader, one does not have to use same names of classes for
implementations of interfaces targeting different platforms and IDEs
will be happy.
Regards, Peter