'RVM-like' tool for Java - java

I am looking for a tool that would let me switch the running Java implementation, like Ruby's RVM (or RBENV). I am aware that Debian systems provide the alternatives mechanism, and that I can set JAVA_HOME manually.
However, I'd like something more automated if possible. If it could fetch JDKs that would be even better, but not necessary.
I've searched but didn't see anything like it. My guess the Java ecosystem got used to having this functionality in an IDE.
Edit: Changing PATH and JAVA_HOME seems to work fine. It could be trivially automated.

There's jenv, based on Ruby's RVM.
You have to go through some manual steps to add new Java versions†, but once they're in you can switch between them using jenv use java $version. It also handles installing Java applications against specific Java versions.
There's also another tool that I haven't used, confusingly also named jenv but based on Ruby's rbenv instead.
† The hassle adding Java versions appears to be due to Oracle, perhaps licensing issues, and seems to apply to both tools.

I think there is no such tool. Every platform has hits own system. Debian/Ubuntu, RedHat/CentOS and SLE/OpenSUSE ( probably some other distributions as well) use the alternative mechanism. Mac OSX has its own buildin switching mechanism to change the current used JVM.
I have to maintain a lot of developer workstations and servers. All *nix based (OSX, Linux, Solaris) and used to install all JVMs in a directory and create a symlink CURRENT to the Version that should be used. The JAVA_HOME and PATH variable pointing to this CURRENT symlink. If Ia want to use another version only haf to move the CURRENT symlink. No further actions are necessary.
Unfortunately this approach does not work for Windows based systems.

For those looking for such tool in 2016+ - try jabba. It's designed after nvm/gvm/rvm (in fact CLI is almost identical to the one of nvm).
jabba install 1.8 # "jabba use 1.8" will be called automatically
jabba ls # list all installed jdk's
jabba use 1.6 # switch to a different version of jdk
Full disclosure: I'm maintainer of the project.

SDKman is the way to go:
The Software Development Kit Manager
SDKMAN! is a tool for managing parallel versions of multiple Software Development Kits on most Unix based systems. It provides a convenient Command Line Interface (CLI) and API for installing, switching, removing and listing Candidates. Formerly known as GVM the Groovy enVironment Manager, it was inspired by the very useful RVM and rbenv tools, used at large by the Ruby community.
https://sdkman.io/
Specifically mentions RVM and, like RVM, install through curl:
Get started now!
Go on, paste and run the following in a terminal:
$ curl -s "https://get.sdkman.io" | bash

Related

What JDK should I compile with to support most desktop users? [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 7 months ago.
Improve this question
I write a few small, free, desktop command-line applications in Java. I package those as JAR files in releases on GitHub. About a year ago in light of Oracle licensing changes, I switched from the Oracle JDK to Open JDK. Developing on Windows, this is what I currently have installed:
C:\Users\admin>java -version
openjdk version "17.0.1" 2021-10-19
OpenJDK Runtime Environment (build 17.0.1+12-39)
OpenJDK 64-Bit Server VM (build 17.0.1+12-39, mixed mode, sharing)
Now, about a week ago I was visiting a friend (also a software developer) and a reason came up where we wanted to run my application on his Windows box. He didn't have Java installed. So, watching over his shoulder, he went to the java.com "Download Java for Windows" page (currently listing Java Version 8 Update 341), downloaded, and installed it.
Then when he went to run my application, it failed to run, giving back an error along the lines of (paraphrasing from memory), "This version of the JRE does not support a later version of Java". This surprised both of us; he didn't know there was a later version of Java, and I didn't know compiling with the current OpenJDK would make a non-supported binary.
What's the best practice to fix this release problem?
Your user most likely ran into the issue that Java classes compiled with a newer class file version number do not run on older JVMs. If that is the only issue it can be addressed by recompiling ...
But there is a deeper issue. Older Java class libraries don't support all of the APIs provided by newer versions of Java. Also there have been some important architectural changes starting in Java 9 (e.g. addition of modules, removal of applets and closing off access to JDK internal classes) that "break" applications that run on older Java versions
What this means is that if you develop and test your code on Java 17 (say) there is a significant chance that it won't work on (say) Java 8 ... even if you compiled it for Java 8. And vice versa, because some APIs have been removed, or made inaccessible or ... work differently.
So my advice would be:
Decide on a specific range of Java versions you will support for your application; e.g. Java 8 LTS1 through Java 17 LTS.
Develop targeting the oldest Java version and its APIs.
Build and test on the Java oldest version.
Also test on (at least) all of the other LTS Java versions ... within the range you are supporting.
This will mean that you are limited to using the APIs and Java language features of your oldest supported version. This could hold you back, so you have to choose between that and supporting users with old (out of date) versions of Java.
The issue of users trying to install / use old versions of Java can be addressed in three ways:
Provide clear installation instructions to the user that say what kind / version(s) of Java they need to install, and where to get them from. (And how to set or configure JAVA_HOME if your application relies on that.)
Of course, some users won't read the instructions properly, but that is their lookout ...
Use jlink to turn your application into a custom JVM, and distribute your code that way.
Use jpackage to create platform specific binaries.
If you take the jlink or jpackage routes, the onus will be on you to push out new distributables whenever there are Java security patches that are relevant to your application. Your users won't be able to "just install the latest Java patches" anymore.
Note that jlink is available for Java 9 onwards, and jpackage from Java 16 onwards.
What JDK should I compile with to support most desktop users?
I don't think there is a good answer to that. We can't tell you what proportion of "desktop" users have each version of Java installed. (Or what they are permitted to install; e.g. by corporate policy.) But you can't support old Java versions indefinitely.
I did find this though:
Java 8 still dominates, but Java 17 wave is coming – survey - dated March 2022.
1 - Java 7 and earlier are all well beyond "end of life". You are not helping anyone by trying to support them.
Well, you have a few options...
First of all you can TARGET the version 8 runtime, but you can compile code from later revisions of the language. This may or may not work in all cases, as Java 9 and up do some things rather differently! Still, fairly vanilla Java that isn't doing weird ClassLoader stuff is LIKELY to work, and you can certainly avoid problematic constructs.
Secondly, you can simply stick to Java 8! It is ANCIENT but it is a virtually immortal LTS, due to the reason above that things in Java 9 are different. However, you will miss out on new things.
You COULD go whole hog and move on from Java 17 to GraalVM, which can be had in versions compatible with Java11, Java17, etc. It has the ability to compile code down to a completely stand-alone binary, using native-image, and again unless you do some fairly esoteric stuff, your code will work. The end result will be similar to using something like C++. You can even build shareable libraries.
I guess your other option is to just make sure people are not using Java8. Ideally they're using Java11, but I guess now java17 is the newest LTS, though few people seem to install it.
It looks like you are using Java 17. Developers of apps targeting Java version after 8 are expected to supply the runtime for running the application. This means there is no more 'downloading and installing Java' separately on the user side. This is also why the download page you refer to only offers Java 8.
In practice, this means that you should use jlink to create a runtime image (i.e. the thing that you would previously download and install) that can run your application.
jpackage can also be used to create application images and installers (it calls jlink under the hood). Both of those are tools that come with the JDK.
For your purposes I recommend using jpackage with something like this:
jpackage `
--win-console `
--main-jar app.jar `
--main-class Main `
--name myapp `
--type app-image `
--input input
In this command, input is a folder that has the main app.jar in it (Note: the input folder should not be the current directory, since that will lead to infinite recursion).
--win-console is also needed for console applications on Windows, since otherwise no console is created when running the app.
This command will create a myapp folder that you can zip/tar up and distribute.
This myapp folder has a myapp.exe launcher that can be used to run the application.
Also, note that this will create a runtime image with a default set of modules. If your jar is modular (i.e. it has a module-info file), I suggest using --module instead of --main-jar/--main-class, since that will use the module descriptor to determine the set of modules in the runtime image. (See jpackage --help)
Note that on Windows you will also need to install the wix toolkit. It can be installed easily through e.g. scoop:
scoop install wixtoolset

Java 7 update 25 silent installation fails if another version of java already exists

I am trying to install java from install shield script
1) I have no other version of Java in my PC and When I install Java 7 silently it installs correctly
2) If I have any other java version already installed in my PC and I try to install Java 7 silently it fails
Do we have an option to install java silently even though it detects another version of java is already installed?
Why is the install failing?
The first thing you should probably do is find out for sure why the JRE install is failing.
The Windows version of it takes some command-line parameters that may be of some use to you. For logging /L <path_to_log> will create a log file.
I usually extract the MSI from the EXE's that Oracle makes available. Using the MSI directly allows you to specify install properties without having to please InstallShield's goofy command-line syntax. If you launch the EXE downloaded from Oracle (but don't proceed—just let it extract itself), look in the user's AppData\LocalLow\Sun\Java directory for a dir corresponding to the version of Java whose installer you just launched (e.g. jre1.7.0_25). Get the MSI and other files from there.
With the MSI, you can specify logging options on the command-line, like msiexec /i <jre_msi_file> /lxv* C:\temp\jre_install.log.
I'm pretty sure I've seen instances where JRE installers will effectively block the installation of an older ("less secure") version. It might be that this is what's happening in your case. You should see an indication of such in the install log file. If that's the case, I think there's a registry key that you can remove to "unblock" the install.
Static vs. Patch-in-Place
Another potential source of trouble is the type of install you want (or previously used). Oracle has two install methods that you may need to expressly specify when you install it.
A patch-in-place install always leaves a single version of the JRE installed, removing the old one (or upgrading it—I'm not certain about the details of how it's done) and leaving the new one in its place. This is the default behavior, and is probably what you will want to use. Browsers can only use one version of Java at a time, so there's not much reason to have older versions around if you're only interested in having Java in the browser.
A static install creates a new install of Java for every unique version number. This would be useful if you needed to be able to choose among some precise versions of Java for specific applications. Programs relying on quirky/undocumented behavior of specific Java VM implementations might need to use such an installation. In general, though, this kind of thing should be avoided, if for no other reason, than to avoid leaving JRE versions with known (and actively exploited) security vulnerabilities.
You can specify which install type on the command-line with STATIC=0 (a patch-in-place install) or STATIC=1. This should work with either the EXE or the MSI.

Should I remove normal Java before install Java Development Kit?

I have normal java installed already. now I want to install a software which requires the 2:
Java Development Kit 6 or higher (http://java.sun.com/javase/downloads/index.jsp)
Maven 2.2.1 or higher (http://maven.apache.org/)
Should I remove normal java to install the Development Kit?
No you do not have to. However JDK contains the runtime environment (JRE), so if you can safely remove it, if you wish so.
EDIT: Although, as Johannes points out, you may need to take care of PATH environment variable and file associations on Windows.

Is there an uniform way to detect the installed java on linux?

Is there a way to detect the installed java on various different Linux distributions?
With Windows you could use the JAVA_HOME or the registry for that, but Linux? Can it be also detected if this is JDK, JRE, 32 or 64 bit?
REPHRASE: If I need 64-bit JDK on Linux, how do I programatically check that it is present and inform the user that he has some other java instead?
You can always use java -version.
This works on all platforms, but make sure that Java is included in the system PATH variable.
No unified way. You can use JAVA_HOME env. variable but it is not defined on all machines.
But there is a "common" way like ls /usr/java/*/bin/java | tail -1.
This should give in most cases you the latest version.
To see the file called by the java command use which java, although this will often be just a symlink to the real executable, such as /usr/bin/java. This works across all distros as far as I know.
On some Linux distros you can use update-alternatives --display java (possibly with sudo) to see a list of all the java executables installed on your system, and it will also tell you which one the symlink points to. You can switch between them by using the --config option instead.
You can use java -version in the terminal to find out some info.
There are many answers here helping you to check if Java is installed. If this is the case you can get more information programatically. SystemUtils of commons-lang gives you many information about the Java version actually running.

Multiple Java versions running concurrently under Windows

We have a couple of applications running on Java 5 and would like now to bring in an application based on Java 6. Can both java versions live together under Windows?
Is there any control panel to set the appropriate Java version for different applications, or any other way to set up, what version of Java will be used to run that particular application?
Of course you can use multiple versions of Java under Windows. And different applications can use different Java versions. How is your application started? Usually you will have a batch file where there is something like
java ...
This will search the Java executable using the PATH variable. So if Java 5 is first on the PATH, you will have problems running a Java 6 application. You should then modify the batch file to use a certain Java version e.g. by defining a environment variable JAVA6HOME with the value C:\java\java6 (if Java 6 is installed in this directory) and change the batch file calling
%JAVA6HOME%\bin\java ...
I was appalled at the clumsiness of the CLASSPATH, JAVA_HOME, and PATH ideas, in Windows, to keep track of Java files. I got here, because of multiple JREs, and how to content with it. Without regurgitating information, from a guy much more clever than me, I would rather point to to his article on this issue, which for me, resolves it perfectly.
Article by: Ted Neward: Multiple Java Homes: Giving Java Apps Their Own JRE
With the exponential growth of Java as a server-side development language has come an equivablent
exponential growth in Java development tools, environments, frameworks, and extensions.
Unfortunately, not all of these tools play nicely together under the same Java VM installation. Some
require a Servlet 2.1-compliant environment, some require 2.2. Some only run under JDK 1.2 or above,
some under JDK 1.1 (and no higher). Some require the "com.sun.swing" packages from pre-Swing 1.0
days, others require the "javax.swing" package names.
Worse yet, this problem can be found even within the corporate enterprise, as systems developed using
Java from just six months ago may suddenly "not work" due to the installation of some Java Extension
required by a new (seemingly unrelated) application release. This can complicate deployment of Java
applications across the corporation, and lead customers to wonder precisely why, five years after the
start of the infamous "Installing-this-app-breaks-my-system" woes began with Microsoft's DLL schemes,
we still haven't progressed much beyond that. (In fact, the new .NET initiative actually seeks to solve the
infamous "DLL-Hell" problem just described.)
This paper describes how to configure a Java installation such that a given application receives its own,
private, JRE, allowing multiple Java environments to coexist without driving customers (or system
administrators) insane...
It is absolutely possible to install side-by-side several JRE/JDK versions. Moreover, you don't have to do anything special for that to happen, as Sun is creating a different folder for each (under Program Files).
There is no control panel to check which JRE works for each application. Basically, the JRE that will work would be the first in your PATH environment variable. You can change that, or the JAVA_HOME variable, or create specific cmd/bat files to launch the applications you desire, each with a different JRE in path.
We can install multiple versions of Java Development kits on the same machine using SDKMan.
Some points about SDKMan are as following:
SDKMan is free to use and it is developed by the open source community.
SDKMan is written in bash and it only requires curl and zip/unzip programs to be present on your system.
SDKMan can install around 29 Software Development Kits for the JVM such as Java, Groovy, Scala, Kotlin and Ceylon. Ant, Gradle, Grails, Maven, SBT, Spark, Spring Boot, Vert.x.
We do not need to worry about setting the _HOME and PATH environment variables because SDKMan handles it automatically.
SDKMan can run on any UNIX based platforms such as Mac OSX, Linux, Cygwin, Solaris and FreeBSD and we can install it using following commands:
$ curl -s "https://get.sdkman.io" | bash
$ source "$HOME/.sdkman/bin/sdkman-init.sh"
Because SDKMan is written in bash and only requires curl and zip/unzip to be present on your system. You can install SDKMan on windows as well either by first installing Cygwin or Git Bash for Windows environment and then running above commands.
Command sdk list java will give us a list of java versions which we can install using SDKMan.
Installing Java 8
$ sdk install java 8.0.201-oracle
Installing Java 9
$ sdk install java 9.0.4-open
Installing Java 11
$ sdk install java 11.0.2-open
Uninstalling a Java version
In case you want to uninstall any JDK version e.g., 11.0.2-open you can do that as follows:
$ sdk uninstall java 11.0.2-open
Switching current Java version
If you want to activate one version of JDK for all terminals and applications, you can use the command
sdk default java <your-java_version>
Above commands will also update the PATH and JAVA_HOME variables automatically. You can read more on my article How to Install Multiple Versions of Java on the Same Machine.
It should be possible changing setting the JAVA_HOME environment variable differently for specific applications.
When starting from the command line or from a batch script you can use set JAVA_HOME=C:\...\j2dskXXX to change the JAVA_HOME environment.
It is possible that you also need to change the PATH environment variable to use the correct java binary. To do this you can use set PATH=%JAVA_HOME%\bin;%PATH%.
I use a simple script when starting JMeter with my own java version
setlocal
set JAVA_HOME="c:\java8"
set PATH=%JAVA_HOME%\bin;%PATH%;
java -version
To have a java "portable"
you can use this method here:
https://www.whitebyte.info/programming/java/how-to-install-a-portable-jdk-in-windows-without-admin-rights
Or use links. While it is rather unpleasant to update the PATH in a running environment, it's easy to recreate a link to a new version of JRE/JDK. So:
install different versions of JDK you want to use
create a link to that folder either by junction or by built-in mklink command
set the PATH to the link
If other version of java is to be used, delete the link, create a new one, PATH/JAVA_HOME/hardcoded scripts remain untouched
Invoking Java with "java -version:1.5", etc. should run with the correct version of Java. (Obviously replace 1.5 with the version you want.)
If Java is properly installed on Windows there are paths to the vm for each version stored in the registry which it uses so you don't need to mess about with environment versions on Windows.
If you use Java Web Start (you can start applications from any URL, even the local file system) it will take care of finding the right version for your application.
Using Java Web Start, you can install multiple JRE, then call what you need.
On win, you can make a .bat file:
1- online version:
<your_JRE_version\bin\javaws.exe> -localfile -J-Djnlp.application.href=<the url of .jnlp file.jnlp> -localfile -J "<path_temp_jnlp_file_.jnlp>"
2- launch from cache:
<your_JRE_version\bin\javaws.exe> -localfile -J "<path_of_your_local_jnlp_file.jnlp>"

Categories

Resources