This question already has answers here:
Can I set Java max heap size for running from a jar file?
(8 answers)
Closed 9 years ago.
I am trying to create a jar file that will execute my game with just a click. My game exceeds java's default allocated heap memory so I have to run my code with -Xmx1000m. I've been researching online and unfortunately there doesn't seem to be a way to tell a jar file to fun my code with more than the default memory. Instead I created another class that will use runtime to compile my code from within another main method and created a jar file using this:
import java.io.*;
public class RuntimeExec{
public static void main(String[] args){
try
{
Process process = Runtime.getRuntime().exec("java -Xmx1000m Controller");
process.waitFor();
int exitCode = process.exitValue();
if(exitCode == 0) { /* success*/ }
else { /*failed*/ }
}
catch (Exception e)
{e.printStackTrace();}
}
}
This works however I think it only works because it runs my existing class in the folder and not the one I stored in the jar. Is there a way so that the jar will run a class within in or combine two different jars that will allow me to get around the memory heap problem?
The entire solution to providing an easy install for users is to deploy the app. using Java Web Start. It can set RAM for an app., and also install a desktop shortcut to launch it. JWS is much more robust than a (poorly implemented) call to exec.
However if JWS is not for some reason suitable for this app., see IWantToBeBig for a hack that will cause a Jar to have enough memory (similar to how you use exec above, but slightly more robust in using ProcessBuilder to relaunch the app. that does not have enough memory).
Organizing the desktop shortcut to allow the user to launch it with a click, is left as an exercise for the reader.
There are many ways of doing it:
As you mentioned, by having another Jar file which triggers your game file
As #Perception mentioned, have a batch file which will start your game. But be careful, if downloaded from say Net, the user will have to set permissions for the script to be runnable
Build an installer. On Mac, using the Oracle Java App bundler for Java 7, Apple App bundler for Java 6 build the .app file. You still cant redistribute it as the necessary permissions wont be set. Build a dmg for the app file. This can be used for distribution.
A similar installer for Windows
The third technique would be the best, as you can then package the dependencies well, set all JVM arguments etc
Related
My app has already been signed and notarized successfully, but I got this error while trying to launch the app:
"jna7223640233751603426.tmp" cannot be opened because the developer cannot be verified
Does anybody have the solution for this?
How can I fix this problem? Can I block the file created while launching the app or make it valid for the Gatekeeper?
JNA releases have small precompiled binary JARs for each of its supported operating system/architecture combinations. These are not signed, although the source code is available if you wish to build and sign them yourself.
From a conversation on the JNA mailing list:
MacOS does not allow code created at runtime (which is typical malware behaviour), and that extracting a library at runtime looks like that code was created because it’s not visible outside the jar file in which it came.
A solution listed in that thread is:
by pre-extracting the library and bundling it as part of the installer.
In addition to this, you'll need to configure your application to tell JNA not to extract its own library but to use the one which you have signed and extracted as part of your installer. Source code from the above email thread:
boolean sandboxed = System.getenv("APP_SANDBOX_CONTAINER_ID") != null;
// Some 3rd party apps install to the system and can cause crashes
System.setProperty("jna.nosys", "true");
if(sandboxed) {
// Don't unpack the libraries
System.setProperty("jna.nounpack", "true");
// Tell JNA where the native libraries are
System.setProperty("jna.boot.library.path", "<path to native libs>");
}
So I have this code that works fine, it launch the .jar file from another machine that I have configure in my pc as a red ubication
Runtime.getRuntime().exec("java -jar Z:\\AAA\\BBB\\CCC\\ZZZ.jar");
But now I want to launch the .jar from that external path without using the shortcut before (so I can launch it with this code in a machine that dont have that red ubication configured)
Runtime.getRuntime().exec("java -jar MMM\\NNN LLL\\OOO\\AAA\\BBB\\CCC\\ZZZ.jar");
But doent work (I can access and open the file manually without a problem).
When I enter the java -jar MMM\\NNN LLL\\OOO\\AAA\\BBB\\CCC\\ZZZ.jar in the Command prompt it return me Error: Unable to access jarfile MMM\NNN, so perhaps one problem is that the path have a space in the folder name, but I think that may be something else too.
The question is, if the problem is the space, how I can solve it? I cant find a way. And in the other hand, how I can run it in another machine? I have to use that red ubication IP in some way instead?
PD: Using this code, it return me true
File f = new File("\\\\MMM\\NNN LLL\\OOO\\ZZZ.jar");
System.out.println(f.exists()); //--> true
So looks like the spaces dont interfere in the path (the four "\" doesnt seem to do anything in the tests when launching)
I have heard other people having such problems. The main reason for that is that probably Java exec method is not network (SMB) aware. So it doesn't even try to open from the network.
Anyway running the code like that from the network might not be the best solution. First of all the network might be unavailable, or the java file coming might be corrupted. If you want to do it properly you have several options:
Simple option that can work:
Create a bat file that works and exec that one - you can even copy the file locally first to make sure it is available first (if it is big and the network fails)
A better solution :
Use java to copy the file to the working directory and execute it from there.
A plus to do it like that by downloading is that you can maintain a version of the file (hash?) so you don't download it if it is the same. Or you can have fallback - execute the last downloaded version if the network drive is unavailable.
Use a local maven repository and dependency for that jar :)
This way it will keep the version of the jar locally and won't have to download it every time. It will also download a new version if available and the code will be more mainstream (for example not platform / pc dependent)
The answer give by #MadProgrammer works fine!
ProcessBuilder builder = new ProcessBuilder("java", "-jar", "MMM\\NNN LLL\\OOO\\AAA\\BBB\\CCC\\ZZZ.jar");
try {
builder.start();
} catch (IOException e) {
e.printStackTrace();
}
Lot of thanks! In any case going to check the ideas posted by Veselin Davidov
I have been reading many answers about the different between the compile time and the runtime in Java. But I am still not clear. Some answers said: the compile time is the period when you, the developer, are compiling your program or code. My question is when do I compile my program or code? For example: I open my IDE, eclipse or netbeans, write code in different classes and click on Run button and my application opens. Can someone explain me when did I compile my program/code in this sample process? or when was I in the compile time stage in this sample process?
When you write any java class,extension of file must be .java. Let take simple java class to print Hello World :
public class Simple {
public static void main(String[] args) {
System.out.println("Hello World !!");
}
}
So save this file as Simple.java.
Now open the cmd,lets say file saved in d:\test directory
d:\test>javac Simple.java // When you run this the .java is converted into byte code and it is saved in .class file.
d:\test>java Simple // JVM will execute the byte code file i.e. Simple.class
Note : All this process is done by IDE internally
Do this. Open notepad. Type in :
class Sampl{
public static void main(String []args){
System.out.println("hi from run time");
}
}
Save it as Sampl.java
Save it in a new folder without spaces - say c:\j\academic or ~/j/academic if on linux
Now open a command promot, figure out path to your JDK and type in
cd c:\j\academic
dir
Should see just Sampl.java
javac Sampl.java
dir
Should see 2 files :
Sampl.java and Sampl.class
That's you byte code
Now you can move or even delete Sampl.java and can still run Sampl.class from command line using
java -cp . Sampl
So you notepad and .java time was coding time. On command prompt was compile and run time
javac is the java compiler
java.exe is the runtime app that loads and runs our classes
[When runing jboss or other app container we run java with the jboss main class, and its calsses load and run ours]
These search results should help too google java tutorial command propmpt
There is a very important thing you may not have fully understood yet, namely that the text you type - which in this case makes a Java program - is not on the form of the instructions that the CPU is executing millions of every second - which for Java is Java Byte Code, and which needs to be present for the JVM to execute your program.
The transformation of the Java source code you wrote into the corresponding Java Byte Code, is done by a so-called Java compiler. There is nothing magical about a compiler as it is just a program which can read in text and generate the corresponding byte codes, and it is a standard assignment for computer science students to write one (but usually for smaller languages than Java).
If you write your programs in a standard text editor (not an IDE) and save to disk, you need to manually invoke the Java compiler by running javac on your Java sources. One of the advantages of IDE's is that they usually do the compilation automatically - either immediately when you save your file or when you want to run your program - but it makes it a bit more magical what goes on.
(Note: This transparent compilation step in an IDE becomes very useful when debugging in i.e. Eclipse, as it allows for updating the code being executed without having to restart the debug session from scratch.)
I'm pretty new to Perl but have been programming in java for several months now (coming from a C++ background). I wrote a Perl script that parses some data logs and now the customer I'm working for wants a GUI. The GUI has been created as a java applet (using Netbeans) and I would like to "embed" the perl script inside its jar file as a default safety feature. Multiple updates are expected for the perl script later in the future, so I want to set it up so that all the user has to do when an update comes along is define a new file path to the latest perl script through the GUI. I've already implemented this functionality with a file browser and everything works fine.
The problem I'm running into is something very simple that's probably not very hard for someone with more java experience. Just in case one of the updated perl scripts they receive in the future doesn't work properly, I want them to be able to use the default "embedded" script if they have to resort to that. When I'm running the applet through Netbeans, everything works perfectly however when I try and run the jar file from the command line, the program returns an error saying it cannot find the file. I might not be using the correct terminology to search for a solution to this problem, but I would like to be able to have my jar file execute the embedded perl script at runtime. Any suggestions are appreciated. I've tried placing the perl file in the same package as the java files and calling for the script by its filename alone, but that was a no go.
You can access any file in the jar as a classpath resource, but the problem you're going to have is users may not have a perl interpreter installed.
EDIT: Since you've mentioned that users will have a Perl runtime, then this is doable. You can try piping the contents of the file using Process.getOutputStream() or just copy the contents to a temp file with File.createTempFile() and pass that file name as an argument to the perl interpreter.
I have the same problem, here's how I solved it based on Josh and Jiggy's discussion above. First look for the file in src/main/resources/perl (so it works in Eclipse). If it does not exist then copy the Perl file from the perl directory inside the jar to src/main/resources/perl. I building with Maven so using the src/main/resources/perl directory means when I build the jar, Maven automatically includes the perl directory in the jar.
This is a similar strategy to the one used to load resources from jars such as properties files.
I am using this approach because I have a multi-module Maven project when each submodule builds a jar. We have one that does general information extraction, then another one that specializes that module for a particular client. The Perl code lives inside the general module, but it is needed in the specialized one. Copying files between modules in Maven is rather awkward, so it is easier just to put it in resources, then let the Java code solve the problem.
See this related question for a good answer of an alternative approach to embedding native code such as C in jars.
The code looks like this (I'm using Apache Commons IO):
public class PerlTableParser {
private static final String RESOURCES_DIR = "src/main/resources";
private static final String LIB_PATH = RESOURCES_DIR + "perl/";
private static final String PERL_PARSER = "perl/parser.pl";
private static final String PERL_CMD = String.format("perl -I %s %s",
LIB_PATH, RESOURCES_DIR + PERL_PARSER);
public PerlTableParser() {
File perlCodeDir = new File(LIB_PATH);
if (!perlCodeDir.exists()) {
perlCodeDir.mkdirs();
}
File perlParserFile = new File(RESOURCES_DIR, PERL_PARSER);
try {
if (!perlParserFile.exists()) {
FileUtils.copyInputStreamToFile(getClass().getClassLoader()
.getResourceAsStream(PERL_PARSER), perlParserFile);
}
} catch (IOException e) {
MyLogger.logger.error(
"Failed to copy Perl code to local directory " + e, e);
}
}
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How to bundle a native library and a JNI library inside a JAR?
I need to include native lib (jnotify but I think that it does't matter) to my jar. I want to do it with NetBeans.
I added Bundle-NativeCode: /lib/jnotify.dll; osname=win32 to my manifest.mf file and added jnotify.dll to projektHome\src\lib\ folder. But unfortunately NetBeans is overidning manifest.mf file.
How can I fixed? Can I do this using only NetBeans? Is it line 'Bundle-NativeCode: /lib/jnotify.dll; osname=win32 correct? I also heard I should put dlls hash in manifest.mf and sign my jar. Is that true?
I don't think the Java executable supports Bundle-NativeCode. I'm pretty sure that is an OSGi attribute. The list of supported attributes is defined in the JAR File Specification.
Outside frameworks that provide it, there is no built-in support for bundling native libraries inside JAR files. If I recall correctly, it is possible to extract the file to a temporary location and load it manually.
Sometimes i found the problem is not the Java way of loading native libs, but the 3rd party library that needs that native code.
The problem is that the 3rd party libs will do at some point (normally very early in initialization)
System.loadLibrary("native.dll");
And if native.dll is not at the appropiated place it throws an Error.
If you have access to the java source of the 3rd party library it might be easy to patch that code and you could easily extract your dll from the JAR and run System.load before using the 3rd party lib.
Update
I had a look into JNotify sources. It is exactly what i said:
public class JNotify_win32
{
static
{
System.loadLibrary("jnotify"); /* *** */
int res = nativeInit();
if (res != 0)
{
throw new RuntimeException("Error initialiing native library. (#" + res + ")");
}
}
Take line *** out or surround with try-catch, load with System.load() and you are done.
I ran into this problem when trying to hook a Windows shutdown event when the program runs on that OS. The solution I ended up using was essentially McDowell's - adding the DLL to the jar file and extracting it to a temporary location when the program starts. If it fits your program, you can leave the DLL in a more permanent place and then reference it on subsequent program startups. My application was used in an environment where the users might intentionally delete files they shouldn't, so I had to extract the DLL on every run. However, it hasn't resulted in any performance hit of significance.