Memory leak warning in Tomcat

1,500 views
Skip to first unread message

Tomáš Bleša

unread,
Sep 27, 2014, 4:00:33 AM9/27/14
to rxj...@googlegroups.com
If I call subscibeOn(...) in my webapp under Tomcat 8 and then reload my app (using Manager app or automatic reload triggered by code changes) I get this warning:

SEVERE: The web application [/rxtest] appears to have started a thread named [RxComputationThreadPool-4] but has failed to stop it. This is very likely to create a memory leak.

Zář 27, 2014 9:39:22 DOP. org.apache.catalina.loader.WebappClassLoader clearReferencesThreads

SEVERE: Stack trace of thread "RxComputationThreadPool-4":

 sun.misc.Unsafe.park(Native Method)

 java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)

 java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)

 java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:1081)

 java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:809)

 java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1067)

 java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1127)

 java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)

 java.lang.Thread.run(Thread.java:745)


The code that causes this behavior is this:

public static String stuffResult()

{

StringBuilder b = new StringBuilder();

for (String d : doStuff().toBlocking().toIterable()) b.append('-').append(d);

return b.toString();

}


public static Observable<String> doStuff() {

Observable<String> a = Observable.range(0, 20).map(num -> "A"+num).subscribeOn(Schedulers.computation());

Observable<String> b = Observable.range(0, 20).map(num -> "B"+num).subscribeOn(Schedulers.computation());

Observable<String> c = Observable.range(0, 20).map(num -> "C"+num).subscribeOn(Schedulers.computation());

Observable<String> d = Observable.range(0, 20).map(num -> "D"+num).subscribeOn(Schedulers.computation());

Observable<String> e = Observable.range(0, 20).map(num -> "E"+num).subscribeOn(Schedulers.computation());

Observable<String> f = Observable.range(0, 20).map(num -> "F"+num).subscribeOn(Schedulers.computation());


return Observable.merge(a, b, c, d, e, f);

}


I call stuffResult() method from index.jsp:

<body>

<h1>Doing stuff</h1>

<p><%=RxTest.stuffResult()%></p>

</body>


... and if I reload my app in Tomcat just after the call I get the warning (8x for every used thread).
Is there any problem with my code (or understanding of Rx concepts) or is it a bug in RxJava (I use 1.0.0-rc.3)?

Thank you.
Tomas

Tomáš Bleša

unread,
Oct 2, 2014, 1:54:55 PM10/2/14
to rxj...@googlegroups.com
I appears to me that
.subscribeOn(Schedulers.computation())
creates executor for every CPU core and these executors are never shutdown. Every time I reload my little test-app, RxJava creates next batch of threads (8 on my 8-core MacBook Pro). I found that NewThreadWorker.unsubscribe() is never called (checked by setting breakpoint there). This method contains .shutdownNow() call to inner executor, but it is never invoked.
This is not a problem if the whole JVM ends, but in case of application server like Tomcat it leads to memory leaks.

I must confess I'm pretty new to Rx world, so please tell me if I missing something.
Tomas

Shixiong Zhu

unread,
Oct 3, 2014, 12:24:45 PM10/3/14
to Tomáš Bleša, rxj...@googlegroups.com
Now RxJava does not provide a method, such as "shutdownNow", to clean up the theads in Schedulers.computation() and Schedulers.io().

Do you use Tomcat reload mechanism in production? If not, it should not be a big problem.

Best Regards,

Shixiong Zhu

Tomáš Bleša

unread,
Oct 6, 2014, 3:02:14 AM10/6/14
to rxj...@googlegroups.com, tbl...@gmail.com
Thank you for reply. 

Do you use Tomcat reload mechanism in production? If not, it should not be a big problem.

We host our app on our servers (SaaS), but we also distribute .war for those customers who want to run the application on their own hardware. It may be a problem in the latter case because their admins will call our tech support if they found memory leak warning in their app-server logs.
I understand that's how it is with RxJava and I can live with it (e.g. plug in my own scheduler implementations, not using provided schedulers at all, ...), but...
  1. I think it is good practice for any library that takes up resources to provide a method for releasing them.
  2. Is it good idea to introduce something like Schedulers.shutdown()?
Tomas

Shixiong Zhu

unread,
Oct 6, 2014, 4:32:06 AM10/6/14
to Tomáš Bleša, rxj...@googlegroups.com
You can open a bug report on GitHub: https://github.com/ReactiveX/RxJava
It's a better place to discuss new feature. Thank you.

Best Regards,

Shixiong Zhu
Reply all
Reply to author
Forward
0 new messages