Aller au contenu

JMX : Java Management eXtensions

C’est quoi ?

JMX est un framework de gestion de la technologie qui permet de surveiller et de gérer des applications Java à distance.

On définit des beans de gestion appelés *MBeans (pour Management Bean) qui donnent accès à :

Ensuite, par l’intermédiaire d’un client JMX, on accéde à ces informations et fonctionnalités à distance. Cela permet de surveiller et de gérer votre application de manière centralisée.

A quoi ça sert ?

Vous pouvez donner accès aux informations suivantes :

JMX peut être particulièrement utile dans les environnements de production pour surveiller et diagnostiquer les problèmes de performance et de stabilité.

comment l’utiliser avec SpringBoot ?

Créer un serveur JMX

Il faut créer un serveur JMX pour donner accès à vos MBeans via un serveur RMI (Remote Method Invocation). Il suffit ensuite d’utiliser un client JMX pour y accèder à distance via RMI.

Voici ci-dessous un exemple d’implémentation de JMX avec SpringBoot :

Exemple de code :

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jmx.support.ConnectorServerFactoryBean;
import org.springframework.remoting.rmi.RmiRegistryFactoryBean;

@Configuration
public class JmxConfiguration {

    @Bean
    public RmiRegistryFactoryBean rmiRegistry() {
        final RmiRegistryFactoryBean rmiRegistryFactoryBean = new RmiRegistryFactoryBean();
        rmiRegistryFactoryBean.setPort(1099); // port d'écoute
        return rmiRegistryFactoryBean;
    }

    @Bean
    public ConnectorServerFactoryBean connectorServerFactoryBean() throws Exception {
        final ConnectorServerFactoryBean connectorServerFactoryBean = new ConnectorServerFactoryBean();
        connectorServerFactoryBean.setObjectName("connector:name=rmi");
        connectorServerFactoryBean.setServiceUrl("service:jmx:rmi://localhost/jndi/rmi://localhost:1099/jmxrmi");
        return connectorServerFactoryBean;
    }
}

Pour exposer vos MBeans avec Spring Boot, vous pouvez utiliser l’annotation @ManagedResource sur vos beans de gestion. Ce bean ci-dessous sera alors publié sur votre serveur JMX et vous pourrez accéder à ses informations et fonctionnalités à distance.

En fait, on associe plusieurs technologies pour arriver à ce résultat.

import org.springframework.jmx.export.annotation.ManagedResource;

@ManagedResource
public class MyService {
    // ...
}

Créer un client JMX

Le code ci-dessous permet de se connecter à notre serveur JMX sur l’URL spécifiée et imprime la liste des MBeans publiés sur le serveur. Pour commencer, c’est pratique !

Vous pouvez ensuite utiliser les méthodes de l’interface MBeanServerConnection pour accéder aux informations et aux fonctionnalités des MBeans.

Utilisez :

import java.io.IOException;
import java.util.Set;

import javax.management.MBeanServerConnection;
import javax.management.ObjectName;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;

public class JmxClient {

    public static void main(String[] args) throws IOException {
        // Créez une URL de service JMX pour vous connecter au serveur JMX
        JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://localhost:1099/jmxrmi");

        // Créez un connecteur JMX et connectez-vous au serveur
        JMXConnector jmxConnector = JMXConnectorFactory.connect(url);
        MBeanServerConnection connection = jmxConnector.getMBeanServerConnection();

        // Obtenez la liste des MBeans publiés sur le serveur
        Set<ObjectName> mbeans = connection.queryNames(null, null);
        for (ObjectName mbean : mbeans) {
            System.out.println(mbean);
        }

        // Fermez le connecteur
        jmxConnector.close();
    }
}

Accès aux informations de configuration de SpringBoot

Vous avez de la chance car Spring Boot expose automatiquement certaines informations de configuration et de la jvm via JMX.

Pour accéder aux informations de configuration de votre application Spring Boot via JMX, vous pouvez utiliser l’MBean org.springframework.boot:type=Admin,name=SpringApplication. Ce MBean expose les propriétés de configuration de votre application sous forme d’attributs.

Par exemple, vous pouvez utiliser getAttribute(objectName, “spring.application.name”) pour lire le nom de votre application.

Exemple de code pour lire les propriétés de configuration de votre application SpringBoot avec un client JMX :

import javax.management.MBeanServerConnection;
import javax.management.ObjectName;

public class ConfigurationPrinter {

    public static void printConfiguration(MBeanServerConnection connection) throws Exception {
        ObjectName objectName = new ObjectName("org.springframework.boot:type=Admin,name=SpringApplication");
        String[] propertyNames = (String[]) connection.getAttribute(objectName, "propertyNames");
        for (String propertyName : propertyNames) {
            Object propertyValue = connection.getAttribute(objectName, propertyName);
            System.out.println(propertyName + " = " + propertyValue);
        }
    }
}

Autre exemple :

Accédez aux informations de jvm de votre application en utilisant le MBean java.lang:type=Memory. Ce dernier donne des informations sur l’utilisation de la mémoire de votre jvm sous forme d’attributs.

Par exemple, vous pouvez utiliser cette écriture pour y accéder : getAttribute(objectName, “HeapMemoryUsage”). Vous obtenez alors l’utilisation de la mémoire heap de votre jvm.

Exemple de code pour lire les informations de jvm :

import javax.management.MBeanServerConnection;
import javax.management.ObjectName;
import javax.management.openmbean.CompositeData;

public class JvmInfoPrinter {

    public static void printJvmInfo(MBeanServerConnection connection) throws Exception {
        ObjectName objectName = new ObjectName("java.lang:type=Memory");
        CompositeData heapMemoryUsage = (CompositeData) connection.getAttribute(objectName, "HeapMemoryUsage");
        long used = (long) heapMemoryUsage.get("used");
        long max = (long) heapMemoryUsage.get("max");
        System.out.println("Heap memory usage: " + used + " / " + max);
    }
}

Conclusion

Ce n’est pas si compliquer, il faut juste lire la documentation et savoir ce que vous voulez rendre accessible comme informations. Je me souviens que les informations du serveur J2EE JBoss permettait l’accès à de nombreux MBeans car au serveur JMX intégré.

De toute façon, avec Spring ou SpringBoot ça devient plus simple !