FileChannel incompatibility introduced between 6 and 7 (and possible compiler bug) (original) (raw)
David M. Lloyd david.lloyd at redhat.com
Thu Jul 26 11:44:11 PDT 2012
- Previous message: WatchService re-register events appended or replaced
- Next message: FileChannel incompatibility introduced between 6 and 7 (and possible compiler bug)
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
Ran into a pretty ugly little issue just now. My NIO framework has a FileChannel subclass that it uses for certain tasks. This works fine on 7, but on 6 I get errors like this:
java.lang.NoClassDefFoundError: java/nio/channels/SeekableByteChannel
I found this odd, initially, because I never reference this interface. I noticed that in 7 this interface was introduced and (sensibly) retroactively added as a superinterface of FileChannel. Logically this seems like it should not be a problem; it just means that in 7 we should have a couple new bridge methods on FileChannel (and we do):
public java.nio.channels.SeekableByteChannel truncate(long) throws java.io.IOException; Code: 0: aload_0 1: lload_1 2: invokevirtual #95 // Method truncate:(J)Ljava/nio/channels/FileChannel; 5: areturn
public java.nio.channels.SeekableByteChannel position(long) throws java.io.IOException; Code: 0: aload_0 1: lload_1 2: invokevirtual #94 // Method position:(J)Ljava/nio/channels/FileChannel; 5: areturn
Note the invokevirtual, which is specifically relevant here.
These methods are obviously necessary as FileChannel covariantly overrides the new interface methods. However, the trouble started when I compiled my subclass and noticed, to my surprise, the very same bridge methods are on it! Thus there's a static linkage from my class directly to SeekableByteChannel, despite there being no reference to it in the source code at all.
Now what bugs me about this is that if my class did not have these bridge methods, it would still work just fine, since the superclass is using invokevirtual to access the covariantly overridden method! I could understand this behavior if it were using invokespecial, but it's not, or if I were actually directly implementing SeekableByteChannel on my class, which I'm not; the end result is what appears to be a needless break in compatibility.
Now I do have some options available - I can make mocks of the Java 7 classes I need to compile against, and then compile against 6, or I can add a build-time step to strip these methods from the class. But this strikes me as being a somewhat serious, if highly specific, problem. Is this a compiler bug, or is it an irreparable backwards-compatibility mistake in NIO?
--
- DML
- Previous message: WatchService re-register events appended or replaced
- Next message: FileChannel incompatibility introduced between 6 and 7 (and possible compiler bug)
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]