As far as I know, ReadableByteChannel and WritableByteChannel from the nio package can be considered a replacement of InputStream and OutputStream from the legacy io package. If fact, they can be used to do the same I/O operations and more.
Nevertheless, they still seem not much used. Also, their support in popular libraries is quite poor. For example, the Guava team is even thinking about dropping it.
Is there any reason for new code dealing with I/O to use Streams with respect to Channels?
There is a historical context that should not be ignored. When NIO was introduced (back in Java 1.4), a lot of features were missing and the promise to hand them in later was not hold for a long time. Recall that in Java 1.4 the way to get a FileChannel was to first create a FileInputStream, FileOutputStream, or RandomAccessFile and invoke getChannel on it. Thus, there was no way to write code using NIO/channels without using the older IO/stream API.
The first Java version providing a way to create a FileChannel without using the old API is Java 7. This is also the first version providing an NIO API for directory scan, change notifications and advanced file attributes.
So the NIO API can be considered quite new regarding these features and it’s not that surprising that it takes some time for developers adopting it. By the way, this kind of adoption might include removing utility methods which became unnecessary with the new API like the proposal you have linked. As far as I can see it really means removing just four methods whose functionality is trivial when using the most recent API.
Obviously, when you want to use one of the newer features like memory mapping or the Java 7 features named above you have to use the NIO API. On the other hand, when you want to use Serialization or Zip/GZip (de)compression the only channel support, Java offers, is to wrap your channel into a stream…
It really depends on what you are doing. If you are dealing directly with files and/or sockets, there are many advantages to using nio. In some cases (especially around sockets) new functionality is /only/ being exposed through nio. Some of those advantages are muted if you also compress or encrypt data, where most apis only support streams. Historically the servlet-api spec was all based on streams. However, there is growing support for nio in that space as well.
Immediate performance benefits are gained by using NIO Channels with ByteBuffers. Also if you need to block on multiple things Selectors can be handy.
Related
In Java IO, we use Stream and Reader while in NIO we use Channel, Selector.
They both do the same thing, but the structure is totally different.
So why they don't write a new Stream like "AsyncStream" or a Reader like "AsyncReader" to implement what NIO have implemented. If so, we only have one structure and it's beautiful.
So why Java IO cannot implement async reading?
What are the difficulties to implement async reading using Java IO ?
Or what is the advantage of writing a new framework instead of using the existing one?
I tried to understand your idea in the comment above, but I'm afraid that there is insufficient detail to understand it as a proposal. Without that, it is impossible to make a judgment on whether it would work or not.
However, there are a couple of points that can be made in response:
IF Java was a shiny new (and unreleased) language, THEN they could improve on the I/O API design in a few areas.
In addition, IF someone came up with a well-considered, fleshed out API design that combined sync and async capabilities, THEN that could be considered.
But Java is NOT a shiny new language. It is an old programming language, with billions of lines of source code written in it. The kind of change that you are contemplating on a central API would either create huge binary compatibility problems for Oracle's paying customers, or it would lead to a huge legacy code problem. It simply would not happen.
Setting that aside, if you attempted to merge sync and async capabilities into a single API, you risk creating a situation where:
custom stream types need to implement a lot of extra functionality, and / or
the merger leads to unanticipated performance issues.
Now these concerns may not be warranted.
However, we cannot tell without seeing a concrete API design proposal and an implementation to try out for usability and performance. Bear in mind that the original elegant API design for I/O streams and (then) readers / writers actually turned out to have a variety of problems. These did not become apparent until people used the APIs in production code. For example:
character encoding concerns lead to the introduction of Reader / Writer in Java 1.1.
performance analyse identified that memory memory-to-memory copying was a problem, leading to the introduction of Buffer and so on.
In summary, it is really hard to design a good I/O API ... and Java is unlikely to change anyway.
As we had known, If we want to use traditional IO to construct server, it must block somewhere, so we had to use loop or one thread one socket mode, So nio seem it is better choice. So I want know if the nio is better choice forever?
IMHO, Blocking IO is generally the simplest to use, and unless you have a specific requirement which demands more from your system, you should stick with simplest option.
The next simplest option is blocking NIO, which I often prefer if I want something more efficiency or control than IO. It is still relatively simple but allows you to use ByteBuffers. e.g. ByteBuffers support little endian.
A common option is to use non-blocking NIO with Selectors. Much of the complexity this introduces can be handled by frameworks such as Netty or Mina. I suggest you use such a library if you need non-blocking IO e.g. because you have thousands of concurrent connections per server. IMHO You have thousands of connections, you should consider having more servers unless what each connection does is pretty trivial. AFAIK google go for more servers rather thousands of users per server.
The more extreme option is to use NIO2. This is even more complex and lengthy it write than non-blocking NIO. I don't know of any frameworks which support this well. i.e. it is actually faster when you do. AFAIK It appears this is worth using if you have Infiniband (which is what it was designed to support) but perhaps not worth using if you have Ethernet.
If you want non-blocking IO, NIO is not the better choice—it's the only choice in Java. Keep in mind that people still use the old IO regularly because it is way simpler to code against. NIO API is quite raw and is more of an enabling low-level technology than a client-side API. I suggest using NIO through an API that provides a simpler interface to the problems you want to solve using non-blocking IO.
A little late, but personally, I use NIO even for the regular "everyday" file handling. So, I use things like:
1. if(Files.notExists(path)) { }
2. Files.createDirectory(path);
3. Files.newInputStream(path) targetPath.resolve("somefile.txt");
4. Files.newBufferedWriter(path, charset);
5. DirectoryStream<Path> directoryStream = Files.newDirectoryStream(path);
and it works fine for me. I prefer Path instead of the old File because of methods like relativize or resolveSibling.
Doesn't strike me as more complicated than IO.
You would only use NIO if you can justify the inevitable complexity that it introduces. If you do not have any guidance in terms of the expected load, and also in terms of whether your product / project has the resources to maintain the relevant code, then your should err on the side of caution and use IO.
To give my answer some weight, I have just spent three months maintaining and bug fixing an integration layer where raw Java NIO (i.e. no overarching framework was used) was used. The design was based, in essence, on client threads adding messages to a queue and a small number of worker threads performing their NIO magic and then passing replies back to client threads in an event-based manner. In retrospect, I cannot justify the original decision to use NIO, since it became a distraction that ate significant amounts of time that should have been spent on higher level business logic.
You can use any of this, unless you are going to create "super fast" server.
Of course a good approach here is to use nio, since it's new and modern way to write multi-client servers for high throughput tasks.
Some advantages of the NIO.2 API over the legacy java.io.File class for working with files:
Supports file system–dependent attributes.
Allows you to traverse a directory tree directly.
Supports symbolic links.
For specific use cases and more details, you can see this article
Traditional IO is easy and simplified code, NIO is more complicated but more flexible.
In my case i prefer use IO for small streaming and NIO for large streaming but nio is really more complex
with NIO i have to create an entire package to manage it instead io package that i directly use snippet
Before Java 1.4 it was common practice to work with files by moving bytes around between different InputStreams/OutputStreams.
Since Java 1.4, where NIO got added, it is suggested to use Channels to do the same.
With NIO2 in Java 7, there will be yet another API in java.nio.file which supports doing things like
val source = Paths.get("fooDir/fooFile.txt")
val target = Paths.get("barDir/barFile.txt")
source moveTo target
source createLinkTo target
Are the older ones more or less useless now for file system operations unless you want to touch bytes manually?
For most operations, NIO2 will let you do more / better.
Some operations are just impossible using legacy APIs (some attributes, ACL, file change notifications, better error handling...).
And best of all: this is not necessarily more difficult.
To answer your question: when you could do some operations with two different APIs, I don't see any use case where the old one would allow to do it better.
There has been some discussion:
Java NIO FileChannel versus FileOutputstream performance / usefulness
http://mailinator.blogspot.com/2008/02/kill-myth-please-nio-is-not-faster-than.html
But I'd say newest APIs are designed to be faster. If they don't in some situation, expect a jvm update to restore the situation without having to change any code if you've been using the newer APIs.
It is best practice to use the newer APIs when you can. They are usually better at handling corner cases like symlinks. They are also more likely to be built directly on OS primitives which will provide better hardware utilization. So the short answer to your question is "yes, the old ones are pretty much useless". The big downside to the new apis is that they require newer JREs to be installed.
I will add my 2 cents here. #Ymajoros and #Matt have summed it pretty well.
Definitely, the newer NIO will be better than the predecessors. There were lots of limitations in the old file io classes. I had moved from C++ back ground and found that even though the Apis were easier to use they were lacking lots of features. Right now also if you look at the classes, if you try to query remote directory you may see some slowness or your JVM may hang. This is being fixed in 7. Also to note is that some file systems support symbolic links and there is provision made to handle that. Iterators are being added for directory listing and also it will support the POSIX and the ACL control model.
My app is written in Java.
There is a C++ library I need to utilize. I don't want to use JNI.
60 times a second, the C++ app needs to send the Java app 10MB of data; and the Java app needs to send the C++ app 10 MB of data.
Both apps are running on the same machine; the OS is either Linux or Mac OS X.
What is the most efficient way to do this? (At the moment, I'm considering TCPIP ports; but in C++, I can do memory mapping -- can I do something similar in Java?)
Thanks!
Yes, Java has memory-mapped files with the NIO framework.
If you're trying to avoid JNI because you didn't want to write stubs, you can also interface with C++ code (at least ones that are extern "C") using JNA. For best performance, use direct mapping (concrete classes with native methods, not a mapped interface)---see documentation for more details. :-)
Using mapped files is a way of hand-rolling a highly optimized rpc. You might consider starting with a web service talking over local sockets, using MTOM for attaching the data, or just dropping it into a file. Then you could measure the performance. If the data was a problem, you could then use mapping.
Note that there are some odd restrictions on this that make your code sensitive to whether it is running on Windows or not. On Windows, you can't delete something that is open.
I should point out that I have done exactly what you are proposing here. It has a control channel on a socket, and the data is shared via a file that is mmapped in C++ (or the Windows equivalent) and NIO mapped in Java. It works. I've never measured maximum throughput, though.
Sounds like shared memory would be the way to go. I believe the NIO libraries support that.
The question is WHAT do you want your program to do?
You should give a look at BridJ (and JNAerator).
It's a recent alternative to JNA with support for C++ and a special focus on performance.
Not directly helpful and will be interesting at least to develop but you could throw in an SSD/RAM drive accessible to both the Java and C++ application and have a sort of juggle between data ops in there with file-based locking and all that odd stuff.
What would make this scheme sort of manageable from performance point is that for this purpose Java NIO has ByteBuffer which is a high level representation of low level byte mapping on disk.
You should take a look at javolution.
They are using NIO direct buffers for data exchange.
In theory, this should be faster then plain JNI
since you do not have the overhead of passing
data through the argument list.
What is up with nio channels ? There were some nice talks when it was added to java but I still don't see people using it in their applications.
Is there something wrong with it, or am I just not encountering people who use it?
Any nice examples as to why I should bother using it at all ?
Thanks
You're asking about channels, but channels only make sense within the general framework of using the (relatively) new nio capabilities as a whole.
My guess is that of the many, many Java applications out in the world, not many need the capabilities of nio. The usual "business" process read streams and/or files... nothing special.
That said, the Apache folks have recently rewritten their core Java libraries ( http://hc.apache.org/ ) to use nio, and claim some impressive performance benefits in some cases.
nio also lets you do stuff like memory-mapping files, and this can allow an application to do very fast random access to the file. Again, only some special applications need this, and that's probably why you don't see a lot of it used.
Apache Mina is a great networking library and uses NIO.
Apache MINA is a network application framework which helps users develop high performance and high scalability network applications easily. It provides an abstract · event-driven · asynchronous API over various transports such as TCP/IP and UDP/IP via Java NIO.
Net4J, a signaling platform/framework, makes heavy use of NIO channels. (One part of Net4J basically provides a convenience API to NIO channels.)