Search code examples
javamemory-leaksapache-cameleclipse-memory-analyzer

How to interpret Eclipse Memory Analizer (memory leaks in a camel route)


I'm running several camel routes (about 100) in JBoss Fuse. Recently I'm getting a OutOfMemoryError: Java heap space so I decided use Eclipse Memory Analyzer Tool to hunt the leaks.

The report shows several suspects, but the biggest one is this:

11.539 instances of "org.apache.http.impl.conn.PoolingHttpClientConnectionManager", loaded by "org.apache.felix.framework.BundleWiringImpl$BundleClassLoaderJava5 @ 0xd16558b8" occupy 443.624.920 (63,87%) bytes.

Unlike other leaks problems, the details report for this case is small, is just 4 lines:

class java.lang.Thread @ 0xd0a9c0c8
\class org.apache.camel.component.jms.DefaultJmsMessageListenerContainer @ 0xd367ee58 .\class org.apache.camel.component.jms.JmsQueueEndpoint @ 0xd36750d8
..\class org.apache.camel.blueprint.BlueprintCamelContext @ 0xd33bcd50

Very small report

It seems that something is wrong with the http connections, but I really don't know.

I use the http component in pollEnrichers like this:

from(URI_COLA_ENTRADA_STEP)
.pollEnrich().simple("{{URL_CORRELATIVO}}?ruta=STEP", String.class).aggregationStrategy(new EstrategiaCorrelativo()).cacheSize(1).timeout(10000).aggregateOnException(true)
.to(URI_TOPIC_ARTICULOS);

or with a ProducerTemplate inside a processor:

final String URL = exchange.getContext().resolvePropertyPlaceholders("{{URL_PAGO}}");
ProducerTemplate producer = exchange.getContext().createProducerTemplate();
String response = producer.requestBody(URL, "", String.class);
producer.stop();

So, as you can see, I'm doing nothing too complicated.

What could be causing the problem?


Solution

  • Ok... I solved the problem. It was a thing between camel parameters and http parameters.

    First: Actually, I was using the http4 component like this:

    String URL = exchange.getContext().resolvePropertyPlaceholders("{{URL_PAGO}}");
    
    String PARAMS = "?param1=" + value1 + "&param2=" + value2;
    
    ProducerTemplate producer = exchange.getContext().createProducerTemplate();
    String response = producer.requestBody(URL + PARAMS, "", String.class);
    producer.stop();
    

    I did it that way because the documentation says it:

    The camel-http4 producer supports URI parameters to be sent to the HTTP server. The URI parameters can either be set directly on the endpoint URI or as a header with the key Exchange.HTTP_QUERY on the message:

    But... If value1 and/or value2 change, camel will use URL + PARAMS to create a NEW endpoint. So, if I use that code a million of times, it will create a million of http4 endpoints with all the stuff (headers, caché, etc).

    To avoid that I use the Exchange.HTTP_QUERY header:

    String URL = exchange.getContext().resolvePropertyPlaceholders("{{URL_PAGO}}");
    
    String PARAMS = "param1=" + value1 + "&param2=" + value2;
    Map<String,Object> headers = new HashMap<String,Object>();
    headers.put(Exchange.HTTP_QUERY, PARAMS);
    
    ProducerTemplate producer = exchange.getContext().createProducerTemplate();
    String response = producer.requestBody(URL, "",headers, String.class);
    producer.stop();
    

    using this method, camel creates only 1 http4 endpoint.

    I think the documentation should be more detailed about this point.

    Bye.