Why is the java getPeer call deprecated?

2.2k views Asked by At

I'm attempting to find the best way of obtaining the X ID code of the backing windows of heavyweight AWT panels. Why is the java.awt.Component.getPeer command listed as deprecated? Is there a security issue involved?

2

There are 2 answers

0
Rácz Attila On

I made a native JNI wrapper for MacOS and needed the AWTWindow pointer in java 17 which is the NSWindow basically.

You can still get the AWTWindow pointer by a little bit of hackery.

Add the following jvm args to the target:

--add-exports java.desktop/sun.lwawt=ALL-UNNAMED --add-exports java.desktop/sun.lwawt.macosx=ALL-UNNAMED --add-opens java.desktop/java.awt=ALL-UNNAMED

The java code is the following:

    JFrame jf = new JFrame();
    Component jfComponent = ((Component) jf);
    
    try {
        Field field =  Component.class.getDeclaredField("peer");
        field.setAccessible(true);
        CPlatformWindow platformWindow = (CPlatformWindow)((LWWindowPeer)field.get(jfComponent)).getPlatformWindow();
    
        AtomicLong awtWindowPointer = new AtomicLong();
        platformWindow.execute(l -> {
            awtWindowPointer.set(l);
        });
        System.out.println("AWT window pointer: "+String.format("0x%08X", awtWindowPointer.get()));
    } catch (Exception ex) {
        ex.printStackTrace();
    }

By the way, obviously this may breaks future compatibility and also this code is platform specific, so kinda defeat the java purpose.

0
Stephen C On

The javadoc states:

As of JDK version 1.1, programs should not directly manipulate peers; replaced by boolean isDisplayable().

It is a design issue rather than a security issue.

The issue being addressed is that the peer implementations can behave rather differently from one platform to another, and indeed (at least in theory) from one version of Java to another. So, if your application accesses the peers directly, then it is liable to be non-portable.

At any rate, direct access to peers has been strongly discourage for a long time. The java.awt.peer package and classes have not been documented in the standard javadoc (at least) as far back as Java 1.4.2. The source code for the peer classes say this: (Java 6 version)

 * The peer interfaces are intended only for use in porting
 * the AWT. They are not intended for use by application
 * developers, and developers should not implement peers
 * nor invoke any of the peer methods directly on the peer
 * instances.

In fact, as of Java 9 the previously deprecated getPeer() method has been removed. So if you want a strong reason why you should not use getPeer() it is because your code won't work on Java 9 if you use it!

Now, if you really, really needed to access the AWT peers in Java 9, you could still use reflection to access the package-private peer variable. However, the risk of using reflection to dive into the AWT implementation is that your code may break (again) in a future release. Indeed, the Java maintainers are progressively locking down reflective access to the Java internals. (I have not checked, but I suspect that this access will have been blocked in Java 16 by "JEP 396: Strongly Encapsulate JDK Internals by Default (JDK-8256299)")