...
Distributing GPLv2+CPEx licensed component in Apache software is hard
it would be way easier to use plain
javac
from a JDKnb-javac
has to be downloaded by end-user on demand via autoupdate
On demand download is problematic
user needs internet connection
- download server needs to be on (nb-javac isn't yet on Maven central)
e.g. sometimes download fails
Testing matrix is complicated
each supported JDK needs to be tested twice - with
nb-javac
and withoutnb-javac
Every bug/problem one needs to know whether
nb-javac
was or wasn't in useRecent version
nb-javac-15
isn't really stable
nb-javac
is a fork of JDK's javacnobody likes forks
ironically Arvind's team is part of JDK organization - e.g. it maintains own fork of JDK's `javac`
- Upstream JDK javac hasn't been IDE ready up to JDK15
- see below for details
- Without NbJavac one needs to run NetBeans on latest JDK to get latest language features
- Serious disadvantage compared to competitors IDEs
- They have their own Java parsers and support latest features on any JDK
...
Eliminating the need for nb-javac
Clearly there are numerous drawbacks and Apache NetBeans needs a way out. Let's get rid of nb-javac
as we know it. Let's replace it with JDK's own javac
! However there are some problems...
-
javac
in JDK15 isn't good enough - compile on save doesn't work
- re-compilation of a single method doesn't work
- runs out of memory more often than `nb-javac`.
Before NetBeans can really get rid of nb-javac
, the `javac` in JDK is needs to be good enough.
Using JDK 17 javac Instead
Let's now assume JDK17 offers good enough javac
, now NetBeans can suggest people to use JDK17 when using Apache NetBeans IDE
- not a big problem, JDK17 is LTS, but then?
- if people wanted to use language features of JDK19, they'd have to run on 19!
- that's not what competition does - they support latest language features running on JDK11 LTS or even JDK8 LTS
The story may end here and it might even be a good enough story for Apache NetBeans IDE. However...
Automatically Generating nb-javac
However, I don't like it. It is not good enough story yet. There are parties that want to run on LTS and support the latest Java features. To address their needs let's take JDK17's `javac` and let run it on JDK8! Of course, there are issues:
- latest `javac` is written in the language syntax of modern Java
- such syntax cannot be compiled to JDK8 bytecode with `javac`
- latest `javac` is using APIs not available on JDK8
- one needs to rewrite these calls to some older APIs
- the behavior needs to be tested to remain the same
The great revelation is that both these problems can be solved with Apache NetBeans tools! Rather than maintaining manual patches like nb-javac
does, let's write advanced refactoring rules and apply them automatically. For example Optional.isEmpty()
method has been added in JDK11. Let's add following rule:
Code Block |
---|
$1.isEmpty() :: $1 instanceof java.util.Optional
=>
!$1.isPresent()
;; |
That automatically rewrites all occurences of optional.isEmpty()
to !optional.isPresent()
and that is going to compile on JDK8. Few more (~30) rules like this and the `javac` is almost ready to run on JDK8! Run few tests to verify the behavior remains the same after transformation and that's all. People can use Apache NetBeans with `javac` from the latest JDK or they can use the automatic port of the same code running on JDK8. Ideally the behavior shall be identical. No more questions: Are you using nb-javac or not? No more duplicated testing matrix.
What does nb-javac do that's different to vanilla javac?
...