UPDATE2:
最初这个问题与MongoDB和Jackson混淆了,但它实际上只是通过制作大量的Strings
来重现。
问题在于,当创建许多小String
时,大约10%的JVM内存似乎永久丢失。这仅在创建三次字符串后才会出现,并且似乎不再出现。
这似乎是Java“功能”或错误。
UPDATE3: JVM以-Xms3000m
启动。
UPDATE4:可能与string interning有关。
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
public class TestMemLeak {
public static String TEXT100 = "";
static {
for (int i = 0; i < 10; i++) {
TEXT100 += "aaaaabbbbb";
}
}
public static String TEXT1000 = "";
static {
for (int i = 0; i < 10; i++) {
TEXT1000 += TEXT100;
}
}
public static void main(String[] args) throws Exception {
for (int i: Arrays.asList(1, 2, 3, 4)) {
System.out.println("---------- " + i + " ------------");
System.gc();
try {
makeStrings();
} catch (Exception e) {
e.printStackTrace();
}
}
}
public static List<String> makeStrings() throws Exception {
printMem("*** start ***");
List<String> l= new LinkedList<String>();
for (int i = 0; i < 1000000; i++) {
l.add("" + TEXT1000);
}
printMem("*** end ***");
return l;
}
public static void printMem(String s) {
System.out.println(s);
System.out.println("free mem: " + Runtime.getRuntime().freeMemory());
System.out.println(" max mem: " + Runtime.getRuntime().maxMemory());
System.out.println(" ttl mem: " + Runtime.getRuntime().totalMemory());
}
}
以下输出。请注意,在第三个循环中,可用的mem永久丢失。在进一步的循环中不会发生这种情况。
---------- 1 ------------
*** start ***
free mem: 2967193768
max mem: 3014656000
ttl mem: 3014656000
*** end ***
free mem: 937879792
max mem: 3014656000
ttl mem: 3014656000
---------- 2 ------------
*** start ***
free mem: 2998712752
max mem: 3014656000
ttl mem: 3014656000
*** end ***
free mem: 938854128
max mem: 3014656000
ttl mem: 3014656000
---------- 3 ------------
*** start ***
free mem: 2998619464
max mem: 3014656000
ttl mem: 3014656000
*** end ***
free mem: 729745856
max mem: 2796224512
ttl mem: 2796224512
---------- 4 ------------
*** start ***
free mem: 2788946120
max mem: 2796224512
ttl mem: 2796224512
*** end ***
free mem: 726522240
max mem: 2796224512
ttl mem: 2796224512
Java:1.7_25