package jalview.bin; public class MemorySetting { public static final long leaveFreeMinMemory = 536870912; // 0.5 GB public static final long applicationMinMemory = 536870912; // 0.5 GB private final static int maxHeapSizePerCentDefault = 90; public final static String maxHeapSizePerCentProperty = "jvmmempc"; private final static long maxHeapSizeDefault = 34359738368L; // 32GB private final static long noMemMaxHeapSizeDefault = 8589934592L; // 8GB public final static String maxHeapSizeProperty = "jvmmemmax"; public static long getMemorySetting() { return getMemorySetting(null, null); } public static long getMemorySetting(String jvmmemmaxString, String jvmmempcString) { // actual Xmx value-to-be long maxMemLong = -1; // get (absolute) jvmmaxmem setting long memmax = maxHeapSizeDefault; String jvmmemmaxorig = jvmmemmaxString; if (jvmmemmaxorig == null) { jvmmemmaxorig = System.getProperty(maxHeapSizeProperty); } String jvmmemmax = jvmmemmaxorig; if (jvmmemmax != null && jvmmemmax.length() > 0) { long multiplier = 1; switch (jvmmemmax.toLowerCase().substring(jvmmemmax.length() - 1)) { case "t": multiplier = 1099511627776L; // 2^40 jvmmemmax = jvmmemmax.substring(0, jvmmemmax.length() - 1); break; case "g": multiplier = 1073741824; // 2^30 jvmmemmax = jvmmemmax.substring(0, jvmmemmax.length() - 1); break; case "m": multiplier = 1048576; // 2^20 jvmmemmax = jvmmemmax.substring(0, jvmmemmax.length() - 1); break; case "k": multiplier = 1024; // 2^10 jvmmemmax = jvmmemmax.substring(0, jvmmemmax.length() - 1); break; case "b": multiplier = 1; // 2^0 jvmmemmax = jvmmemmax.substring(0, jvmmemmax.length() - 1); break; default: break; } // parse the arg try { memmax = Long.parseLong(jvmmemmax); } catch (NumberFormatException e) { memmax = maxHeapSizeDefault; System.out.println("MemorySetting Property '" + maxHeapSizeProperty + "' (" + jvmmemmaxorig + "') badly formatted, using default (" + memmax + ")."); } // apply multiplier if not too big (i.e. bigger than a long) if (Long.MAX_VALUE / memmax < multiplier) { memmax = maxHeapSizeDefault; System.out.println( "MemorySetting Property '" + maxHeapSizeProperty + "' (" + jvmmemmaxorig + ") too big, using default (" + memmax + ")."); } else { memmax = multiplier * memmax; } // check at least minimum value (this accounts for negatives too) if (memmax < MemorySetting.applicationMinMemory) { memmax = MemorySetting.applicationMinMemory; System.out.println( "MemorySetting Property '" + maxHeapSizeProperty + "' (" + jvmmemmaxorig + ") too small, using minimum (" + memmax + ")."); } } else { // no need to warn if no setting // System.out.println("MemorySetting Property '" + maxHeapSizeProperty + "' not // set."); } // get max percent of physical memory float percent = maxHeapSizePerCentDefault; String jvmmempc = jvmmempcString; if (jvmmempc == null) { jvmmempc = System.getProperty(maxHeapSizePerCentProperty); } long pcmem = -1; try { if (jvmmempc != null) { float trypercent = Float.parseFloat(jvmmempc); if (0 < trypercent && trypercent <= 100f) { percent = trypercent; } else { System.out.println( "MemorySetting Property '" + maxHeapSizePerCentProperty + "' should be in range 1..100"); } } } catch (NumberFormatException e) { System.out.println( "MemorySetting property '" + maxHeapSizePerCentProperty + "' (" + jvmmempc + ") badly formatted"); } // catch everything in case of no com.sun.management.OperatingSystemMXBean boolean memoryPercentError = false; try { pcmem = MemoryPercent.memPercent(percent); } catch (Throwable t) { memoryPercentError = true; System.out.println("Problem calling MemoryPercent.memPercent(" + percent + "). Likely to be problem with com.sun.management.OperatingSystemMXBean"); t.printStackTrace(); } // In the case of an error reading the percentage if physical memory, let's cap maxMemLong to 8GB if (memoryPercentError && jvmmempc != null && pcmem == -1 && memmax > noMemMaxHeapSizeDefault) { System.out.println( "Capping maximum memory to 8GB due to failure to read physical memory size."); memmax = noMemMaxHeapSizeDefault; } if (pcmem == -1) // not set { maxMemLong = memmax; } else { maxMemLong = Math.min(pcmem, memmax); } return maxMemLong; } }