mirror of
				https://e.coding.net/circlecloud/Yum.git
				synced 2025-11-04 05:06:02 +00:00 
			
		
		
		
	feat: 添加主线程阻断检查
1.修复网络监测 2.修复配置文件错误 Signed-off-by: 502647092 <admin@yumc.pw>
This commit is contained in:
		
							
								
								
									
										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
 | 
			
		||||
		Reference in New Issue
	
	Block a user