Ranter
Join devRant
Do all the things like
++ or -- rants, post your own rants, comment on others' rants and build your customized dev avatar
Sign Up
Pipeless API
From the creators of devRant, Pipeless lets you power real-time personalized recommendations and activity feeds using a simple API
Learn More
Comments
-
public class Sabotage {
private static List<String> data = new ArrayList();
public static void leak(int amount) {
while (amount-- > 0) {
data.add("aaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
}
}
}
// any other class
Sabotage.leak(1000);
It's very easy to leak memory in static context as it's never garbage-collected. -
SnafuAI6846y@netikras not really a leak since the object holding thar memory is still accessible and never freed.
-
SnafuAI6846yEasiest way to create a true memory leak is to use ThreadLocal in a thread from a thread pool and store stuff then reuse the tread without first performing cleanup. You will no longer have references to the stored data but they will not be garbage collected.
Also, nested classloaders can do the trick. -
@SnafuAI never freed, constantly growing, constantly requiring more and more memory. And most likely already forgotten by a dev.
How does that not qualify to mem leak? :)
I can think of more examples, involving jni, which would be a hard to find leak. But the one above, in static context, is just a plain-simple example -
@SnafuAI threadlocal also uses static context. And you do have references to all the values in there. That's how sessions get all mixed up in thread-per-req model. And threadlocals is the reason why you can't use spring's static security context resolver in reactive webservices.
So yeah, references are in the map, you can reach them via static context. It's just a more complicated version of my example -
SnafuAI6846y@netikras for me a memory leak is something that happens contrary to expectations. In the ThreadLocal example, the expectation would be that the upon releasing the thread, the data you saved would get deleted. Since the classes involved are part of the SDK and not custom code, you do not have control over the behavior and unless you know in advance of that particular gotcha, you would not expect it.
In your example, the code is designed specifically to keep data in memory, so in my book it qualifies as a "Stupidity Leak".
I know that technically they are the same thing, but I do believe that code intent makes a difference. Otherwise, what's the difference between objects you normally create and leaks? -
@SnafuAI Well then every leak is a stupidity leak :)
the "contrary to expectations" part is very slippery. One might expect for some some mechanism in SDK that should housekeep records from List<String> data; once response is returned. Now imagine this `data` happens to be in Spring. Wouldn't you expect Spring to clean after itself? I assume you would. Me too.
Different people (of different xp) might expect different things from the same piece of code, especially when that code is in different contexts :) -
SnafuAI6846y@netikras Well, there is some housekeeping in the case of List<String>. The fact that string literals and interned string do not get GC'd is intended behaviour and not a mistake. All other strings will be treated as any other object would.
The List<String> is a bit contrived here since String is a bit of a. To be honest, I would be quite annoyed if a List<Object> would not get proper housekeeping after it is no longer in use.
I believe that intent matters. If it doesn't, a cache and a memory leak are the same thing, right?
Also, in the case of pooled threads, there's a bit of inconsistency - if I instantiate a thread by hand, use it, use its ThreadLocal and then remove any reference to the thread, everything will be cleaned; however, if the same thread is part of a pool, when I remove all my explicit references it will just go back in the pool without any cleanup. The problem here is that I have no indication on the behavior of the pool - will it sanitize the thread or not?
How can we create a memory leak in Java?
question