You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by ma...@apache.org on 2019/06/25 13:48:26 UTC

[tomcat-native] 01/02: Add Java test files

This is an automated email from the ASF dual-hosted git repository.

markt pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/tomcat-native.git

commit 80f264c3d4a7a0b75cf147e5e0f1a64858ca1f44
Author: Mark Thomas <ma...@apache.org>
AuthorDate: Tue Jun 25 14:44:45 2019 +0100

    Add Java test files
---
 test/org/apache/tomcat/jni/AbstractJniTest.java    |  46 ++++
 test/org/apache/tomcat/jni/TestFile.java           |  67 ++++++
 test/org/apache/tomcat/jni/TestSocketServer.java   | 233 +++++++++++++++++++++
 .../jni/TestSocketServerAnyLocalAddress.java       | 207 ++++++++++++++++++
 test/org/apache/tomcat/jni/TesterSSL.java          |  58 +++++
 5 files changed, 611 insertions(+)

diff --git a/test/org/apache/tomcat/jni/AbstractJniTest.java b/test/org/apache/tomcat/jni/AbstractJniTest.java
new file mode 100644
index 0000000..84ed1ac
--- /dev/null
+++ b/test/org/apache/tomcat/jni/AbstractJniTest.java
@@ -0,0 +1,46 @@
+/*
+ *  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 org.apache.tomcat.jni;
+
+import org.junit.After;
+import org.junit.Assume;
+import org.junit.Before;
+
+public abstract class AbstractJniTest {
+
+    private boolean nativeLibraryPresent = false;
+
+    @Before
+    public void initBase() throws Exception {
+        try {
+            Library.initialize(null);
+            nativeLibraryPresent = true;
+        } catch (LibraryNotFoundError lnfe) {
+            nativeLibraryPresent = false;
+        }
+        Assume.assumeTrue("APR Library not found", nativeLibraryPresent);
+    }
+
+
+    @After
+    public void destroyBase() {
+        if (nativeLibraryPresent) {
+            Library.terminate();
+        }
+    }
+
+}
diff --git a/test/org/apache/tomcat/jni/TestFile.java b/test/org/apache/tomcat/jni/TestFile.java
new file mode 100644
index 0000000..433939f
--- /dev/null
+++ b/test/org/apache/tomcat/jni/TestFile.java
@@ -0,0 +1,67 @@
+/*
+ *  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 org.apache.tomcat.jni;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+
+public class TestFile extends AbstractJniTest {
+
+    @Test
+    public void testInfoGet() throws Exception {
+        String testFile = "test/org/apache/tomcat/jni/TestFile.java";
+        java.io.File file = new java.io.File(testFile);
+        Assert.assertTrue("File " + testFile + " does not exist!", file.exists());
+
+        Library.initialize(null);
+        long pool = Pool.create(0L);
+        int openFlags = File.APR_FOPEN_READ | File.APR_FOPEN_BUFFERED | File.APR_FOPEN_XTHREAD;
+        int openPermissions = File.APR_FPROT_OS_DEFAULT;
+        int statFlags = File.APR_FINFO_MIN;
+        long fd = File.open(testFile, openFlags, openPermissions, pool);
+        FileInfo fileInfo = new FileInfo();
+        for (int i = 0; i < 100000; i++) {
+            org.apache.tomcat.jni.File.infoGet(fileInfo, statFlags, fd);
+            @SuppressWarnings("unused")
+            String info = inspectFileInfo(fileInfo);
+        }
+    }
+
+    public static String inspectFileInfo(FileInfo fileInfo) {
+        String result = fileInfo.toString() + " : {" +
+                String.format("\n  pool : %d", Long.valueOf(fileInfo.pool)) +
+                String.format("\n  valid : %d", Integer.valueOf(fileInfo.valid)) +
+                String.format("\n  protection : %d", Integer.valueOf(fileInfo.protection)) +
+                String.format("\n  filetype : %d", Integer.valueOf(fileInfo.filetype)) +
+                String.format("\n  user : %d", Integer.valueOf(fileInfo.user)) +
+                String.format("\n  group : %d", Integer.valueOf(fileInfo.group)) +
+                String.format("\n  inode : %d", Integer.valueOf(fileInfo.inode)) +
+                String.format("\n  device : %d", Integer.valueOf(fileInfo.device)) +
+                String.format("\n  nlink : %d", Integer.valueOf(fileInfo.nlink)) +
+                String.format("\n  size : %d", Long.valueOf(fileInfo.size)) +
+                String.format("\n  csize : %d", Long.valueOf(fileInfo.csize)) +
+                String.format("\n  atime : %d", Long.valueOf(fileInfo.atime)) +
+                String.format("\n  mtime : %d", Long.valueOf(fileInfo.mtime)) +
+                String.format("\n  ctime : %d", Long.valueOf(fileInfo.ctime)) +
+                String.format("\n  fname : %s", fileInfo.fname) +
+                String.format("\n  name : %s", fileInfo.name) +
+                String.format("\n  filehand : %d", Long.valueOf(fileInfo.filehand)) +
+                "\n}";
+        return result;
+    }
+}
\ No newline at end of file
diff --git a/test/org/apache/tomcat/jni/TestSocketServer.java b/test/org/apache/tomcat/jni/TestSocketServer.java
new file mode 100644
index 0000000..d1ea90d
--- /dev/null
+++ b/test/org/apache/tomcat/jni/TestSocketServer.java
@@ -0,0 +1,233 @@
+/*
+ *  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 org.apache.tomcat.jni;
+
+import java.io.OutputStream;
+import java.util.concurrent.CountDownLatch;
+
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Tests for server-side sockets.
+ */
+public class TestSocketServer extends AbstractJniTest {
+
+    private static final String HOST = "localhost";
+    private static final long ERROR_MARGIN;
+
+    private int port = 0;
+    private long serverSocket = 0;
+    private long clientSocket = 0;
+
+    // Determine the resolution of System.nanoTime() so an appropriate error
+    // margin can be used in tests that use nanoTime()
+    static {
+        long start = System.nanoTime();
+        long end = System.nanoTime();
+        while (end == start) {
+            end = System.nanoTime();
+        }
+        ERROR_MARGIN = 2 * (end - start);
+    }
+
+
+    @Before
+    public void init() throws Exception {
+        long serverPool = Pool.create(0);
+        long inetAddress = Address.info(HOST, Socket.APR_INET,
+                                        0, 0, serverPool);
+        serverSocket = Socket.create(Socket.APR_INET, Socket.SOCK_STREAM,
+                                   Socket.APR_PROTO_TCP, serverPool);
+        if (OS.IS_UNIX) {
+            Socket.optSet(serverSocket, Socket.APR_SO_REUSEADDR, 1);
+        }
+        int rc = Socket.bind(serverSocket, inetAddress);
+        Assert.assertEquals("Can't bind: " + Error.strerror(rc), 0, rc);
+        Socket.listen(serverSocket, 5);
+        if (!OS.IS_UNIX) {
+            Socket.optSet(serverSocket, Socket.APR_SO_REUSEADDR, 1);
+        }
+
+        long localAddress = Address.get(Socket.APR_LOCAL, serverSocket);
+        port = Address.getInfo(localAddress).port;
+    }
+
+
+    @After
+    public void destroy() {
+        if (clientSocket != 0) {
+            Socket.close(clientSocket);
+            Socket.destroy(clientSocket);
+        }
+        if (serverSocket != 0) {
+            Socket.close(serverSocket);
+            Socket.destroy(serverSocket);
+        }
+    }
+
+
+    @Test
+    public void testPort() {
+        Assert.assertTrue(port > 0);
+    }
+
+
+    @Test
+    public void testBlockingReadFromClientWithTimeout() throws Exception {
+        /* Start the client that connects to the server */
+        Client client = new Client(port);
+        client.start();
+
+        /* Accept the client connection */
+        clientSocket = Socket.accept(serverSocket);
+
+        /* Configure a 1s timeout for reading from client */
+        Socket.timeoutSet(clientSocket, 1000000);
+        long timeout = Socket.timeoutGet(clientSocket);
+        Assert.assertEquals("Socket.timeoutGet clientSocket failed", 1000000, timeout);
+
+        byte [] buf = new byte[1];
+        long start = System.nanoTime();
+        while (Socket.recv(clientSocket, buf, 0, 1) == 1) {
+        }
+        long wait = System.nanoTime() - start;
+        Assert.assertFalse("Socket.timeoutSet failed (<1s) [" + wait + "] +-[" + ERROR_MARGIN + "]",
+                wait < 1000000000 - ERROR_MARGIN);
+        Assert.assertFalse("Socket.timeoutSet failed (>2s) [" + wait + "] +-[" + ERROR_MARGIN + "]",
+                wait > 2000000000 + ERROR_MARGIN);
+
+        client.countDown();
+        client.join();
+    }
+
+
+    @Test
+    public void testNonBlockingReadFromClient() throws Exception {
+        /* Start the client that connects to the server */
+        Client client = new Client(port);
+        client.start();
+
+        /* Accept the client connection */
+        clientSocket = Socket.accept(serverSocket);
+
+        /* Configure the connection for non-blocking */
+        Socket.optSet(clientSocket, Socket.APR_SO_NONBLOCK, 1);
+        int val = Socket.optGet(clientSocket, Socket.APR_SO_NONBLOCK);
+        Assert.assertEquals("Socket.optGet clientSocket failed", 1, val);
+
+        byte [] buf = new byte[1];
+        long start = System.nanoTime();
+        while (Socket.recv(clientSocket, buf, 0, 1) == 1) {
+        }
+        long wait = System.nanoTime() - start;
+        Assert.assertFalse("non_blocking client Socket.APR_SO_NONBLOCK failed (>2ms) [" + wait +
+                "] +-[" + ERROR_MARGIN + "]", wait > 2000000 + ERROR_MARGIN);
+
+        client.countDown();
+        client.join();
+    }
+
+
+    @Test
+    public void testNonBlockingReadThenBlockingReadFromClient() throws Exception {
+        /* Start the client that connects to the server */
+        Client client = new Client(port);
+        client.start();
+
+        /* Accept the client connection */
+        clientSocket = Socket.accept(serverSocket);
+
+        /* Configure the connection for non-blocking */
+        Socket.optSet(clientSocket, Socket.APR_SO_NONBLOCK, 1);
+
+        byte [] buf = new byte[1];
+        long start = System.nanoTime();
+        while (Socket.recv(clientSocket, buf, 0, 1) == 1) {
+        }
+        long wait = System.nanoTime() - start;
+        Assert.assertFalse("non_blocking client Socket.APR_SO_NONBLOCK failed (>1ms) [" + wait +
+                "] +-[" + ERROR_MARGIN + "]", wait > 1000000 + ERROR_MARGIN);
+
+        /* Configure for blocking */
+        Socket.optSet(clientSocket, Socket.APR_SO_NONBLOCK, 0);
+        Socket.timeoutSet(clientSocket, 2000);
+        start = System.nanoTime();
+        while (Socket.recv(clientSocket, buf, 0, 1) == 1) {
+        }
+        wait = System.nanoTime() - start;
+        Assert.assertFalse("non_blocking client Socket.APR_SO_NONBLOCK false failed (<1ms) [" +
+                wait + "] +-[" + ERROR_MARGIN + "]", wait < 1000000 - ERROR_MARGIN);
+
+        client.countDown();
+        client.join();
+    }
+
+
+    @Test
+    public void testNonBlockingAcceptWithNoClient() throws Exception {
+        Socket.optSet(serverSocket, Socket.APR_SO_NONBLOCK, 1);
+        int val = Socket.optGet(serverSocket, Socket.APR_SO_NONBLOCK);
+        Assert.assertEquals("Socket.optGet serverSocket failed", 1, val);
+
+        long start = System.nanoTime();
+        boolean ok = false;
+        try {
+            Socket.accept(serverSocket);
+        } catch (Exception ex) {
+            ok = true;
+        }
+        long wait = System.nanoTime() - start;
+        Assert.assertTrue("Timeout failed", ok);
+        Assert.assertFalse("non_blocking accept Socket.APR_SO_NONBLOCK failed (>10ms) [" + wait +
+                "] +-[" + ERROR_MARGIN + "]", wait > 10000000 + ERROR_MARGIN);
+    }
+
+
+    /**
+     * Simple client that connects, sends a single byte then closes the
+     * connection.
+     */
+    private static class Client extends java.lang.Thread {
+
+        private final int port;
+        private final CountDownLatch complete = new CountDownLatch(1);
+
+        public Client(int port) throws Exception {
+            this.port = port;
+        }
+
+        public void countDown() {
+            complete.countDown();
+        }
+
+        @Override
+        public void run() {
+
+            try (java.net.Socket sock = new java.net.Socket(TestSocketServer.HOST, port)) {
+                OutputStream os = sock.getOutputStream();
+                os.write('A');
+                os.flush();
+                complete.await();
+            } catch (Exception ex) {
+                ex.printStackTrace();
+            }
+        }
+    }
+}
diff --git a/test/org/apache/tomcat/jni/TestSocketServerAnyLocalAddress.java b/test/org/apache/tomcat/jni/TestSocketServerAnyLocalAddress.java
new file mode 100644
index 0000000..866ba77
--- /dev/null
+++ b/test/org/apache/tomcat/jni/TestSocketServerAnyLocalAddress.java
@@ -0,0 +1,207 @@
+/*
+ *  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 org.apache.tomcat.jni;
+
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.NetworkInterface;
+import java.util.Enumeration;
+
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Tests for server-side sockets using any local address (0.0.0.0 or ::).
+ */
+public class TestSocketServerAnyLocalAddress extends AbstractJniTest {
+
+    // Excessive but allows for slow systems
+    private static final int TIMEOUT_MICROSECONDS = 10 * 1000 * 1000;
+
+    private long serverSocket = 0;
+    private long clientSocket = 0;
+
+
+    @Before
+    public void init() throws Exception {
+        long serverPool = Pool.create(0);
+        long inetAddress = Address.info(null, Socket.APR_UNSPEC,
+                                        0, 0, serverPool);
+        serverSocket = Socket.create(Address.getInfo(inetAddress).family, Socket.SOCK_STREAM,
+                                   Socket.APR_PROTO_TCP, serverPool);
+        if (OS.IS_UNIX) {
+            Socket.optSet(serverSocket, Socket.APR_SO_REUSEADDR, 1);
+        }
+        int rc = Socket.bind(serverSocket, inetAddress);
+        Assert.assertEquals("Can't bind: " + Error.strerror(rc), 0, rc);
+        Socket.listen(serverSocket, 5);
+        if (!OS.IS_UNIX) {
+            Socket.optSet(serverSocket, Socket.APR_SO_REUSEADDR, 1);
+        }
+    }
+
+
+    @After
+    public void destroy() {
+        if (clientSocket != 0) {
+            Socket.close(clientSocket);
+            Socket.destroy(clientSocket);
+        }
+        if (serverSocket != 0) {
+            Socket.close(serverSocket);
+            Socket.destroy(serverSocket);
+        }
+    }
+
+
+    @Test
+    public void testWithClient() throws Exception {
+        /* Start the client that connects to the server */
+        Client client = new Client(serverSocket);
+        client.start();
+
+        boolean running = true;
+        while (running) {
+            /* Accept the client connection */
+            clientSocket = Socket.accept(serverSocket);
+
+            /* Configure a 10s timeout for reading from client */
+            Socket.timeoutSet(clientSocket, TIMEOUT_MICROSECONDS);
+
+            byte [] buf = new byte[1];
+            while (Socket.recv(clientSocket, buf, 0, 1) == 1) {
+                // If 'A' was read, echo back 'Z'
+                if (buf[0] == 'A') {
+                    buf[0] = 'Z';
+                    Socket.send(clientSocket, buf, 0, 1);
+                }
+            }
+            if (buf[0] == 'E') {
+                running = false;
+            } else if (buf[0] == 'Z') {
+                // NO-OP - connection closing
+            } else {
+                Assert.fail("Unexpected data [" + (char) buf[0] + "]");
+            }
+        }
+
+        client.join();
+    }
+
+
+    /**
+     * Simple client that connects, sends a single byte then closes the
+     * connection.
+     */
+    private static class Client extends java.lang.Thread {
+
+        private final long serverSocket;
+
+        public Client(long serverSocket) throws Exception {
+            this.serverSocket = serverSocket;
+        }
+
+        @Override
+        public void run() {
+
+            try {
+                InetSocketAddress connectAddress = getConnectAddress(serverSocket);
+                java.net.Socket sock = new java.net.Socket();
+                sock.connect(connectAddress, TIMEOUT_MICROSECONDS);
+                sock.setSoTimeout(TIMEOUT_MICROSECONDS);
+                OutputStream ou = sock.getOutputStream();
+                InputStream in =  sock.getInputStream();
+                ou.write('A');
+                ou.flush();
+                int rep = in.read();
+                sock.close();
+                if (rep != 'Z') {
+                     throw new Exception("Read wrong data [" + rep + "]");
+                }
+
+                sock = new java.net.Socket();
+                sock.connect(connectAddress, TIMEOUT_MICROSECONDS);
+                sock.setSoTimeout(TIMEOUT_MICROSECONDS);
+                ou = sock.getOutputStream();
+                ou.write('E');
+                ou.flush();
+                sock.close();
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+        }
+
+
+        /*
+         * Assumes server is listening on any local address
+         */
+        private static InetSocketAddress getConnectAddress(long serverSocket) throws Exception {
+            long sa = Address.get(Socket.APR_LOCAL, serverSocket);
+            Sockaddr addr = Address.getInfo(sa);
+            InetSocketAddress localAddress;
+            if (addr.family == Socket.APR_INET6) {
+                localAddress = new InetSocketAddress("::", addr.port);
+            } else {
+                localAddress = new InetSocketAddress("0.0.0.0", addr.port);
+            }
+
+            // Need a local address of the same type (IPv4 or IPV6) as the
+            // configured bind address since the connector may be configured
+            // to not map between types.
+            InetAddress loopbackConnectAddress = null;
+            InetAddress linkLocalConnectAddress = null;
+
+            Enumeration<NetworkInterface> networkInterfaces = NetworkInterface.getNetworkInterfaces();
+            while (networkInterfaces.hasMoreElements()) {
+                NetworkInterface networkInterface = networkInterfaces.nextElement();
+                Enumeration<InetAddress> inetAddresses = networkInterface.getInetAddresses();
+                while (inetAddresses.hasMoreElements()) {
+                    InetAddress inetAddress = inetAddresses.nextElement();
+                    if (localAddress.getAddress().getClass().isAssignableFrom(inetAddress.getClass())) {
+                        if (inetAddress.isLoopbackAddress()) {
+                            if (loopbackConnectAddress == null) {
+                                loopbackConnectAddress = inetAddress;
+                            }
+                        } else if (inetAddress.isLinkLocalAddress()) {
+                            if (linkLocalConnectAddress == null) {
+                                linkLocalConnectAddress = inetAddress;
+                            }
+                        } else {
+                            // Use a non-link local, non-loop back address by default
+                            return new InetSocketAddress(inetAddress, localAddress.getPort());
+                        }
+                    }
+                }
+            }
+            // Prefer loop back over link local since on some platforms (e.g.
+            // OSX) some link local addresses are not included when listening on
+            // all local addresses.
+            if (loopbackConnectAddress != null) {
+                return new InetSocketAddress(loopbackConnectAddress, localAddress.getPort());
+            }
+            if (linkLocalConnectAddress != null) {
+                return new InetSocketAddress(linkLocalConnectAddress, localAddress.getPort());
+            }
+            // Fallback
+            return new InetSocketAddress("localhost", localAddress.getPort());
+        }
+    }
+}
diff --git a/test/org/apache/tomcat/jni/TesterSSL.java b/test/org/apache/tomcat/jni/TesterSSL.java
new file mode 100644
index 0000000..3ef57ee
--- /dev/null
+++ b/test/org/apache/tomcat/jni/TesterSSL.java
@@ -0,0 +1,58 @@
+/*
+ * 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 org.apache.tomcat.jni;
+
+import org.junit.Test;
+
+/*
+ * Helper class to investigate native memory leaks. Needs to be used with tools
+ * to monitor native memory usage.
+ *
+ * Note: Moving the Pool, SSLContext, SSL and BIO creation in/out of the loop
+ *       can help identify where the memory is leaking.
+ */
+public class TesterSSL {
+
+    @Test
+    public void testCreateDestroy() throws Exception {
+        Library.initialize(null);
+        SSL.initialize(null);
+
+        long memoryPool = Pool.create(0);
+        long sslCtx = SSLContext.make(memoryPool, SSL.SSL_PROTOCOL_ALL, SSL.SSL_MODE_SERVER);
+
+        for (int i = 0; i < 10000000; i++) {
+            doNative(sslCtx);
+            if (i % 1000 == 0) {
+                System.gc();
+            }
+        }
+
+        SSLContext.free(sslCtx);
+        Pool.destroy(memoryPool);
+
+        System.gc();
+    }
+
+
+    private void doNative(long sslCtx) throws Exception {
+        long ssl = SSL.newSSL(sslCtx, true);
+        long bio = SSL.makeNetworkBIO(ssl);
+        SSL.freeBIO(bio);
+        SSL.freeSSL(ssl);
+    }
+}


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org