Commit ffedaea5 authored by Jan S's avatar Jan S Committed by skylot

fix(gui): limit the spare memory to max. 512MiB (#434)

parent aec98644
package jadx.gui.ui; package jadx.gui.ui;
import jadx.gui.utils.NLS; import jadx.gui.utils.NLS;
import jadx.gui.utils.Utils;
import javax.swing.*; import javax.swing.*;
import java.awt.*; import java.awt.*;
...@@ -44,7 +45,7 @@ public class HeapUsageBar extends JProgressBar implements ActionListener { ...@@ -44,7 +45,7 @@ public class HeapUsageBar extends JProgressBar implements ActionListener {
setValue(usedKB); setValue(usedKB);
setString(String.format(textFormat, (usedKB / TWO_TO_20), maxGB)); setString(String.format(textFormat, (usedKB / TWO_TO_20), maxGB));
if (used > r.maxMemory() * 0.8) { if ((used + Utils.MIN_FREE_MEMORY) > r.maxMemory()) {
setForeground(RED); setForeground(RED);
} else { } else {
setForeground(GREEN); setForeground(GREEN);
......
...@@ -26,6 +26,16 @@ public class Utils { ...@@ -26,6 +26,16 @@ public class Utils {
public static final Font FONT_HACK = openFontTTF("Hack-Regular"); public static final Font FONT_HACK = openFontTTF("Hack-Regular");
/**
* The minimum about of memory in bytes we are trying to keep free, otherwise the application may run out of heap
* which ends up in a Java garbage collector running "amok" (CPU utilization 100% for each core and the UI is
* not responsive).
*
* We can calculate and store this value here as the maximum heap is fixed for each JVM instance
* and can't be changed at runtime.
*/
public static final long MIN_FREE_MEMORY = calculateMinFreeMemory();
private Utils() { private Utils() {
} }
...@@ -107,11 +117,21 @@ public class Utils { ...@@ -107,11 +117,21 @@ public class Utils {
return overIcon; return overIcon;
} }
/**
* @return 20% of the maximum heap size limited to 512 MB (bytes)
*/
public static long calculateMinFreeMemory() {
Runtime runtime = Runtime.getRuntime();
long minFree = (long) (runtime.maxMemory() * 0.2);
minFree = Math.min(minFree, 512 * 1048576);
return minFree;
}
public static boolean isFreeMemoryAvailable() { public static boolean isFreeMemoryAvailable() {
Runtime runtime = Runtime.getRuntime(); Runtime runtime = Runtime.getRuntime();
long maxMemory = runtime.maxMemory(); long maxMemory = runtime.maxMemory();
long totalFree = runtime.freeMemory() + maxMemory - runtime.totalMemory(); long totalFree = runtime.freeMemory() + (maxMemory - runtime.totalMemory());
return totalFree > maxMemory * 0.2; return totalFree > MIN_FREE_MEMORY;
} }
public static String memoryInfo() { public static String memoryInfo() {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment