This question already has answers here:
Get OS-level system information
(17 answers)
Closed 8 years ago.
I would like using Java to get data from Windows about CPU, RAM, HDD, Network and list of processes(services). How I can get these system values values without using third-party libraries or JNI?
Is there something similar to /proc in Windows where I can get all necessary values and use them?
You can use native API's using JNI.
You can also use SIGAR which is Apache licensed library which does much more then what you are asking for.It has wrapped the native calls in Java API's so that you dont have to know the inner workings of JNI.
You can also spawn processes from inside the code to run OS specific commands so that you can collect the system stats e.g. systeminfo |find "Available Physical Memory" or wmic command on windows or Linux cat /proc/meminfo . This can be achieved via java.lang.ProcessBuilder.
I dont think you can get everything you want from a single location in the standard java API, but you could use the following classes for some of your requirements:
For the number of processors / processor stats / memory, etc:
http://docs.oracle.com/javase/7/docs/api/java/lang/Runtime.html\
For information about physical disks and whatnot:
http://docs.oracle.com/javase/7/docs/api/java/io/File.html
Another, really, really ugly option would be to make platform specific invokations of utilities via a Process object, and parse their output. EG invoke the top command via a process, read and parse its output.
There is Windows Management Instrumentation API (WMI) for this kind of stuff. See e.g. .NET bindings here: MSDN - System.Management Namespace
Older Stack Overflow answer to similar question is available here: Recommended libraries/howtos for using WMI with java?
Look for newer Java bindings. There used to be J# as one of the .NET languages that was source-level compatible with Java. So in theory there should not be a big problem to find suitable Java→.NET→WMI bridge
This API is very powerful and besides some basic stuff like processes, sound devices, disk drives etc. you can access approximately same set of information that you can get by running msinfo32.exe.
So this is not Java-specific answer this is Windows-specific answer. All Windows versions support .NET and .NET can access that information through WMI easily.
For instance list of processes can be accessed easily through MSDN - System.Diagnostics.Process.GetProcesses
There used to be special Win32 APIs for native binaries and though still supported they are the history now. Piping output from one command line app to input of another is not the usual way to connect processes. In case this is really needed there is Microsoft Technet - Scripting with Windows PowerShell
I hope this will help you find some solution of your problem
There are several options for getting system information in Java (the Runtime class, the java.lang.management package, etc.).
However, this is usually very limited information, and tends not to cover the things you seem to require.
You should consider using a 3rd party solution, such as the following:
SIGAR - http://www.hyperic.com/products/sigar (requires native DLL to be installed)
OSHI - https://github.com/oshi/oshi
Well, I would suggest you to try JavaSysMon:
https://github.com/jezhumble/javasysmon
Manage OS processes and get cpu and memory stats cross-platform in Java. So the good thing about it is , its cross-platform.
Currently it supports Mac OS X, Linux, Windows, and Solaris.
So that is a positive. If this can do your work, you can actually use the cross-platform feature for your application.
Maybe its not as good as Sigar, but give it a try.
Related
I come from a C/Linux background and don't have much background in Java. I generally develop system administrator utilities like :
disk cleanup
retrieve lost data / files
repairing file systems
disk de-fragmentation
I also develop Network monitoring security applications which help admins monitor :
- their networks,
- scan incoming & outgoing data packets,
- remotely block ports / USBs
- monitor emails with attachments etc
Right now we write code in C for Linux which has to be ported to windows but such a problem will not exist in Java.
My questions are :
Is Java the right language for writing these applications & utilities (as mentioned above)?
I understand Java will provide Libraries and classes to access system resources / network / sockets but will Java abstraction be a hindrance at some point (which would restrict the flexibility which C/C++ provide )?
If for example I want to write a utility to repair a file system / or retrieve data for Windows & Unix ...will I be using same API for both OS or there are different API for different OS?
I am not concerned about the speed / execution trade off since none of my applications have to make real time decisions as in the gaming industry.
Java is the right language if you want portability. You can do almost everything you can do with C/C++ and you can utilize patterns and libraries that help you create great maintainable designs. In case there is something very low level you cannot do with Java, you always can create your own native code that is loaded with Java Native Interface. Thus the only non-portable code you will have will be these native-code libraries.
Right now we write code in C for Linux which has to be ported to
windows but such a problem will not exist in Java.
Java can abstract away only so much since in the end, low level stuff always boils down to making system calls, which are different between OSes.
As long as you're working with pure java logic, or simple operating system utilities, you'll be golden. You want to open a TCP socket and connect to google.com? No problem. You want to open a file in a known location, read some lines, process them, and write the results to a different file? No problem, Java has you covered.
But, if you want to do more low-level stuff with Java, you'll run into trouble pretty soon. You want to open a raw socket and send a TCP packet? You can't, windows doesn't allow that. You want to get a file's creation time on Linux? You can't, Linux doesn't keep that information. Java's BasicFileAttributes.creationTime() will return a file's modification time on Linux. You want to get a nanosecond resolution timestamp? Well, you can, but only on some OSes. Or say you want to get the computer's hostname without resorting to a network lookup (which depends on a network being actually available), well, get ready for some hacking (this is my own answer by the way).
Now, to your more specific questions:
Is Java the right language for writing these applications & utilities (as mentioned above)?
I frankly don't know. I never tried defragmenting or restoring a file programmatically from Java. But since it involves some very low level filesystem operations, I suggest you do some serious reading before moving to Java. Check whether the APIs you need exist in the language itself or in some good libraries.
I understand Java will provide Libraries and classes to access system
resources / network / sockets but will Java abstraction be a hindrance
at some point (which would restrict the flexibility which C/C++
provide )?
Yes. For instance, it's impossible to open a raw socket using pure Java. And if I recall correctly, it's also impossible to set some socket options.
If for example I want to write a utility to repair a file system / or
retrieve data for Windows & Unix ...will I be using same API for both
OS or there are different API for different OS?
I never tried repairing a file system in Java, so I can't tell you about the APIs involved. But I find it hard to believe you'll find a pure Java api for doing low level stuff with the file system. You'll probably have to write your own native code (and run it through JNI) or use someone else's library (which probably uses JNI, like the raw socket library I mentioned earlier).
I'd like to obtain the host's full network usage, that is, the current upload and download rates. How can I do that in Java? If it makes that easier, assume the platform is Linux.
How can I do that in Java?
Doing this in Java is a bad idea ... unless there is a strong requirement to have the information in a larger Java application.
You can't do it in pure Java. There are no standard Java APIs for accessing this kind of information.
I Googled for something Java-specific and free that matched your requirements, but didn't spot anything. (YMMV ... please feel free to repeat the search for yourself!).
There are OS specific tools for looking at network stats, etcetera, and one could attempt to run these tools as external processes from Java and "scrape" the output. But that would necessarily be OS / tool specific.
You could attempt to replicate what these tools are doing in Java, but this may involve native library calls, and would certainly be OS specific. (On Linux, you may be able to get the information you need by reading from the /proc file system ... but there could also be access control issues.)
Nethogs: http://nethogs.sourceforge.net/ is probably the tool you're looking for.
Most people use prefer this as it splits bandwith usage up by process.
Suppose i want to search some text in a file. I want to know when we should use system utilities/programs like grep and when we should use Java API's like reading a line, and then search the text in that line or use java Scanner class.
I want to understand the trade-offs between the two approaches. I mean, suppose if we use grep, then will there be communication overhead between JVM and the grep process? Is creation of a new OS process for grep an overhead?
Does grep performs better than normal java file search?
Please help...
Yes, there will be an overhead. Starting an external process and communicating with it is costly. And moreover, many systems don't have a grep command. If you want to make your Java code portable, don't rely on OS-specific commands.
Another problem is that OS commands will be able to search (for example) in files, but not in your in-memory data structures.
You're basically trading off system independence for the perceived gain of the tool, in some cases this can't be avoid.
Not every system will have the tools you want installed, in the locations you think they should be or the version you need.
Even if you can deploy the tools with your application, you will need to provide an implementation for each of your targeted platforms.
Sure, it's easy to say "it will never be run on X", but can never come around real quick ;)
There is also the added over head of executing and managing the IO of the external applications, while not difficult, it's much more complex that a well written Java API.
As I said, sometimes, you simply don't have a choice (I have some media inspection tools that I use on Windows and Mac that I'm not about to try and implement in Java, not because it can't be, but because it's complex and time consuming and somebody has already done it (with a native program)).
You need to balance the choice over what the benefits are of the external command weight against the issues of using it. You should also investigate if a API has already begin developed that might solve the problem at hand.
IMHO
We have a situation where we would like to be able to create a zip file containing as much information as possible about a currently running Java program (which may be on its way down) to allow for post-mortem forensic analysis. We currently deploy to Java 5 but Java 6 features are interesting too.
So far I've thought of:
A programmatically generated thread dump. This appears to work better in Java 6.
The logged log events for the last X minutes. We currently use logback or java.util.logging.
Some serialized objects.
External environment - all system properties.
What else would be useful of JVM information?
Would it be possible in a generic way to walk the call stacks and see the arguments? (or does this require JVMTI or equivalent). It is a IBM JVM so we cannot use jvisualvm and the Attach API.
You could go all the way and capture a full heap dump? I realize you are on an IBM JVM, but this page seems to indicate there is a way.
I am looking to get into operating system kernel development and figured my contribution would be to extend the SANOS operating system in order to support JDK 1.6 and 1.7. I have been reading books on operating systems (Tannenbaum) as well as studying how BSD and Linux have tackled this challenge but still am stuck on several concepts.
What is the fastest way to tell what additional system calls I would need to support as SANOS starts more from the bottoms up?
If I have a list of system calls that need to be supported, what is the best way to roll them up if they are similar in nature?
The minimum number of system calls any reasonable *nix style OS should have are (IMHO):
open
close
read
write
fork
exec
waitpid
the first 4 allow you to both provide input to a program and get its output. (Remember on *nix like operating systems stdout is just another file handle as far as the OS is concerned).
The other 3 are the bare minimum needed to start another program and wait for its result. However, it is certain that SanOS already has these since it is already a very functional operating system.
It is entirely possible that the additions you need to make won't need to be done at a kernel level.
EDIT:
As far as what is needed to support a newer JVM, this paragraph from the SanOS site gives a great hint:
You can run the Windows version of Sun
HotSpot JVM under sanos. This is
possible because sanos supports the
standard PE executable format (.EXE
and .DLL files). Wrappers are provided
for the Win32 DLLs like kernel32.dll,
user32.dll, wsock32.dll, etc., as well
as the C runtime library msvcrt.dll. I
have tested sanos with the following
JVMs:
Basically, the JVMs are the standard windows exe files. So you would just need to find out which system calls the referenced dlls make and ensure that they exist and are implemented correctly.