5

I was following tutorial and below was the example for auto boxing memory leak.

package com.example.memoryleak;
public class Adder {
  public long addIncremental(long l) {
    Long sum=0L;
    sum =sum+l;
    return sum;
  }
  public static void main(String[] args) {
    Adder adder = new Adder();
    for(long ;i<1000;i++)  {
      adder.addIncremental(i);
      }
    }
 }

Now, I could understand that unnecessary objects would be created because of autoboxing but how it caused memory leak, the way I understand is that memory leak is caused when you are holding a strong reference to a dead object. Now, in this case once I have came out of the FOR loop there would be no strong references to those Long objects then how it caused memory leak?

Please note I want to understand how it caused memory leak, I know those objects were unnecessary.

GhostCat
  • 137,827
  • 25
  • 176
  • 248
pjj
  • 2,015
  • 1
  • 17
  • 42
  • 1
    How did you realize that you have memory leak? – Andrii Abramov May 17 '17 at 12:45
  • 1
    The tutorial seems to be absolute rubbish. DZone isn't usually *that* bad. This is more roseindia quality. – Kayaman May 17 '17 at 12:48
  • 1
    @Kayaman as for me, this article should be rewritten or even deleted at all. A lot of typos, wrong explanations. In the comments there are useful comments provided but author says that everything is fine :) – Andrii Abramov May 17 '17 at 13:01
  • While there is no memory leak there, it doesn't mean allocating too many objects in a tight loop can't possibly cause runtime problems. It's just that your problems will be different. – biziclop Apr 30 '19 at 12:15

3 Answers3

9

The other answers are correct: this is not a memory leak.

The code you are showing creates object on a very high rate; and they are subject to garbage collection immediately. None of of these "temp" objects is somehow forgotten; they all get eligible for collection; and the GC will collect them at some point.

A memory leak refers to situations where the used memory keeps ever increasing - without the objects ever becoming eligible for garbage collection.

Given the comment that asks about the "cache" example that uses a map:

  • as long as there is a single (strong!) reference to the map object from another object that is "alive" in GC terms, that map is "alive". And therefore: all objects stored within that map are alive (not eligible for GC)
  • when the last reference to that map vanishes, the map itself becomes eligible for the GC. Same is true for the values within the map - unless there is some other reference to such a value which is still alive.
GhostCat
  • 137,827
  • 25
  • 176
  • 248
  • Thank you so much for your time to answer, could you please have a look to their "Example 2: Using Cache" example because this article is confusing me, my understanding is that suppose someone has explicitly created object of `Cache`, now as soon the method of that class which created object of `Cache` will complete, cache object will become eligible for GC, right? (2.) Suppose in that map if am inserting my own objects, from my method, now as still as soon cache objects will be GC'ed, those object will not have any strong reference and hence they will become eligible for GC, right? – pjj May 17 '17 at 13:09
  • See my updates. But please avoid coming back with more questions. This site is not a free "we make sense out of some not-so-good tutorial" service. Of course, upvotes here or there always help motivating people ;-) – GhostCat May 17 '17 at 13:20
3

Cite from link you provided:

Can you spot the memory leak?

Here I made a mistake. Instead of taking the primitive long for the sum, I took the Long (wrapper class), which is the cause of the memory leak. Due to auto-boxing, sum=sum+l; creates a new object in every iteration, so 1000 unnecessary objects will be created. Please avoid mixing and matching between primitive and wrapper classes. Try to use primitive as much as you can.

Actually, there is no memory leak here. Better say, it produces some redundant memory usage and garbage collection.

If you want to simulate real memory leak refer to this question: Creating a memory leak with Java.

Also, as a result of adder.addIncremental(i); is ignored there could be some JVM optimizations for this code.

If you take a look at plots of memory you will see that memory usage is quite stable from GC cycle to cycle.

For example:

enter image description here

Community
  • 1
  • 1
Andrii Abramov
  • 10,019
  • 9
  • 74
  • 96
  • Thanks for your answer. And how about "Example 2: Using Cache" in same example, same case that there is no really a memory leak, right? – pjj May 17 '17 at 12:51
  • @pjj, well, Example 1 is absolutely incorrectly explained. Second example is very logic dependent. The only useful phrase there is about WeakHashMap. – Andrii Abramov May 17 '17 at 12:54
1

Can you spot the memory leak?

Here I made a mistake. Instead of taking the primitive long for the sum, I took the Long (wrapper class), which is the cause of the memory leak. Due to auto-boxing, sum=sum+l; creates a new object in every iteration, so 1000 unnecessary objects will be created.

This quoter from tutorial is wrong. In this example you will have no memory leaks but just not efficient memory using.

Mike Adamenko
  • 2,944
  • 1
  • 15
  • 28