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).
Related
I am planning to create a software that will be compatible with both Windows CE and Android devices.
Nothing has been decided yet, but so far I've imagined that I could write most parts of the program using C++ code that could be reused on these two platforms, except for system-dependant things like threads. C++ is highly recommended for performance in my case.
In the case of system-dependent things I would create interfaces that would be implemented in two different ways, one using the win32 API, and the other one using the linux equivalent. The other parts of the code the logic) would be independent and reused on both platforms.
The only part of the application that would not be written in C++ would be the user interface. Using the Android API on Android platforms, and something else on Windows CE (C#, Java, don't know yet).
I've read that Android is not like other linux distributions because many linux features are not available from native code on it.
So my question is : is it possible to natively create and use sockets, threads, critical sections (and any other system-dependant things) from a native linux api using JNI (i.e the equivalent of the win32 api but for linux) or do i always have to create them into the Java layer and pass them down to the native code ?
I've not yet decided how II am going to build this, i'm just informing myself on the different possibilities.
Thank you.
NDK implemented POSIX (include pthread, mutex) and BSD socket, so you don't necessary create them with java objects.
However, STL support is still crappy IMO, which you may need to pay attention with your own code or porting any dependency libraries.
It is possible to do all of this with JNI, but I would think twice before doing so. Using JNI has its share of liabilities; it will make development and debugging considerably more difficult. You will also end up with a lot of callbacks to Java code to communicate with the GUI. Think of features like visual progress indicators for ongoing operations. And don't forget that in the end, your app's performance may suffer because of the extra indirection required by each JNI call. Be sure to measure performance in either case. JNI, or C++ for that matter, does not automatically make anything faster.
Also, it may be harder than what you think to just "mirror" your app on another operating system. Android, as an operating system, behaves differently not only on the GUI side (it is, for example, nonsense to provide a back button within in an Android app), but also on the inside, with its typical app architecture broken down into Services, Activities and Receivers. It's not just "a different GUI", not at all.
If you have backend functionality that really can and should behave identically on both platforms, then go on, write it in C++ and reuse it on Android via JNI. But it may be easier, and it may be equally or more performant, to just implement it or parts of it from scratch on Android, using Java. Without knowing any details about your project, it is impossible to say.
Why don't you try and implement a simple test app on Android using JNI? Try to use the NDK to send an HTTP request in a background thread and write the respone back to Java as a String. You'll eventually see that it works, but you will also have a better understanding of the difficulties involved.
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.
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.
I have an existing library written in C# which wraps a much lower-level TCP/IP API and exposes messages coming down the wire from a server (proprietary binary protocol) as .NET events. I also provide method calls on an object which handles the complexities of marshalling convenient .NET types (like System.DateTime) down to the binary encodings and fixed-length structures that the API requires (for outgoing messages to the server). There are a fair number of existing applications (both internally and used by third parties) built on top of this .NET library.
Recently, we've been approached by someone who doesn't want to do all the legwork of abstracting the TCP/IP themselves, but their environment is strictly non-Windows (I assume *nix, but I'm not 100% sure), and they've intimated that their ideal would be something callable from Java.
What's the best way to support their requirements, without me having to:
Port the code to Java now (including an unmanaged DLL that we currently P/Invoke into for decompression)
Have to maintain two separate code-bases going forwards (i.e. making the same bug-fixes and feature enhancements twice)
One thing I've considered is to re-write most of the core TCP/IP functionality once into something more cross-platform (C / C++) and then change my .NET library to be a thin layer on top of this (P/Invoke?), and then write a similarly thin Java layer on top of it too (JNI?).
Pros:
I mostly spend my time writing things only once.
Cons:
Most of the code would now be unmanaged - not the end of the world, but not ideal from a productivity point of view (for me).
Longer development time (can't port C# sockets code to C / C++ as quickly as just porting to Java) [How true is this?]
At this point, the underlying API is mostly wrapped and the library is very stable, so there's probably not a lot of new development - it might not be that bad to just port the current code to Java and then have to make occasional bug-fixes or expose new fields twice in the future.
Potential instability for my existing client applications while the version they're running on changes drastically underneath them. (Off the top of my head I can think of 32/64 bit issues, endianness issues, and general bugs that may crop up during the port, etc.)
Another option I've briefly considered is somehow rigging Mono up to Java, so that I can leverage all of the existing C# code I already have. I'm not too clued up though on how smooth the developer experience will be for the Java developers who have to consume it though. I'm pretty sure that most of the code should run without trouble under Mono (bar the decompression P/Invoke which should probably just be ported to C# anyway).
I'd ideally not like to add another layer of TCP/IP, pipes, etc. between my code and the client Java app if I can help it (so WCF to Java-side WS-DeathStar is probably out). I've never done any serious development with Java, but I take some pride in the fact that the library is currently a piece of cake for a third-party developer to integrate into his application (as long as he's running .NET of course :)), and I'd like to be able to keep that same ease-of-use for any Java developers who want the same experience.
So if anyone has opinions on the 3 options I've proposed (port to Java & maintain twice, port to C and write thin language bindings for .NET and Java or, try and integrate Java and Mono), or any other suggestions I'd love to hear them.
Thanks
Edit: After speaking directly with the developer at the client (i.e. removal of broken telephone AKA Sales Department) the requirements have changed enough that this question no longer applies very well to my immediate situation. However, I'll leave the question open in the hopes that we can generate some more good suggestions.
In my particular case, the client actually runs Windows machines in addition to Solaris (who doesn't these days?) and is happy for us to write an application (Windows Service) on top of the library and provide a much more simplified and smaller TCP/IP API for them to code against. We will translate their simple messages into the format that the downstream system understands, and translate incoming responses back for them to consume, so that they can continue to interface with this downstream system via their Java application.
Getting back to the original scenario after thinking about this for a couple of weeks, I do have a few more comments:
A portable C-based library with different language bindings on top would probably be the way to go if you knew up front that you'd need to support multiple languages / platforms.
On *nix, can a single process host both a Java runtime and a Mono runtime simultaneously? I know in earlier versions of .NET you couldn't have two different .NET runtimes in the same process, but I believe they've fixed this with .NET 4? If this is possible, how would one communicate between the two? Ideally you'd want something as simple as a static method call and a delegate to raise responses with.
If there's no easy direct interface support between Java & Mono (methods & delegates, etc.), one might consider using something like ZeroMQ with Protocol Buffers or Apache Thrift as the message format. This would work in-process, inter-process and over the network because of ZeroMQ's support for different transports.
Spend more time getting the requirements nailed down before deciding on an implementation. Until you know what is required, you don't have any criteria for choosing between designs.
If it's a non-windows environment, it doesn't make sense to have .NET anywhere in there, for example.
If you need something that runs on the Java Virtual Machine but looks a lot like C#, you should check out Stab. This will not help you with P/Invoke and the like but you may find it less work to port your C# code to Java and maintain it.
You should look into Mono though. I expect that all your C# code would run unmodified (except the parts that touch the unmanaged DLL).
I have not used it but jni4net is supposed to allow calling .NET code from Java. If your clients want a Java interface, this may be a solution.
I use Mono on Linux and the Mac all the time even when .NET compatibility is not a priority. I like C# and the .NET libraries and prefer the CLR to the JVM. Mono is MIT/X11 licensed which means that you can use it commercially if you like. Unlike some others, I see no reason to avoid technology championed by Microsoft while favouring technology championed by Oracle and IBM.
Using Mono will not help you with the unmanaged bits, although you can still P/Invoke into a native DLL. You will just have to port that DLL yourself or find some equivalent.
You may also want to look into Mono Ahead of Time compilation.
Have you considered mono? It would most likely support your existing code in the non-windows environment. The trick would be calling it from java, but the mono folks might have something to help you out there, too.
This probably isn't the right solution in your case, but for completeness:
There are a few languages that can target both the JVM and .NET, in particular Ruby (JRuby and IronRuby) and Python (Jython and IronPython). Scala might eventually get there too, although right now the .NET version is a long way behind the JVM version.
Anyway, you could potentially rewrite your library in Ruby or Python and target both runtimes.
If what you really, really want is to be able to code in .NET and have it run on the JVM, you could check out Grasshopper (2015-09: link possibly dead). That is what it is designed to do.
I know the Mainsoft guys have been contributors to Mono over the years. If I remember correctly, they wrote the Visual Basic compiler for Mono.
There is also the C# to Java converter from Tangible. I have heard good things but I have never used it myself.
Also, it does not help your situation much but I should point out Mono for Android.
Mono for Android runs the CLR and the Dalvik VM in parallel. In other words, the C# code you wrote for Android can be calling into Java libraries (like the Android UI for example) and executing as a single app. You had asked about the ability to run .NET and Java code in the same process. Clearly, it can be done.
One thing I've considered is to re-write most of the core TCP/IP functionality once into something more cross-platform (C / C++) and then change my .NET library to be a thin layer on top of this (P/Invoke?), and then write a similarly thin Java layer on top of it too (JNI?).
That's a possibility. On the Java side, you should consider using JNA rather than JNI. (If you use JNI, the C / C++ code needs to be written to use JNI-specific signatures.)
Another possibility is to replace the proprietary binary protocol with something that "just works" with multiple programming languages. This is the kind of problem space where CORBA and similar technologies provide a good solution.
Some modern network cards support Direct Memory Access for improved performance. How can I utilize this feature from Java?
Does the JVM provide this automatically, or do I need to do an allocateDirect on the ByteBuffers that I am using to talk to that NIC?
Does anyone have documentation that discusses this?
It is the operating systems task to use the DMA feature of the network card. The JVM does not really care how the OS does it, and simply uses the operating system's functions for talking to "network interfaces".
You cannot do this from inside Java in the typical desktop/server JVMs, as this is operating system area which requires you to reach out into C code. Go have a look on JNI or JNA to see how to do this. Please note that this may make your application brittle if you do not get this exactly right.
Yeah - ankon's answer is right. Java operates in a sandbox - a virtual machine (hence the, "VM" in JVM; Sun actually built ONE physical version -- it's on display somewhere).
Java was never designed (intentionally) to reach outside the sandbox, unlike ActiveX, which can go just about anywhere on a PC.
Just think of all the bad things ActiveX has done over the years via a browser. You wouldn't want that to happen with Java, would you?
Although...
you might be able to instantiate an object in Java that does have access to the hardware (like one of those ActiveX controls, or some DLL, for example - which you'd have to write, too).
The problem I see is the throughput. With 100MB or 1000MB cards, would a JVM (remember, this is a VM running on an OS, so you're a couple of layers removed from the hardware) have the speed to handle what's coming in under load? Would you want a Java program holding up data in your NIC while it tinkered with it (think of the impact to the rest of the system)?
At this point, you're probably better off writing the hard-working guts of your solution in C. And, if you still need Java to play with that data, put it in a place where Java can get to it.
If you're not getting the network throughput you need in java, then you're going to need to write a C wrapper in order to access it.
Have you benchmarked your code to find where your performance issues really are? If you let us know that we can likely help you out without resorting to JNI.