How do I run Java apps upscaled on a high-DPI display?

81

36

I'm trying to run a Java app (JAR file) on a high-DPI display on Windows 10. The app uses Swing and thus isn't DPI-aware. Normally when I run an application that isn't DPI-aware, Windows will scale it for me, albeit blurry. But for some reason it's not scaling the Java app; I just get a tiny little window in the corner with impossible-to-read text. How do I run a Java app with Windows' high-DPI (blurry) scaling?

Jeff E

Posted 2015-10-18T16:43:09.387

Reputation: 906

Is it your application and do you control the sources/objects, or is it a legacy application that is now unchangeable ? – harrymc – 2015-11-20T14:57:20.863

3It's not my application; no control over the source. – Jeff E – 2015-11-20T18:53:54.507

Bad news, you might need to lower your DPI to run that application. Here are some resources with hacks that might help : Fix blurry fonts in Windows 10, DPI Settings in Windows 10, Windows 10 DPI blurry. Create at least a system restore point backup before trying them out, just in case. The fallback solution might be to return to Windows 7.

– harrymc – 2015-11-20T19:39:42.520

You could also try out Display Changer which can change the display resolution, run the program, then restore the original settings.

– harrymc – 2015-11-20T20:34:13.840

Please comment on the above comments ... – harrymc – 2015-11-23T08:25:01.663

5@harrymc How would either of the above help? The problem isn't blurry fonts or that it refuses to run, the problem is that everything is tiny. The "blurry" font rendering is what I want to achieve, and as I understood the OP's question, they do too. Setting the DPI scaling to 100% would make the whole system tiny; setting the display resolution to a non-native one would make everything look blurry. (Okay, no blurrier than on a 1080p display for me, but still.) – millimoose – 2015-11-25T20:48:17.760

1@harrymc And while the latter might make the app usable, I'm sure you understand why answering "how do I make X work on a 2160p display?" with "use a worse display" is kind of missing the point. – millimoose – 2015-11-25T20:49:58.567

In its march toward the perfect automatic display on tablets, Microsoft unfortunately doesn't much care about older desktop applications. I have listed all the known display hacks for Windows 10, because not all their effects are known, and they might be helpful if you had to reduce screen resolution or use the magnifier. Display Changer is probably the best solution by reducing resolution only for the duration of running this one app. Another would be having a secondary monitor of lower resolution. If I had a better solution, I would have put it in an answer rather than a comment ... – harrymc – 2015-11-26T07:27:41.293

I wouldn't blame Microsoft for this. Their solution for older desktop applications is the "blurry" upscaling, and it works, even though it's not pretty. The problem seems to be that Java "claims" it can handle a high-DPI display, or otherwise insists on working with physical pixels, as opposed to an upscaled abstraction, but then does is not quite able to cash the checks it's written. (At least for Swing applications.) That's why I was kind of hoping there's a solution on the Java side of things to make it stop pretending it can handle my display when it can't. – millimoose – 2015-11-26T09:13:05.000

(A sane legacy app will actually be presented with a "fake" display to render on that's the dimensions of your actual display divided by your scaling factor. A handy example of such an app would be Steam, whose seemingly incorrect hardware survey results clued me in to this. It actually seems to take some effort to land in the uncanny valley of microscopic rendering, on the part of either an app's developers or whoever made the GUI toolkit they're using.) – millimoose – 2015-11-26T09:21:36.783

The GUI toolkit the app uses is of course the problem here and dates from when hi-res monitors and Windows 10 did not exist. If it worked once in Windows 7, where the display algorithms were less automatic, you might consider downgrading, which is easy enough to do (on condition of having upgraded Windows 7 to 10). – harrymc – 2015-11-26T13:45:05.030

Answers

38

The problem here seems to be that Swing is by default claiming that it is DPI aware, so windows doesn't scale it. Use this switch to turn off this behavior and windows will start scaling your swing app:

-Dsun.java2d.dpiaware=false

[EDIT: Unfortunately, this flag no longer seems to work in Java 8, I was testing it in Java 6. Looks like this is a known issue.]

[EDIT 2: You can modify a Java 8 install to work correctly, using a program to modify the EXE manifests. I changed the setting from true to false in the manifests inside of java.exe and javaw.exe, and now my Swing programs scale correctly in Windows 10 high dpi. I used Resource Tuner to this.]

[Edit 3] Just use Java 9

CarlG

Posted 2015-10-18T16:43:09.387

Reputation: 506

Can you elaborate on the edit #2? Which setting did you modify in the manifest, exactly? – Tomalak – 2016-11-11T14:56:59.467

In the Manifest XML, it is the <dpiAware> flag under asmv3:applicationasmv3:windowsSettings

– CarlG – 2016-11-17T17:39:36.770

That's the point. I've seen that flag and I set it to false, but the application (JNLP/WebStart) did not scale properly either way. Can you think of a simple way to cross-check whether this works or not, e.g. a test app that you know of that responds to this setting? – Tomalak – 2016-11-17T17:45:58.860

Webstart is particularly finicky because it can be hard to pinpoint exactly which executable in which jre distro you have installed you end up using. As a cross-check, I'd try launching your app directly with java.exe or javaw.exe and skipping JWS to see if there's a difference. – CarlG – 2016-12-05T14:39:54.210

There's only one JRE installed. But I get a sinking feeling that the app screen actually is implemented as an image with sensitive areas as "buttons" (much like image map in HTML) and that it therefore won't scale no matter what I do. – Tomalak – 2016-12-05T16:15:19.877

Just wanted to add that if you have a java application which has been packaged up as an exe with a jre (so you don't have to install java) this works wonderfully - specifically changing the dpiaware flag to false in the packaged java.exe and javaw.exe – stoves – 2017-03-15T02:24:57.787

4This is somewhere between comical and farcical. The framework mis-reports its capabilities and the switch that fixed the error is removed. The only work-around? For end-users to buy a 3rd party tool. And people wonder why Java has such a poor reputation. – Basic – 2017-08-01T12:52:47.617

The linked issue for the first edit is for OpenJDK. This flag works fine for me on Oracle Java 8. – Justin Smith – 2017-08-10T19:14:17.910

No need for a special tool, a simple hex editor will do to edit the java(w).exe, just take care to overwrite instead of insert. Never failed me. Mind though that things change in Java 9: E.g. on a 200% scale system, your Graphics2Ds will come with a scale of 2 right away (not those of your BufferedImages, though). You can getTransform, setToScale(1,1) the return value, and then setTransform with that changed transform to get to scale 1 if you absolutely want to.

– Dreamspace President – 2017-10-08T06:29:18.550

After more research, I created a class for devs who do their scaling manually (e.g. for custom components and custom graphics) that should be applicable to scaling problems independently of whether Java 8 or Java 9 is used.

– Dreamspace President – 2017-10-08T12:13:27.430

I found that for some applications it is necessary to run java with the following command line: "*Your_Path_To_Java*\javaw.exe" -Xms256M -Xmx512M -noverify -jar *YOUR_FILE.jar . Run such command in the directory where *YOUR_FILE.jar is located. More details can be found here

– 1NN – 2017-12-19T13:20:13.497

WARNING: we've just discovered that if you 'hack' your JDK to make it high-dpi compliant (using the Resource Tuner method described above for exemple), then it may not be recognized by default by your Antivirus (which has some preconfigured whitelist of exe) and in some case it may considerably drag down the performance. In our case, with a lot of threads, our app was unusable after 'hacking' the JDK... – Francois Marot – 2018-01-10T10:09:29.640

Sorry for stupid question, where do I get consumer version of Java 9? – sich – 2019-05-13T08:23:55.633

77

Just found an easy solution on my Windows 10 machine:

  1. Find java.exe you installed.
  2. Right click -> Properties
  3. Go to Compatibility tab
  4. Check Override high DPI scaling behavior.
  5. Choose System for Scaling performed by:

Elderry

Posted 2015-10-18T16:43:09.387

Reputation: 1 231

5Best solution - I had this problem running a .jnlp file so I had to change the "C:\Program Files\Java\jre1.8.0_131\bin\jp2launcher.exe" but this worked like charm. – Dror Harari – 2017-05-18T13:49:56.090

For me it was the JDK version. Found by right clicking and opening the options from the task manager in Windows 10. – Brian Knoblauch – 2017-05-31T18:32:23.983

3For Windows 10, running Java-based Minecraft launchers, I had to change all the installed Java versions on my system for it to work (java.exe and javaw.exe). – cyberbit – 2017-07-10T22:32:48.650

6I used a less intrusive variant. I created a shortcut for command java -jar myJarFile.jar and did the steps 2 to 5 on that shortcut (Windows 10, Java 8). – Julien Kronegg – 2017-08-25T11:41:11.673

Note a potential issue: When I use this to fix C.a.R. (Compass and Ruler), the startup dialog (the logo while initializing) goes to the bottom right corner on a Surface Pro 4. – SOFe – 2017-11-28T01:35:04.693

2For me, it was javaw.exe – masterxilo – 2017-12-13T11:28:14.313

Yes, as @masterxilo says - you need to make this change to both java.exe and javaw.exe to affect all various java apps that may run on your system. – Gal – 2018-03-18T04:48:02.400

Excellent, a really elegant solution. I had an issue with a web initialised program so for me the exe was jp2launcher.exe found in the jre<version>\bin folder. – Edward Comeau – 2018-05-17T13:47:37.397

This seems to work if all monitors are scaled the same amount. But if you have the main monitor at 150% and second monitor at 100%, it will come up right if it first comes up on the main monitor (even if moved to the second), but be broken if it first comes up on the second monitor (regardless if you move it to the main one). Still, better than being broken everywhere... – LightCC – 2018-11-16T05:54:36.207

Amazing, this worked! – David Brossard – 2019-07-18T16:11:49.290

Also to note it also worked for me on a jave-based executable, MySQLWorkbench.exe. I'm thankful for finally unblurry text! (I haven't yet tested LightCC's warning about 2 monitors with different resolutions.) – Daryn – 2020-02-09T14:01:16.873

15

If you stumbled across this question but are actually looking for a solution that works on Linux, this is for you.

If you can add parameters to the java binary which launches the application, you can use the option -D to pass a value for the sun.java2d.uiScale proprty to specify a scaling factor for Java2D. This will scale your application. The scaling factor value is a double. Make sure that you pass this option to the java binary itself, not the launched Java application.

Example: Launch NearInfinity.jar with a UI scaling factor of 2.5

java -Dsun.java2d.uiScale=2.5 -jar ~/jars/NearInfinity.jar

I found this article quite useful in general for running Linux on HiDPI systems, and some of the things might work on Windows as well: https://wiki.archlinux.org/index.php/HiDPI

Christian Hujer

Posted 2015-10-18T16:43:09.387

Reputation: 260

This is good, though I wish I could get a scaling of 1 for JFrames and the system scaling for JOptionPanes. – NateS – 2018-08-11T13:01:48.643

1Doesn't work for me. – Atte Juvonen – 2018-09-26T16:52:10.200

@AtteJuvonen Instead of just telling "my car doesn't work", when it doesn't work for you, why don't you post a new question describing what you've tried, what was the expected result, what was the actual result, what command line you've used, and what, if any, error messages you got? – Christian Hujer – 2018-09-27T05:51:17.000

@ChristianHujer I tried launching my Java Swing app with that parameter (same command line as the one in your answer, except path to jar is different) and the app was launched without scaling. – Atte Juvonen – 2018-09-27T11:55:10.000

Sorry if I seem rude, just frustrated when nothing works. FWIW I did post a new question on this and I will also post a bounty on it as soon as the site allows me. – Atte Juvonen – 2018-09-27T11:56:25.970

@AtteJuvonen I've tried to find your question. I've checked the following profiles of yours: stackoverflow, superuser, askubuntu, unix. If it is there, I must have missed it. If you copy the URL of your question here, that might help. – Christian Hujer – 2018-09-27T12:43:52.673

11

Solution: Run it on JRE 9.

This is because the Java runtime declared itself to be "DPI-aware" but didn't really supported it for AWT and Swing. Java applications were sized and rendered based on pixels rather than being properly scaled, this included HiDPI displays. Anyways, this has been recently solved. See the issue JEP 263: HiDPI Graphics on Windows and Linux and the upgrade.

So, increasing the font size does not work (because it does not increase the rest of the things); the jvm argument -Dsun.java2d.dpiaware=false does not work (because it is not really supported); and the manifest file + registry edit (for Windows) just does not work.

Then, You need to run it on JRE 9 because it really supports this feature.

Sergio Muriel

Posted 2015-10-18T16:43:09.387

Reputation: 211

I'll be really excited if Java9 fixes this. – music2myear – 2017-08-01T00:12:49.917

3This fails to point out you have to recompile the code. Simply running the same Java 8- application on Java 9+ won't change the behavior – Ramhound – 2017-08-01T01:25:10.843

Running HiDPI programs on Java 9 solves a lot of problems. goo.gl/3zmL7b – Gernot Krost – 2017-09-23T17:45:31.323

3@Ramhound You don't have to recompile. I just built a jar with JDK8 for Java 8 that overrides a fullscreen JPanel's paint() method on a W10 system with 4K screen and 200% scale setting. Run with the java.exe of Java 8, the Graphics2D object given to the method has a scaling of 1, and the JPanel has a getWidth/height of 3840x2160. Run with the java.exe of Java 9, the scaling is 2 and the width/height is 1920x1080. – Dreamspace President – 2017-10-08T06:48:16.893

@DreamspacePresident Exactly what I thought. This is because JREs are usually backwards compatible, meaning that code built on Java 1.4 will run on Java 5, 6, 7, etc; whereas JDKs are usually forwards compatible, meaning that code compiled for Java 1.5 do not necessarily compile for 1.4 or earliest versions. – Sergio Muriel – 2017-10-09T21:45:51.880

@SergioMuriel Huh, I don't understand. Really, I don't see how what you're saying is on topic or logical - but, really, this could be me, I sometimes have that. Could you help me understand? – Dreamspace President – 2017-10-11T15:49:25.247

1You'll find a new method in Java 9: Screen.getPrimary().getOutputScaleX(); which actually does work. (The other option is to use JavaFX screen size, (Screen.getPrimary().getVisualBounds()) which does work, and divide this against Toolkit.getDefaultToolkit().getScreenSize(), You'll find that you can get a guess at the DPI selected: 200% will result in about 2.0, but unfortunately 125% still results in a 1.0 Scaling percentage. However, even after moving to Java9: I found my GUIs all utterly destroyed as the buttons expanded, but some of the constants (used for gaps, padding etc). didn't. – wax_lyrical – 2017-12-20T12:57:24.597

Running JRE 9 doesn't fix this for me. – Atte Juvonen – 2018-09-26T16:52:35.817

Running Java 10 still left my GUI's horribly distorted; even straight horizontal and vertical lines changed between 1 and 2 pixels across their length. I had to modify the javaw.exe compatibility properties (changing the shortcut compatibility properties also works).

– Lawrence Dol – 2018-10-18T19:07:46.197

@wax_lyrical no need to do guesswork; the necessary API actually is there for a very long time. Get a GraphicsConfiguration, either using GraphicsEnvironment.getLocalGraphicsEnvironment() .getDefaultScreenDevice() .getDefaultConfiguration() to get the default or just .getGraphicsConfiguration() on an actual, visible AWT Component. Then, you can invoke .getDefaultTransform() to get the transformation whose scaling component reflects the setting. If you need to deal with BufferedImage etc, needing pixels, apply the transformation to the size, then use identity for painting to screen. – Holger – 2019-03-07T13:24:57.403

@Holger - thanks.. but old comment – wax_lyrical – 2019-03-08T14:07:53.283

@wax_lyrical I know, the comment was old, but it may still affect existing software. After all, this is why these Q&As are kept for future readers. – Holger – 2019-03-11T09:02:57.373

4

To force all java executables to have "properties > compatibility > dpi scaling mode" set to "System", in an administrator powershell (win-x, a), run:

$javaexes = (Get-ChildItem -path "$env:ProgramFiles\Java","${env:ProgramFiles(x86)}\java" -filter java?.exe -recurse  | Where-Object {$_.Name -match "java(|w).exe"} ).fullname

$javaexes | foreach {REG ADD "HKCU\Software\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Layers"  /V $_ /T REG_SZ /D "~ DPIUNAWARE" /F}

to undo:

$javaexes | foreach {REG delete "HKCU\Software\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Layers"  /V $_ /f}

Instead of HKCU you could use HKLM, but then you cannot change the dpi-scaling setting manually anymore in the properties > compatibility dialog of the java*.exe files.

masterxilo

Posted 2015-10-18T16:43:09.387

Reputation: 333

2

You need to set PreferExternalManifest in regedit and create custom manifests for java.exe and javaw.exe as given in following stackoverflow answer https://stackoverflow.com/a/39372897

droidlabel

Posted 2015-10-18T16:43:09.387

Reputation: 21

3Good news, the Fall Creators update allows you to change scaling behaviour by right clicking on the item, selecting properties and then the compatibility tab. Creating a custom external manifest is no longer needed - which is nice. – Richard – 2017-12-19T16:26:13.253

0

Elderry's solution is good, but what if you want to run a jar file on Windows and it doesn't have compatibility options?

Go to C:\Program Files (x86)\Java\jre\bin and find javaw.exe. Right click, properties, compatibility tab, check "override high DPI scaling behavior" and select "System" (Note that "System enhanced" did not work for me).

Now jar file windows should scale properly with readable text. If not, it might mean that Windows doesn't link jar type files to javaw.eve like it should. A third party fix is available at: https://johann.loefflmann.net/en/software/jarfix/index.html

Kenneth

Posted 2015-10-18T16:43:09.387

Reputation: 1

0

Try Java 10.

I found that -Dsun.java2d.dpiaware=false does not work in Java 9 or 10. Also for Java 8 and 9 my swing app is small, but Java 10 sizes properly in windows!

so for an app that you can run from a bat file like: java -jar xxx.jar

I just added JAVA_HOME=....\java_10 and PATH=%JAVA_HOME%\bin;%PATH% in the bat file.

java -jar xxx.jar

Stan Towianski

Posted 2015-10-18T16:43:09.387

Reputation: 101

-2

I tried most of these solutions, but the one that worked for me was setting the system compatibility mode on the files I found in the following location:

C:\Program Files (x86)\Common Files\Oracle\Java\javapath

Ryan Reynolds

Posted 2015-10-18T16:43:09.387

Reputation: 1

2

Welcome to Super User! Please don't add "thanks" or "this one worked for me" as answers. Invest some time in the site and you will gain sufficient privileges to upvote answers you like, which is the Super User way of saying thank you.

– bertieb – 2018-11-30T15:11:38.443

This could be a comment on someone else's answer. To fix, it's necessary to apply compatibility settings to java.exe and/or javaw.exe or use other recommendations. The javapath folder contains links to latest Java executables installed on the system. Thus applying the settings in Program Files should be enough.

– Alexey Ivanov – 2019-10-14T17:20:51.807

-4

I was able to get sensible dpi when ran using command prompt like:

%SystemRoot%\system32\cmd.exe /C C:\your.file.path\yourJarFile.jar

user3301455

Posted 2015-10-18T16:43:09.387

Reputation: 1

This does not answer the question really, and it does not change any High DPI settings of java.exe or javaw.exe. – Alexey Ivanov – 2019-10-14T17:13:00.940