diff --git a/pom.xml b/pom.xml index a9fe139..b89df2d 100644 --- a/pom.xml +++ b/pom.xml @@ -36,19 +36,19 @@ - asm + org.ow2.asm asm - 3.3 + 9.2 commons-logging commons-logging - 1.0.3 + 1.2 log4j log4j - 1.2.15 + 1.2.17 javax.jms @@ -93,7 +93,7 @@ - + @@ -104,8 +104,9 @@ - diff --git a/src/one/nio/net/SelectableJavaSocket.java b/src/one/nio/net/SelectableJavaSocket.java index 34ec242..13c357d 100644 --- a/src/one/nio/net/SelectableJavaSocket.java +++ b/src/one/nio/net/SelectableJavaSocket.java @@ -17,47 +17,63 @@ package one.nio.net; import one.nio.util.JavaInternals; -import sun.nio.ch.Net; -import sun.nio.ch.SelChImpl; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; import java.io.FileDescriptor; import java.io.IOException; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; +import java.lang.reflect.Field; import java.lang.reflect.Method; import java.net.SocketTimeoutException; import java.nio.channels.SelectableChannel; +import static one.nio.util.JavaInternals.unsafe; + /** * @author ivan.grigoryev */ public abstract class SelectableJavaSocket extends Socket { - private static final MethodHandle poll = getPollMethodHandle(); + private static final Log log = LogFactory.getLog(SelectableJavaSocket.class); + + private static final MethodHandle poll = getMethodHandle("sun.nio.ch.Net", "poll", FileDescriptor.class, int.class, long.class); + private static final MethodHandle getFD = getMethodHandle("sun.nio.ch.SelChImpl", "getFD"); - private static MethodHandle getPollMethodHandle() { + static final int POLL_READ = getFieldValue("sun.nio.ch.Net", "POLLIN"); + static final int POLL_WRITE = getFieldValue("sun.nio.ch.Net", "POLLOUT"); + + private static MethodHandle getMethodHandle(String cls, String name, Class... params) { try { - Method m = JavaInternals.getMethod(Net.class, "poll", FileDescriptor.class, int.class, long.class); - if (m != null) { - return MethodHandles.publicLookup().unreflect(m); - } + Method m = Class.forName(cls).getDeclaredMethod(name, params); + JavaInternals.setAccessible(m); + return MethodHandles.publicLookup().unreflect(m); } catch (Throwable e) { - // ignore + log.debug("Failed to access sun.nio.ch API", e); } return null; } - static final int POLL_READ = Net.POLLIN; - static final int POLL_WRITE = Net.POLLOUT; + private static int getFieldValue(String cls, String name) { + try { + Field f = Class.forName(cls).getDeclaredField(name); + return unsafe.getShort(unsafe.staticFieldBase(f), unsafe.staticFieldOffset(f)); + } catch (Throwable e) { + log.debug("Failed to access sun.nio.ch API", e); + return 0; + } + } void checkTimeout(int events, long timeout) throws IOException { - if (timeout <= 0 || poll == null) { + if (timeout <= 0 || poll == null || getFD == null) { return; } try { long endTime = System.currentTimeMillis() + timeout; do { - int result = (int) poll.invokeExact(((SelChImpl) getSelectableChannel()).getFD(), events, timeout); + FileDescriptor fd = (FileDescriptor) getFD.invoke(getSelectableChannel()); + int result = (int) poll.invokeExact(fd, events, timeout); if (result > 0) { return; } diff --git a/test/one/nio/net/SocketTest.java b/test/one/nio/net/SocketTest.java index a73ba0f..fbd16b1 100755 --- a/test/one/nio/net/SocketTest.java +++ b/test/one/nio/net/SocketTest.java @@ -29,7 +29,7 @@ private static void testIPv4() throws IOException { Socket s = Socket.create(); s.setTimeout(3000); - s.connect("www.ru", 80); + s.connect("google.com", 80); System.out.println("connected from " + s.getLocalAddress() + " to " + s.getRemoteAddress()); s.close(); } @@ -38,7 +38,7 @@ private static void testIPv6() throws IOException { Socket s = Socket.create(); s.setTimeout(3000); - s.connect("::1", 22); + s.connect("2a00:1450:4010:c07::71", 80); System.out.println("connected from " + s.getLocalAddress() + " to " + s.getRemoteAddress()); byte[] b = new byte[1000];