Skip to content

Commit

Permalink
Changed the access levels of the classes to reflect what people shoul…
Browse files Browse the repository at this point in the history
…d be able to see and use, and started adding JavaDoc
  • Loading branch information
Jez Humble committed Jan 8, 2010
1 parent ce4f8d8 commit b38b606
Show file tree
Hide file tree
Showing 11 changed files with 173 additions and 10 deletions.
13 changes: 13 additions & 0 deletions build.xml
Original file line number Diff line number Diff line change
Expand Up @@ -59,4 +59,17 @@
<arg value="50"/>
</exec>
</target>

<target name="javadoc">
<javadoc packagenames="com.jezhumble.javasysmon.*"
sourcepath="src/main/java"
destdir="target/javadoc"
author="true"
version="true"
windowtitle="Java System Monitor">
<doctitle><![CDATA[<h1>Java System Monitor</h1>]]></doctitle>
<bottom><![CDATA[<i>Copyright &#169; 2009 ThoughtWorks. All Rights Reserved.</i>]]></bottom>
</javadoc>
</target>

</project>
129 changes: 127 additions & 2 deletions src/main/java/com/jezhumble/javasysmon/JavaSysMon.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,42 @@
import java.util.ArrayList;
import java.util.Iterator;

/**
* This class provides the main API for JavaSysMon.
* You must instantiate this class in order to use it,
* but it stores no state, so there is zero overhead to
* instantiating it as many times as you like, and
* hence no need to cache it.
* <p>
* When instantiated for the first time, JavaSysMon
* will discover which operating system it is running on
* and attempt to load the appropriate OS-specific
* extensions. If JavaSysMon doesn't support the OS
* you're running on, all calls to the API will return
* null or zero values. Probably the best one to test is
* osName.
* <p>
* You can run JavaSysMon directly as a jar file, using
* the command "java -jar javasysmon.jar", in which case
* it will display output similar to the UNIX "top"
* command. You can optionally specify a process id as an
* argument, in which case JavaSysMon will attempt to
* kill the process.
*
* @author Jez Humble
*/
public class JavaSysMon implements Monitor {

private static Monitor monitor = null;
private static ArrayList supported = new ArrayList();

static void setMonitor(Monitor myMonitor) {
if (monitor == null) {
/**
* Allows you to register your own implementation of {@link Monitor}.
*
* @param myMonitor An implementation of the Monitor interface that all API calls will be delegated to
*/
public static void setMonitor(Monitor myMonitor) {
if (monitor == null || monitor instanceof NullMonitor) {
monitor = myMonitor;
}
}
Expand All @@ -26,6 +55,20 @@ static void addSupportedConfig(String config) {
new NullMonitor(); // make sure the API never gives back a NPE
}

/**
* Creates a new JavaSysMon object through which to access
* the JavaSysMon API. All necessary state is kept statically
* so there is zero overhead to instantiating this class.
*/
public JavaSysMon() {}

/**
* This is the main entry point when running the jar directly.
* It prints out some system performance metrics and the process table
* in a format similar to the UNIX top command. Optionally you can
* specify a process id as an argument, in which case JavaSysMon
* will attempt to kill the process specified by that pid.
*/
public static void main (String[] params) throws Exception {
if (monitor instanceof NullMonitor) {
System.err.println("Couldn't find an implementation for OS: " + System.getProperty("os.name"));
Expand Down Expand Up @@ -65,46 +108,125 @@ private static String secsInDaysAndHours(long seconds) {

// Following is the actual API

/**
* Get the operating system name.
*
* @return The operating system name.
*/
public String osName() {
return monitor.osName();
}

/**
* Get the number of CPU cores.
*
* @return The number of CPU cores.
*/
public int numCpus() {
return monitor.numCpus();
}

/**
* Get the CPU frequency in Hz
*
* @return the CPU frequency in Hz
*/
public long cpuFrequencyInHz() {
return monitor.cpuFrequencyInHz();
}

/**
* How long the system has been up in seconds.
* Doesn't generally include time that the system
* has been hibernating or asleep.
*
* @return The time the system has been up in seconds.
*/
public long uptimeInSeconds() {
return monitor.uptimeInSeconds();
}

/**
* Gets the pid of the process that is calling this method
* (assuming it is running in the same process).
*
* @return The pid of the process calling this method.
*/
public int currentPid() {
return monitor.currentPid();
}

/**
* Gets the total amount of time the CPU has spent in
* user mode, kernel mode, and idle. Can be used to
* calculate CPU usage. Simply take two data points,
* take the difference between these numbers, and
* calculate the percentage of time spent not idle.
*
* @return An object containing the amount of time the
* CPU has spent idle, in user mode and in kernel mode,
* in milliseconds.
*/
public CpuTimes cpuTimes() {
return monitor.cpuTimes();
}

/**
* Gets the physical memory installed, and the amount free.
*
* @return An object containing the amount of physical
* memory installed, and the amount free.
*/
public MemoryStats physical() {
return monitor.physical();
}

/**
* Gets the amount of swap available to the operating system,
* and the amount that is free.
*
* @return An object containing the amount of swap available
* to the system, and the amount free.
*/
public MemoryStats swap() {
return monitor.swap();
}

/**
* Get the current process table. This call returns an array of
* objects, each of which represents a single process. If you want
* the objects in a tree structure, use {@link #processTree} instead.
*
* @return An array of objects, each of which represents a process.
*/
public ProcessInfo[] processTable() {
return monitor.processTable();
}

/**
* Gets the current process table in the form of a process tree.
* The object returned is a top-level container which doesn't actually
* represent a process - its children are the top-level processes
* running in the system. This is necessary because some operating systems
* (Windows, for example) don't have a single top-level process (orphans
* are literally orphaned), and because the process table snapshot
* is not atomic. That means the process table thus returned can be
* internally inconsistent.
*
* @return The current process table in the form of a process tree.
*/
public OsProcess processTree() {
return OsProcess.createTree(monitor.processTable());
}

/**
* Attempts to kill the process identified by the integer id supplied.
* This will silently fail if you don't have the authority to kill
* that process. This method sends SIGTERM on the UNIX platform,
* and kills the process using TerminateProcess on Windows.
*
* @param pid The id of the process to kill
*/
public void killProcess(int pid) {
monitor.killProcess(pid);
}
Expand All @@ -113,6 +235,9 @@ public void killProcessTree(int pid, boolean descendantsOnly) {
processTree().find(pid).killTree(descendantsOnly);
}

/**
* Attempts to kill all the descendents of the currently running process.
*/
public void infanticide() {
killProcessTree(currentPid(), true);
}
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/com/jezhumble/javasysmon/LinuxMonitor.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import java.util.regex.Pattern;

// Network stats will come from /proc/net/dev; disk stats will be from /proc/diskstats
public class LinuxMonitor implements Monitor {
class LinuxMonitor implements Monitor {

private static final Pattern TOTAL_MEMORY_PATTERN =
Pattern.compile("MemTotal:\\s+(\\d+) kB", Pattern.MULTILINE);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class LinuxProcessInfoParser {
class LinuxProcessInfoParser {
private final String stat;
private final String status;
private final String cmdline;
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/com/jezhumble/javasysmon/MacOsXMonitor.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package com.jezhumble.javasysmon;

public class MacOsXMonitor implements Monitor {
class MacOsXMonitor implements Monitor {

private static Monitor monitor = null;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import java.io.*;

// This is "optimised" based on the fact we only load each native library once.
public class NativeLibraryLoader {
class NativeLibraryLoader {
public void loadLibrary(String libraryName) {
try {
InputStream is = this.getClass().getResourceAsStream("/" + libraryName);
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/com/jezhumble/javasysmon/NullMonitor.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package com.jezhumble.javasysmon;

public class NullMonitor implements Monitor {
class NullMonitor implements Monitor {

public NullMonitor() {
JavaSysMon.setMonitor(this);
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/com/jezhumble/javasysmon/SolarisMonitor.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import java.io.IOException;

public class SolarisMonitor implements Monitor {
class SolarisMonitor implements Monitor {
private static Monitor monitor = null;
private final FileUtils fileUtils;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import java.io.InputStreamReader;
import java.util.HashMap;

public class UnixPasswdParser {
class UnixPasswdParser {

public HashMap parse() {
try {
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/com/jezhumble/javasysmon/WindowsMonitor.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package com.jezhumble.javasysmon;

public class WindowsMonitor implements Monitor {
class WindowsMonitor implements Monitor {
private static Monitor monitor = null;

static {
Expand Down
25 changes: 25 additions & 0 deletions src/main/java/com/jezhumble/javasysmon/package.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<html>
<body>

<p>JavaSysMon is designed to provide an OS-independent way to get live system information,
such as CPU and memory usage, and manage processes, distributed as a single jar file.
It is written in C and Java. However the native binaries are hidden away inside the jar,
so you never need to worry about them.</p>

<p>The main API is to be found in {@link com.jezhumble.javasysmon.JavaSysMon}, so start there.</p>

<p>JavaSysMon is licensed according to the terms of the NetBSD (2-line BSD) license.</p>

<h2>Related Documentation</h2>

<ul>
<li><a href="http://github.com/jezhumble/javasysmon">Source code</a></li>
<li><a href="http://github.com/arya/javasysmon/issues">Bug / feature tracker</a></li>
<li><a href="http://groups.google.com/group/javasysmon">Mailing list</a></li>
</ul>

<!-- Put @see and @since tags down here. -->

</body>
</html>

0 comments on commit b38b606

Please sign in to comment.