1 /* 2 * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 /* @test 25 * @bug 4607272 6999915 26 * @summary Unit test for AsynchronousSocketChannel 27 * @run main/othervm -XX:+DisableExplicitGC -XX:MaxDirectMemorySize=64m Leaky 28 */ 29 30 import java.nio.ByteBuffer; 31 import java.nio.channels.*; 32 import java.net.*; 33 import java.util.List; 34 import java.util.concurrent.Future; 35 import java.util.concurrent.ThreadFactory; 36 import java.lang.management.BufferPoolMXBean; 37 import java.lang.management.ManagementFactory; 38 39 /** 40 * Heap buffers must be substituted with direct buffers when doing I/O. This 41 * test creates a scenario on Windows that challenges the per-thread buffer 42 * cache and quickly leads to an OutOfMemoryError if temporary buffers are 43 * not returned to the native heap. 44 */ 45 46 public class Leaky { 47 48 static final int K = 1024; 49 50 static class Connection { 51 private final AsynchronousSocketChannel client; 52 private final SocketChannel peer; 53 private final ByteBuffer dst; 54 private Future<Integer> readResult; 55 56 Connection(AsynchronousChannelGroup group) throws Exception { 57 ServerSocketChannel ssc = 58 ServerSocketChannel.open().bind(new InetSocketAddress(0)); 59 InetAddress lh = InetAddress.getLocalHost(); 60 int port = ((InetSocketAddress)(ssc.getLocalAddress())).getPort(); 61 SocketAddress remote = new InetSocketAddress(lh, port); 62 client = AsynchronousSocketChannel.open(group); 63 client.connect(remote).get(); 64 peer = ssc.accept(); 65 ssc.close(); 66 dst = ByteBuffer.allocate(K*K); 67 } 68 69 void startRead() { 70 dst.clear(); 71 readResult = client.read(dst); 72 } 73 74 void write() throws Exception { 75 peer.write(ByteBuffer.wrap("X".getBytes())); 76 } 77 78 void finishRead() throws Exception { 79 readResult.get(); 80 } 81 } 82 83 public static void main(String[] args) throws Exception { 84 ThreadFactory threadFactory = new ThreadFactory() { 85 @Override 86 public Thread newThread(Runnable r) { 87 Thread t = new Thread(r); 88 t.setDaemon(true); 89 return t; 90 } 91 }; 92 AsynchronousChannelGroup group = 93 AsynchronousChannelGroup.withFixedThreadPool(4, threadFactory); 94 95 final int CONNECTION_COUNT = 10; 96 Connection[] connections = new Connection[CONNECTION_COUNT]; 97 for (int i=0; i<CONNECTION_COUNT; i++) { 98 connections[i] = new Connection(group); 99 } 100 101 for (int i=0; i<1024; i++) { 102 // initiate reads 103 for (Connection conn: connections) { 104 conn.startRead(); 105 } 106 107 // write data so that the read can complete 108 for (Connection conn: connections) { 109 conn.write(); 110 } 111 112 // complete read 113 for (Connection conn: connections) { 114 conn.finishRead(); 115 } 116 } 117 118 // print summary of buffer pool usage 119 List<BufferPoolMXBean> pools = 120 ManagementFactory.getPlatformMXBeans(BufferPoolMXBean.class); 121 for (BufferPoolMXBean pool: pools) 122 System.out.format(" %8s ", pool.getName()); 123 System.out.println(); 124 for (int i=0; i<pools.size(); i++) 125 System.out.format("%6s %10s %10s ", "Count", "Capacity", "Memory"); 126 System.out.println(); 127 for (BufferPoolMXBean pool: pools) { 128 System.out.format("%6d %10d %10d ", 129 pool.getCount(), pool.getTotalCapacity(), pool.getMemoryUsed()); 130 } 131 System.out.println(); 132 } 133 }