1. Introducción
Cuando se trata de monitorear el uso de CPU, el estado de la memoria o el espacio en disco en Java, muchos programadores se preguntan: “¿Es necesario ejecutar comandos del sistema o utilizar JNI?”. ¡La respuesta es no! En este artículo, exploraremos cómo podemos utilizar OSHI (Operating System and Hardware Information), una biblioteca pura de Java que permite obtener detalles a nivel de sistema sin depender de ningún código nativo.
OSHI actúa como un puente entre nuestras aplicaciones Java y las API del sistema operativo, recolectando información útil sobre el sistema operativo, el hardware y la red de manera multiplataforma. Esta entrada está diseñada para ofrecer una visión integral sobre cómo configurar y utilizar OSHI para monitorizar el sistema en aplicaciones Java.
Más información sobre OSHI aquí.
2. ¿Por Qué Utilizar OSHI para Monitoreo del Sistema?
Es natural preguntarse: “¿Por qué no usar Runtime.exec()
o System.getProperty()
?”. Estas aproximaciones tienen limitaciones significativas. Mientras que System.getProperty()
puede obtener el nombre y versión del sistema operativo, Runtime.exec()
requiere comandos específicos del sistema, lo que lo hace intensivo en mantenimiento y menos portátil.
OSHI, por otro lado, funciona con los sistemas operativos más populares (Windows, macOS, Linux). Proporciona información detallada sobre la CPU, RAM, discos, sensores y redes sin necesidad de código nativo, es ligero y fácil de usar. Solo necesitamos agregar una dependencia a nuestro proyecto.
3. Características Clave y Ventajas
Con OSHI, podemos:
- Obtener detalles del sistema operativo: nombre, versión, arquitectura y tiempo de actividad.
- Monitorear el uso de la CPU, detalles del núcleo y velocidad del procesador.
- Obtener estadísticas de memoria: RAM total, memoria disponible, uso de intercambio.
- Recuperar información sobre el almacenamiento del disco: particiones, velocidad de lectura/escritura.
- Rastrear interfaces de red, direcciones IP y uso de ancho de banda.
- Acceder a datos de sensores como temperatura del CPU, velocidades de ventilador y voltajes (si está soportado).
Ahora, veamos cómo implementar estas características en nuestro proyecto.
4. Configuración de OSHI en un Proyecto Java
Agregando la Dependencia
Antes de comenzar, necesitamos agregar OSHI a nuestro proyecto. Si estamos utilizando Maven, debemos incluir la siguiente dependencia en nuestro pom.xml
:
<dependency>
<groupId>com.github.oshi</groupId>
<artifactId>oshi-core</artifactId>
<version>6.4.2</version>
</dependency>
Una vez agregada, ¡OSHI estará listo para usarse!
5. Recuperando Información Básica del Sistema
5.1. Obteniendo Detalles del Sistema Operativo
Imaginemos que queremos saber qué sistema operativo estamos utilizando, su versión y si es de 32 o 64 bits. Veamos cómo hacerlo fácilmente con OSHI:
@Test
void givenSystem_whenUsingOSHI_thenExtractOSDetails() {
SystemInfo si = new SystemInfo();
OperatingSystem os = si.getOperatingSystem();
assertNotNull(os, "El objeto del Sistema Operativo no debe ser nulo");
assertNotNull(os.getFamily(), "La familia del SO no debe ser nula");
assertNotNull(os.getVersionInfo(), "La información de la versión del SO no debe ser nula");
assertTrue(os.getBitness() == 32 || os.getBitness() == 64, "La arquitectura del SO debe ser 32 o 64 bits");
}
En este código, creamos un objeto SystemInfo
de la biblioteca OSHI para acceder a detalles relacionados con el sistema. Obtenemos la instancia de OperatingSystem
, que proporciona información sobre la familia del sistema operativo, la versión y la arquitectura.
5.2. Verificando el Tiempo de Actividad del Sistema
¿Alguna vez te has preguntado cuánto tiempo ha estado funcionando tu sistema sin reinicio? El tiempo de actividad del sistema nos lo dice:
@Test
void givenSystem_whenUsingOSHI_thenExtractSystemUptime() {
SystemInfo si = new SystemInfo();
OperatingSystem os = si.getOperatingSystem();
long uptime = os.getSystemUptime();
assertTrue(uptime >= 0, "El tiempo de actividad del sistema debe ser no negativo");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
fail("Prueba interrumpida");
}
long newUptime = os.getSystemUptime();
assertTrue(newUptime >= uptime, "El tiempo de actividad debe aumentar con el tiempo");
}
Aquí, recuperamos el tiempo de actividad del sistema y comprobamos que es no negativo, asegurando así un valor válido. Después, pausamos el hilo durante dos segundos y verificamos que el tiempo de actividad aumenta.
Si vemos un valor como 3600 segundos
, significa que nuestra máquina lleva encendida durante una hora.
6. Monitoreo de la CPU con OSHI
La CPU (Unidad Central de Procesamiento) es el corazón de cualquier sistema. Monitorear su uso, carga y número de núcleos es vital para la optimización del rendimiento.
6.1. Recuperando Detalles del Procesador
OSHI facilita la obtención del nombre de nuestro procesador, el conteo de núcleos y la velocidad de reloj usando Java:
@Test
void givenSystem_whenUsingOSHI_thenExtractCPUDetails() {
SystemInfo si = new SystemInfo();
CentralProcessor processor = si.getHardware().getProcessor();
assertNotNull(processor, "El objeto del procesador no debe ser nulo");
assertTrue(processor.getPhysicalProcessorCount() > 0, "La CPU debe tener al menos un núcleo físico");
assertTrue(processor.getLogicalProcessorCount() >= processor.getPhysicalProcessorCount(),
"Los núcleos lógicos deben ser mayores o iguales a los núcleos físicos");
}
Este test inicializa un objeto SystemInfo
de OSHI y recupera la instancia CentralProcessor
de la hardware del sistema. Proporciona detalles sobre el CPU, como el número de núcleos y métricas de carga.
6.2. Midiendo la Carga de la CPU Dinámicamente
Para comprobar la carga de nuestra CPU en un momento dado, podemos hacerlo fácilmente:
@Test
void givenSystem_whenUsingOSHI_thenExtractCPULoad() throws InterruptedException {
SystemInfo si = new SystemInfo();
CentralProcessor processor = si.getHardware().getProcessor();
long[] prevTicks = processor.getSystemCpuLoadTicks();
TimeUnit.SECONDS.sleep(1);
double cpuLoad = processor.getSystemCpuLoadBetweenTicks(prevTicks) * 100;
assertTrue(cpuLoad >= 0 && cpuLoad <= 100, "La carga de la CPU debe estar entre 0% y 100%");
}
El código captura los ticks de carga del CPU del sistema, espera un segundo y calcula el porcentaje de carga de CPU entre los ticks grabados. Finalmente, comprobamos que la carga de CPU se encuentra en el rango válido de 0% a 100%.
Una carga baja significa que el CPU está inactivo, mientras que un porcentaje alto indica una alta carga de trabajo.
7. Monitoreo de Memoria
La RAM (Memoria de Acceso Aleatorio) de nuestro sistema determina cuántas aplicaciones pueden ejecutarse simultáneamente.
7.1. Recuperando RAM Total y Disponible
Veamos cómo podemos recuperar la RAM total y disponible para nuestro sistema:
@Test
void givenSystem_whenUsingOSHI_thenExtractMemoryDetails() {
SystemInfo si = new SystemInfo();
GlobalMemory memory = si.getHardware().getMemory();
assertTrue(memory.getTotal() > 0, "La memoria total debe ser positiva");
assertTrue(memory.getAvailable() >= 0, "La memoria disponible no debe ser negativa");
assertTrue(memory.getAvailable() <= memory.getTotal(), "La memoria disponible no debe exceder la memoria total");
}
Este código inicializa un objeto SystemInfo
y obtiene la instancia GlobalMemory
, que proporciona información relacionada con la memoria. Aseguramos que la memoria total sea positiva y que la memoria disponible no sea negativa.
7.2. Información de Almacenamiento y Disco
Los discos duros y SSD almacenan todos nuestros datos. OSHI ayuda a monitorear el espacio total en disco, particiones y estadísticas de uso:
@Test
void givenSystem_whenUsingOSHI_thenExtractDiskDetails() {
SystemInfo si = new SystemInfo();
List<HWDiskStore> diskStores = si.getHardware().getDiskStores();
assertFalse(diskStores.isEmpty(), "Debe haber al menos un disco");
for (HWDiskStore disk : diskStores) {
assertNotNull(disk.getModel(), "El modelo del disco no debe ser nulo");
assertTrue(disk.getSize() >= 0, "El tamaño del disco debe ser no negativo");
}
}
El código recoge detalles del almacenamiento del disco usando OSHI y asegura que al menos un disco esté presente. Iteramos sobre cada disco, verificando que el modelo no sea nulo y que el tamaño sea no negativo, asegurando que OSHI detecte correctamente la información del disco.
8. Limitaciones de OSHI
Aunque OSHI es una herramienta rica en características, tiene algunas limitaciones:
- La disponibilidad de datos de sensores depende del soporte del hardware: No todas las máquinas exponen lecturas de temperatura o voltajes.
- Control limitado a bajo nivel: OSHI proporciona información de sistema en modo de solo lectura; no permite modificaciones del sistema.
- Dependencia de las API del sistema: Algunas informaciones pueden variar ligeramente entre sistemas operativos.
9. Conclusión
En este artículo, exploramos cómo OSHI es una poderosa y ligera biblioteca de Java para recuperar información del sistema y hardware. Elimina la necesidad de lidiar con comandos nativos del sistema, JNI o dependencias específicas de la plataforma, lo que la convierte en una excelente opción para desarrolladores que necesitan monitoreo de sistemas multiplataforma.
OSHI proporciona una solución simple y efectiva para cualquier desarrollador de Java que busque entender su entorno de ejecución y optimizar el rendimiento de sus aplicaciones. ¡Anímate a implementarlo en tu próximo proyecto!
Para más ejemplos y código, visita la página oficial de OSHI en GitHub.