How can I detect if a user has a retina display in Java? I am already aware of detecting the scale factor using Toolkit.getDefaultToolkit().getDesktopProperty("apple.awt.contentScaleFactor")
, but java won't let me convert the returned value into an int. I'm wondering how I can convert that into an int, or another way to detect retina displays.

- 486
- 1
- 6
- 20
-
How do you run Java on a device with a Retina display? Or perhaps I mean, which Java are you running... – Elliott Frisch Dec 24 '13 at 23:25
-
What are you using that won't let you convert the returned value to an int? (it should be a float). – brandonscript Dec 24 '13 at 23:25
-
I'm running it on a Macbook Pro with retina display. When I run the code and try to typecast the returned value into an `Integer`, it gives me an error saying `Exception in thread "main" java.lang.ClassCastException: java.lang.Float cannot be cast to java.lang.Integer` – Tyler Dec 24 '13 at 23:28
-
Don't do it that way! Just use [intValue()](http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/Float.html#intValue%28%29)... – Elliott Frisch Dec 24 '13 at 23:30
-
Java won't let me do that because "the method intValue() is undefined for the type Object." – Tyler Dec 24 '13 at 23:36
3 Answers
Beware that users may have multiple displays! What does “detect a Retina display” mean in this scenario?
For most purposes, you are interested in rendering an image onto a GUI component. You therefore need to detect what display the component is on.
Luckily java.awt.Component
has a getGraphicsConfiguration
method that gives us the necessary information.
However, Java 8 (and 7) and Java 9 require different handling: Java 9 exposes the necessary information directly via the graphics device’s default transform. Java 7 and 8 also expose this transformation, but it is always set to an identity transformation (i.e. no transformation), even for a Retina display.
For Java < 9, we need to use reflection to query macOS specific fields in the OpenJDK classes that implement graphics for Mac.
The following class implements the necessary checks for Retina displays and works for Java 8 as well as Java 9. Java 7 might also work with trivial changes but I didn’t test it.
package me.klmr.ui;
import java.awt.*;
import java.lang.reflect.Method;
public final class Device {
private enum JavaVersion {
V8,
V9
}
private static final JavaVersion JAVA_VERSION = getJavaVersion();
private static JavaVersion getJavaVersion() {
final String versionString = System.getProperty("java.version");
if (versionString.startsWith("1.8")) return JavaVersion.V8;
if (versionString.startsWith("9.")) return JavaVersion.V9;
throw new RuntimeException("Unsupported Java version");
}
public static GraphicsConfiguration getCurrentConfiguration(final Component component) {
final GraphicsConfiguration graphicsConfiguration = component.getGraphicsConfiguration();
if (graphicsConfiguration == null) {
return GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration();
} else {
return graphicsConfiguration;
}
}
public static GraphicsDevice getCurrentDevice(final Component component) {
final GraphicsConfiguration graphicsConfiguration = component.getGraphicsConfiguration();
if (graphicsConfiguration == null) {
return GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice();
} else {
return graphicsConfiguration.getDevice();
}
}
public static boolean isOnRetinaDisplay(final Component component) {
switch (JAVA_VERSION) {
case V8: return isOnRetinaDisplayJava8(component);
case V9: return isOnRetinaDisplayJava9(component);
default: throw new AssertionError("Unreachable");
}
}
public static double getDisplayScalingFactor(final Component component) {
switch (JAVA_VERSION) {
case V8: return getDisplayScalingFactorJava8(component);
case V9: return getDisplayScalingFactorJava9(component);
default: throw new AssertionError("Unreachable");
}
}
private static boolean isOnRetinaDisplayJava8(final Component component) {
final GraphicsDevice device = getCurrentDevice(component);
try {
final Method getScaleFactorMethod = device.getClass().getMethod("getScaleFactor");
final Object scale = getScaleFactorMethod.invoke(device);
return scale instanceof Integer && ((Integer) scale).intValue() == 2;
} catch (ReflectiveOperationException e) {
return false;
}
}
private static boolean isOnRetinaDisplayJava9(final Component component) {
return ! getCurrentConfiguration(component).getDefaultTransform().isIdentity();
}
private static double getDisplayScalingFactorJava8(final Component component) {
return isOnRetinaDisplayJava8(component) ? 2.0 : 1.0;
}
private static double getDisplayScalingFactorJava9(final Component component) {
return getCurrentConfiguration(component).getDefaultTransform().getScaleX();
}
}
In practice, moving a dialog from one screen to another will cause components to re-render. If the component’s rendering code uses the above class to find out the correct resolution, they will render correctly regardless of which display they are currently on.

- 530,221
- 131
- 937
- 1,214
I would get the value this way -
public static boolean hasRetinaDisplay() {
Object obj = Toolkit.getDefaultToolkit()
.getDesktopProperty(
"apple.awt.contentScaleFactor");
if (obj instanceof Float) {
Float f = (Float) obj;
int scale = f.intValue();
return (scale == 2); // 1 indicates a regular mac display.
}
return false;
}

- 198,278
- 20
- 158
- 249
-
Thank you very much, this works. I guess I just needed that if statement and to convert it to a float before converting it into an int. – Tyler Dec 24 '13 at 23:38
-
1May I ask what value you get with a retina display? I'll reword the answer to a full utility method... – Elliott Frisch Dec 24 '13 at 23:40
-
You get 2 if it's a retina display, 1 if it isn't and the computer's a mac, and null otherwise. – Tyler Dec 24 '13 at 23:44
-
1It would be nice to have something that works with Oracle JDKs, since the new ones now support retina display. – eye_mew Jul 29 '14 at 14:14
-
-
4doesn't work for me on latest Oracle JDK, `obj` is just null, however I found another way to get that information, and wrote [this answer](https://stackoverflow.com/a/40399909/1418097) – Display Name Nov 03 '16 at 11:08
-
I confirm that this check does not work on Java 11. The property is always null. – Vladimir Kondratyev Apr 24 '20 at 13:03
-
@VladimirKondratyev When I wrote this answer 7 years ago it worked properly on my Macintosh computer. As it is now 2020, I can assure you that Java 11 did not exist seven years ago. The property has a vendor name in the String. Obviously you can't expect the world to stand still. – Elliott Frisch Apr 24 '20 at 13:32
-
@ElliottFrisch I just wanted to confirm that code does not work any more, so people do not waste a time like me :) Here is working code for Java 11: private boolean isRetina() { final GraphicsConfiguration config = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration(); final AffineTransform transform = config.getDefaultTransform(); return !transform.isIdentity(); } – Vladimir Kondratyev Aug 14 '20 at 20:29
For Java 9, this also works:
public static boolean isMacRetinaDisplay() {
final GraphicsConfiguration gfxConfig = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration();
final AffineTransform transform = gfxConfig.getDefaultTransform();
return !transform.isIdentity();
}
You could alternatively inspect the scale factor of the transform and check if it is equal to 2 and fall back to non-retina otherwise.

- 1,083
- 10
- 18
-
What makes this Java 9 specific? Compiles in Java 7 (haven't run it yet, don't have a silly Retina Mac). – NateS Sep 28 '18 at 22:54
-
1@NateS The API exists but prior to Java 9 it returns the wrong value: Java 7 and Java 8 use an identity transformation even on Retina displays, and the `ScaleX` and `ScaleY` values are always 1.0, regardless of the actual hardware display scale value. – Konrad Rudolph Nov 29 '18 at 11:24