First of all, we need to get the java.net.Socket file descriptor. This can be done using the reflection mechanism. The idea is to access the java.io.FileDescriptor in java.net.SocketImpl and then get your own socket descriptor. See DualStackPlainSocketImpl.java for code snippets (this method is also specified by Zoran Regvart here ).
Another method is to use JNI, as discussed here , here is an example:
static int getFd(JNIEnv *env, jobject sock) { JNIEnv e = *env; jclass clazz; jfieldID fid; jobject impl; jobject fdesc; if (!(clazz = e->GetObjectClass(env,sock)) || !(fid = e->GetFieldID(env,clazz,"impl","Ljava/net/SocketImpl;")) || !(impl = e->GetObjectField(env,sock,fid))) return -1; if (!(clazz = e->GetObjectClass(env,impl)) || !(fid = e->GetFieldID(env,clazz,"fd","Ljava/io/FileDescriptor;")) || !(fdesc = e->GetObjectField(env,impl,fid))) return -1; if (!(clazz = e->GetObjectClass(env,fdesc)) || !(fid = e->GetFieldID(env,clazz,"fd","I"))) return -1; return e->GetIntField(env,fdesc,fid); }
I also assume that you are talking about Boost.Asio TCP socket. If so, then you need to associate the native socket with the Asio socket object using the assign method.
Remember that this solution may not work for some Java implementations, as it uses internal implementation details that do not guarantee that they will remain the same. Also, make sure there is no concurrency (i.e. Java is not trying to read the same socket descriptor in parallel), etc. In other words - use at your own risk.
Hope this helps. Good luck
user405725
source share