Instantiating a Java AWT object causes empty application to open on macOS - java

When I instantiate an object from java.awt, the program causes a new macOS application named "Java", with no windows, to open.
How can I prevent this from happening?
Here is a minimal example:
import java.awt.Rectangle;
public class Main {
public static void main(String[] args) {
Rectangle rect = new Rectangle();
}
}
After compiling and running it in the most canonical way (javac Main.java; java Main), the following icon appears in the Dock: screenshot
I've traced the code, and the offending method is Toolkit.loadLibraries() (JDK 1.8.0_172-b11).

I found the solution based on #MadProgrammer's comment.
The answer is to set AWT to headless mode.
When executing the program:
$ java -Djava.awt.headless=true Main
Or programatically:
System.setProperty("java.awt.headless", "true");

Related

JavaFX native packaging - bizarre error with initialising static variables

I'm working on a JavaFX project in Netbeans that's currently around 3000 lines long, and I've packaged as an .exe regularly for testing but never come across an issue like this curious incident.
When packaging natively as a Windows .exe file, I found that after installing the .exe and launching my program I was getting a popup saying "Class {mypackage}/{mymainclass} not found." followed by "Failed to launch JVM."
Launching the program in Netbeans, packaging as an .exe, and launching the .jar in Powershell with "java -jar {app}.jar" all gave absolutely no errors. Even the .jar inside the installed application folder was fine, with no errors on the command line.
After a few hours of trawling through git commits and packaging natively, I managed to trace the issue down to a single line of code:
private static ComboBox choices = new ComboBox();
When I initialise the ComboBox in an initialiser, the program magically works after being installed from an .exe:
private static ComboBox choices;
{
choices = new ComboBox();
}
However, when I use a static initialiser (by placing static in front of the first curly brace), even though Netbeans states "initialiser can be static", I get the same error as before.
This is puzzling, because Java is obviously fine with the code itself, but after it's been through the native packager it will not launch. I've used plenty of similar lines of code to initialise static variables in other classes, with no ill effects.
I tried adding a similar line to the main class: private static CheckBox chkbox = new CheckBox();
It caused the exact same error after the .exe was installed (as before, the .jar was fine), but when I cut-and-pasted the line to a different class, it had no effect.
Interestingly, my main class already has a static boolean that is initialised in the same way that the ComboBox and CheckBox were: private static boolean someBool = true; but the boolean causes no problems.
Can anyone explain the reason behind this? Thank you.
Edit: I also tried packaging on a different machine, but it stopped working after the same git commit.
I'm using version 1.8.0_144 of the JDK and JRE.
Edit 2: here is the main class of a simple example that produces the error.
package testproject;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.CheckBox;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
public class MainApplication extends Application {
private static CheckBox testCheckBox = new CheckBox(); // Causes error after launching from installed .exe
/* UNCOMMENT THIS SECTION AND REMOVE THE " = new CheckBox()" ABOVE TO FIX THE ERROR
{
testCheckBox = new CheckBox();
}
*/
#Override
public void start(Stage primaryStage) {
StackPane root = new StackPane();
Scene scene = new Scene(root, 300, 250);
primaryStage.setTitle("Empty window");
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
I would avoid creating JavaFX widgets in static initializers (such as a static field or static block), as this would create them when class is loaded, which might happen in any thread. You want that to happen in JavaFX Application Thread.
In your case it happens in main thread, which is definitely not correct.
Check this answer for more details about JavaFX application startup, and how threads are involved in the process.
Trying to initialize a JavaFX widget outside of "JavaFX Application Thread" is (to my understanding) undefined behavior, and might fail in many different ways (or succeed by luck). If that creation fails, then the class loading fails (because static init has failed), hence "class not found". Unfortunately, since this happens while loading main class, you don't get to see the initial error, just "class XXX not found".
Possibly in your case, the java launcher can deal with this initialization just fine, but the launcher used by your .exe is different. I'm not too surprised it fails. I'm equally surprised it works with regular java :)

Using External .jars compile time vs run time

I'm trying to break into java and game programming using opengl. I built jogl and gluegen using ant and all junit tests ran successfully. However, when I attempt to run a simple OpenGL test program it gives me a "Could not find or load main class..." error. When compiling the program I enter:
javac -cp etc...\jogl-all.jar;etc...\gluegen-rt.jar filename.java
into the command line and I receive no compile-time errors. Then I attempt to run the program using:
java -cp etc...\jogl-all.jar;etc...\gluegen-rt.jar filename
and it tells me it cannot locate the main class.
Is this an error caused by using the external .jars? Or am I not using the -cp function properly? Any help would be appreciated!
The following is the code I'm trying to run:
import com.jogamp.opengl.*;
import com.jogamp.newt.event.WindowAdapter;
import com.jogamp.newt.event.WindowEvent;
import com.jogamp.newt.opengl.GLWindow;
import com.jogamp.common.type.*;
public class SimpleScene {
public static void main(String args[]) {
GLProfile glp = GLProfile.getDefault();
GLCapabilities caps = new GLCapabilities(glp);
GLWindow window = GLWindow.create(caps);
window.setSize(300, 300);
window.setVisible(true);
window.setTitle("NEWT Window Test");
window.addWindowListener(new WindowAdapter() {
public void windowDestroyNotify(WindowEvent arg0) {
System.exit(0);
};
});
}
}

How to modify the "About" OS X dialog panel in a Java application?

What is the simplest way to customize this panel considered that the application is written in Java 7 and my favorite environment is Mac Os?
Thanks
You need to use the com.apple.eawt classes. For example, this scratch program shows a Java dialog instead of the Mac one.
import javax.swing.*;
import com.apple.eawt.*;
import com.apple.eawt.AppEvent.*;
public class Foo
extends JPanel
implements AboutHandler
{
public static void main(String[] args)
throws Exception
{
Foo r = new Foo();
}
public Foo() {
Application.getApplication().setAboutHandler(this);
}
public void handleAbout(final AboutEvent e) {
JOptionPane.showMessageDialog(null, "hello, world");
}
}
Unfortunately all of this stuff is deprecated. Apple used to develop and support all of this but doesn’t anymore, and there are a lot of dead links around the internet.
I figured out the API from reading the Javadoc comments in the source code for these classes.
And running mdfind -name apple | grep -i jar turned up /usr/share/java/Stubs/AppleJavaExtensions.jar on my machine, which allowed the above program to compile and run on my machine. But I have no idea where that file came from or if it’ll be in future versions of Mac OS.

Java mac os x dock application name setting doesn't work?

I tried to set the application name and icon for the Mac OS X dock in my Java program.
I used the following code:
public static void main(String[] args)
{
Application.getApplication().setDockIconImage(icon); // Dock icon
System.setProperty("com.apple.mrj.application.apple.menu.about.name", "Alfabet"); // Program name
new UpdateChecker(); // Check for an update
new Alfabet(); // Start the program
}
The object 'icon' is an java.awt.Image.
The class Alfabet creates the main JFrame of the program. The icon shows up correctly, but the application name doesn't, it still displays the name of the main class of the program. What am I doing wrong? Thank you.
It's not clear where things are going awry, but there's a complete working example here for reference.
Alternatively , try setting the name from the command line:
java -Xdock:name=Alfabet
See also Initial Threads.

Programmatically setting the dock:name Java Mac OS X JVM property

Is there a programatic alternative to setting the dock:name Java Mac OS X property by doing
java -Xdock:name="My App Name" -jar myapp.jar
, or is this the only way to set the dock:name property?
It's been a while, but I believe you need to do the following (this is assuming you're using Swing):
Put your main() method in a separate class from the JFrame.
Before creating the JFrame, set the "com.apple.mrj.application.apple.menu.about.name" system property.
For example:
public class Launcher {
public static void main(String[] args) {
System.setProperty("com.apple.mrj.application.apple.menu.about.name", "Hello World!");
JFrame jframe = new MyJFrame();
jframe.setVisible(true);
}
}
The Apple extensions are documented here:
http://developer.apple.com/mac/library/documentation/Java/Reference/1.5.0/appledoc/api/overview-summary.html
I looked at com.apple.eawt.Application, which gives you access to the icon and menus... but not title, unfortunately.
I am guessing the prescribed approach is to roll out your own App Bundle, as detailed here: http://developer.apple.com/Mac/library/documentation/Java/Conceptual/Java14Development/03-JavaDeployment/JavaDeployment.html

Categories

Resources