In the below explanation only the plain memory for the data is in the scope. All additional memory need for the structures are left out. It's more an overview as an in deep detail view.
The memory is eaten at those lines
String parcour = "";
...
String line = bReader.readLine();
...
parcour += line;
The line parcour += line
is compiled into the class file as
new StringBuilder().append(parcour).append(line).toString()
Assume parcour
contains a string of size 10 MB and line
would be of size 2 MB. Then the memory allocated during parcour += line;
would be (roughly)
// creates a StringBuilder object of size 12 MB
new StringBuilder().append(parcour).append(line)
// the `.toString()` would generate a String object of size 12 MB
new StringBuilder().append(parcour).append(line).toString()
Your code needs before the newly created String is assigned to parcour
around 34 MB.
parcour = 10 MB
the temporary StringBuilder object = 12 MB
the String fromStringBuilder = 12 MB
------------------------------------------
total 34 MB
A small demo snippet to show that the OutOfMemoryException
is thrown much earlier then you currently expect.
OOMString.java
class OOMString {
public static void main(String[] args) throws Exception {
String parcour = "";
char[] chars = new char[1_000];
String line = new String(chars);
while(line != null)
{
System.out.println("length = " + parcour.length());
parcour += line;
}
}
}
OOMStringBuilder.java
class OOMStringBuilder {
public static void main(String[] args) throws Exception {
StringBuilder parcour = new StringBuilder();
char[] chars = new char[1_000];
String line = new String(chars);
while(line != null)
{
System.out.println("length = " + parcour.length());
parcour.append(line);
}
}
}
Both snippets do the same. They add a 1,000 charcater string to parcour
till the OutOfMemoryException
is thrown. To speed it up we limit the heap size to 10 MB.
output of java -Xmx10m OOMString
length = 1048000
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
output of java -Xmx10m OOMStringBuilder
length = 2052000
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
When you execute the code you will notice that OOMString
needs much more time to fail (even at a shorter length) than OOMStringBuilder
.
You also need to keep in mind that a single character is two bytes long. If your file contains 100 ASCII characters they consume 200 byte in memory.
Maybe this small demonstration could explain it a little bit for you.