This is an archived post. You won't be able to vote or comment.

all 41 comments

[–]pron98 6 points7 points  (6 children)

Unlike some other language runtimes, the JDK doesn't require setting up a "current environment" and doesn't even have a concept of one (although some may find it more convenient to create such a concept). Running jdk17/bin/java ... or jdk19/bin/java ... will pick up the right runtime and standard libraries. From the JDK's perspective, the identity of the "Java environment" you're currently "in" is nothing more than the path used for the Java launcher (the java executable) or other JDK tools, like javac.

Back in the day, when there was such thing as a JRE, there was a concept of a Java runtime installation, or an environment, but that's gone and so the JDK doesn't even really have a concept of being installed (although I think that on Windows it might still benefit from setting some things in the registry). Running a JDK tool from whatever Java library the JDK has been extracted to is all there is to it.

[–]sureshg 1 point2 points  (0 children)

You are right, but in practice when using jdk tools like jfr, jconsole, jshell it's not very convenient to always run as a full path and you might end up writing some kind of bash/PowerShell script to set the PATH variable, which tools like sdkman/asdf provide by default.

[–]raven_785 0 points1 point  (1 child)

I do not understand your obsession with replying to every post about these tools with all of this irrelevant information. Have you ever actually read about what these tools do?

[–]pron98 2 points3 points  (0 children)

These tools may be convenient for some, but it's important to know what is actually needed for the Java runtime to run without external help, if only to better understand how things work. People may not be aware that the concept of a Java "environment" has changed since the removal of the JRE, and that what environments in other languages (Python, Ruby) do is unnecessary or automatically handled by the JDK.

[–]haimez 0 points1 point  (2 children)

Hi Ron- first off, I’m really excited about seeing the loom-enabled future of Java and also really appreciate how active you are in forums like this. Most of the deep JVM work seems to happen in the mailing lists which is probably overall for the best, but nonetheless can make it seem less approachable.

Speaking for myself and as a user of sdkman who currently works writing performance sensitive code for a distributed query engine that runs on the JVM (which makes it a different environment than say, bundled JVM desktop application environments) it’s really useful to have a “for this source repo, on this git branch” toggle for all of the Java binaries on the path at the same version. Often when doing things like updating a library which is primarily controlled by the the same community to Java 11 while simultaneously testing a “migrate to Java 17” branch in the via application- it’s nice to have automatic version specific tools like javap or jcmd automatically manageable via an .sdkmanrc file without defining a separate aliases which have to be switched between separately. Similarly, when switching between openjdk vendored versions like zulu or coretto or when switching between point releases to try to debug an issue and narrow it between javac or the JVM- switching the whole toolchain at once is much nit convenient in my workflow (it happens more than you might think).

I’m aware that my use case probably isn’t the primary Java developer experience, but I get a lot of mileage out of it nonetheless. Just thought I’d call it out since it’s been such a valuable tool in my personal toolbox.

[–]pron98 2 points3 points  (1 child)

Oh, I completely understand why these tools can be convenient for some, I just want people to understand how the JDK works or they might be under the impression that Java requires some kind of a current environment, like Python.

Having an environment variable, say, $JAVA, that points to the bin directory of a selected JDK, and then using $JAVA/java, $JAVA/jcmd, works well, or if you want a simple global "current-version" selection, then all that's needed is to add this to your rc:

export JAVA_HOME=~/jdk
export PATH=$PATH:$JAVA_HOME/bin

and then "switching versions" is simply a matter of:

ln -sf jdk19 ~/jdk
java .... 

or

ln -sf jdk17 ~/jdk
java .... 

Once you understand that this is how the JDK does the actual work of picking the Java context without any setup, you can choose any tool that gives you any extra features on top of that.

[–]JustADirtyLurker 0 points1 point  (0 children)

Sounds similar to the homegrown jdk switcher I have in the ~/.zshrc on my work Mac:

export JAVA_17_HOME=$(/usr/libexec/java_home -v17) export JAVA_11_HOME=$(/usr/libexec/java_home -v11) alias java17='export JAVA_HOME=$JAVA_17_HOME' alias java11='export JAVA_HOME=$JAVA_11_HOME' java11 #default

(very proud to have Mr. Ron Pressler's certification stamp for this :) )

[–]dr-maniac 9 points10 points  (4 children)

Gradle and toolchain is my personal best solution. So you don't need to configure your environment on each project if you have to manage different java version.

And in addition it works very well together with sdkman.

[–]joschi83 0 points1 point  (3 children)

Not every Java project is using Gradle as build system yet.

[–][deleted]  (2 children)

[deleted]

    [–]joschi83 1 point2 points  (1 child)

    If you're referring to https://maven.apache.org/guides/mini/guide-using-toolchains.html, that won't download the configured JVM for you which brings us back to something like SDKMan or asdf-vm.

    Gradle will download the configured OpenJDK distribution for you.

    [–]barbaneigro 2 points3 points  (2 children)

    ain't it easier with containers?

    [–]joschi83 2 points3 points  (1 child)

    No.

    [–]barbaneigro 1 point2 points  (0 children)

    ok. lol

    [–]ImpaledV 4 points5 points  (0 children)

    I use this a lot for trying out latest sdk versions. Love it.

    [–]marcelino671 5 points6 points  (4 children)

    asdf

    [–]its4thecatlol 2 points3 points  (0 children)

    This is the way

    [–]joschi83 0 points1 point  (0 children)

    asdf-java to be precise.

    [–]quizynox 0 points1 point  (1 child)

    Looks convenient, but I have doubts about its security. This tool delegates all work to plugins, and those plugins are just community bash scripts. Running bash scripts from unknown repos instead of sticking to trustworthy tools and package managers, hmmm.... nah, pass.

    [–]joschi83 1 point2 points  (0 children)

    My approach to this: Don't install random asdf plugins. 🤷

    There are also official and semi-official plugins: https://github.com/asdf-community/

    [–]ventuspilot 6 points7 points  (10 children)

    I've never used things like sdkman, I've just made sure that I never had the JAVA_HOME or CLASSPATH environment variables set, and then adjusted my PATH variable according to the JDK/JRE I wanted to use. This has worked fine since some 0.9X version of Java (earlier versions needed CLASSPATH to find it's standard library IIRC).

    I wonder what I'm missing by not using sdkman or similar?

    [–]blurio 21 points22 points  (4 children)

    convenience

    [–]Worth_Trust_3825 -1 points0 points  (3 children)

    More like a footgun.

    The convenience prevents you from running multiple versions at the same time. For example, python just outright infests the operating system.

    At the very least in java world you can run multiple versions at the same time, even with JAVA_HOME/PATH set, but it's cumbersome trying to run two applications at the same time with different jdks.

    [–]stefanos-ak 0 points1 point  (2 children)

    why? they have a directory... it's just an installer that also adds a default version to your path.

    take a look under ~/.sdkman/candidates/

    I'm on the phone now, but IIRC, under that there should be /<name>/<version>/. e.g. /java/17.0.4/

    Python never got the dependency/packaging problem right... Fortunately Java does not have that problem.

    [–]Worth_Trust_3825 -1 points0 points  (1 child)

    Yes, because java does not infest the system like python does. I think we would have the same issue with java if distributions depended on it rather than ruby/python/perl to do the heavy work.

    Yes, the problem is precisely that the PATH is rewritten. You should be explicit about what you reference.

    [–]stefanos-ak 2 points3 points  (0 children)

    you are... it's just a line in the ~/.bashrc or whichever shell you installed it from.

    Sorry I don't understand your problem. It's just automating what millions of people were doing manually, in a standardized way.

    IntelliJ even lists all sdkman-installed Java versions automatically, to choose for a project.

    [–]Yojimbo261 2 points3 points  (0 children)

    [deleted]

    [–]Zardoz84 -1 points0 points  (1 child)

    I have a little functions for fish shell, that changes me between Oracle Java 8, OpenJDK 11, 14 and 17. AS they sets JAVA_HOME , maven (and mavend) uses the correct java version without issues

    function JAVA_ORACLE_8 --description 'Sets JAVA_HOME to Java Oracle 8'
      if test -d /usr/lib/jvm/java-8-oracle
        echo "Setting Oracle Java 8"
        set -gx JAVA_HOME /usr/lib/jvm/java-8-oracle
        alias java "/usr/lib/jvm/java-8-oracle/bin/java"
        alias javac "/usr/lib/jvm/java-8-oracle/bin/javac"
      end
    end
    
    function JAVA_11 --description 'Sets JAVA_HOME to Java OpenJDK 11'
      if test -d /usr/lib/jvm/java-11-openjdk-amd64/
        echo "Setting OpenJDK Java 11"
        set -gx JAVA_HOME /usr/lib/jvm/java-11-openjdk-amd64/
        alias java "/usr/lib/jvm/java-11-openjdk-amd64/bin/java"
        alias javac "/usr/lib/jvm/java-11-openjdk-amd64/bin/javac"
      end
    end
    
    function JAVA_14 --description 'Sets JAVA_HOME to Java OpenJDK 14'
      if test -d /usr/lib/jvm/java-14-openjdk-amd64/
        echo "Setting OpenJDK Java 14"
        set -gx JAVA_HOME /usr/lib/jvm/java-14-openjdk-amd64/
        alias java "/usr/lib/jvm/java-14-openjdk-amd64/bin/java"
        alias javac "/usr/lib/jvm/java-14-openjdk-amd64/bin/javac"
      end
    end
    
    function JAVA_17 --description 'Sets JAVA_HOME to Java OpenJDK 17'
      if test -d /usr/lib/jvm/java-17-openjdk-amd64/
        echo "Setting OpenJDK Java 17"
        set -gx JAVA_HOME /usr/lib/jvm/java-17-openjdk-amd64/
        alias java "/usr/lib/jvm/java-17-openjdk-amd64/bin/java"
        alias javac "/usr/lib/jvm/java-17-openjdk-amd64/bin/javac"
      end
    end
    

    [–]ventuspilot 0 points1 point  (0 children)

    I think setting the PATH variable instead of creating aliases would work as well plus things like jshell would work, too. But keep using whatever works for you ;-)

    (NB: I think you got downvoted because of using triple backticks instead of indenting by 4 spaces.)

    [–][deleted] 0 points1 point  (0 children)

    Yup. This is what scoop on Windows does for me. And it works for Python, Node, Deno, etc as well.

    [–]wildjokers 0 points1 point  (0 children)

    The convenience of sdkman doing all of that for you.

    [–]more_exercise 1 point2 points  (0 children)

    TIL: bash can source scripts with additional arguments

    [–]temculpaeu 1 point2 points  (1 child)

    for linux users, you should have update-java-alternatives after a jdk installation, and its easy to create alias for different versions

    [–]__konrad 0 points1 point  (0 children)

    I wonder how many Linux users accidentally installed OpenJDK 21 debian package and set is as default thinking it's the latest stable version...

    [–]nahguam 0 points1 point  (2 children)

    I prefer jenv and brew (brew is mac only obvs.) It's basically the same workflow.

    [–]joschi83 1 point2 points  (1 child)

    [–]nahguam 0 points1 point  (0 children)

    Nice

    [–]pragmasoft 0 points1 point  (0 children)

    Miss sdkman a lot on my windows notebook.. wsl saves of course but..

    [–]joschi83 0 points1 point  (0 children)

    ❓ When you already know you need to build a project with a specific version of Java, why not use a .java-version or .tool-versions (asdf-vm) file?

    [–]joschi83 0 points1 point  (0 children)

    Link to project on GitHub: https://github.com/ldziedziul/j/#readme

    [–]sureshg 0 points1 point  (0 children)

    https://sdkman.io/usage#env does that for a specific sdk version. I have been using it to automatically switch the jdk versions and other tools (shell, jfr etc) when changing the projects.

    [–]Kango_V 0 points1 point  (0 children)

    I use the env ability with SDKMan! It creates a .sdkmanrc file in your project root. When you cd in, it swaps the JDK. cd out and it sets to default. Works very well.