• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 package org.unicode.cldr.util;
2 
3 import java.text.CharacterIterator;
4 import java.text.StringCharacterIterator;
5 
6 public class MemoryHelper {
7 
8     /**
9      * Get the amount of memory still available for us to allocate,
10      * including not only freeMemory but also maxMemory - totalMemory
11      *
12      * https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Runtime.html#freeMemory()
13      *
14      * Generally: freeMemory <= totalMemory <= maxMemory
15      *
16      * @param callerId a string identifying the caller, used in log if verbose
17      * @param verbose if true, log the stats
18      * @return the available memory, in bytes
19      */
availableMemory(String callerId, boolean verbose)20     public static synchronized long availableMemory(String callerId, boolean verbose) {
21         final Runtime r = Runtime.getRuntime();
22         long freeMem = r.freeMemory();
23         long maxMem = r.maxMemory();
24         long totalMem = r.totalMemory();
25         if (freeMem > totalMem || totalMem > maxMem) {
26             log(callerId, "Values returned by Runtime violate assumptions!");
27             verbose = true;
28         }
29         long availMem = freeMem + maxMem - totalMem;
30         if (verbose) {
31             log(callerId, "Available memory: " + humanReadableByteCountSI(availMem) +
32                 "; free: " +  humanReadableByteCountSI(freeMem) +
33                 "; max: " +  humanReadableByteCountSI(maxMem) +
34                 "; total: " +  humanReadableByteCountSI(totalMem));
35         }
36         return availMem;
37     }
38 
log(String callerId, String message)39     private static void log(String callerId, String message) {
40         System.out.println("MemoryHelper[" + callerId + "]: " + message);
41     }
42 
43     /**
44      * Convert a byte count to a human readable string
45      * Use SI (1 k = 1,000), not Binary (1 K = 1,024)
46      *
47      * @param bytes the number such as 1234567890
48      * @return the formatted string such as "1.2 GB"
49      *
50      * Source: https://programming.guide/java/formatting-byte-size-to-human-readable-format.html
51     */
humanReadableByteCountSI(long bytes)52     public static String humanReadableByteCountSI(long bytes) {
53         if (-1000 < bytes && bytes < 1000) {
54             return bytes + " B";
55         }
56         CharacterIterator ci = new StringCharacterIterator("kMGTPE");
57         while (bytes <= -999_950 || bytes >= 999_950) {
58             bytes /= 1000;
59             ci.next();
60         }
61         return String.format("%.1f %cB", bytes / 1000.0, ci.current());
62     }
63 }
64