Author: remm
Date: Wed Jun 10 12:45:26 2015
New Revision: 1684663
URL: http://svn.apache.org/r1684663
Log:
Direct buffers need explicit cleanup to ensure complete reliability without
OOMs.
Modified:
tomcat/trunk/java/org/apache/catalina/security/SecurityClassLoad.java
tomcat/trunk/java/org/apache/tomcat/util/buf/ByteBufferUtils.java
tomcat/trunk/java/org/apache/tomcat/util/net/AprEndpoint.java
tomcat/trunk/java/org/apache/tomcat/util/net/Nio2Channel.java
tomcat/trunk/java/org/apache/tomcat/util/net/Nio2Endpoint.java
tomcat/trunk/java/org/apache/tomcat/util/net/NioChannel.java
tomcat/trunk/java/org/apache/tomcat/util/net/NioEndpoint.java
tomcat/trunk/java/org/apache/tomcat/util/net/SecureNio2Channel.java
tomcat/trunk/java/org/apache/tomcat/util/net/SecureNioChannel.java
tomcat/trunk/java/org/apache/tomcat/util/net/SocketBufferHandler.java
Modified: tomcat/trunk/java/org/apache/catalina/security/SecurityClassLoad.java
URL:
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/security/SecurityClassLoad.java?rev=1684663&r1=1684662&r2=1684663&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/security/SecurityClassLoad.java
(original)
+++ tomcat/trunk/java/org/apache/catalina/security/SecurityClassLoad.java Wed
Jun 10 12:45:26 2015
@@ -263,6 +263,7 @@ public final class SecurityClassLoad {
throws Exception {
final String basePackage = "org.apache.tomcat.";
// buf
+ loader.loadClass(basePackage + "util.buf.ByteBufferUtils");
loader.loadClass(basePackage + "util.buf.HexUtils");
loader.loadClass(basePackage + "util.buf.StringCache");
loader.loadClass(basePackage + "util.buf.StringCache$ByteEntry");
Modified: tomcat/trunk/java/org/apache/tomcat/util/buf/ByteBufferUtils.java
URL:
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/buf/ByteBufferUtils.java?rev=1684663&r1=1684662&r2=1684663&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/util/buf/ByteBufferUtils.java (original)
+++ tomcat/trunk/java/org/apache/tomcat/util/buf/ByteBufferUtils.java Wed Jun
10 12:45:26 2015
@@ -16,10 +16,29 @@
*/
package org.apache.tomcat.util.buf;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
import java.nio.ByteBuffer;
public class ByteBufferUtils {
+ private static final Method cleanerMethod;
+ private static final Method cleanMethod;
+
+ static {
+ try {
+ ByteBuffer tempBuffer = ByteBuffer.allocateDirect(0);
+ cleanerMethod = tempBuffer.getClass().getMethod("cleaner");
+ cleanerMethod.setAccessible(true);
+ Object cleanerObject = cleanerMethod.invoke(tempBuffer);
+ cleanMethod = cleanerObject.getClass().getMethod("clean");
+ cleanMethod.invoke(cleanerObject);
+ } catch (IllegalAccessException | IllegalArgumentException
+ | InvocationTargetException | NoSuchMethodException |
SecurityException e) {
+ throw new ExceptionInInitializerError(e);
+ }
+ }
+
private ByteBufferUtils() {
// Hide the default constructor since this is a utility class.
}
@@ -56,8 +75,10 @@ public class ByteBufferUtils {
}
ByteBuffer out;
+ boolean direct = false;
if (in.isDirect()) {
out = ByteBuffer.allocateDirect(newSize);
+ direct = true;
} else {
out = ByteBuffer.allocate(newSize);
}
@@ -66,6 +87,20 @@ public class ByteBufferUtils {
in.flip();
out.put(in);
+ if (direct) {
+ cleanDirectBuffer(in);
+ }
+
return out;
}
+
+ public static void cleanDirectBuffer(ByteBuffer buf) {
+ try {
+ cleanMethod.invoke(cleanerMethod.invoke(buf));
+ } catch (IllegalAccessException | IllegalArgumentException
+ | InvocationTargetException | SecurityException e) {
+ // Ignore
+ }
+ }
+
}
Modified: tomcat/trunk/java/org/apache/tomcat/util/net/AprEndpoint.java
URL:
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/net/AprEndpoint.java?rev=1684663&r1=1684662&r2=1684663&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/util/net/AprEndpoint.java (original)
+++ tomcat/trunk/java/org/apache/tomcat/util/net/AprEndpoint.java Wed Jun 10
12:45:26 2015
@@ -51,6 +51,7 @@ import org.apache.tomcat.jni.Sockaddr;
import org.apache.tomcat.jni.Socket;
import org.apache.tomcat.jni.Status;
import org.apache.tomcat.util.ExceptionUtils;
+import org.apache.tomcat.util.buf.ByteBufferUtils;
import org.apache.tomcat.util.net.AbstractEndpoint.Acceptor.AcceptorState;
import org.apache.tomcat.util.net.AbstractEndpoint.Handler.SocketState;
import org.apache.tomcat.util.net.SSLHostConfig.Type;
@@ -2569,6 +2570,9 @@ public class AprEndpoint extends Abstrac
return;
}
closed = true;
+ if (sslOutputBuffer != null) {
+ ByteBufferUtils.cleanDirectBuffer(sslOutputBuffer);
+ }
((AprEndpoint)
getEndpoint()).getPoller().close(getSocket().longValue());
}
}
Modified: tomcat/trunk/java/org/apache/tomcat/util/net/Nio2Channel.java
URL:
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/net/Nio2Channel.java?rev=1684663&r1=1684662&r2=1684663&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/util/net/Nio2Channel.java (original)
+++ tomcat/trunk/java/org/apache/tomcat/util/net/Nio2Channel.java Wed Jun 10
12:45:26 2015
@@ -55,6 +55,13 @@ public class Nio2Channel implements Asyn
bufHandler.reset();
}
+ /**
+ * Free the channel memory
+ */
+ public void free() {
+ bufHandler.free();
+ }
+
public SocketWrapperBase<Nio2Channel> getSocket() {
return socket;
}
Modified: tomcat/trunk/java/org/apache/tomcat/util/net/Nio2Endpoint.java
URL:
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/net/Nio2Endpoint.java?rev=1684663&r1=1684662&r2=1684663&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/util/net/Nio2Endpoint.java (original)
+++ tomcat/trunk/java/org/apache/tomcat/util/net/Nio2Endpoint.java Wed Jun 10
12:45:26 2015
@@ -1660,7 +1660,9 @@ public class Nio2Endpoint extends Abstra
// Close socket and pool
closeSocket(socket);
if (running && !paused) {
- nioChannels.push(socket.getSocket());
+ if (!nioChannels.push(socket.getSocket())) {
+ socket.getSocket().free();
+ }
}
} else if (state == Handler.SocketState.LONG) {
if (socket.isAsync()) {
@@ -1673,7 +1675,9 @@ public class Nio2Endpoint extends Abstra
} else if (handshake == -1 ) {
closeSocket(socket);
if (running && !paused) {
- nioChannels.push(socket.getSocket());
+ if (!nioChannels.push(socket.getSocket())) {
+ socket.getSocket().free();
+ }
}
}
} catch (VirtualMachineError vme) {
Modified: tomcat/trunk/java/org/apache/tomcat/util/net/NioChannel.java
URL:
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/net/NioChannel.java?rev=1684663&r1=1684662&r2=1684663&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/util/net/NioChannel.java (original)
+++ tomcat/trunk/java/org/apache/tomcat/util/net/NioChannel.java Wed Jun 10
12:45:26 2015
@@ -66,6 +66,13 @@ public class NioChannel implements ByteC
/**
+ * Free the channel memory
+ */
+ public void free() {
+ bufHandler.free();
+ }
+
+ /**
* Returns true if the network buffer has been flushed out and is empty.
*
* @param block Unused. May be used when overridden
Modified: tomcat/trunk/java/org/apache/tomcat/util/net/NioEndpoint.java
URL:
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/net/NioEndpoint.java?rev=1684663&r1=1684662&r2=1684663&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/util/net/NioEndpoint.java (original)
+++ tomcat/trunk/java/org/apache/tomcat/util/net/NioEndpoint.java Wed Jun 10
12:45:26 2015
@@ -1536,7 +1536,9 @@ public class NioEndpoint extends Abstrac
// We do NOT want to do this more than
once - see BZ
// 57340.
if (running && !paused) {
- nioChannels.push(socket);
+ if (!nioChannels.push(socket)) {
+ socket.free();
+ }
}
socket = null;
}
@@ -1550,7 +1552,9 @@ public class NioEndpoint extends Abstrac
socket.getPoller().cancelledKey(key);
}
if (running && !paused) {
- nioChannels.push(socket);
+ if (!nioChannels.push(socket)) {
+ socket.free();
+ }
}
socket = null;
ka = null;
Modified: tomcat/trunk/java/org/apache/tomcat/util/net/SecureNio2Channel.java
URL:
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/net/SecureNio2Channel.java?rev=1684663&r1=1684662&r2=1684663&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/util/net/SecureNio2Channel.java
(original)
+++ tomcat/trunk/java/org/apache/tomcat/util/net/SecureNio2Channel.java Wed Jun
10 12:45:26 2015
@@ -122,6 +122,14 @@ public class SecureNio2Channel extends N
closing = false;
}
+ @Override
+ public void free() {
+ super.free();
+ if (endpoint.getSocketProperties().getDirectSslBuffer()) {
+ ByteBufferUtils.cleanDirectBuffer(netInBuffer);
+ ByteBufferUtils.cleanDirectBuffer(netOutBuffer);
+ }
+ }
private class FutureFlush implements Future<Boolean> {
private Future<Integer> integer;
Modified: tomcat/trunk/java/org/apache/tomcat/util/net/SecureNioChannel.java
URL:
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/net/SecureNioChannel.java?rev=1684663&r1=1684662&r2=1684663&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/util/net/SecureNioChannel.java
(original)
+++ tomcat/trunk/java/org/apache/tomcat/util/net/SecureNioChannel.java Wed Jun
10 12:45:26 2015
@@ -93,6 +93,14 @@ public class SecureNioChannel extends Ni
netInBuffer.clear();
}
+ @Override
+ public void free() {
+ super.free();
+ if (endpoint.getSocketProperties().getDirectSslBuffer()) {
+ ByteBufferUtils.cleanDirectBuffer(netInBuffer);
+ ByteBufferUtils.cleanDirectBuffer(netOutBuffer);
+ }
+ }
//===========================================================================================
// NIO SSL METHODS
Modified: tomcat/trunk/java/org/apache/tomcat/util/net/SocketBufferHandler.java
URL:
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/net/SocketBufferHandler.java?rev=1684663&r1=1684662&r2=1684663&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/util/net/SocketBufferHandler.java
(original)
+++ tomcat/trunk/java/org/apache/tomcat/util/net/SocketBufferHandler.java Wed
Jun 10 12:45:26 2015
@@ -28,9 +28,11 @@ public class SocketBufferHandler {
private volatile boolean writeBufferConfiguredForWrite = true;
private volatile ByteBuffer writeBuffer;
+ private final boolean direct;
public SocketBufferHandler(int readBufferSize, int writeBufferSize,
boolean direct) {
+ this.direct = direct;
if (direct) {
readBuffer = ByteBuffer.allocateDirect(readBufferSize);
writeBuffer = ByteBuffer.allocateDirect(writeBufferSize);
@@ -156,4 +158,12 @@ public class SocketBufferHandler {
configureWriteBufferForWrite();
writeBuffer = ByteBufferUtils.expand(writeBuffer, newSize);
}
+
+ public void free() {
+ if (direct) {
+ ByteBufferUtils.cleanDirectBuffer(readBuffer);
+ ByteBufferUtils.cleanDirectBuffer(writeBuffer);
+ }
+ }
+
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]