6565 * </ul>
6666 */
6767public final class JNIObjectHandles {
68- @ Fold // replaces with true/false at compile time and removes unnecessary runtime checks
68+ @ Fold
6969 static boolean haveAssertions () {
7070 return RuntimeAssertionsSupport .singleton ().desiredAssertionStatus (JNIObjectHandles .class );
7171 }
@@ -219,6 +219,7 @@ public static void deleteLocalRef(JNIObjectHandle localRef) {
219219 getOrCreateLocals ().delete (decodeLocal (localRef ));
220220 }
221221 }
222+
222223 // in frames are local handles stored
223224 public static int pushLocalFrame (int capacity ) {
224225 return getOrCreateLocals ().pushFrame (capacity );
@@ -227,6 +228,7 @@ public static int pushLocalFrame(int capacity) {
227228 public static void popLocalFrame () {
228229 getExistingLocals ().popFrame ();
229230 }
231+
230232 // pops frames down to a specific starting point identified by the int frame
231233 @ Uninterruptible (reason = "Called from uninterruptible code." , mayBeInlined = true )
232234 public static void popLocalFramesIncluding (int frame ) {
@@ -295,6 +297,7 @@ static long computeCurrentGlobalHandleCount() {
295297final class JNIGlobalHandles {
296298 static final SignedWord MIN_VALUE = Word .signed (Long .MIN_VALUE ); // -2^63
297299 static final SignedWord MAX_VALUE = JNIObjectHandles .nullHandle ().subtract (1 ); // -1
300+
298301 static {
299302 assert JNIObjectHandles .nullHandle ().equal (Word .zero ());
300303 }
@@ -311,6 +314,23 @@ final class JNIGlobalHandles {
311314 // Define the mid-point to split the range in half
312315 private static final SignedWord HANDLE_RANGE_SPLIT_POINT = Word .signed (1L << 30 );
313316
317+ // Strong global handles will occupy the lower half of the global handles range
318+ public static final SignedWord STRONG_GLOBAL_RANGE_MIN = JNIObjectHandles .nullHandle ().add (1 );
319+ ;
320+ public static final SignedWord STRONG_GLOBAL_RANGE_MAX = HANDLE_RANGE_SPLIT_POINT .subtract (1 );
321+
322+ // Weak global handles will occupy the upper half of the global handles range
323+ public static final SignedWord WEAK_GLOBAL_RANGE_MIN = HANDLE_RANGE_SPLIT_POINT ;
324+ public static final SignedWord WEAK_GLOBAL_RANGE_MAX = HANDLE_BITS_MASK ;
325+
326+ private static final ObjectHandlesImpl strongGlobalHandles
327+ = new ObjectHandlesImpl (STRONG_GLOBAL_RANGE_MIN , STRONG_GLOBAL_RANGE_MAX , JNIObjectHandles .nullHandle ());
328+ private static final ObjectHandlesImpl weakGlobalHandles
329+ = new ObjectHandlesImpl (WEAK_GLOBAL_RANGE_MIN , WEAK_GLOBAL_RANGE_MAX , JNIObjectHandles .nullHandle ());
330+
331+ // Define the mid-point to split the range in half
332+ private static final SignedWord HANDLE_RANGE_SPLIT_POINT = Word .signed (1L << 30 );
333+
314334 // Strong global handles will occupy the lower half of the global handles range
315335 public static final SignedWord STRONG_GLOBAL_RANGE_MIN = JNIObjectHandles .nullHandle ().add (1 );;
316336 public static final SignedWord STRONG_GLOBAL_RANGE_MAX = HANDLE_RANGE_SPLIT_POINT .subtract (1 );
@@ -334,6 +354,19 @@ private static Word isolateHash() {
334354 return Word .unsigned (isolateHash );
335355 }
336356
357+ /**
358+ * Encodes a raw {@code ObjectHandle} into a strong {@code JNIObjectHandle}.
359+ * * A strong handle guarantees the referenced object remains alive as long as
360+ * the handle itself exists.
361+ * * The handle is encoded by:
362+ * 1. Asserting the handle fits within the available bit range.
363+ * 2. Inserting validation bits (derived from the isolate hash) for security.
364+ * 3. Setting the Most Significant Bit (MSB, bit 63) to mark it as an encoded handle.
365+ * 4. The WEAK_HANDLE_FLAG bit (bit 62) remains 0.
366+ *
367+ * @param handle The raw, unencoded handle to the Java object.
368+ * @return The resulting strong JNI object handle with embedded metadata.
369+ */
337370 private static JNIObjectHandle encodeStrong (ObjectHandle handle ) {
338371 SignedWord h = (Word ) handle ;
339372 if (JNIObjectHandles .haveAssertions ()) {
@@ -347,34 +380,38 @@ private static JNIObjectHandle encodeStrong(ObjectHandle handle) {
347380 return (JNIObjectHandle ) h ;
348381 }
349382
383+ /**
384+ * Encodes a raw {@code ObjectHandle} into a weak {@code JNIObjectHandle}.
385+ * * A weak handle allows the referenced object to be garbage collected even
386+ * if the handle exists. The handle will be cleared when the object dies.
387+ * * This method calls {@link #encodeStrong(ObjectHandle)} to perform all
388+ * common encoding steps, and then explicitly sets the {@code WEAK_HANDLE_FLAG}
389+ * bit (bit 62) to mark the handle as weak.
390+ *
391+ * @param handle The raw, unencoded handle to the Java object.
392+ * @return The resulting weak JNI object handle with embedded metadata.
393+ */
350394 private static JNIObjectHandle encodeWeak (ObjectHandle handle ) {
351- SignedWord h = (Word ) handle ;
352- if (JNIObjectHandles .haveAssertions ()) {
353- assert h .and (HANDLE_BITS_MASK ).equal (h ) : "unencoded handle must fit in range" ;
354- Word v = isolateHash ().shiftLeft (VALIDATION_BITS_SHIFT );
355- assert v .and (VALIDATION_BITS_MASK ).equal (v ) : "validation value must fit in its range" ;
356- h = h .or (v );
357- }
358- h = h .or (MSB );
359- h = h .or (WEAK_HANDLE_FLAG ); // Set bit 62 to mark it as weak
395+ SignedWord h = (Word ) encodeStrong (handle );
396+ h = h .or (WEAK_HANDLE_FLAG );
360397 assert isInRange ((JNIObjectHandle ) h );
361398 return (JNIObjectHandle ) h ;
362399 }
363400
364401 private static ObjectHandle decode (JNIObjectHandle handle ) {
365402 assert isInRange (handle );
366403 assert ((Word ) handle ).and (VALIDATION_BITS_MASK ).unsignedShiftRight (VALIDATION_BITS_SHIFT )
367- .equal (isolateHash ()) : "mismatching validation value -- passed a handle from a different isolate?" ;
404+ .equal (isolateHash ()) : "mismatching validation value -- passed a handle from a different isolate?" ;
368405 return (ObjectHandle ) HANDLE_BITS_MASK .and ((Word ) handle );
369406 }
370407
371408 static <T > T getObject (JNIObjectHandle handle ) {
372409 SignedWord handleValue = (Word ) handle ;
373- if (handleValue .greaterOrEqual ( STRONG_GLOBAL_RANGE_MIN ) && handleValue . lessOrEqual ( STRONG_GLOBAL_RANGE_MAX ) ) {
410+ if (( handleValue .toLong ( ) & WEAK_HANDLE_FLAG . toLong ()) == 0 ) {
374411 return strongGlobalHandles .get (decode (handle ));
375412 }
376413
377- if (handleValue .greaterOrEqual ( WEAK_GLOBAL_RANGE_MIN ) && handleValue . lessOrEqual ( WEAK_GLOBAL_RANGE_MAX ) ) {
414+ if (( handleValue .toLong ( ) & WEAK_HANDLE_FLAG . toLong ()) == 1 ) {
378415 return weakGlobalHandles .get (decode ((handle )));
379416 }
380417
@@ -383,11 +420,11 @@ static <T> T getObject(JNIObjectHandle handle) {
383420
384421 static JNIObjectRefType getHandleType (JNIObjectHandle handle ) {
385422 SignedWord handleValue = (Word ) handle ;
386- if (handleValue .greaterOrEqual ( STRONG_GLOBAL_RANGE_MIN ) && handleValue . lessOrEqual ( STRONG_GLOBAL_RANGE_MAX ) ) {
423+ if (( handleValue .toLong ( ) & WEAK_HANDLE_FLAG . toLong ()) == 0 ) {
387424 return JNIObjectRefType .Global ;
388425 }
389426
390- if (handleValue .greaterOrEqual ( WEAK_GLOBAL_RANGE_MIN ) && handleValue . lessOrEqual ( WEAK_GLOBAL_RANGE_MAX ) ) {
427+ if (( handleValue .toLong ( ) & WEAK_HANDLE_FLAG . toLong ()) == 1 ) {
391428 return JNIObjectRefType .WeakGlobal ;
392429 }
393430 return JNIObjectRefType .Invalid ;
@@ -419,7 +456,7 @@ public static long computeCurrentCount() {
419456 * move and are not garbage-collected, so the handle just contains an object's offset in the image
420457 * heap. This approach has the major benefit that handles are valid across isolates that are created
421458 * from the same image, which helps with native code that is unaware of multiple isolates.
422- *
459+ * <p>
423460 * Although this type of handle doesn't need explicit management, we still distinguish between
424461 * local, global and weak-global references by means of a bit pattern in order to comply with the
425462 * JNI specification (in particular, for function {@code GetObjectRefType}).
0 commit comments