You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by mt...@apache.org on 2011/04/13 10:35:40 UTC
svn commit: r1091701 - in /commons/sandbox/runtime/trunk/src/main:
java/org/apache/commons/runtime/NioByteBuffer.java native/Makefile.unx.in
native/shared/nbb.c test/org/apache/commons/runtime/TestNioByteBuffer.java
Author: mturk
Date: Wed Apr 13 08:35:40 2011
New Revision: 1091701
URL: http://svn.apache.org/viewvc?rev=1091701&view=rev
Log:
Add NativeByteBuffer support
Added:
commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/NioByteBuffer.java (with props)
commons/sandbox/runtime/trunk/src/main/native/shared/nbb.c (with props)
commons/sandbox/runtime/trunk/src/main/test/org/apache/commons/runtime/TestNioByteBuffer.java (with props)
Modified:
commons/sandbox/runtime/trunk/src/main/native/Makefile.unx.in
Added: commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/NioByteBuffer.java
URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/NioByteBuffer.java?rev=1091701&view=auto
==============================================================================
--- commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/NioByteBuffer.java (added)
+++ commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/NioByteBuffer.java Wed Apr 13 08:35:40 2011
@@ -0,0 +1,262 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.runtime;
+
+import java.nio.ByteBuffer;
+
+/** Manages NIO direct ByteBuffers
+ * <p>
+ * <b>Warning:</b><br/>Using this class improperly may crash the running JVM.
+ * Any method call after free method was called might write or read from
+ * the memory location that has been already allocated for
+ * something else.
+ * </p>
+ * <p>
+ * Using this class methods on ByteBuffers that were not created by
+ * DirectNioByteBuffer.allocate methods will almost certainly crash the
+ * running JVM.
+ * </p>
+ * @since Runtime 1.0
+ */
+public final class NioByteBuffer
+{
+
+ private NioByteBuffer()
+ {
+ // No class instance
+ }
+
+ private static native ByteBuffer malloc0(long size)
+ throws OutOfMemoryError, IllegalArgumentException;
+
+ private static native ByteBuffer calloc0(long size)
+ throws OutOfMemoryError, IllegalArgumentException;
+
+ private static native ByteBuffer attach0(long ptr, long len)
+ throws OutOfMemoryError;
+
+ private static native long addr0(ByteBuffer buf);
+
+ private static native void copy0(ByteBuffer src, long srcPos, ByteBuffer dst,
+ long dstPos, int count)
+ throws NullPointerException, IllegalArgumentException,
+ IndexOutOfBoundsException;
+
+ /**
+ * Allocate a new {@code ByteBuffer} from {@link Pointer} memory area.
+ * <p>
+ * <b>Warning:</b><br/>
+ * Allocated array elements share the same memory segment
+ * so the {@code free()} must <b>not</b> be called on the retured
+ * {@code ByteBuffer}, neither it can be used after the {@code ptr}
+ * has been destroyed.
+ * </p>
+ * @param ptr Memory area to use.
+ * @param off Start offset of the {@code ptr} memory area.
+ * @param len The length of the {@code ptr} memory areat to use.
+ * @return The {@code ByteBuffer} backed by the {@code ptr} memory area.
+ *
+ * @throws NullPointerException if {@code ptr} is null.
+ * @throws IllegalArgumentException if {@code off} or {@code len}
+ * is invalid.
+ * @throws IndexOutOfBoundsException if copying would cause access of
+ * data outside array bounds.
+ */
+ public static ByteBuffer allocate(Pointer ptr, long off, long len)
+ throws NullPointerException, IllegalArgumentException,
+ IndexOutOfBoundsException, OutOfMemoryError
+ {
+ if (ptr == null || ptr.POINTER == 0L)
+ throw new NullPointerException();
+ if (off < 0L || len < 1L)
+ throw new IllegalArgumentException();
+ if (off + len >= ptr.PLENGTH)
+ throw new IndexOutOfBoundsException();
+
+ return attach0(ptr.POINTER + off, len);
+ }
+
+ /**
+ * Allocate a new {@code ByteBuffer} from {@link Pointer} memory area.
+ * <p>
+ * <b>Warning:</b><br/>
+ * Allocated array elements share the same memory segment
+ * so the {@code free()} must <b>not</b> be called on the retured
+ * {@code ByteBuffer}, neither it can be used after the {@code ptr}
+ * has been destroyed.
+ * </p>
+ * @param ptr Memory area to use.
+ * @return The {@code ByteBuffer} backed by the {@code ptr} memory area.
+ *
+ * @throws NullPointerException if {@code ptr} is null.
+ */
+ public static ByteBuffer allocate(Pointer ptr)
+ throws NullPointerException, OutOfMemoryError
+ {
+ if (ptr == null || ptr.POINTER == 0L)
+ throw new NullPointerException();
+ return attach0(ptr.POINTER, ptr.PLENGTH);
+ }
+
+ /**
+ * Returns the allocated memory size of the ByteBuffer.
+ * @param buf Previously allocated ByteBuffer.
+ */
+ public static native long size(ByteBuffer buf)
+ throws NullPointerException;
+
+ /**
+ * Set ByteBuffer to specified character.
+ * @param buf The ByteBuffer to use
+ * @param c The character to set
+ * @param count Number of characters
+ *
+ * @throws NullPointerException if {@code buf} is null.
+ * @throws IllegalArgumentException if {@code count} is less then {@code 1}.
+ * @throws IndexOutOfBoundsException if copying would cause access of
+ * data outside ByteBuffer bounds.
+ */
+ public static native void set(ByteBuffer buf, int c, int count)
+ throws NullPointerException, IllegalArgumentException,
+ IndexOutOfBoundsException;
+
+ /**
+ * Copy an ByteBuffer content from specified source ByteBuffer.
+ * @param src The source ByteBuffer.
+ * @param dst The destination ByteBuffer.
+ * @param length The number of bytes to be copied.
+ *
+ * @throws NullPointerException if {@code src} or {@code dst} is null
+ * @throws IllegalArgumentException if {@code length} invalid
+ * @throws IndexOutOfBoundsException if copying would cause access of
+ * data outside ByteBuffer bounds.
+ */
+ public static void copy(ByteBuffer src, ByteBuffer dst, int length)
+ throws NullPointerException, IllegalArgumentException,
+ IndexOutOfBoundsException
+ {
+ if (src == null || dst == null)
+ throw new NullPointerException();
+ copy0(src, 0, dst, 0, length);
+ }
+
+ /**
+ * Copy an ByteBuffer content from specified source ByteBuffer.
+ * @param src The source ByteBuffer.
+ * @param srcPos Starting position in the source ByteBuffer.
+ * @param dst The destination ByteBuffer.
+ * @param dstPos Starting position in the source ByteBuffer.
+ * @param length The number of bytes to be copied.
+ *
+ * @throws NullPointerException if {@code src} or {@code dst} is null
+ * @throws IllegalArgumentException if {@code length} invalid
+ * @throws IndexOutOfBoundsException if copying would cause access of
+ * data outside ByteBuffer bounds.
+ */
+ public static void copy(ByteBuffer src, long srcPos, ByteBuffer dst,
+ long dstPos, int length)
+ throws NullPointerException, IllegalArgumentException,
+ IndexOutOfBoundsException
+ {
+ if (src == null || dst == null)
+ throw new NullPointerException();
+ copy0(src, srcPos, dst, dstPos, length);
+ }
+
+ // Unsafe methods
+ // TODO: See if those methods should be present at the first
+ // place because they can very easily crash the VM.
+
+ /**
+ * Allocate a new ByteBuffer from memory.
+ * @param size The amount of memory to allocate
+ * @return The ByteBuffer with allocated memory
+ *
+ * @throws OutOfMemoryError if memory cannot be allocated from the system.
+ * @throws IllegalArgumentException if {@code size} is invalid.
+ */
+ public static ByteBuffer allocate(long size)
+ throws OutOfMemoryError, IllegalArgumentException
+ {
+ return malloc0(size);
+ }
+
+ /**
+ * Allocate a new ByteBuffer from memory and set all of the memory
+ * bytes to zero.
+ * @param size Length in bytes of each element.
+ * @return The ByteBuffer with allocated memory
+ *
+ * @throws OutOfMemoryError if memory cannot be allocated from the system.
+ * @throws IllegalArgumentException if {@code size} is invalid.
+ */
+ public static ByteBuffer allocateAndClear(long size)
+ throws OutOfMemoryError, IllegalArgumentException
+ {
+ return calloc0(size);
+ }
+
+ /**
+ * Allocate a new ByteBuffer from already allocated ByteBuffer.
+ * @param buf The ByteBuffer who's memory to use
+ * @param offset Offset from the memory to use
+ * @param size The amount of memory to use
+ * @return The ByteBuffer with attached memory
+ *
+ * @throws NullPointerException if {@code buf} is null
+ * @throws IllegalArgumentException if {@code offset} or
+ * {@code size} are invalid.
+ */
+ public static ByteBuffer allocate(ByteBuffer buf, long offset, long size)
+ throws NullPointerException, IllegalArgumentException
+ {
+ if (buf == null)
+ throw new NullPointerException();
+ long mem = addr0(buf);
+ if (mem == 0L)
+ throw new NullPointerException();
+ if (offset < 0L || size < 1L)
+ throw new IllegalArgumentException();
+ long len = size(buf);
+ if (offset + size > len)
+ throw new IndexOutOfBoundsException();
+ return attach0(mem + offset, size);
+ }
+
+ /**
+ * Deallocates or frees a memory block used by ByteBuffer.
+ * <p>
+ * <b>Warning:</b><br/>
+ * Invoke this method only on ByteBuffers
+ * that were created by {@code NioByteBuffer.allocate} methods
+ * and only if the Buffer was not allocated from the {@code Pointer}
+ * object.
+ * </p>
+ * <p>
+ * <b>Warning:</b><br/>
+ * This method must be called when the buffer is no longer needed.
+ * Failing to do so will leak system memory resources, causing memory
+ * growth because the underlying memory has to be explicitly released.
+ * </p>
+ * @param buf Previously allocated ByteBuffer to be deallocated.
+ *
+ * @throws NullPointerException if {@code buf} is null
+ */
+ public static native void free(ByteBuffer buf)
+ throws NullPointerException;
+
+}
Propchange: commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/NioByteBuffer.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified: commons/sandbox/runtime/trunk/src/main/native/Makefile.unx.in
URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/Makefile.unx.in?rev=1091701&r1=1091700&r2=1091701&view=diff
==============================================================================
--- commons/sandbox/runtime/trunk/src/main/native/Makefile.unx.in (original)
+++ commons/sandbox/runtime/trunk/src/main/native/Makefile.unx.in Wed Apr 13 08:35:40 2011
@@ -97,6 +97,7 @@ LIBSOURCES=\
$(TOPDIR)/shared/iofd.c \
$(TOPDIR)/shared/memory.c \
$(TOPDIR)/shared/native.c \
+ $(TOPDIR)/shared/nbb.c \
$(TOPDIR)/shared/pointer.c \
$(TOPDIR)/shared/object.c \
$(TOPDIR)/shared/observer.c \
Added: commons/sandbox/runtime/trunk/src/main/native/shared/nbb.c
URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/shared/nbb.c?rev=1091701&view=auto
==============================================================================
--- commons/sandbox/runtime/trunk/src/main/native/shared/nbb.c (added)
+++ commons/sandbox/runtime/trunk/src/main/native/shared/nbb.c Wed Apr 13 08:35:40 2011
@@ -0,0 +1,174 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ *
+ * @author Mladen Turk
+ */
+
+#include "acr/memory.h"
+#include "acr/clazz.h"
+
+/**
+ * NioByteBuffer utilities
+ */
+ACR_JNI_EXPORT(jobject, NioByteBuffer, malloc0)(JNI_STDARGS,
+ jlong size)
+{
+ void *mem;
+ jlong sz = ACR_ALIGN_DEFAULT(size);
+
+ if (size < 1L || size > SIZE_T_MAX) {
+ ACR_THROW(ACR_EX_EINVAL, 0);
+ return 0;
+ }
+ mem = ACR_MALLOC(char, sz);
+ if (mem != 0) {
+ jobject rv = (*env)->NewDirectByteBuffer(env, mem, sz);
+ if (rv == 0)
+ free(mem);
+ return rv;
+ }
+ return 0;
+}
+
+ACR_JNI_EXPORT(jobject, NioByteBuffer, calloc0)(JNI_STDARGS,
+ jlong size)
+{
+ jlong sz = ACR_ALIGN_DEFAULT(size);
+ void *mem;
+
+ if (size < 1L || size > SIZE_T_MAX) {
+ ACR_THROW(ACR_EX_EINVAL, 0);
+ return 0;
+ }
+ mem = ACR_CALLOC(char, sz);
+ if (mem != 0) {
+ jobject rv = (*env)->NewDirectByteBuffer(env, mem, sz);
+ if (rv == 0)
+ free(mem);
+ return rv;
+ }
+ return 0;
+}
+
+ACR_JNI_EXPORT(jobject, NioByteBuffer, attach0)(JNI_STDARGS,
+ jlong src, jlong len)
+{
+ return (*env)->NewDirectByteBuffer(env, J2P(src, char *), len);
+}
+
+ACR_JNI_EXPORT(void, NioByteBuffer, free)(JNI_STDARGS, jobject bb)
+{
+ void *mem;
+
+ if (bb != 0 && (mem = (*env)->GetDirectBufferAddress(env, bb)) != 0) {
+ /* This can cause core dump if address was
+ * allocated using different method.
+ * Make sure you call Native.enableExceptionHandler() to
+ * throw an exception instead.
+ */
+ free(mem);
+ }
+ else {
+ ACR_THROW(ACR_EX_ENULL, 0);
+ }
+}
+
+ACR_JNI_EXPORT(jlong, NioByteBuffer, addr0)(JNI_STDARGS,
+ jobject bb)
+{
+ return P2J((*env)->GetDirectBufferAddress(env, bb));
+}
+
+ACR_JNI_EXPORT(jlong, NioByteBuffer, size)(JNI_STDARGS,
+ jobject bb)
+{
+ if (bb == 0) {
+ ACR_THROW(ACR_EX_ENULL, 0);
+ return -1;
+ }
+ return (*env)->GetDirectBufferCapacity(env, bb);
+}
+
+ACR_JNI_EXPORT(void, NioByteBuffer, set)(JNI_STDARGS,
+ jobject bb,
+ jint c,
+ jint count)
+{
+ void *m;
+ jlong sz;
+
+ if (bb == 0) {
+ ACR_THROW(ACR_EX_ENULL, 0);
+ return;
+ }
+ sz = (*env)->GetDirectBufferCapacity(env, bb);
+ if (count < 1) {
+ ACR_THROW(ACR_EX_EINVAL, 0);
+ return;
+ }
+ if ((jlong)count > sz) {
+ ACR_THROW(ACR_EX_EINVAL, ACR_ERANGE);
+ return;
+ }
+ if ((m = (*env)->GetDirectBufferAddress(env, bb))) {
+ memset(m, c, count);
+ }
+ else {
+ ACR_THROW(ACR_EX_ENULL, 0);
+ }
+}
+
+ACR_JNI_EXPORT(void, NioByteBuffer, copy0)(JNI_STDARGS,
+ jobject srcb,
+ jlong srco,
+ jobject dstb,
+ jlong dsto,
+ jint count)
+{
+ char *d;
+ char *s;
+ jlong ss;
+ jlong ds;
+
+
+ ss = (*env)->GetDirectBufferCapacity(env, srcb);
+ ds = (*env)->GetDirectBufferCapacity(env, dstb);
+ if (ss < 1 || ds < 1) {
+ ACR_THROW(ACR_EX_EINVAL, ACR_EINVALSIZ);
+ return;
+ }
+ if ((count + srco) > ss) {
+ ACR_THROW(ACR_EX_EINDEX, ACR_ERANGE);
+ return;
+ }
+ if ((count + dsto) > ds) {
+ ACR_THROW(ACR_EX_EINDEX, ACR_ERANGE);
+ return;
+ }
+ s = (char *)(*env)->GetDirectBufferAddress(env, srcb);
+ if (s == 0 ) {
+ ACR_THROW(ACR_EX_ENULL, 0);
+ return;
+ }
+ d = (char *)(*env)->GetDirectBufferAddress(env, dstb);
+ if (d == 0 ) {
+ ACR_THROW(ACR_EX_ENULL, 0);
+ return;
+ }
+ memcpy(d + (intptr_t)dsto, s + (intptr_t)srco, count);
+}
Propchange: commons/sandbox/runtime/trunk/src/main/native/shared/nbb.c
------------------------------------------------------------------------------
svn:eol-style = native
Added: commons/sandbox/runtime/trunk/src/main/test/org/apache/commons/runtime/TestNioByteBuffer.java
URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/test/org/apache/commons/runtime/TestNioByteBuffer.java?rev=1091701&view=auto
==============================================================================
--- commons/sandbox/runtime/trunk/src/main/test/org/apache/commons/runtime/TestNioByteBuffer.java (added)
+++ commons/sandbox/runtime/trunk/src/main/test/org/apache/commons/runtime/TestNioByteBuffer.java Wed Apr 13 08:35:40 2011
@@ -0,0 +1,117 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.runtime;
+
+import java.io.IOException;
+import java.io.File;
+import org.testng.annotations.*;
+import org.testng.Assert;
+import java.nio.ByteBuffer;
+
+@Test(groups = { "utils" })
+public class TestNioByteBuffer
+{
+
+ public void malloc()
+ throws Exception
+ {
+ ByteBuffer bb = NioByteBuffer.allocate(1000);
+ Assert.assertTrue(bb.isDirect());
+ Assert.assertEquals(1000, bb.capacity());
+ NioByteBuffer.free(bb);
+ }
+
+ public void calloc()
+ throws Exception
+ {
+ ByteBuffer bb = NioByteBuffer.allocateAndClear(1000);
+ Assert.assertTrue(bb.isDirect());
+ Assert.assertEquals(1000, bb.capacity());
+ NioByteBuffer.free(bb);
+ }
+
+
+ public void pointer()
+ throws Exception
+ {
+ // ptr, bb1 and bb2 share the same memory
+ Pointer ptr = Memory.malloc(1000);
+ ByteBuffer bb = NioByteBuffer.allocate(ptr);
+ Assert.assertTrue(bb.isDirect());
+ Assert.assertEquals(1000, bb.capacity());
+ /*
+ * Call to the free crashes the JVM !
+ * Also call to the any operation on any
+ * Byte buffer will probably crash the JVM after the
+ * memory is free'd
+ * bb.putInt(0xcafebabe); might write to something else
+ * NioByteBuffer.free(bb); will free already free'd memory
+ * causing core.
+ */
+ }
+
+ public void doNotDoThis()
+ throws Exception
+ {
+ // ptr, bb1 and bb2 share the same memory
+ Pointer ptr = Memory.malloc(1000);
+ ByteBuffer bb = NioByteBuffer.allocate(ptr);
+ Assert.assertTrue(bb.isDirect());
+ Assert.assertEquals(1000, bb.capacity());
+ try {
+ boolean test_me = Native.HAS_MAINTAINER_MODE;
+ ptr.free();
+ // This is double free. Don't do this!
+ // Exception handler won't help here.
+ test_me = false;
+ if (test_me) {
+ NioByteBuffer.free(bb);
+ }
+ } catch (Throwable t) {
+ // Empty
+ }
+ }
+
+ public void memset()
+ throws Exception
+ {
+ ByteBuffer bb = NioByteBuffer.allocate(1000);
+ Assert.assertTrue(bb.isDirect());
+ bb.putInt(0xcafebabe);
+ bb.rewind();
+ Assert.assertEquals(0xcafebabe, bb.getInt());
+ NioByteBuffer.set(bb, 0x55, 1000);
+ Assert.assertEquals(0x55555555, bb.getInt());
+ NioByteBuffer.free(bb);
+ }
+
+ public void copy()
+ throws Exception
+ {
+ ByteBuffer sb = NioByteBuffer.allocate(1000);
+ ByteBuffer db = NioByteBuffer.allocateAndClear(1000);
+// Assert.assertTrue(sb.isDirect());
+// Assert.assertTrue(db.isDirect());
+ sb.putInt(0xcafebabe);
+ NioByteBuffer.copy(sb, 0, db, 4, 996);
+ Assert.assertEquals(0, db.getInt());
+ Assert.assertEquals(0xcafebabe, db.getInt());
+ NioByteBuffer.free(sb);
+ NioByteBuffer.free(db);
+ }
+
+}
Propchange: commons/sandbox/runtime/trunk/src/main/test/org/apache/commons/runtime/TestNioByteBuffer.java
------------------------------------------------------------------------------
svn:eol-style = native