That works and no more thread hanging around. I'll see if I can do an evolver version.
On Oct 8, 2010 8:43 PM, "Jonathan Kaplan" <jonat...@gmail.com> wrote:
Ugly. Have I mentioned how I feel about that particular code?I think the best solution would be to replace the threads with Executors, which are designed to handle exactly this type of job submission, and also deal with shutdown and other synchronization conditions properly. I've attached a patch to convert to an executor, but I haven't tried it at all. If you don't mind trying it out and letting me know what I did wrong, that would be great!Next up: asynchronous synchronize...
On Fri, Oct 8, 2010 at 3:59 PM, Morris Ford <morri...@gmail.com> wrote:
>
> That code is gettin...
Ok. I'll start chipping away at it.
On Oct 14, 2010 6:26 PM, "Jonathan Kaplan" <jonat...@gmail.com> wrote:
Morris,
Thanks for the patches. We are moving in the right direction, but it looks like there is still a ways to go. I was able to find a few more issues with the following method:1. stop the server2. remove a bunch of optional modules (like multimesh evolver avatar and others that threw exceptions during logout)3. restore the empty world4. log in5. select File -> Log Out in the Wonderland client6. connect with the profiler using the minimum settings (monitor only)7.take a heap dumpI believe this strategy eliminates many of the profiler-related issues you ran into. Once I had the "clean" heap dump, I selected the ScannedClassLoader and looked through its references, ignoring anything that met any of the following conditions:1. field is "$classloader$"2. type is "DelegatingClassLoader"3. type is "Package"4. type is "WeakHashMap$Entry"5. type is "ResourceBundle$LoaderReference"6. type is "ProtectionDomain"I found the following items that don't fit in those categories:1. Type is "JmeCellCache": there are at least two paths to the cell cache that need to be cleaned up. One is ProcessorManager holding a reference to AvatarControls, and the other is the static ClientContext.cellCaches variable.2. Type is "JmeClientSession": sadly, there are a ton of paths to this one. For example MainFrame holds a reference to the TextChatPanel, which holds a reference to the session. There is also a path through the App2D invoker thread, which is never shut down properly. To track down the references to this class, I right clicked and selected "show instance" since there was so much to explore.Using the same logged out client instance, I also generated more heap dumps, and used "find nearest GC root" to locate a few other stragglers (it turns out the "ProtectionDomain" type isn't entirely safe):1. the App2D invoker thread is never shut down2. in the webdav module, the MultiThreadedHttpConnectionManager is not shut down, leaving several threads running
It would be nice to eliminate the JmeCellCache and extra threads before going after the JmeClientSession, which seems like the biggest hairball at this point.
On Wed, Oct 13, 2010 at 3:37 PM, Morris Ford <morri...@gmail.com> wrote:
>
> I generated patche...
With a bit of poking around I found some indications of where the executor is that is causing the GCRoot that I can't find. Looks like it might be avatar related?? I attached two screen shots. See anything there useful?
ExecutorThreadFactory() {
SecurityManager s = System.getSecurityManager();
group = (s != null)? s.getThreadGroup() :
Thread.currentThread().getThreadGroup();
ccl = Thread.currentThread().getContextClassLoader();
acc = AccessController.getContext();
}
private Thread createThread(Runnable r) {
Thread t = new Thread(group, r,
namePrefix + threadNumber.getAndIncrement(),
0);
if (t.isDaemon())
t.setDaemon(false);
if (t.getPriority() != Thread.NORM_PRIORITY)
t.setPriority(Thread.NORM_PRIORITY);
return t;