Skip to content

feat: install multiple JDKs with same major version - #2271

Merged
maxandersen merged 7 commits into
jbangdev:mainfrom
quintesse:devkitman_multi_jdks
May 14, 2026
Merged

feat: install multiple JDKs with same major version#2271
maxandersen merged 7 commits into
jbangdev:mainfrom
quintesse:devkitman_multi_jdks

Conversation

@quintesse

Copy link
Copy Markdown
Contributor

Fixes #2118

@quintesse
quintesse force-pushed the devkitman_multi_jdks branch from 14d6edb to 9f510d6 Compare November 4, 2025 21:43
@maxandersen

Copy link
Copy Markdown
Collaborator

Interesting. How's it to be used/managed? Couldn't spot clearly the user impact if any?

@quintesse

Copy link
Copy Markdown
Contributor Author

The idea is that user impact at first is as close to zero as possible. Mainly to detect if the new system causes any backward compatibility issues.

For the user that is accustomed to installing jdks with jbang jdk install N nothing changes. That command keeps working as before, as does uninstall.

What does change is how jdks are stored on disk. Before you'd just have a bunch of numbered directories in ~/.jbang/cache/jdks, each one containing the jdk for that version, eg:

$ ls -F ~/.jbang/cache/jdks
11/  17/  21/  24/  25/  8/

But now with the new devkitman version you could see this:

$ ls -F ~/.jbang/cache/jdks
11/  17/  21/  24/  25/  26@  26-ea+21-temurin-jbang/  8/

As you can see I just installed a new version 26. And it gets stored in a directory with a full name (its id) and additionally a symlink was created with the name "26" that points to the actual directory.

This symlink serves two purposes: a) is serves as the "default" for that version, so if you have multiple version 26 jdks installed this symlink will point to your "preferred 26 version" and b) it maintains backward compatibility with older JBang versions that will only see the symlinks (older JBang versions ignore directories whose names are not integers).

I still have to make a couple of changes before explaining what else has changed. I will keep you posted in follow-up messages here.

@maxandersen

Copy link
Copy Markdown
Collaborator

gotcha.

and i assume its fine but just asking to know if some limits - on windows the symbolic linking also works ? no extra rights needed etc? in past we "survived" these even without extra rights as jsut one folder but i know some stuff improved here i just forget which :)

And wouldn't it be nicer if stored per vendor?, i.e. / ? or even to simplify have /installs//? just suggesting this to not mix-n-match too much in one folder directly.

whats the signficance of "-jbang" in the name?

@quintesse

Copy link
Copy Markdown
Contributor Author

on windows the symbolic linking also works ?

JBang already needs those to work. The default jdk that gets added to your path is a link (a Junction to be precise).

And wouldn't it be nicer if stored per vendor?, i.e. / ? or even to simplify have /installs//? just suggesting this to not mix-n-match too much in one folder directly.

I'm just somewhat following what I see others do. I also think it makes file/folder management slightly more complex to have more levels of directories. Given the fact that nobody should be looking directly at that folder and definitely not depend on its names and structure I feel it's okay to do it this way.

whats the signficance of "-jbang" in the name?

It's because the jdks are managed by the "jbang" provider. There's other providers that can create folders there, for example links to external jdks are handled by the "linked" provider and marked with "-linked".

@quintesse
quintesse force-pushed the devkitman_multi_jdks branch 2 times, most recently from 6decb1a to db613f3 Compare November 20, 2025 15:04
@quintesse
quintesse force-pushed the devkitman_multi_jdks branch from db613f3 to 3e306cf Compare December 12, 2025 17:43
@quintesse
quintesse force-pushed the devkitman_multi_jdks branch 2 times, most recently from 3a2a8c8 to 8aeb565 Compare January 16, 2026 08:50
@quintesse
quintesse marked this pull request as ready for review January 16, 2026 08:50
@quintesse
quintesse requested a review from maxandersen January 16, 2026 08:52
@quintesse

Copy link
Copy Markdown
Contributor Author

@maxandersen this is now ready for review and devkitman 0.4.0 has been released so you don't need to build that to be able to test this PR.

Given the fact that this is a pretty major change it must be tested quite well (I already did of course, but I might be "blind" to certain issues). It must also be tested that older JBang versions keep working even when newer JDKs get installed by this new version.

Also, the workings and output of some of the jdk commands (eg jdk list) have changed somewhat, we might still want to polish that.

@quintesse

Copy link
Copy Markdown
Contributor Author

NB: currently releasing 0.4.1 because of a test failure that only appeared when running JBang's GH CI. (Seems GH uses legacy DOS paths in their environment variables, eg. JAVA_HOME=C:\PROGRA~1\Java\jdk11, which devkit handles okay enough except when trying to match it against a modern path)

@quintesse
quintesse force-pushed the devkitman_multi_jdks branch 3 times, most recently from 0ac3adf to 056cbeb Compare January 16, 2026 20:05

@maxandersen maxandersen left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should I ignore or honor the "do not merge" message ? :)

@quintesse
quintesse marked this pull request as draft January 19, 2026 11:01
@quintesse

quintesse commented Jan 19, 2026

Copy link
Copy Markdown
Contributor Author

Sorry, this PR is ready for review but not ready to merge, I put it back to draft to make that clear.
Any changes I make are to make sure all tests pass and to add some new tests to make sure more things are covered.
But for review purposes (by you) the PR should be good.

@quintesse
quintesse force-pushed the devkitman_multi_jdks branch 5 times, most recently from 25edf97 to f5e2801 Compare January 20, 2026 11:29
@quintesse
quintesse marked this pull request as ready for review January 20, 2026 11:42
@quintesse

Copy link
Copy Markdown
Contributor Author

Ok, I marked this PR ready for review again because everything works now. The integration tests are failing because of the Alpine test not being able to download the Jdk 17 it needs, but that's unrelated to this PR.

@maxandersen

Copy link
Copy Markdown
Collaborator

I ran just jbang jdk install --force --jdk-distros=graalvm 24 (it wanted --force exactly there - as had already a 24)
but it completed very fast (no download and no output) and I didnt get any linking?

ls -F ~/.jbang/cache/jdks
Permissions Size User Date Modified Name
drwxr-xr-x@    - max  13 Nov  2025   8/
drwxr-xr-x@    - max  23 Oct  2025   11/
drwxr-xr-x@    - max   9 Oct  2025   17/
drwxr-xr-x@    - max   9 Oct  2025   21/
drwxr-xr-x@    - max   7 Jan 10:35   22/
drwxr-xr-x@    - max  28 Dec  2025   24/
drwxr-xr-x@    - max  30 Sep  2025   25/
drwxr-xr-x@    - max  17 Mar 14:21   26/

bug?

@quintesse

Copy link
Copy Markdown
Contributor Author

Ok, will look into that.

But what would be the expected result here?

Because I could think of two different interpretations:

  1. "Yes, I know I already have a 24, but I also want this one"
  2. "Yes, I know I already have a default 24, but I also want this one and I want you to make it the default"

There could even be a 3rd interpretation:

  1. "Yes, I know I already have a 24 but I want to use this one instead, so replace existing with this new one"

And depending on the other arguments you pass you might even expect a different result:

  • jbang jdk install --force 24 - Option (3)? Because there's a new minor release and you want to update to that one? Although option (2) might also work if we don't want to automatically remove versions
  • jbang jdk install --force --jdk-distros=graalvm 24 - Option (1)? Because it's obviously a different one? Or still option (3)? (Or option (2) if we don't want to auto-remove)

Option (1) might be difficult to explain, someone does jbang jdk install --force --jdk-distros=graalvm 24 and then probably expects to be able to run jbang --java 24 graalvmtest.java and not first have to look up the id of the newly installed JDK and use that.

Looking at this option (2) is perhaps the one easiest to explain and giving the least headaches?

@maxandersen

Copy link
Copy Markdown
Collaborator

I assume if i say use Zulu 24 that 24 will give me Zulu.

I think that's what you call option 2.

But this also mean we need someway to say "don't put this as default"

Maybe Jbang jdk install --extra 24 ?

And somehow print what id to use if want to be explicit.

@quintesse

Copy link
Copy Markdown
Contributor Author

Not sure, that --extra isn't really an option that makes me "happy", so to speak.

It seems like a fix/workaround that's only useful in very specific situations that will be somewhat hard to explain when to use.

Perhaps combining option (1) with a --default option?

(THe problem might be: the default of what? There is a main/global default and a per-version default. DOes this option mean you want it to become the default for 24 or the main/global default?)

@maxandersen

Copy link
Copy Markdown
Collaborator

How is the current PR intended to be used? it says install multiple jdks with same major version ...whats the command to do that if not jbang jdk install --jdk-provider=zulu 24 ? how to choose which exact version will be installed?

@quintesse

Copy link
Copy Markdown
Contributor Author

Well the current PR doesn't yet give you all the options that I have in mind, because the changes were already big enough and I first wanted to get basic functionality working.

Anyway, if you do jdk list -a -d (--available --details) you'll see IDs and you can use those IDs to install exactly that version, eg:

$ jbang jdk list -a -d
   27 (27-ea+17, jbang, 27-ea+17-temurin-jbang, [ea])
   26 (26+35, jbang, 26+35-temurin-jbang)
   25 (25.0.2+10, jbang, 25.0.2+10-temurin-jbang)
   ... etc

And then you can run install 26+35-temurin-jbang to install that exact version.

Right now we don't really show any other options, but you could easily imagine a list that returns options from multiple distros (like sdkman does, for example).

Now that we have the basics working we just have to come up with good ideas and what options/features to add :-)

@quintesse

Copy link
Copy Markdown
Contributor Author

For example, one of the things I want to allow is <version>,<tag>... where we now support <version>

Imagine:

  • install 24,zulu instead of install --jdk-provider=zulu 24
  • install 24,jre,javafx install a version 24 JRE with JavaFx support
  • run --java 24+,native run using a 24 or higher GraalVM-based version

PD: I say <version>, but we actually support <version>|<id>, so the new format with tags would also be: <version>,<tag>...|<id>

@maxandersen

Copy link
Copy Markdown
Collaborator

about provider and tags - thats why I was suggesting more structured format, like 24{jre,javafx}@zulu which matches how we been discussing other ways to provide properties to jbang directive syntaxes.

@maxandersen

Copy link
Copy Markdown
Collaborator

#2133 is where that syntax mostly implemented.

@quintesse

Copy link
Copy Markdown
Contributor Author

Sure, the actual syntax is irrelevant to devkitman, it's something that would be implemented by JBang itself and then implemented using the existing filtering system.

@quintesse

Copy link
Copy Markdown
Contributor Author

I ran just jbang jdk install --force --jdk-distros=graalvm 24 (it wanted --force exactly there - as had already a 24)
but it completed very fast (no download and no output) and I didnt get any linking?

Btw, it seems the current jbang doesn't handle this either.
Still looking into it...

@quintesse
quintesse force-pushed the devkitman_multi_jdks branch 3 times, most recently from ccc6860 to 9219409 Compare April 22, 2026 08:38
@quintesse

Copy link
Copy Markdown
Contributor Author

I ran just jbang jdk install --force --jdk-distros=graalvm 24 (it wanted --force exactly there - as had already a 24)
but it completed very fast (no download and no output) and I didnt get any linking?

@maxandersen this should be fixed now, can you try this new version?

@maxandersen

maxandersen commented May 14, 2026

Copy link
Copy Markdown
Collaborator

finally got around trying this again.

this time I seem to be getting a graalvm downloaded - yaay!

one thing I did spot is a repeated read of release...is that expected?

just jbang --verbose jdk install --force --jdk-distros=graalvm 24
PATH="build/install/jbang/bin:$PATH" jbang --verbose jdk install --force --jdk-distros=graalvm 24
[jbang] [0:163] jbang version 0.138.0.7
[jbang] [2026-05-14 11:21:27] Using JDK provider(s): CurrentJdkProvider, DefaultJdkProvider, JavaHomeJdkProvider, PathJdkProvider, LinkedJdkProvider, JBangJdkProvider
[jbang] [2026-05-14 11:21:27] Unable to read 'release' file in path: /Users/max/.jbang/cache/jdks/8
[jbang] [2026-05-14 11:21:27] Unable to read 'release' file in path: /Users/max/.jbang/cache/jdks/8
[jbang] [2026-05-14 11:21:27] Unable to read 'release' file in path: /Users/max/.jbang/cache/jdks/8
[jbang] [2026-05-14 11:21:27] Unable to read 'release' file in path: /Users/max/.jbang/cache/jdks/8
[jbang] [2026-05-14 11:21:27] Unable to read 'release' file in path: /Users/max/.jbang/cache/jdks/8
[jbang] [2026-05-14 11:21:27] Unable to read 'release' file in path: /Users/max/.jbang/cache/jdks/8
[jbang] [0:348] Using cached file /Users/max/.jbang/cache/urls/1bee4c4e888dcfd526c7e4206b9921908844e651d2951c3565b28ac9b7e76c89/packages for remote https://api.foojay.io/disco/v3.0/packages?distro=graalvm&javafx_bundled=false&libc_type=libc&directly_downloadable=true&archive_type=tar.gz&operating_system=mac&package_type=jdk&version=24&release_status=ga&architecture=aarch64&latest=available
[jbang] [2026-05-14 11:21:27] Downloading JDK 24. Be patient, this can take several minutes...
[jbang] [2026-05-14 11:21:27] Downloading https://api.foojay.io/disco/v3.0/ids/07b0c04a8d6a8b0fa8911aec54b2e0e2/redirect
[jbang] [0:402] Requesting HTTP GET https://api.foojay.io/disco/v3.0/ids/07b0c04a8d6a8b0fa8911aec54b2e0e2/redirect
[jbang] [0:402] Headers {User-Agent=[JBang/0.138.0.7 (Mac OS X/26.3/aarch64) avaJ/25.0.2/Oracle Corporation]}
[jbang] [1:202] Redirected to: https://download.oracle.com/graalvm/24/archive/graalvm-jdk-24.0.2_macos-aarch64_bin.tar.gz
[jbang] [1:621] Deleting folder /Users/max/.jbang/cache/urls/e84da4bb18c108cdda486657256c89f2b7eeedfed1d921c53d698a53f4f65442.tmp
[jbang] [1:630] Deleting folder /Users/max/.jbang/cache/urls/e84da4bb18c108cdda486657256c89f2b7eeedfed1d921c53d698a53f4f65442-meta.tmp
^[[<65;137;39M^[[<65;137;39M^[[<64;127;44M[jbang] [16:980] Downloaded file https://download.oracle.com/graalvm/24/archive/graalvm-jdk-24.0.2_macos-aarch64_bin.tar.gz
[jbang] [2026-05-14 11:21:44] Installing JDK 24...
[jbang] [2026-05-14 11:21:44] Unpacking to /Users/max/.jbang/cache/jdks/24.0.2-graalvm-jbang

Whats the "Unable to read 'release' file in path: /Users/max/.jbang/cache/jdks/8" x 6 about?

@maxandersen

Copy link
Copy Markdown
Collaborator

So after I ran just jbang --verbose jdk install --force --jdk-distros=graalvm 24 I kinda expected jdk list to show some link to what I installed..

jbang jdk list --show-details
Installed JDKs (<=default):
   25 (25.0.2+10-69, current, current, /Users/max/.local/share/mise/installs/java/25.0.2)
   25 (25+36-LTS, default, default, /Users/max/.jbang/currentjdk) <
   25 (25.0.2+10-69, javahome, javahome, /Users/max/.local/share/mise/installs/java/25.0.2)
   25 (25.0.2+10-69, path, path, /Users/max/.local/share/mise/installs/java/25.0.2)
   24 (24.0.2+11-jvmci-b01, linked, 24, /Users/max/.jbang/cache/jdks/24)
   11 (11.0.28+6, jbang, 11-jbang, /Users/max/.jbang/cache/jdks/11)
   17 (17.0.16+8, jbang, 17-jbang, /Users/max/.jbang/cache/jdks/17)
   26 (26-beta+35-ea, jbang, 26-jbang, /Users/max/.jbang/cache/jdks/26)
   8 (1.8.0_472, jbang, 8-jbang, /Users/max/.jbang/cache/jdks/8)
   21 (21.0.8+9-LTS, jbang, 21-jbang, /Users/max/.jbang/cache/jdks/21)
   22 (22.0.2+9, jbang, 22-jbang, /Users/max/.jbang/cache/jdks/22)
   25 (25+36-LTS, jbang, 25-jbang, /Users/max/.jbang/cache/jdks/25)

the graalvm 24 is this:

24 (24.0.2+11-jvmci-b01, linked, 24, /Users/max/.jbang/cache/jdks/24)

but what is linked? and remind me what does 24 mean here vs 26-jbang?

quintesse added 7 commits May 14, 2026 11:47
Added a flag `--for-version` (or `-v`) to the `jdk default` command to
allow setting the default Jdk to use for a specific major version.
This is necessary now that we allow multiple Jdks of the same major
version to be installed simultaneously.
Added some more parameter checks to `jdk install`.
Also refactored `Jdk` class.
@quintesse
quintesse force-pushed the devkitman_multi_jdks branch from 9219409 to 2c621db Compare May 14, 2026 09:48
@maxandersen
maxandersen merged commit 221049f into jbangdev:main May 14, 2026
28 checks passed
@quintesse

Copy link
Copy Markdown
Contributor Author

Yay! Only took 7 months 😁

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Make it possible to have multiple JDKs installed of the same version

2 participants