package com.cnd3b.utility;

import com.alibaba.fastjson.JSONException;
import p2.ws.restful.WSRESTService;

import java.lang.management.*;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Calendar;
import java.util.List;

public class sysmsg implements WSRESTService {
    public static final long MB = 1024 * 1024;

    public String getCustMsg() throws JSONException {
        StringBuffer msg = new StringBuffer();
        String cline = "<br/>";
        String kg = "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;";
        {
            msg.append("<!DOCTYPE html>");
            msg.append("<html>");
            msg.append("<head>");
            msg.append("<meta http-equiv=\"Content-Type\" content=\"text/html;charset=utf-8\">");
            msg.append("</head>");
            msg.append("<body>");
            // 打印系统信息
            msg.append("===========打印系统信息==========").append(cline);
            OperatingSystemMXBean system = ManagementFactory.getOperatingSystemMXBean();
            msg.append("系统名称:").append(system.getName()).append(cline);
            msg.append("系统版本:").append(system.getVersion()).append(cline);
            msg.append("操作系统的架构:").append(system.getArch()).append(cline);
            msg.append("可用的内核数:").append(system.getAvailableProcessors()).append(cline);
            if (isSunOsMBean(system)) {
                long totalPhysicalMemory = getLongFromOperatingSystem(system, "getTotalPhysicalMemorySize");
                long freePhysicalMemory = getLongFromOperatingSystem(system, "getFreePhysicalMemorySize");
                long usedPhysicalMemorySize = totalPhysicalMemory - freePhysicalMemory;
                msg.append("总物理内存(M):").append(totalPhysicalMemory / MB).append(cline);
                msg.append("已用物理内存(M):").append(usedPhysicalMemorySize / MB).append(cline);

                long totalSwapSpaceSize = getLongFromOperatingSystem(system, "getTotalSwapSpaceSize");
                long freeSwapSpaceSize = getLongFromOperatingSystem(system, "getFreeSwapSpaceSize");
                long usedSwapSpaceSize = totalSwapSpaceSize - freeSwapSpaceSize;
                msg.append("总交换空间(M):").append(totalSwapSpaceSize / MB).append(cline);
                msg.append("已用交换空间(M):").append(usedSwapSpaceSize / MB).append(cline);
                msg.append("剩余交换空间(M):").append(freeSwapSpaceSize / MB).append(cline);
            }
        }
        {
            // 打印编译信息
            msg.append("===========打印编译信息==========").append(cline);
            CompilationMXBean compilation = ManagementFactory.getCompilationMXBean();
            msg.append("JIT编译器名称：").append(compilation.getName()).append(cline);
            // 判断jvm是否支持编译时间的监控
            if (compilation.isCompilationTimeMonitoringSupported()) {
                msg.append("总编译时间：").append(compilation.getTotalCompilationTime() / 1000).append("秒").append(cline);
            }
        }
        {
            // 打印类加载信息
            msg.append("===========打印类加载信息==========").append(cline);
            ClassLoadingMXBean classLoad = ManagementFactory.getClassLoadingMXBean();
            msg.append("已加载类总数：").append(classLoad.getTotalLoadedClassCount()).append(cline);
            msg.append("已加载当前类：").append(classLoad.getLoadedClassCount()).append(cline);
            msg.append("已卸载类总数：").append(classLoad.getUnloadedClassCount()).append(cline);
        }
        {
            // 打印运行时信息
            msg.append("===========打印运行时信息==========").append(cline);
            RuntimeMXBean runtime = ManagementFactory.getRuntimeMXBean();
            msg.append("进程PID=").append(runtime.getName().split("@")[0]).append(cline);
            msg.append("jvm规范名称:").append(runtime.getSpecName()).append(cline);
            msg.append("jvm规范运营商:").append(runtime.getSpecVendor()).append(cline);
            msg.append("jvm规范版本:").append(runtime.getSpecVersion()).append(cline);
            // 返回虚拟机在毫秒内的开始时间。该方法返回了虚拟机启动时的近似时间
            Calendar c = Calendar.getInstance();
            c.setTimeInMillis(runtime.getStartTime());
            msg.append("jvm启动时间:").append(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(c.getTime())).append(cline);
            // msg.append("获取System.properties:" + runtime.getSystemProperties()
            // + cline);
            long runtitme = runtime.getUptime();
            String timestr = "";
            long daytimes = 86400000;
            if (runtitme / daytimes > 0) {
                timestr = runtitme / daytimes + "天";
                runtitme = runtitme % daytimes;
            }
            long hourtimes = 3600000;
            if (runtitme / hourtimes > 0) {
                timestr = timestr + runtitme / hourtimes + "小时";
                runtitme = runtitme % hourtimes;
            }
            long mtimes = 60000;
            if (runtitme / mtimes > 0) {
                timestr = timestr + runtitme / mtimes + "分";
                runtitme = runtitme % mtimes;
            }
            long mmtimes = 1000;
            if (runtitme / mmtimes > 0) {
                timestr = timestr + runtitme / mmtimes + "秒";
            }
            msg.append("jvm正常运行时间:").append(timestr).append(cline);
            msg.append("jvm名称:").append(runtime.getVmName()).append(cline);
            msg.append("jvm运营商:").append(runtime.getVmVendor()).append(cline);
            msg.append("jvm实现版本:").append(runtime.getVmVersion()).append(cline);
            List<String> args = runtime.getInputArguments();
            if (args != null && !args.isEmpty()) {
                msg.append("vm参数:").append(cline);
                for (String arg : args) {
                    msg.append(kg).append(arg).append(cline);
                }
            }
            // msg.append("类路径:" + runtime.getClassPath() + cline);
            // msg.append("引导类路径:" + runtime.getBootClassPath() + cline);
            // msg.append("库路径:" + runtime.getLibraryPath() + cline);
        }
        {
            // 打印内存管理器信息
            msg.append("===========打印内存管理器信息==========").append(cline);
            List<MemoryManagerMXBean> managers = ManagementFactory.getMemoryManagerMXBeans();
            if (managers != null && !managers.isEmpty()) {
                for (MemoryManagerMXBean manager : managers) {
                    msg.append("vm内存管理器：").append(cline).append(kg).append("名称=").append(manager.getName()).append(cline).append(kg).append(",管理的内存区=").append(Arrays.deepToString(manager.getMemoryPoolNames())).append(cline).append(kg).append(",ObjectName=").append(manager.getObjectName()).append(cline);
                }
            }
        }
        {
            // 打印垃圾回收信息
            msg.append("===========打印垃圾回收信息==========").append(cline);
            List<GarbageCollectorMXBean> garbages = ManagementFactory.getGarbageCollectorMXBeans();
            for (GarbageCollectorMXBean garbage : garbages) {
                msg.append("垃圾收集器：").append(cline).append(kg).append("名称=").append(garbage.getName()).append(cline).append(kg).append("收集=").append(garbage.getCollectionCount()).append(cline).append(kg).append("总花费时间=").append(garbage.getCollectionTime()).append(cline).append(kg).append("内存区名称=").append(Arrays.deepToString(garbage.getMemoryPoolNames())).append(cline);
            }
        }
        {
            // 打印vm内存
            msg.append("===========打印vm内存信息==========").append(cline);
            MemoryMXBean memory = ManagementFactory.getMemoryMXBean();
            MemoryUsage headMemory = memory.getHeapMemoryUsage();
            msg.append("head堆:").append(cline);
            msg.append(kg).append("初始(M):").append(headMemory.getInit() / MB).append(cline);
            msg.append(kg).append("最大(上限)(M):").append(headMemory.getMax() / MB).append(cline);
            msg.append(kg).append("当前(已使用)(M):").append(headMemory.getUsed() / MB).append(cline);
            msg.append(kg).append("提交的内存(已申请)(M):").append(headMemory.getCommitted() / MB).append(cline);
            msg.append(kg).append("使用率:").append(Math.round(headMemory.getUsed() * 100 / (double) headMemory.getCommitted(), 2)).append("%").append(cline);

            msg.append("non-head非堆:").append(cline);
            MemoryUsage nonheadMemory = memory.getNonHeapMemoryUsage();
            msg.append(kg).append("初始(M):").append(nonheadMemory.getInit() / MB).append(cline);
            msg.append(kg).append("最大(上限)(M):").append(nonheadMemory.getMax() / MB).append(cline);
            msg.append(kg).append("当前(已使用)(M):").append(nonheadMemory.getUsed() / MB).append(cline);
            msg.append(kg).append("提交的内存(已申请)(M):").append(nonheadMemory.getCommitted() / MB).append(cline);
            msg.append(kg).append("使用率:").append(Math.round(nonheadMemory.getUsed() * 100 / (double) nonheadMemory.getCommitted(), 2)).append("%").append(cline);
        }
        {
            // 打印vm各内存区信息
            msg.append("===========打印vm各内存区信息==========").append(cline);

            List<MemoryPoolMXBean> pools = ManagementFactory.getMemoryPoolMXBeans();
            if (pools != null && !pools.isEmpty()) {
                for (MemoryPoolMXBean pool : pools) {
                    // 只打印一些各个内存区都有的属性，一些区的特殊属性，可看文档或百度
                    // 最大值，初始值，如果没有定义的话，返回-1，所以真正使用时，要注意
                    msg.append("vm内存区:").append(cline).append(kg).append("名称=").append(pool.getName()).append(cline).append(kg).append("所属内存管理者=").append(Arrays.deepToString(pool.getMemoryManagerNames())).append(cline).append(kg).append("ObjectName=").append(pool.getObjectName()).append(cline).append(kg).append("初始大小(M)=").append(pool.getUsage().getInit() / MB).append(cline).append(kg).append("最大(上限)(M)=").append(pool.getUsage().getMax() / MB).append(cline).append(kg).append("已用大小(M)=").append(pool.getUsage().getUsed() / MB).append(cline).append(kg).append("已提交(已申请)(M)=").append(pool.getUsage().getCommitted() / MB).append(cline).append(kg).append("使用率=").append(Math.round((pool.getUsage().getUsed() * 100 / (double) pool.getUsage().getCommitted()), 2)).append("%").append(cline);
                }
            }
        }
        {
            // 打印线程信息
            msg.append("===========打印线程==========").append(cline);

            ThreadMXBean thread = ManagementFactory.getThreadMXBean();
            msg.append("ObjectName=").append(thread.getObjectName()).append(cline);
            msg.append("仍活动的线程总数=").append(thread.getThreadCount()).append(cline);
            msg.append("峰值=").append(thread.getPeakThreadCount()).append(cline);
            msg.append("线程总数（被创建并执行过的线程总数）=").append(thread.getTotalStartedThreadCount()).append(cline);
            msg.append("当初仍活动的守护线程（daemonThread）总数=").append(thread.getDaemonThreadCount()).append(cline);

            // 检查是否有死锁的线程存在
            long[] deadlockedIds = thread.findDeadlockedThreads();
            if (deadlockedIds != null && deadlockedIds.length > 0) {
                ThreadInfo[] deadlockInfos = thread.getThreadInfo(deadlockedIds);
                msg.append("死锁线程信息:").append(cline);
                msg.append("\t\t线程名称\t\t状态\t\t").append(cline);
                for (ThreadInfo deadlockInfo : deadlockInfos) {
                    msg.append("\t\t").append(deadlockInfo.getThreadName()).append("\t\t").append(deadlockInfo.getThreadState()).append("\t\t").append(deadlockInfo.getBlockedTime()).append("\t\t").append(deadlockInfo.getWaitedTime()).append("\t\t").append(deadlockInfo.getStackTrace().toString()).append(cline);
                }
            }
			/*long[] threadIds = thread.getAllThreadIds();
			if (threadIds != null && threadIds.length > 0) {
				ThreadInfo[] threadInfos = thread.getThreadInfo(threadIds);
				msg.append("所有线程信息:" + cline);
				msg.append("<table border=\"1\" align=\"left\">");
				msg.append("<tr>");
				msg.append("<th>");
				msg.append("线程名称");
				msg.append("</th>");
				msg.append("<th>");
				msg.append("状态");
				msg.append("</th>");
				msg.append("<th>");
				msg.append("线程id");
				msg.append("</th>");
				msg.append("</tr>");
				for (ThreadInfo threadInfo : threadInfos) {
					msg.append("<tr>");
					msg.append("<td>");
					msg.append(threadInfo.getThreadName());
					msg.append("</td>");
					msg.append("<td>");
					msg.append(threadInfo.getThreadState());
					msg.append("</td>");
					msg.append("<td>");
					msg.append(threadInfo.getThreadId());
					msg.append("</td>");
					msg.append("</tr>");
				}
				msg.append("</table>");
			}
			*/
        }
        msg.append("</body>");
        msg.append("</html>");
        return msg.toString();
    }

    private static long getLongFromOperatingSystem(OperatingSystemMXBean operatingSystem, String methodName) {
        try {
            final Method method = operatingSystem.getClass().getMethod(methodName, (Class<?>[]) null);
            method.setAccessible(true);
            return (Long) method.invoke(operatingSystem, (Object[]) null);
        } catch (final InvocationTargetException e) {
            if (e.getCause() instanceof Error) {
                throw (Error) e.getCause();
            } else if (e.getCause() instanceof RuntimeException) {
                throw (RuntimeException) e.getCause();
            }
            throw new IllegalStateException(e.getCause());
        } catch (final NoSuchMethodException e) {
            throw new IllegalArgumentException(e);
        } catch (final IllegalAccessException e) {
            throw new IllegalStateException(e);
        }
    }

    private static boolean isSunOsMBean(OperatingSystemMXBean operatingSystem) {
        final String className = operatingSystem.getClass().getName();
        return "com.sun.management.OperatingSystem".equals(className)
                || "com.sun.management.UnixOperatingSystem".equals(className);
    }
}
