Java 8环境下获取GCInfo方法及Minecraft服务器/gcinfo命令实现
解决方案:Minecraft服务器/gcinfo命令获取最近GC信息(兼容Java8)
针对你遇到的Java7 GC代码在Java8无法运行,且需要实现Minecraft服务器的/gcinfo命令来触发查询最近一次GC详细信息的需求,这里提供一个不需要监听器、基于JVM标准管理API的兼容实现:
核心实现思路
Java8中可以通过JDK自带的java.lang.management包提供的标准MXBean来获取GC信息,完全替代Java7中可能依赖的非公开API,同时不需要注册GC监听器,只在命令触发时查询最新数据。
完整命令代码实现
import org.bukkit.command.Command; import org.bukkit.command.CommandExecutor; import org.bukkit.command.CommandSender; import java.lang.management.GarbageCollectorMXBean; import java.lang.management.ManagementFactory; import java.lang.management.MemoryMXBean; import java.lang.management.GcInfo; import java.util.List; import java.util.Map; public class GCInfoCommand implements CommandExecutor { @Override public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) { if (!cmd.getName().equalsIgnoreCase("gcinfo")) { return false; } // 获取JVM内存管理Bean MemoryMXBean memoryBean = ManagementFactory.getMemoryMXBean(); List<GarbageCollectorMXBean> gcBeans = ManagementFactory.getGarbageCollectorMXBeans(); // 筛选出记录了最近GC信息的收集器(覆盖多收集器场景) GcInfo latestGcInfo = null; for (GarbageCollectorMXBean bean : gcBeans) { GcInfo currentInfo = bean.getLastGcInfo(); if (currentInfo != null && (latestGcInfo == null || currentInfo.getStartTime() > latestGcInfo.getStartTime())) { latestGcInfo = currentInfo; } } if (latestGcInfo == null) { sender.sendMessage("§c未查询到最近一次GC的记录,请检查JVM配置是否开启GC信息收集!"); return true; } // 转换内存单位为MB,方便管理员阅读 long maxMemoryMB = memoryBean.getHeapMemoryUsage().getMax() / 1024 / 1024; long freeMemoryMB = (memoryBean.getHeapMemoryUsage().getMax() - memoryBean.getHeapMemoryUsage().getUsed()) / 1024 / 1024; // 计算GC前后的堆内存使用总量 long memoryBeforeGcMB = latestGcInfo.getMemoryUsageBeforeGc().values().stream() .mapToLong(usage -> usage.getUsed()) .sum() / 1024 / 1024; long memoryAfterGcMB = latestGcInfo.getMemoryUsageAfterGc().values().stream() .mapToLong(usage -> usage.getUsed()) .sum() / 1024 / 1024; // 计算距离上次GC的时间(秒) long timeSinceLastGcSec = (System.currentTimeMillis() - latestGcInfo.getEndTime()) / 1000; // 发送格式化的消息(使用Minecraft颜色代码) sender.sendMessage("§6=== 最近一次GC详情 ==="); sender.sendMessage("§f最大内存: §a" + maxMemoryMB + " MB"); sender.sendMessage("§f剩余内存: §a" + freeMemoryMB + " MB"); sender.sendMessage("§fGC后已用内存: §a" + memoryAfterGcMB + " MB"); sender.sendMessage("§fGC前已用内存: §c" + memoryBeforeGcMB + " MB"); sender.sendMessage("§f距离上次GC时长: §e" + timeSinceLastGcSec + " 秒"); return true; } }
配置与注意事项
- 注册命令到插件:在你的
plugin.yml中添加命令配置,确保命令能被Minecraft识别:
name: GCInfoTool main: com.yourpluginpackage.GCInfoPlugin version: 1.0 commands: gcinfo: description: 查询最近一次JVM垃圾回收的详细信息 usage: /<command> permission: gcinfo.admin permission-message: §c你没有权限执行此命令!
- 权限控制:配置
gcinfo.admin权限,只允许服务器管理员或OP使用该命令,避免普通玩家滥用。 - JVM兼容性:代码基于JDK标准API,兼容Java8及以上版本,不需要依赖任何非公开的Sun/Oracle API,彻底解决Java7到Java8的兼容问题。
- 空值处理:如果JVM未开启GC信息收集(比如某些极端优化配置),代码会返回友好提示,避免插件报错。
内容的提问来源于stack exchange,提问作者Xeonmeister
相关产品推荐
相关产品推荐

