jdk/src/java.desktop/windows/native/libawt/windows/README.JNI
author martin
Wed, 02 Sep 2015 14:11:50 -0700
changeset 32427 c22b7e41adf3
parent 26751 70bac69b37c9
permissions -rw-r--r--
8134984: Text files should end in exactly one newline Summary: automated fixup of newlines at end-of-file via the usual perl one-liner Reviewed-by: chegar, sherman
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
     1
[sl@eng 97/07/24]
90ce3da70b43 Initial load
duke
parents:
diff changeset
     2
90ce3da70b43 Initial load
duke
parents:
diff changeset
     3
All the free-standing functions (those that are not JNI native
90ce3da70b43 Initial load
duke
parents:
diff changeset
     4
methods) must not leak local references.  Local references are
90ce3da70b43 Initial load
duke
parents:
diff changeset
     5
automatically freed when the native method returns to Java. However,
90ce3da70b43 Initial load
duke
parents:
diff changeset
     6
the free-standing functions are called from the event loop that never
90ce3da70b43 Initial load
duke
parents:
diff changeset
     7
returns to Java. If these functions do not clean up the local
90ce3da70b43 Initial load
duke
parents:
diff changeset
     8
references they create, the Java objects corresponding to the local
90ce3da70b43 Initial load
duke
parents:
diff changeset
     9
references will never be garbage collected.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    10
90ce3da70b43 Initial load
duke
parents:
diff changeset
    11
This is caused by the fact that JNI does not clean up local refs 
90ce3da70b43 Initial load
duke
parents:
diff changeset
    12
until control returns to Java. However, this problem is somewhat
90ce3da70b43 Initial load
duke
parents:
diff changeset
    13
unique to AWT code because AWT code has long-running native methods
90ce3da70b43 Initial load
duke
parents:
diff changeset
    14
that never return.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    15
90ce3da70b43 Initial load
duke
parents:
diff changeset
    16
Local refs may be cleaned up manually *before* control returns to 
90ce3da70b43 Initial load
duke
parents:
diff changeset
    17
Java in one of the following two ways:
90ce3da70b43 Initial load
duke
parents:
diff changeset
    18
90ce3da70b43 Initial load
duke
parents:
diff changeset
    19
1. Use EnsureLocalCapacity at the beginning of the function to make
90ce3da70b43 Initial load
duke
parents:
diff changeset
    20
sure the VM has enough memory to create the number of JNI local refs
90ce3da70b43 Initial load
duke
parents:
diff changeset
    21
needed in the function. Use DeleteLocalRef to clean up any local ref
90ce3da70b43 Initial load
duke
parents:
diff changeset
    22
created inside the function that are not returned as the result. For
90ce3da70b43 Initial load
duke
parents:
diff changeset
    23
example:
90ce3da70b43 Initial load
duke
parents:
diff changeset
    24
90ce3da70b43 Initial load
duke
parents:
diff changeset
    25
  void AwtComponent::MeasureListItem(JNIEnv *env, 
90ce3da70b43 Initial load
duke
parents:
diff changeset
    26
				     MEASUREITEMSTRUCT far& measureInfo)
90ce3da70b43 Initial load
duke
parents:
diff changeset
    27
  {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    28
      if (env->EnsureLocalCapacity(1) < 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    29
	  return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    30
      }
90ce3da70b43 Initial load
duke
parents:
diff changeset
    31
      jobject dimension = PreferredItemSize(env);
90ce3da70b43 Initial load
duke
parents:
diff changeset
    32
90ce3da70b43 Initial load
duke
parents:
diff changeset
    33
      ... /* Use dimension */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    34
90ce3da70b43 Initial load
duke
parents:
diff changeset
    35
      env->DeleteLocalRef(dimension);
90ce3da70b43 Initial load
duke
parents:
diff changeset
    36
  }
90ce3da70b43 Initial load
duke
parents:
diff changeset
    37
90ce3da70b43 Initial load
duke
parents:
diff changeset
    38
2. Use PushLocalFrame and PopLocalFrame to start a new local reference
90ce3da70b43 Initial load
duke
parents:
diff changeset
    39
frame. All the local refs created in the new frame will be automatically
90ce3da70b43 Initial load
duke
parents:
diff changeset
    40
freed when PopLocalFrame is called. For example, the above function can be
90ce3da70b43 Initial load
duke
parents:
diff changeset
    41
rewritten as follows:
90ce3da70b43 Initial load
duke
parents:
diff changeset
    42
90ce3da70b43 Initial load
duke
parents:
diff changeset
    43
  void AwtComponent::MeasureListItem(JNIEnv *env, 
90ce3da70b43 Initial load
duke
parents:
diff changeset
    44
				     MEASUREITEMSTRUCT far& measureInfo)
90ce3da70b43 Initial load
duke
parents:
diff changeset
    45
  {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    46
      if (env->PushLocalFrame(1) < 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    47
	  return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    48
      }
90ce3da70b43 Initial load
duke
parents:
diff changeset
    49
      jobject dimension = PreferredItemSize(env);
90ce3da70b43 Initial load
duke
parents:
diff changeset
    50
90ce3da70b43 Initial load
duke
parents:
diff changeset
    51
      ... /* Use dimension */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    52
90ce3da70b43 Initial load
duke
parents:
diff changeset
    53
      env->PopLocalFrame(NULL);
90ce3da70b43 Initial load
duke
parents:
diff changeset
    54
  }
90ce3da70b43 Initial load
duke
parents:
diff changeset
    55
90ce3da70b43 Initial load
duke
parents:
diff changeset
    56
The second approach is easier to use when there are multiple local refs 
90ce3da70b43 Initial load
duke
parents:
diff changeset
    57
to manage. The first approach is more efficient when the function only 
90ce3da70b43 Initial load
duke
parents:
diff changeset
    58
needs to create a small number (3 or less) of local refs.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    59
90ce3da70b43 Initial load
duke
parents:
diff changeset
    60
Pay special attention to local refs created inside a loop. They must be
90ce3da70b43 Initial load
duke
parents:
diff changeset
    61
deleted after every iteration, otherwise they accumulate very quickly:
90ce3da70b43 Initial load
duke
parents:
diff changeset
    62
90ce3da70b43 Initial load
duke
parents:
diff changeset
    63
int AwtFont::getFontDescriptorNumber(JNIEnv *env, jobject font,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    64
				     jobject fontDescriptor)
90ce3da70b43 Initial load
duke
parents:
diff changeset
    65
{
90ce3da70b43 Initial load
duke
parents:
diff changeset
    66
    ... /* other stuff */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    67
90ce3da70b43 Initial load
duke
parents:
diff changeset
    68
    jarray array = ...
90ce3da70b43 Initial load
duke
parents:
diff changeset
    69
90ce3da70b43 Initial load
duke
parents:
diff changeset
    70
    for (i = 0; i < num; i++){
90ce3da70b43 Initial load
duke
parents:
diff changeset
    71
	refFontDescriptor = env->GetObjectArrayElement(array, i);
90ce3da70b43 Initial load
duke
parents:
diff changeset
    72
	if (env->IsSameObject(refFontDescriptor, fontDescriptor)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    73
	    env->DeleteLocalRef(refFontDescriptor);
90ce3da70b43 Initial load
duke
parents:
diff changeset
    74
	    env->DeleteLocalRef(array);
90ce3da70b43 Initial load
duke
parents:
diff changeset
    75
	    return i;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    76
	}
90ce3da70b43 Initial load
duke
parents:
diff changeset
    77
	env->DeleteLocalRef(refFontDescriptor);
90ce3da70b43 Initial load
duke
parents:
diff changeset
    78
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
    79
    env->DeleteLocalRef(array);
90ce3da70b43 Initial load
duke
parents:
diff changeset
    80
    return 0;	// Not found.  Use default.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    81
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
    82
90ce3da70b43 Initial load
duke
parents:
diff changeset
    83
Note that we must make sure the local refs are cleaned up at every possible
90ce3da70b43 Initial load
duke
parents:
diff changeset
    84
return branch. To reduce code duplication, many AWT functions use "goto"
90ce3da70b43 Initial load
duke
parents:
diff changeset
    85
to jump to a common set of cleanup statements.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    86
90ce3da70b43 Initial load
duke
parents:
diff changeset
    87
Even if we use PushLocalFrame, we must still delete the local refs created
90ce3da70b43 Initial load
duke
parents:
diff changeset
    88
in the loop:
90ce3da70b43 Initial load
duke
parents:
diff changeset
    89
90ce3da70b43 Initial load
duke
parents:
diff changeset
    90
    if (env->PushLocalFrame(2) < 0)
90ce3da70b43 Initial load
duke
parents:
diff changeset
    91
	return 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    92
    jarray array = ...
90ce3da70b43 Initial load
duke
parents:
diff changeset
    93
    for (i = 0; i < num; i++){
90ce3da70b43 Initial load
duke
parents:
diff changeset
    94
	refFontDescriptor = env->GetObjectArrayElement(array, i);
90ce3da70b43 Initial load
duke
parents:
diff changeset
    95
	if (env->IsSameObject(refFontDescriptor, fontDescriptor)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    96
	    env->PopLocalFrame(NULL);
90ce3da70b43 Initial load
duke
parents:
diff changeset
    97
	    return i;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    98
	}
90ce3da70b43 Initial load
duke
parents:
diff changeset
    99
	env->DeleteLocalRef(refFontDescriptor);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   100
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   101
    env->PopLocalFrame(NULL);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   102
    return 0;	// Not found.  Use default.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   103
90ce3da70b43 Initial load
duke
parents:
diff changeset
   104
unless we ensure that we have space for all possible local refs we are 
90ce3da70b43 Initial load
duke
parents:
diff changeset
   105
going to create inside the loop (note the different argument passed 
90ce3da70b43 Initial load
duke
parents:
diff changeset
   106
to PushLocalFrame):
90ce3da70b43 Initial load
duke
parents:
diff changeset
   107
90ce3da70b43 Initial load
duke
parents:
diff changeset
   108
// Maximum number of local refs we can create in this code segment is
90ce3da70b43 Initial load
duke
parents:
diff changeset
   109
// num + 1.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   110
    if (env->PushLocalFrame(num + 1) < 0)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   111
	return 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   112
    jarray array = ...
90ce3da70b43 Initial load
duke
parents:
diff changeset
   113
    for (i = 0; i < num; i++){
90ce3da70b43 Initial load
duke
parents:
diff changeset
   114
	refFontDescriptor = env->GetObjectArrayElement(array, i);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   115
	if (env->IsSameObject(refFontDescriptor, fontDescriptor)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   116
	    env->PopLocalFrame(NULL);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   117
	    return i;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   118
	}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   119
// no longer necessary. env->DeleteLocalRef(refFontDescriptor);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   120
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   121
    env->PopLocalFrame(NULL);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   122
    return 0;	// Not found.  Use default.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   123
90ce3da70b43 Initial load
duke
parents:
diff changeset
   124
THINGS TO DO:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   125
90ce3da70b43 Initial load
duke
parents:
diff changeset
   126
    1. Investigate another possibility of dealing with local refs. Instead
90ce3da70b43 Initial load
duke
parents:
diff changeset
   127
    of making sure every free-standing function does not leak local refs,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   128
    we could alternatively create a new local ref frame for each invocation
90ce3da70b43 Initial load
duke
parents:
diff changeset
   129
    of callback functions. All local refs created during the execution of 
90ce3da70b43 Initial load
duke
parents:
diff changeset
   130
    the callback will then be automatically freed.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   131
90ce3da70b43 Initial load
duke
parents:
diff changeset
   132
    2. Handle exceptions properly. The current code lacks error checking
90ce3da70b43 Initial load
duke
parents:
diff changeset
   133
    and recovery. This leads to random runtime crashes.