4646 */
4747@ SuppressWarnings ("restriction" )
4848public class NativeMemory implements Memory {
49- protected final long objectBaseOffset_ ; //only non-zero for on-heap objects. freeMemory sets to 0.
50- protected final Object memArray_ ; //null for off-heap, valid for on-heap.
51- protected MemoryRequest memReq_ = null ; //set via AllocMemory
49+ /*
50+ Class Case ObjBaseOff MemArr byteBuf rawAdd CapacityBytes ReqFree Direct
51+ NativeMemory byteArr >0 valid null 0 >0 FALSE FALSE
52+ NativeMemory longArr >0 valid null 0 >0 FALSE FALSE
53+ NativeMemory ByteBuffer Direct 0 null valid >0 >0 FALSE TRUE
54+ NativeMemory ByteBuffer not Direct >0 valid valid 0 >0 FALSE FALSE
55+ AllocMemory All cases 0 null null >0 >0 TRUE TRUE
56+ */
57+ protected final long objectBaseOffset_ ;
58+ protected final Object memArray_ ;
5259 //holding on to this to make sure that it is not garbage collected before we are done with it.
5360 protected final ByteBuffer byteBuf_ ;
54-
55- protected long nativeRawStartAddress_ ; //only non-zero for native
56- protected long capacityBytes_ ; //only non-zero if allocated and class still valid
57-
58- protected NativeMemory (long objectBaseOffset , Object memArray , ByteBuffer byteBuf ,
59- long nativeRawStartAddress , long capacityBytes ) {
60- this .objectBaseOffset_ = objectBaseOffset ;
61- this .memArray_ = memArray ;
62- this .byteBuf_ = byteBuf ;
63- this .nativeRawStartAddress_ = nativeRawStartAddress ;
64- this .capacityBytes_ = capacityBytes ;
61+ protected volatile long nativeRawStartAddress_ ;
62+ protected volatile long capacityBytes_ ;
63+ protected volatile MemoryRequest memReq_ = null ; //set via AllocMemory
64+
65+ //only sets the finals
66+ protected NativeMemory (long objectBaseOffset , Object memArray , ByteBuffer byteBuf ) {
67+ objectBaseOffset_ = objectBaseOffset ;
68+ memArray_ = memArray ;
69+ byteBuf_ = byteBuf ;
6570 }
6671
6772 /**
6873 * Provides access to the given byteArray using Memory interface
6974 * @param byteArray an on-heap byte array
7075 */
7176 public NativeMemory (byte [] byteArray ) {
72- int arrLen = byteArray .length ;
73- memArray_ = byteArray ;
74- objectBaseOffset_ = BYTE_ARRAY_BASE_OFFSET ;
77+ this (BYTE_ARRAY_BASE_OFFSET , byteArray , null );
78+ if ((byteArray == null ) || (byteArray .length == 0 )) {
79+ throw new IllegalArgumentException (
80+ "Array must must not be null and have a length greater than zero." );
81+ }
7582 nativeRawStartAddress_ = 0L ;
76- capacityBytes_ = arrLen ;
77- byteBuf_ = null ;
83+ capacityBytes_ = byteArray . length ;
84+
7885 }
7986
8087 /**
8188 * Provides access to the given longArray using Memory interface
8289 * @param longArray an on-heap long array
8390 */
8491 public NativeMemory (long [] longArray ) {
85- int arrLen = longArray . length ;
86- if (arrLen <= 0 ) {
92+ this ( LONG_ARRAY_BASE_OFFSET , longArray , null );
93+ if (( longArray == null ) || ( longArray . length == 0 ) ) {
8794 throw new IllegalArgumentException (
88- "longArray must have a length greater than zero." );
95+ "Array must must not be null and have a length greater than zero." );
8996 }
90- memArray_ = longArray ;
91- objectBaseOffset_ = LONG_ARRAY_BASE_OFFSET ;
9297 nativeRawStartAddress_ = 0L ;
93- capacityBytes_ = arrLen << LONG_SHIFT ;
94- byteBuf_ = null ;
98+ capacityBytes_ = longArray .length << LONG_SHIFT ;
9599 }
96100
97101 /**
98102 * Provides access to the backing store of the given ByteBuffer using Memory interface
99103 * @param byteBuf the given ByteBuffer
100104 */
101105 public NativeMemory (ByteBuffer byteBuf ) {
102- capacityBytes_ = byteBuf .capacity ();
103- byteBuf_ = byteBuf ;
104- if (byteBuf_ .isDirect ()) {
105- memArray_ = null ;
106+ if (byteBuf .isDirect ()) {
106107 objectBaseOffset_ = 0L ;
108+ memArray_ = null ;
109+ byteBuf_ = byteBuf ;
107110 nativeRawStartAddress_ = ((sun .nio .ch .DirectBuffer )byteBuf ).address ();
108111 }
109112 else { //must have array
110- memArray_ = byteBuf_ .array ();
111113 objectBaseOffset_ = BYTE_ARRAY_BASE_OFFSET ;
114+ memArray_ = byteBuf .array ();
115+ byteBuf_ = byteBuf ;
112116 nativeRawStartAddress_ = 0L ;
113117 }
118+ capacityBytes_ = byteBuf .capacity ();
119+
114120 }
115121
116122 @ Override
@@ -557,13 +563,22 @@ public Object getParent() {
557563 return memArray_ ;
558564 }
559565
566+ @ Override
567+ public void setMemoryRequest (MemoryRequest memReq ) {
568+ memReq_ = memReq ;
569+ }
570+
560571 @ Override
561572 public String toHexString (String header , long offsetBytes , int lengthBytes ) {
562573 StringBuilder sb = new StringBuilder ();
563574 sb .append (header ).append ("\n " );
564- String s1 = String .format ("(%d, %d)" , offsetBytes , lengthBytes );
565- sb .append (this .getClass ().getName ());
566- sb .append (".toHexString" ).append (s1 ).append (", hash: " ).append (this .hashCode ()).append (":" );
575+ String s1 = String .format ("(..., %d, %d)" , offsetBytes , lengthBytes );
576+ sb .append (this .getClass ().getSimpleName ()).append (".toHexString" ).
577+ append (s1 ).append (", hash: " ).append (this .hashCode ()).append ("\n " );
578+ sb .append (" MemoryRequest: " );
579+ if (memReq_ != null ) {
580+ sb .append (memReq_ .getClass ().getSimpleName ()).append (", hash: " ).append (memReq_ .hashCode ());
581+ } else sb .append ("null" );
567582 return toHex (sb .toString (), offsetBytes , lengthBytes );
568583 }
569584
@@ -586,15 +601,28 @@ public ByteBuffer byteBuffer() {
586601 }
587602
588603 /**
589- * Frees this Memory. If direct, off-heap native memory is allocated via the AllocMemory
590- * sub-class this method must be called in either the NativeMemory class or the AllocMemory class.
604+ * Returns true if this NativeMemory is accessing native (off-heap) memory directly.
605+ * This includes the case of a Direct ByteBuffer.
606+ * @return true if this NativeMemory is accessing native (off-heap) memory directly.
607+ */
608+ public boolean isDirect () {
609+ return nativeRawStartAddress_ > 0 ;
610+ }
611+
612+ /**
613+ * This frees this Memory only if it is required. This always sets the capacity to zero
614+ * and the reference to MemoryRequest to null, which effectively disables this class.
615+ * However,
616+ *
617+ * It is always safe to call this method when you are done with this class.
591618 */
592619 public void freeMemory () {
593620 if (requiresFree ()) {
594621 unsafe .freeMemory (nativeRawStartAddress_ );
595622 nativeRawStartAddress_ = 0L ;
596623 }
597624 capacityBytes_ = 0L ;
625+ memReq_ = null ;
598626 }
599627
600628 /**
@@ -664,7 +692,7 @@ private String toHex(String header, long offsetBytes, int lengthBytes) {
664692 * @return true if the object should be freed when it is no longer needed
665693 */
666694 protected boolean requiresFree () {
667- return nativeRawStartAddress_ != 0L && (byteBuf_ == null );
695+ return ( nativeRawStartAddress_ != 0L ) && (byteBuf_ == null );
668696 }
669697
670698}
0 commit comments