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?
Related
I currently wrote a simple GUI in Eclipse which runs as intended. I was hoping to export it so I can share it with my friend (who doesn't need to install eclipse and the java libraries). I tried all 3 library handling method Eclipse provides and none of them works. I read a little online and saw something about a manifest file, but wasn't quite sure what to do with it. Is it going to help?
This is where I placed the folder that comes with the .dll file.
This is the result. Am I doing something wrong?
As indicated by the error messages in the first screenshot, what you are missing here is the native library - the software library written and compiled to native code specific to the operating system. What you will need to do is provide the libraries specific to the operating system on which your software will run, eg. dlls for 32 or 64 bit Windows. The manifest does not provide the capability to include those libraries.
When the program is run on Windows, Java will look for native libraries in the following locations:
The current directory
The directories in the PATH environment variable
The directories in java.library.path (if it's specified)
It may be easiest to simply put all files in the one directory. If you do this, you should be able to run the program in the same way as you do now.
The java.library.path option is only needed if you want to put your native library files in a directory separate to the one in which you run your program and not on your PATH. It is only in this case that you will need to add java.library.path, eg. by adding -Djava.library.path=c:\path\to\your\lib after java. Also note that you may use a relative path, ie. a path that is relative to the directory you are in when you execute the command.
I also see from your later error messages that you have another dependency, but on a java library LeapJava.jar. As running a jar with -jar will only work if you have a single jar, but because you have more than one (your own program plus the dependency), you'll instead need to use the -classpath (or -cp for short) argument and add your main class. The classpath argument is a semicolon-separated list of classpath locations, while the main class is the one containing your public static void main method, eg. your.package.name.YourMainClass. So assuming your UI.jar is still in C:\Users\Ian\Desktop\Leap Data UI, you should be able to navigate to that directory and execute with:
java -cp UI.jar;UI_lib\LeapJava.jar -Djava.library.path="UI_lib\x64" your.package.name.YourMainClass
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.
(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.
I'm working on a java android project. this project requires to use specific commands.
these commands are all developed in c++/c but I've been given two files (.jar and .so) that are supposed to "turn them into" java, so I can use them in my java android project.
The thing is, what am I supposed to do with these 2 files?? I've read a lot of stuff (mostly about creating the .jar and .so, but I don't care about this step, for I already have the 2 files)
I tried to import the .jar (import external lib), I tried to add the .so via the static loading :
//static {
// System.loadLibrary("MySoFile");
// }
All I get is a stack overflow error or a problem with the DEX file...
Has anybody ever tried to do this??
I don't seem to get the point here...all I want to do is being able to use the commands in the .jar file.... ://
thanks in advance!!
Take a look at this answer about adding jar files. '.so' files can usually just be drag and dropped to the project.
All you need to do is make sure the jar is in your classpath and you can then access the classes within this jar. A jar is just an archive of classes, you don't need to load the library into memory or something similar.
You may want to read the answer to the question here How to use classes from .jar files?
I would like to ship my application as a self-contained jar file. The jar file should contain all the class files, as well as two shared libraries. One of these shared libraries is written for the JNI and is essentially an indirection to the other one (which is 100% C).
I have first tried running my jar file without the libraries, but having them accessible through the LD_LIBRARY_PATH environment variable. That worked fine.
I then put the JNI library into the jar file. I have read about loading libraries from jar files by copying them first to some temporary directory, and that worked well for me (note that the 100% C library was, I suppose, loaded as before).
Now I want to put both libraries into the jar, but I don't understand how I can make sure that they will both be loaded. Sure I can copy them both to a temporary directory, but when I load the "indirection" one, it always gives me:
java.lang.UnsatisfiedLinkError: /tmp/.../libindirect.so: /libpure.so: cannot open shared object file: No such file or directory
I've tried to force the JVM to load the "100% C" library first by explicitely calling System.load(...) on its temporary file, but that didn't work better. I suspect the system is looking for it when resolving the links in libindirect.so but doesn't care about what the JVM loaded.
Can anyone help me on that one?
Thanks
One way would be to spawn another Java process from the first, generating the appropriate invocation script.
The jar is invoked by the user
The libraries are extracted to a temp directory
A (bash) script is written to the temp directory
this sets/exports the necessary environment variables
this launches the second JRE instance
The code makes the script executable
The code invokes the script
I know, spawning two JRE instances to launch one app would not be my first choice either.
If you are using Eclipse IDE, then this answer might help you.
I had same problem in eclipse windows that I couldn't added dependant .class files from the JNI.
After searching for a while I came to know that "Its a known bug inside Eclipse", In order resolve the same, I ported all the code to NetBeans IDE.
Can not add all the classes files from the JNI folder in Eclipse (JAVA, Windows 7)