From 696880949938a74b96b66f45ae76736fc5bf9a7b Mon Sep 17 00:00:00 2001 From: huangyuhui Date: Thu, 31 Dec 2015 21:30:39 +0800 Subject: [PATCH] supported linux memory reading --- .../hellominecraft/launcher/Launcher.java | 22 ++++++-- .../installers/InstallerVersionList.java | 1 - .../version/MinecraftVersionManager.java | 14 ++--- .../launcher/views/MainPagePanel.java | 10 +++- .../hellominecraft/tasks/TaskList.java | 4 +- .../jackhuang/hellominecraft/utils/Utils.java | 28 ++-------- .../utils/system/JavaProcessMonitor.java | 21 ++++++-- .../hellominecraft/utils/system/OS.java | 52 ++++++++++++++++--- .../hellominecraft/views/LogWindow.java | 8 ++- .../hellominecraft/views/SwingUtils.java | 37 ++++++++++++- .../svrmgr/utils/MonitorServiceImpl.java | 27 +--------- 11 files changed, 146 insertions(+), 78 deletions(-) diff --git a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/Launcher.java b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/Launcher.java index 3e4922e53..175a7adbe 100755 --- a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/Launcher.java +++ b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/Launcher.java @@ -1,7 +1,7 @@ /* * Hello Minecraft! Launcher. * Copyright (C) 2013 huangyuhui - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or @@ -46,7 +46,7 @@ public final class Launcher { public static void println(String s) { System.out.println(s); } - + static String classPath = "", proxyHost = "", proxyPort = "", proxyUsername = "", proxyPassword = ""; public static void main(String[] args) { @@ -79,7 +79,14 @@ public final class Launcher { int len = tokenized.length; if (showInfo) { - LogWindow.INSTANCE.setTerminateGame(() -> Utils.shutdownForcely(1)); + LogWindow.INSTANCE.setTerminateGame(() -> { + try { + Utils.shutdownForcely(1); + } catch (Exception e) { + MessageBox.Show(C.i18n("launcher.exit_failed")); + HMCLog.err("Failed to shutdown forcely", e); + } + }); try { File logFile = new File("hmclmc.log"); if (!logFile.exists()) @@ -144,7 +151,7 @@ public final class Launcher { int flag = 0; try { - minecraftMain.invoke(null, new Object[] {(String[]) cmdList.toArray(new String[cmdList.size()])}); + minecraftMain.invoke(null, new Object[]{(String[]) cmdList.toArray(new String[cmdList.size()])}); } catch (Throwable throwable) { String trace = StrUtils.getStackTrace(throwable); final String advice = MinecraftCrashAdvicer.getAdvice(trace); @@ -159,7 +166,12 @@ public final class Launcher { } println("*** Game Exited ***"); - Utils.shutdownForcely(1); + try { + Utils.shutdownForcely(flag); + } catch (Exception e) { + MessageBox.Show(C.i18n("launcher.exit_failed")); + HMCLog.err("Failed to shutdown forcely", e); + } } /* static Object getShutdownHaltLock() { diff --git a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/installers/InstallerVersionList.java b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/installers/InstallerVersionList.java index fee90fc3d..232d743a9 100755 --- a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/installers/InstallerVersionList.java +++ b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/installers/InstallerVersionList.java @@ -18,7 +18,6 @@ package org.jackhuang.hellominecraft.launcher.utils.installers; import java.util.ArrayList; -import java.util.Collections; import java.util.Comparator; import java.util.List; import org.jackhuang.hellominecraft.utils.functions.Consumer; diff --git a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/version/MinecraftVersionManager.java b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/version/MinecraftVersionManager.java index ec3b8e7bd..f70a6cf9f 100755 --- a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/version/MinecraftVersionManager.java +++ b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/version/MinecraftVersionManager.java @@ -42,7 +42,7 @@ import org.jackhuang.hellominecraft.tasks.TaskWindow; import org.jackhuang.hellominecraft.tasks.download.FileDownloadTask; import org.jackhuang.hellominecraft.utils.system.IOUtils; import org.jackhuang.hellominecraft.utils.MessageBox; -import org.jackhuang.hellominecraft.utils.Utils; +import org.jackhuang.hellominecraft.views.SwingUtils; /** * @@ -196,16 +196,16 @@ public class MinecraftVersionManager extends IMinecraftProvider { @Override public File getRunDirectory(String id) { switch (profile.getGameDirType()) { - case VERSION_FOLDER: - return new File(baseFolder, "versions/" + id + "/"); - default: - return baseFolder; + case VERSION_FOLDER: + return new File(baseFolder, "versions/" + id + "/"); + default: + return baseFolder; } } @Override public void open(String mv, String name) { - Utils.openFolder((name == null) ? getRunDirectory(mv) : new File(getRunDirectory(mv), name)); + SwingUtils.openFolder((name == null) ? getRunDirectory(mv) : new File(getRunDirectory(mv), name)); } @Override @@ -236,7 +236,7 @@ public class MinecraftVersionManager extends IMinecraftProvider { @Override public IMinecraftLoader provideMinecraftLoader(UserProfileProvider p) - throws IllegalStateException { + throws IllegalStateException { return new MinecraftLoader(profile, this, p); } diff --git a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/views/MainPagePanel.java b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/views/MainPagePanel.java index 291ace7a7..bd24df449 100755 --- a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/views/MainPagePanel.java +++ b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/views/MainPagePanel.java @@ -567,7 +567,15 @@ public class MainPagePanel extends AnimatedPanel implements Event { MainFrame.INSTANCE.dispose(); } JavaProcessMonitor jpm = new JavaProcessMonitor(p); - jpm.stoppedEvent.register((sender3, t) -> { + jpm.applicationExitedAbnormallyEvent.register((sender2, t) -> { + MessageBox.Show(C.i18n("launch.exited_abnormally") + ", exit code: " + t); + return true; + }); + jpm.jvmLaunchFailedEvent.register((sender2, t) -> { + MessageBox.Show(C.i18n("launch.cannot_create_jvm") + ", exit code: " + t); + return true; + }); + jpm.stoppedEvent.register((sender2, t) -> { if (obj.getProfile().getLauncherVisibility() != LauncherVisibility.KEEP && !LogWindow.INSTANCE.isVisible()) System.exit(0); return true; diff --git a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/tasks/TaskList.java b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/tasks/TaskList.java index bfff52ad4..31ba361bc 100755 --- a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/tasks/TaskList.java +++ b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/tasks/TaskList.java @@ -1,7 +1,7 @@ /* * Hello Minecraft! Launcher. * Copyright (C) 2013 huangyuhui - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or @@ -40,6 +40,7 @@ public class TaskList extends Thread { boolean shouldContinue = true; public TaskList() { + setDaemon(true); } public void clean() { @@ -71,6 +72,7 @@ public class TaskList extends Thread { public InvokeThread(Task task, Set ss) { this.task = task; s = ss; + setDaemon(true); } @Override diff --git a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/Utils.java b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/Utils.java index c27f90db8..1bbf63cea 100755 --- a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/Utils.java +++ b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/Utils.java @@ -18,14 +18,12 @@ package org.jackhuang.hellominecraft.utils; import com.sun.management.OperatingSystemMXBean; -import java.awt.Desktop; import java.awt.Image; import java.awt.Toolkit; import java.awt.datatransfer.StringSelection; import java.io.File; import java.io.UnsupportedEncodingException; import java.lang.management.ManagementFactory; -import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.net.MalformedURLException; import java.net.URL; @@ -33,7 +31,6 @@ import java.net.URLClassLoader; import java.net.URLDecoder; import java.util.Random; import javax.swing.ImageIcon; -import org.jackhuang.hellominecraft.C; import org.jackhuang.hellominecraft.HMCLog; /** @@ -79,16 +76,6 @@ public final class Utils { Toolkit.getDefaultToolkit().getSystemClipboard().setContents(new StringSelection(text), null); } - public static void openFolder(File f) { - try { - f.mkdirs(); - java.awt.Desktop.getDesktop().open(f); - } catch (Exception ex) { - MessageBox.Show(C.i18n("message.cannot_open_explorer") + ex.getMessage()); - HMCLog.warn("Failed to open folder:" + f, ex); - } - } - public static ImageIcon scaleImage(ImageIcon i, int x, int y) { return new ImageIcon(i.getImage().getScaledInstance(x, y, Image.SCALE_SMOOTH)); } @@ -153,16 +140,11 @@ public final class Utils { * * @param status exit code */ - public static void shutdownForcely(int status) { - try { - Class z = Class.forName("java.lang.Shutdown"); - Method exit = z.getDeclaredMethod("exit", int.class); - exit.setAccessible(true); - exit.invoke(z, status); - } catch (ClassNotFoundException | NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { - MessageBox.Show(C.i18n("launcher.exit_failed")); - e.printStackTrace(); - } + public static void shutdownForcely(int status) throws Exception { + Class z = Class.forName("java.lang.Shutdown"); + Method exit = z.getDeclaredMethod("exit", int.class); + exit.setAccessible(true); + exit.invoke(z, status); } public static void requireNonNull(Object o) { diff --git a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/system/JavaProcessMonitor.java b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/system/JavaProcessMonitor.java index e221c66b6..0a888e418 100755 --- a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/system/JavaProcessMonitor.java +++ b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/system/JavaProcessMonitor.java @@ -1,7 +1,7 @@ /* * Hello Minecraft! Launcher. * Copyright (C) 2013 huangyuhui - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or @@ -17,10 +17,8 @@ */ package org.jackhuang.hellominecraft.utils.system; -import org.jackhuang.hellominecraft.utils.MessageBox; import java.util.Arrays; import java.util.HashSet; -import org.jackhuang.hellominecraft.C; import org.jackhuang.hellominecraft.utils.CollectionUtils; import org.jackhuang.hellominecraft.utils.Event; import org.jackhuang.hellominecraft.utils.EventHandler; @@ -33,7 +31,20 @@ import org.jackhuang.hellominecraft.utils.StrUtils; public class JavaProcessMonitor { private final HashSet al = new HashSet<>(); + /** + * this event will be executed only if the application returned 0. + */ public final EventHandler stoppedEvent = new EventHandler<>(this); + /** + * When the monitored application exited with exit code not zero, this event + * will be executed. Event args is the exit code. + */ + public final EventHandler applicationExitedAbnormallyEvent = new EventHandler<>(this); + /** + * When jvm crashed, this event will be executed. Event args is the exit + * code. + */ + public final EventHandler jvmLaunchFailedEvent = new EventHandler<>(this); private final JavaProcess p; public JavaProcessMonitor(JavaProcess p) { @@ -43,7 +54,7 @@ public class JavaProcessMonitor { public void start() { Event event = (sender2, t) -> { if (t.getExitCode() != 0) - MessageBox.Show(C.i18n("launch.exited_abnormally")); + applicationExitedAbnormallyEvent.execute(t.getExitCode()); processThreadStopped((ProcessThread) sender2, false); return true; }; @@ -51,7 +62,7 @@ public class JavaProcessMonitor { if (p1.getExitCode() != 0 && p1.getStdErrLines().size() > 0 && StrUtils.containsOne(p1.getStdErrLines(), Arrays.asList("Could not create the Java Virtual Machine.", "Error occurred during initialization of VM", "A fatal exception has occurred. Program will exit."))) - MessageBox.Show(C.i18n("launch.cannot_create_jvm")); + jvmLaunchFailedEvent.execute(p1.getExitCode()); processThreadStopped((ProcessThread) sender3, false); return true; }; diff --git a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/system/OS.java b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/system/OS.java index 7caf0c133..b358bbe0a 100755 --- a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/system/OS.java +++ b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/system/OS.java @@ -1,7 +1,7 @@ /* * Hello Minecraft! Launcher. * Copyright (C) 2013 huangyuhui - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or @@ -18,7 +18,13 @@ package org.jackhuang.hellominecraft.utils.system; import com.sun.management.OperatingSystemMXBean; +import java.io.BufferedReader; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStreamReader; import java.lang.management.ManagementFactory; +import java.util.StringTokenizer; import org.jackhuang.hellominecraft.HMCLog; /** @@ -40,9 +46,8 @@ public enum OS { } public static OS os() { - String str; - if ((str = System.getProperty("os.name").toLowerCase()) - .contains("win")) + String str = System.getProperty("os.name").toLowerCase(); + if (str.contains("win")) return OS.WINDOWS; if (str.contains("mac")) return OS.OSX; @@ -62,12 +67,45 @@ public enum OS { */ public static long getTotalPhysicalMemory() { try { - OperatingSystemMXBean o = (OperatingSystemMXBean) ManagementFactory.getOperatingSystemMXBean(); - return o.getTotalPhysicalMemorySize(); + if (os() == LINUX) + return memoryInfoForLinux()[0] * 1024; + else { + OperatingSystemMXBean o = (OperatingSystemMXBean) ManagementFactory.getOperatingSystemMXBean(); + return o.getTotalPhysicalMemorySize(); + } } catch (Throwable t) { - HMCLog.warn("Failed to get total physical memory size"); + HMCLog.warn("Failed to get total physical memory size", t); return -1; } } + public static long[] memoryInfoForLinux() throws IOException { + File file = new File("/proc/meminfo"); + BufferedReader br = new BufferedReader(new InputStreamReader( + new FileInputStream(file))); + long[] result = new long[4]; + String str = null; + StringTokenizer token; + while ((str = br.readLine()) != null) { + token = new StringTokenizer(str); + if (!token.hasMoreTokens()) + continue; + + str = token.nextToken(); + if (!token.hasMoreTokens()) + continue; + + if (str.equalsIgnoreCase("MemTotal:")) + result[0] = Long.parseLong(token.nextToken()); + else if (str.equalsIgnoreCase("MemFree:")) + result[1] = Long.parseLong(token.nextToken()); + else if (str.equalsIgnoreCase("SwapTotal:")) + result[2] = Long.parseLong(token.nextToken()); + else if (str.equalsIgnoreCase("SwapFree:")) + result[3] = Long.parseLong(token.nextToken()); + } + + return result; + } + } diff --git a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/views/LogWindow.java b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/views/LogWindow.java index 96e270c4d..53a26c15d 100755 --- a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/views/LogWindow.java +++ b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/views/LogWindow.java @@ -28,6 +28,7 @@ import org.jackhuang.hellominecraft.logging.Level; import org.jackhuang.hellominecraft.utils.functions.NonFunction; import org.jackhuang.hellominecraft.utils.DoubleOutputStream; import org.jackhuang.hellominecraft.utils.LauncherPrintStream; +import org.jackhuang.hellominecraft.utils.MessageBox; import org.jackhuang.hellominecraft.utils.Utils; /** @@ -208,7 +209,12 @@ public class LogWindow extends javax.swing.JFrame { if (flag) this.dispose(); else - Utils.shutdownForcely(0); + try { + Utils.shutdownForcely(0); + } catch (Exception e) { + MessageBox.Show(C.i18n("launcher.exit_failed")); + HMCLog.err("Failed to shutdown forcely", e); + } }//GEN-LAST:event_btnCloseActionPerformed private void btnClearActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnClearActionPerformed diff --git a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/views/SwingUtils.java b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/views/SwingUtils.java index 05ef08fe7..8603a8a18 100755 --- a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/views/SwingUtils.java +++ b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/views/SwingUtils.java @@ -19,6 +19,8 @@ package org.jackhuang.hellominecraft.views; import java.awt.EventQueue; import java.awt.FontMetrics; +import java.io.File; +import java.io.IOException; import java.net.URI; import javax.swing.DefaultListModel; import javax.swing.JLabel; @@ -28,9 +30,12 @@ import javax.swing.JScrollPane; import javax.swing.JTable; import javax.swing.JTextArea; import javax.swing.table.DefaultTableModel; +import org.jackhuang.hellominecraft.C; import org.jackhuang.hellominecraft.HMCLog; +import org.jackhuang.hellominecraft.utils.MessageBox; import org.jackhuang.hellominecraft.utils.StrUtils; import org.jackhuang.hellominecraft.utils.functions.NonFunction; +import org.jackhuang.hellominecraft.utils.system.OS; /** * @@ -50,8 +55,8 @@ public class SwingUtils { */ public static DefaultTableModel makeDefaultTableModel(String[] titleA, final Class[] typesA, final boolean[] canEditA) { return new DefaultTableModel( - new Object[][]{}, - titleA) { + new Object[][]{}, + titleA) { Class[] types = typesA; boolean[] canEdit = canEditA; @@ -67,6 +72,28 @@ public class SwingUtils { }; } + public static void openFolder(File f) { + f.mkdirs(); + String path = f.getAbsolutePath(); + switch (OS.os()) { + case OSX: + try { + Runtime.getRuntime().exec(new String[]{"/usr/bin/open", path}); + } catch (IOException ex) { + HMCLog.err("Failed to open " + path + " through /usr/bin/open", ex); + } + break; + default: + try { + java.awt.Desktop.getDesktop().open(f); + } catch (Throwable ex) { + MessageBox.Show(C.i18n("message.cannot_open_explorer") + ex.getMessage()); + HMCLog.warn("Failed to open " + path + " through java.awt.Desktop.getDesktop().open()", ex); + } + break; + } + } + /** * Open URL by java.awt.Desktop * @@ -76,6 +103,12 @@ public class SwingUtils { try { java.awt.Desktop.getDesktop().browse(new URI(link)); } catch (Throwable e) { + if (OS.os() == OS.OSX) + try { + Runtime.getRuntime().exec(new String[]{"/usr/bin/open", link}); + } catch (IOException ex) { + HMCLog.warn("Failed to open link: " + link, ex); + } HMCLog.warn("Failed to open link: " + link, e); } } diff --git a/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/utils/MonitorServiceImpl.java b/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/utils/MonitorServiceImpl.java index 27b642ef6..d936e9be7 100755 --- a/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/utils/MonitorServiceImpl.java +++ b/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/utils/MonitorServiceImpl.java @@ -1,7 +1,7 @@ /* * Hello Minecraft! Launcher. * Copyright (C) 2013 huangyuhui - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or @@ -37,7 +37,7 @@ public class MonitorServiceImpl implements IMonitorService { private static final int CPUTIME = 30; private static final int PERCENT = 100; private static final int FAULTLENGTH = 10; - private static String linuxVersion = null; + private static final String linuxVersion = null; /** * 获得当前的监控对象. @@ -94,7 +94,6 @@ public class MonitorServiceImpl implements IMonitorService { BufferedReader brStat = null; StringTokenizer tokenStat; try { - System.out.println("Getting usage rate of CPU , linux version: " + linuxVersion); Process process = Runtime.getRuntime().exec("top -b -n 1"); is = process.getInputStream(); isr = new InputStreamReader(is); @@ -249,26 +248,4 @@ public class MonitorServiceImpl implements IMonitorService { } return null; } - - /** - * 测试方法. - * - * @param args - * - * @throws Exception - * @author GuoHuang - */ - public static void main(String[] args) throws Exception { - IMonitorService service = new MonitorServiceImpl(); - MonitorInfoBean monitorInfo = service.getMonitorInfoBean(); - System.out.println("cpu占有率=" + monitorInfo.getCpuRatio()); - System.out.println("可使用内存=" + monitorInfo.getTotalMemory()); - System.out.println("剩余内存=" + monitorInfo.getFreeMemory()); - System.out.println("最大可使用内存=" + monitorInfo.getMaxMemory()); - System.out.println("操作系统=" + monitorInfo.getOsName()); - System.out.println("总的物理内存=" + monitorInfo.getTotalMemorySize() + "kb"); - System.out.println("剩余的物理内存=" + monitorInfo.getFreeMemory() + "kb"); - System.out.println("已使用的物理内存=" + monitorInfo.getUsedMemory() + "kb"); - System.out.println("线程总数=" + monitorInfo.getTotalThread() + "kb"); - } }