Launch a java application from another java application - java

I'm doing a Java Record/Replay tool and I need to launch Java applications from my main Java app.
I need access to the EventDispatchThread in order to intercept the events and record them, so I'm launching the application through reflection with (code snippet simplified):
Class<?> app = Class.forName(mainClass);
Method m = app.getMethod("main", new Class[] { String[].class });
m.invoke(null, new Object[] { new String[] {} });
I previously dynamically load all the jars to the classpath and the application is launching almost perfectly.
The problem occurs when the application needs to access any file and does it with relative paths. Because the application is launched through my application the path is not the same as launched from its normal path and the files are not found.
What can I do to solve this problem? dynamically change the execution environment? any ideas?

I would suggest loading your code as a "Java Agent" whilst starting the target application.
(With your method you will also find that the system class loader is wrong.)

In general, there's no way to do this.
http://bugs.sun.com/bugdatabase/view_bug.do;jsessionid=30b24551130ee4ffffffffc17df8d7ce8a9c3?bug_id=4117557
You can try System.setProperty("user.dir", "C:\\Some\\Location"); but it probably won't work for all cases and will give you weird behavior.
It's a pretty bad design for an app to rely on the directory from which it was launched.
The best advice I can give you is to launch your app from the directory from which the misbehaving app expects to be launched (assuming you know what that directory is).
Otherwise, hell, copy/symlink the data files into your directory so that the client app can find them...

Related

Using JNI in C++, use own .jar in existing JVM or create new JVM

I'm trying to crate an Matlab IMAQ adapter for a 3D camera using the Java API of this camera.
So I create a .dll for Matlab within I handle the connection to the camera. There are specific functions needed by Matlab within I would like to call the Java functions of the API to connect to the device and make image acquisition.
My problem is Matlab is already starting a JVM, so I can't directly start a JVM in the adaptor, because in this case I would try to run two JVMs in one process
So my question is, which one is the better way:
Creating a new process in the adaptor to start a new JVM which will load the used .jar file in the classpath.
Attach to the running JVM started by Matlab and load the .jar I need in the running JVM.
First. Thanks for updating your question - makes now more sence to me.
I would rather attach to the running JVM. Maybe this could help you.
Attach to running JVM
Regards,
Rainer

Missing OpenFilesEvent for JavaFX on Mac

I have a JavaFX 8 desktop application and I'm creating an .app application bundle to distribute the application to Mac users. I use the Oracle “Self-Contained Application Packaging” tool to generate the bundle.
The problem that I have relates to the files associated with my application. I am associating the extension .wordy with these files. If I have the application open and I double click one of these files in the Mac Finder, my application receives an OpenFilesEvent containing the path to the file and everything works perfectly. If, however, the application is not open, double clicking a .wordy file in the Finder opens my application as I would expect but I never receive the event containing the path to the file that the user double-clicked on.
The file association is done in the Ant script for the Oracle “Self-Contained Application Packaging” tool, as follows:
<project name="VocabHunter Packaging" basedir=""
xmlns:fx="javafx:com.sun.javafx.tools.ant">
...
<fx:info title="VocabHunter">
<fx:association description="VocabHunter session"
extension="wordy"
mimetype="application/x-vnd.VocabHunterSession"
icon="${basedir}/icons/mac/VocabHunterSession.icns"/>
</fx:info>
...
</project>
In the Java code, I obtain an instance of com.apple.eawt.Application and then register the listener for the OpenFilesEvent as follows:
Application application = Application.getApplication();
application.setOpenFileHandler(new OsxOpenFilesHandler(listener));
You can see the full code here.
Does anyone know how to fix this so that I receive an event containing the path to the .wordy file even if the application was not running at the moment that the file was double clicked?
In the interests of completeness, I'm using the Oracle JDK 1.8.0_66 for Mac.
I tested with your code and also met this problem.
But when I used code directly in start(Stage primaryStage) method in to listen like this:
Application lowLevelApp = com.sun.glass.ui.Application.GetApplication();
lowLevelApp.setEventHandler {...}
I can get the OpenFilesEvent when first double clicked on file.
There is an entry in the bug database for this issue.
https://bugs.openjdk.java.net/browse/JDK-8187992
You probably call the application.setOpenFileHandler() code too late during the application initialization. Try calling it as early as possible in main() and see if that solves the problem. I am not sure exactly when Mac OS X passes the OpenFile event to Java, but if at that time you haven't prepared by calling application.setOpenFileHandler() then the event will get lost.
For future reference: getting the openFileHandler to work correctly can be very tricky. The handler is invoked from an event handler on the UI event thread, which means there is no guarantee that main() has completed when the handler is run. For best results, the openFileHandler should be set up using a static initializer, and main() and the open file handler should both invoke the same initialization code on the UI event thread, and the initialization code should be written to work if called more than once.

Restart an Application in JavaFx

I want to close and then restart a already running application (automatically) that I am making, by clicking a button or something like that, I want to do that for the purpose of re-launching the application in an other language, I'm new to JavaFx and Java in general, please can you give me a solution for this problem ?
This question lacks details. You did mention a JavaFX application but it is important to know how that application is being deployed. Is it running in the web browser, as a java webstart application, a stand-alone jar, or a self-contained native application? How are you starting the application to begin with? Having the answer to these questions will make it easier to answer your question with specifics.
While the following example is not JavaFX, the approach used here would work for some of the ways in which a JavaFX application can be deployed. One approach for restarting an application that works nicely is to start the application from a script. Inside the script would be a while loop that continually restarts the program based on the program exit code. Here is an example for a bash shell script which starts IntelliJ on a Linux platform:
while true ; do
eval "$JDK/bin/java" $ALL_JVM_ARGS -Djb.restart.code=88 $MAIN_CLASS_NAME $*
test $? -ne 88 && break
done
In this example, the startup script is passing "jb.restart.code" as an application parameter. If IntelliJ wishes to restart, it will return that value 88 as the exit code. The script observes the application exit code, and restarts the application if the value is 88.
This approach works well on most platforms, but requires the application to be initiated via a script.
One solution is to pass commandline and working dir in your start script to your main() method. Using ProcessBuilder you then can restart the appliation. Another possibility is to start the whole application in a custom classloader (e.g. Spring project has suitable classloaders in their source base), you then can basically restart by starting your main in anouther classloader, however you then need proper housekeeping to free threads and resources of the first instance.
retstart.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent t) {
if(getOnCloseRequest()!=null){
getOnCloseRequest().handle(new WindowEvent(getScene().getWindow(), WindowEvent.WINDOW_CLOSE_REQUEST));
//write code to invoke application instance again
}else{
close();
}
}
});

Cannot run two instances of java webstart

I am unable to run more than one instance of java webstart at any given time.
For example, I am unable to run both the production & QA instance of an application at once, both of which are launched via java webstart. Additionally, I am unable to run the java webstart cache viewer at the same time as either the production or QA instance of my application.
I am however able to run any of the above three webstart launches when they are run in isolation of each other. When I try to bring up a second option, I see the 'Java Loading...' screen which then disappears and nothing happens.
Additionally, I have tried to delete the webstart cache (via the java webstart cache viewer) and I receive the following error regardless of which JRE I point to:
"Bad installation. Error invoking Java VM (execv)
'path to my javaw.exe'"
I expect both the problems I mention above are interlinked. I do not believe I have changed any configuration recently and I have been happily running java webstart for years.
Has anyone seen such a problem before?
Thanks,
Jack
EDIT: When the second instance of webstart attempts to run, during the display of the 'Java Loading...' screen I can see in the task manager that a new javaw.exe process is spawned. This process almost immediately dies though. I'm not sure how to inspect the failure in that process, but I expect it is similar to the failure when trying to clear my cache through the webstart cache viewer.
You may be able to use javaws from the command line to run a second instance in -offline mode. The verbose option is handy, too.
javaws -offline -verbose MyApplication.jnlp
I think it is because both instances of the application use the same folder as current working directory. I do not remember exactly but it is somewhere under user home and the folder contains the application name or something...
So, if this is correct the solution is to change the application name like "My Application - QA" vs. "My Application" used on production.
The name is somewhere in jnlp.xml.
The reason may be the startup parameters for client java/javaw, which do not allow to run more than one instance of Java. For example because of set debug port. These parameters can be set in the command line or in the Java Control Panel -> Java -> button View.

Launching a java application from an URI

I'm looking for a way to launch my java application when using a custom URI.
Something in the lines of
movie://superman/
This should start my application and display information about the movie "Superman".
if friends of my have my application installed as well, i can send them that URI so they can click on it.
I used to do this back in the days in VB6 but i lost my code and forgot how to do it.
OS: windows
Any help would be appreciated.
The actual mechanism to implement this is operating-system dependent (and thus not accessible from pure Java).
The general idea is to register your application as the protocol handler for the protocol in question.
On Windows you do that by writing the appropriate registry keys
..should start my application and display information about the movie "Superman".
If you can distribute your app. from a web site, you might take a slightly different approach:
Launch the app. using Java Web Start.
In the JWS launch file (JNLP format), add a custom file extension, e.g. xuri.
Send the user an clickthis.xuri file containing the URI of interest.
When the JWS app. registered to that file type is invoked, it will be passed -open clickthis.xuri as arguments to the main(String[]).
Proceed from there..
This approach should work on any OS with 'modern' Java installed. JWS was available since 1.2, & became co-bundled with the JRE around 1.4.2.

Categories

Resources