Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsWhite Papers
Discussion GroupsFirst AidDatabasesJavaBeansGUIJava 3DVirtual MachineCORBASecurityToolsGeneral
Java DirectoryOpen Source ProjectsSample Book ChaptersUser GroupsWeb Resources
Related Topics
Databases.NETMore Topics ...

Java Forum / General / August 2006

Tip: Looking for answers? Try searching our database.

String.valueOf() Memory Leak inside of thread.

Thread view: 
BLlewellyn@gmail.com - 10 Aug 2006 20:52 GMT
If anyone could shed some light, I'd appreciate it.

I have a simple class with a main method.  Inside the main method is a
loop.  Each iteration of that loop instantiates an anonymous thread
whose run method contains a single line:

String str = String.valueOf(1);

This is causing a memory leak.  If I change the line to read "String
str = "String.valueOf("1"); there is no problem.  Also, if I do
something like: String str = "Hello world!"; there is also no problem.

If I use String.valueOf(1); inside the loop but outside of the thread,
there is no problem.  Can anyone see why garbage collection is not
occurring inside the thread?

Thanks.

--Bradley

public class Main {
    public static void main(String[] args) {
         Thread thread = null;
         for ( int intLoop = 0; intLoop < 10000; intLoop++ ) {
              String myString;
              myString = String.valueOf(1);
              thread = new Thread() {
                   public void run() {
                        String str = String.valueOf(1);
                   }
              };
              thread.start();
              thread=null;
              System.gc();
         }
    }
}
Thomas Hawtin - 10 Aug 2006 16:16 GMT
> This is causing a memory leak.  If I change the line to read "String
> str = "String.valueOf("1"); there is no problem.  Also, if I do
[quoted text clipped - 3 lines]
> there is no problem.  Can anyone see why garbage collection is not
> occurring inside the thread?

Are you sure you aren't just causing vast numbers of threads to be
running at once? Does shoving in a thread.join() fix it for you?

Tom Hawtin
BLlewellyn@gmail.com - 11 Aug 2006 13:07 GMT
> > This is causing a memory leak.  If I change the line to read "String
> > str = "String.valueOf("1"); there is no problem.  Also, if I do
[quoted text clipped - 8 lines]
>
> Tom Hawtin

Tom:

I have tried adding a thread.join() immediately after the
thread.start() method is called.  The result is the same - according to
the NetBeans Profiler, none of the strings are being reclaimed.  Any
more thoughts?  

Thanks!

--Brad
Robert Klemme - 11 Aug 2006 12:52 GMT
> If anyone could shed some light, I'd appreciate it.
>
[quoted text clipped - 33 lines]
>      }
> }

Some things to consider:

1. IIRC System.gc() is just a hint.  There is no guarantee that GC will
actually start at that moment.

2. There is no timely correlation between thread termination and
System.gc(), i.e. the string might not yet have been created when gc()
is invoked.

3. Generally the JVM is very free to decide when GC occurs.  I doubt it
will create GC overhead if there is just a single (or a few) new objects
on the heap.

4. Your other examples do not exhibit the behavior you seem to observe
because they don't create new instances.

Kind regards

    robert
BLlewellyn@gmail.com - 11 Aug 2006 13:20 GMT
> > If anyone could shed some light, I'd appreciate it.
> >
[quoted text clipped - 53 lines]
>
>     robert

Regarding number 1, using the NetBeans profiler, I'm seeing that each
thread is a live object right up to the end of the program.  Not sure
if it will help, but according to the profiler there are 10,000 live
instances of the anonymous class (Main$1), and over 10,000 instances of
char arrays.

Because of number 2, I've tried using a thread.join() to make sure the
object is done being used.

3.  The profiler is showing that time is being spent in GC - is it
possible that GC is running but decides the memory is not worth
reclaiming?

4.  So basically you're saying that because String.valueOf("AString")
just returns a pointer, there's no string actually being created?  That
makes sense.

I'm thinking that if I can get rid of the char[] reference that's
showing up in the profiler, the thread objects will go along with it.
Any idea what I can do to clear it?

Thanks again!

--Bradley
Robert Klemme - 11 Aug 2006 13:47 GMT
>> Some things to consider:
>>
[quoted text clipped - 17 lines]
> instances of the anonymous class (Main$1), and over 10,000 instances of
> char arrays.

Well, then GC decided to not collect them.

> Because of number 2, I've tried using a thread.join() to make sure the
> object is done being used.
>
> 3.  The profiler is showing that time is being spent in GC - is it
> possible that GC is running but decides the memory is not worth
> reclaiming?

Yes.  There are some nice articles about how GC works on Sun's site.  I
suggest you grab those and read through them - pretty interesting stuff.

GC is a quite complex process and the short story is that the JVM is
pretty free as to /when/ do GC and /which objects/ it will collect.
Especially will an object stay around even after a method terminated as
long as the stack frame is not overridden.  This could be the case for
"myString" in run() because every thread gets its own stack.

> 4.  So basically you're saying that because String.valueOf("AString")
> just returns a pointer, there's no string actually being created?  That
> makes sense.

Exactly.

> I'm thinking that if I can get rid of the char[] reference that's
> showing up in the profiler, the thread objects will go along with it.
> Any idea what I can do to clear it?

I have no idea what you mean here.  The reference path is the other way
round, the char[] inside the String is referenced via the Thread.
Freeing the char[] or the String doesn't impact a thread's reachability
in any way.  Note that threads are special and so the JVM might collect
them at different points in time than ordinary objects.

Cheers

    robert
Gilbert Ostlethwaite - 11 Aug 2006 13:24 GMT
> This is causing a memory leak.  If I change the line to read "String
> str = "String.valueOf("1"); there is no problem.  Also, if I do
> something like: String str = "Hello world!"; there is also no problem.

What version of the JVM are you using?

Regards
Roger
BLlewellyn@gmail.com - 11 Aug 2006 13:41 GMT
> > This is causing a memory leak.  If I change the line to read "String
> > str = "String.valueOf("1"); there is no problem.  Also, if I do
[quoted text clipped - 4 lines]
> Regards
> Roger

Roger:

Thanks for your reply.  I have observed this on JVM 6 beta as well as
1.4.2.  After getting nowhere with it, I decided to stop using the beta
JVM but it didn't change the result.  I haven't tried 1.5.4 or 1.5.7
but I could if you think that might help.

Thanks.

--Bradley
Gilbert Ostlethwaite - 11 Aug 2006 13:50 GMT
> Thanks for your reply.  I have observed this on JVM 6 beta as well as
> 1.4.2.  After getting nowhere with it, I decided to stop using the beta
> JVM but it didn't change the result.  I haven't tried 1.5.4 or 1.5.7
> but I could if you think that might help.

It's just that while investigating something else a couple of weeks ago
I came across a bug report that related to memory leaks, strings and
string buffers in 1.4.1. (Sorry I can't remember the details but it was
on the Sun bug site if you want to go find it) However I was under the
impression that it had been fixed in 1.4.2 :-(  (Again, my memory may
be wrong).

Regards
Roger
BLlewellyn@gmail.com - 11 Aug 2006 13:55 GMT
> > Thanks for your reply.  I have observed this on JVM 6 beta as well as
> > 1.4.2.  After getting nowhere with it, I decided to stop using the beta
[quoted text clipped - 10 lines]
> Regards
> Roger

Ok...thanks for the lead.  I will follow-up with that.  It's all I got
right now :)

--Brad
Thomas Kellerer - 11 Aug 2006 14:30 GMT
> If anyone could shed some light, I'd appreciate it.
>
[quoted text clipped - 11 lines]
> there is no problem.  Can anyone see why garbage collection is not
> occurring inside the thread?

This is strange.

String.valueOf(int) gets dispatched to Integer.toString(int) which has a
special treatment for some values. In your case it directly returns the
literal "1"

public static String toString(int i) {
        switch(i) {
            case Integer.MIN_VALUE: return "-2147483648";
            case -3: return "-3";
            case -2: return "-2";
            case -1: return "-1";
            case 0: return "0";
            case 1: return "1";
            case 2: return "2";
            case 3: return "3";
            case 4: return "4";
            case 5: return "5";
            case 6: return "6";
            case 7: return "7";
            case 8: return "8";
            case 9: return "9";
            case 10: return "10";
        }
....

So the memory leak might be somewhere else.
Maybe inside the Thread class?

Regards
Thomas


Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.