Why doesn't the Java SDK installer set JAVA_HOME? - java

I always wondered why I have to manually set the JAVA_HOME environment variable after installing the Java SDK.
JAVA_HOME=c:\Program Files\Java\jdk1.6.0_12
Visual Studio at least provides a batch file to set these kind of environment variables:
call "c:\Program Files\Microsoft Visual
Studio 9.0\VC\vcvarsall.bat"
Does Java have something similar? I'm trying to make a build script that should simply work after installing the Java SDK. I don't want people to mess with environment variables on their PC.

You can install as many versions of Java as you like.
It would be dangerous for the setup to modify a local environment variable such as JAVA_HOME, since it might reference an existing Java installation.
This has nothing to do with an alleged "platform dependent issue". ;)
Since scripts might depend on JAVA_HOME to launch themselves, again, this would be disasterous for a new Java install to modify JAVA_HOME: all those scripts would suddenly have to be launched with a new potentially incompatible JVM.
Plus, by setting $JAVA_HOME/bin or %JAVA_HOME%/bin in your path, you can dynamically change JAVA_HOME to whatever version of Java you want to use without having to much with your PATH variable.
Michael Borgwardt has made in the comments the interesting followup's question
Still, this does not explain why the installer does not set JAVA_HOME when it is not previously set at all.
The answer is simple:
The setup cannot know if a script already depends on JAVA_HOME or not.
Meaning: some scripts could test for JAVA_HOME value, and if not set, refer to another JVM installed elsewhere (and do not forget that by "install", one can only refer to "copied": a JDK/JRE is not always installed by a setup)
If you set JAVA_HOME, that can disrupt the default behavior of some of your scripts.
Not wanting to disturb hypothetical scripts that depend on a env var not being set sound pointlessly paranoid to me - If a script does that, then it clearly WANTS to use a different JVM when one is installed - no reason to avoid that.
Mmm... Sweet. For dealing with massive deployment issues on a daily-basis (for internal application in my shop), I can assure you: it is very sane "paranoid"
treat to have.
When you deploy to a (very) large set of users, you do not want to make any assumption about their platform and configurations. "clearly WANTS" is an assumption I would not dare to make (or I redirect my phone to yours ;) and you handle the angry calls).
For instance, we have many scripts which launches with a 1.4.2 JVM from sun (JAVA_HOME not set on development platform, default path set directly in the script), or with 1.4.2 from JRockit (JAVA_HOME set, as it is the intended target on integration, pre-production and production platforms).
But we install regularly the new JDK1.6.x since we use it for launching eclipse.
Assume that those scripts want their JAVA_HOME set... and nothing works anymore.
... To which Robert Grant makes this on-the-spot critic:
You're describing scripts that require one specific version, but still look at global JAVA_HOME. That's just badly thought out scripts.
While that may or may not be true, that also illustrates precisely my point:
"you do not want to make any assumption": no assumption on their platform/settings, and no assumption on their "best practices".
The former may sound paranoid, the latter is plain common-sense: thinking that your product (here a JDK setup) will not break anything on the user's environment because the user has "correctly" thought out his scripts... would be insane.
GvS suggests:
Or it could just have option to do it, disabled by default
That would mean another option to include in the setup screens, option which should be carefully reviewed by the user, and which may have unintended consequences, even when the user selects it thinking he knows what he is doing...
It is simply not worth it.

I don't think JAVA_HOME is a convention invented or supported by Sun.
They probably remember the fiasco that was the CLASSPATH environment variable** all too well and prefer to stay the hell away from environment variables.
** This was encouraged as the primary way to set the JVM classpath in earlier Java SDKs and literature, and resulted in the user and various applications messing with the environment variable, overwriting each other's changes and depending on mutually contradictive contents.

The vcvarsall.bat mechanism is a convenient way for Visual C++ to provide a console with the correct variables without messing with the user's/system's environment variables. However, it assumes that Installshield is the only way to get code onto the system. The JDK should tolerate being cut'n'pasted from one location to another.
If you're looking for java.exe, the Installshield installer should put it in %windir%\system32, so it is available on the PATH.
You can gain some hints about the location of installed apps by querying the registry:
C:>REG QUERY "HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\Java Development Kit\1.6" /v JavaHome
! REG.EXE VERSION 3.0
HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\Java Development Kit\1.6
JavaHome REG_SZ C:\dev\Java\jdk1.6.0_05
However, you can't rely on this absolutely because this makes some assumptions about vendor, version and installation mechanism.

This may help someone else out who ends up here like me. I just want to use Java as a tool, not adopt it as a way of life, so I only needed to know how JAVA_HOME was getting set and why it was not correct. The answer turned out to be that the WinAnt installation sets JAVA_HOME (along with ANT_HOME), but only based on the currently installed Java. So if you need to change the version of Java, and you are using Ant, the correct way to do it is to uninstall WinAnt, uninstall Java, install the new Java, and then reinstall WinAnt.

I'm not sure why this is, because the installers clearly solve platform dependant issues (which is ofcourse the whole point of a JVM). Are you sure you aren't mixing the JRE with the JSDK?
Maybe there's a way for your program to search where java is installed (that would be a script I guess), and then set JAVA_HOME and possibly add it to the path.
IBM seems to be doing this trick already:
http://www-01.ibm.com/support/docview.wss?rs=180&uid=swg21199220
Other interesting post hinting at the difference between JRE and JSDK installations:
http://confluence.atlassian.com/display/CONF26/Set+JAVA_HOME+variable+in+Windows
Hope this helps.

I guess java doesn't want to do anything which is platform-dependent. In Windows, classpaths are set differently from LINUX/UNIX.

Related

A better way how to make Eclipse resistant to Java updates

It is a know problem, when you update Java, JDK or JRE, on Windows Eclipse will likely to fail to start as it points to outdated JDK/JRE folder. Fix is relatively simple, it was discussed and solved on several threads like here or here.
But I found those solutions unsatisfyingly inflexible. This solutions suggest to manually fix path in eclipse.ini to something like:
-vm C:\Program Files\Java\<jdk-version-just-installed>\bin\javaw.exe
This means you have to do it after every update, again and again. If you update JDK frequently, and everyone should to have latest security patches, that makes it very annoying.
I expect that after a smart installation every Java program would just run out of box without any manual step involved; any solution less than that I would not consider satisfactory.
I can think of two ways:
using environmental (system) variable like JAVA_HOME. Can eclipse.ini reference environmental variables?
using symbolic link pointing to the latest JDK. And if you wonder, yes, Windows with NTFS support symlinks.
Both ways however need some cooperation from the installer, both JAVA_HOME or symlink as to be updated to the new value. Automatically of course, otherwise there would be no reason why to have them in the first place.
Please correct me if I am wrong, but JDK/JRE installation on linux does exactly that, provides and updates symlink to latest JDK/JRE. Why not Windows installer?
Is there a hidden parameter, option or a toggle in Java install tool doing that?
If not, is there a better, an alternative installation tool?
Can Eclipse launcher itself find a latest Java?
Is there a better eclipse.ini parameter for that?
The purpose of specifying the VM in either eclipse.ini or on the command line is to isolate it from system updates. For example, in the past it has been a big problem that some programs install their own JVM and include it on the system PATH (Oracle was particularly bad about this). So the entire idea is to isolate Eclipse from those kinds of changes; it should not care what other JVMs you have on your system, it refers to a "known" good one for running Eclipse.
Another alternative is to place a JVM directly under the Eclipse installation directory, in a directory named jre, as documented here. I don't personally ever do that, however; I find it to be unnecessary and cumbersome.
What I do that would probably help you is to not install JVM updates into separate directories with names that reflect the actual update version. Instead, I install JDKs into a consistent place based on the major java version. For example:
/Java/
/JDK/
/1.7/
/bin/
<etc...>
/1.8/
/bin/
<etc...>
That way, in eclipse.ini (or any other place a need to refer to a particular JVM) I just use /Java/JDK/1.8 and that will continue to work no matter how many updates I install into that location.
What we do to avoid this problem: We have custom dedicated JDK's for our development environment (for eclipse and for our products), which are not 'attached' to the system. We're using softlinks e.g. ../app/jdk which links to a specific jdk, for intellij we have a ../app/intellij-jdk softlink.
Not sure who to do it in windows, but in linux you download the gzip and extract it, withing messing up your system, like paths, I think for windows you can only download the installer, but it's possible to only extract the actual software from the executable.
Older Windows JDK installers used to copy java.exe and javaw.exe (and also javavm.dll I think) in c:\windows\system32 to make them available in the default path.
In recent installers, a symbolic link is created for java.exe, javaw.exe and javaws.exe in C:\ProgramData\Oracle\Java\javapath. This means that these executables will point always to the most recent JDK update.

Why doesn't the Java Installer set the environment variable PATH automatically? [duplicate]

I always wondered why I have to manually set the JAVA_HOME environment variable after installing the Java SDK.
JAVA_HOME=c:\Program Files\Java\jdk1.6.0_12
Visual Studio at least provides a batch file to set these kind of environment variables:
call "c:\Program Files\Microsoft Visual
Studio 9.0\VC\vcvarsall.bat"
Does Java have something similar? I'm trying to make a build script that should simply work after installing the Java SDK. I don't want people to mess with environment variables on their PC.
You can install as many versions of Java as you like.
It would be dangerous for the setup to modify a local environment variable such as JAVA_HOME, since it might reference an existing Java installation.
This has nothing to do with an alleged "platform dependent issue". ;)
Since scripts might depend on JAVA_HOME to launch themselves, again, this would be disasterous for a new Java install to modify JAVA_HOME: all those scripts would suddenly have to be launched with a new potentially incompatible JVM.
Plus, by setting $JAVA_HOME/bin or %JAVA_HOME%/bin in your path, you can dynamically change JAVA_HOME to whatever version of Java you want to use without having to much with your PATH variable.
Michael Borgwardt has made in the comments the interesting followup's question
Still, this does not explain why the installer does not set JAVA_HOME when it is not previously set at all.
The answer is simple:
The setup cannot know if a script already depends on JAVA_HOME or not.
Meaning: some scripts could test for JAVA_HOME value, and if not set, refer to another JVM installed elsewhere (and do not forget that by "install", one can only refer to "copied": a JDK/JRE is not always installed by a setup)
If you set JAVA_HOME, that can disrupt the default behavior of some of your scripts.
Not wanting to disturb hypothetical scripts that depend on a env var not being set sound pointlessly paranoid to me - If a script does that, then it clearly WANTS to use a different JVM when one is installed - no reason to avoid that.
Mmm... Sweet. For dealing with massive deployment issues on a daily-basis (for internal application in my shop), I can assure you: it is very sane "paranoid"
treat to have.
When you deploy to a (very) large set of users, you do not want to make any assumption about their platform and configurations. "clearly WANTS" is an assumption I would not dare to make (or I redirect my phone to yours ;) and you handle the angry calls).
For instance, we have many scripts which launches with a 1.4.2 JVM from sun (JAVA_HOME not set on development platform, default path set directly in the script), or with 1.4.2 from JRockit (JAVA_HOME set, as it is the intended target on integration, pre-production and production platforms).
But we install regularly the new JDK1.6.x since we use it for launching eclipse.
Assume that those scripts want their JAVA_HOME set... and nothing works anymore.
... To which Robert Grant makes this on-the-spot critic:
You're describing scripts that require one specific version, but still look at global JAVA_HOME. That's just badly thought out scripts.
While that may or may not be true, that also illustrates precisely my point:
"you do not want to make any assumption": no assumption on their platform/settings, and no assumption on their "best practices".
The former may sound paranoid, the latter is plain common-sense: thinking that your product (here a JDK setup) will not break anything on the user's environment because the user has "correctly" thought out his scripts... would be insane.
GvS suggests:
Or it could just have option to do it, disabled by default
That would mean another option to include in the setup screens, option which should be carefully reviewed by the user, and which may have unintended consequences, even when the user selects it thinking he knows what he is doing...
It is simply not worth it.
I don't think JAVA_HOME is a convention invented or supported by Sun.
They probably remember the fiasco that was the CLASSPATH environment variable** all too well and prefer to stay the hell away from environment variables.
** This was encouraged as the primary way to set the JVM classpath in earlier Java SDKs and literature, and resulted in the user and various applications messing with the environment variable, overwriting each other's changes and depending on mutually contradictive contents.
The vcvarsall.bat mechanism is a convenient way for Visual C++ to provide a console with the correct variables without messing with the user's/system's environment variables. However, it assumes that Installshield is the only way to get code onto the system. The JDK should tolerate being cut'n'pasted from one location to another.
If you're looking for java.exe, the Installshield installer should put it in %windir%\system32, so it is available on the PATH.
You can gain some hints about the location of installed apps by querying the registry:
C:>REG QUERY "HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\Java Development Kit\1.6" /v JavaHome
! REG.EXE VERSION 3.0
HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\Java Development Kit\1.6
JavaHome REG_SZ C:\dev\Java\jdk1.6.0_05
However, you can't rely on this absolutely because this makes some assumptions about vendor, version and installation mechanism.
This may help someone else out who ends up here like me. I just want to use Java as a tool, not adopt it as a way of life, so I only needed to know how JAVA_HOME was getting set and why it was not correct. The answer turned out to be that the WinAnt installation sets JAVA_HOME (along with ANT_HOME), but only based on the currently installed Java. So if you need to change the version of Java, and you are using Ant, the correct way to do it is to uninstall WinAnt, uninstall Java, install the new Java, and then reinstall WinAnt.
I'm not sure why this is, because the installers clearly solve platform dependant issues (which is ofcourse the whole point of a JVM). Are you sure you aren't mixing the JRE with the JSDK?
Maybe there's a way for your program to search where java is installed (that would be a script I guess), and then set JAVA_HOME and possibly add it to the path.
IBM seems to be doing this trick already:
http://www-01.ibm.com/support/docview.wss?rs=180&uid=swg21199220
Other interesting post hinting at the difference between JRE and JSDK installations:
http://confluence.atlassian.com/display/CONF26/Set+JAVA_HOME+variable+in+Windows
Hope this helps.
I guess java doesn't want to do anything which is platform-dependent. In Windows, classpaths are set differently from LINUX/UNIX.

Installing JDK vs Portable JDK

As I know, there are two ways to use JDK in windows:
Download JDK installation file and install.
Download JDK binary.
What's the difference between them?
Pros: Simple and easy, all of a sudden everything works. Cons: Everything now uses the new version - which may not be the desired effect.
Pros: You can put it anywhere you like and make sure it is only accessible by code you expect. Cons: More work involved - usually requires manual intervention.
You don't need to unpack, set JAVA_HOME and PATH environment variables manually. This all is done for you.
You should set environment variables below manually, but you may have more than one installation of one major build (different build, for example). Also, you may put it in any place you want it to be in.

I make my executable jar in exe format,but i want to add jre with this

I make my executable jar in exe format, but I want to add JRE with this because if JRE is not present in their machine, they can use it with this included JRE.
But I do not want to install this JRE in their machine. This JRE is only used by this application only. It will just like game or other application. I use launch4j to make jar to exe but i did not find any option from where it can attach JRE and it has no option from where I can link my jar dynamically.
How do I achieve that?
If there is other free installer then mention it, and please give the procedure with example.
Since it has been established that your app. has a GUI, I will suggest Java Web Start as the answer.
But I do not want to install this JRE in their machine.
That is not a sensible requirement. The user might already have a usable JRE installed, if they don't they probably also don't want every Java based application to be installing its own 'private' JRE.
Oracle's deployJava.js can do the checking, and help guide the user through the steps of installing (which basically comes down to click 'OK' when prompted).
I make my executable jar in exe format,..
If you only intend to support Windows, what is the attraction of coding in Java? JWS supports any platform for which Java is available. That brings a lot more potential customers for the app.
I want to use free installer.
JWS is entirely free. Just like the JRE.
..please give the procedure with example.
Do you run an IDE? If not, do you otherwise have Ant installed? If that is a yes to either one, check out my small JNLP API examples. Each comes with complete source and a build file (an Ant build.xml).
Within a couple of keystrokes & a few moments, you can see the app. installed and launched on your desktop. For the end user, it is even simpler. Just click a link in a web page, and it all happens automatically (possibly with a security prompt - for the protection of the user).
I like JSmooth. You can give it a try here:
http://jsmooth.sourceforge.net/features.php
Flexible automatic Java VM detection
Detects the location of any Sun JVM installed. The wrappers use
several strategies to detect all the JVM available on a computer,
using windows registry, environment variables, windows path.
Detects
and uses Microsoft's JView (for 1.0 and 1.1 Java applications), if
available.
The JVM search sequence is fully customizable using the
GUI. You can force the executable to search in the path first, and in
the registry last, or in JAVA_HOME first. We have all the flavours!
Sometimes it's more convenient to bundle a JRE with your application.
JSmooth can deal with that too, you just need to define in which
folder the JRE is expected. It falls back nicely to a standard JVM
search if the JRE is not where it should be.
Specify which versions of
the JVM are compatible with your software. You can set a minimum
version, but also a maximum JVM version.
Documentation: http://jsmooth.sourceforge.net/docs/jsmooth-doc.html
Take a look at launch4j.
I had to use it, and it worked out very well.
You can set a minimum version of a needed JRE, bundle a JRE, or if a JRE is not found (and not bundled) the launcher may lead the user to a download location of an appropriate JRE.
There are various further features launch4j offers, and as opposed to another suggestion here, launch4j is activly developed
http://launch4j.sourceforge.net/

How do I properly repackage the JRE installer in my installer?

I've got a Java application that I'm writing an installer for. We're using the AdvancedInstaller program to create our installer (well, we're evaluating it currently, but will definitely purchase a license soon), and although it has special support for Java applications, it is geared more towards repackaging them as desktop-type apps, and our software is a series of Java services and other utilities which doesn't make sense to distribute in EXE-wrappers. The target audience for this software is very specific, and we know that our software will probably be automatically distributed on freshly-imaged Windows 2003 Server machines. So requiring Java as a prerequisite basically makes more work for some poor sysadmin, and I'd rather avoid that if at all possible by repackaging the JRE's installer inside of our own.
I discovered that if I tried to execute the JRE's installer as a pre-install step from my MSI, it complains that another installer is already running (mine, of course), so it bails out. When I try to add the JRE installer as a software prerequisite in the AdvancedInstaller project (as a bundled EXE, not a URL link), it never seems to actually get installed, despite me trying to force-install it.
What's the best way to repackage the JRE? I'm not really a Java guy, so I don't know too much about how other developers deal with this same problem, short of requiring their users to hunt out and install the JRE on their own. The ideal solution here would be for us to find a EXE installer which can be executed from inside of another MSI installer, or if it's possible, to just package all of the files inside of the JRE and then create the appropriate registry and environment variables. How should I go about doing this?
I have not idea if this is "the way" to do it, but confronted with a somewhat similar problem, we simply archive an installed JRE with the rest of our application files and make sure that all our start scripts don't use java ..., but rather ..\..\jre\bin\java ... or similar. The JRE is unpackaged as part of our installation process in a subdirectory of where we install and that's that.
I agree with bdumitriu's answer:
a simple zip of a jre is enough, unless you want to link that jre to:
default java (meaning you must add java.exe of the unzipped jre to the path, before any other java path references)
default java for some script (you could define JAVA_HOME as referencing your new unzipped jre, but that may have side effects on other script also using JAVA_HOME before that new JRE)
file associations like .jnlp or .jar files (this requires some registry modifications)
browser java plugin registration (which requires also registry modifications)
If the last two points do not interest you on the desktop concerned by this deplyment, a simple zip is enough.
http://www.syswow64.co.uk/2013/05/java-7-update-21-1721-enterprise.html
The issue on many blogs and articles is around creating the 'deployment.config' and 'deployment.properties' files for an enterprise deployment. In my case i wanted to set the security level to 'Medium', but everytime I open the Java control panel it was set to the default HIGH setting.

Categories

Resources