JMX(Java Management Extensions)
JMX(Java Management eXtensions)는 응용 프로그램(소프트웨어)/객체/장치 (프린터 등) 및 서비스 지향 네트워크 등을 감시 관리를 위한 도구를 제공하는 자바 API이다.
JDK 1.5 이상부터 기본적으로 탑재된 기능 자바 어플리케이션의 모니터링과 관리 기능을 제공한다. Non-Java Resource와 하드웨어에 대해 wrapping한 인터페이스를 제공하며, API를 외부로 노출해 application 설정 및 통계데이터를 수집할 수 있는 기능을 제공한다.
mBean으로 알려진 하나 이상의 사용자 JavaBean 오브젝트를 통해(혹은 리소스를 호출하는) 애플리케이션, 디바이스, 서비스를 원격으로 제어할 수 있다.
mBean들은 mBean 서버에 등록되며, mBean 서버는 리소스에 접근하는 모든 원격 매니저를 관리한다.
- MBean(Managed Bean) 플랫폼 혹은 사용자에 의해 만들어진 모니터링용 객체.
- Standard MBean, Dynamic MBean, Model MBean, Open MBean 4가지 종류로 나뉨
- MBean Server : MBean을 등록. MBeans를 모니터링하기 원하는 원격 JMX 관리자는 MBean Server를 통하여 정보를 획득
- agent service : MBeans를 관리하는 (개발자가 제작한) 서비스 - client
MXBean( Managed Extended Bean )은 Java Management Extensions (JMX)의 일부로, JMX 프로토콜을 사용합니다. JMX 프로토콜은 Java 애플리케이션에서 모니터링 및 관리를 위한 표준화된 방법을 제공합니다.

RMI(Remote Method Invocation)는 기본적으로 TCP/IP 프로토콜을 사용하여 통신합니다. RMI는 자바에서 분산 객체 호출을 처리하는 메커니즘으로, 원격 서버에서 객체의 메서드를 로컬 객체처럼 호출할 수 있도록 해줍니다.
RMI의 통신 방식은 다음과 같습니다
1. 객체 전송: RMI는 원격 객체의 메서드를 호출하기 위해 네트워크를 통해 객체와 데이터를 전송합니다. 이 과정에서 기본적으로 TCP/IP를 사용하여 데이터가 송수신됩니다.
2. RMI 레지스트리: RMI는 "RMI 레지스트리"라는 서비스를 통해 원격 객체를 찾습니다. 클라이언트가 원격 객체를 호출하려면 먼저 RMI 레지스트리에서 객체를 조회한 후, TCP/IP 프로토콜을 통해 원격 객체와의 연결을 설정합니다.
3.RMI 통신: 원격 객체의 메서드를 호출할 때, 호출은 TCP/IP 네트워크를 통해 전달됩니다. Java RMI는 내부적으로 TCP/IP 기반의 소켓을 이용해 객체와 메서드 호출 정보를 전송하고, 그 결과를 클라이언트로 되돌려 보냅니다.
JMX 프로토콜은 RMI (Remote Method Invocation) 프로토콜을 기반으로 하며, 원격으로 JMX MBean을 연결하고 접근할 수 있도록 합니다. RMI는 자바 애플리케이션 간에 객체를 직접 주고받을 수 있도록 해주는 기술입니다.
따라서, MXBean은 RMI 프로토콜을 사용하여 JMX 서버와 클라이언트 사이의 통신을 처리하며, 자바 애플리케이션 간에 객체를 주고받을 수 있도록 합니다.
클래스명: BeanObj
인터페이스: BeanObjMXBean
이 쌍이 있어야 JMX가 자동으로 “이건 MXBean이다”라고 인식함.
package org.example;
public interface BeanObjMXBean {
String getMessage();
void setMessage(String message);
}
package org.example;
import javax.management.*;
import java.util.concurrent.atomic.AtomicLong;
public class BeanObj extends NotificationBroadcasterSupport
implements BeanObjMXBean {
private String message = "init";
private final AtomicLong seq = new AtomicLong(1);
@Override
public synchronized void setMessage(String message) {
Notification n = new AttributeChangeNotification(
this,
seq.getAndIncrement(),
System.currentTimeMillis(),
"message changed",
"Message",
"java.lang.String",
this.message,
message
);
this.message = message;
sendNotification(n); // 🔔 이벤트 발생
}
@Override
public synchronized String getMessage() {
return message;
}
}
public class MyMXBeanImpl implements MyMXBean {
private String message;
@Override
public void setMessage(String msg) {
message = msg;
}
@Override
public String getMessage() {
return message;
}
}
package org.example;
import javax.management.AttributeChangeNotification;
import javax.management.MBeanServer;
import javax.management.ObjectName;
import javax.management.remote.JMXConnectorServer;
import javax.management.remote.JMXConnectorServerFactory;
import javax.management.remote.JMXServiceURL;
import java.lang.management.ManagementFactory;
import java.nio.charset.StandardCharsets;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
public class MxBeanServer {
public static void main(String[] args) throws Exception {
// MBeanServer 생성
MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
// JMX 커넥터 생성
String host = "127.0.0.1"; // 서버 IP 주소
int port = 9999; // 서버 포트 번호
// Rmi registry에 서버 IP, port를 설정한다.
Registry registry = LocateRegistry.createRegistry(port);
JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://" + host + ":" + port + "/server");
JMXConnectorServer connector = JMXConnectorServerFactory.newJMXConnectorServer(url, null, mbs);
// 커넥터 시작
connector.start();
// MBean 등록
ObjectName mxbeanName = new ObjectName("jmx:type=MXBean");
BeanObj mxbean = new BeanObj();
mbs.registerMBean(mxbean, mxbeanName);
// 클라이언트 요청 대기
System.out.println("MXBean Server started, waiting for client requests...");
// 🔔 변경 감지 리스너
mbs.addNotificationListener(mxbeanName, (notification, handback) -> {
if (notification instanceof AttributeChangeNotification acn) {
System.out.println("MXBean 변경됨!");
System.out.println("ATTR: " + acn.getAttributeName());
System.out.println("OLD VALUE: " + acn.getOldValue());
System.out.println("NEW VALUE: " + acn.getNewValue());
}
}, null, null);
Thread.sleep(Long.MAX_VALUE);
}
}
package org.example;
import javax.management.JMX;
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 MxBeanClient {
public static void main(String[] args) throws Exception {
String host = "localhost"; // 서버 IP 주소
int port = 9999; // 서버 포트 번호
JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://" + host + ":" + port + "/server");
JMXConnector jmxc = JMXConnectorFactory.connect(url, null);
MBeanServerConnection mBeanServerConnection = jmxc.getMBeanServerConnection();
ObjectName mxbeanname = new ObjectName("jmx:type=MXBean");
BeanObjMXBean bean = JMX.newMXBeanProxy(mBeanServerConnection, mxbeanname, BeanObjMXBean.class);
bean.setMessage("hello");
jmxc.close();
}
}
Jolokia
Jolokia는 JMX MBean을 HTTP/JSON 기반 REST API로 노출하는 에이전트이다.
이를 통해 JMX를 RMI 대신 HTTP로 접근할 수 있어, 방화벽·NAT·보안 설정이 단순해진다.
public class MyMXBeanClient {
public static void main(String[] args) throws Exception {
// Jolokia Client 생성
String host = "localhost"; // 서버 IP 주소
int port = 8080; // 서버 포트 번호
System.out.println(new URL("http", host, port, "").toString());
J4pClient j4pClient = new J4pClient(new URL("http", host, port, "").toString());
// MXBean 데이터 조회
J4pReadRequest request = new J4pReadRequest("com.app.woo.jmx:type=MyMXBean", "Message");
J4pReadResponse response = j4pClient.execute(request);
// JSON 데이터 파싱
Object value = response.getValue();
if (value instanceof JSONObject) {
JSONObject jsonObject = (JSONObject)value;
String message = (String)jsonObject.get("Message");
System.out.println("Message: " + message);
}
}
}
dependencies {
implementation 'org.jolokia:jolokia-core:1.7.1'
implementation 'org.jolokia:jolokia-jvm:1.7.1'
}
https://ko.wikipedia.org/wiki/JMX
'WEB개발 > JAVA' 카테고리의 다른 글
| [JAVA - NIO] Netty (0) | 2024.03.28 |
|---|---|
| [JAVA] 메모리 스택, 힙 (0) | 2022.10.31 |
| [JAVA] Thread-Safe, Concurrent Collection class, Double Checked Locking (0) | 2021.09.23 |
| 객체 직렬화 serialization, IOStream (0) | 2021.08.25 |
| [JAVA] AtomicInteger (thread-safe) (0) | 2021.08.13 |