mirror of
https://e.coding.net/circlecloud/Yum.git
synced 2024-12-22 20:58:47 +00:00
feat: 添加主线程阻断检查
1.修复网络监测 2.修复配置文件错误 Signed-off-by: 502647092 <admin@yumc.pw>
This commit is contained in:
parent
acef319e0d
commit
44842a38ec
2
pom.xml
2
pom.xml
@ -3,7 +3,7 @@
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>pw.yumc</groupId>
|
||||
<artifactId>Yum</artifactId>
|
||||
<version>2.1</version>
|
||||
<version>2.2</version>
|
||||
<name>Yum</name>
|
||||
<description>Minecraft 服务器插件管理系统</description>
|
||||
<build>
|
||||
|
@ -3,7 +3,10 @@
|
||||
*/
|
||||
package pw.yumc.Yum;
|
||||
|
||||
import java.util.Timer;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
import cn.citycraft.CommonData.UpdatePlugin;
|
||||
@ -17,6 +20,7 @@ import pw.yumc.Yum.listeners.PluginNetworkListener;
|
||||
import pw.yumc.Yum.listeners.SecurityListener;
|
||||
import pw.yumc.Yum.managers.ConfigManager;
|
||||
import pw.yumc.Yum.managers.NetworkManager;
|
||||
import pw.yumc.Yum.runnables.MainThreadCheckTask;
|
||||
|
||||
/**
|
||||
* MC插件仓库
|
||||
@ -25,15 +29,50 @@ import pw.yumc.Yum.managers.NetworkManager;
|
||||
* @since 2015年8月21日下午5:14:39
|
||||
*/
|
||||
public class Yum extends JavaPlugin {
|
||||
NetworkManager netmgr;
|
||||
@Override
|
||||
public FileConfiguration getConfig() {
|
||||
return ConfigManager.i().config;
|
||||
}
|
||||
|
||||
public void initCommands() {
|
||||
@Override
|
||||
public void onDisable() {
|
||||
NetworkManager.unregister();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
new YumAPI(this);
|
||||
initCommands();
|
||||
initListeners();
|
||||
initRunnable();
|
||||
new VersionChecker(this);
|
||||
YumAPI.updaterepo(Bukkit.getConsoleSender());
|
||||
YumAPI.updatecheck(Bukkit.getConsoleSender());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoad() {
|
||||
// 初始化配置
|
||||
ConfigManager.i();
|
||||
// 初始化更新列
|
||||
UpdatePlugin.getUpdateList();
|
||||
// 启用网络注入
|
||||
NetworkManager.register(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化命令
|
||||
*/
|
||||
private void initCommands() {
|
||||
new YumCommand(this);
|
||||
new NetCommand(this);
|
||||
new FileCommand(this);
|
||||
}
|
||||
|
||||
public void initListeners() {
|
||||
/**
|
||||
* 初始化监听
|
||||
*/
|
||||
private void initListeners() {
|
||||
if (ConfigManager.i().isSetOpEnable()) {
|
||||
try {
|
||||
final ClassLoader cl = Class.forName("pw.yumc.injected.event.SetOpEvent").getClassLoader();
|
||||
@ -52,30 +91,15 @@ public class Yum extends JavaPlugin {
|
||||
new PluginNetworkListener(this);
|
||||
PluginKit.scp("§a网络管理系统已启用...");
|
||||
}
|
||||
new
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisable() {
|
||||
netmgr.unregister();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
new YumAPI(this);
|
||||
initCommands();
|
||||
initListeners();
|
||||
new VersionChecker(this);
|
||||
YumAPI.updaterepo(Bukkit.getConsoleSender());
|
||||
YumAPI.updatecheck(Bukkit.getConsoleSender());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoad() {
|
||||
// 初始化配置
|
||||
ConfigManager.i();
|
||||
// 初始化更新列
|
||||
UpdatePlugin.getUpdateList();
|
||||
// 启用网络注入
|
||||
netmgr = new NetworkManager().register(this);
|
||||
/**
|
||||
* 初始化任务
|
||||
*/
|
||||
private void initRunnable() {
|
||||
final Timer task = new Timer();
|
||||
PluginKit.scp("§a线程管理系统已启用...");
|
||||
task.scheduleAtFixedRate(new MainThreadCheckTask(Thread.currentThread()), 0, 3000);
|
||||
}
|
||||
}
|
||||
|
@ -11,6 +11,7 @@ import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
import cn.citycraft.CommonData.UpdatePlugin;
|
||||
import pw.yumc.Yum.managers.ConfigManager;
|
||||
import pw.yumc.Yum.managers.DownloadManager;
|
||||
import pw.yumc.Yum.managers.PluginsManager;
|
||||
import pw.yumc.Yum.managers.RepositoryManager;
|
||||
@ -29,20 +30,6 @@ public class YumAPI {
|
||||
private static RepositoryManager repo;
|
||||
private static boolean runlock = false;
|
||||
|
||||
/**
|
||||
* 初始化Yum管理中心
|
||||
*
|
||||
* @param plugin
|
||||
* 插件实体
|
||||
*/
|
||||
public YumAPI(final Plugin plugin) {
|
||||
YumAPI.main = plugin;
|
||||
plugman = new PluginsManager(main);
|
||||
download = new DownloadManager(main);
|
||||
repo = new RepositoryManager(main);
|
||||
plugman.addIgnore(main.getConfig().getStringList("ignorelist"));
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除插件
|
||||
*
|
||||
@ -366,4 +353,18 @@ public class YumAPI {
|
||||
public static void upgrade(final CommandSender sender, final Plugin plugin) {
|
||||
plugman.upgrade(sender, plugin);
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化Yum管理中心
|
||||
*
|
||||
* @param plugin
|
||||
* 插件实体
|
||||
*/
|
||||
public YumAPI(final Plugin plugin) {
|
||||
YumAPI.main = plugin;
|
||||
plugman = new PluginsManager(main);
|
||||
download = new DownloadManager(main);
|
||||
repo = new RepositoryManager(main);
|
||||
plugman.addIgnore(ConfigManager.i().getIgnoreList());
|
||||
}
|
||||
}
|
||||
|
@ -1,32 +1,38 @@
|
||||
package pw.yumc.Yum.listeners;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
import cn.citycraft.PluginHelper.kit.ExceptionKit;
|
||||
import cn.citycraft.PluginHelper.kit.PluginKit;
|
||||
import pw.yumc.Yum.Yum;
|
||||
import pw.yumc.Yum.events.PluginNetworkEvent;
|
||||
import pw.yumc.Yum.managers.ConfigManager;
|
||||
|
||||
public class PluginNetworkListener implements Listener {
|
||||
public String prefix = "§6[§bYum §a网络管理§6] ";
|
||||
|
||||
public PluginNetworkListener(final Yum yum) {
|
||||
Bukkit.getPluginManager().registerEvents(this, yum);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onPluginNetworkConect(final PluginNetworkEvent e) {
|
||||
final Plugin plugin = e.getPlugin();
|
||||
final String urlinfo = e.getUrl().toString();
|
||||
final boolean isPrimaryThread = e.isPrimaryThread();
|
||||
final String str = isPrimaryThread ? "§6[§bYum §a网络管理§6] §c插件 §6%s §c尝试在主线程访问 §e%s §4可能会导致服务器卡顿或无响应!" : "§6[§bYum §a网络监控§6] §c插件 §6%s §c尝试访问 §e%s §c请注意服务器网络安全!";
|
||||
final String str = prefix + (isPrimaryThread ? "§c插件 §6%s §c尝试在主线程访问 §e%s §4可能会导致服务器卡顿或无响应!" : "§c插件 §6%s §c尝试访问 §e%s §c请注意服务器网络安全!");
|
||||
if (plugin != null) {
|
||||
Bukkit.getConsoleSender().sendMessage(String.format(str, plugin.getName(), urlinfo));
|
||||
if (ConfigManager.i().getNetworkBlackList().contains(plugin.getName())) {
|
||||
PluginKit.sc(prefix + "§4已阻止黑名单插件 §b" + plugin.getName() + " §4访问网络!");
|
||||
PluginKit.sc(prefix + "§4地址: " + urlinfo);
|
||||
return;
|
||||
}
|
||||
PluginKit.sc(String.format(str, plugin.getName(), urlinfo));
|
||||
if (!ConfigManager.i().isAllowPrimaryThread() && isPrimaryThread) {
|
||||
Bukkit.getConsoleSender().sendMessage("§6[§bYum §a网络管理§6] §4已阻止插件 §b" + plugin.getName() + " §4在主线程访问网络!");
|
||||
ExceptionKit.throwException(new IOException("[Yum 网络防护] 已开启网络防护 不允许在主线程访问网络!"));
|
||||
PluginKit.sc(prefix + "§4已阻止插件 §b" + plugin.getName() + " §4在主线程访问网络!");
|
||||
e.setCancelled(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -8,18 +8,15 @@ import cn.citycraft.PluginHelper.config.FileConfig;
|
||||
import cn.citycraft.PluginHelper.kit.PKit;
|
||||
|
||||
public class ConfigManager {
|
||||
private static List<String> blackList;
|
||||
private static List<String> ignoreList;
|
||||
|
||||
private final static String ENABLE = "Enable";
|
||||
private final static String BLACK = "Black";
|
||||
private final static String IGNORE = "Ignore";
|
||||
|
||||
private final static ConfigManager i = new ConfigManager(PKit.i());
|
||||
|
||||
private final FileConfig config;
|
||||
private final FileConfig setop;
|
||||
private final FileConfig network;
|
||||
public final FileConfig config;
|
||||
public final FileConfig setop;
|
||||
public final FileConfig network;
|
||||
|
||||
public static ConfigManager i() {
|
||||
return i;
|
||||
@ -32,11 +29,11 @@ public class ConfigManager {
|
||||
}
|
||||
|
||||
public List<String> getBlackList() {
|
||||
return blackList;
|
||||
return config.getStringList("blacklist");
|
||||
}
|
||||
|
||||
public List<String> getIgnoreList() {
|
||||
return ignoreList;
|
||||
return config.getStringList("ignorelist");
|
||||
}
|
||||
|
||||
public List<String> getNetworkBlackList() {
|
||||
|
@ -8,8 +8,8 @@ import java.net.URI;
|
||||
import java.util.List;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
import cn.citycraft.PluginHelper.kit.ExceptionKit;
|
||||
import cn.citycraft.PluginHelper.kit.PluginKit;
|
||||
import pw.yumc.Yum.Yum;
|
||||
import pw.yumc.Yum.events.PluginNetworkEvent;
|
||||
@ -22,20 +22,19 @@ import pw.yumc.Yum.events.PluginNetworkEvent;
|
||||
*/
|
||||
public class NetworkManager {
|
||||
|
||||
public NetworkManager register(final Yum plugin) {
|
||||
public static void register(final Yum plugin) {
|
||||
Bukkit.getConsoleSender().sendMessage("§6[§bYum §a网络管理§6] §a注入网络管理系统 将托管服务器网络!");
|
||||
ProxySelector.setDefault(new YumProxySelector(ProxySelector.getDefault(), plugin));
|
||||
return this;
|
||||
}
|
||||
|
||||
public void unregister() {
|
||||
public static void unregister() {
|
||||
final ProxySelector cur = ProxySelector.getDefault();
|
||||
if (cur instanceof YumProxySelector) {
|
||||
ProxySelector.setDefault(((YumProxySelector) cur).getDefaultSelector());
|
||||
}
|
||||
}
|
||||
|
||||
class YumProxySelector extends ProxySelector {
|
||||
static class YumProxySelector extends ProxySelector {
|
||||
private final ProxySelector defaultSelector;
|
||||
|
||||
public YumProxySelector(final ProxySelector defaultSelector, final Yum plugin) {
|
||||
@ -53,12 +52,10 @@ public class NetworkManager {
|
||||
|
||||
@Override
|
||||
public List<Proxy> select(final URI uri) {
|
||||
final boolean isPrimaryThread = Bukkit.isPrimaryThread();
|
||||
final Plugin plugin = PluginKit.getOperatePlugin();
|
||||
final PluginNetworkEvent pne = new PluginNetworkEvent(plugin, uri, isPrimaryThread);
|
||||
final PluginNetworkEvent pne = new PluginNetworkEvent(PluginKit.getOperatePlugin(), uri, Bukkit.isPrimaryThread());
|
||||
Bukkit.getPluginManager().callEvent(pne);
|
||||
if (pne.isCancelled()) {
|
||||
return null;
|
||||
ExceptionKit.throwException(new IOException("[Yum 网络防护] 已开启网络防护 不允许在主线程访问网络!"));
|
||||
}
|
||||
return defaultSelector.select(uri);
|
||||
}
|
||||
|
53
src/main/java/pw/yumc/Yum/runnables/MainThreadCheckTask.java
Normal file
53
src/main/java/pw/yumc/Yum/runnables/MainThreadCheckTask.java
Normal file
@ -0,0 +1,53 @@
|
||||
package pw.yumc.Yum.runnables;
|
||||
|
||||
import java.lang.Thread.State;
|
||||
import java.util.TimerTask;
|
||||
import java.util.logging.Level;
|
||||
|
||||
import cn.citycraft.PluginHelper.kit.PKit;
|
||||
|
||||
/**
|
||||
*
|
||||
* @since 2016年6月22日 下午4:57:32
|
||||
* @author 喵♂呜
|
||||
*/
|
||||
public class MainThreadCheckTask extends TimerTask {
|
||||
|
||||
private final Thread mainThread;
|
||||
|
||||
public MainThreadCheckTask(final Thread mainThread) {
|
||||
this.mainThread = mainThread;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
// According to this post the thread is still in Runnable although it's waiting for
|
||||
// file/http ressources
|
||||
// https://stackoverflow.com/questions/20795295/why-jstack-out-says-thread-state-is-runnable-while-socketread
|
||||
if (mainThread.getState() == State.RUNNABLE) {
|
||||
// Based on this post we have to check the top element of the stack
|
||||
// https://stackoverflow.com/questions/20891386/how-to-detect-thread-being-blocked-by-io
|
||||
final StackTraceElement[] stackTrace = mainThread.getStackTrace();
|
||||
final StackTraceElement topElement = stackTrace[0];
|
||||
if (topElement.isNativeMethod()) {
|
||||
// Socket/SQL (connect) - java.net.DualStackPlainSocketImpl.connect0
|
||||
// Socket/SQL (read) - java.net.SocketInputStream.socketRead0
|
||||
// Socket/SQL (write) - java.net.SocketOutputStream.socketWrite0
|
||||
if (isElementEqual(topElement, "java.net.DualStackPlainSocketImpl", "connect0")
|
||||
|| isElementEqual(topElement, "java.net.SocketInputStream", "socketRead0")
|
||||
|| isElementEqual(topElement, "java.net.SocketOutputStream", "socketWrite0")) {
|
||||
PKit.i().getLogger().log(Level.WARNING, "主线程存在网络操作 服务器处于停止状态...", stackTrace);
|
||||
}
|
||||
// File (in) - java.io.FileInputStream.readBytes
|
||||
// File (out) - java.io.FileOutputStream.writeBytes
|
||||
else if (isElementEqual(topElement, "java.io.FileInputStream", "readBytes") || isElementEqual(topElement, "java.io.FileOutputStream", "writeBytes")) {
|
||||
PKit.i().getLogger().log(Level.WARNING, "主线程存在IO操作 服务器处于停止状态...", stackTrace);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isElementEqual(final StackTraceElement traceElement, final String className, final String methodName) {
|
||||
return traceElement.getClassName().equals(className) && traceElement.getMethodName().equals(methodName);
|
||||
}
|
||||
}
|
@ -3,6 +3,7 @@ Enable: true
|
||||
#黑名单列表
|
||||
Black:
|
||||
- BukkitInjectedTools
|
||||
- FeatherBoard
|
||||
#忽略检测列表
|
||||
Ignore:
|
||||
- Essentials
|
Loading…
Reference in New Issue
Block a user