I'm experiencing a quite aggressive memory leak using Tomee, Apache Open Web Beans and JSF.
The following code in org.apache.openejb.core.WebContext is continually adding elements every time we navigate to a page but never removes them:
if (webBeansContext != null) {
final InjectionTargetBean<Object> bean = InjectionTargetBean.class.cast(beanDefinition);
bean.getInjectionTarget().inject(beanInstance, creationalContext);
creatonalContexts.put(beanInstance, creationalContext);
}
Resulting in a massive map of JSF Objects and their relating CreationalContext which is never garbage collected:
Ultimately this is causing the server to run out of memory and fall over. Has anybody encountered this?
Related
So I am using embedded jetty server for my project application. Whenever a request comes in to specific method it has all the attributes populated in org.eclipse.jetty.server.Request object including SessionHandler, but since my code is taking significant amount of time to excecute , after some time Session and SessionHandler attribute becomes null in Request object. Due to this , obviously I am getting exception whenever I try o access session as below :
Exception in thread "Thread-19" java.lang.IllegalStateException: No SessionManager
at org.eclipse.jetty.server.Request.getSession(Request.java:1548)
Initially I thought , since my code is taking longer to complete execution , it might be that I am losing session due to timeout, so I increased the session-timeout value. But it didn't help.
Has anyone come across similar issue , please suggest me solution. Any help is appreciated.
I had a similar issue. You are probably missing a Jetty session manager in your handler list.
Instead of:
server.setHandler( context );
do this:
HandlerCollection contexts = new HandlerCollection( new org.eclipse.jetty.server.session.SessionHandler(), context );
server.setHandler( contexts );
I have a Spring Service, which calls an API. This Service creates several objects and returns these to the client (of a REST request).
Is this good practice? I observe rising memory consumption with every request. Is there is no garbage collection happening?
#org.springframework.stereotype.Service("FanService")
public class Service {
private static final Logger log = LoggerFactory.getLogger(Service.class);
public List<String> allCLubsInLeague() {
try {
URI urlString = new URI("https://www.thesportsdb.com/api/v1/json/1/search_all_teams.php?l=German%20Bundesliga");
RestTemplate restTemplate = new RestTemplate();
TeamsList response = restTemplate.getForObject(urlString, TeamsList.class);
List<BundesligaTeams> bundesligaTeams = response.getTeams();
//ResponseEntity<List<BundesligaTeams>> test = t.getForEntity(urlString, BundesligaTeams.class);
List<String> teamList = new ArrayList<>();
bundesligaTeams.forEach(value -> teamList.add(value.getStrTeam()));
log.info(bundesligaTeams.get(0).getStrAlternate());
bundesligaTeams = null;
response = null;
urlString = null;
restTemplate = null;
return teamList;
} catch (Exception e) {
log.info(e.getMessage());
}
return null;
}
}
I don't see any memory leak in this code.
Your memory is raising in every request because Garbage Collector will garbage unused objects when it decides to do so. So your objects can be garbaged after 10 or 20 request - you never know.
This happens because you still have a lot of free memory on your heap so garbage collector is not forced to clean it up yet. If you will try to invoke many many requests you will see Garbage Collector activity soon.
If you want to see more details, you can always run jvisualvm which should be shipped with JDK and observe how your heap memory increase/decrease according to garbage collector activity
If you are not coding low-latency application with zero-garbage allocation you should focus on writing readable and maintainable code first. Only then tune performance if it's not acceptable.
It's ok to create objects if you have available memory, memory allocation is cheap comparing to a GET request. See Latency Numbers Every Programmer Should Know.
There is no reason to null a local variable unless you are trying to remove security credentials. Don't write bundesligaTeams = null; and other statements at the end, these object will be collected once they are not reachable.
RestTemplate should be a separate bean. Creating this object could be expensive if the underling HTTP client creation is expensive. Consider auto-wiring the default RestTemplate provided by Spring Boot.
Cache the result of the GET request locally if the data is not changing often. A list of all the clubs in the German Bundesliga will change only once a year.
You should avoid creating String for log.info() call if the info logging level is not enabled. Either use placeholder syntax or call log.isInfoEnabled() before. Check out the What is the fastest way of (not) logging? FAQ.
I am having some problems when I try to implement a new function in my working servlet.
Now I have a servlet in which mobile phones can register. Mobile phones use rest to register against this servlet. And it works perfect. Anytime you try to register a phone, it works.
But now, I need to add a new functionality. I want to register this server against other component of my infrastructure.
I want that registration done at the very beggining. I mean, when the servlet starts, make the registration and forget about it, just work as it did before.
This is the error tomcat gives me:
Grave: The web application [/servletRegister] appears to have started a thread named [Timer-8] but has failed to stop it. This is very likely to create a memory leak.
This is my start class:
#Override
public Set<Class<?>> getClasses() {
//-------------------------------
//Set registration here
//GatewayRegistrationHandler reg = GatewayRegistrationHandler.getInstance();
//reg.registerDevice();
//-------------------------------
//register on a new thread due to process time
new Thread (new RegisterGatewayOnBackground()).start();
//Next are the working servlet code
Set<Class<?>> classes = new HashSet<Class<?>>();
classes.add(PublicationsResource.class); /
classes.add(DeviceResource.class);
return classes;
}
}
I tried the commented lines firstly. Then I got a memory leak and I tried to execute them in a new thread trying to avoid the leak. But the behavior is the same.
The background function is this:
public class RegisterGatewayOnBackground implements Runnable {
public RegisterGatewayOnBackground() {
}
public void run() {
registerDevice();
}
private void registerDevice() {
GatewayRegistrationHandler reg = GatewayRegistrationHandler.getInstance();
reg.registerDevice();
}
}
GatewayRegistrationHandler works fine because when I run the servlet, it executes, makes the registration and then, after that, crash. I thought it was a time problem and background would solve it but I am stuck here since background does the same.
I don't know any way to check where to find my memory leak. I am looking for advice or any tools which might help me solve the problem.
When you start your thread like that, it will not be named "Timer-x". Therefore, this was probably a thread started elsewhere.
The message tomcat is giving you indicates that the webapp is somehow being undeployed (and then it checks for threads which are still there, and complains if there is). I'm not sure why the undeploy is happening, but if it's because you are stopping the webapp., you may not need to fix this unless you do (lots of) hot-deploys (deploying and undeploying while keeping the tomcat running). This is because, if it's leaking memory right before you are going to kill the process anyways, the memory leak won't have any harm and it would be waste of time to fix it.
If you want to fix it, one easy way is to hook a profiler and see who started this "Timer" thread.
I'm not quite sure whether this is more of an Openbravo issue or more of a Quartz issue, but we have some manual processes that run on schedules via Openbravo ProcessRequest objects (OB v2.50MP24), but it seems that the processes are running twice, at the exact same time. Openbravo extends the Quartz platform for their scheduling. I've tried to resolve this issue on my own by ensuring that my process classes extend this class:
import java.util.List;
import org.openbravo.dal.service.OBDal;
import org.openbravo.model.ad.ui.ProcessRequest;
import org.openbravo.scheduling.ProcessBundle;
import org.openbravo.service.db.DalBaseProcess;
public abstract class RBDDalProcess extends DalBaseProcess {
#Override
protected void doExecute(ProcessBundle bundle) throws Exception {
org.quartz.Scheduler sched = org.openbravo.scheduling.OBScheduler
.getInstance().getScheduler();
int runCount = 0;
synchronized (sched) {
List<org.quartz.JobExecutionContext> currentlyExecutingJobs = (List<org.quartz.JobExecutionContext>) sched
.getCurrentlyExecutingJobs();
for (org.quartz.JobExecutionContext jec : currentlyExecutingJobs) {
ProcessRequest processRequest = OBDal.getInstance().get(
ProcessRequest.class, jec.getJobDetail().getName());
if (processRequest == null)
continue;
String processClass = processRequest.getProcess()
.getJavaClassName();
if (bundle.getProcessClass().getCanonicalName()
.equals(processClass)) {
runCount++;
}
}
}
if (runCount > 1) {
System.out.println("Process "
+ bundle.getProcessClass().getSimpleName()
+ " is already running. Cancelling.");
return;
}
doRun(bundle);
}
protected abstract void doRun(ProcessBundle bundle);
}
This worked fine when I tested by requesting the process to run immediately twice at the same time. One of them cancelled. However, it's not working on the scheduled processes. I have S.o.p's set up to log when the processes start, and looking at the logs shows each line of the output twice, each line one right after the other.
I have a sneaking suspicion that it's because the processes are either running in two completely different threads that don't know about each others' processes, however, I'm not sure how to verify my suspicions or, if I am correct, what to do about it. I've already verified that there is only one instance of each of the ProcessRequest objects stored in the database.
Has anyone else experienced this, know why they might be running twice, or know what I can do to prevent them from simultaneously running?
The most common reasons for a double Job execution are the following:
EDITED:
Your application is deployed in a clustered environment and you have not configured Quartz to run in a cluster environment.
Your application is deployed more than once. There are many cases where the application is deployed twice especially in Tomcat server. As a consequence the QuartzInitializerListener is invoked twice and the Jobs are executed twice. In case you use Tomcat server and you are defining contexts explicitly in server.xml, you should turn off automatic application deployment or specify deployIgnore. Both the autoDeploy set to true and the context element existence in server.xml, have as a consequence the twice deployment of the application. Set autoDeploy to false or remove the context element from the server.xml.
Your application has been redeployed without unscheduling the current processes.
I hope this helps you.
Quartz uses a thread pool for the jobs execution. So as you suspect, the RBDDalProcess will probably have separate instances a in separate thread and the counter check will fail.
One thing you can do is list the jobs registered in the Scheduler (you can get the Scheduler using the OB API as: OBScheduler.getScheduler()):
// enumerate each job group
for(String group: sched.getJobGroupNames()) {
// enumerate each job in group
for(JobKey jobKey : sched.getJobKeys(groupEquals(group))) {
System.out.println("Found job identified by: " + jobKey);
}
}
If you see the same job added twice, check out org.quartz.spi.JobFactory and the org.quartz.Scheduler.setJobFactory method for controlling jobs instantiations.
Also make sure you have only one entry for this process in the 'Report and Process' table in Openbravo.
I have used DalBaseProcess in Openbravo 3.0 and I cannot confirm this behavior you're describing. Having this in mind it would be probably a good idea to checkout the reported bugs for Openbravov2.50MP24 and Quartz or post a thread in Openbravo Forge forums with your problem.
I am trying to implement a nagios plugin, and doing so requires that I know specifically what object and attribute I want to monitor. The thing is, I haven't been able to find a listing anywhere of the standard system jmx objects and attributes. Can anyone point me in the right direction? I need to monitor things like memory pools, heap size, etc.
You can use
Set mbeans = mBeanServer.queryNames(null, null);
for (Object mbean : mbeans)
{
WriteAttributes(mBeanServer, (ObjectName)mbean);
}
private void WriteAttributes(final MBeanServer mBeanServer, final ObjectName http)
throws InstanceNotFoundException, IntrospectionException, ReflectionException
{
MBeanInfo info = mBeanServer.getMBeanInfo(http);
MBeanAttributeInfo[] attrInfo = info.getAttributes();
System.out.println("Attributes for object: " + http +":\n");
for (MBeanAttributeInfo attr : attrInfo)
{
System.out.println(" " + attr.getName() + "\n");
}
}
This will write all the object names and their attributes...
You can always use mBeanServer.queryNames(null, null); for getting to all MBeans registered at a certain MBeanServer (where mBeanServer is the MBeanServerConnection which you obtained either locally or remotely).
However, before implementing your own Nagios Plugins, why not using an already exisiting one ? E.g. jmx4perl's check_jmx4perl which comes with tools for exploring the JMX namespace (like jmx4perl <url> list for listing all JMX MBeans with their attributes and operations or j4psh a readline based JMX shell with context sensitive command line completion).
From a sysadmin point of view, I fully understand the bases for the question. The standard JMX documentation, or the objects one can encounter while trying to browse JMX object trees, can be overwhelming and confusing.
I have found this Op5 KB article quite useful in providing a decent overview of JMX objects of interest for JBoss.
Obviously, one needs to adjust to fit with the monitoring system they are actually using, but there is enough in the examples for whatever nagios-based monitoring system is being used.
Are you looking for the JVM platform MBean docs?
There are examples there on to get the MBeans and interrogate them e.g.
The ThreadMXBean platform MBean
provides support for monitoring thread
contention and thread CPU time.
Check out MC4J or JConsole - it's trivial to get going with both of 'em.