com.ovea.system.internal.jna.Memory Maven / Gradle / Ivy
/* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*/
package com.sun.jna;
import java.nio.ByteBuffer;
import java.util.Collections;
import java.util.Map;
import java.util.WeakHashMap;
/**
* A Pointer
to memory obtained from the native heap via a
* call to malloc
.
*
* In some cases it might be necessary to use memory obtained from
* malloc
. For example, Memory
helps
* accomplish the following idiom:
*
* void *buf = malloc(BUF_LEN * sizeof(char));
* call_some_function(buf);
* free(buf);
*
*
* The {@link #finalize} method will free allocated memory when
* this object is no longer referenced.
*
* @author Sheng Liang, originator
* @author Todd Fast, suitability modifications
* @author Timothy Wall
* @see Pointer
*/
public class Memory extends Pointer {
private static Map buffers = Collections.synchronizedMap(new WeakHashMap());
protected long size; // Size of the malloc'ed space
/** Force cleanup of memory that has associated NIO Buffers which have
been GC'd.
*/
public static void purge() {
buffers.size();
}
/** Provide a view into the original memory. */
private class SharedMemory extends Memory {
public SharedMemory(long offset) {
this.size = Memory.this.size - offset;
this.peer = Memory.this.peer + offset;
}
/** No need to free memory. */
protected void finalize() { }
/** Pass bounds check to parent. */
protected void boundsCheck(long off, long sz) {
Memory.this.boundsCheck(this.peer - Memory.this.peer + off, sz);
}
public String toString() {
return super.toString() + " (shared from " + Memory.this.toString() + ")";
}
}
/**
* Allocate space in the native heap via a call to C's malloc
.
*
* @param size number of bytes of space to allocate
*/
public Memory(long size) {
this.size = size;
if (size <= 0) {
throw new IllegalArgumentException("Allocation size must be greater than zero");
}
peer = malloc(size);
if (peer == 0)
throw new OutOfMemoryError("Cannot allocate " + size + " bytes");
}
protected Memory() { }
/** Provide a view onto this structure from the given offset. The
* returned {@link Pointer} will have the same size as the original,
* reduced by the offset.
* @throws IndexOutOfBoundsException if the requested memory is outside
* the allocated bounds.
*/
public Pointer share(long offset) {
return share(offset, getSize() - offset);
}
/** Provide a view onto this structure from the given offset.
* @throws IndexOutOfBoundsException if the requested memory is outside
* the allocated bounds.
*/
public Pointer share(long offset, long sz) {
if (offset == 0 && sz == getSize())
return this;
boundsCheck(offset, sz);
return new SharedMemory(offset);
}
/** Provide a view onto this structure with the given alignment.
* @param byteBoundary Align memory to this number of bytes; should be a
* power of two.
* @throws IndexOutOfBoundsException if the requested alignment can
* not be met.
* @throws IllegalArgumentException if the requested alignment is not
* a positive power of two.
*/
public Memory align(int byteBoundary) {
if (byteBoundary <= 0) {
throw new IllegalArgumentException("Byte boundary must be positive: " + byteBoundary);
}
for (int i=0;i < 32;i++) {
if (byteBoundary == (1< size) {
String msg = "Bounds exceeds available space : size="
+ size + ", offset=" + (off + sz);
throw new IndexOutOfBoundsException(msg);
}
}
//////////////////////////////////////////////////////////////////////////
// Raw read methods
//////////////////////////////////////////////////////////////////////////
/**
* Indirect the native pointer to malloc
space, a la
* Pointer.read
. But this method performs a bounds
* checks to ensure that the indirection does not cause memory outside the
* malloc
ed space to be accessed.
*
* @see Pointer#read(long,byte[],int,int)
*/
public void read(long bOff, byte[] buf, int index, int length) {
boundsCheck(bOff, length * 1L);
super.read(bOff, buf, index, length);
}
/**
* Indirect the native pointer to malloc
space, a la
* Pointer.read
. But this method performs a bounds
* checks to ensure that the indirection does not cause memory outside the
* malloc
ed space to be accessed.
*
* @see Pointer#read(long,short[],int,int)
*/
public void read(long bOff, short[] buf, int index, int length) {
boundsCheck(bOff, length * 2L);
super.read(bOff, buf, index, length);
}
/**
* Indirect the native pointer to malloc
space, a la
* Pointer.read
. But this method performs a bounds
* checks to ensure that the indirection does not cause memory outside the
* malloc
ed space to be accessed.
*
* @see Pointer#read(long,char[],int,int)
*/
public void read(long bOff, char[] buf, int index, int length) {
boundsCheck(bOff, length * 2L);
super.read(bOff, buf, index, length);
}
/**
* Indirect the native pointer to malloc
space, a la
* Pointer.read
. But this method performs a bounds
* checks to ensure that the indirection does not cause memory outside the
* malloc
ed space to be accessed.
*
* @see Pointer#read(long,int[],int,int)
*/
public void read(long bOff, int[] buf, int index, int length) {
boundsCheck(bOff, length * 4L);
super.read(bOff, buf, index, length);
}
/**
* Indirect the native pointer to malloc
space, a la
* Pointer.read
. But this method performs a bounds
* checks to ensure that the indirection does not cause memory outside the
* malloc
ed space to be accessed.
*
* @see Pointer#read(long,long[],int,int)
*/
public void read(long bOff, long[] buf, int index, int length) {
boundsCheck(bOff, length * 8L);
super.read(bOff, buf, index, length);
}
/**
* Indirect the native pointer to malloc
space, a la
* Pointer.read
. But this method performs a bounds
* checks to ensure that the indirection does not cause memory outside the
* malloc
ed space to be accessed.
*
* @see Pointer#read(long,float[],int,int)
*/
public void read(long bOff, float[] buf, int index, int length) {
boundsCheck(bOff, length * 4L);
super.read(bOff, buf, index, length);
}
/**
* Indirect the native pointer to malloc
space, a la
* Pointer.read
. But this method performs a bounds checks to
* ensure that the indirection does not cause memory outside the
* malloc
ed space to be accessed.
*
* @see Pointer#read(long,double[],int,int)
*/
public void read(long bOff, double[] buf, int index, int length)
{
boundsCheck(bOff, length * 8L);
super.read(bOff, buf, index, length);
}
//////////////////////////////////////////////////////////////////////////
// Raw write methods
//////////////////////////////////////////////////////////////////////////
/**
* Indirect the native pointer to malloc
space, a la
* Pointer.write
. But this method performs a bounds
* checks to ensure that the indirection does not cause memory outside the
* malloc
ed space to be accessed.
*
* @see Pointer#write(long,byte[],int,int)
*/
public void write(long bOff, byte[] buf, int index, int length) {
boundsCheck(bOff, length * 1L);
super.write(bOff, buf, index, length);
}
/**
* Indirect the native pointer to malloc
space, a la
* Pointer.write
. But this method performs a bounds
* checks to ensure that the indirection does not cause memory outside the
* malloc
ed space to be accessed.
*
* @see Pointer#write(long,short[],int,int)
*/
public void write(long bOff, short[] buf, int index, int length) {
boundsCheck(bOff, length * 2L);
super.write(bOff, buf, index, length);
}
/**
* Indirect the native pointer to malloc
space, a la
* Pointer.write
. But this method performs a bounds
* checks to ensure that the indirection does not cause memory outside the
* malloc
ed space to be accessed.
*
* @see Pointer#write(long,char[],int,int)
*/
public void write(long bOff, char[] buf, int index, int length) {
boundsCheck(bOff, length * 2L);
super.write(bOff, buf, index, length);
}
/**
* Indirect the native pointer to malloc
space, a la
* Pointer.write
. But this method performs a bounds
* checks to ensure that the indirection does not cause memory outside the
* malloc
ed space to be accessed.
*
* @see Pointer#write(long,int[],int,int)
*/
public void write(long bOff, int[] buf, int index, int length) {
boundsCheck(bOff, length * 4L);
super.write(bOff, buf, index, length);
}
/**
* Indirect the native pointer to malloc
space, a la
* Pointer.write
. But this method performs a bounds
* checks to ensure that the indirection does not cause memory outside the
* malloc
ed space to be accessed.
*
* @see Pointer#write(long,long[],int,int)
*/
public void write(long bOff, long[] buf, int index, int length) {
boundsCheck(bOff, length * 8L);
super.write(bOff, buf, index, length);
}
/**
* Indirect the native pointer to malloc
space, a la
* Pointer.write
. But this method performs a bounds
* checks to ensure that the indirection does not cause memory outside the
* malloc
ed space to be accessed.
*
* @see Pointer#write(long,float[],int,int)
*/
public void write(long bOff, float[] buf, int index, int length) {
boundsCheck(bOff, length * 4L);
super.write(bOff, buf, index, length);
}
/**
* Indirect the native pointer to malloc
space, a la
* Pointer.write
. But this method performs a bounds
* checks to ensure that the indirection does not cause memory outside the
* malloc
ed space to be accessed.
*
* @see Pointer#write(long,double[],int,int)
*/
public void write(long bOff, double[] buf, int index, int length) {
boundsCheck(bOff, length * 8L);
super.write(bOff, buf, index, length);
}
//////////////////////////////////////////////////////////////////////////
// Java type read methods
//////////////////////////////////////////////////////////////////////////
/**
* Indirect the native pointer to malloc
space, a la
* Pointer.getByte
. But this method performs a bounds
* checks to ensure that the indirection does not cause memory outside the
* malloc
ed space to be accessed.
*
* @see Pointer#getByte(long)
*/
public byte getByte(long offset) {
boundsCheck(offset, 1);
return super.getByte(offset);
}
/**
* Indirect the native pointer to malloc
space, a la
* Pointer.getByte
. But this method performs a bounds
* checks to ensure that the indirection does not cause memory outside the
* malloc
ed space to be accessed.
*
* @see Pointer#getByte(long)
*/
public char getChar(long offset) {
boundsCheck(offset, 1);
return super.getChar(offset);
}
/**
* Indirect the native pointer to malloc
space, a la
* Pointer.getShort
. But this method performs a bounds
* checks to ensure that the indirection does not cause memory outside the
* malloc
ed space to be accessed.
*
* @see Pointer#getShort(long)
*/
public short getShort(long offset) {
boundsCheck(offset, 2);
return super.getShort(offset);
}
/**
* Indirect the native pointer to malloc
space, a la
* Pointer.getInt
. But this method performs a bounds
* checks to ensure that the indirection does not cause memory outside the
* malloc
ed space to be accessed.
*
* @see Pointer#getInt(long)
*/
public int getInt(long offset) {
boundsCheck(offset, 4);
return super.getInt(offset);
}
/**
* Indirect the native pointer to malloc
space, a la
* Pointer.getLong
. But this method performs a bounds
* checks to ensure that the indirection does not cause memory outside the
* malloc
ed space to be accessed.
*
* @see Pointer#getLong(long)
*/
public long getLong(long offset) {
boundsCheck(offset, 8);
return super.getLong(offset);
}
/**
* Indirect the native pointer to malloc
space, a la
* Pointer.getFloat
. But this method performs a bounds
* checks to ensure that the indirection does not cause memory outside the
* malloc
ed space to be accessed.
*
* @see Pointer#getFloat(long)
*/
public float getFloat(long offset) {
boundsCheck(offset, 4);
return super.getFloat(offset);
}
/**
* Indirect the native pointer to malloc
space, a la
* Pointer.getDouble
. But this method performs a
* bounds check to ensure that the indirection does not cause memory
* outside the malloc
ed space to be accessed.
*
* @see Pointer#getDouble(long)
*/
public double getDouble(long offset) {
boundsCheck(offset, 8);
return super.getDouble(offset);
}
/**
* Indirect the native pointer to malloc
space, a la
* Pointer.getPointer
. But this method performs
* a bounds checks to ensure that the indirection does not cause memory
* outside the malloc
ed space to be accessed.
*
* @see Pointer#getPointer(long)
*/
public Pointer getPointer(long offset) {
boundsCheck(offset, Pointer.SIZE);
return super.getPointer(offset);
}
/**
* Get a ByteBuffer mapped to a portion of this memory.
* We keep a weak reference to all ByteBuffers provided so that this
* memory object is not GC'd while there are still implicit outstanding
* references to it (it'd be nice if we could attach our own reference to
* the ByteBuffer, but the VM generates the object so we have no control
* over it).
*
* @param offset byte offset from pointer to start the buffer
* @param length Length of ByteBuffer
* @return a direct ByteBuffer that accesses the memory being pointed to,
*/
public ByteBuffer getByteBuffer(long offset, long length) {
boundsCheck(offset, length);
ByteBuffer b = super.getByteBuffer(offset, length);
// Ensure this Memory object will not be GC'd (and its memory freed)
// if the Buffer is still extant.
buffers.put(b, this);
return b;
}
/**
* Indirect the native pointer to malloc
space, a la
* Pointer.getString
. But this method performs a
* bounds checks to ensure that the indirection does not cause memory
* outside the malloc
ed space to be accessed.
*
* @see Pointer#getString(long, boolean)
*/
public String getString(long offset, boolean wide) {
// NOTE: we only make sure the start of the string is within bounds
boundsCheck(offset, 0);
return super.getString(offset, wide);
}
//////////////////////////////////////////////////////////////////////////
// Java type write methods
//////////////////////////////////////////////////////////////////////////
/**
* Indirect the native pointer to malloc
space, a la
* Pointer.setByte
. But this method performs a bounds
* checks to ensure that the indirection does not cause memory outside the
* malloc
ed space to be accessed.
*
* @see Pointer#setByte
*/
public void setByte(long offset, byte value) {
boundsCheck(offset, 1);
super.setByte(offset, value);
}
/**
* Indirect the native pointer to malloc
space, a la
* Pointer.setChar
. But this method performs a bounds
* checks to ensure that the indirection does not cause memory outside the
* malloc
ed space to be accessed.
*
* @see Pointer#setChar
*/
public void setChar(long offset, char value) {
boundsCheck(offset, Native.WCHAR_SIZE);
super.setChar(offset, value);
}
/**
* Indirect the native pointer to malloc
space, a la
* Pointer.setShort
. But this method performs a bounds
* checks to ensure that the indirection does not cause memory outside the
* malloc
ed space to be accessed.
*
* @see Pointer#setShort
*/
public void setShort(long offset, short value) {
boundsCheck(offset, 2);
super.setShort(offset, value);
}
/**
* Indirect the native pointer to malloc
space, a la
* Pointer.setInt
. But this method performs a bounds
* checks to ensure that the indirection does not cause memory outside the
* malloc
ed space to be accessed.
*
* @see Pointer#setInt
*/
public void setInt(long offset, int value) {
boundsCheck(offset, 4);
super.setInt(offset, value);
}
/**
* Indirect the native pointer to malloc
space, a la
* Pointer.setLong
. But this method performs a bounds
* checks to ensure that the indirection does not cause memory outside the
* malloc
ed space to be accessed.
*
* @see Pointer#setLong
*/
public void setLong(long offset, long value) {
boundsCheck(offset, 8);
super.setLong(offset, value);
}
/**
* Indirect the native pointer to malloc
space, a la
* Pointer.setFloat
. But this method performs a bounds
* checks to ensure that the indirection does not cause memory outside the
* malloc
ed space to be accessed.
*
* @see Pointer#setFloat
*/
public void setFloat(long offset, float value) {
boundsCheck(offset, 4);
super.setFloat(offset, value);
}
/**
* Indirect the native pointer to malloc
space, a la
* Pointer.setDouble
. But this method performs a
* bounds checks to ensure that the indirection does not cause memory
* outside the malloc
ed space to be accessed.
*
* @see Pointer#setDouble
*/
public void setDouble(long offset, double value) {
boundsCheck(offset, 8);
super.setDouble(offset, value);
}
/**
* Indirect the native pointer to malloc
space, a la
* Pointer.setPointer
. But this method performs
* a bounds checks to ensure that the indirection does not cause memory
* outside the malloc
ed space to be accessed.
*
* @see Pointer#setPointer
*/
public void setPointer(long offset, Pointer value) {
boundsCheck(offset, Pointer.SIZE);
super.setPointer(offset, value);
}
/**
* Indirect the native pointer to malloc
space, a la
* Pointer.setString
. But this method performs a
* bounds checks to ensure that the indirection does not cause memory
* outside the malloc
ed space to be accessed.
*
* @see Pointer#setString(long,String,boolean)
*/
public void setString(long offset, String value, boolean wide) {
if (wide)
boundsCheck(offset, (value.length() + 1L) * Native.WCHAR_SIZE);
else
boundsCheck(offset, value.getBytes().length + 1L);
super.setString(offset, value, wide);
}
public String toString() {
return "allocated@0x" + Long.toHexString(peer) + " ("
+ size + " bytes)";
}
protected static void free(long p) {
Native.free(p);
}
protected static long malloc(long size) {
return Native.malloc(size);
}
}