0

Recently I created a maven based web project and used tomcat as application server to debug ...

But tomcat is frequently dead (pergem error which means out of memery ) after run app from the Project context menu directly.

The worst is that It created many idle threads and they are all can not be killed by manually.

And tomcat status is also can not be detected by NetBeans, it can not be stop and restart. I must restart my system to clean them.

My system is Fedora 12 x86... Java version is SUN JDK 6 update 17. NetBeans verison is 6.7.1.

I tried to create a bug about this, but the NetBeans developer rejected it ... I am very surprise this is a big stopper to use NetBeans to develop web app.

Today I used JBoss 5.1 in the latest NetBeans 6.8rc1 and also encountered the same problem... I've tried adjusted the VM parameters and allocate more memory but no effects.

I've deployed several seam samples to JBoss 5.1 via seam ant build script , and there is no problem. But I switch to use NetBeans to do this, It failed due to Out of memory.

What is wrong????

Pascal Thivent
  • 562,542
  • 136
  • 1,062
  • 1,124
wayne
  • 21
  • 1
  • you tried adjusting the VM parameters, but was it successful? Try calling Runtime.getRuntime().maxMemory(), and see if your settings have been taken into account – Bozho Dec 07 '09 at 06:40
  • Runtime.getRuntime().maxMemory() isn't relevant here. PermGen space is used to hold code and related data that's unlikely to ever be GC'd. A web container under development conditions of repeatedly undeploying and redeploying is a special case, so you either need to allocate more PermGen (specifically!) or you need to enable GC of the classes. – Bob Kerns Oct 23 '12 at 05:22
  • Check if JRebel does support your current configuration, maybe it can solve your problem: http://www.zeroturnaround.com/jrebel/ – penguintux Dec 07 '09 at 09:59

1 Answers1

4

(I'm assuming that the idle threads you are talking about are application threads. If you are talking about Tomcat's worker threads, then they should not cause permgen problems when idle.)

I tried to create a bug about this, but the NetBeans developer rejected it ... I am very surprise ...

I'm very unsurprised. This is not really a NetBeans problem. It is not even really a Tomcat or JBoss problem.

The problem with idle / orphaned application threads is that you cannot safely kill threads in a running JVM. And without the ability to do this you cannot stop leakages of (in this case) permgen space. This is essentially a Java platform problem. It can only be solved when JVMs support the Isolate mechanisms defined by JSR 121.

But assuming that your problem is related to doing hot deployment, it is not just the idle application threads that you have to worry about. If there is any reachable instance of any class that you are redeploying, that will cause the original old class loader and all classes it loaded to remain reachable.

... this is a big stopper to use NetBeans to develop web app.

The solution is to restart your web container every now and then. This will clean out the idle threads and other cruft and release the leaked permgen space. You can ameliorate it by running with a larger heap and more permgen, but you cannot make it go away, especially if some of the orphaned threads are not idle ...

Oh yea, and don't be a big baby! This ain't a show stopper, its just a small inconvenience :-)

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
  • While I generally agree with your lack of surprise, it really has little to do with idle threads. Rather, it has to do with classes not, by default, being garbage collected. You can enable garbage collection of classes, if you really want to pay the price of the extra GC work. Generally, you won't want to do that in a production server, and personally, I'd rather just restart Tomcat from time to time (and set the max permgen space high enough that "from time to time" is not too frequent. – Bob Kerns Oct 23 '12 at 05:15
  • Threads only enter into it, if they're actually running the user's code, and thus protecting it from GC, even if you enable GC of classes. And if THAT is the case, the user has a bad application; that's not how J2EE applications are supposed to work. – Bob Kerns Oct 23 '12 at 05:16
  • In a production server, you will only need enough permgen space for the code and associated data you actually use. It does not keep growing. What you are seeing is the impact of either deploying vast amounts of demo code, or repeatedly deploying. Raising your PermGen space will help you either way. – Bob Kerns Oct 23 '12 at 05:17
  • In any event, there is certainly no need to restart your system just to restart your web server! – Bob Kerns Oct 23 '12 at 05:18
  • @BobKerns - 1) webcontainer == webserver != system. 2) Enabling class garbage collection won't fix the problem if the classes are still reachable due to a leaked threads. 3) There are other things that will cause classloaders and hence all of their classes to remain reachable. 4) The idle threads he is talking about certainly sound like application threads to me ... not request threads. – Stephen C Oct 23 '12 at 05:56
  • @BobKerns 5) All *live* threads are reachable ... whether or not they are running user's code. 6) You seem to be saying that a J2EE application should not create threads for running things asynchronously with the request thread. In fact there is nothing wrong with this, provided that you manage the threads properly. (That's the hard part though ...) – Stephen C Oct 23 '12 at 06:02
  • yes, of course, but you miss the point. Threads themselves do not contribute to PermGen space. – Bob Kerns Oct 23 '12 at 06:05
  • Threads that have direct or indirect references to classes DO contribute to PermGen **leakage**. – Stephen C Oct 23 '12 at 06:07
  • Re: your point 3). That is true, but has nothing to do with threads. But it's a good point to bring up. Hanging onto classloaders is a Bad Idea if you're going to be reloading. – Bob Kerns Oct 23 '12 at 06:07
  • *"A thread only references code WHEN IT IS RUNNING THE CODE."* - False. – Stephen C Oct 23 '12 at 06:09
  • And finally, your point 4) That's not how you're supposed to write J2EE code, which I pointed out earlier. If he has "application threads", he should rework his application to use timers or other means. If he has constructed his application so it cannot be stopped and reloaded, then it is his problem, not the JVM's. It is perfectly possible to code with threads so they DO terminate when not needed. – Bob Kerns Oct 23 '12 at 06:10
  • In short, your blaming this on an imagined failure of the JVM is misleading. – Bob Kerns Oct 23 '12 at 06:10
  • *"Hanging onto classloaders is a Bad Idea if you're going to be reloading."* - and the most common cause of permgen leaks in Tomcat is doing just that. Keep a reference to some instance of C somewhere, and you have a reference to C, to C's classloader and all of the classes loaded by that classloader. – Stephen C Oct 23 '12 at 06:11
  • False? Really, what makes you think that? Unless you can clarify with citations, or have actually implemented a VM for any language, I must invoke argument-by-authority here, I'm afraid. Why on earth would a thread reference code it is no longer running? – Bob Kerns Oct 23 '12 at 06:12
  • I hear what you are saying, and I think you are WRONG on a number of points. Let's just leave it at that. I've got better things to do right now. – Stephen C Oct 23 '12 at 06:12
  • Perhaps you misinterpret the point? When you create a thread with a runnable, that counts as running that code. If you create a thread with a runnable, and it calls other code, and then leaves that code, it is no longer referencing that other code. – Bob Kerns Oct 23 '12 at 06:13
  • *"... or have actually implemented a VM for any language"*. Actually, I have (JNode and Kissme) ... though both were team efforts. But like I've said, I've got better things to do than argue about this ... – Stephen C Oct 23 '12 at 06:15
  • Re your most common cause -- I don't have any statistics on what people actually do, but I'll certainly concur that it is at least the easiest way. I don't want my disagreement with your other arguments to carry over to that point. It's easy enough to avoid -- if it's your code that's doing it. In my experience, it tends to be third-party libraries that bite people. Nothing to do with threads, though, which is where we disagree. – Bob Kerns Oct 23 '12 at 06:18
  • *"If you create a thread with a runnable, and it calls other code, and then leaves that code, it is no longer referencing that other code."* That is incorrect. The internal code object for the class containing the `run()` method has a reference to the code objects for each class that the `run()` method calls. It is not relevant that a call is in progress or not. – Stephen C Oct 23 '12 at 06:22
  • Well, I worked on LISP VMs back in the 1970's, with Guy Steele. It's possible we're talking past each other somehow. The point I think is important here is that rather than focusing on the threads, you have to focus on the code, and its references. Thread pool threads are not the problem -- but if you have your code active, or as you point out, referenced in some static way, that's where the problem lies. Perhaps we can agree on that much, for the benefit of those who land here via Google (which is why I bother to address this). – Bob Kerns Oct 23 '12 at 06:25
  • Ah, I see, you're making a large number of assumptions about what that run() method does. If it calls an interface method on some object, and that object is then discarded, all the implementation methods are no longer referenced. – Bob Kerns Oct 23 '12 at 06:26
  • Even with static references, you MAY only be referencing a small subtree -- though from my experience with codewalking the bytecode of large systems, often that's a surprisingly large subset. Anyway, you're misinterpreting what I said, apparently. If you have that runnable there with your code, then yes, you have a reference to at least that runnable's code, so long as it remains on the stack, and that in turn has its own references, etc. I never said otherwise. You definitely DO have to consider the entire reference chain. (And yes, I've implemented GCs). – Bob Kerns Oct 23 '12 at 06:31
  • You've forgotten about the implications of Java reflection too. From the runnable instance, I can get hold of the Class object for the runnable. Form there, I can get hold of the Classes for every field type, every formal method parameter type, and every supertype and so on. And then I can instantiate them. So that means that the corresponding code objects must be reachable. – Stephen C Oct 23 '12 at 09:38
  • Finally, from any object, I can get the object's Class, and then the classes ClassLoader instance. That instance has a table of Class objects for all other classes loaded by the classloader. If I can dig out those Class objects (e.g. reflectively), I can create instances reflectively. Ergo they must all be reachable. – Stephen C Oct 23 '12 at 09:44
  • "Thread pool threads are not the problem ..." I agree with that. But I've been assuming all along that the OP wasn't talking about thread pool threads. I've been assuming all along that he's been taking about idle **application** threads. – Stephen C Oct 23 '12 at 09:48
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/18487/discussion-between-bob-kerns-and-stephen-c) – Bob Kerns Oct 23 '12 at 17:13