javax.management 包是 Java Management Extensions (JMX) 技术的核心部分,用于实现应用程序、系统对象和服务的监控和管理。
MBeans(管理 Beans) - 暴露管理接口的可管理对象
MBean Server - MBeans 的注册表和访问点
JMX Agent - 提供管理服务的组件
通知模型 - 事件通知机制
MBeanServer - MBean 服务器接口
ObjectName - MBean 的唯一标识符
StandardMBean - 标准 MBean 实现
Notification - 通知事件
Attribute - MBean 属性
// GameMBean.java
public interface GameMBean {
// 属性
String getGameName();
void setGameName(String gameName);
int getPlayerCount();
// 操作
void startGame();
void addPlayer(String playerName);
String[] getPlayers();
String displayGameInfo();
}// Game.java
import java.util.ArrayList;
import java.util.List;
public class Game implements GameMBean {
private String gameName;
private List<String> players;
private boolean gameStarted;
public Game(String gameName) {
this.gameName = gameName;
this.players = new ArrayList<>();
this.gameStarted = false;
}
@Override
public String getGameName() {
return gameName;
}
@Override
public void setGameName(String gameName) {
this.gameName = gameName;
}
@Override
public int getPlayerCount() {
return players.size();
}
@Override
public void startGame() {
gameStarted = true;
System.out.println("游戏 " + gameName + " 已开始!");
}
@Override
public void addPlayer(String playerName) {
players.add(playerName);
System.out.println("玩家 " + playerName + " 已加入游戏");
}
@Override
public String[] getPlayers() {
return players.toArray(new String[0]);
}
@Override
public String displayGameInfo() {
return String.format("游戏: %s, 玩家数: %d, 状态: %s",
gameName, players.size(), gameStarted ? "进行中" : "未开始");
}
}// JMXAgent.java
import javax.management.*;
import java.lang.management.ManagementFactory;
public class JMXAgent {
public static void main(String[] args) throws Exception {
// 获取平台 MBeanServer
MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
// 创建 MBean 对象名
ObjectName objectName = new ObjectName("com.example:type=Game,name=AdventureGame");
// 创建并注册 MBean
Game gameMBean = new Game("冒险游戏");
mbs.registerMBean(gameMBean, objectName);
System.out.println("JMX Agent 已启动...");
System.out.println("使用 JConsole 连接到此进程进行管理");
// 模拟一些操作
performOperations(gameMBean);
// 保持程序运行
Thread.sleep(Long.MAX_VALUE);
}
private static void performOperations(Game game) throws InterruptedException {
Thread.sleep(2000);
game.addPlayer("玩家1");
Thread.sleep(2000);
game.addPlayer("玩家2");
Thread.sleep(2000);
game.startGame();
}
}// DynamicGameMBean.java
import javax.management.*;
public class DynamicGameMBean implements DynamicMBean {
private String gameName = "动态游戏";
private int playerCount = 0;
@Override
public Object getAttribute(String attribute) throws AttributeNotFoundException {
switch (attribute) {
case "GameName":
return gameName;
case "PlayerCount":
return playerCount;
default:
throw new AttributeNotFoundException("属性未找到: " + attribute);
}
}
@Override
public void setAttribute(Attribute attribute) throws InvalidAttributeValueException {
String name = attribute.getName();
Object value = attribute.getValue();
switch (name) {
case "GameName":
if (value instanceof String) {
gameName = (String) value;
}
break;
case "PlayerCount":
if (value instanceof Integer) {
playerCount = (Integer) value;
}
break;
}
}
@Override
public AttributeList getAttributes(String[] attributes) {
AttributeList list = new AttributeList();
for (String attribute : attributes) {
try {
list.add(new Attribute(attribute, getAttribute(attribute)));
} catch (Exception e) {
// 忽略错误
}
}
return list;
}
@Override
public AttributeList setAttributes(AttributeList attributes) {
AttributeList result = new AttributeList();
for (Object attribute : attributes) {
Attribute attr = (Attribute) attribute;
try {
setAttribute(attr);
result.add(new Attribute(attr.getName(), getAttribute(attr.getName())));
} catch (Exception e) {
// 忽略错误
}
}
return result;
}
@Override
public Object invoke(String actionName, Object[] params, String[] signature)
throws MBeanException, ReflectionException {
if ("addPlayer".equals(actionName)) {
playerCount++;
return "玩家已添加,当前玩家数: " + playerCount;
} else if ("getGameInfo".equals(actionName)) {
return "游戏: " + gameName + ", 玩家数: " + playerCount;
}
throw new UnsupportedOperationException("操作不支持: " + actionName);
}
@Override
public MBeanInfo getMBeanInfo() {
MBeanAttributeInfo[] attributes = new MBeanAttributeInfo[] {
new MBeanAttributeInfo("GameName", "java.lang.String", "游戏名称", true, true, false),
new MBeanAttributeInfo("PlayerCount", "int", "玩家数量", true, false, false)
};
MBeanOperationInfo[] operations = new MBeanOperationInfo[] {
new MBeanOperationInfo("addPlayer", "添加玩家", null, "java.lang.String", MBeanOperationInfo.ACTION),
new MBeanOperationInfo("getGameInfo", "获取游戏信息", null, "java.lang.String", MBeanOperationInfo.INFO)
};
return new MBeanInfo(this.getClass().getName(), "动态游戏MBean",
attributes, null, operations, null);
}
}// GameWithNotification.java
import javax.management.*;
public class GameWithNotification extends NotificationBroadcasterSupport implements GameMBean {
private String gameName;
private int sequenceNumber = 1;
public GameWithNotification(String gameName) {
this.gameName = gameName;
}
@Override
public String getGameName() {
return gameName;
}
@Override
public void setGameName(String gameName) {
String oldName = this.gameName;
this.gameName = gameName;
// 发送属性变更通知
Notification notification = new AttributeChangeNotification(
this,
sequenceNumber++,
System.currentTimeMillis(),
"游戏名称已变更",
"GameName",
"String",
oldName,
gameName
);
sendNotification(notification);
}
@Override
public int getPlayerCount() {
return 0;
}
@Override
public void startGame() {
// 发送游戏开始通知
Notification notification = new Notification(
"game.started",
this,
sequenceNumber++,
System.currentTimeMillis(),
"游戏 " + gameName + " 已开始!"
);
sendNotification(notification);
}
@Override
public void addPlayer(String playerName) {
// 发送玩家加入通知
Notification notification = new Notification(
"player.joined",
this,
sequenceNumber++,
System.currentTimeMillis(),
"玩家 " + playerName + " 已加入游戏"
);
notification.setUserData(playerName);
sendNotification(notification);
}
@Override
public String[] getPlayers() {
return new String[0];
}
@Override
public String displayGameInfo() {
return "游戏: " + gameName;
}
}1、编译和运行:
javac *.java
java -Dcom.sun.management.jmxremote.port=9999 \
-Dcom.sun.management.jmxremote.authenticate=false \
-Dcom.sun.management.jmxremote.ssl=false \
JMXAgent2、使用 JConsole 连接:
启动 JConsole:jconsole
连接到本地进程或远程进程(localhost:9999)
在 MBeans 标签页中查看和管理注册的 MBeans
1、标准化管理:提供统一的管理接口
2、远程管理:支持远程监控和管理
3、动态性:可以动态添加和移除管理组件
4、集成性:与各种管理工具(如 JConsole)无缝集成