Reputation: 919
I have an application doing a lot of string manipulation, and I noticed that the jvm memory usage is very high while I'm not even storing anything in memory.
I made a sample application to demonstrate the issue : I have a simple JFrame with one button
private void buttonDoWorkActionPerformed(java.awt.event.ActionEvent evt) {
String randomString = "abc test garbagecollector";
ArrayList<String> results;
for(int i=0; i<100000; i++)
results = doNothing(randomString.split(" "));
results = null;//No effect
System.gc();//No effect
}
private static ArrayList<String> doNothing(String[] words) {
ArrayList<String> results = new ArrayList<String>();
for (String word : words)
results.add(word);
return results;
}
If you run this sample the JVM takes about 50Mo in the memory, and once you hit the button it will raise to 150Mo and will never go down. EDIT : I am refering to the "java.exe" process in the windows task manager.
Obviously I'm doing a lot of temporary string copies, but I excpect them to be freed by the carbage collector once I lose the references.
EDIT: Maybe not related but I tryed with java 1.6 both 32 and 64 bits versions.
Upvotes: 4
Views: 612
Reputation: 533510
You need to clarify what you mean by it
as there are many levels you might be seeing here. Some will decrease on a GC, some will not.
If you are looking at memory usage after a GC, you should see not increase, and if you are seeing an increase in something else it's likely to be the maximum memory or some other number.
public static long memoryUsed() {
return Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory();
}
public static void main(String... args) {
String randomString = "abc test garbagecollector";
System.gc();
System.out.printf("Memory used before test started %.1f MB%n", memoryUsed() / 1e6);
for (int t = 0; t < 5; t++) {
List<String> results = new ArrayList<String>();
for (int i = 0; i < 100000; i++) {
for (String word : randomString.split(" "))
results.add(word);
}
long beforeGC = memoryUsed();
results = null;
System.gc();
System.out.printf("%d: before GC %.1f MB used, after GC %.1f MB used%n",
t, beforeGC / 1e6, memoryUsed() / 1e6);
}
}
prints
Memory used before test started 5.7 MB
0: before GC 61.8 MB used, after GC 5.8 MB used
1: before GC 44.3 MB used, after GC 5.8 MB used
2: before GC 44.3 MB used, after GC 5.8 MB used
3: before GC 44.3 MB used, after GC 5.8 MB used
4: before GC 44.3 MB used, after GC 5.8 MB used
Upvotes: 5
Reputation: 2471
The Strings are probably being interned, this is an issue w/ Java and Strings related to some of the VM design decisions. You can probably try getting VisualVM or some other framework, connect to the JVM you're running and see the objects, and/or do a heap dump and look at the results.
Upvotes: 0