This would be my first question, so please if I have not completed the question or left something out do let me know.
Background:
Well I have a Java based web-service and it is serving an iPhone app. It has connection to database and in order to improve the performance I have implemented caching using Memcached. The connector I use is spymemcached.
My question:
I have a static class which has a synchronous connection to the memcached server.
my reference is: http://sacharya.com/using-memcached-with-java/
But when I restart the memcached server or deploy another jar on tomcat I get this error:
The web application appears to have started a thread name [some name] but has failed to stop it. This is very likely to create a memory leak.
So, how do I deallocate the static class before I can restart or redeploy my application on tomcat?
--
Thanks.
The static class is not the problem. That will be unloaded assuming that it is in a JAR in WEB-INF/lib. The problem is the thread. Whatever starts that thread needs to stop it. See this presentation for further details on Tomcat's memory leak prevention and detection:
http://people.apache.org/~markt/presentations/2010-11-04-Memory-Leaks-60mins.pdf
That page implements a Singleton Pattern for MyCache class.
A singleton can't be destroyed.
Maybe you can define a ServletContextListener (or similar Listener in the app server) to stop the thread manually.
Related
I am writing a Springboot application embedding Tomcat as a Web Server.
At startup, some of my threads are ready (and so start doing their job) before Tomcat is. For many contraints I have, I want that these threads do nothing before Tomcat is ready
But I don't know how to decided to block/unblock my threads; to do so, I need to be informed of the Tomcat status. Is there:
a way to ask: isWebServerStarted()?
or a way to be notified asynchronously by a message saying: WEB_SERVER_IS_STARTED?
Thank you for help
FYI, I don't want to declare a kind of "private ReST endpoint" that my
application could try to reach in order to guess whether the webserver
is ready
Go with a ServletContextListener. Annotate your class with #WebListener and tell spring configuration about this listener by adding #ServletComponentScan annotation.
I have WebApplication which is deployed in Tomcat 7.0.70. I simulated the following situation:
I created the heap dump.
Then I sent the Http request and in service's method I printed the current thread and its classLoader. And then I invoked Thread.currentThread.sleep(10000).
And at the same moment I clicked 'undeploy this application' in Tomcat's admin page.
I created new heap dump.
After some minutes I created new hep dump.
RESULTS
Thread dump
On the following screen you can see that after I clicked "redeploy", all threads (which were associated with this web application) were killed except the thread "http-apr-8081-exec-10". As I set Tomcat's attribute "renewThreadsWhenStoppingContext == true", so you can see that after some time this thread ("http-apr-8081-exec-10") was killed and new thread (http-apr-8081-exec-11) was created instead of it. So I didn't expect to have the old WCL after creation of heap dump 3, because there are not any old threads or objects.
Heapd dump 1
On the following two screens you can see that when the application was running there was only one WCL(its parameter "started" = true).
And the thread "http-apr-8081-exec-10" had the contextClassLoader = URLClassLoader ( because it was in the Tomcat's pool).
I'm speaking only about this thread because you will able to see that this thread will handle my future HTTP request.
Sending HTTP request
Now I send the HTTP request and in my code I get information about the current thread.You can see that my request is being handled by the thread "http-apr-8081-exec-10"
дек 23, 2016 9:28:16 AM c.c.c.f.s.r.ReportGenerationServiceImpl INFO: request has been handled in
thread = http-apr-8081-exec-10, its contextClassLoader = WebappClassLoader
context: /hdi
delegate: false
repositories:
/WEB-INF/classes/
----------> Parent Classloader: java.net.URLClassLoader#4162ca06
Then I click "Redeploy my web application" and I get the following message in console.
дек 23, 2016 9:28:27 AM org.apache.catalina.loader.WebappClassLoaderBase clearReferencesThreads
SEVERE: The web application [/hdi] appears to have started a thread named [http-apr-8081-exec-10] but has failed to stop it. This is very likely to create a memory leak.
Heapd dump 2
On the following screens you can see that there are two instances WebAppClassLoader. One of them( number #1) is old( its attribute "started" = false).
And the WCL #2 was created after redeploying application (its attribute "started" = true).
And the thread we review has contextClassLoader = "org.apache.catalina.loader.WebappClassLoader".
Why? I expected to see contextClassLoader = "java.net.URLClassLoader" (after all, when any thread finishes its work it is returned to the Tomcat's pool
and its attribute "contextClassLoader" is set to any base classloader).
Heapd dump 3
You can see that there isn't thread "http-apr-8081-exec-10", but there is thread "http-apr-8081-exec-11" and it has contextClassLoader = "WebappClassLoader"
(Why not URLClassLoader?).
In the end we have the following: there is thread "http-apr-8081-exec-11" which has the ref to the WebappClassLoader #1.
And obviosly when I make "Nearest GC Root" on the WCL #1 I will see the ref to the thread 11.
Questions.
How can I forcibly say to Tomcat to return old value contextClassLoader (URLClassLoader) after thread will finish its work?
How can I make sure Tomcat doesn't copy old value "contextClassLoader" during the thread renewal?
Maybe, do you know other way to resolve my problem?
Tomcat is usually not a good option on production environments. I was using Tomcat on a few production applications and I found that even if the heap size and other configurations are properly setup - and every time you reload your application, the memory consumption goes up and up. Until you don't restart the tomcat service, memory is not fully reclaimed. We did testing all such experiments like, clearing logs, redeploying all apps, regularly restarting tomcat once a month or a week during least busy hours. But at the end I have to say that we have shifted our production environments to Glassfish and WebSphere.
I hope you would already have gone through these pages:
Memory leak in a Java web application
Tomcat Fix Memory Leak?
https://developers.redhat.com/blog/2014/08/14/find-fix-memory-leaks-java-application/
http://www.tomcatexpert.com/blog/2010/04/06/tomcats-new-memory-leak-prevention-and-detection
If your web applications are not tightly coupled with Tomcat then you can think of using another web container. Now we use the Glassfish even on development machines and production and the day we make this decision, we saved a lot of our time. Though Glassfish and other such server take more time while they start as they are not as lightweight as the Tomcat is but after life is bit more easy.
From my experience with this problem, what was preventing tomcat to properly GC older class loaders was some ThreadLocals a couple of frameworks I was using were creating (and not properly handling).
Something similar to what is explained here: ThreadLocal & Memory Leak
I tried to properly finalize this ThreadLocals and my leak reduced A LOT. It was still leaking, but I could handle 10 times more redeploys than before.
I would definitely check your memory dumps to objects that could be connected somehow to ThreadLocals (they are very common, specially if you use something to control transactions or anything that is thread-isolated).
I hope it helps!
Memory leak in tomcat's redeploing is very old problem.
The only real way to solve it is restart tomcat instead of redeploy application. If you have several apps you need to run several tomcat's services on different ports and join it with nginx.
We have hundreds of Tomcat instances running in several environments (also production) and the only reasonable solution we've found to this issue is to stop and restart every Tomcat at a set time daily (in the nighttime).
We've tried many tricks, but this is the lasting solution for our uptime requirements.
Tomcat is usually not a good option on production environments. I was using Tomcat on a few production applications and I found that even if the heap size and other configurations are properly setup - and every time you reload your application, the memory consumption goes up and up. Until you don't restart the tomcat service, memory is not fully reclaimed. We did testing all such experiments like, clearing logs, redeploying all apps, regularly restarting tomcat once a month or a week during least busy hours. But at the end I have to say that we have shifted our production environments to Glassfish and WebSphere.
Check for ThreadLocal uses that prevent your ClassLoader to be garbage collected. Either remove references to your classes in ThreadLocal values or use https://github.com/codesinthedark/ImprovedThreadLocal instead of ThreadLocal
I need to built a thread/process that is always running, and can be queried through other servelts and JSP pages...
This thread/process will be dealing with large files, so it will cache file blocks to reduce file accesses (plus some other processing)...
So, that thread/process will be loaded and waiting for any queries coming, to answer... as long as the server is running.
I though about making a static class common between all the servelt classes, but I found out that will not work (tomcat deals with each new servelt as a totally new program)
So what are the other options I can try??
I think you have two options:
Use the ServletContext to access application-wide scope objects.
Use a more sophisticated solution, such as ehcache to put your data in memory.
Other options in addition to the ones proposed by Morritz
Inside Tomcat: register a global object accessible by all servlets using the Global JNDI
Within the same JVM: start you shared resources (your static class, repository, etc...) and Tomcat programmatically (embedded) using a launcher like The Java Service Wrapper. You will need to define a small API implemented by your shared resource and usable by your servlets.
Distributed accross JVM: memcached, hazelcast, etc...
I have a system written in java where I have multiple distinct objects each with different resources in use. Some have connections to activeMQ queues, some have network connections and others have open files. Some also contain running threads.
When a fatal error occurs anywhere in this system, I need to shut it down and correctly close all resources and stop all running threads.
My problem arises when the object that caused the error needs to start the shutdown process. This object does not know about the other objects that have open files and so on. So it can basically release all its resources and that is it.
I am looking for a clean way to achieve this without getting messy and passing multiple object references around the system.
Any insight is appreciated. Thank you.
Create a central Lifecycle object which all of these other objects in your application have a reference to, and which in turn has a reference to all of these other objects. In addition, each of these objects should implement a common interface such as
public interface ShutdownListener {
void onShutdown();
}
When one of the objects needs to start an orderly shutdown, it can call lifecycle.shutdown() which can in turn call object.onShutdown() on all of the objects registered with it, in order to give these objects a chance to close their resources.
This is basically the Observer pattern.
If you use a dependency-injection container such as Spring, this type of thing is built-in - your beans can extend a certain interface to be notified when the container is shutting down.
You may be able to use Shutdown hook for that. In it you can notify all related objects, which, of course, need to be registered somewhere.
A java virtual machine allows the registration of Shutdown Hooks. Your database connection pool, your file IO manager, your activeMQ queues manager can all independently register their own shutdown hooks that each close all their resources cleanly.
A shutdown hook is a Thread that requires a reference to the resource manager(s) it's responsible for shutting down. The run method of this thread will be executed when the application is terminated. Your application has access to register a shutdown hook anywhere as Runtime.getRuntime() is available as a static call, so no need to wire it into the areas of the application that need it (although it is advisable that you register such shutdown hooks at the time of the creation of each resource manager).
More information here.
http://download.oracle.com/javase/6/docs/api/java/lang/Runtime.html#addShutdownHook(java.lang.Thread)
I've made a web application using Java, Struts and running over Apache Server and Tomcat. It would be very useful to be able to restart the application from the web. I don't want to restart Tomcat, only this webapp, the same way as Tomcat Manager does it.
Do you know how can I do it? If not, any way to simulate that behaviour (reload config.properties, make Hibernate init process, etc)?
Thank you a lot.
I took a quick look at the source code for the Tomcat Manager. It looks like there's a class that's part of the Tomcat source called "Container Servlet". From the javadocs:
A ContainerServlet is a servlet
that has access to Catalina internal
functionality, and is loaded from the
Catalina class loader instead of the
web application class loader.
A ContainerServlet automatically gets passed a wrapper that can be used to get the Context and Deployer -- and the Deployer has helpful methods such as start(String contextPath) and stop(String contextPath) that will do what you want.
So, what I think you would need to do is write your own servlet that inherits from ContainerServlet, and configure Tomcat to load your servlet using the Catalina class loader (look at how the Manager is configured to see how). Note that this is probably not going to be an option for you in a hosted environment.
Then your servlet could have, say, a button you press to reload the application. I recommend putting password-protection of some kind in front of that. :)
Just hit the URLs
http://<username>:<password>#<hostname>:<port>/manager/stop?path=/<context path>
to stop and
http://<username>:<password>#<hostname>:<port>/manager/start?path=/<context path>
to start. That simulates you using the manager application.
Tomcat Manager offers an http interface to start/stop an application and other tasks. There are Ant tasks that you can use to easily access these operations.