diff options
author | Lajos Molnar <lajos@google.com> | 2014-05-12 14:49:47 +0000 |
---|---|---|
committer | Android Git Automerger <android-git-automerger@android.com> | 2014-05-12 14:49:47 +0000 |
commit | 28ae9615170bac91eb89fd3098d8c8b19bec759e (patch) | |
tree | 4eafa2cbfc9ee7071565a9337924ea5e6fdecaf1 | |
parent | c1fa59836cb9699e22b90eba7fa443e41ac9530e (diff) | |
parent | a238515382b28f73f82d2df362dee1d011689fd3 (diff) | |
download | libcore-28ae9615170bac91eb89fd3098d8c8b19bec759e.zip libcore-28ae9615170bac91eb89fd3098d8c8b19bec759e.tar.gz libcore-28ae9615170bac91eb89fd3098d8c8b19bec759e.tar.bz2 |
am a2385153: Merge changes I726f16f9,Idd2f4ef1
* commit 'a238515382b28f73f82d2df362dee1d011689fd3':
DirectByteBuffer: add setAccessible()
Better protection against accessing freed DirectByteBuffers
-rw-r--r-- | luni/src/main/java/java/nio/ByteBuffer.java | 25 | ||||
-rw-r--r-- | luni/src/main/java/java/nio/DirectByteBuffer.java | 112 | ||||
-rw-r--r-- | luni/src/main/java/java/nio/MemoryBlock.java | 24 | ||||
-rw-r--r-- | luni/src/test/java/libcore/java/nio/BufferTest.java | 185 |
4 files changed, 269 insertions, 77 deletions
diff --git a/luni/src/main/java/java/nio/ByteBuffer.java b/luni/src/main/java/java/nio/ByteBuffer.java index 4fdd1f4..4c0f4a6 100644 --- a/luni/src/main/java/java/nio/ByteBuffer.java +++ b/luni/src/main/java/java/nio/ByteBuffer.java @@ -609,17 +609,30 @@ public abstract class ByteBuffer extends Buffer implements Comparable<ByteBuffer @Override public abstract boolean isDirect(); /** - * Indicates whether this buffer is still valid. + * Indicates whether this buffer is still accessible. * - * @return {@code true} if this buffer is valid, {@code false} if the - * buffer was invalidated and should not be used anymore. + * @return {@code true} if this buffer is accessible, {@code false} if the + * buffer was made inaccessible (e.g. freed) and should not be used. * @hide */ - public boolean isValid() { + public boolean isAccessible() { return true; } /** + * Sets buffer accessibility (only supported for direct byte buffers). If + * {@code accessible} is {@code false}, {@link #isAccessible} will return + * false, and any attempt to access the buffer will throw an exception. If + * {@code true}, the buffer will become useable again, unless it has been + * freed. + * + * @hide + */ + public void setAccessible(boolean accessible) { + throw new UnsupportedOperationException(); + } + + /** * Returns the byte order used by this buffer when converting bytes from/to * other primitive types. * <p> @@ -753,6 +766,10 @@ public abstract class ByteBuffer extends Buffer implements Comparable<ByteBuffer * if no changes may be made to the contents of this buffer. */ public ByteBuffer put(ByteBuffer src) { + if (!src.isAccessible() || !isAccessible()) { + throw new IllegalStateException("buffer is inaccessible"); + } + if (isReadOnly()) { throw new ReadOnlyBufferException(); } diff --git a/luni/src/main/java/java/nio/DirectByteBuffer.java b/luni/src/main/java/java/nio/DirectByteBuffer.java index ab47c93..f19fb42 100644 --- a/luni/src/main/java/java/nio/DirectByteBuffer.java +++ b/luni/src/main/java/java/nio/DirectByteBuffer.java @@ -26,7 +26,6 @@ class DirectByteBuffer extends MappedByteBuffer { // This is the offset into {@code Buffer.block} at which this buffer logically starts. // TODO: rewrite this so we set 'block' to an OffsetMemoryBlock? protected final int offset; - private boolean freed; private final boolean isReadOnly; @@ -64,7 +63,7 @@ class DirectByteBuffer extends MappedByteBuffer { } @Override public ByteBuffer compact() { - checkNotFreed(); + checkIsAccessible(); if (isReadOnly) { throw new ReadOnlyBufferException(); } @@ -89,7 +88,7 @@ class DirectByteBuffer extends MappedByteBuffer { } @Override byte[] protectedArray() { - checkNotFreed(); + checkIsAccessible(); if (isReadOnly) { throw new ReadOnlyBufferException(); } @@ -110,7 +109,7 @@ class DirectByteBuffer extends MappedByteBuffer { } @Override public final ByteBuffer get(byte[] dst, int dstOffset, int byteCount) { - checkNotFreed(); + checkIsAccessible(); checkGetBounds(1, dst.length, dstOffset, byteCount); this.block.peekByteArray(offset + position, dst, dstOffset, byteCount); position += byteCount; @@ -118,49 +117,49 @@ class DirectByteBuffer extends MappedByteBuffer { } final void get(char[] dst, int dstOffset, int charCount) { - checkNotFreed(); + checkIsAccessible(); int byteCount = checkGetBounds(SizeOf.CHAR, dst.length, dstOffset, charCount); this.block.peekCharArray(offset + position, dst, dstOffset, charCount, order.needsSwap); position += byteCount; } final void get(double[] dst, int dstOffset, int doubleCount) { - checkNotFreed(); + checkIsAccessible(); int byteCount = checkGetBounds(SizeOf.DOUBLE, dst.length, dstOffset, doubleCount); this.block.peekDoubleArray(offset + position, dst, dstOffset, doubleCount, order.needsSwap); position += byteCount; } final void get(float[] dst, int dstOffset, int floatCount) { - checkNotFreed(); + checkIsAccessible(); int byteCount = checkGetBounds(SizeOf.FLOAT, dst.length, dstOffset, floatCount); this.block.peekFloatArray(offset + position, dst, dstOffset, floatCount, order.needsSwap); position += byteCount; } final void get(int[] dst, int dstOffset, int intCount) { - checkNotFreed(); + checkIsAccessible(); int byteCount = checkGetBounds(SizeOf.INT, dst.length, dstOffset, intCount); this.block.peekIntArray(offset + position, dst, dstOffset, intCount, order.needsSwap); position += byteCount; } final void get(long[] dst, int dstOffset, int longCount) { - checkNotFreed(); + checkIsAccessible(); int byteCount = checkGetBounds(SizeOf.LONG, dst.length, dstOffset, longCount); this.block.peekLongArray(offset + position, dst, dstOffset, longCount, order.needsSwap); position += byteCount; } final void get(short[] dst, int dstOffset, int shortCount) { - checkNotFreed(); + checkIsAccessible(); int byteCount = checkGetBounds(SizeOf.SHORT, dst.length, dstOffset, shortCount); this.block.peekShortArray(offset + position, dst, dstOffset, shortCount, order.needsSwap); position += byteCount; } @Override public final byte get() { - checkNotFreed(); + checkIsAccessible(); if (position == limit) { throw new BufferUnderflowException(); } @@ -168,13 +167,13 @@ class DirectByteBuffer extends MappedByteBuffer { } @Override public final byte get(int index) { - checkNotFreed(); + checkIsAccessible(); checkIndex(index); return this.block.peekByte(offset + index); } @Override public final char getChar() { - checkNotFreed(); + checkIsAccessible(); int newPosition = position + SizeOf.CHAR; if (newPosition > limit) { throw new BufferUnderflowException(); @@ -185,13 +184,13 @@ class DirectByteBuffer extends MappedByteBuffer { } @Override public final char getChar(int index) { - checkNotFreed(); + checkIsAccessible(); checkIndex(index, SizeOf.CHAR); return (char) this.block.peekShort(offset + index, order); } @Override public final double getDouble() { - checkNotFreed(); + checkIsAccessible(); int newPosition = position + SizeOf.DOUBLE; if (newPosition > limit) { throw new BufferUnderflowException(); @@ -202,13 +201,13 @@ class DirectByteBuffer extends MappedByteBuffer { } @Override public final double getDouble(int index) { - checkNotFreed(); + checkIsAccessible(); checkIndex(index, SizeOf.DOUBLE); return Double.longBitsToDouble(this.block.peekLong(offset + index, order)); } @Override public final float getFloat() { - checkNotFreed(); + checkIsAccessible(); int newPosition = position + SizeOf.FLOAT; if (newPosition > limit) { throw new BufferUnderflowException(); @@ -219,13 +218,13 @@ class DirectByteBuffer extends MappedByteBuffer { } @Override public final float getFloat(int index) { - checkNotFreed(); + checkIsAccessible(); checkIndex(index, SizeOf.FLOAT); return Float.intBitsToFloat(this.block.peekInt(offset + index, order)); } @Override public final int getInt() { - checkNotFreed(); + checkIsAccessible(); int newPosition = position + SizeOf.INT; if (newPosition > limit) { throw new BufferUnderflowException(); @@ -236,13 +235,13 @@ class DirectByteBuffer extends MappedByteBuffer { } @Override public final int getInt(int index) { - checkNotFreed(); + checkIsAccessible(); checkIndex(index, SizeOf.INT); return this.block.peekInt(offset + index, order); } @Override public final long getLong() { - checkNotFreed(); + checkIsAccessible(); int newPosition = position + SizeOf.LONG; if (newPosition > limit) { throw new BufferUnderflowException(); @@ -253,13 +252,13 @@ class DirectByteBuffer extends MappedByteBuffer { } @Override public final long getLong(int index) { - checkNotFreed(); + checkIsAccessible(); checkIndex(index, SizeOf.LONG); return this.block.peekLong(offset + index, order); } @Override public final short getShort() { - checkNotFreed(); + checkIsAccessible(); int newPosition = position + SizeOf.SHORT; if (newPosition > limit) { throw new BufferUnderflowException(); @@ -270,7 +269,7 @@ class DirectByteBuffer extends MappedByteBuffer { } @Override public final short getShort(int index) { - checkNotFreed(); + checkIsAccessible(); checkIndex(index, SizeOf.SHORT); return this.block.peekShort(offset + index, order); } @@ -280,8 +279,13 @@ class DirectByteBuffer extends MappedByteBuffer { } /** @hide */ - @Override public final boolean isValid() { - return !freed; + @Override public final boolean isAccessible() { + return block.isAccessible(); + } + + /** @hide */ + @Override public void setAccessible(boolean accessible) { + block.setAccessible(accessible); } /** @@ -289,10 +293,7 @@ class DirectByteBuffer extends MappedByteBuffer { * buffer will throw {@link IllegalStateException}. */ public final void free() { - if (!freed) { - block.free(); - freed = true; - } + block.free(); } @Override public final CharBuffer asCharBuffer() { @@ -326,7 +327,7 @@ class DirectByteBuffer extends MappedByteBuffer { } @Override public ByteBuffer put(byte value) { - checkNotFreed(); + checkIsAccessible(); if (isReadOnly) { throw new ReadOnlyBufferException(); } @@ -338,7 +339,7 @@ class DirectByteBuffer extends MappedByteBuffer { } @Override public ByteBuffer put(int index, byte value) { - checkNotFreed(); + checkIsAccessible(); if (isReadOnly) { throw new ReadOnlyBufferException(); } @@ -348,7 +349,7 @@ class DirectByteBuffer extends MappedByteBuffer { } @Override public ByteBuffer put(byte[] src, int srcOffset, int byteCount) { - checkNotFreed(); + checkIsAccessible(); if (isReadOnly) { throw new ReadOnlyBufferException(); } @@ -359,49 +360,49 @@ class DirectByteBuffer extends MappedByteBuffer { } final void put(char[] src, int srcOffset, int charCount) { - checkNotFreed(); + checkIsAccessible(); int byteCount = checkPutBounds(SizeOf.CHAR, src.length, srcOffset, charCount); this.block.pokeCharArray(offset + position, src, srcOffset, charCount, order.needsSwap); position += byteCount; } final void put(double[] src, int srcOffset, int doubleCount) { - checkNotFreed(); + checkIsAccessible(); int byteCount = checkPutBounds(SizeOf.DOUBLE, src.length, srcOffset, doubleCount); this.block.pokeDoubleArray(offset + position, src, srcOffset, doubleCount, order.needsSwap); position += byteCount; } final void put(float[] src, int srcOffset, int floatCount) { - checkNotFreed(); + checkIsAccessible(); int byteCount = checkPutBounds(SizeOf.FLOAT, src.length, srcOffset, floatCount); this.block.pokeFloatArray(offset + position, src, srcOffset, floatCount, order.needsSwap); position += byteCount; } final void put(int[] src, int srcOffset, int intCount) { - checkNotFreed(); + checkIsAccessible(); int byteCount = checkPutBounds(SizeOf.INT, src.length, srcOffset, intCount); this.block.pokeIntArray(offset + position, src, srcOffset, intCount, order.needsSwap); position += byteCount; } final void put(long[] src, int srcOffset, int longCount) { - checkNotFreed(); + checkIsAccessible(); int byteCount = checkPutBounds(SizeOf.LONG, src.length, srcOffset, longCount); this.block.pokeLongArray(offset + position, src, srcOffset, longCount, order.needsSwap); position += byteCount; } final void put(short[] src, int srcOffset, int shortCount) { - checkNotFreed(); + checkIsAccessible(); int byteCount = checkPutBounds(SizeOf.SHORT, src.length, srcOffset, shortCount); this.block.pokeShortArray(offset + position, src, srcOffset, shortCount, order.needsSwap); position += byteCount; } @Override public ByteBuffer putChar(char value) { - checkNotFreed(); + checkIsAccessible(); if (isReadOnly) { throw new ReadOnlyBufferException(); } @@ -415,7 +416,7 @@ class DirectByteBuffer extends MappedByteBuffer { } @Override public ByteBuffer putChar(int index, char value) { - checkNotFreed(); + checkIsAccessible(); if (isReadOnly) { throw new ReadOnlyBufferException(); } @@ -425,7 +426,7 @@ class DirectByteBuffer extends MappedByteBuffer { } @Override public ByteBuffer putDouble(double value) { - checkNotFreed(); + checkIsAccessible(); if (isReadOnly) { throw new ReadOnlyBufferException(); } @@ -439,7 +440,7 @@ class DirectByteBuffer extends MappedByteBuffer { } @Override public ByteBuffer putDouble(int index, double value) { - checkNotFreed(); + checkIsAccessible(); if (isReadOnly) { throw new ReadOnlyBufferException(); } @@ -449,7 +450,7 @@ class DirectByteBuffer extends MappedByteBuffer { } @Override public ByteBuffer putFloat(float value) { - checkNotFreed(); + checkIsAccessible(); if (isReadOnly) { throw new ReadOnlyBufferException(); } @@ -463,7 +464,7 @@ class DirectByteBuffer extends MappedByteBuffer { } @Override public ByteBuffer putFloat(int index, float value) { - checkNotFreed(); + checkIsAccessible(); if (isReadOnly) { throw new ReadOnlyBufferException(); } @@ -473,7 +474,7 @@ class DirectByteBuffer extends MappedByteBuffer { } @Override public ByteBuffer putInt(int value) { - checkNotFreed(); + checkIsAccessible(); if (isReadOnly) { throw new ReadOnlyBufferException(); } @@ -487,7 +488,7 @@ class DirectByteBuffer extends MappedByteBuffer { } @Override public ByteBuffer putInt(int index, int value) { - checkNotFreed(); + checkIsAccessible(); if (isReadOnly) { throw new ReadOnlyBufferException(); } @@ -497,7 +498,7 @@ class DirectByteBuffer extends MappedByteBuffer { } @Override public ByteBuffer putLong(long value) { - checkNotFreed(); + checkIsAccessible(); if (isReadOnly) { throw new ReadOnlyBufferException(); } @@ -511,7 +512,7 @@ class DirectByteBuffer extends MappedByteBuffer { } @Override public ByteBuffer putLong(int index, long value) { - checkNotFreed(); + checkIsAccessible(); if (isReadOnly) { throw new ReadOnlyBufferException(); } @@ -521,7 +522,7 @@ class DirectByteBuffer extends MappedByteBuffer { } @Override public ByteBuffer putShort(short value) { - checkNotFreed(); + checkIsAccessible(); if (isReadOnly) { throw new ReadOnlyBufferException(); } @@ -535,7 +536,7 @@ class DirectByteBuffer extends MappedByteBuffer { } @Override public ByteBuffer putShort(int index, short value) { - checkNotFreed(); + checkIsAccessible(); if (isReadOnly) { throw new ReadOnlyBufferException(); } @@ -544,8 +545,15 @@ class DirectByteBuffer extends MappedByteBuffer { return this; } + private void checkIsAccessible() { + checkNotFreed(); + if (!block.isAccessible()) { + throw new IllegalStateException("buffer is inaccessible"); + } + } + private void checkNotFreed() { - if (freed) { + if (block.isFreed()) { throw new IllegalStateException("buffer was freed"); } } diff --git a/luni/src/main/java/java/nio/MemoryBlock.java b/luni/src/main/java/java/nio/MemoryBlock.java index 1ce8fea..a619b8d 100644 --- a/luni/src/main/java/java/nio/MemoryBlock.java +++ b/luni/src/main/java/java/nio/MemoryBlock.java @@ -48,8 +48,8 @@ class MemoryBlock { // a state where munmap(2) could return an error. throw new AssertionError(errnoException); } - address = 0; } + super.free(); } @Override protected void finalize() throws Throwable { @@ -78,7 +78,7 @@ class MemoryBlock { @Override public void free() { array = null; - address = 0; + super.free(); } } @@ -90,15 +90,11 @@ class MemoryBlock { private UnmanagedBlock(long address, long byteCount) { super(address, byteCount); } - - @Override - public void free() { - address = 0; - } } protected long address; protected final long size; + private boolean accessible; public static MemoryBlock mmap(FileDescriptor fd, long offset, long size, MapMode mapMode) throws IOException { if (size == 0) { @@ -143,6 +139,7 @@ class MemoryBlock { private MemoryBlock(long address, long size) { this.address = address; this.size = size; + accessible = true; } // Used to support array/arrayOffset/hasArray for direct buffers. @@ -151,6 +148,19 @@ class MemoryBlock { } public void free() { + address = 0; + } + + public boolean isFreed() { + return address == 0; + } + + public boolean isAccessible() { + return !isFreed() && accessible; + } + + public final void setAccessible(boolean accessible) { + this.accessible = accessible; } public final void pokeByte(int offset, byte value) { diff --git a/luni/src/test/java/libcore/java/nio/BufferTest.java b/luni/src/test/java/libcore/java/nio/BufferTest.java index a5cc484..de4e0f1 100644 --- a/luni/src/test/java/libcore/java/nio/BufferTest.java +++ b/luni/src/test/java/libcore/java/nio/BufferTest.java @@ -731,7 +731,7 @@ public class BufferTest extends TestCase { Class<?> c = Class.forName("java.nio.DirectByteBuffer"); Constructor<?> ctor = c.getDeclaredConstructor(long.class, int.class); ctor.setAccessible(true); - ByteBuffer bb = (ByteBuffer) ctor.newInstance(0, 0); + ByteBuffer bb = (ByteBuffer) ctor.newInstance(1, 0); try { bb.array(); @@ -886,43 +886,162 @@ public class BufferTest extends TestCase { } public void testFreed() { - ByteBuffer b = ByteBuffer.allocateDirect(1); - NioUtils.freeDirectBuffer(b); - assertFalse(b.isValid()); - try { - b.compact(); - fail(); - } catch (IllegalStateException expected) { + ByteBuffer b1 = ByteBuffer.allocateDirect(1); + ByteBuffer b2 = b1.duplicate(); + NioUtils.freeDirectBuffer(b1); + for (ByteBuffer b: new ByteBuffer[] { b1, b2 }) { + assertFalse(b.isAccessible()); + try { + b.compact(); + fail(); + } catch (IllegalStateException expected) { + } + try { + b.duplicate(); + fail(); + } catch (IllegalStateException expected) { + } + testFailForPutMethods(b); + testFailForAsMethods(b); + testFailForGetMethods(b); + NioUtils.freeDirectBuffer(b); // should be able to free twice } - try { + } + + public void testAccess() { + ByteBuffer b1 = ByteBuffer.allocate(1); + ByteBuffer b2 = b1.duplicate(); + for (ByteBuffer b: new ByteBuffer[] { b1, b2 }) { + try { + b.setAccessible(true); + fail(); + } catch (UnsupportedOperationException expected) { + } + try { + b.setAccessible(false); + fail(); + } catch (UnsupportedOperationException expected) { + } + } + b1 = ByteBuffer.allocateDirect(8); + b2 = b1.duplicate(); + b1.setAccessible(false); + ByteBuffer b3 = b1.asReadOnlyBuffer(); + for (ByteBuffer b: new ByteBuffer[] { b1, b2, b3 }) { b.duplicate(); - fail(); - } catch (IllegalStateException expected) { + assertFalse(b.isAccessible()); + // even read-only buffers should fail with IllegalStateException + testFailForPutMethods(b); + testAsMethods(b); + testFailForGetMethods(b); + b.position(0); + b.limit(8); + try { + b.asCharBuffer().get(0); + fail(); + } catch (IllegalStateException expected) { + } + try { + b.asShortBuffer().get(0); + fail(); + } catch (IllegalStateException expected) { + } + try { + b.asIntBuffer().get(0); + fail(); + } catch (IllegalStateException expected) { + } + try { + b.asLongBuffer().get(0); + fail(); + } catch (IllegalStateException expected) { + } + try { + b.asFloatBuffer().get(0); + fail(); + } catch (IllegalStateException expected) { + } + try { + b.asDoubleBuffer().get(0); + fail(); + } catch (IllegalStateException expected) { + } + } + b2.setAccessible(true); + for (ByteBuffer b: new ByteBuffer[] { b1, b2, b3 }) { + assertTrue(b.isAccessible()); + b.position(0); + b.limit(8); + b.asCharBuffer().get(0); + b.asShortBuffer().get(0); + b.asIntBuffer().get(0); + b.asLongBuffer().get(0); + b.asFloatBuffer().get(0); + b.asDoubleBuffer().get(0); + if (!b.isReadOnly()) { + testPutMethods(b); + b.compact(); + } else { + try { + b.put(0, (byte) 0); + fail(); + } catch (ReadOnlyBufferException expected) { + } + } + testAsMethods(b); + testGetMethods(b); } - testFailForPutMethods(b); - testFailForAsMethods(b); - testFailForGetMethods(b); + } + + private void testPutMethods(ByteBuffer b) { + b.position(0); + b.put((byte) 0); + b.put(0, (byte) 0); + b.put(new byte[1]); + b.put(new byte[1], 0, 1); + b.put(ByteBuffer.allocate(1)); + b.putChar('a'); + b.putChar(0, 'a'); + b.position(0); + b.putDouble(0); + b.putDouble(0, 0); + b.position(0); + b.putFloat(0); + b.putFloat(0, 0); + b.putInt(0); + b.putInt(0, 0); + b.position(0); + b.putLong(0); + b.putLong(0, 0); + b.position(0); + b.putShort((short) 0); + b.putShort(0, (short) 0); } private void testFailForPutMethods(ByteBuffer b) { try { b.put((byte) 0); + fail(); } catch (IllegalStateException expected) { } try { b.put(0, (byte) 0); + fail(); } catch (IllegalStateException expected) { } try { b.put(new byte[1]); + fail(); } catch (IllegalStateException expected) { } try { b.put(new byte[1], 0, 1); + fail(); } catch (IllegalStateException expected) { } try { b.put(ByteBuffer.allocate(1)); + fail(); } catch (IllegalStateException expected) { } try { @@ -987,21 +1106,49 @@ public class BufferTest extends TestCase { } } + private void testGetMethods(ByteBuffer b) { + b.position(0); + b.get(); + b.get(0); + b.get(new byte[1]); + b.get(new byte[1], 0, 1); + b.getChar(); + b.getChar(0); + b.position(0); + b.getDouble(); + b.getDouble(0); + b.position(0); + b.getFloat(); + b.getFloat(0); + b.getInt(); + b.getInt(0); + b.position(0); + b.getLong(); + b.getLong(0); + b.position(0); + b.getShort(); + b.getShort(0); + } + private void testFailForGetMethods(ByteBuffer b) { try { b.get(); + fail(); } catch (IllegalStateException expected) { } try { b.get(0); + fail(); } catch (IllegalStateException expected) { } try { b.get(new byte[1]); + fail(); } catch (IllegalStateException expected) { } try { b.get(new byte[1], 0, 1); + fail(); } catch (IllegalStateException expected) { } try { @@ -1066,6 +1213,16 @@ public class BufferTest extends TestCase { } } + private void testAsMethods(ByteBuffer b) { + b.asCharBuffer(); + b.asDoubleBuffer(); + b.asFloatBuffer(); + b.asIntBuffer(); + b.asLongBuffer(); + b.asReadOnlyBuffer(); + b.asShortBuffer(); + } + private void testFailForAsMethods(ByteBuffer b) { try { b.asCharBuffer(); |