verificar internet instalado control comprobar como chrome activar java sockets monitoring netty

internet - panel de control de java



Averiguar qué conectores de red están abiertos en la máquina virtual Java actual (2)

No lo he probado yo mismo, pero el boletín JavaSpecialists presenta un problema similar:

http://www.javaspecialists.eu/archive/Issue169.html

En la parte inferior, describe un enfoque utilizando AspectJ. Probablemente podrías poner el punto de corte alrededor del constructor que crea el socket y tener un código que registre la creación del socket allí.

Estoy escribiendo una prueba de extremo a extremo en la que mi programa Java lanza todos sus recursos: subprocesos, sockets de servidor, sockets de clientes. Es una biblioteca, por lo que liberar recursos al salir de la JVM no es una opción. Probar la liberación de subprocesos fue fácil, porque puede solicitar un ThreadGroup para todos los subprocesos, pero todavía no he encontrado una buena manera de obtener una lista de todos los sockets de red que está utilizando la JVM actual.

¿Hay alguna forma de obtener de una JVM la lista de todos los sockets de clientes y servidores, similar a netstat? Estoy usando Netty con OIO (es decir, java.net.ServerSocket y java.net.Socket ) en Java 7. La solución necesita funcionar tanto en Windows como en Linux.

Mi primera preferencia sería preguntarlo desde la JVM usando Java puro. Traté de buscar un MX Bean o similar, pero no encontré ninguno.

Otra opción podría ser conectarse a las API de perfilado / depuración de la JVM y solicitar todas las instancias de Socket y ServerSocket, pero no sé cómo hacerlo y si se puede hacer sin código nativo (AFAIK, JVMTI es solo nativo ) Además, no debe hacer que las pruebas sean lentas (incluso mi prueba más lenta de extremo a extremo es de solo 0.5 segundos, lo que incluye comenzar otro proceso de JVM).

Si la interrogación de la JVM no funciona, una tercera opción sería crear un diseño que rastree todos los sockets a medida que se crean. Esto tiene la desventaja de tener la posibilidad de perder un lugar donde se crean los enchufes. Como estoy usando Netty, parece implementable al envolver ChannelFactory y usar un ChannelGroup .


Pude conectarme a java.net.Socket y java.net.ServerSocket y espiar todas las instancias nuevas de esas clases. El código completo se puede ver en el repositorio fuente . Aquí hay una descripción general del enfoque:

Cuando se crea una instancia de un Socket o ServerSocket, lo primero en su constructor es una llamada a setImpl() que ejemplifica el objeto que realmente implementa la funcionalidad del socket. La implementación predeterminada es una instancia de java.net.SocksSocketImpl , pero es posible sobrescribirlo configurando una java.net.SocketImplFactory personalizada mediante java.net.Socket#setSocketImplFactory y java.net.ServerSocket#setSocketFactory .

Esto es un poco complicado para todas las implementaciones de java.net.SocketImpl ser paquetes privados, pero con un poco de reflexión no es demasiado difícil:

private static SocketImpl newSocketImpl() { try { Class<?> defaultSocketImpl = Class.forName("java.net.SocksSocketImpl"); Constructor<?> constructor = defaultSocketImpl.getDeclaredConstructor(); constructor.setAccessible(true); return (SocketImpl) constructor.newInstance(); } catch (Exception e) { throw new RuntimeException(e); } }

La implementación de SocketImplFactory para espiar en todos los sockets a medida que se crean se parece a esto:

final List<SocketImpl> allSockets = Collections.synchronizedList(new ArrayList<SocketImpl>()); ServerSocket.setSocketFactory(new SocketImplFactory() { public SocketImpl createSocketImpl() { SocketImpl socket = newSocketImpl(); allSockets.add(socket); return socket; } });

Tenga en cuenta que setSocketFactory / setSocketImplFactory solo se puede llamar una vez, por lo que solo necesita tener una prueba que lo haga (como yo lo tengo), o debe crear un singleton estático (yuck!) Para mantener ese espía.

Entonces, la pregunta es ¿cómo averiguar si el socket está cerrado? Tanto Socket como ServerSocket tienen un método isClosed() , pero que usa un booleano interno para esas clases para mantener un registro de si se cerró: la instancia de SocketImpl no tiene una manera fácil de verificar si se cerró. (Por cierto, tanto SocketImpl como SocketImpl están respaldados por SocketImpl - no hay "ServerSocketImpl").

Afortunadamente, SocketImpl tiene una referencia al Socket o ServerSocket que está respaldando. El método setImpl() mencionado setImpl() llama a impl.setSocket(this) o impl.setServerSocket(this) , y es posible recuperar esa referencia llamando a java.net.SocketImpl#getSocket o java.net.SocketImpl#getServerSocket .

Una vez más, esos métodos son privados del paquete, por lo que se necesita un poco de reflexión:

private static Socket getSocket(SocketImpl impl) { try { Method getSocket = SocketImpl.class.getDeclaredMethod("getSocket"); getSocket.setAccessible(true); return (Socket) getSocket.invoke(impl); } catch (Exception e) { throw new RuntimeException(e); } } private static ServerSocket getServerSocket(SocketImpl impl) { try { Method getServerSocket = SocketImpl.class.getDeclaredMethod("getServerSocket"); getServerSocket.setAccessible(true); return (ServerSocket) getServerSocket.invoke(impl); } catch (Exception e) { throw new RuntimeException(e); } }

Tenga en cuenta que getSocket / getServerSocket no se puede llamar dentro de SocketImplFactory, porque Socket / ServerSocket solo los establece después de que se devuelva SocketImpl desde allí.

Ahora existe toda la infraestructura necesaria para comprobar en nuestras pruebas lo que queramos sobre Socket / ServerSocket:

for (SocketImpl impl : allSockets) { assertIsClosed(getSocket(impl)); }

El código fuente completo está aquí .