7

I'm using the following code to set my Java Swing application's title in Gnome 3's top bar. However, when I run it, I get the warnings shown below the code. Is there a better way to set the application title in code? Please note that this not a question about setting the title of the window itself.

try
{
    Toolkit toolkit = Toolkit.getDefaultToolkit();
    Field awtAppClassNameField = toolkit.getClass().getDeclaredField("awtAppClassName");
    awtAppClassNameField.setAccessible(true);
    awtAppClassNameField.set(toolkit, "FNDice");
}
catch (NoSuchFieldException | IllegalAccessException e)
{
    e.printStackTrace();
}

Here are the warnings I see when I run my application.

WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by com.gmail.fishnet37222.fndice.App (file:/home/dave/IdeaProjects/fndice/target/classes/) to field sun.awt.X11.XToolkit.awtAppClassName
WARNING: Please consider reporting this to the maintainers of com.gmail.fishnet37222.fndice.App
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release
Dave F
  • 821
  • 1
  • 9
  • 20
  • And it doesnt works? Giving your JFrame a title inst enough? – Marcos Vasconcelos Nov 20 '17 at 00:09
  • It works when I use the code I provided. It gives me those warnings, though. My question is whether there is a way to set the Application title without resorting to hacks that may not be supported in a future version of Java. And no, setting the title on the JFrame is not enough. – Dave F Nov 20 '17 at 00:48
  • These warnings started with JDK9. Instead of allowing custom app name, Oracle is going after their developers. Java is dead. – mariusm Nov 27 '17 at 23:00
  • @mariusm Seems like it was just warning that it's not s supported interface, probably because there's not a guarantee that all environments have a displayed "Application title" in their desktop environment. As it was a warning, and the Project jigsaw (Java 9) now makes API contracts enforceable through their module system, odds are that this app was launched without a flag permitting illegal module access. – Edwin Buck Feb 14 '20 at 20:54

4 Answers4

0

This is a side-effect of two different things, using a non-API interface via reflection, and using a new JVM which is using the module loading system (introduced in Java 9)

With Java Modules, JAR files now contain more metadata about what parts of the contained code should be accessed by other JAR files. This permits a lot of things that were only previously possible with OSGI or custom class loaders.

Odds are the code you are working with and the libraries you are working with have not been updated to correctly work / interface with the module system, which is enforcing by default. To get legacy reflective code to access non-API entry points in a backwards compatible way, you need to add the command line flag --illegal-access=permit to your java launch command.

Note that this might be needed for both the run-time launch and the compiler launch, if you are doing both.

Out of curiosity, on this platform, does jframe.setTitle("title") not work, or is the code base before setTitle was available?

Edwin Buck
  • 69,361
  • 7
  • 100
  • 138
  • 1
    I perceive the same problem. And to answer your question: I use JFrame.setTitle("A"), still in Ubuntu I can see a top menu named after the fully qualified classname. So a setTitle() is not enough. For OS X, there is a JVM switch https://stackoverflow.com/questions/4007512/how-can-i-change-my-java-swing-application-title-in-mac-os-x-title-bar – Queeg Dec 22 '21 at 07:34
0

Assuming the application is launched with a .desktop file, this issue can be fixed by adding the StartupWMClass key to the .desktop file, for example:

StartupWMClass=com-example-Application

The value is the fully qualified name of the main class of the application, with the dots replaced by hyphens.

If you prefer hacking the sun.awt.X11.XToolkit class you simply have to add:

--add-opens=java.desktop/sun.awt.X11=ALL-UNNAMED

to the command line to avoid the illegal reflective access warning.

Emmanuel Bourg
  • 9,601
  • 3
  • 48
  • 76
0

This is what I use to determine the app name for KDE running on Ubuntu using Oracle's JDK. I know of no method to override the value, which is calculated from the java class that contains your main() method. I haven't tested on other window managers or OpenJDK. If your main() method is in com.foo.MyApp, then your app name will be "com-foo-MyApp".

    /**
     * For Java 17, we can no longer access private fields, which means we can't override the "awtAppClassName" setting to control the
     * app name that the Linux window manager uses for window rules in Settings/Window Management/Window Rules.
     *
     * This code was copied from sun.awt.X11.XToolkit. It displays Window class (application) name needed to configure window rules
     */
    public static void displayMainClassName() {
        String mainClassName = null;
        StackTraceElement[] trace = (new Throwable()).getStackTrace();
        int bottom = trace.length - 1;
        if (bottom >= 0) {
            mainClassName = trace[bottom].getClassName();
        }
        if (mainClassName == null || mainClassName.isEmpty()) {
            mainClassName = "AWT";
        }
        mainClassName = mainClassName.replace('.', '-');
        System.out.println("mainClassName = " + mainClassName);
    }
0

I did not find the suggestions here to work for me. And I could not find a natural way either. Note I'm using Ubunutu.

I decided to create a different main class as my entry point. For example instead of having com-my-specific-domain-GameName appear in the task bar and in the dock on mouse hover, I had Game-Name appear by having separate package and class name to mimic what I wanted:

package Game;

import com.my.specific.domain.GameName;

public class Name {
    public static void main(String[] args) {
        GameName.main(args);
    }
}

Unfortunately I don't think this works with single word application names, since class must have a package, requiring at least one '-' delimiter in result.

bourne2program
  • 121
  • 1
  • 5