如何减小Apache CXF客户端存根对象的内存大小?

21

我的Web服务客户端应用程序使用Apache CXF生成客户端存根,用于与多个Web服务进行通信。生成的CXF Web服务存根对象具有相当大的内存占用(10-15个Web服务对象需要超过64 MB的内存)。是否有办法减少CXF对象的内存占用?


你认为为什么恰恰是这些对象占用了内存? - Bozho
我进行了一些简单的分析(在Windows任务管理器中观察进程内存大小)。创建了一个测试应用程序,在循环中创建Web服务存根的实例并绑定到Web服务。每次绑定发生时,会使用另外5-10k的内存。Web服务本身有大约360个Web方法。 - Jeremy Raymond
Apache CXF是建立在JAX-WS之上的,所以我认为这是JAX-WS的问题。我有同样的问题,在这里提问:http://weblogs.java.net/blog/jitu/archive/2008/08/control_of_jaxb.html#comment-813979 - dma_k
2
这不是内存分析的适当方法。使用VisualVM获取堆转储并进行分析。这可能意味着它正在消耗5-10kb,但它应该是几乎所有可垃圾回收的内存,因此它已经准备好等待释放。Java将在需要时或以其他方式决定GC时释放它。如果服务调用正在处理大量XML,则5-10kb并不算过多。 - squawknull
1
@squawknull: 我有由Spring上下文管理的WebService代理(作用域为singleton)。这意味着当我的服务部署时,我需要一直使用它们。而且,如果我按需创建它们,在线应用程序中无法承受每个代理需要约1秒钟的时间来创建 - 这是我不能承受的豪华。堆分析显示,内存的使用效率不高,无法进行垃圾回收。@all:我已经创建了http://java.net/jira/browse/JAX_WS-942 - 请投票支持。 - dma_k
3
虽然我的评论并不能解决问题,但是在单个端点上使用360个Web方法是非常多的。这显然违反了大多数Web服务的最佳实践(保持表面积小、单一职责原则、内聚等)。当合同稍有变化时,你需要重新生成存根等情况时,我可不想站在你的立场上。 - jbx
3个回答

1
我们在使用Axis时遇到了类似的问题。我们的问题是,我们想要对Web服务进行许多并发调用,而使用WSDL生成的Axis客户端会导致每个客户端使用大量内存。这些客户端不是线程安全的,因此我们必须为每个请求创建一个客户端。
我们有两个选择。首先,我们可以修剪生成的代码,但出于维护原因,这样做并不好。
其次,我们简单地修剪了WSDL以删除对我们不相关的部分,并重新生成了精简的客户端。这样,如果我们调用一个服务方法,它的客户端就不会包含该线程不使用的无关方法的大块内容。
效果还不错,但仍然是维护的噩梦,因为每当WSDL更新(例如,我们的合作伙伴发布其Web服务的新版本)时,我们都需要花时间创建简化的WSDL。我想理想的解决方案是让我们的合作伙伴认识到我们的问题并承担简化WSDL的责任。

0

我们对CXF客户端采取了不同的方法。我还没有研究过它的内存占用情况,在我们的环境中这不是一个问题,但与创建存根相比,它肯定是一种更简单的开发方法。它看起来像这样:

JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
HTTPClientPolicy httpClientPolicy = new HTTPClientPolicy();

factory.setAddress(endpoint);
factory.getServiceFactory().setDataBinding(new AegisDatabinding());
factory.setServiceClass(myInterface.class);
Object client = factory.create();
((BindingProvider) client).getRequestContext().put(BindingProvider.SESSION_MAINTAIN_PROPERTY, true);

myInterface stub = (myInterface)client;

我们只是这样做(当然,我们已经构建了一些实用类来进一步简化事情),以便在运行时连接到任何我们想要连接的WS(前提是我们有其Java接口)。我们的目标是使整个WS过程对程序员尽可能透明。我们真的没有兴趣WSDL和XSD per se。我们怀疑我们并不孤单。

在我的情况下,Web服务本身是一个.NET Web服务,因此没有Java接口。 - Jeremy Raymond

0
如果您的SOAP需求非常基本,您可以考虑使用kSOAP2,它非常节省内存。它被设计为在J2ME手机应用程序中运行良好。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接