用 Java 创建内存泄漏

I just had an interview, and I was asked to create a memory leak with Java. Needless to say I felt pretty dumb having no clue on how to even start creating one.

What would an example be?

转载于:https://stackoverflow.com/questions/6470651/creating-a-memory-leak-with-java

csdnceshi52
妄徒之命 Google: "Java memory leak"
2 年多之前 回复
csdnceshi64
游.程 Leaving a Scanner unclosed :P
大约 3 年之前 回复
csdnceshi69
YaoRaoLov infinite recurrent method will blow the stack which technically is a memory leak?
大约 3 年之前 回复
csdnceshi77
狐狸.fox I've been asked this question in an interview and the interviewer really wanted to know what can cause the JVM to run out of heap space or perm gen space. I think its a poorly worded interview question in my opinion. I would first qualify: do they really want you to understand errors related to running out of memory and to diagnose and fix them? Trying to provide a sophisticated example to guarantee a problem across all JVMs (some that have deadlock detection) and configurations (a ton of memory allocated) might not be what they are truely looking for.
3 年多之前 回复
csdnceshi59
ℙℕℤℝ Just upvoted so the counter equals the current year. gj mates
3 年多之前 回复
csdnceshi60
℡Wang Yan add data to static lists, create new processes from your JVM, create file handle leaks (they consume memory as well, though usually your OS dies well before it runs out of memory), ... I think the question is more "when is a memory leak a memory leak" than "how do you create one".
接近 4 年之前 回复
weixin_41568126
乱世@小熊 Use a LoggerFactory to create a new logger having a name generated by an incremental sequence. Logger logger = LoggerFactory.get(i); where i increments.
4 年多之前 回复
csdnceshi56
lrony* If you are using any database related tasks then it will be easy to create a memory leak just by ignoring the dispose of the database connection after you finish your database job. such as ignoring to write conn.close() after you opened the connection in a method or a class. You can see the performance of the application will be so weak due to memory leak.
4 年多之前 回复
csdnceshi66
必承其重 | 欲带皇冠 Heck... Java itself is a memory leak. Is running nothing in Java not enough?
接近 5 年之前 回复
weixin_41568127
?yb? you can have a reference leak - a long running thread creates a list collection and always adds objects to it, as long as there is a reference to this list it stays in memory and it grows and grows. How to fix it? java heap profiler hprof can help with visualizing memory usage of threads.
大约 6 年之前 回复
csdnceshi50
三生石@ What about using JNI and make a memory leak in your native code?
接近 8 年之前 回复
csdnceshi71
Memor.の - isn't that a leak in the JVM, not in the Java code? Memory leaks don't exist in interpreted code, but they can exist in the code doing the interpreting.
大约 8 年之前 回复
csdnceshi80
胖鸭 I have encountered one issue in tomcat 5.5, 6.0 and later i came to know this is a memory leak. The following Question itself will give you how to create a memory leak in permgen generation stackoverflow.com/q/10937935/639891
8 年多之前 回复
weixin_41568110
七度&光 while I consider installing JDBC drivers inside the web-app a terribly bad practice, the containers are free to uninstall any JDBC driver and it takes around 3 lines of code. Tomcat does unregistered for quite long time. Yet, still a leak: if you install anything, you must uninstall it - leak.
大约 9 年之前 回复
csdnceshi54
hurriedly% most applications that have a JDBC driver inside the webapp (like most app that want to be independant of container datasource) forget to unregister the JDBC driver when unloading. This one of the root cause for memory leak when unloading app in Toncat. And Tomcat can now FORCE the deregistering the driver (wiki.apache.org/tomcat/MemoryLeakProtection#jdbc). The leak do appear when unloading, not before so you basically mesure the JDBC unregister bug, and not the application leaks.
9 年多之前 回复
weixin_41568110
七度&光 your statement aint true for the simple reason: if the JDBC driver was loaded by the same classloader that loads the application and effectively remains registered, the classloader and all classes will be leaking just the same. If a simple class or instance pertains a registration is a leak clear as day. (in other words failing to unregister or the register not using weak references - leak)
9 年多之前 回复
csdnceshi54
hurriedly% Not to be offencive. But do you really think at your BeanShell solution like that something you'll want to do, something pratical?
9 年多之前 回复
csdnceshi54
hurriedly% Not really. In fact the appliction could really never leak in production but fail to unregister some things (like JDBC drivers) when unloading. This is anoying, but not that bad as you can stay month without redeploy and without leaks. The thing is that as it not pratical to restart your server each time you redeploy, it is worse to have to redeploy the app to recover memory. (And after an OutOfMemory exception you'll not have the opportunity anyway).
9 年多之前 回复
csdnceshi51
旧行李 Not necessarily, if your application uses something like BeanShell or any sort of dynamic loading, you can cause new code to run to fix the problem without recompiling. Obviously a root fix is always preferable, but in some cases it's as easy as triggering an already-written code path to periodically clean things up.
9 年多之前 回复
weixin_41568110
七度&光 defining a special class of leaks is quite easy to me when you have pluggable/redeployable modules, if after a redeploy and full garbage collection a previously loaded class instance remains, it's a leak. Of course, there could be a lot other type like String, byte[] and what not leaks but they manifest themselves too.
9 年多之前 回复
csdnceshi67
bug^君 (1) "ability" to reclaim the memory is useless if your program never use that ability; on both cases you have to change your source code to do the Right Thing. (2) you can even more easily detect the "true memory leaks" because a tool like Valgrind can tell for sure that the memory is completely lost (so, yes, that's another difference). (3) That's true. But that's why I said "equivalent" not "completely the same situation, without any detectable difference".
9 年多之前 回复
csdnceshi51
旧行李 No, they are not equivalent. (1) You possess the ability to reclaim the memory, whereas in a "true leak" your C/C++ program forgets the range that was allocated, there's no safe way to recover. (2) You can very easily detect the problem with profiling, because you can see what objects the "bloat" involves. (3) A "true leak" is an unequivocal error, while a program that keeps lots of objects around until terminated could be a deliberate part of how it is meant to work.
9 年多之前 回复
csdnceshi51
旧行李 It was linked on Reddit, so that's probably driven a lot of views. (And of course, everybody there is having the same problem with the distinction between a memory leak versus just cruddy program logic.)
9 年多之前 回复
csdnceshi61
derek5. - darien's answer is not fanboyism. he explicitly admitted that certain JVMs can have bugs that mean memory gets leaked. this is different than the language spec itself allowing for memory leaks.
9 年多之前 回复
csdnceshi68
local-host Honestly I can't believe the similar question I asked about "Go" got downvoted to -1. Here: stackoverflow.com/questions/4400311/… Basically the memory leaks I was talking about are the ones who got +200 upvotes to the OP and yet I got attacked and insulted for asking if "Go" had the same issue. Somehow I'm not sure that all wiki-thing is working that great.
9 年多之前 回复
csdnceshi67
bug^君 I find it funny that on most answers people are looking for those edge cases and tricks and seem to be completely missing the point (IMO). They could just show code that keep useless references to objects that will never use again, and at the same time never drop those references; one may say those cases are not "true" memory leaks because there are still references to those objects around, but if the program never use those references again and also never drop them, it is completely equivalent to (and as bad as) a "true memory leak".
9 年多之前 回复
csdnceshi65
larry*wei Do they mean, explicitly create a memory leak? Or over time, how can a memory leak occur?
9 年多之前 回复
csdnceshi51
旧行李 I would tell them that Java uses a garbage collector, and ask them to be a bit more specific about their definition of "memory leak", explaining that--barring JVM bugs--Java can't leak memory in quite the same way C/C++ can. You have to have a reference to the object somewhere.
9 年多之前 回复
weixin_41568110
七度&光 I guess I can add at least 10 extra weird cases of memory leaks (my 2nd specialty feels tracking such issues)
9 年多之前 回复
csdnceshi78
程序go I had forgotten about File.deleteOnExit(), that's a great one. If you post that as an answer, I'll upvote it.
9 年多之前 回复

30个回答

I came across a more subtle kind of resource leak recently. We open resources via class loader's getResourceAsStream and it happened that the input stream handles were not closed.

Uhm, you might say, what an idiot.

Well, what makes this interesting is: this way, you can leak heap memory of the underlying process, rather than from JVM's heap.

All you need is a jar file with a file inside which will be referenced from Java code. The bigger the jar file, the quicker memory gets allocated.

You can easily create such a jar with the following class:

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

public class BigJarCreator {
    public static void main(String[] args) throws IOException {
        ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(new File("big.jar")));
        zos.putNextEntry(new ZipEntry("resource.txt"));
        zos.write("not too much in here".getBytes());
        zos.closeEntry();
        zos.putNextEntry(new ZipEntry("largeFile.out"));
        for (int i=0 ; i<10000000 ; i++) {
            zos.write((int) (Math.round(Math.random()*100)+20));
        }
        zos.closeEntry();
        zos.close();
    }
}

Just paste into a file named BigJarCreator.java, compile and run it from command line:

javac BigJarCreator.java
java -cp . BigJarCreator

Et voilà: you find a jar archive in your current working directory with two files inside.

Let's create a second class:

public class MemLeak {
    public static void main(String[] args) throws InterruptedException {
        int ITERATIONS=100000;
        for (int i=0 ; i<ITERATIONS ; i++) {
            MemLeak.class.getClassLoader().getResourceAsStream("resource.txt");
        }
        System.out.println("finished creation of streams, now waiting to be killed");

        Thread.sleep(Long.MAX_VALUE);
    }

}

This class basically does nothing, but create unreferenced InputStream objects. Those objects will be garbage collected immediately and thus, do not contribute to heap size. It is important for our example to load an existing resource from a jar file, and size does matter here!

If you're doubtful, try to compile and start the class above, but make sure to chose a decent heap size (2 MB):

javac MemLeak.java
java -Xmx2m -classpath .:big.jar MemLeak

You will not encounter an OOM error here, as no references are kept, the application will keep running no matter how large you chose ITERATIONS in the above example. The memory consumption of your process (visible in top (RES/RSS) or process explorer) grows unless the application gets to the wait command. In the setup above, it will allocate around 150 MB in memory.

If you want the application to play safe, close the input stream right where it's created:

MemLeak.class.getClassLoader().getResourceAsStream("resource.txt").close();

and your process will not exceed 35 MB, independent of the iteration count.

Quite simple and surprising.

Any time you keep references around to objects that you no longer need you have a memory leak. See Handling memory leaks in Java programs for examples of how memory leaks manifest themselves in Java and what you can do about it.

weixin_41568183
零零乙 I think this got a bit out of hand... I was originally responding to "any time you keep references around to objects that you no longer need you have a memory leak". Specifically, I think I took "need" to mean something more absolute than you meant--rereading your early comments, Bill the Lizard, I find that I actually agree with you. (I also found that I had actually upvoted a few of your comments before I started this mess.)
9 年多之前 回复
weixin_41568110
七度&光 I was think along similar lines. It's technically a memory leak, but there are more useful ways to think about it in order to fix the problem.
9 年多之前 回复
csdnceshi77
狐狸.fox let us continue this discussion in chat
9 年多之前 回复
csdnceshi77
狐狸.fox turning your example around: if I have a bug on my C game where I do "next_stage = NULL" by mistake and didn't allow the user to move on, it is technically a "true memory leak", but it would be silly to call it a memory leak because the right fix would be to allow the user to move on, not to free the memory.
9 年多之前 回复
csdnceshi77
狐狸.fox right, I wouldn't call your game stage example a "memory leak". But I think the difference is what is considered the "right behavior" in each case: In your Minesweeper example, the program was supposed to let the user go to the next stages. In other cases, if your program is keeping useless references around when it was supposed to drop them, it is as bad as a "ture memory leak".
9 年多之前 回复
weixin_41568183
零零乙 In other words, I agree with you too! But I think you are both misrepresenting my scenario as something that it isn't. Another possibly simpler case could be a game with a fatal bug in it, that prevents you from passing a certain stage. Would the further stages, inaccessible but existent, be considered memory leaks? Would a patch that fixes the broken stage be "fixing a memory leak"? I think it's a little silly to use that phrase in that manner.
9 年多之前 回复
weixin_41568183
零零乙 Yes, I realize the difference. My example isn't like that, though--let's say the data is stored in the Sweeper class. When you start a new game the Sweeper reference is set to null, the instance is successfully garbage collected, and the Sweeper reference is assigned a new instance. There is no leakage taking place here. On the other hand, if you had a Vec2f class and managed to accidentally add each instance to some static stack that is never cleared, that would indeed be a memory leak. I find the more apt term for unplayable minesweeper "wasted" memory, instead of "leaked".
9 年多之前 回复
csdnceshi77
狐狸.fox if you keep a reference to an object around and never remove it, the memory won't be retrieved until the JVM is killed, too. Some people won't call it a "true memory leak" because there's a reference somewhere; but if the object is never going to be used again by the program and at the same time the reference will never be dropped by the program either, it is as important as the "true memory leaks" people are looking for as a funny exercise here (or more important, as they are more common than the edge cases people are creating on their answers just to get "true" memory leaks)
9 年多之前 回复
weixin_41568183
零零乙 the Lizard: I didn't have enough characters to say it in my previous comment, but I do want to say that I agree with you given how you define memory leak. Given the loose definition, I'd say there are two types of memory leaks: those that are less important, and those that are more important. The lesser are the ones where memory is simply wasted. The greater are the ones where memory isn't retrieved until the JVM is killed. While you consider both types memory leaks, I only consider the latter a leak.
9 年多之前 回复
weixin_41568183
零零乙 the Lizard: Seems that it's just a difference of definition then, unfortunately. I think that the first definition of a memory leak on Wikipedia supports me--that a memory leak is "when a computer program consumes memory but is unable to release it back to the operating system". The program can certainly do that, and this extra "leaked" data in Minesweeper will go away when whatever class holds the data is garbage collected. I understand your point, and in a broad sense the data is leaked, however I hold the term "memory leak" to be something more specific, and a more serious problem.
9 年多之前 回复
weixin_41568110
七度&光 If you know for a fact that it won't be, then it can't be. The program, as written, will never access the data.
9 年多之前 回复
weixin_41568183
零零乙 the Lizard: According to wikipedia, leaked memory in an OO program is technically "when an object is stored in memory but cannot be accessed by the running code." In my scenario, the object can very well be accessed--it just won't be. (en.wikipedia.org/wiki/Memory_leak)
9 年多之前 回复
weixin_41568110
七度&光 If your program keeps objects in memory that it can never use, then technically it's leaked memory. The fact that you have bigger problems doesn't really change that.
9 年多之前 回复
weixin_41568183
零零乙 the Lizard: I agree--it would still be a valid question, but it becomes worthless. Still meaningful, but worthless. If memory leaks exist when you still have references to objects, anything could be considered a memory leak. Like let's say you fire up Minesweeper, but it has been modified so that you can't click the tiles. (I dunno, maybe you like how the board looks.) Because the data under the tiles is now "no longer need"ed, would that memory be a leak? I think not--but your answer implies it would be.
9 年多之前 回复
csdnceshi56
lrony* great point, never thought about it that way. In a sense, it's impossible to leak in Java, yet programs can have their memory footprint grow unintentionally. In Objective-C, that problem would NOT be called a memory leak.
9 年多之前 回复
weixin_41568110
七度&光 ...then the question of "how do you create a memory leak in X?" becomes meaningless, since it's possible in any language. I don't see how you're drawing that conclusion. There are fewer ways to create a memory leak in Java by any definition. It's definitely still a valid question.
9 年多之前 回复
csdnceshi60
℡Wang Yan I see what you mean (and agree with some of it), but the problem is that if you look at it that way, then the question of "how do you create a memory leak in X?" becomes meaningless, since it's possible in any language. So while it may be true, it's not really specific to Java, so I don't think that's what we're referring to as a "leak" here.
9 年多之前 回复
weixin_41568110
七度&光 That's only one narrow definition that doesn't fully apply to all languages. I'd argue that any memory leak is a bug caused by poor design of the program.
9 年多之前 回复
csdnceshi60
℡Wang Yan I don't believe this is a "leak". It's a bug, and it's by design of the program and language. A leak would be an object hanging around without any references to it.
9 年多之前 回复

Take any web application running in any servlet container (Tomcat, Jetty, Glassfish, whatever...). Redeploy the app 10 or 20 times in a row (it may be enough to simply touch the WAR in the server's autodeploy directory.

Unless anybody has actually tested this, chances are high that you'll get an OutOfMemoryError after a couple of redeployments, because the application did not take care to clean up after itself. You may even find a bug in your server with this test.

The problem is, the lifetime of the container is longer than the lifetime of your application. You have to make sure that all references the container might have to objects or classes of your application can be garbage collected.

If there is just one reference surviving the undeployment of your web app, the corresponding classloader and by consequence all classes of your web app cannot be garbage collected.

Threads started by your application, ThreadLocal variables, logging appenders are some of the usual suspects to cause classloader leaks.

csdnceshi69
YaoRaoLov This is not because of a memory leak, but because the class loader does not unload the previous set of classes. Therefor it is not recommended to redeploy an application server without restarting the server (not the physical machine, but the app server). I have seen the same issue with WebSphere.
2 年多之前 回复

I recently encountered a memory leak situation caused in a way by log4j.

Log4j has this mechanism called Nested Diagnostic Context(NDC) which is an instrument to distinguish interleaved log output from different sources. The granularity at which NDC works is threads, so it distinguishes log outputs from different threads separately.

In order to store thread specific tags, log4j's NDC class uses a Hashtable which is keyed by the Thread object itself (as opposed to say the thread id), and thus till the NDC tag stays in memory all the objects that hang off of the thread object also stay in memory. In our web application we use NDC to tag logoutputs with a request id to distinguish logs from a single request separately. The container that associates the NDC tag with a thread, also removes it while returning the response from a request. The problem occurred when during the course of processing a request, a child thread was spawned, something like the following code:

pubclic class RequestProcessor {
    private static final Logger logger = Logger.getLogger(RequestProcessor.class);
    public void doSomething()  {
        ....
        final List<String> hugeList = new ArrayList<String>(10000);
        new Thread() {
           public void run() {
               logger.info("Child thread spawned")
               for(String s:hugeList) {
                   ....
               }
           }
        }.start();
    }
}    

So an NDC context was associated with inline thread that was spawned. The thread object that was the key for this NDC context, is the inline thread which has the hugeList object hanging off of it. Hence even after the thread finished doing what it was doing, the reference to the hugeList was kept alive by the NDC context Hastable, thus causing a memory leak.

csdnceshi79
python小菜 +1 Do you know offhand whether there is a similar issue with the MDC in slf4j/logback (successor products by the same author)? I'm about to do a deep dive on the source but wanted to check first. Either way, thanks for posting this.
6 年多之前 回复
csdnceshi77
狐狸.fox NDCs are stored in ThreadLocal.
6 年多之前 回复
csdnceshi64
游.程 That sucks. You should check this logging library that allocates ZERO memory while logging to a file: mentalog.soliveirajr.com
大约 9 年之前 回复

What's a memory leak:

  • It's caused by a bug or bad design.
  • It's a waste of memory.
  • It gets worse over time.
  • The garbage collector cannot clean it.

Typical example:

A cache of objects is a good starting point to mess things up.

private static final Map<String, Info> myCache = new HashMap<>();

public void getInfo(String key)
{
    // uses cache
    Info info = myCache.get(key);
    if (info != null) return info;

    // if it's not in cache, then fetch it from the database
    info = Database.fetch(key);
    if (info == null) return null;

    // and store it in the cache
    myCache.put(key, info);
    return info;
}

Your cache grows and grows. And pretty soon the entire database gets sucked into memory. A better design uses an LRUMap (Only keeps recently used objects in cache).

Sure, you can make things a lot more complicated:

  • using ThreadLocal constructions.
  • adding more complex reference trees.
  • or leaks caused by 3rd party libraries.

What often happens:

If this Info object has references to other objects, which again have references to other objects. In a way you could also consider this to be some kind of memory leak, (caused by bad design).

Create a static Map and keep adding hard references to it. Those will never be GC'd.

public class Leaker {
    private static final Map<String, Object> CACHE = new HashMap<String, Object>();

    // Keep adding until failure.
    public static void addToCache(String key, Object value) { Leaker.CACHE.put(key, value); }
}
csdnceshi72
谁还没个明天 This is the classic memory leak in Java. It is not a leak in the sense of the JVM has lost track of the memory, but it is a leak in the sense that the JVM will never garbage collect it. If you monitor the heap of an application that uses this construct it will have a generally increasing trend and will eventually terminate with OutOfMemoryError. That is the definition of a memory leak.
接近 3 年之前 回复
weixin_41568127
?yb? Absolutely invalid. You are just collecting a bunch of objects in a Map collection. Their references will be kept because the Map holds them.
接近 7 年之前 回复
csdnceshi74
7*4 But that's not really what the question was asking. It has nothing to do with simply using up all your memory.
8 年多之前 回复
csdnceshi53
Lotus@ My point is that somebody who keeps creating objects, perhaps putting them into a cache, could end up with an OOM error if they aren't careful.
8 年多之前 回复
csdnceshi58
Didn"t forge I agree with @Falmarri. I don't see a leak there, you are just creating objects. You could certainly 'reclaim' the memory that you just allocated with another method called 'removeFromCache'. A leak is when you can't reclaim the memory.
8 年多之前 回复
csdnceshi74
7*4 How is that a leak? It's doing exactly what you're asking it to do. If that's a leak, creating and storing objects anywhere is a leak.
9 年多之前 回复
csdnceshi55
~Onlooker Could you please give a code example?
9 年多之前 回复

there are many different situations memory will leak. One i encountered, which expose a map that should not be exposed and used in other place.

public class ServiceFactory {

private Map<String, Service> services;

private static ServiceFactory singleton;

private ServiceFactory() {
    services = new HashMap<String, Service>();
}

public static synchronized ServiceFactory getDefault() {

    if (singleton == null) {
        singleton = new ServiceFactory();
    }
    return singleton;
}

public void addService(String name, Service serv) {
    services.put(name, serv);
}

public void removeService(String name) {
    services.remove(name);
}

public Service getService(String name, Service serv) {
    return services.get(name);
}

// the problematic api, which expose the map.
//and user can do quite a lot of thing from this api.
//for example, create service reference and forget to dispose or set it null
//in all this is a dangerous api, and should not expose 
public Map<String, Service> getAllServices() {
    return services;
}

}

// resource class is a heavy class
class Service {

}

Threads are not collected until they terminate. They serve as roots of garbage collection. They are one of the few objects that won't be reclaimed simply by forgetting about them or clearing references to them.

Consider: the basic pattern to terminate a worker thread is to set some condition variable seen by the thread. The thread can check the variable periodically and use that as a signal to terminate. If the variable is not declared volatile, then the change to the variable might not be seen by the thread, so it won't know to terminate. Or imagine if some threads want to update a shared object, but deadlock while trying to lock on it.

If you only have a handful of threads these bugs will probably be obvious because your program will stop working properly. If you have a thread pool that creates more threads as needed, then the obsolete/stuck threads might not be noticed, and will accumulate indefinitely, causing a memory leak. Threads are likely to use other data in your application, so will also prevent anything they directly reference from ever being collected.

As a toy example:

static void leakMe(final Object object) {
    new Thread() {
        public void run() {
            Object o = object;
            for (;;) {
                try {
                    sleep(Long.MAX_VALUE);
                } catch (InterruptedException e) {}
            }
        }
    }.start();
}

Call System.gc() all you like, but the object passed to leakMe will never die.

(*edited*)

csdnceshi55
~Onlooker Can't you just allocate a bunch of memory on background threads and intentionally deadlock them by using a very poorly structured system of nested thread locks? It fits the profile of running for the life of the program and not being accessible by the application or recoverable by the GC.
6 年多之前 回复
csdnceshi51
旧行李 "I could accept that as a memory leak" Thank you. Earlier, you'd said something couldn't be a leak if it's still referenced and that you couldn't have a leak in Java because it has a garbage collector. >_< "Your answer suggests that any unused allocated object implies a leak". Well, the example is a scenario of an object that the garbage collector can't/won't collect. If it emerges in a program and happens repeatedly it becomes a leak. I'll try to improve my answer with that info.
大约 7 年之前 回复
csdnceshi63
elliott.david This is totally valid code, it's what it means to use threads. They are designed to keep their references. Also it's not only threads that do this, also GUI frames keep everything referenced by them even though there is no thread. There are a few other "tops" to the GC tree as well. If you have a thread that runs forever then, by design, it will keep everything it references forever, otherwise nothing will work. If this is not what you intended however, then you DO have a programming bug!
大约 7 年之前 回复
weixin_41568183
零零乙 I mean all the people who read your answer and our discussion, and still didn't care to up or down your post. But that's not a real argument anyway. See slowlyLeakingVector in Listing 2. I could accept that as a memory leak, but that's different from what you are doing. As I see, your answer suggests that any unused allocated object implies in a leak. I don't agree with that.
大约 7 年之前 回复
csdnceshi51
旧行李 "not much people think you are right".. Uh, about which? Which people? Where? Check the previous page of answers for the many older, popular answers that I'm defending here and which you are calling wrong. "Memory leaks in Java are not real leaks" Nowhere does the article say that. It gives examples of memory leaks and shows how they are a real loss of usable memory due to objects not being reclaimed. Those objects accumulate over time and become a real problem. That's what a memory leak is. "they are bad design choices or bugs in code" ... which result in memory leaks, yes.
大约 7 年之前 回复
weixin_41568183
零零乙 obviously not much people think you are right. See this: ibm.com/developerworks/rational/library/05/0816_GuptaPalanki Memory leaks in Java are not real leaks, they are bad design choices or bugs in code.
大约 7 年之前 回复
csdnceshi51
旧行李 It's the most important difference. At a lower level (program -> JVM -> OS -> RAM chips -> Universe) any memory leak from the higher level becomes unreal. The practical definition for a memory leak is that during execution, your memory space (at whatever level you define it) is accumulating things which are not wanted, reducing available space for things which are wanted. "In a C program, a leak isn't referenced anywhere" -- also wrong -- leaked memory could still be referenced. What matters is whether the memory can be re-used, which in C does not depend on whether it's referenced.
大约 7 年之前 回复
weixin_41568183
零零乙 There is no difference between "live references and obsolete ones" in the context of the question. They are still referenced somewhere. In a C program, a leak isn't referenced anywhere, even the OS can't touch it. It can release all memory pages used by a given process, but it can't reference each and every memory block allocated.
大约 7 年之前 回复
csdnceshi51
旧行李 Then try it for yourself and you'll see that it does leak. The garbage collector isn't (and cannot be) infallible because it can't tell the difference between live references and obsolete ones, which is why explicit nulling of obsolete references is necessary when the object or scope holding the obsolete reference is still in use.
大约 7 年之前 回复
weixin_41568183
零零乙 Since Java has a garbage collector, I don't think it can even leak.
大约 7 年之前 回复
csdnceshi51
旧行李 What is your answer? What do you consider a leak?
大约 7 年之前 回复
csdnceshi51
旧行李 The practical definition of a leak is that it's memory which has been lost track of such that we don't know and thus can't perform the procedure necessary to reclaim only it; we would have to tear down and rebuild the entire memory space. A rogue thread like this could arise naturally through a deadlock or dodgy threadpool implementation. Objects referenced by such threads, even indirectly, are now prevented from ever being collected, so we have memory which will not be naturally reclaimed or reusable during the lifetime of the program. I'd call that a problem; specifically it's a memory leak.
大约 7 年之前 回复
csdnceshi51
旧行李 If you would count memory that the process knows about as not being leaked, then all the answers here are wrong, since the process always tracks which pages in its virtual address space are mapped. When the process terminates, the OS cleans up all the leaks by putting the pages back on the free page stack. To take that to the next extreme, one could beat to death any argued leak by pointing out that none of the physical bits in the RAM chips or in the swap space on disk have been physically misplaced or destroyed, so you can switch the computer off and on again to clean up any leak.
大约 7 年之前 回复
weixin_41568183
零零乙 Yes I do. The process still references the thread, and the thread still references the o object. You may have misunderstood what a memory leak is.
大约 7 年之前 回复
csdnceshi51
旧行李 "You'll have a [thing] for the lifetime of your program. That doesn't count as a leak to me." Do you hear yourself?
大约 7 年之前 回复
weixin_41568183
零零乙 You'll have a thread "running" (or sleeping, whatever) for the lifetime of your program. That doesn't count as a leak to me. As well as a pool doesn't count as a leak, even if you don't use it entirely.
大约 7 年之前 回复
csdnceshi51
旧行李 Nothing is "stuck". The calling method returns promptly, and the passed object will never be reclaimed. That's precisely a leak.
大约 7 年之前 回复
weixin_41568183
零零乙 It's not leaked, the code is stuck but it's still in scope.
大约 7 年之前 回复

I can copy my answer from here: Easiest way to cause memory leak in Java?

"A memory leak, in computer science (or leakage, in this context), occurs when a computer program consumes memory but is unable to release it back to the operating system." (Wikipedia)

The easy answer is: You can't. Java does automatic memory management and will free resources that are not needed for you. You can't stop this from happening. It will ALWAYS be able to release the resources. In programs with manual memory management, this is different. You cann get some memory in C using malloc(). To free the memory, you need the pointer that malloc returned and call free() on it. But if you don't have the pointer anymore (overwritten, or lifetime exceeded), then you are unfortunately incapable of freeing this memory and thus you have a memory leak.

All the other answers so far are in my definition not really memory leaks. They all aim at filling the memory with pointless stuff real fast. But at any time you could still dereference the objects you created and thus freeing the memory --> NO LEAK. acconrad's answer comes pretty close though as I have to admit since his solution is effectively to just "crash" the garbage collector by forcing it in an endless loop).

The long answer is: You can get a memory leak by writing a library for Java using the JNI, which can have manual memory management and thus have memory leaks. If you call this library, your java process will leak memory. Or, you can have bugs in the JVM, so that the JVM looses memory. There are probably bugs in the JVM, there may even be some known ones since garbage collection is not that trivial, but then it's still a bug. By design this is not possible. You may be asking for some java code that is effected by such a bug. Sorry I don't know one and it might well not be a bug anymore in the next Java version anyway.

csdnceshi76
斗士狗 What is object resurrection? How many times does a destructor get called? How do these questions disprove this answer?
接近 4 年之前 回复
csdnceshi65
larry*wei No it's not. I turned the reference above to link now, so you can easily find it.
接近 5 年之前 回复
csdnceshi69
YaoRaoLov The mentioned acconrad's answer was deleted?
接近 5 年之前 回复
csdnceshi55
~Onlooker That's an extremely limited (and not very useful) definition of memory leaks. The only definition that makes sense for practical purposes is "a memory leak is any condition in which the program continues to hold memory allocated after the data it holds it is no longer needed."
接近 7 年之前 回复

You are able to make memory leak with sun.misc.Unsafe class. In fact this service class is used in different standard classes (for example in java.nio classes). You can't create instance of this class directly, but you may use reflection to do that.

Code doesn't compile in Eclipse IDE - compile it using command javac (during compilation you'll get warnings)

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import sun.misc.Unsafe;


public class TestUnsafe {

    public static void main(String[] args) throws Exception{
        Class unsafeClass = Class.forName("sun.misc.Unsafe");
        Field f = unsafeClass.getDeclaredField("theUnsafe");
        f.setAccessible(true);
        Unsafe unsafe = (Unsafe) f.get(null);
        System.out.print("4..3..2..1...");
        try
        {
            for(;;)
                unsafe.allocateMemory(1024*1024);
        } catch(Error e) {
            System.out.println("Boom :)");
            e.printStackTrace();
        }
    }

}
csdnceshi60
℡Wang Yan Strongly advise readers to consider that IDE specific behaviors in developing code is not only irrelevant but dangerous. Namely, system stability and consistency demands a singular, consistent compiler. An IDE generally uses "javac" of some version from some vendor/impl. Consistency in runtime behavior within a given JVM relies on having the same byte-code interpretation. Since servers do not run IDEs or their (as likely instrumented) run-time environments, it is dangerous to make any presumptions or cases around what a given IDE does or doesn't do. Reference the javac instance and JVM only.
2 年多之前 回复
csdnceshi79
python小菜 This will build in eclipse (at least in recent versions) but you'll need to change the compiler settings: in Window > Preferences > Java > Compiler > Errors/Warning > Deprecated and restricted API set Forbidden reference (access rules) to "Warning".
4 年多之前 回复
csdnceshi79
python小菜 The memory certainly does "belong to Java", at least in the sense that i) its not available to anyone else, ii) when the Java application exits it will be returned to the system. It is just outside the JVM.
4 年多之前 回复
csdnceshi62
csdnceshi62 Brow In fact I've didn't work with jvm of IBM. But as I told - some standart packages (java.nio, java.util.concurrent etc.) use this service class. So if IBMs jvm supports usage of these libraries, probably it has native code to cope with sun.misc.Unsafe
9 年多之前 回复
weixin_41568183
零零乙 Is this sun/oracle jvm specific? E.g. will this work on IBM?
9 年多之前 回复
csdnceshi75
衫裤跑路 The allocated memory doesn't belong to Java either.
9 年多之前 回复
csdnceshi62
csdnceshi62 Allocated memory is invisible for garbage collector
9 年多之前 回复
共30条数据 首页 2 尾页
Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!
立即提问
相关内容推荐