2

I am using Jersey Client (v2.17) to make external calls from my app.

I found out this memory leak bug (the CPU consumption was very high) which made me re-write my code to make the client static like this:

public class GeneralUtil {

    private static final Client client = ClientBuilder.newClient()


    public static String makeCall(String url) throws NotFoundException {
        return client.target(url).request().get(String.class);
      }
}

However, now I have concurrency problems - I am using this class to be called from multiple threads. I keep on getting:

org.apache.http.impl.execchain.RequestAbortedException: Request aborted

Any suggestion - how can I still prevent the memory leak, and still use the client?

Dejell
  • 13,947
  • 40
  • 146
  • 229

2 Answers2

2

If you don't want to create an arbitrary number of Client objects, you can use ThreadLocal and have one object per thread.

You can override ThreadLocal.initialValue to return ClientBuilder.newClient() to automate creation of Client objects for new threads.

Or you could make the methods synchronized, but that means that you will only be able to do one request at a time.

Here's some example code:

class GeneralUtil {

    ThreadLocal<Client> client = new ThreadLocal<Client>() {
        @Override
        public Client initialValue() {
            return ClientBuilder.newClient();
        }
    };

    public static String makeCall(String url) throws NotFoundException {
        return client.get().target(url).request().get(String.class);
    }

    ...
}
aioobe
  • 413,195
  • 112
  • 811
  • 826
  • can you give an example for the first solution? do you mean not to make it static? – Dejell Jun 05 '15 at 12:08
  • Added an example. (I didn't test the code myself. Feel free to update the answer if you for instance find any syntactical issues.) – aioobe Jun 05 '15 at 12:13
  • what would be with the client object once the thread is finished? – Dejell Jun 05 '15 at 12:23
  • It will be left in memory. This solution assumes that you're not creating an arbitrary number of threads. (If you are, consider using a thread pool instead.) – aioobe Jun 05 '15 at 12:24
  • Another solution would be to create a pool of `Client` objects, store them in a thread safe data structure and let each thread extract an object, use it, and put it back into the pool. – aioobe Jun 05 '15 at 12:25
  • It's a tomcat application. for each request that the user is making, I am making another 6 calls. so I believe that it will keep it in the memory and it's not good (I have many user). – Dejell Jun 05 '15 at 12:27
  • I don't think it matters match. Tomcat uses a thread pool to serve requests. – aioobe Jun 05 '15 at 12:28
  • can you show an example for the other solution approach? – Dejell Jun 05 '15 at 12:28
  • Follow the advice here: http://stackoverflow.com/questions/8924086/how-to-create-an-object-pool-to-be-able-to-borrow-and-return-objects – aioobe Jun 05 '15 at 12:29
  • Thanks will use the thread pool. so actually if 2 users make a call to tomcat - will the object stay in memory, or after each user finished making the call it will return the object (which is the call with all the objects) to memory pool - am I right? – Dejell Jun 05 '15 at 13:18
  • There will be one object per thread, which is a fixed number, and these will stay in memory. – aioobe Jun 05 '15 at 18:07
1

As initially stated by Dejel, this is a known issue.

The "workarounds" work... but I believe this issue is critical and should be fixed by the Jersey team.

Let the Jersey team know that this affects YOU by logging in to JIRA and voting it up. It currently only has 3 votes :

https://java.net/jira/browse/JERSEY-2830

Filip
  • 906
  • 3
  • 11
  • 33
  • Thanks! Isn't it crazy? that such a bug exists?I don't think that users of an open source need to make such a work around in order to use the code. – Dejell Jun 08 '15 at 15:10