Java string memory leak

I am not a Java expert.

My code reads the file in String . This code runs every 5 minutes. File size is changing. Sometimes it is 100, sometimes it is 1000 lines.

I worry from memory, after a few days.

The question I have is, when my codes go out of scope of the Reading file function , does Java garbage collect a string?

I'm pretty confused reading on the internet. Some people say that it is not deleted and uses a StringBuffer .

 // Demonstrate FileReader. import java.io.*; class FileReaderDemo { public static void read(BufferedReader br) throws Exception { long length = 0; String s; while (true) { s = br.readLine(); s += "abcd"; if (s == null) { break; } length += s.length(); //System.out.println(s); } System.out.println("Read: " + (length / 1024 / 1024) + " MB"); } public static void main(String args[]) throws Exception { //FileReader fr = new FileReader("FileReaderDemo.java"); FileReader fr = new FileReader("big_file.txt.1"); BufferedReader br = new BufferedReader(fr); String s; read(br); fr = new FileReader("big_file.txt.1"); br = new BufferedReader(fr); read(br); fr = new FileReader("big_file.txt.1"); br = new BufferedReader(fr); read(br); fr = new FileReader("big_file.txt.1"); br = new BufferedReader(fr); read(br); BufferedReader in = new BufferedReader(new InputStreamReader(System. in )); in .readLine(); fr.close(); } } 
+7
source share
5 answers

The code you posted will not be a memory leak. However, the while (true) will never be completed, because s will never be null in the place where you tested it.


Allows you to slightly change it so that it "works"

  public static void read(BufferedReader br) throws Exception { long length = 0; String s = ""; while (true) { String ss = br.readLine(); if (ss == null) { break; } s += ss; length += ss.length(); } System.out.println("Read: " + (length/1024/1024) + " MB"); } 

This code is not a memory leak, because the lines created in the method will be candidates for garbage collection when the method returns (if not earlier).

Every time we do s += ss; , a new line is created consisting of all characters currently in s and characters in ss . Assuming that there are N lines containing the average value of L characters, the operator s += ss; will be called N times, will create N lines and copy on average (N * L)^2 / 2 2/2 characters.


However, there is a good reason to make StringBuilder , which means reducing the number of line strings and copying characters that continue. Let's rewrite the method to use StringBuilder ; those. replacement for StringBuffer that is not synchronized.

  public static void read(BufferedReader br) throws Exception { long length = 0; StringBuilder sb = new StringBuilder(sb); while (true) { String ss = br.readLine(); if (ss == null) { break; } sb.append(ss); length += ss.length(); } System.out.println("Read: " + (length/1024/1024) + " MB"); } 

This version redistributes the internal array of StringBuilder characters no more than log2(N) times and copies no more than 2 * N * L characters.


Summary - using StringBuilder is a good idea, but not due to memory leaks. If you have a memory leak, it is not in the source code sample or in the fixed version.

+3
source

Hi, I am not a Java expert.

Everyone has something that they can learn.

My code reads the file in String, this code runs every 5 minutes. Now once the file size is 100 lines sometimes 1000 lines.

It doesn’t sound very much or very often. There should be no problem.

I worry from memory, after a few days.

You should be able to get a bunch of heaps and see where you run out of memory and why.

The question I have is when my codes go out of scope of the read function. Does Java garbage collect String.

It can be compiled when it is no longer available through a strong link.

I'm pretty confused while reading on the internet, some say it is not deleted and uses StringBuffer

Looks like you came to the right place. I have never heard that.

+6
source

Your read method will never end. Once you reach the end of the file, you just keep adding the string "nullabcd" to s , forever.

EDIT: Forget s reinstalling every time. However, I do not see how your read method can end.

+5
source

Modify the program as shown below to consume less memory. A huge source of memory consumption is associated with repeated string concatenation s += "abcd"; - Avoid this, and you are probably more than halving your memory consumption (not tested - profile it yourself if you want to find out).

 public static void read(BufferedReader br) throws Exception { long length = 0; //String s; <--- change to the line below StringBuilder sb = new StringBuilder(); while (true) { String s = br.readLine(); if (s == null) { break; } //s += "abcd"; <--- change to the line below sb.append(s).append("abcd"); length += s.length(); //System.out.println(s); } System.out.println("Read: " + (length / 1024 / 1024) + " MB"); } 
+2
source

As pointed out by others, this code never ends. It looks like the code you submitted is not the source code you came across.

It is difficult to diagnose without seeing the actual code, but Lines will certainly collect garbage as soon as they do not refer to other parts of the code.

Wild hunch: do you call close() on your readers and InputStreams as soon as you finish with them? If not, it may cause your memory errors.

+1
source

All Articles