Steps for installing JRE to users' pc manually - java

I am currently working on a jar file and I am going to distribute it soon. I was looking forward to distributing it for user without him needing installing JRE to run my app. I am well aware of tools like Jar2Exe but those tools inject some additional content to the executable and I am not going to buy license for that! So I am working on a solution. And I have the idea, So I will create a C file with this content ( I am using C Language power in nativity! ) :
#include <stdlib.h>
int main() {
system("java -jar test.jar");
return 0;
}
And I will put the jar file and the compiled file of the C file above and java.exe located in my JRE installation dir in a same directory and this should work but surely there are a bunch of dlls that java.exe depends on them! A list of those dependencies to put them all in a directory and make the idea work will be very helpful:)
Please Note : I don't want to create an executable from the JAR file, I only want the user need not INSTALL JRE.
EDIT
I realized the above approach isn't practical, so I am going to install JRE behind the scenes ( my only goal is that the user doesn't find out whats going on in the installation process ) I am going to copy required files to ProgramFiles/jre_version but what in addition should I do? In the other words what does the JRE installer do under the hood?

Why do you think those other companies want you to pay money for their product?
Hint: because it ain't that easy.
The point is that not only need your JAR file. You need to make each and any class that your code will be using available to the JVM you are starting up.
You know, exactly that other stuff that those commercial tools are backing into their EXE files; the stuff that you think makes their EXE files so big and slow. That is the stuff that you need to run your java classes ...
The JRE alone comes with megabytes and megabytes of java classes, packaged up in various JARs. And any 3rd party library that you are using will be required too.
So, of course, when you are able to find all classes that will be loaded when your code is executed, then you could manually package that into a single JAR. But as said: if that would be an easy undertaking, those other people wouldn't have much of a business case. And of course: as soon as reflection and Class.forName() kicks in, you are completely broken. Because you can't predict at all, which classes will be used at runtime then.

Related

Java Jar file main class run when runs from command line, but not from Windows batch file

I'm re-using a standalone Swing-based Java class which backs up and restores mysql databases.
I've tested running it from a Windows batch file (.bat) on my dev system, and it works there.
But, if I run the batch file on a different Windows , I get a "main class not found" exception.
However, when I run the command directly on the command line, it works.
The command in the batch file to run it is:
java -cp lda-services.jar;bip-services-1.6.0.0-SNAPSHOT.jar;decryptor-1.6.0.0-SNAPSHOT.jar;slf4j-api-1.7.31.jar;commons-io-2.6.jar com.ilcore.util.SosaMaintenanceJFrame
The SosaMaintenanceJFrame class is contained in the lda-services jar.
Here's the error message:
Error: Could not find or load main class com.ilcore.util.SosaMaintenanceJFrame
Caused by: java.lang.ClassNotFoundException: com.ilcore.util.SosaMaintenanceJFrame
The class is definitely in the jar file, as I've extracted it the file and seen it.
Any thoughts on why this would be happening? I need to run inside a batch file so the user can just click on it to run it.
Most likely explanation
Your paths are relative, which means that the batch file isn't going to work unless you run it from the right place. In general, having a batch file that has an invisible rider stapled to it with: "I break in mysterious ways if not run from the appropriate dir" is a crappy batch file - make it better.
Better solution
Or, even better, get rid of it. You don't need batch files to distribute java programs.
Proper ways to distribute java programs:
The modern take is very very different from what you have here: JREs are dead, you must ship an installer that does the whole thing, notably including a java runtime (no longer called a JRE, and one you ship and keep up to date if relevant). That's perhaps a bridge too far for what you're doing here. Relevant tools include jlink.
A slightly less modern take involves jars with manifests:
Your jar file should contain a manifest. This manifest must contain 2 relevant entries:
Class-Path: lda-services.jar bip-services-1.6.0.0-SNAPSHOT.jar decryptor-1.6.0.0-SNAPSHOT.jar slf4j-api-1.7.31.jar commons-io-2.6.jar
and
Main-Class: com.ilcore.util.SosaMaintenanceJFrame
You can use jar's -m switch, or just include the manifest (it's just a file in the jar): it's at META_INF/MANIFEST.MF and it's a text file, each line is an entry, and an entry consists of a key: value pair.
When a jar contains this, just double clicking the jar and running java -jar thejar.jar will then take care of it all: Java will load the stated jars as part of the classpath, and these, crucially, are resolved as paths relative to the directory the jar is in, so it DOES work when you try to launch them from elsewhere, i.e. if you do:
C:
CD \
java -jar "c:\Program Files\MyApp\myapp.jar"
it works fine, whereas that batch script would fail due to being in the wrong place.
Build systems let you define the manifest too, check your build systems docs for how to do this, it'll be easy, and there are tons of tutorials if you search the web for e.g. 'manifest executable jar maven' or whatnot.
You can consider making a shaded jar. But I wouldn't.
A shaded jar takes all your dependencies and packs them into your main jar, so that there is only one jar. There is now no need for a Class-Path entry (the jar you run is obviously already on the classpath and there's nothing else to include) and your app is shipped as 'just' a single jar file.
But this is mostly a red herring: There are no consumer JREs anymore so you've made the user experience from a D- to a D. If you actually care about giving your users a nice experience, there's no getting around an installation process of some sort and once you have that, having the separate jars is no longer a problem. Separate jars are less hairy when signed jars are involved, are much easier to keep up to date, and have a significantly faster turnaround (when you build your stuff and want to ship what you built, shading takes ages, so it's nice to cut that step out). The faster your CI system tells you about failing tests, the better.
Meet in the middle
You don't have to upgrade to modules and the like. What you can do instead is use something like launch4j. The aim is to end up with a zip file along with the installation instructions: Make a dir somewhere. unzip this zip in it. Doubleclick 'myapp.exe'. Done.
The zip would contain an entire JRE, all your jar file deps, and your main app, and an exe file which launch4j made for you, that launches your app using the JRE packed into the jar. This means you know exactly which JRE is being used, and it'll work even on systems that didn't have one installed yet (which, these days, should be all of them - the notion of 'end user downloads a JRE from oracle and the user + oracle work together to keep that thing up to date and security-issue-free', is dead).
The fact that it's an EXE is nice: Now if the user e.g. alt+tabs through their apps, they get your app, with your name, and your icon, instead of 'javaw.exe' with an ugly coffee mug logo.
But when I try running it from the jar file generated by Maven, however, I get a "class not found" exception.
Even if you didn't get that error, you'd get another one unless you'd used Maven Shade, as that's the only way you're going to run that with a single jar. My guess as to why that particular error occurs is that the app class you're attempting to run is in fact in one of the *SNAPSHOT* jars

Packaging Java/Netbeans project for easy end user usage

(I guess this is less a question than a report/personal experience looking for critique or whatever. The project described contains an external library.)
Many users need more than all the help they can get in trying to execute a Java project. I'm describing ways that come to mind for getting a project to a user--none particularly foolproof--and wonder if I'm missing some much-easier method.
One way: Do what the dist folder README says: "To distribute this project, right click to zip up the dist folder (including the lib folder) and distribute the ZIP file" and, I'll add, hope the user has the skill to extract and then find the executable jar. And to go get a JRE if need be.
A seamless way: use Netbeans 7.4 Native Java Packaging, which produces a self-extracting executable (an "EXE installer"; an .EXE file) and runs whether or not user has JRE installed. It can be executed from Windows Search box (and can be uninstalled via Control Panel). Method assumes NO JRE available; humongous (30MB) .EXE was produced. [See ((this link))
Unhappy medium: forget the admirable use of an external library; just add the package containing the library's source code. This produces a .jar that runs if JRE is present; otherwise user still has to get involved.
None of the above are exactly ideal ways of providing an app for a tech-challenged user.
I was going to include Webstart as a fourth and what I hoped best alternative, but for no apparent reason, I can't get a compilation that works inside my own Netbeans IDE. Calls to the utility modules--now included in the GUI part of the project; external in NO WAY--never pop up the dialogs they should.

How do I dynamically load the Java3D library?

I am finishing up a game that I developed using Java3D. Since Java3D does not come with the standard JRE, all of the people who I am giving this game to will have to download Java3D. Some of my friends are a little less computer savvy so I thought it would be a lot less work to just write the Jars to the disk and dynamically load them in Java. Is there a better solution to this? Or is dynamically loading the Jars the way to go?
I have installed Java3D on another computer of mine from here:
Download Java3D
It was a pretty quick installation but it would be better if you didn't have to download anything at all. If they are only going to use Java3D for my game then it doesn't really seem logical for them to go through the trouble of downloading it.
Are there any more efficient solutions to this? Is dynamically loading the Jars just the way to go?
EDIT
Here is my problem simplified:
Java3D is not a standard part of Java, it is an extension that must be installed separately
Java3D consists of 3 Jar Files (j3core.jar, j3dutils, vecmath)
I want to be able to run my game on other computers without them having to download the Jar files
Now here is my simplified question:
How do I run Java3D on a computer that doesn't have Java3D installed? I want to write the Jar files to a CD, along with the game, and be able to play the game right off the CD, no installations no downloads. How can I do this?
The jars are not platform specific, the native code in the dynamic libraries is. The dynamic libraries are already loaded as they are called for in code. If you take a look back at that code you will see that loadLibrary() does not ask for the extension. There is a reason for this, JNI (the Java Native Interface) looks for certain extensions based on what system it is running on. For this reason just package all the dynamic libraries where JNI can find it, such as right next to your application and JNI will take care of the rest.
Some code to point you in the right direction:
Blah.java
public class blah{
public native void meh();
public static void main(String args[]) {
meh();
}
}
static {
System.loadLibrary("thing");
}
Blah.cpp
#include <jni.h>
#include <iostream>
#include "Blah.h"
JNIEXPORT void JNICALL Java_Blah_meh() {
cout << "Meh.";
}
Blah.cpp (with the Blah.h generated by the javah program) is compiled into a dynamic library for each major system (thing.dll, thing.dylib, thing.so). Blah.java is compiled into a .class file, toss it in a jar just for ease for execution.
Now for the important part, the layout of files!
ThingApp //that's a folder
|thing.dll
|thing.dylib
|thing.so
|Blah.jar
Put this on any system and JNI will find the right file for the system due to the extensions, load the library into memory, execute the code, and print out "Meh.". JNI finds the files because they are in the PATH environment variable (or the system equivalent). The PATH includes the folder the executed code/program is in, folders set with the java.library.path system property, and the folders included int he PATH variable itself.
Basically you just need to worry about the part about the PATH as everything else is done for you!
If you are distributing it over disk, you can wrap your application in a setup executable (for instance using the free Inno Setup). Once the users put in your disk, the setup will start. You can configure your setup in Inno Setup to also install the correct version of Java3D.
I think that is how most of the disk-distributed games work. It takes a bit to get the hang of those more advanced setup wrappers, but they are worth it. I don't know anything else than Inno Setup, but it was able to handle any of my requirements so far that's why I recommend that one.
Download the classes from here: http://java3d.java.net/binary-builds.html and extract the included zip file. Extract the jar files (vecmath, j3dcore, j3dutils) in the lib folder to your class folder. Bundle your class folder to a single jar file.
Now follow these steps to add the libraries (*.dll, *.so) from the bin folder in the above zip file to your jar file:
How to make a JAR file that includes DLL files?

How to refer a jar outside exe in Java desktop application?

I have a Java application installed. The jar is bundled into an .exe file using Launch4J. Now I want to create a patch for this application.
If I create another jar containing only updated files, how can I refer it in the original code?
I have java application installed. ..Now I want to create a patch for this application.
This is one of the strengths of the Java Web Start launch technology that comes with the J2SE. Simply update the Jar on the server, and the next time the app. launches, it will be updated.
The update can be honed for your use-case, configured to be done lazily or eagerly, before or after launch, or even programatically controlled using the JNLP API's DownloadService.
..And the jar is bundlled into an .exe file ..
'Unfortunately', JWS works on Windows, ..and Mac., and *nix - so you may have to expand your horizons.
BTW - I have no idea how to do the same with Launch4J, but then, that is really the wrong question. I aim to provide an answer to the right question, which is "How do I deploy & update a Java rich client?". ;)
I've never worked with Launch4J, however I think you should try to affect the classpath. JRE always loads the classes from the classpath. From this point of view, jars have no added value and just serve as a containers for your *.class files and resources.
Now, if you succeed to configure your tool to do something like:
classpath = C:\Temp\my_patch_path;$your_current_classpath
then its enough to put your changed files into C:\Temp\my_patch_path (of course preserving the package structure). JRE will load your classes first in this case.
Hope, this helps
Mark
It is might not be possible to do this without changing the contents of the exe.

The conventional location for storing my Java libraries and applications in UNIX based systems

I usually store the Java applications and JAR files that I download from the Web in the ~/Java folder on my computer (an OS X machine). I have been doing this since the days when I was a Windows user. However I think in UNIX based systems user local apps are conventionally stored in another directory. I have a feeling that this directory should either be /usr/local/, /usr/local/USERNAME, /opt/local, or /opt/local/USERNAME but I am not sure. Any ideas which directory can I use for this purpose?
Please note that, I am talking about archive files that I download from the Web, unpack and use locally and not programs that have installation scripts or MacPorts, etc.
The para-answer is that you shouldn't be downloading jars by hand at all, you should be using Gradle, Ivy, Maven, or something similar to manage your jars for you. These tools take a simple specification of your dependencies as input, and go and find, download, store, and make available all the necessary jar files. This takes a little bit of getting used to, but are rather wonderful once you're in the swing of it.
A direct answer, though, is that on orthodox unix, these files belong in /usr/local/share. usr because they're read-only data that is not part of the base operating system, local because they are not being supplied by the operating system (which owns the rest of /usr), and share because jar files are architecture-independent.
Note that on FreeBSD, the 'ports' package management system puts files in /usr/local, but i believe it shares it with the local administrator. There isn't some other location where purely local files go.
If the system has a convention for where package-managed jars go, then copy that under /usr/local. For example, on Ubuntu, there is /usr/share/java, so you should use /usr/local/share/java.
Further, if the system has a convention for handling versions, copy that. Again, on Ubuntu, jars are all stored in one directory, with version numbers in the name, but with a versionless symlink pointing to the default/latest version. So, i have a file at /usr/share/java/xstream-1.3.1.jar, and a symlink at /usr/share/java/xstream.jar pointing to it. I'd use the same approach in /usr/local/share/java.
Now, that's for orthodox unix. You're on OS X, which is not orthodox unix. Still, the principles apply: find how the system stores jars it provides, and transpose that into a user-managed filesystem space.
There isn't any blessed way to do it. You may, however, run into having multiple versions of a jar, and then it just goes downhill from there.
I usually download the jars I need as a distribution, and unpack it to its own folder, and then add the jars to the projects I need them for in my IDE. For libraries a common approach is to use Maven and its dependency handling.
So, my suggestion is to keep your current way of doing it, if you like that, but have each project in its own folder, like
~/Java/jakarta-commons-net-1.1.8/commons-net.jar
Apple have a note giving /Library/Java/Extensions as the directory for shared jars and ~/Library/Java/Extensions for jars just for yourself. These paths are on the classpath.
The jars can be anywhere as long as that directory is on your class path. (I use a version of
Thorbjørn Ravn Andersen's style I use ~/Library/Jar/jakarta-commons-net-1.1.8/commons-net.jar)
See Tom Anderson's answer for a better way to do it using ivy etc
You might wish to read the Filesystem Hierarchy Standard /opt or /usr/local are probably appropriate but you should read there FHS definitions first.
On FreeBSD systems the location is ${LOCALBASE}/share/java -- and subdirectories thereof. Not that all software-ports respect it, but they should.
LOCALBASE is usually /usr/local -- unless overwritten by the system administrator.

Categories