I'm building a GUI application in Java using JavaFX. So far I've been using Oracle JDK but due to licensing issues, I've decided to move on to OpenJDK or Azul Zulu. They don't come with JavaFX so I built OpenJFX myself on Ubuntu 16.04 (running on WSL).
Now, to wrap the application using Launch4j, I need the only the required JRE files to keep the application size minimum. In Oracle JDK distributions JRE is simply found in JRE folder, however, OpenJDK and OpenJFX have a different structure and I could not find (or missed, my bad) any documentation relevant to my question.
tl;dr: Need the location/path of minimum of required JRE files from OpenJDK and OpenJFX to wrap a cross-platform application using Lanuch4j.
I have a very old application (published in 2001) I am trying to get working in Windows 7/8/10. There is a setup.exe part of it that is using Java in some capacity, and not working correctly. I suspect it is using java because I decompiled the JAR file packaged with the application and there are references to several setup steps within the .java files (along with a file named setup.java). There is also a jre folder published with the application as well, running the following (dated) version:
F:\jre\bin>java -version
java version "1.3.0_01"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.3.0_01)
Java HotSpot(TM) Client VM (build 1.3.0_01, mixed mode)
At first I suspected the application was using the systems environmental variables to use the currently installed version of JAVA, but I ruled that out by completely purging JAVA from the system and retesting - same results.
I next tried to simply update the folder to the latest version. As expected however, there were calls being made that were no longer supported (error message was referencing _JVM_IsVMGeneratedMethodl).
At this point I am running out of options. I could always run this application in a VM (and it works fine), but I would prefer to somehow package it in a nice streamlined way for easy distribution and install. Is there anything I can do? I was thinking something along the lines of application virtualization but still reading up on it.
It's hard to tell without "being there", but I'm guessing that the old (1.3) JVM just isn't compatible with the more modern versions of Windows.
Your best bet is probably running it against whatever version of Windows the app was originally developed on, in a VM.
If you have / can get the complete source code, you could try recompiling it with the version of Java supported on your current system. But it's probably a long-shot.
If it is containing a JRE folder, then you could skip the installer and add some batch file to launch that .jar with the specific JRE via a command of this form:
java -jar pathToYourJAR
btw, you could also consider options to convert to executable, some older are mentioned here:
How can I convert my Java program to an .exe file?
some of them may allow you to select which JRE to bundle/use
Im running Java 1.8.0_065 (64 Bit) on Windows 10 (64 bit). I've downloaded the latest cmake version (3.4.0-rc2) for windows and the latest VTK sources (6.3.0). I generated a VS2015 solution via cmake and set up everything (seemingly!!) successfully using this tutorial:
https://www.particleincell.com/2011/vtk-java-visualization/
When I try to run the DemoJavaVTK.java which is provided by the tutorial I get linker errors in IntelliJ. (14.1.5) At apperently every VTK library that has to be loaded there is the same error:
java.lang.UnsatisfiedLinkError: C:\Program Files\VTK\bin\ANY_VTK_DLL.dll: Can't find dependent libraries at
java.lang.ClassLoader$NativeLibrary.load(Native Method) at
java.lang.ClassLoader.loadLibrary0(ClassLoader.java:1938) at
java.lang.ClassLoader.loadLibrary(ClassLoader.java:1854) at
java.lang.Runtime.loadLibrary0(Runtime.java:870) at
java.lang.System.loadLibrary(System.java:1122) at
vtk.vtkNativeLibrary.LoadLibrary(vtkNativeLibrary.java:223) at
vtk.vtkNativeLibrary.LoadAllNativeLibraries(vtkNativeLibrary.java:158)
at sample.DemoJavaVTK.(DemoJavaVTK.java:54) at
java.lang.Class.forName0(Native Method) at
java.lang.Class.forName(Class.java:264) at
com.intellij.rt.execution.application.AppMain.main(AppMain.java:122)
Mind that ANY_VTK_DLL is just a placeholder. Concrete examples would be: vtkViewsContext2DJava.dll or vtkRenderingVolumeOpenGLJava.dll.
The path should be correct. All the "versions" are 64 bit. I compiled VTK for 64 Bit. I'm running a 64 bit OS with 64 bit java.
The wierdest thing is: Using eclipse everything works fine and I can run the VTK-demo without any problems. Also I'm using VTK for a course at my university, I'm working on my project with a colleague who has the same java and intellij version. He also used the same tutorial to set up VTK/Java. And the example also works in IntelliJ for him. The only difference I can tell between his and my system is, that he is using Windows 8.1 and I am using windows 10.
I really don't know where to continue from here. What is IntelliJs problem?
Got it fixed out of pure randomness by manually setting the JRE via the Run-configurations:
http://puu.sh/l3315/7c1d5e3393.png
Why does this work?
Update:
The UnsatisfiedLinkError denotes that the Java Virtual Machine (JVM) cannot find an appropriate native-language definition of a method declared as native. Specifically, in order to find the required native library, the JVM looks in both the PATH environment variable and the java.library.path system property. (Got from this article)
I used to have this kind of problems mostly because two causes:
The native librarie cannot be found (i.e don't exist)
The library being linked is not the same (Debug vs Release, 32 bit
vs 64 bit, VC10 vs VC9, etc.)
The library is already loaded by your application and the application tries to load it again
The native library is present either in the java.library.path or in the PATH environment library of your application
In order to be sure to whom library you are linking use Dependency Walker. Using this tool will make you understand what's wrong by telling you to which native libraries you are linking to.
Download the tool and then open C:\Program Files\VTK\bin\ANY_VTK_DLL.dll to see to which library it's linking to and where they are in your machine. Then make sure that IntelliJ can find these paths.
Here is a good tuto on how to use this tool: http://www-archive.mozilla.org/quality/help/dependency-walker.html
If they are the correct ones, verify the class path that IntelliJ Idea uses to launch your application to check that the native libraries are there.
I could run using,
System.setProperty("vtk.lib.dir", YourBuildVTKLibPath);
I am new using VTK, took me a while to fix this, I am using eclipse ,
I added to the PATH environment variable the dll folder and the lib folder
We've got a GWT web app that uses JNI to call a dll. We build the dll as well. It works fine on my developer machine, which is a 64-bit Windows 7 machine, running Java 6 and running the webapps in Tomcat 6. But when we run it on the tester's VM which is running 32-bit WinXP, it errors with
java.lang.UnsatisfiedLinkError: Cannot load native JNIWrapper library (jniwrap64.dll)
at com.jniwrapper.Library.loadNativeCode(SourceFile:78)
at com.jniwrapper.Library.loadNativeCode(SourceFile:103)
at com.jniwrapper.Library.ensureNativeCode(SourceFile:113)
at com.jniwrapper.Library.load(SourceFile:189)
My JRE_HOME is set to a 32-bit version of Java 6, because I wanted the build to be able to work on a 32-bit machine, but clearly I'm mis-understanding something about how the 32 or 64-bit versions of java work in compiling the web app.
And yes, the dll that we call is built in to the .war, since it works on my machine.
I also googled the jniwrap64.dll but didn't find much that was relevant.
Added for clarification : jniwrap64.dll is not the dll that I've built, and my code is not explicitly loading this library. That's part of my confusion, is what is this library, why is it being loaded, etc. I have assumed that jniwrap64.dll is some kind of system library that needs to be installed. My code that loads our library is as follows:
Library myLib = Library(path);
myLib.load(this.getClass().getClassLoader());
When you load the dll with System.loadLibrary() do you load "jniwrap64.dll" or "jniwrap32.dll" ? Cna you show us the line of code which loads this library?
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>"