There is a possible JNI local-reference leak in the native implementation of NativeUnixSocket.poll().
File: junixsocket-native/src/main/c/polling.c
Function: Java_org_newsclub_net_unix_NativeUnixSocket_poll
Relevant code:
(*env)->GetIntArrayRegion(env, opsObj, 0, nfds, buf);
for(int i=0; i<nfds;i++) {
jobject fdObj = (*env)->GetObjectArrayElement(env, fdsObj, i);
struct pollfd *pfd = &pollFd[i];
if(fdObj) {
int fd = _getFD(env, fdObj);
pfd->fd = fd;
pfd->events = opToEvent(buf[i]);
} else {
pfd->fd = 0;
pfd->events = 0;
}
}
GetObjectArrayElement() returns a new local reference:
jobject fdObj = (*env)->GetObjectArrayElement(env, fdsObj, i);
The reference is only needed during the current loop iteration to read the native file descriptor:
int fd = _getFD(env, fdObj);
But the loop never calls DeleteLocalRef(fdObj). Those local references are eventually released when the native method returns, so this is not a cross-call leak. However, poll() can receive an array containing many FileDescriptor objects from the Java selector implementation. In that case, one local reference is accumulated for each descriptor during a single native call, which can exhaust the JNI local reference table for large selector sets.
This method is reached from the Java selector path:
num = NativeUnixSocket.poll(pfd, timeout);
and the PollFd object contains the FileDescriptor[] passed to native code:
final FileDescriptor[] fds;
Suggested fix: delete the local reference after _getFD() has consumed it:
jobject fdObj = (*env)->GetObjectArrayElement(env, fdsObj, i);
if(fdObj) {
int fd = _getFD(env, fdObj);
(*env)->DeleteLocalRef(env, fdObj);
pfd->fd = fd;
pfd->events = opToEvent(buf[i]);
} else {
pfd->fd = 0;
pfd->events = 0;
}
It would also be reasonable to handle a pending exception from GetObjectArrayElement() before continuing the loop.
There is a possible JNI local-reference leak in the native implementation of
NativeUnixSocket.poll().File:
junixsocket-native/src/main/c/polling.cFunction:
Java_org_newsclub_net_unix_NativeUnixSocket_pollRelevant code:
GetObjectArrayElement()returns a new local reference:The reference is only needed during the current loop iteration to read the native file descriptor:
But the loop never calls
DeleteLocalRef(fdObj). Those local references are eventually released when the native method returns, so this is not a cross-call leak. However,poll()can receive an array containing manyFileDescriptorobjects from the Java selector implementation. In that case, one local reference is accumulated for each descriptor during a single native call, which can exhaust the JNI local reference table for large selector sets.This method is reached from the Java selector path:
and the
PollFdobject contains theFileDescriptor[]passed to native code:Suggested fix: delete the local reference after
_getFD()has consumed it:It would also be reasonable to handle a pending exception from
GetObjectArrayElement()before continuing the loop.