本来想做一个win32平台下, 由于vc没有psapi.dll的库. 所以选择了mingw包和gcc编译器.
java部分
这里主要是申明接口. javah工具会根据你声明的接口自动生成对于的.h头文件
//SystemInfo.java
package com.khan.system;
public abstract class SystemInfo
{
// public: ................................................................
/**
* A simple class to represent data snapshots taken by {@link #makeCPUUsageSnapshot}.
*/
public static final class CPUUsageSnapshot {
public final long m_time, m_CPUTime;
// constructor is private to ensure that makeCPUUsageSnapshot()
// is used as the factory method for this class:
private CPUUsageSnapshot (final long time, final long CPUTime) {
m_time = time;
m_CPUTime = CPUTime;
}
} // end of nested class
// Custom exception class for throwing
public static final class NegativeCPUTime extends Exception {}
/**
* Minimum time difference [in milliseconds] enforced for the inputs into
* {@link #getProcessCPUUsage(SystemInfo.CPUUsageSnapshot,SystemInfo.CPUUsageSnapshot)}.
* The motivation for this restriction is the fact that <CODE>System.currentTimeMillis()</CODE>
* on some systems has a low resolution (e.g., 10ms on win32). The current value
* is 100 ms.
*/
public static final int MIN_ELAPSED_TIME = 100;
/**
* Creates a CPU usage data snapshot by associating CPU time used with system
* time. The resulting data can be fed into
* {@link #getProcessCPUUsage(SystemInfo.CPUUsageSnapshot,SystemInfo.CPUUsageSnapshot)}.
*/
public static CPUUsageSnapshot makeCPUUsageSnapshot() throws SystemInfo.NegativeCPUTime {
long prCPUTime = getProcessCPUTime ();
if (prCPUTime<0)
throw new NegativeCPUTime();
return new CPUUsageSnapshot (System.currentTimeMillis (), getProcessCPUTime ());
}
/**
* Computes CPU usage (fraction of 1.0) between <CODE>start.m_CPUTime</CODE> and
* <CODE>end.m_CPUTime</CODE> time points [1.0 corresponds to 100% utilization of
* all processors].
*
* @throws IllegalArgumentException if start and end time points are less than
* {@link #MIN_ELAPSED_TIME} ms apart.
* @throws IllegalArgumentException if either argument is null;
*/
public static double getProcessCPUUsage (final CPUUsageSnapshot start, final CPUUsageSnapshot end) {
if (start == null)
throw new IllegalArgumentException ("null input: start");
if (end == null)
throw new IllegalArgumentException ("null input: end");
if (end.m_time < start.m_time + MIN_ELAPSED_TIME)
throw new IllegalArgumentException ("end time must be at least " + MIN_ELAPSED_TIME + " ms later than start time");
return ((double)(end.m_CPUTime - start.m_CPUTime)) / (end.m_time - start.m_time);
}
/**
* Returns the PID of the current process. The result is useful when you need
* to integrate a Java app with external tools.
*/
public static native int getProcessID ();
/**
* Returns the number of processors on machine
*/
public static native int getCPUs ();
/**
* Returns CPU (kernel + user) time used by the current process [in milliseconds].
* The returned value is adjusted for the number of processors in the system.
*/
public static native long getProcessCPUTime ();
/**
* Returns CPU (kernel + user) time used by the current process [in perecents].
* The returned value is either CPU percentage, or zero if this is not supported by OS.
* Currently it is supported by Solaris8, and not supported by Windows XP
*/
public static native double getProcessCPUPercentage();
/**
* Returns maximum memory available in the system.
*/
public static native long getMaxMem ();
/**
* Returns current free memory in the system.
*/
public static native long getFreeMem ();
/**
* Returns system name info like "uname" command output
*/
public static native String getSysInfo ();
/**
* Returns CPU usage (fraction of 1.0) so far by the current process. This is a total
* for all processors since the process creation time.
*/
public static native double getProcessCPUUsage ();
/**
* Returns current space allocated for the process, in Kbytes. Those pages may or may not be in memory.
*/
public static native long getMemoryUsage();
/**
* Returns current process space being resident in memory, in Kbytes.
*/
public static native long getMemoryResident();
/**
* Sets the system native process PID for which all measurements will be done.
* If this method is not called then the current JVM pid will act as a default.
* Returns the native-dependent error code, or 0 in case of success.
*/
public static native int setPid(int pid);
/**
* Closes native-dependent process handle, if necessary.
*/
public static native int detachProcess();
// protected: .............................................................
// package: ...............................................................
// private: ...............................................................
private SystemInfo() {} // prevent subclassing
private static final String SILIB = "SystemInfo";
static {
// loading a native lib in a static initializer ensures that it is
// available done before any method in this class is called:
try {
System.loadLibrary (SILIB);
}catch (UnsatisfiedLinkError e){
System.out.println("native lib '" + SILIB
+ "' not found in 'java.library.path': "
+ System.getProperty ("java.library.path"));
}catch (Exception e){
System.out.println(e.getMessage());
}
}
} // end of class
//AppMain.java 测试文件
package com.khan.system;
public class AppMain {
/**
* Default constructor
*/
public AppMain() {
// TODO: Add constructor code here
}
public static void main(String[] args) {
try {
Thread.sleep(1000);
System.out.println("getMaxMem:" + SystemInfo.getMaxMem());
System.out.println("getCPUs:" + SystemInfo.getCPUs());
System.out.println("getSysInfo:" + SystemInfo.getSysInfo());
}catch (Exception e){
System.out.println(e.getMessage());
}
}
}
java部分工程文件. 等同与makefile
ant build.xml
<project name="IpNet" default="build" basedir=".">
<description>
simple example build file
</description>
<!-- set global properties for this build -->
<property name="name" value="IpNet"/>
<property name="src" location="src"/>
<property name="build" location="build"/>
<property name="dist" location="dist"/>
<property name="web" location="web/WEB-INF/lib"/>
<path id="master-classpath">
<fileset dir="./lib">
<include name="*.jar"/>
</fileset>
</path>
<target name="init">
<tstamp/>
<mkdir dir="${build}"/>
<mkdir dir="${dist}"/>
</target>
<target name="build" depends="init" description="compile the source " >
<javac srcdir="${src}" destdir="${build}">
<compilerarg value="-Xlint:unchecked"/>
<compilerarg value="-deprecation"/>
<classpath refid="master-classpath"/>
</javac>
<copy todir="${build}" preservelastmodified="true">
<fileset dir="${src}">
<include name="*.class"/>
</fileset>
</copy>
<jar jarfile="${dist}/${name}.jar" compress="true">
<fileset dir="${build}">
<include name="**"/>
</fileset>
</jar>
<copy todir="${web}" >
<fileset dir="${dist}">
<include name="${name}.jar"/>
</fileset>
</copy>
</target>
<target name="clean" description="clean up" >
<delete dir="${build}"/>
<delete dir="${dist}"/>
<delete file="${web}/${name}.jar"/>
</target>
</project>
在工程目录下ant 编译工程
build目录为本工程目标二进制文件目录. 编译后的class在此目录下
然后到build目录下
javah javah -jni com.khan.system.SystemInfo //注意, 一定要使用包全路径. 如果不是default包的话.
会在此目录下生成3个.h文件
com_khan_system_SystemInfo.h
com_khan_system_SystemInfo_CPUUsageSnapshot.h
com_khan_system_SystemInfo_NegativeCPUTime.h
java这边的准备工作完成
接下来处理c部分
新建一个c工程. 我用gcc的. 所以这些部分我手工完成的
将刚刚的.h文件实现
/* ------------------------------------------------------------------------- */
/*
* An implementation of JNI methods in com.vladium.utils.SystemInformation
* class. The author compiled it using Microsoft Visual C++ and GCC for Win32 but the code
* should be easy to use with any compiler for win32 platform.
*
* For simplicity, this implementaion assumes JNI 1.2+ and omits error handling.
*
* Enhanced by Peter V. Mikhalenko (C) 2004, Deutsche Bank [[email protected]]
* Original source (C) 2002, Vladimir Roubtsov [[email protected]]
*/
/* ------------------------------------------------------------------------- */
#include <windows.h>
#include <stdio.h>
#include <process.h>
#include <winbase.h>
#include <psapi.h>
#include <string.h>
#include "include/com_khan_system_SystemInfo.h"
static jint s_PID;
static HANDLE s_currentProcess;
static int alreadyDetached;
static int s_numberOfProcessors;
static SYSTEM_INFO systemInfo;
static WORD processorArchitecture;
static DWORD pageSize;
static DWORD processorType;
static WORD processorLevel;
static WORD processorRevision;
#define INFO_BUFFER_SIZE 32768
#define BUFSIZE 2048
//BOOL flll = TRUE;
/* ------------------------------------------------------------------------- */
/*
* A helper function for converting FILETIME to a LONGLONG [safe from memory
* alignment point of view].
*/
static LONGLONG fileTimeToInt64 (const FILETIME * time)
{
ULARGE_INTEGER _time;
_time.LowPart = time->dwLowDateTime;
_time.HighPart = time->dwHighDateTime;
return _time.QuadPart;
}
/* ......................................................................... */
/*
* This method was added in JNI 1.2. It is executed once before any other
* methods are called and is ostensibly for negotiating JNI spec versions, but
* can also be conveniently used for initializing variables that will not
* change throughout the lifetime of this process.
*/
JNIEXPORT jint JNICALL JNI_OnLoad (JavaVM * vm, void * reserved)
{
s_PID = _getpid ();
s_currentProcess = GetCurrentProcess ();
//externalCPUmon = 0;
alreadyDetached = 0;
GetSystemInfo (&systemInfo);
s_numberOfProcessors = systemInfo.dwNumberOfProcessors;
processorArchitecture = systemInfo.wProcessorArchitecture;
pageSize = systemInfo.dwPageSize;
processorType = systemInfo.dwProcessorType;
processorLevel = systemInfo.wProcessorLevel;
processorRevision = systemInfo.wProcessorRevision;
printf("SystemInfo.dll is Loaded");
return JNI_VERSION_1_2;
}
/* ......................................................................... */
JNIEXPORT void JNICALL
JNI_OnUnload (JavaVM * vm, void * reserved)
{
if (!alreadyDetached && s_currentProcess!=NULL) {
CloseHandle(s_currentProcess);
printf("[JNI Unload] Detached from native process.");
fflush(stdout);
}
printf("SystemInfo.dll is UnLoaded");
}
/* ......................................................................... */
/*
* Class: com_vladium_utils_SystemInformation
* Method: getCPUs
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_com_khan_system_SystemInfo_getCPUs(JNIEnv * env, jclass cls)
{
return (jint)s_numberOfProcessors;
}
/* ......................................................................... */
/*
* Class: com_vladium_utils_SystemInformation
* Method: getProcessID
* Signature: ()I
*/
JNIEXPORT jint JNICALL
Java_com_khan_system_SystemInfo_getProcessID(JNIEnv * env, jclass cls)
{
return s_PID;
}
/* ......................................................................... */
/*
* Class: com_vladium_utils_SystemInformation
* Method: setPid
* Signature: ()I
*/
JNIEXPORT jint JNICALL
Java_com_khan_system_SystemInfo_setPid(JNIEnv * env, jclass cls, jint pid)
{
DWORD errCode;
LPVOID lpMsgBuf;
s_PID = pid;
s_currentProcess = OpenProcess(PROCESS_ALL_ACCESS,FALSE,pid);
if (s_currentProcess==NULL) {
errCode = GetLastError();
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
errCode,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR) &lpMsgBuf,
0, NULL );
printf("[CPUmon] Could not attach to native process. Error code: %ld Error description: %s", errCode, (char *)lpMsgBuf);
fflush(stdout);
LocalFree(lpMsgBuf);
return errCode;
}
printf("[CPUmon] Attached to native process.");
fflush(stdout);
return 0;
}
/* ......................................................................... */
/*
* Class: com_vladium_utils_SystemInformation
* Method: detachProcess
* Signature: ()I
*/
JNIEXPORT jint JNICALL
Java_com_khan_system_SystemInfo_detachProcess(JNIEnv * env, jclass cls)
{
if (!alreadyDetached && s_currentProcess!=NULL) {
CloseHandle(s_currentProcess);
alreadyDetached = 1;
printf("[CPUmon] Detached from native process.");
fflush(stdout);
}
return 0;
}
/* ......................................................................... */
/*
* Class: com_vladium_utils_SystemInformation
* Method: getProcessCPUTime
* Signature: ()J
*/
JNIEXPORT jlong JNICALL
Java_com_khan_system_SystemInfo_getProcessCPUTime (JNIEnv * env, jclass cls)
{
FILETIME creationTime, exitTime, kernelTime, userTime;
DWORD errCode;
LPVOID lpMsgBuf;
BOOL resultSuccessful = GetProcessTimes (s_currentProcess, & creationTime, & exitTime, & kernelTime, & userTime);
if (!resultSuccessful) {
errCode = GetLastError();
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
errCode,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR) &lpMsgBuf,
0, NULL );
printf("[CPUmon] An error occured while trying to get CPU time. Error code: %ld Error description: %s", errCode, (char *)lpMsgBuf);
fflush(stdout);
LocalFree(lpMsgBuf);
return -1;
}
return (jlong) ((fileTimeToInt64 (& kernelTime) + fileTimeToInt64 (& userTime)) /
(s_numberOfProcessors * 10000));
}
/* ......................................................................... */
/*
* Class: com_vladium_utils_SystemInformation
* Method: getMaxMem
* Signature: ()J
*/
JNIEXPORT jlong JNICALL
Java_com_khan_system_SystemInfo_getMaxMem(JNIEnv * env, jclass cls)
{
MEMORYSTATUS stat;
GlobalMemoryStatus (&stat);
return (jlong)(stat.dwTotalPhys/1024);
}
/* ......................................................................... */
/*
* Class: com_vladium_utils_SystemInformation
* Method: getFreeMem
* Signature: ()J
*/
JNIEXPORT jlong JNICALL
Java_com_khan_system_SystemInfo_getFreeMem (JNIEnv * env, jclass cls)
{
MEMORYSTATUS stat;
GlobalMemoryStatus (&stat);
return (jlong)(stat.dwAvailPhys/1024);
}
/* ......................................................................... */
/* define min elapsed time (in units of 10E-7 sec): */
#define MIN_ELAPSED_TIME (10000)
/*
* Class: com_vladium_utils_SystemInformation
* Method: getProcessCPUUsage
* Signature: ()D
*/
JNIEXPORT jdouble JNICALL
Java_com_khan_system_SystemInfo_getProcessCPUUsage(JNIEnv * env, jclass cls)
{
FILETIME creationTime, exitTime, kernelTime, userTime, nowTime;
LONGLONG elapsedTime;
DWORD errCode;
LPVOID lpMsgBuf;
BOOL resultSuccessful = GetProcessTimes (s_currentProcess, & creationTime, & exitTime, & kernelTime, & userTime);
if (!resultSuccessful) {
errCode = GetLastError();
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
errCode,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR) &lpMsgBuf,
0, NULL );
printf("[CPUmon] An error occured while trying to get CPU time. Error code: %ld Error description: %s", errCode, (char *)lpMsgBuf);
fflush(stdout);
LocalFree(lpMsgBuf);
return -1.0;
}
GetSystemTimeAsFileTime (& nowTime);
/*
NOTE: win32 system time is not very precise [~10ms resolution], use
sufficiently long sampling intervals if you make use of this method.
*/
elapsedTime = fileTimeToInt64 (& nowTime) - fileTimeToInt64 (& creationTime);
if (elapsedTime < MIN_ELAPSED_TIME)
return 0.0;
else
return ((jdouble) (fileTimeToInt64 (& kernelTime) + fileTimeToInt64 (& userTime))) /
(s_numberOfProcessors * elapsedTime);
}
/* ......................................................................... */
/*
* Class: com_vladium_utils_SystemInformation
* Method: getProcessCPUPercentage
* Signature: ()D
*/
JNIEXPORT jdouble JNICALL
Java_com_khan_system_SystemInfo_getProcessCPUPercentage (JNIEnv * env, jclass cls)
{
// Not implemented on Windows
return (jdouble)(-1.0);
}
/* ......................................................................... */
/*
* Class: com_vladium_utils_SystemInformation
* Method: getMemoryUsage
* Signature: ()J
*/
JNIEXPORT jlong JNICALL
Java_com_khan_system_SystemInfo_getMemoryUsage (JNIEnv * env, jclass cls)
{
PROCESS_MEMORY_COUNTERS pmc;
if ( GetProcessMemoryInfo( s_currentProcess, &pmc, sizeof(pmc)) )
{
return (jlong)(pmc.PagefileUsage/1024);
} else {
return (jlong)(0);
}
}
/* ......................................................................... */
/*
* Class: com_vladium_utils_SystemInformation
* Method: getMemoryResident * Signature: ()J
*/
JNIEXPORT jlong JNICALL
Java_com_khan_system_SystemInfo_getMemoryResident(JNIEnv * env, jclass cls)
{
PROCESS_MEMORY_COUNTERS pmc;
if ( GetProcessMemoryInfo( s_currentProcess, &pmc, sizeof(pmc)) )
{
return (jlong)(pmc.WorkingSetSize/1024);
} else {
return (jlong)(0);
}
}
/*
* Class: com_vladium_utils_SystemInformation
* Method: getSysInfo
* Signature: ()S
*/
JNIEXPORT jstring JNICALL
Java_com_khan_system_SystemInfo_getSysInfo(JNIEnv * env, jclass cls)
{
char buf[2048];
char buf2[512];
jstring retval;
OSVERSIONINFOEX osvi;
BOOL bOsVersionInfoEx;
TCHAR infoBuf[INFO_BUFFER_SIZE];
DWORD bufCharCount = INFO_BUFFER_SIZE;
*buf = 0; //c语言. 变量定义所有代码在前
*buf2 = 0;
ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
if( !(bOsVersionInfoEx = GetVersionEx ((OSVERSIONINFO *) &osvi)) )
{
osvi.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
if (! GetVersionEx ( (OSVERSIONINFO *) &osvi) ) {
// Return empty string in case of problems
goto next_label;
}
}
switch (osvi.dwPlatformId)
{
// Test for the Windows NT product family.
case VER_PLATFORM_WIN32_NT:
// Test for the specific product.
if ( osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 2 )
strcat(buf,"WinServer2003, ");
if ( osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1 )
strcat(buf,"WinXP ");
if ( osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0 )
strcat(buf,"Win2K ");
if ( osvi.dwMajorVersion <= 4 )
strcat(buf,"WinNT ");
// Display service pack (if any) and build number.
if( osvi.dwMajorVersion == 4 && lstrcmpi( osvi.szCSDVersion, "Service Pack 6" ) == 0 )
{
HKEY hKey;
LONG lRet;
// Test for SP6 versus SP6a.
lRet = RegOpenKeyEx( HKEY_LOCAL_MACHINE, "SOFTWAREMicrosoftWindows NTCurrentVersionHotfixQ246009", 0, KEY_QUERY_VALUE, &hKey );
if( lRet == ERROR_SUCCESS ) {
sprintf(buf2, "SP 6a (Build %d), ", (int)(osvi.dwBuildNumber & 0xFFFF) );
strcat(buf,buf2);
}
else // Windows NT 4.0 prior to SP6a
{
sprintf(buf2, "%s (Build %d), ",
osvi.szCSDVersion,
(int)(osvi.dwBuildNumber & 0xFFFF));
strcat(buf,buf2);
}
RegCloseKey( hKey );
}
else // not Windows NT 4.0
{
sprintf(buf2, "%s (Build %d), ", osvi.szCSDVersion, (int)(osvi.dwBuildNumber & 0xFFFF));
strcat(buf,buf2);
}
break;
// Test for the Windows Me/98/95.
case VER_PLATFORM_WIN32_WINDOWS:
if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 0)
{
strcat(buf,"Win95 ");
if ( osvi.szCSDVersion[1] == 'C' || osvi.szCSDVersion[1] == 'B' )
strcat(buf,"OSR2 " );
}
if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 10)
{
strcat(buf,"Win98 ");
if ( osvi.szCSDVersion[1] == 'A' )
strcat(buf,"SE " );
}
if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 90)
{
strcat(buf,"WinME ");
}
break;
case VER_PLATFORM_WIN32s:
strcat(buf,"Win32s ");
break;
}
next_label:
strcat(buf,"on ");
// Get and display the name of the computer.
bufCharCount = INFO_BUFFER_SIZE;
if( !GetComputerName( infoBuf, &bufCharCount ) )
goto next_label_2;
strcat(buf, infoBuf );
next_label_2:
strcat(buf," (");
if (!(osvi.dwPlatformId==VER_PLATFORM_WIN32_WINDOWS && osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 0)) {
// Win95 does not keep CPU info in registry
LONG lRet;
HKEY hKey;
char szOrigCPUType[BUFSIZE];
int i=0;
DWORD dwBufLen=BUFSIZE;
lRet = RegOpenKeyEx( HKEY_LOCAL_MACHINE, "HARDWAREDESCRIPTIONSystemCentralProcessor", 0, KEY_QUERY_VALUE, &hKey );
if( lRet != ERROR_SUCCESS ) {
goto next_label_3;
}
lRet = RegQueryValueEx( hKey, "ProcessorNameString", NULL, NULL, (LPBYTE) szOrigCPUType, &dwBufLen);
if( (lRet != ERROR_SUCCESS) || (dwBufLen > BUFSIZE) ) {
goto next_label_3;
}
RegCloseKey( hKey );
if (strlen(szOrigCPUType)>0) {
while(szOrigCPUType[i]==' ' && szOrigCPUType[i]!=0)
i++;
strcat(buf,szOrigCPUType+i);
} else
goto next_label_3;
} else {
next_label_3:
if (processorArchitecture==PROCESSOR_ARCHITECTURE_UNKNOWN)
strcat(buf,"unknown_arch");
else if (processorArchitecture==PROCESSOR_ARCHITECTURE_INTEL) {
strcat(buf,"Intel ");
sprintf(buf2,"level %d ",processorLevel);
strcat(buf,buf2);
} else if (processorArchitecture==PROCESSOR_ARCHITECTURE_IA64)
strcat(buf,"IA64 ");
else if (processorArchitecture==PROCESSOR_ARCHITECTURE_MIPS)
strcat(buf,"MIPS ");
else if (processorArchitecture==PROCESSOR_ARCHITECTURE_ALPHA)
strcat(buf,"Alpha ");
else if (processorArchitecture==PROCESSOR_ARCHITECTURE_PPC)
strcat(buf,"PowerPC ");
else if (processorArchitecture==PROCESSOR_ARCHITECTURE_SHX)
strcat(buf,"SHX ");
else if (processorArchitecture==PROCESSOR_ARCHITECTURE_ALPHA64)
strcat(buf,"Alpha64 ");
else
strcat(buf,"unknown_arch ");
}
strcat(buf,")");
retval = (*env)->NewStringUTF(env,buf);
return retval;
}
/* ......................................................................... */
#undef MIN_ELAPSED_TIME
/* ------------------------------------------------------------------------- */
/* end of file */
编写makefile
# Project: SystemInfo
# Makefile created by Khan.Lau
# Write by 2007-05-16
# 应用程序名
#LIB = SystemInfo.a
DLL = SystemInfo.dll
#BIN = SystemInfo.exe
# 输出目录
# CONFIGURATION = debug
CONFIGURATION = release
# 取得项目的当前工作路径
PROJECT_PATH = "D:/Project/Cplus/SystemInfo/src"
CPP = g++
CC = gcc
COMPILER = $(CC)
# c/c++库路径
LIBPATH = "D:/Develop/CPlus/MinGW/lib"
WINDRES = windres.exe
RES =
# 包路径
LIBS = -L$(LIBPATH) \
-lpsapi
INCS = -I$(LIBPATH)/include \
-ID:/Develop/Java/jdk1.5.0_02/include \
-ID:/Develop/Java/jdk1.5.0_02/include/win32 \
-I$(PROJECT_PATH)
CXXINCS = -I$(LIBPATH)/include \
-I$(LIBPATH)/include/c++/3.2.3 \
-I$(LIBPATH)/include/c++/3.2.3/backward \
-I$(LIBPATH)/include/c++/3.2.3/mingw32 \
-I$(PROJECT_PATH)
DLLFLAGS = -DBUILD_DLL
CXXFLAGS = $(DLLFLAGS) -g -Wall $(CXXINCS)
CFLAGS = $(DLLFLAGS) -Wall $(INCS)
COMPILER_FLAG = $(CFLAGS)
RM = rm -f
LINKOBJ = $(CONFIGURATION)/SystemInfo.o \
$(RES)
.PHONY: all all-before all-after clean clean-custom rebuild
all: all-before $(DLL) all-after
clean: clean-custom
${RM} $(LINKOBJ) $(CONFIGURATION)/$(DLL)
$(LIB): $(LINKOBJ)
ar -r $(CONFIGURATION)/$(LIB) $(LINKOBJ)
$(DLL): $(LINKOBJ)
$(COMPILER) -shared -Wl,--add-stdcall-alias -o $(CONFIGURATION)/$(DLL) $(LINKOBJ) $(LIBS)
$(BIN): $(LINKOBJ)
$(COMPILER) -o $(CONFIGURATION)/$(BIN) $(LINKOBJ) $(LIBS)
#缩减可执行文件大小
strip:
strip $(CONFIGURATION)/$(LIB)
################################################################################
$(CONFIGURATION)/SystemInfo.o: src/dll/SystemInfo.c
$(COMPILER) -c src/dll/SystemInfo.c -o $(CONFIGURATION)/SystemInfo.o $(COMPILER_FLAG)
################################################################################
rebuild: clean all
makefile中注意
$(DLL): $(LINKOBJ)
$(COMPILER) -shared -Wl,--add-stdcall-alias -o $(CONFIGURATION)/$(DLL) $(LINKOBJ) $(LIBS)
-shared -Wl,--add-stdcall-alias 这3个参数是一定要的. 具体含义请参阅gcc帮助..
否则会出现如下异常:java.lang.UnsatisfiedLinkError
如果你确认自己的dll名没有错. loadlibrary的名字也没有填错. 那应该就要检查如上部分了
实际发布的时候. 不要使用调试版本. 也就是编译参数不能有-g
ok, 现在make出dll使用吧....
我本地测试的输出结果为 :
getMaxMem:506604
getCPUs:1
getSysInfo:WinXP Service Pack 2 (Build 2600), on A7648944D08843B (Intel level 15 )
SystemInfo.dll is Loaded
java部分
这里主要是申明接口. javah工具会根据你声明的接口自动生成对于的.h头文件
//SystemInfo.java
package com.khan.system;
public abstract class SystemInfo
{
// public: ................................................................
/**
* A simple class to represent data snapshots taken by {@link #makeCPUUsageSnapshot}.
*/
public static final class CPUUsageSnapshot {
public final long m_time, m_CPUTime;
// constructor is private to ensure that makeCPUUsageSnapshot()
// is used as the factory method for this class:
private CPUUsageSnapshot (final long time, final long CPUTime) {
m_time = time;
m_CPUTime = CPUTime;
}
} // end of nested class
// Custom exception class for throwing
public static final class NegativeCPUTime extends Exception {}
/**
* Minimum time difference [in milliseconds] enforced for the inputs into
* {@link #getProcessCPUUsage(SystemInfo.CPUUsageSnapshot,SystemInfo.CPUUsageSnapshot)}.
* The motivation for this restriction is the fact that <CODE>System.currentTimeMillis()</CODE>
* on some systems has a low resolution (e.g., 10ms on win32). The current value
* is 100 ms.
*/
public static final int MIN_ELAPSED_TIME = 100;
/**
* Creates a CPU usage data snapshot by associating CPU time used with system
* time. The resulting data can be fed into
* {@link #getProcessCPUUsage(SystemInfo.CPUUsageSnapshot,SystemInfo.CPUUsageSnapshot)}.
*/
public static CPUUsageSnapshot makeCPUUsageSnapshot() throws SystemInfo.NegativeCPUTime {
long prCPUTime = getProcessCPUTime ();
if (prCPUTime<0)
throw new NegativeCPUTime();
return new CPUUsageSnapshot (System.currentTimeMillis (), getProcessCPUTime ());
}
/**
* Computes CPU usage (fraction of 1.0) between <CODE>start.m_CPUTime</CODE> and
* <CODE>end.m_CPUTime</CODE> time points [1.0 corresponds to 100% utilization of
* all processors].
*
* @throws IllegalArgumentException if start and end time points are less than
* {@link #MIN_ELAPSED_TIME} ms apart.
* @throws IllegalArgumentException if either argument is null;
*/
public static double getProcessCPUUsage (final CPUUsageSnapshot start, final CPUUsageSnapshot end) {
if (start == null)
throw new IllegalArgumentException ("null input: start");
if (end == null)
throw new IllegalArgumentException ("null input: end");
if (end.m_time < start.m_time + MIN_ELAPSED_TIME)
throw new IllegalArgumentException ("end time must be at least " + MIN_ELAPSED_TIME + " ms later than start time");
return ((double)(end.m_CPUTime - start.m_CPUTime)) / (end.m_time - start.m_time);
}
/**
* Returns the PID of the current process. The result is useful when you need
* to integrate a Java app with external tools.
*/
public static native int getProcessID ();
/**
* Returns the number of processors on machine
*/
public static native int getCPUs ();
/**
* Returns CPU (kernel + user) time used by the current process [in milliseconds].
* The returned value is adjusted for the number of processors in the system.
*/
public static native long getProcessCPUTime ();
/**
* Returns CPU (kernel + user) time used by the current process [in perecents].
* The returned value is either CPU percentage, or zero if this is not supported by OS.
* Currently it is supported by Solaris8, and not supported by Windows XP
*/
public static native double getProcessCPUPercentage();
/**
* Returns maximum memory available in the system.
*/
public static native long getMaxMem ();
/**
* Returns current free memory in the system.
*/
public static native long getFreeMem ();
/**
* Returns system name info like "uname" command output
*/
public static native String getSysInfo ();
/**
* Returns CPU usage (fraction of 1.0) so far by the current process. This is a total
* for all processors since the process creation time.
*/
public static native double getProcessCPUUsage ();
/**
* Returns current space allocated for the process, in Kbytes. Those pages may or may not be in memory.
*/
public static native long getMemoryUsage();
/**
* Returns current process space being resident in memory, in Kbytes.
*/
public static native long getMemoryResident();
/**
* Sets the system native process PID for which all measurements will be done.
* If this method is not called then the current JVM pid will act as a default.
* Returns the native-dependent error code, or 0 in case of success.
*/
public static native int setPid(int pid);
/**
* Closes native-dependent process handle, if necessary.
*/
public static native int detachProcess();
// protected: .............................................................
// package: ...............................................................
// private: ...............................................................
private SystemInfo() {} // prevent subclassing
private static final String SILIB = "SystemInfo";
static {
// loading a native lib in a static initializer ensures that it is
// available done before any method in this class is called:
try {
System.loadLibrary (SILIB);
}catch (UnsatisfiedLinkError e){
System.out.println("native lib '" + SILIB
+ "' not found in 'java.library.path': "
+ System.getProperty ("java.library.path"));
}catch (Exception e){
System.out.println(e.getMessage());
}
}
} // end of class
//AppMain.java 测试文件
package com.khan.system;
public class AppMain {
/**
* Default constructor
*/
public AppMain() {
// TODO: Add constructor code here
}
public static void main(String[] args) {
try {
Thread.sleep(1000);
System.out.println("getMaxMem:" + SystemInfo.getMaxMem());
System.out.println("getCPUs:" + SystemInfo.getCPUs());
System.out.println("getSysInfo:" + SystemInfo.getSysInfo());
}catch (Exception e){
System.out.println(e.getMessage());
}
}
}
java部分工程文件. 等同与makefile
ant build.xml
<project name="IpNet" default="build" basedir=".">
<description>
simple example build file
</description>
<!-- set global properties for this build -->
<property name="name" value="IpNet"/>
<property name="src" location="src"/>
<property name="build" location="build"/>
<property name="dist" location="dist"/>
<property name="web" location="web/WEB-INF/lib"/>
<path id="master-classpath">
<fileset dir="./lib">
<include name="*.jar"/>
</fileset>
</path>
<target name="init">
<tstamp/>
<mkdir dir="${build}"/>
<mkdir dir="${dist}"/>
</target>
<target name="build" depends="init" description="compile the source " >
<javac srcdir="${src}" destdir="${build}">
<compilerarg value="-Xlint:unchecked"/>
<compilerarg value="-deprecation"/>
<classpath refid="master-classpath"/>
</javac>
<copy todir="${build}" preservelastmodified="true">
<fileset dir="${src}">
<include name="*.class"/>
</fileset>
</copy>
<jar jarfile="${dist}/${name}.jar" compress="true">
<fileset dir="${build}">
<include name="**"/>
</fileset>
</jar>
<copy todir="${web}" >
<fileset dir="${dist}">
<include name="${name}.jar"/>
</fileset>
</copy>
</target>
<target name="clean" description="clean up" >
<delete dir="${build}"/>
<delete dir="${dist}"/>
<delete file="${web}/${name}.jar"/>
</target>
</project>
在工程目录下ant 编译工程
build目录为本工程目标二进制文件目录. 编译后的class在此目录下
然后到build目录下
javah javah -jni com.khan.system.SystemInfo //注意, 一定要使用包全路径. 如果不是default包的话.
会在此目录下生成3个.h文件
com_khan_system_SystemInfo.h
com_khan_system_SystemInfo_CPUUsageSnapshot.h
com_khan_system_SystemInfo_NegativeCPUTime.h
java这边的准备工作完成
接下来处理c部分
新建一个c工程. 我用gcc的. 所以这些部分我手工完成的
将刚刚的.h文件实现
/* ------------------------------------------------------------------------- */
/*
* An implementation of JNI methods in com.vladium.utils.SystemInformation
* class. The author compiled it using Microsoft Visual C++ and GCC for Win32 but the code
* should be easy to use with any compiler for win32 platform.
*
* For simplicity, this implementaion assumes JNI 1.2+ and omits error handling.
*
* Enhanced by Peter V. Mikhalenko (C) 2004, Deutsche Bank [[email protected]]
* Original source (C) 2002, Vladimir Roubtsov [[email protected]]
*/
/* ------------------------------------------------------------------------- */
#include <windows.h>
#include <stdio.h>
#include <process.h>
#include <winbase.h>
#include <psapi.h>
#include <string.h>
#include "include/com_khan_system_SystemInfo.h"
static jint s_PID;
static HANDLE s_currentProcess;
static int alreadyDetached;
static int s_numberOfProcessors;
static SYSTEM_INFO systemInfo;
static WORD processorArchitecture;
static DWORD pageSize;
static DWORD processorType;
static WORD processorLevel;
static WORD processorRevision;
#define INFO_BUFFER_SIZE 32768
#define BUFSIZE 2048
//BOOL flll = TRUE;
/* ------------------------------------------------------------------------- */
/*
* A helper function for converting FILETIME to a LONGLONG [safe from memory
* alignment point of view].
*/
static LONGLONG fileTimeToInt64 (const FILETIME * time)
{
ULARGE_INTEGER _time;
_time.LowPart = time->dwLowDateTime;
_time.HighPart = time->dwHighDateTime;
return _time.QuadPart;
}
/* ......................................................................... */
/*
* This method was added in JNI 1.2. It is executed once before any other
* methods are called and is ostensibly for negotiating JNI spec versions, but
* can also be conveniently used for initializing variables that will not
* change throughout the lifetime of this process.
*/
JNIEXPORT jint JNICALL JNI_OnLoad (JavaVM * vm, void * reserved)
{
s_PID = _getpid ();
s_currentProcess = GetCurrentProcess ();
//externalCPUmon = 0;
alreadyDetached = 0;
GetSystemInfo (&systemInfo);
s_numberOfProcessors = systemInfo.dwNumberOfProcessors;
processorArchitecture = systemInfo.wProcessorArchitecture;
pageSize = systemInfo.dwPageSize;
processorType = systemInfo.dwProcessorType;
processorLevel = systemInfo.wProcessorLevel;
processorRevision = systemInfo.wProcessorRevision;
printf("SystemInfo.dll is Loaded");
return JNI_VERSION_1_2;
}
/* ......................................................................... */
JNIEXPORT void JNICALL
JNI_OnUnload (JavaVM * vm, void * reserved)
{
if (!alreadyDetached && s_currentProcess!=NULL) {
CloseHandle(s_currentProcess);
printf("[JNI Unload] Detached from native process.");
fflush(stdout);
}
printf("SystemInfo.dll is UnLoaded");
}
/* ......................................................................... */
/*
* Class: com_vladium_utils_SystemInformation
* Method: getCPUs
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_com_khan_system_SystemInfo_getCPUs(JNIEnv * env, jclass cls)
{
return (jint)s_numberOfProcessors;
}
/* ......................................................................... */
/*
* Class: com_vladium_utils_SystemInformation
* Method: getProcessID
* Signature: ()I
*/
JNIEXPORT jint JNICALL
Java_com_khan_system_SystemInfo_getProcessID(JNIEnv * env, jclass cls)
{
return s_PID;
}
/* ......................................................................... */
/*
* Class: com_vladium_utils_SystemInformation
* Method: setPid
* Signature: ()I
*/
JNIEXPORT jint JNICALL
Java_com_khan_system_SystemInfo_setPid(JNIEnv * env, jclass cls, jint pid)
{
DWORD errCode;
LPVOID lpMsgBuf;
s_PID = pid;
s_currentProcess = OpenProcess(PROCESS_ALL_ACCESS,FALSE,pid);
if (s_currentProcess==NULL) {
errCode = GetLastError();
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
errCode,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR) &lpMsgBuf,
0, NULL );
printf("[CPUmon] Could not attach to native process. Error code: %ld Error description: %s", errCode, (char *)lpMsgBuf);
fflush(stdout);
LocalFree(lpMsgBuf);
return errCode;
}
printf("[CPUmon] Attached to native process.");
fflush(stdout);
return 0;
}
/* ......................................................................... */
/*
* Class: com_vladium_utils_SystemInformation
* Method: detachProcess
* Signature: ()I
*/
JNIEXPORT jint JNICALL
Java_com_khan_system_SystemInfo_detachProcess(JNIEnv * env, jclass cls)
{
if (!alreadyDetached && s_currentProcess!=NULL) {
CloseHandle(s_currentProcess);
alreadyDetached = 1;
printf("[CPUmon] Detached from native process.");
fflush(stdout);
}
return 0;
}
/* ......................................................................... */
/*
* Class: com_vladium_utils_SystemInformation
* Method: getProcessCPUTime
* Signature: ()J
*/
JNIEXPORT jlong JNICALL
Java_com_khan_system_SystemInfo_getProcessCPUTime (JNIEnv * env, jclass cls)
{
FILETIME creationTime, exitTime, kernelTime, userTime;
DWORD errCode;
LPVOID lpMsgBuf;
BOOL resultSuccessful = GetProcessTimes (s_currentProcess, & creationTime, & exitTime, & kernelTime, & userTime);
if (!resultSuccessful) {
errCode = GetLastError();
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
errCode,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR) &lpMsgBuf,
0, NULL );
printf("[CPUmon] An error occured while trying to get CPU time. Error code: %ld Error description: %s", errCode, (char *)lpMsgBuf);
fflush(stdout);
LocalFree(lpMsgBuf);
return -1;
}
return (jlong) ((fileTimeToInt64 (& kernelTime) + fileTimeToInt64 (& userTime)) /
(s_numberOfProcessors * 10000));
}
/* ......................................................................... */
/*
* Class: com_vladium_utils_SystemInformation
* Method: getMaxMem
* Signature: ()J
*/
JNIEXPORT jlong JNICALL
Java_com_khan_system_SystemInfo_getMaxMem(JNIEnv * env, jclass cls)
{
MEMORYSTATUS stat;
GlobalMemoryStatus (&stat);
return (jlong)(stat.dwTotalPhys/1024);
}
/* ......................................................................... */
/*
* Class: com_vladium_utils_SystemInformation
* Method: getFreeMem
* Signature: ()J
*/
JNIEXPORT jlong JNICALL
Java_com_khan_system_SystemInfo_getFreeMem (JNIEnv * env, jclass cls)
{
MEMORYSTATUS stat;
GlobalMemoryStatus (&stat);
return (jlong)(stat.dwAvailPhys/1024);
}
/* ......................................................................... */
/* define min elapsed time (in units of 10E-7 sec): */
#define MIN_ELAPSED_TIME (10000)
/*
* Class: com_vladium_utils_SystemInformation
* Method: getProcessCPUUsage
* Signature: ()D
*/
JNIEXPORT jdouble JNICALL
Java_com_khan_system_SystemInfo_getProcessCPUUsage(JNIEnv * env, jclass cls)
{
FILETIME creationTime, exitTime, kernelTime, userTime, nowTime;
LONGLONG elapsedTime;
DWORD errCode;
LPVOID lpMsgBuf;
BOOL resultSuccessful = GetProcessTimes (s_currentProcess, & creationTime, & exitTime, & kernelTime, & userTime);
if (!resultSuccessful) {
errCode = GetLastError();
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
errCode,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR) &lpMsgBuf,
0, NULL );
printf("[CPUmon] An error occured while trying to get CPU time. Error code: %ld Error description: %s", errCode, (char *)lpMsgBuf);
fflush(stdout);
LocalFree(lpMsgBuf);
return -1.0;
}
GetSystemTimeAsFileTime (& nowTime);
/*
NOTE: win32 system time is not very precise [~10ms resolution], use
sufficiently long sampling intervals if you make use of this method.
*/
elapsedTime = fileTimeToInt64 (& nowTime) - fileTimeToInt64 (& creationTime);
if (elapsedTime < MIN_ELAPSED_TIME)
return 0.0;
else
return ((jdouble) (fileTimeToInt64 (& kernelTime) + fileTimeToInt64 (& userTime))) /
(s_numberOfProcessors * elapsedTime);
}
/* ......................................................................... */
/*
* Class: com_vladium_utils_SystemInformation
* Method: getProcessCPUPercentage
* Signature: ()D
*/
JNIEXPORT jdouble JNICALL
Java_com_khan_system_SystemInfo_getProcessCPUPercentage (JNIEnv * env, jclass cls)
{
// Not implemented on Windows
return (jdouble)(-1.0);
}
/* ......................................................................... */
/*
* Class: com_vladium_utils_SystemInformation
* Method: getMemoryUsage
* Signature: ()J
*/
JNIEXPORT jlong JNICALL
Java_com_khan_system_SystemInfo_getMemoryUsage (JNIEnv * env, jclass cls)
{
PROCESS_MEMORY_COUNTERS pmc;
if ( GetProcessMemoryInfo( s_currentProcess, &pmc, sizeof(pmc)) )
{
return (jlong)(pmc.PagefileUsage/1024);
} else {
return (jlong)(0);
}
}
/* ......................................................................... */
/*
* Class: com_vladium_utils_SystemInformation
* Method: getMemoryResident * Signature: ()J
*/
JNIEXPORT jlong JNICALL
Java_com_khan_system_SystemInfo_getMemoryResident(JNIEnv * env, jclass cls)
{
PROCESS_MEMORY_COUNTERS pmc;
if ( GetProcessMemoryInfo( s_currentProcess, &pmc, sizeof(pmc)) )
{
return (jlong)(pmc.WorkingSetSize/1024);
} else {
return (jlong)(0);
}
}
/*
* Class: com_vladium_utils_SystemInformation
* Method: getSysInfo
* Signature: ()S
*/
JNIEXPORT jstring JNICALL
Java_com_khan_system_SystemInfo_getSysInfo(JNIEnv * env, jclass cls)
{
char buf[2048];
char buf2[512];
jstring retval;
OSVERSIONINFOEX osvi;
BOOL bOsVersionInfoEx;
TCHAR infoBuf[INFO_BUFFER_SIZE];
DWORD bufCharCount = INFO_BUFFER_SIZE;
*buf = 0; //c语言. 变量定义所有代码在前
*buf2 = 0;
ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
if( !(bOsVersionInfoEx = GetVersionEx ((OSVERSIONINFO *) &osvi)) )
{
osvi.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
if (! GetVersionEx ( (OSVERSIONINFO *) &osvi) ) {
// Return empty string in case of problems
goto next_label;
}
}
switch (osvi.dwPlatformId)
{
// Test for the Windows NT product family.
case VER_PLATFORM_WIN32_NT:
// Test for the specific product.
if ( osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 2 )
strcat(buf,"WinServer2003, ");
if ( osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1 )
strcat(buf,"WinXP ");
if ( osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0 )
strcat(buf,"Win2K ");
if ( osvi.dwMajorVersion <= 4 )
strcat(buf,"WinNT ");
// Display service pack (if any) and build number.
if( osvi.dwMajorVersion == 4 && lstrcmpi( osvi.szCSDVersion, "Service Pack 6" ) == 0 )
{
HKEY hKey;
LONG lRet;
// Test for SP6 versus SP6a.
lRet = RegOpenKeyEx( HKEY_LOCAL_MACHINE, "SOFTWAREMicrosoftWindows NTCurrentVersionHotfixQ246009", 0, KEY_QUERY_VALUE, &hKey );
if( lRet == ERROR_SUCCESS ) {
sprintf(buf2, "SP 6a (Build %d), ", (int)(osvi.dwBuildNumber & 0xFFFF) );
strcat(buf,buf2);
}
else // Windows NT 4.0 prior to SP6a
{
sprintf(buf2, "%s (Build %d), ",
osvi.szCSDVersion,
(int)(osvi.dwBuildNumber & 0xFFFF));
strcat(buf,buf2);
}
RegCloseKey( hKey );
}
else // not Windows NT 4.0
{
sprintf(buf2, "%s (Build %d), ", osvi.szCSDVersion, (int)(osvi.dwBuildNumber & 0xFFFF));
strcat(buf,buf2);
}
break;
// Test for the Windows Me/98/95.
case VER_PLATFORM_WIN32_WINDOWS:
if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 0)
{
strcat(buf,"Win95 ");
if ( osvi.szCSDVersion[1] == 'C' || osvi.szCSDVersion[1] == 'B' )
strcat(buf,"OSR2 " );
}
if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 10)
{
strcat(buf,"Win98 ");
if ( osvi.szCSDVersion[1] == 'A' )
strcat(buf,"SE " );
}
if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 90)
{
strcat(buf,"WinME ");
}
break;
case VER_PLATFORM_WIN32s:
strcat(buf,"Win32s ");
break;
}
next_label:
strcat(buf,"on ");
// Get and display the name of the computer.
bufCharCount = INFO_BUFFER_SIZE;
if( !GetComputerName( infoBuf, &bufCharCount ) )
goto next_label_2;
strcat(buf, infoBuf );
next_label_2:
strcat(buf," (");
if (!(osvi.dwPlatformId==VER_PLATFORM_WIN32_WINDOWS && osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 0)) {
// Win95 does not keep CPU info in registry
LONG lRet;
HKEY hKey;
char szOrigCPUType[BUFSIZE];
int i=0;
DWORD dwBufLen=BUFSIZE;
lRet = RegOpenKeyEx( HKEY_LOCAL_MACHINE, "HARDWAREDESCRIPTIONSystemCentralProcessor", 0, KEY_QUERY_VALUE, &hKey );
if( lRet != ERROR_SUCCESS ) {
goto next_label_3;
}
lRet = RegQueryValueEx( hKey, "ProcessorNameString", NULL, NULL, (LPBYTE) szOrigCPUType, &dwBufLen);
if( (lRet != ERROR_SUCCESS) || (dwBufLen > BUFSIZE) ) {
goto next_label_3;
}
RegCloseKey( hKey );
if (strlen(szOrigCPUType)>0) {
while(szOrigCPUType[i]==' ' && szOrigCPUType[i]!=0)
i++;
strcat(buf,szOrigCPUType+i);
} else
goto next_label_3;
} else {
next_label_3:
if (processorArchitecture==PROCESSOR_ARCHITECTURE_UNKNOWN)
strcat(buf,"unknown_arch");
else if (processorArchitecture==PROCESSOR_ARCHITECTURE_INTEL) {
strcat(buf,"Intel ");
sprintf(buf2,"level %d ",processorLevel);
strcat(buf,buf2);
} else if (processorArchitecture==PROCESSOR_ARCHITECTURE_IA64)
strcat(buf,"IA64 ");
else if (processorArchitecture==PROCESSOR_ARCHITECTURE_MIPS)
strcat(buf,"MIPS ");
else if (processorArchitecture==PROCESSOR_ARCHITECTURE_ALPHA)
strcat(buf,"Alpha ");
else if (processorArchitecture==PROCESSOR_ARCHITECTURE_PPC)
strcat(buf,"PowerPC ");
else if (processorArchitecture==PROCESSOR_ARCHITECTURE_SHX)
strcat(buf,"SHX ");
else if (processorArchitecture==PROCESSOR_ARCHITECTURE_ALPHA64)
strcat(buf,"Alpha64 ");
else
strcat(buf,"unknown_arch ");
}
strcat(buf,")");
retval = (*env)->NewStringUTF(env,buf);
return retval;
}
/* ......................................................................... */
#undef MIN_ELAPSED_TIME
/* ------------------------------------------------------------------------- */
/* end of file */
编写makefile
# Project: SystemInfo
# Makefile created by Khan.Lau
# Write by 2007-05-16
# 应用程序名
#LIB = SystemInfo.a
DLL = SystemInfo.dll
#BIN = SystemInfo.exe
# 输出目录
# CONFIGURATION = debug
CONFIGURATION = release
# 取得项目的当前工作路径
PROJECT_PATH = "D:/Project/Cplus/SystemInfo/src"
CPP = g++
CC = gcc
COMPILER = $(CC)
# c/c++库路径
LIBPATH = "D:/Develop/CPlus/MinGW/lib"
WINDRES = windres.exe
RES =
# 包路径
LIBS = -L$(LIBPATH) \
-lpsapi
INCS = -I$(LIBPATH)/include \
-ID:/Develop/Java/jdk1.5.0_02/include \
-ID:/Develop/Java/jdk1.5.0_02/include/win32 \
-I$(PROJECT_PATH)
CXXINCS = -I$(LIBPATH)/include \
-I$(LIBPATH)/include/c++/3.2.3 \
-I$(LIBPATH)/include/c++/3.2.3/backward \
-I$(LIBPATH)/include/c++/3.2.3/mingw32 \
-I$(PROJECT_PATH)
DLLFLAGS = -DBUILD_DLL
CXXFLAGS = $(DLLFLAGS) -g -Wall $(CXXINCS)
CFLAGS = $(DLLFLAGS) -Wall $(INCS)
COMPILER_FLAG = $(CFLAGS)
RM = rm -f
LINKOBJ = $(CONFIGURATION)/SystemInfo.o \
$(RES)
.PHONY: all all-before all-after clean clean-custom rebuild
all: all-before $(DLL) all-after
clean: clean-custom
${RM} $(LINKOBJ) $(CONFIGURATION)/$(DLL)
$(LIB): $(LINKOBJ)
ar -r $(CONFIGURATION)/$(LIB) $(LINKOBJ)
$(DLL): $(LINKOBJ)
$(COMPILER) -shared -Wl,--add-stdcall-alias -o $(CONFIGURATION)/$(DLL) $(LINKOBJ) $(LIBS)
$(BIN): $(LINKOBJ)
$(COMPILER) -o $(CONFIGURATION)/$(BIN) $(LINKOBJ) $(LIBS)
#缩减可执行文件大小
strip:
strip $(CONFIGURATION)/$(LIB)
################################################################################
$(CONFIGURATION)/SystemInfo.o: src/dll/SystemInfo.c
$(COMPILER) -c src/dll/SystemInfo.c -o $(CONFIGURATION)/SystemInfo.o $(COMPILER_FLAG)
################################################################################
rebuild: clean all
makefile中注意
$(DLL): $(LINKOBJ)
$(COMPILER) -shared -Wl,--add-stdcall-alias -o $(CONFIGURATION)/$(DLL) $(LINKOBJ) $(LIBS)
-shared -Wl,--add-stdcall-alias 这3个参数是一定要的. 具体含义请参阅gcc帮助..
否则会出现如下异常:java.lang.UnsatisfiedLinkError
如果你确认自己的dll名没有错. loadlibrary的名字也没有填错. 那应该就要检查如上部分了
实际发布的时候. 不要使用调试版本. 也就是编译参数不能有-g
ok, 现在make出dll使用吧....
我本地测试的输出结果为 :
getMaxMem:506604
getCPUs:1
getSysInfo:WinXP Service Pack 2 (Build 2600), on A7648944D08843B (Intel level 15 )
SystemInfo.dll is Loaded