Understanding Secure Access of JNI Arguments

I am doing some research on how HotSpot performs garbage collection and / or heap compression while running JNI code.

It is well known that objects can be moved at any time in Java. I am trying to figure out finally if the JNI is prone to garbage collection effects. There are a number of JNI features to explicitly prevent garbage collection; for example GetPrimitiveArrayCritical. It makes sense that such a function exists if the links are really unstable. However, this makes no sense if they are not.

It seems that there is a significant portion of conflicting information on this subject, and I'm trying to figure it out.

JNI code runs in a safe place and can continue to work, unless it calls back to Java or calls some specific JVM methods, after which it can be stopped to prevent exit from safepoint (thanks Nitzan for comments).

What mechanism does the JVM use to block threads during pause pause

The above makes me think that garbage collection will start at the same time as the JNI code. It can't be safe, right?

To implement local references, the Java virtual machine creates a registry for each control transition from Java to its own method. Registry maps are irreplaceable local references to Java objects and saves objects from garbage collection. All Java objects passed the method (including those returned as JNI function calls) are automatically added to the registry. The registry is deleted after the return of its own method, which allows entries to collect garbage.

https://docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/design.html#wp16789

Ok, so the links localare immutable, but that says nothing about compaction.

JVM , Java ™ , . GC, JVM , "" ".

, :

  • JVM (" " ).
  • J2N .

JVM , J2N, :

  • .
  • , .

J2N , set, " " PushLocalFrame JNI.

http://www.ibm.com/support/knowledgecenter/en/SSYKE2_5.0.0/com.ibm.java.doc.diagnostics.50/diag/understanding/jni_transitions_j2n.html

, IBM local reference root set, . , .

GC , . . JNI . , JNI . .

, . , , . . JNI , , JNI . . JNI .

  • GetPrimitiveArrayCritical Java ™, ReleasePrimitiveArrayCritical.
  • GetStringCritical java.lang.String, , ReleaseStringCritical.

http://www.ibm.com/support/knowledgecenter/SSYKE2_6.0.0/com.ibm.java.doc.diagnostics.60/diag/understanding/jni_copypin.html

, IBM , JNI , ! HotSpot?

GetArrayElements , (, , ). , GetPrimitiveArrayCritical. , / ( ) , .

GC JNI?

, - Get<PrimitiveType>ArrayElements GetPrimitiveArrayCritical

.

, JVM ( , ), CMS GC, JNI ( , , - , - , , , , ). , ( ), , , (- ), - , ( ).

http://mail.openjdk.java.net/pipermail/hotspot-runtime-dev/2007-December/000074.html

OpenJDK, , , GC ConcurrentMarkAndSweep .

https://www.infoq.com/articles/G1-One-Garbage-Collector-To-Rule-Them-All

G1 , , .


IBM , ; , JNI HotSpot . , , , , JNI.

HotSpot, . GetByteArrayElements. , . , .

GetByteArrayElements

#ifndef USDT2
#define DEFINE_GETSCALARARRAYELEMENTS(ElementTag,ElementType,Result, Tag) 
JNI_QUICK_ENTRY(ElementType*,
          jni_Get##Result##ArrayElements(JNIEnv *env, ElementType##Array array, jboolean *isCopy))
  JNIWrapper("Get" XSTR(Result) "ArrayElements");
  DTRACE_PROBE3(hotspot_jni, Get##Result##ArrayElements__entry, env, array, isCopy);
  /* allocate an chunk of memory in c land */
  typeArrayOop a = typeArrayOop(JNIHandles::resolve_non_null(array));
  ElementType* result;
  int len = a->length();
  if (len == 0) {
    result = (ElementType*)get_bad_address();
  } else {
    result = NEW_C_HEAP_ARRAY_RETURN_NULL(ElementType, len, mtInternal);
    if (result != NULL) {                                    
          memcpy(result, a->Tag##_at_addr(0), sizeof(ElementType)*len);
      if (isCopy) {
        *isCopy = JNI_TRUE;
      }
    }  
  }
  DTRACE_PROBE1(hotspot_jni, Get##Result##ArrayElements__return, result);
  return result;
JNI_END

JNI_QUICK_ENTRY

#define JNI_QUICK_ENTRY(result_type, header)                         \
extern "C" {                                                         \
  result_type JNICALL header {                                \
    JavaThread* thread=JavaThread::thread_from_jni_environment(env); \
    assert( !VerifyJNIEnvThread || (thread == Thread::current()), "JNIEnv is only valid in same thread"); \
    ThreadInVMfromNative __tiv(thread);                              \
    debug_only(VMNativeEntryWrapper __vew;)                          \
VM_QUICK_ENTRY_BASE(result_type, header, thread)

- . , , __tiv, , , .

  • - , JNI, GetByteArrayElements, ?
  • , - , JNI VM Native, JNI_QUICK_ENTRY ?
+4
2

JNI- JVM HotSpot

JNI

  • = _thread_in_native;
    GC

  • JNI

  • = _thread_in_native_trans;
    GC

  • VM, ,

  • state = _thread_in_vm;

+2

, .

, , . , JNI, , , , , .

, JNI ?

, . .

+2

Source: https://habr.com/ru/post/1653960/


All Articles