如果操作不正确,RestEasyClient JAX RS可能会发生资源泄漏 [英] RestEasyClient JAX RS possible resource leak if not done correctly

查看:216
本文介绍了如果操作不正确,RestEasyClient JAX RS可能会发生资源泄漏的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

问题: 我有一个其他客户端,该客户端应该将请求发送到URL. Java应用程序是一个独立的Java应用程序(以java -jar开头),然后在退出时关闭了所有应用程序上下文.但是应用程序将结束但不会关闭,并且PID保留给Java进程. 对于每个请求,我都进行了异步调用,并在InvocationCallback实现中获取了响应.

Issue: I had a rest client that was supposed to send request to a URL. The java application was a standalone java Application ( started with java -jar ) and then on exit all application context were closed. but the application would end but not shutdown and the PID remained for the java process. On each request I was doing an async call and getting the response in an InvocationCallback implementation.

 client = new ResteasyClientBuilder().connectTimeout(timeout, TimeUnit.SECONDS).readTimeout(timeout, TimeUnit.SECONDS).httpEngine(engine).build();
ResteasyWebTarget resteasyWebTarget = client.target(url));
        Future<Response>  response = resteasyWebTarget.
                          request().
                          headers(headers).
                          async().
                          get(restResponseCallback);

即使在一次测试URL的测试调用之后,即使所有上下文都已关闭,我的应用也无法关闭.

Even after one test call to test URL my app would not close Even though all contexts were closed.

如以下所述,已关闭应用程序上下文 Spring ApplicationContext.close()不会关闭应用程序

The application contexts were closed as described in Spring ApplicationContext.close() doesnot shut down application

推荐答案

总之,问题是我在每个请求上都创建了一个新客户端.

the issue in short was that i was creating a new client on each request.

我关闭"了该应用程序,然后寻找关闭后始终挂起的Java进程的虚假PID.即使该应用程序已关闭",但PID仍然存在,所以我做了PID的jmap.当jmap在资深人士的建议下没有告诉我有关虚假资源的任何信息时,我尝试了使用jstack作为pid.

I "closed" the application and then looked for the ghost PID of the java processn that always hung after a shutdown. even though the application was " shutdown" but the PID remained, so I did the jmap of the PID When jmap didnt tell me anything about a ghost resource on an advice of a senior i tried jstack for the pid.

简而言之,我看到此资源已挂起(或类似的资源),它被卡在LinkedBlockingqueue.take()上.

I saw this resource hanging (or similar) in short it was stuck on LinkedBlockingqueue.take().

"pool-17-thread-1" #50 prio=5 os_prio=64 tid=0x0000000101758000 nid=0x5f waiting on condition [0xffffffff3f4fe000]
   java.lang.Thread.State: WAITING (parking)
        at sun.misc.Unsafe.park(Native Method)
        - parking to wait for  <0x00000007bf948000> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
        at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
        at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)
        at java.util.concurrent.LinkedBlockingQueue.take(LinkedBlockingQueue.java:442)
        at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1074)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1134)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
        at java.lang.Thread.run(Thread.java:748)

我注意到同一个堆栈中的条目与我进行的许多测试(请求)一样多.

I noticed that there will be as many entries of the same stack as many tests (requests) i did.

我有一些自己的LinkedBlockingQueues,所以我删除了take()以使用stackoverflow上的答案进行轮询(我现在找不到链接).但这不是我们的之一.所以我怀疑restEasy在下面使用LBQueue.调试只会向我显示一个可以执行此操作的线程,而不会向我显示它从何处启动.

I had some LinkedBlockingQueues of my own so i removed take() to poll using an answer on stackoverflow ( i cannot find the link now) . but it was not one of ours. So i suspected restEasy using a LBQueue underneath. the debug would only show me a thread that would do that but didnt give me where it initiated from.

我阅读了stackoverflow,在一些resteasy邮件组中出现了此问题,但没有解决方案.在阅读RestEasyClient的父级的Javadoc后,我试图改变自己的方法并得出结论

I read up on stackoverflow and in some resteasy mail groups there was this issue but no solution. I tried to change my approach and came to the conclusion after reading the javadoc of the parent of RestEasyClient

客户端是管理客户端的重量级对象 通讯基础设施.初始化以及处置 {@code Client}实例可能是一个相当昂贵的操作.它是 因此建议仅构建少量的{@code Client} 应用程序中的实例.客户端实例必须为{@link

Clients are heavy-weight objects that manage the client-side communication infrastructure. Initialization as well as disposal of a {@code Client} instance may be a rather expensive operation. It is therefore advised to construct only a small number of {@code Client} instances in the application. Client instances must be {@link

(应该已经读过我开始使用的内容) 因此,我更改了实现方式,以仅创建一个客户端和多个client.targets

(should have read what i was using to begin with ) So I changed my implementation to create only one client and many client.targets

 ResteasyWebTarget resteasyWebTarget = client.target(url);

这消除了资源泄漏.从技术上讲,JS RX或Resteasy中没有资源泄漏,这只是实现方式. 希望这能帮助一些可能犯了与我相同的错误,并为无法消亡的资源感到困惑的人.

this removed the resource leak. technically there is no resource leak in JS RX or Resteasy it is just how implemented it. hope this helps some one who may have done the same mistake I did and is baffled by a resource that just wouldn't Die.

一些非常好的帖子,可以帮助您进一步完善它们: 使用Jersey的JAX RS的内存问题

Some really nice posts that can help and refine it more: Memory issue with JAX RS using jersey

我认为这两个答案都很有价值

Both the answers are very valuable in my opinion

这篇关于如果操作不正确,RestEasyClient JAX RS可能会发生资源泄漏的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆