[ https://issues.apache.org/jira/browse/AVRO-2519?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17204670#comment-17204670 ]
Julian Wexler commented on AVRO-2519: ------------------------------------- The problem actually IS in the {{NettyTransceiver}}: if an exception occurs during the constructor, the {{NioClientSocketChannelFactory}} is not properly closed. One possible workaround: {code:java} NettyTransceiver client = null; NioClientSocketChannelFactory factory = new NioClientSocketChannelFactory( Executors.newCachedThreadPool(new NettyTransceiver.NettyTransceiverThreadFactory("Avro Netty Boss")), Executors.newCachedThreadPool(new NettyTransceiver.NettyTransceiverThreadFactory("Avro Netty I/O"))); while (true) { try { client = new NettyTransceiver(new InetSocketAddress(InetAddress.getByName("127.0.0.1"), 7999), factory, 3000L); } catch (Exception e) { e.printStackTrace(); } finally { if (client != null) client.close(); } } factory.shutdown(); {code} does not leak resources and can run like forever on my machine. The leak in question is no longer present in 1.10 (due to migration from netty 3 to netty 4, and replaced by another resource leak), but I could help provide a patch for 1.9, if there is going to be a 1.9.3 release at all. > Use NettyTransceiver repeatedly connect to remote server which doesn't > support current RPC or unavailable will cause " java.lang.OutOfMemoryError: > Direct buffer memory" > ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ > > Key: AVRO-2519 > URL: https://issues.apache.org/jira/browse/AVRO-2519 > Project: Apache Avro > Issue Type: Bug > Components: java > Affects Versions: 1.9.0 > Environment: java version "12.0.1" 2019-04-16 > Java(TM) SE Runtime Environment (build 12.0.1+12) > Java HotSpot(TM) 64-Bit Server VM (build 12.0.1+12, mixed mode, sharing) > Reporter: Xun Wang > Priority: Critical > Attachments: avro-rpc-quickstart test.zip > > > I just modify the code from > https://github.com/phunt/avro-rpc-quickstart。Execute the modified code can > 100% reproduce this issue. I have attached the test project file. When use > NettyTransceiver repeatedly connect to remote server which doesn't support > current RPC or unavailable will cause " java.lang.OutOfMemoryError: Direct > buffer memory" > The source to execute: > /** > * Licensed to the Apache Software Foundation (ASF) under one > * or more contributor license agreements. See the NOTICE file > * distributed with this work for additional information > * regarding copyright ownership. The ASF licenses this file > * to you under the Apache License, Version 2.0 (the > * "License"); you may not use this file except in compliance > * with the License. You may obtain a copy of the License at > * > * http://www.apache.org/licenses/LICENSE-2.0 > * > * Unless required by applicable law or agreed to in writing, software > * distributed under the License is distributed on an "AS IS" BASIS, > * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. > * See the License for the specific language governing permissions and > * limitations under the License. > */ > > package example; > > import java.io.IOException; > import java.net.InetAddress; > import java.net.InetSocketAddress; > > import org.apache.avro.ipc.netty.NettyServer; > import org.apache.avro.ipc.netty.NettyTransceiver; > import org.apache.avro.ipc.Server; > import org.apache.avro.ipc.specific.SpecificRequestor; > import org.apache.avro.ipc.specific.SpecificResponder; > import org.apache.avro.util.Utf8; > > import example.proto.Mail; > import example.proto.Message; > > /** > * Start a server, attach a client, and send a message. > */ > public class Main { > public static class MailImpl implements Mail { > // in this simple example just return details of the message > public Utf8 send(Message message) { > System.out.println("Sending message"); > return new Utf8("Sending message to " + message.getTo().toString() + " from " > + message.getFrom().toString() > + " with body " + message.getBody().toString()); > } > } > > private static Server server; > > private static void startServer() throws IOException { > server = new NettyServer(new SpecificResponder(Mail.class, new MailImpl()), > new InetSocketAddress(65111)); > // the server implements the Mail protocol (MailImpl) > } > > public static void main(String[] args) throws IOException { > // if (args.length != 3) { > // System.out.println("Usage: <to> <from> <body>"); > // System.exit(1); > // } > > System.out.println("Starting server"); > // usually this would be another app, but for simplicity > // startServer(); > System.out.println("Server started"); > > while (true) { > NettyTransceiver client = null; > try { > client = new NettyTransceiver(new > InetSocketAddress(InetAddress.getByName("129.28.206.27"), 7999), 3000l); > // client code - attach to the server and send a message > Mail proxy = (Mail) SpecificRequestor.getClient(Mail.class, client); > System.out.println("Client built, got proxy"); > > // fill in the Message record and send it > Message message = new Message(); > message.setTo(new Utf8(args[0])); > message.setFrom(new Utf8(args[1])); > message.setBody(new Utf8(args[2])); > System.out.println("Calling proxy.send with message: " + message.toString()); > System.out.println("Result: " + proxy.send(message)); > } catch (Exception e) { > System.out.println(e.getMessage()); > } finally { > // cleanup > if(client != null) { > client.close(); > } > } > > } > > // server.close(); > } > } > The error log: > Starting server > Server started > Error connecting to /129.28.206.27:7999 > Error connecting to /129.28.206.27:7999 > Error connecting to /129.28.206.27:7999 > Error connecting to /129.28.206.27:7999 > Error connecting to /129.28.206.27:7999 > Error connecting to /129.28.206.27:7999 > Error connecting to /129.28.206.27:7999 > Exception in thread "main" java.lang.OutOfMemoryError: Direct buffer memory > at java.base/java.nio.Bits.reserveMemory(Bits.java:175) > at java.base/java.nio.DirectByteBuffer.<init>(DirectByteBuffer.java:118) > at java.base/java.nio.ByteBuffer.allocateDirect(ByteBuffer.java:317) > at > org.jboss.netty.channel.socket.nio.SocketSendBufferPool$Preallocation.<init>(SocketSendBufferPool.java:156) > at > org.jboss.netty.channel.socket.nio.SocketSendBufferPool.<init>(SocketSendBufferPool.java:42) > at > org.jboss.netty.channel.socket.nio.AbstractNioWorker.<init>(AbstractNioWorker.java:45) > at org.jboss.netty.channel.socket.nio.NioWorker.<init>(NioWorker.java:45) > at > org.jboss.netty.channel.socket.nio.NioWorkerPool.newWorker(NioWorkerPool.java:44) > at > org.jboss.netty.channel.socket.nio.NioWorkerPool.newWorker(NioWorkerPool.java:28) > at > org.jboss.netty.channel.socket.nio.AbstractNioWorkerPool.init(AbstractNioWorkerPool.java:80) > at > org.jboss.netty.channel.socket.nio.NioWorkerPool.<init>(NioWorkerPool.java:39) > at > org.jboss.netty.channel.socket.nio.NioWorkerPool.<init>(NioWorkerPool.java:33) > at > org.jboss.netty.channel.socket.nio.NioClientSocketChannelFactory.<init>(NioClientSocketChannelFactory.java:151) > at > org.jboss.netty.channel.socket.nio.NioClientSocketChannelFactory.<init>(NioClientSocketChannelFactory.java:116) > at > org.apache.avro.ipc.netty.NettyTransceiver.<init>(NettyTransceiver.java:127) > at example.Main.main(Main.java:69) > > The JVM parameter: > -XX:MaxDirectMemorySize=8m -Dio.netty.leakDetection.level=advanced > -- This message was sent by Atlassian Jira (v8.3.4#803005)