Fastest way to create a Java message dialog (swing/awt/other)? - java

I'm creating a Java application that will do some processing then needs to display a message to give the user feedback.
However, it appears to be incredibly slow - taking over two seconds to return.
I stripped the source down to the apparent culprit, and here is the code used:
package SwingPlay;
import javax.swing.JFrame;
public class Dialog
{
public static void main( String[] args )
{
JFrame frame = new JFrame( "DialogDemo" );
}
}
I'm executing this from the command line with:
java -classpath . SwingPlay.Dialog
As you can see - I'm doing nothing but create a JFrame, not even displaying it.
In case it is relevant, here is my java -version output:
java version "1.6.0_11"
Java(TM) SE Runtime Environment (build 1.6.0_11-b03)
Java HotSpot(TM) Client VM (build 11.0-b16, mixed mode, sharing)
And this is (currently) running against Win XP SP2.
So, first question: Why is it so slow?
More importantly, I just want a simple message (GUI, not cmdline) to be displayed without delay - can anyone provide some code to do this?
Update:
A bit of background might be helpful:
I am creating an application which will have many 'heads' (i.e. different user interfaces all using the same core classes to do the complex parts).
I currently have a pure command line head which works fine - responds straight away.
I will also have a standard application with a regular point & click GUI, and don't foresee problems with this bit.
What I am currently working on is a hybrid of these two - it will be launched from a Run box (or similar launcher), possibly with arguments, and only needs to respond with, effectively, a status message, that can be dismissed with a key press.
This latter one is where the question is focused.
Whilst I am not opposed to using my existing command line version with shell scripts (though didn't think it would be necessary!), the existing answers seem to suggest that things are not running as fast for me as they are for others - one example takes 1460ms for me, versus 70ms - a significant difference.

The reason for the delay it because Java is an interpreted language and it takes time to start a new JVM ( the interpreter )
Actually creating the frame takes less than a few ms ( about 70 ms in my machine ).
If this is going to be used within a Java app, you don't need to worry about it. It will be almost instantaneous ( you should use JDialog or JOptionPane for this )
If this is NOT going to be used inside a Java app, and 2 secs it too much ( and I think it is too much ) you should consider another tool for the job.
Here's how I measure the time in your code:
import javax.swing.JFrame;
public class Dialog {
public static void main( String[] args ) {
long start = System.currentTimeMillis();
JFrame frame = new JFrame( "DialogDemo" );
System.out.println( "Took: " + ( System.currentTimeMillis() - start ) );
}
}

I would use a JOptionPane to show the message. Here's a simple example:
import javax.swing.*;
public class OptionDemo {
public static void main(String[] args) throws Exception {
JOptionPane.showMessageDialog(null, "Hello World");
}
}
I'm afraid I can't explain the delay you're experiencing though. On my system, your code snippet runs in 500 milliseconds.

Java is the wrong tool for this. Setting up the JVM involves a lot of stuff happening in the background before the first line of Java code can be executed, and there's really no way to get around it.

Also it would be a lot faster to create an AWT Window (or maybe a Frame) instead of a JFrame because the latter has to pull in a gazillion of additional class files.

Do you NEED to use java to display the message box? IF the box is coming from outside of your application, then you might want to use something else to generate a dialog.
To make a native windows app that just shows a message box from a command line string would only take a few hours at most. Most of the common scripting languages should have ways to do it too. here's an example from some guy through javascript via command line:
http://www.snee.com/bobdc.blog/2009/01/displaying-a-message-box-from.html

Oh, and if you don’t really need to show the dialog from Java you could look into using KDialog (or it’s GNOME counterpart) or something similar.

You could use the JOptionDialog
JOptionPane.showMessageDialog([parent frame], [message], [title], JOptionPane.MESSAGE_TYPE);

Since you're interested in speeding this up, and since most of the overhead seems to be JVM startup overhead, check out Nailgun which aims to address slow JVM startup by keeping a JVM running in the background all the time. In your case, after one run the Swing library too will end up being cached (and hopefully after a few more runs JITed too), further reducing the overhead.
However this approach will lead to increased memory usage due to the background JVM and also cause other problems since it may not be straightforward to determine when to shut it down.

What you're probably looking for is the new SplashScreen functionality in Java 6. Instead of having to wait for the JVM to load (there's always a cost to load any VM), this will load a screen beforehand.

Have you tried running it through a profiler like NetBeans? If there's a bottleneck deep inside the standard library, that's a good way to find it.

Related

Simulate input in c++ and read it in JAVA?

I'm facing a problem here and i'm thinking you guys might be able to help/point me toward appropriate documentation.
But first, context:
I'm working on this c++ script that can call and run different java runnables with arguments. But I'm a complete noob in c++, and in general coding. Started Java a couple weeks back.
this c++ script has for purpose (among other things) to intercept inputs and simulate other inputs that will then be read by already running java threads. The goal is for java to be able to run a loop like this:
public class CalledByCpp extends JFrame{
protected static KeyList listener = new KeyList(); //custom KeyListener
//frame constructor goes here
public void main(String[] args){
//initialization of bunch of things
this.addKeyListener(listener);
while(true){
requestFocus();
}
}
protected static class KeyList(){
//Handling of key pressed
}
Does this sounds possible? Or is there an easier method? And what's the event creation method i'm looking for in c++?
Side note: Both cpp and java would run on a Linux desktop (debian) without any screen attached so I assume it's safe for the java frame to loop on requestFocus(). Right?
Another lead I had was to build a driver, but I have no idea what's the difference, and how to do that, or even if it's a lead worth investing time and effort into when this cpp could act as a driver itself.
Thanks a lot!
You will probably want to give the input to Java through standard in. The 'event' to listen for could just be reading a line from standard in, or possibly multiple lines. You would just need to have some way of detecting when to stop reading and do something. Since all threads in your Java program would receive this data, you would also need some way of detecting which thread was intended to use that data. I would start your C++ program first, and then launch Java from within your C++ program, set up so that you can write data into standard in of the Java process from the C++ program. In a UNIX environment, there is a standard way to do this. From your C++ program, run something like the following (you will need to include the header unistd.h):
int fd[2];
// For sharing data with Java process
pipe(fd);
pid_t id = fork();
if (id < 0) {// system error
printf("Failed to fork process");
exit(1);
}
// parent process
else if (id > 0) {// id of child process (Java)
// optional: writes to standard out go to Java process
// can also use write(fd[1], <data>, <length>)
dup2(1, fd[1]);
close(fd[0]);
// do stuff and write to Java process as needed
// signal end of data to Java process
close(fd[1]);
// wait for Java process to exit and clean it up
if (wait(NULL) < 0) {// system error
exit(2);
}
}
else {// child (Java) process, id = 0
// Read stdin from parent (C++) process
dup2(0, fd[0]);
close(fd[1]);
char* path = "/path/to/java";
// Arguments to java. Always end with NULL
char* argv[] = {"Java_arg1", "Java_arg2", NULL}
// Run java
if (execv(path, argv) < 0) {// system error
printf("Failed to execute java command");
exit(1);
}
}
So I've had the time to try out a quick code. Using Xdotool, which you can find on github or apt-get install xdotool
//in the loop deciding which input to simulate
system("xdotool key T");
this would simulate one press of the key T. No console popping up, the script can run in background and generate inputs easily. They are actual system input so I've been able to read them in java.

Standard output when using multiple threads

I am using eclipse, and when I run it normally I don't see a printed statement in the console, but when I run it in debug mode, I see it. What is going on?
This happens only with some print statements (on the server side of a server-client school project, both being run on local host).
private class GameDriver extends Thread {
private Board board;
public GameDriver() {
board = new Board();
}
#Override
public void run() {
boolean twoActivePlayersAlreadyJoined = false;
while (!twoActivePlayersAlreadyJoined) {
twoActivePlayersAlreadyJoined = connector.activePlayers.size() >= 2;
}
System.out.println("Two players already connected, ready to start game");
sendBoardStateToAll();
}
}
The Eclipse debug window shows different JVMs started from your Eclipse instance.
If you start more than one application in Eclipse, then there will be more than one JVM shown in the debug window as well. Now, if you select one of the JVMs in the debug window the output console changes to the selected JVM's standard output.
Without debug mode, however, Eclipse just displays the standard output of the JVM's console which has printed to standard output last.
Q: I am using eclipse, and when I run it normally I don't see a printed statement in the console, but when I run it in debug mode, I see it. What is going on?
It's entirely possible for a "printf" written from a child thread to remain buffered until the thread is terminated. In which case you'll never see it.
SUGGESTION:
Try "System.err.println()" instead. This uses unbuffered I/O. You might see everything you expect.
connector.activePlayers.size() makes it look like connector.activePlayers is a collection. Is it a thread-safe collection? (And even if it's not a collection, is it it thread-safe?) If not, it could be that connector.activePlayers.size() is constantly returning 0 or 1, resulting in your while loop spinning forever. If this is happening, you might be seeing CPU usage shoot up -- is that the case? Anyway, you can easily check by putting a System.out.println("foo") in the while loop.
It could well be that the debugger is inserting synchronization points or otherwise causing CPU registers, cache, etc to get flushed. That could explain why you're seeing the loop terminate (and thus the System.out.println output) in a debugger, but not in "normal" mode where the JVM is more aggressive about optimization.

Interpreting JavaScript in Java with Rhino: pausing/resuming scripts

I'm using the javax.script.* package of the JDK. Specifically, I'm using the JavaScript engine, which, from what I've read, seems to be based on a Mozilla-developed JavaScript-in-Java interpreter called Rhino.
What I'm hoping to accomplish is to basically have my JavaScript able to "pause" itself at a certain point in the code (say, halfway through a function call) and only resume itself later when Java allows it to do so.
To illustrate what I mean, imagine this JavaScript code:
function myJSFunction() {
print("Hello ");
mysteriousPauseFunction(); // this is the part I'm wondering about. basically, the script should break here and resume later at Java's discretion...
// upon reaching this comment, we know now that Java has told JavaScript that it's okay to resume, so the next line will now be executed...
print("world");
}
If the "pausing"/"breaking" part involves binding a Java function and passing it a reference to the current ScriptEngine or whatever, that's cool with me. I'm thinking that's what this will probably involve: pausing the JavaScript from within Java.
I did some googling and found that the keyword here appears to be "continuations." From what I can tell, Rhino only supports continuations in interpreted mode (versus compiled mode), which I see is accomplished by setting the "context" to -2. Since the built-in JDK ScriptEngine doesn't seem to mention anything about contexts (or maybe I'm missing it), does this mean I have to download and use Mozilla's Rhino library directly instead?
And are Rhino continuations what I need to accomplish this? I've found a useful tutorial on Rhino continuations, but after reading through it, I'm not 100% sure if this is going to be able to accomplish what I described above. If this is what I'm looking for, then my follow-up question is about the "serialization" mentioned: does this mean that when I resume my script, all variables will have been unset unless I serialize them?
Update: It looks like this IS possible with Rhino. Here's what I have so far in my JavaScript; after the code, I'll explain what it does...
var end = new Continuation();
function myJSFunction()
{
print("Hello ");
var kont = new Continuation();
storePause(script, kont); // script is previously bound by Java into the JavaScript. it is a reference to the script itself.
end();
print("world");
}
My "storePause()" function is a Java function which I have written, and it is bound to the JavaScript, but right now, it doesn't do anything. My next goal will be to flesh out its code such that it stores the continuation and script information as Java objects, so that Java can resume the script later.
Right now, what it's doing is pausing/"breaking" the script after "Hello " is printed but before "world" is printed, so this proves to me that it is possible to pause a script this way.
So, all that I should have left to figure out at this point is how to resume a continuation. Note that the above works using the JDK scripting engine by default (I haven't needed to worry about interpreted mode vs compiled mode at this point -- it seems to default to interpreted mode), but it looks like the process of resuming a script will require Mozilla's Rhino library.
Alright, it took me many hours of digging through documentation, tutorials, and examples, and also posting on here and on the Rhino Google Group, but I've managed to compile a working solution. Since there seems to be no complete example, I'll post my findings here for anyone who stumbles across this in the future.
Actually, my findings are probably too long to post here, so I decided to write up a tutorial on my blog:
Tutorial: Continuations in Mozilla Rhino (a JavaScript interpreter for Java)
Hope that helps someone. As far as I know, this is the only complete Rhino tutorial that shows how to do all of the following: initialize Rhino, load a script from a JavaScript (*.js) file, automatically bind all of the functions in a particular Java class (e.g. ScriptFunctions) as global functions in JavaScript, and finally call a JavaScript function and handle continuations for that call.
Basically, the problem was that I needed to first download the Mozilla Rhino source code (because the version packed in with the JDK is outdated and doesn't support continuations), rewrite all of my code to use the official Rhino package's syntax (it is very different from JDK's ScriptingEngine syntax), write a Java function that throws a ContinuationPending exception and bind it to JavaScript so JavaScript can call it (because throwing a ContinuationPending directly from JavaScript results in a JavaScriptException being thrown, not a ContinuationPending being thrown, and even trying to call getCause() on that JavaScriptException results in null), and then in my Java code that calls my JavaScript function ("myJSFunction" in my original example), have try/catch blocks to check for a ContinuationPending (which is an exception), and then use that ContinuationPending
later to resume the script.
Phew. It was tough, but it's all worth it now.
You didn't explain why you were doing this, but I was emulating a program that interacts with an end user, like this:
print('Hello!');
a=Number(input('enter a number'));
b=Number(input('and another number'));
print('the sum of '+a+' plus '+b+' is '+(a+b))
I've got it working just by creating a print and an input function in javascript that checks for program state.
you can see a demo here.
it's all written in javascript so you can look at the source code with any browser.
Hope it helps
You could use wait/notify:
public final class Pause {
private final Object lock = new Object();
public void await() throws InterruptedException {
synchronized (lock) {
lock.wait();
}
}
public void resumeAll() {
synchronized (lock) {
lock.notifyAll();
}
}
}
Usage:
final Pause pause = new Pause();
class Resumer implements Runnable {
#Override public void run() {
try {
Thread.sleep(5000);
pause.resumeAll();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
new Thread(new Resumer()).start();
SimpleBindings bindings = new SimpleBindings();
bindings.put("pause", pause);
String script = "print('Hello, ');\n"
+ "pause.await();\n"
+ "println('ECMAScript!');\n";
new ScriptEngineManager().getEngineByName("ECMAScript")
.eval(script, bindings);
This is a relatively simplistic solution as you don't mention any other constraints. wait() causes the thread to block, which would not be acceptable in all environments. There is also no easy way to identify what threads are waiting on the Pause instance if you want to run scripts concurrently.
Note: the InterruptedException on await() should be handled either by the caller or by doing something more sensible in await().

First call to JFrame constructor takes a long time during Swing application startup (because of java.awt.Window())

I'm trying to build a simple, lightweight, and responsive application using Java Swing.
When it launches, however, there is a noticeable delay (>500ms) before the window (a JFrame) appears.
I've tracked it down to the constructor of the java.awt.Window class, which is an ancestor of JFrame.
Oddly, the constructor is only slow for the first call. If I create multiple JFrame objects, the time spent in the constructor is ~600ms for the first object, but is typically measured as 0ms for subsequent objects.
Here's a simple example which, on my system, shows this significant delay for the first constructor call but not the second:
public static void main(String args[]) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
long start;
start = System.currentTimeMillis();
JFrame frame1 = new JFrame();
System.out.println((System.currentTimeMillis() - start) + " for first JFrame.");
start = System.currentTimeMillis();
JFrame frame2 = new JFrame();
System.out.println((System.currentTimeMillis() - start) + " for second JFrame.");
}
});
}
With typical output:
641 for first JFrame.
0 for second JFrame.
If I add this Window object initialization before the JFrame objects:
java.awt.Window window = new java.awt.Window(null);
Then the output changes to something like:
578 for first Window.
47 for first JFrame.
0 for second JFrame.
When I try the same with the superclass of Window, java.awt.Container, the Window constructor is still the one that takes a long time to execute (so the problem doesn't go above the Window class).
Since the JFrame constructor calls the Window constructor, the above seems to indicate that the first call to the Window constructor is expensive.
What happens in the first call to the constructor that takes so long, and is there anything I can do about it?
Is there some simple fix or is the problem fundamental to Swing/AWT? Or is it perhaps a problem specific to my system/setup?
I'd like my application to open as fast (or nearly as fast) as MS Notepad, and, while I can have text printed to the console around the time Notepad opens (if I put the code before the first JFrame initialization), the above problem means that there is almost a whole second of delay before the window is visible. Will I need to use a different language or GUI framework to get the performance I'm after?
Edit: If I add Thread.sleep(10000) as the first line of run(), the results don't change (they just appear 10 seconds later). This suggests that the problem is not caused by some asynchronous startup code but is instead triggered directly by the constructor call.
Edit 2: Realized the NetBeans Profiler can profile inside the JRE classes, and discovered that most of the time is spent initializing a sun.java2d.d3d.D3DGraphicsDevice object (the Window object needs screen bounds and insets), which is part of a "Direct3D Accelerated Rendering Pipeline for Microsoft Windows Platforms, Enabled by Default", introduced in Java 6u10. It can be disabled by passing the "-Dsun.java2d.d3d=false" property to the JVM, which does reduce the startup time by about 3/4, but I'm not yet sure if I'll need it (D3D) or if there's some other way to get it to load faster.
Here is the output if I put that parameter on the command line:
0 for first Window
47 for first JFrame.
0 for second JFrame.
I'll come back and clean this post up after I dig deeper later.
This answer records what I have found so far. If anyone has more information, please comment or post an answer. I am not completely satisfied with simply disabling Swing's use of D3D, and am open to other solutions.
The Cause: D3D Initialization
Swing uses the Java2D API for drawing, and according to this Java SE 7 troubleshooting guide, Java2D uses a set of rendering pipelines, "which can be roughly defined as different ways of rendering the primitives". More specifically, a Java2D rendering pipeline seems to connect cross-platform Java code to native graphics libraries (OpenGL, X11, D3D, DirectDraw, GDI) that may support hardware acceleration.
In Java 1.6.0_10 (aka 6u10), a "fully hardware accelerated graphics pipeline" based on Direct3D was added to Java2D for Windows to improve rendering performance in Swing and Java2D applications (enabled by default).
By default, when Java2D is used on a Windows system, both this Direct3D pipeline and a DirectDraw/GDI pipeline are enabled by default (I assume they are each being used for different things).
The D3D library, at least, is only loaded and initialized when needed, and a native D3D initialization function which gets called the first time a Window (or a Window descendant) is constructed takes ~500ms (for me) and causes the reported slowness of initialization, and disabling the D3D pipeline seems to remove the call to this native function, significantly decreasing startup time. (Although I'd much prefer to delay, precompute, share (across different java apps), or optimize the D3D initialization, and I wonder if it's this slow for other languages.)
Granted, it's possible that on most systems the time spent in D3D init is negligible, and it is only a problem on my system due to some hardware or driver problem, but I'm somewhat skeptical of this (although, if true, that would be an easy fix).
Detailing the trace down to the native initD3D()
In more detail (skip the following paragraph if you don't care), I used the Netbeans profiler and debugger to find that:
When a JFrame is initialized (constructor called), the constructor of ancestor class java.awt.Window gets called. The Window initializes its GraphicsConfiguration device, which tries to retrieve the default screen device, and so on. The first time this happens (when the first Window or Window descendant is initialized), the screen device doesn't exist, so it is built. In this process, the sun.java2D.d3d.D3DGraphicsDevice class gets initialized, and in its static initialization block (see <clinit>()) it calls a native function, initD3D(), which takes a significant time to execute (~500ms).
I was able to find a version of the source code for D3DGraphicsDevice and its static init block (and I'm really just assuming from this source that initD3D() is what makes its <clinit>() take so long - my profiler doesn't seem to acknowledge native functions - but it's a reasonable guess).
One workaround - disable D3D for Java2D
The D3D pipeline can be disabled by running java with the -Dsun.java2d.d3d=false option, as per this guide on Java2D "system properties" (and also the aforementioned troubleshooting guide). I think this disables D3D but not DirectDraw, which can be disabled with Dsun.java2d.noddraw=true (and then "all operations will be performed with GDI"), but this doesn't noticeably improve initialization time.
For example, I might use a command like the following to run MyJar.jar without D3D:
java -jar -Dsun.java2d.d3d=false MyJar.jar
With the code posted in the question (which initializes a Window and then 2 JFrame objects), I get results like this:
0 for first Window
47 for first JFrame.
0 for second JFrame.
Instead of results like this:
547 for first Window
31 for first JFrame.
0 for second JFrame.
(Note that time is in milliseconds and is measured with System.currentTimeMillis() on Windows, which I think has a resolution of around 15 to 16 ms.)
OpenGL vs Direct3D
OpenGL is used instead of Direct3D if the -Dsun.java2d.opengl=True option is used. On my system there is a slight improvement (~400ms for OpenGL vs ~500ms for D3D), but the delay is still noticeable.
Other Delays
I noticed that initialization of the first JFrame object, even if it is not the first Window, takes much more time than the initialization of subsequent JFrame objects (recorded as 31 to 47 ms vs 0ms).
Profiling indicates this is related to the creation of the first glass pane (a JPanel), and ultimately seems to be caused by Look and Feel and system property intialization/loading inside the javax.swing.UIManager class and object initialization code. It's not too important, but it does explain the observed anomaly.
In my actual program which is a bit more complicated (has to initialize more Swing components), delays seem to be more diffusely distributed in the Swing code, but I've noticed a significant amount of native class loading, "UI installing" (loading default UI properties, etc.), and such. Unfortunately, I don't think there's much to be done about these (please speak up if there is).
Closing thoughts
In the end, there's only so much that can be done, and I have to recognize how far Swing and the JVM have come in the past years.
The creation of the first jframe involves loading the swing library. JVM doesn't load the library looking at the import statement. The libraries are loaded only when the first call to that library is made.
In this case frame1 creation is the first statement that calls the Swing library. By the time frame2 instance is created the swing libraries are already loaded and hence the object creation for frame2 is too fast even to notice some lapse of time. Hence it shows 0.
This explains why it shows 578, 47, 0 when you add up Window statement above the two. This is because the first statement takes time to load java.awt library. Second takes time to load the swing library. And the thirds shows 0 as the library needed for its creation is already loaded.
You can even test it this way. Try to replace the second JFrame creation with JPanel and it still it shows 0.
My guess is that it's loading native libraries. If this is the case, there is not much you can do about it.
Mac OS X 10.5.8, Java 1.6.0_26. Not unexpected, given the JVM startup time and heavyweight graphics peer creation.
247 for first JFrame.
0 for second JFrame.
Addendum: According to the article Java Performance: Startup time, Java Quick Starter may be available on your platform.
It takes time to load all swing classes, then it takes time to load native awt libraries. Perhaps, class loading takes more time because if you just create a JLabel instead of the first JFrame it still takes more time.

Calling function when program exits in java

I would like to save the programs settings every time the user exits the program. So I need a way to call a function when the user quits the program. How do I do that?
I am using Java 1.5.
You can add a shutdown hook to your application by doing the following:
Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
public void run() {
// what you want to do
}
}));
This is basically equivalent to having a try {} finally {} block around your entire program, and basically encompasses what's in the finally block.
Please note the caveats though!
Adding a shutdown hook addShutdownHook(java.lang.Thread) is probably what you look for. There are problems with that approach, though:
you will lose the changes if the program aborts in an uncontrolled way (i.e. if it is killed)
you will lose the changes if there are errors (permission denied, disk full, network errors)
So it might be better to save settings immediately (possibly in an extra thread, to avoid waiting times).
Are you creating a stand alone GUI app (i.e. Swing)?
If so, you should consider how you are providing options to your users how to exit the application.
Namely, if there is going to be a File menu, I would expect that there will be an "Exit" menu item.
Also, if the user closes the last window in the app, I would also expect it to exit the application.
In both cases, it should call code that handles saving the user's preferences.
Using Runtime.getRuntime().addShutdownHook() is certainly a way to do this - but if you are writing Swing applications, I strongly recommend that you take a look at JSR 296 (Swing Application Framework)
Here's a good article on the basics: http://java.sun.com/developer/technicalArticles/javase/swingappfr/.
The JSR reference implementation provides the kind of features that you are looking for at a higher level of abstraction than adding shutdown hooks.
Here is the reference implementation: https://appframework.dev.java.net/

Categories