/*
* Copyright 2010 NCHOVY
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.krakenapps.winapi;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.krakenapps.winapi.impl.LongRef;
import org.krakenapps.winapi.impl.ObjectRef;
public class Process {
public static final int PROCESS_VM_READ = 0x0010;
public static final int PROCESS_ALL_ACCESS = 0x001F0FFF;
public static final int PROCESS_QUERY_INFORMATION = 0x400;
public static final int PROCESS_QUERY_LIMITED_INFORMATION = 0x1000;
static {
System.loadLibrary("winapi");
}
public static int getProcessorCount() {
return GetProcessorCount();
}
/**
* Calculates cpu usages of all processes.
*
* @param interval
* interval in milliseconds
* @return the pid, cpu usage (percent) pairs
* @throws InterruptedException
* when thread is interrupted
*/
public static Map<Integer, Integer> getCpuUsages(int interval) throws InterruptedException {
Map<Integer, Long> first = new HashMap<Integer, Long>();
Map<Integer, Long> second = new HashMap<Integer, Long>();
Map<Integer, Integer> usages = new HashMap<Integer, Integer>();
for (Process p : Process.getProcesses()) {
first.put(p.getPid(), p.getPrivilegedProcessorTime() + p.getUserProcessorTime());
}
long begin = new Date().getTime();
Thread.sleep(interval);
for (Process p : Process.getProcesses()) {
second.put(p.getPid(), p.getPrivilegedProcessorTime() + p.getUserProcessorTime());
}
long end = new Date().getTime();
int cpuCount = getProcessorCount();
long total = end - begin;
for (int pid : second.keySet()) {
if (!first.containsKey(pid))
continue;
// 100ns -> ms (1000000 ns)
long use = (second.get(pid) - first.get(pid));
int usage = (int) (use / total / 100 / cpuCount);
usages.put(pid, usage);
}
return usages;
}
private int pid;
private String name;
private long privilegedProcessorTime;
private long userProcessorTime;
private ProcessMemoryCounters memCounters = new ProcessMemoryCounters();
private Process(int pid, String name) {
this.pid = pid;
this.name = name;
refresh();
}
public int getPid() {
return pid;
}
public String getName() {
return name;
}
public long getPrivilegedProcessorTime() {
return privilegedProcessorTime;
}
public long getUserProcessorTime() {
return userProcessorTime;
}
public long getWorkingSet() {
return memCounters.getWorkingSetSize();
}
public long getPagedMemorySize() {
return memCounters.getQuotaPagedPoolUsage();
}
public long getNonPagedMemorySize() {
return memCounters.getQuotaNonPagedPoolUsage();
}
public long getPageFault() {
return memCounters.getPageFaultCount();
}
public long getPrivateWorkingSet() {
return memCounters.getPrivateUsage();
}
@Override
public String toString() {
return "pid=" + pid + ", name=" + name;
}
public void refresh() {
int hProcess = OpenProcess(PROCESS_VM_READ | PROCESS_QUERY_INFORMATION, 0, pid);
if (hProcess == 0)
return;
LongRef creation = new LongRef();
LongRef exit = new LongRef();
LongRef kernel = new LongRef();
LongRef user = new LongRef();
int ret = GetProcessTimes(hProcess, creation, exit, kernel, user);
if (ret == 1) {
privilegedProcessorTime = kernel.value;
userProcessorTime = user.value;
}
memCounters = getMemoryCounters(hProcess);
CloseHandle(hProcess);
}
private static Integer[] EnumProcesses() {
ObjectRef ref = new ObjectRef();
EnumProcesses(ref);
Integer[] array = (Integer[]) ref.value;
return array;
}
public static List<Process> getProcesses() {
List<Process> processes = new ArrayList<Process>();
Integer[] array = EnumProcesses();
for (int pid : array) {
int hProcess = OpenProcess(PROCESS_VM_READ | PROCESS_QUERY_INFORMATION, 0, pid);
if (hProcess != 0) {
String baseName = GetModuleBaseName(hProcess, 1000);
if (baseName == null)
baseName = "";
processes.add(new Process(pid, baseName));
} else {
String n = "";
if (pid == 0)
n = "System Idle Process";
else if (pid == 4)
n = "System";
else
continue;
processes.add(new Process(pid, n));
}
CloseHandle(hProcess);
}
return processes;
}
private ProcessMemoryCounters getMemoryCounters(int hProcess) {
LongRef pageFaultCount = new LongRef();
LongRef peakWorkingSetSize = new LongRef();
LongRef workingSetSize = new LongRef();
LongRef quotaPeakPagedPoolUsage = new LongRef();
LongRef quotaPagedPoolUsage = new LongRef();
LongRef quotaPeakNonPagedPoolUsage = new LongRef();
LongRef quotaNonPagedPoolUsage = new LongRef();
LongRef pagefileUsage = new LongRef();
LongRef peakPagefileUsage = new LongRef();
LongRef privateUsage = new LongRef();
GetProcessMemoryInfo(hProcess, pageFaultCount, peakWorkingSetSize, workingSetSize, quotaPeakPagedPoolUsage,
quotaPagedPoolUsage, quotaPeakNonPagedPoolUsage, quotaNonPagedPoolUsage, pagefileUsage,
peakPagefileUsage, privateUsage);
return new ProcessMemoryCounters(pageFaultCount.value, peakWorkingSetSize.value, workingSetSize.value,
quotaPeakPagedPoolUsage.value, quotaPagedPoolUsage.value, quotaPeakNonPagedPoolUsage.value,
quotaNonPagedPoolUsage.value, pagefileUsage.value, peakPagefileUsage.value, privateUsage.value);
}
private static native int EnumProcesses(ObjectRef pids);
private static native int OpenProcess(int desiredAccess, int inheritHandle, int processId);
private static native String GetModuleBaseName(int hProcess, int maxLength);
private static native int CloseHandle(int handle);
private static native int GetProcessTimes(int hProcess, LongRef creation, LongRef exit, LongRef kernel, LongRef user);
private static native int GetProcessorCount();
private static native int GetProcessMemoryInfo(int hProcess, LongRef pageFaultCount, LongRef peakWorkingSetSize,
LongRef workingSetSize, LongRef quotaPeakPagedPoolUsage, LongRef quotaPagedPoolUsage,
LongRef quotaPeakNonPagedPoolUsage, LongRef quotaNonPagedPoolUsage, LongRef pagefileUsage,
LongRef peakPagefileUsage, LongRef privateUsage);
}