Eine aufbereitete Darstellung der Quelle

 
     
 
 
Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 

Benutzer

Quelle  jni_test.cc

  Sprache: C
 

/*
 * Copyright (C) 2013 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


#include <pthread.h>

#include <cstdio>
#include <iostream>
#include <vector>

#include <android-base/logging.h>

#include "art_method-inl.h"
#include "base/runtime_debug.h"
#include "jni.h"

namespace art {

static JavaVM* jvm = nullptr;

static jint Java_Main_intFastNativeMethod(JNIEnv*, jclass, jint a, jint b, jint c);
static jint Java_Main_intCriticalNativeMethod(jint a, jint b, jint c);

static JNINativeMethod sMainMethods[] = {
  {"intFastNativeMethod""(III)I"reinterpret_cast<void*>(Java_Main_intFastNativeMethod) },
  {"intCriticalNativeMethod""(III)I"reinterpret_cast<void*>(Java_Main_intCriticalNativeMethod) },
};

extern "C" JNIEXPORT jint JNI_OnLoad(JavaVM *vm, void*) {
  CHECK(vm != nullptr);
  CHECK(jvm == nullptr);
  jvm = vm;
  std::cout << "JNI_OnLoad called" << std::endl;

  return JNI_VERSION_1_6;
}

extern "C" JNIEXPORT void JNI_OnUnload(JavaVM*, void*) {
  // std::cout since LOG(INFO) adds extra stuff like pid.
  std::cout << "JNI_OnUnload called" << std::endl;
  // Clear jvm for CHECK in test 004-JniTest.
  jvm = nullptr;
}

static void* AttachHelper(void* arg) {
  CHECK(jvm != nullptr);

  JNIEnv* env = nullptr;
  JavaVMAttachArgs args = { JNI_VERSION_1_6, __FUNCTION__, nullptr };
  int attach_result = jvm->AttachCurrentThread(&env, &args);
  CHECK_EQ(attach_result, 0);

  using Fn = void(*)(JNIEnv*);
  Fn fn = reinterpret_cast<Fn>(arg);
  fn(env);

  int detach_result = jvm->DetachCurrentThread();
  CHECK_EQ(detach_result, 0);
  return nullptr;
}

static void PthreadHelper(void (*fn)(JNIEnv*)) {
  pthread_t pthread;
  int pthread_create_result = pthread_create(&pthread, nullptr, AttachHelper,
                                             reinterpret_cast<void*>(fn));
  CHECK_EQ(pthread_create_result, 0);
  int pthread_join_result = pthread_join(pthread, nullptr);
  CHECK_EQ(pthread_join_result, 0);
}

static void testFindClassOnAttachedNativeThread(JNIEnv* env) {
  jclass clazz = env->FindClass("Main");
  CHECK(clazz != nullptr);
  CHECK(!env->ExceptionCheck());

  jobjectArray array = env->NewObjectArray(0, clazz, nullptr);
  CHECK(array != nullptr);
  CHECK(!env->ExceptionCheck());
}

extern "C" JNIEXPORT void JNICALL Java_Main_testUTFRegion(JNIEnv* env, jclass, jstring null_str) {
  jstring foo_str = env->NewStringUTF("FOOBAR");
  jstring emoji_str = env->NewStringUTF("SKI ⛷ SKI");
  char buf[1024];
  memset(buf, 'Y'sizeof(buf));
  buf[1023] = '\0';

  env->GetStringUTFRegion(foo_str, 31, buf);
  buf[1023] = '\0';
  CHECK_EQ(strcmp("B", buf), 0) << buf;

  // Null char on 0 len region
  env->GetStringUTFRegion(foo_str, 30, buf);
  buf[1023] = '\0';
  CHECK_EQ(strcmp("", buf), 0) << buf;

  // No SEGV
  env->GetStringUTFRegion(foo_str, 30, nullptr);

  env->GetStringUTFRegion(null_str, 11, buf);
  buf[1023] = '\0';
  std::array<uint8_t, 3> nullbuf{ 0xc0, 0x80, 0x00 };
  CHECK_EQ(memcmp(nullbuf.data(), buf, 3), 0);

  env->GetStringUTFRegion(emoji_str, 16, buf);
  buf[1023] = '\0';
  CHECK_EQ(strcmp("KI ⛷ S", buf), 0);
}

extern "C" JNIEXPORT jint JNICALL Java_Main_getFieldSubclass(JNIEnv* env,
                                                             jclass,
                                                             jobject f_obj,
                                                             jclass sub) {
  jfieldID f = env->FromReflectedField(f_obj);
  return env->GetStaticIntField(sub, f);
}

// http://b/10994325
extern "C" JNIEXPORT void JNICALL Java_Main_testFindClassOnAttachedNativeThread(JNIEnv*, jclass) {
  PthreadHelper(&testFindClassOnAttachedNativeThread);
}

static void testFindFieldOnAttachedNativeThread(JNIEnv* env) {
  jclass clazz = env->FindClass("Main");
  CHECK(clazz != nullptr);
  CHECK(!env->ExceptionCheck());

  jfieldID field = env->GetStaticFieldID(clazz, "testFindFieldOnAttachedNativeThreadField""Z");
  CHECK(field != nullptr);
  CHECK(!env->ExceptionCheck());

  env->SetStaticBooleanField(clazz, field, JNI_TRUE);
}

extern "C" JNIEXPORT void JNICALL Java_Main_testFindFieldOnAttachedNativeThreadNative(JNIEnv*,
                                                                                      jclass) {
  PthreadHelper(&testFindFieldOnAttachedNativeThread);
}

static void testReflectFieldGetFromAttachedNativeThread(JNIEnv* env) {
  jclass clazz = env->FindClass("Main");
  CHECK(clazz != nullptr);
  CHECK(!env->ExceptionCheck());

  jclass class_clazz = env->FindClass("java/lang/Class");
  CHECK(class_clazz != nullptr);
  CHECK(!env->ExceptionCheck());

  jmethodID getFieldMetodId = env->GetMethodID(class_clazz, "getField",
                                               "(Ljava/lang/String;)Ljava/lang/reflect/Field;");
  CHECK(getFieldMetodId != nullptr);
  CHECK(!env->ExceptionCheck());

  jstring field_name = env->NewStringUTF("testReflectFieldGetFromAttachedNativeThreadField");
  CHECK(field_name != nullptr);
  CHECK(!env->ExceptionCheck());

  jobject field = env->CallObjectMethod(clazz, getFieldMetodId, field_name);
  CHECK(field != nullptr);
  CHECK(!env->ExceptionCheck());

  jclass field_clazz = env->FindClass("java/lang/reflect/Field");
  CHECK(field_clazz != nullptr);
  CHECK(!env->ExceptionCheck());

  jmethodID getBooleanMetodId = env->GetMethodID(field_clazz, "getBoolean",
                                                 "(Ljava/lang/Object;)Z");
  CHECK(getBooleanMetodId != nullptr);
  CHECK(!env->ExceptionCheck());

  jboolean value = env->CallBooleanMethod(field, getBooleanMetodId, /* ignored */ clazz);
  CHECK(value == false);
  CHECK(!env->ExceptionCheck());
}

// http://b/15539150
extern "C" JNIEXPORT void JNICALL Java_Main_testReflectFieldGetFromAttachedNativeThreadNative(
    JNIEnv*, jclass) {
  PthreadHelper(&testReflectFieldGetFromAttachedNativeThread);
}


// http://b/11243757
extern "C" JNIEXPORT void JNICALL Java_Main_testCallStaticVoidMethodOnSubClassNative(JNIEnv* env,
                                                                                     jclass) {
  jclass super_class = env->FindClass("Main$testCallStaticVoidMethodOnSubClass_SuperClass");
  CHECK(super_class != nullptr);

  jmethodID execute = env->GetStaticMethodID(super_class, "execute""()V");
  CHECK(execute != nullptr);

  jclass sub_class = env->FindClass("Main$testCallStaticVoidMethodOnSubClass_SubClass");
  CHECK(sub_class != nullptr);

  env->CallStaticVoidMethod(sub_class, execute);
}

extern "C" JNIEXPORT jobject JNICALL Java_Main_testGetMirandaMethodNative(JNIEnv* env, jclass) {
  jclass abstract_class = env->FindClass("Main$testGetMirandaMethod_MirandaAbstract");
  CHECK(abstract_class != nullptr);
  jmethodID miranda_method = env->GetMethodID(abstract_class, "inInterface""()Z");
  CHECK(miranda_method != nullptr);
  return env->ToReflectedMethod(abstract_class, miranda_method, JNI_FALSE);
}

// https://code.google.com/p/android/issues/detail?id=63055
extern "C" void JNICALL Java_Main_testZeroLengthByteBuffers(JNIEnv* env, jclass) {
  std::vector<uint8_t> buffer(1);
  jobject byte_buffer = env->NewDirectByteBuffer(&buffer[0], 0);
  CHECK(byte_buffer != nullptr);
  CHECK(!env->ExceptionCheck());

  CHECK_EQ(env->GetDirectBufferAddress(byte_buffer), &buffer[0]);
  CHECK_EQ(env->GetDirectBufferCapacity(byte_buffer), 0);
}

constexpr size_t kByteReturnSize = 7;
jbyte byte_returns[kByteReturnSize] = { 012127, -1, -2, -128 };

extern "C" jbyte JNICALL Java_Main_byteMethod(JNIEnv*, jclass, jbyte b1, jbyte b2,
                                              jbyte b3, jbyte b4, jbyte b5, jbyte b6,
                                              jbyte b7, jbyte b8, jbyte b9, jbyte b10) {
  // We use b1 to drive the output.
  CHECK_EQ(b2, 2);
  CHECK_EQ(b3, -3);
  CHECK_EQ(b4, 4);
  CHECK_EQ(b5, -5);
  CHECK_EQ(b6, 6);
  CHECK_EQ(b7, -7);
  CHECK_EQ(b8, 8);
  CHECK_EQ(b9, -9);
  CHECK_EQ(b10, 10);

  CHECK_LE(0, b1);
  CHECK_LT(b1, static_cast<jbyte>(kByteReturnSize));

  return byte_returns[b1];
}

constexpr size_t kShortReturnSize = 9;
jshort short_returns[kShortReturnSize] = { 01212732767, -1, -2, -128,
    static_cast<jshort>(0x8000) };
// The weird static_cast is because short int is only guaranteed down to -32767, not Java's -32768.

extern "C" jshort JNICALL Java_Main_shortMethod(JNIEnv*, jclass, jshort s1, jshort s2,
                                                jshort s3, jshort s4, jshort s5, jshort s6,
                                                jshort s7, jshort s8, jshort s9, jshort s10) {
  // We use s1 to drive the output.
  CHECK_EQ(s2, 2);
  CHECK_EQ(s3, -3);
  CHECK_EQ(s4, 4);
  CHECK_EQ(s5, -5);
  CHECK_EQ(s6, 6);
  CHECK_EQ(s7, -7);
  CHECK_EQ(s8, 8);
  CHECK_EQ(s9, -9);
  CHECK_EQ(s10, 10);

  CHECK_LE(0, s1);
  CHECK_LT(s1, static_cast<jshort>(kShortReturnSize));

  return short_returns[s1];
}

extern "C" jboolean JNICALL Java_Main_booleanMethod(JNIEnv*, jclass, jboolean b1,
                                                    jboolean b2, jboolean b3, jboolean b4,
                                                    jboolean b5, jboolean b6, jboolean b7,
                                                    jboolean b8, jboolean b9, jboolean b10) {
  // We use b1 to drive the output.
  CHECK_EQ(b2, JNI_TRUE);
  CHECK_EQ(b3, JNI_FALSE);
  CHECK_EQ(b4, JNI_TRUE);
  CHECK_EQ(b5, JNI_FALSE);
  CHECK_EQ(b6, JNI_TRUE);
  CHECK_EQ(b7, JNI_FALSE);
  CHECK_EQ(b8, JNI_TRUE);
  CHECK_EQ(b9, JNI_FALSE);
  CHECK_EQ(b10, JNI_TRUE);

  CHECK(b1 == JNI_TRUE || b1 == JNI_FALSE);
  return b1;
}

constexpr size_t kCharReturnSize = 8;
jchar char_returns[kCharReturnSize] = { 0121272552561500034000 };

extern "C" jchar JNICALL Java_Main_charMethod(JNIEnv*, jclass, jchar c1, jchar c2,
                                              jchar c3, jchar c4, jchar c5, jchar c6, jchar c7,
                                              jchar c8, jchar c9, jchar c10) {
  // We use c1 to drive the output.
  CHECK_EQ(c2, 'a');
  CHECK_EQ(c3, 'b');
  CHECK_EQ(c4, 'c');
  CHECK_EQ(c5, '0');
  CHECK_EQ(c6, '1');
  CHECK_EQ(c7, '2');
  CHECK_EQ(c8, 1234);
  CHECK_EQ(c9, 2345);
  CHECK_EQ(c10, 3456);

  CHECK_LT(c1, static_cast<jchar>(kCharReturnSize));

  return char_returns[c1];
}

extern "C" JNIEXPORT void JNICALL Java_Main_removeLocalObject(JNIEnv* env, jclass, jclass o) {
  // Delete the arg to see if it crashes.
  env->DeleteLocalRef(o);
}

extern "C" JNIEXPORT jboolean JNICALL Java_Main_nativeIsAssignableFrom(JNIEnv* env, jclass,
                                                                       jclass from, jclass to) {
  return env->IsAssignableFrom(from, to);
}

static void testShallowGetCallingClassLoader(JNIEnv* env) {
  // Test direct call.
  {
    jclass vmstack_clazz = env->FindClass("dalvik/system/VMStack");
    CHECK(vmstack_clazz != nullptr);
    CHECK(!env->ExceptionCheck());

    jmethodID getCallingClassLoaderMethodId = env->GetStaticMethodID(vmstack_clazz,
                                                                     "getCallingClassLoader",
                                                                     "()Ljava/lang/ClassLoader;");
    CHECK(getCallingClassLoaderMethodId != nullptr);
    CHECK(!env->ExceptionCheck());

    jobject class_loader = env->CallStaticObjectMethod(vmstack_clazz,
                                                       getCallingClassLoaderMethodId);
    CHECK(class_loader == nullptr);
    CHECK(!env->ExceptionCheck());
  }

  // Test one-level call. Use System.loadLibrary().
  {
    jclass system_clazz = env->FindClass("java/lang/System");
    CHECK(system_clazz != nullptr);
    CHECK(!env->ExceptionCheck());

    jmethodID loadLibraryMethodId = env->GetStaticMethodID(system_clazz, "loadLibrary",
                                                           "(Ljava/lang/String;)V");
    CHECK(loadLibraryMethodId != nullptr);
    CHECK(!env->ExceptionCheck());

    // Create a string object.
    jobject library_string = env->NewStringUTF("non_existing_library");
    CHECK(library_string != nullptr);
    CHECK(!env->ExceptionCheck());

    env->CallStaticVoidMethod(system_clazz, loadLibraryMethodId, library_string);
    CHECK(env->ExceptionCheck());

    // We expect UnsatisfiedLinkError.
    jthrowable thrown = env->ExceptionOccurred();
    env->ExceptionClear();

    jclass unsatisfied_link_error_clazz = env->FindClass("java/lang/UnsatisfiedLinkError");
    jclass thrown_class = env->GetObjectClass(thrown);
    CHECK(env->IsSameObject(unsatisfied_link_error_clazz, thrown_class));
  }
}

// http://b/16867274
extern "C" JNIEXPORT void JNICALL Java_Main_nativeTestShallowGetCallingClassLoader(JNIEnv*,
                                                                                   jclass) {
  PthreadHelper(&testShallowGetCallingClassLoader);
}

static void testShallowGetStackClass2(JNIEnv* env) {
  jclass vmstack_clazz = env->FindClass("dalvik/system/VMStack");
  CHECK(vmstack_clazz != nullptr);
  CHECK(!env->ExceptionCheck());

  // Test direct call.
  {
    jmethodID getStackClass2MethodId = env->GetStaticMethodID(vmstack_clazz, "getStackClass2",
                                                              "()Ljava/lang/Class;");
    CHECK(getStackClass2MethodId != nullptr);
    CHECK(!env->ExceptionCheck());

    jobject caller_class = env->CallStaticObjectMethod(vmstack_clazz, getStackClass2MethodId);
    CHECK(caller_class == nullptr);
    CHECK(!env->ExceptionCheck());
  }

  // Test one-level call. Use VMStack.getStackClass1().
  {
    jmethodID getStackClass1MethodId = env->GetStaticMethodID(vmstack_clazz, "getStackClass1",
                                                              "()Ljava/lang/Class;");
    CHECK(getStackClass1MethodId != nullptr);
    CHECK(!env->ExceptionCheck());

    jobject caller_class = env->CallStaticObjectMethod(vmstack_clazz, getStackClass1MethodId);
    CHECK(caller_class == nullptr);
    CHECK(!env->ExceptionCheck());
  }

  // For better testing we would need to compile against libcore and have a two-deep stack
  // ourselves.
}

extern "C" JNIEXPORT void JNICALL Java_Main_nativeTestShallowGetStackClass2(JNIEnv*, jclass) {
  PthreadHelper(&testShallowGetStackClass2);
}

class JniCallNonvirtualVoidMethodTest {
 public:
  explicit JniCallNonvirtualVoidMethodTest(JNIEnv* env)
      : env_(env),
        check_jni_ri_(true),
        check_jni_android_(true),
        super_(GetClass("JniCallNonvirtualTest")),
        sub_(GetClass("JniCallNonvirtualTestSubclass")),
        super_constructor_(GetMethodID(super_, true"<init>")),
        super_static_(GetMethodID(super_, false"staticMethod")),
        super_nonstatic_(GetMethodID(super_, true"nonstaticMethod")),
        sub_constructor_(GetMethodID(sub_, true"<init>")),
        sub_static_(GetMethodID(sub_, false"staticMethod")),
        sub_nonstatic_(GetMethodID(sub_, true"nonstaticMethod")),
        super_field_(GetFieldID(super_, "nonstaticMethodSuperCalled")),
        sub_field_(GetFieldID(super_, "nonstaticMethodSubCalled")) {}

  void Test() {
    TestStaticCallNonvirtualMethod();
    TestNewObject();
    TestnonstaticCallNonvirtualMethod();
  }

  JNIEnv* const env_;

  bool const check_jni_ri_;
  bool const check_jni_android_;

  jclass const super_;
  jclass const sub_;

  jmethodID const super_constructor_;
  jmethodID const super_static_;
  jmethodID const super_nonstatic_;
  jmethodID const sub_constructor_;
  jmethodID const sub_static_;
  jmethodID const sub_nonstatic_;

  jfieldID const super_field_;
  jfieldID const sub_field_;

 private:
  jclass GetClass(const char* class_name) {
    jclass c = env_->FindClass(class_name);
    if (env_->ExceptionCheck()) {
      env_->ExceptionDescribe();
      env_->FatalError(__FUNCTION__);
    }
    CHECK(!env_->ExceptionCheck());
    CHECK(c != nullptr);
    return c;
  }

  jmethodID GetMethodID(jclass c, bool nonstatic, const char* method_name) {
    jmethodID m = ((nonstatic) ?
                   env_->GetMethodID(c, method_name, "()V") :
                   env_->GetStaticMethodID(c, method_name, "()V"));
    if (env_->ExceptionCheck()) {
      env_->ExceptionDescribe();
      env_->FatalError(__FUNCTION__);
    }
    CHECK(m != nullptr);
    return m;
  }

  jobject CallConstructor(jclass c, jmethodID m) {
    jobject o = env_->NewObject(c, m);
    if (env_->ExceptionCheck()) {
      env_->ExceptionDescribe();
      env_->FatalError(__FUNCTION__);
    }
    CHECK(o != nullptr);
    return o;
  }

  void CallMethod(jobject o, jclass c, jmethodID m, bool nonstatic, const char* test_case) {
    printf("RUNNING %s\n", test_case);
    env_->CallNonvirtualVoidMethod(o, c, m);
    bool exception_check = env_->ExceptionCheck();
    if (c == nullptr || !nonstatic) {
      if (!exception_check) {
        printf("FAILED %s due to missing exception\n", test_case);
        env_->FatalError("Expected NullPointerException with null jclass");
      }
      env_->ExceptionClear();
    } else if (exception_check) {
      printf("FAILED %s due to pending exception\n", test_case);
      env_->ExceptionDescribe();
      env_->FatalError(test_case);
    }
    printf("PASSED %s\n", test_case);
  }

  jfieldID GetFieldID(jclass c, const char* field_name) {
    jfieldID m = env_->GetFieldID(c, field_name, "Z");
    if (env_->ExceptionCheck()) {
      env_->ExceptionDescribe();
      env_->FatalError(__FUNCTION__);
    }
    CHECK(m != nullptr);
    return m;
  }

  jboolean GetBooleanField(jobject o, jfieldID f) {
    jboolean b = env_->GetBooleanField(o, f);
    if (env_->ExceptionCheck()) {
      env_->ExceptionDescribe();
      env_->FatalError(__FUNCTION__);
    }
    return b;
  }

  void TestStaticCallNonvirtualMethod() {
    if (!check_jni_ri_&& !check_jni_android_) {
      CallMethod(nullptr, nullptr, super_static_, false"null object, null class, super static");
    }
    if (!check_jni_android_) {
      CallMethod(nullptr, super_, super_static_, false"null object, super class, super static");
    }
    if (!check_jni_android_) {
      CallMethod(nullptr, sub_, super_static_, false"null object, sub class, super static");
    }

    if (!check_jni_ri_ && !check_jni_android_) {
      CallMethod(nullptr, nullptr, sub_static_, false"null object, null class, sub static");
    }
    if (!check_jni_android_) {
      CallMethod(nullptr, sub_, sub_static_, false"null object, super class, sub static");
    }
    if (!check_jni_android_) {
      CallMethod(nullptr, super_, sub_static_, false"null object, super class, sub static");
    }
  }

  void TestNewObject() {
    jobject super_super = CallConstructor(super_, super_constructor_);
    jobject super_sub = CallConstructor(super_, sub_constructor_);
    jobject sub_super = CallConstructor(sub_, super_constructor_);
    jobject sub_sub = CallConstructor(sub_, sub_constructor_);

    CHECK(env_->IsInstanceOf(super_super, super_));
    CHECK(!env_->IsInstanceOf(super_super, sub_));

    // Note that even though we called (and ran) the subclass
    // constructor, we are not the subclass.
    CHECK(env_->IsInstanceOf(super_sub, super_));
    CHECK(!env_->IsInstanceOf(super_sub, sub_));

    // Note that even though we called the superclass constructor, we
    // are still the subclass.
    CHECK(env_->IsInstanceOf(sub_super, super_));
    CHECK(env_->IsInstanceOf(sub_super, sub_));

    CHECK(env_->IsInstanceOf(sub_sub, super_));
    CHECK(env_->IsInstanceOf(sub_sub, sub_));
  }

  void TestnonstaticCallNonvirtualMethod(bool super_object, bool super_class, bool super_method, const char* test_case) {
    if (check_jni_android_) {
      if (super_object && !super_method) {
        return;  // We don't allow a call with sub class method on the super class instance.
      }
      if (super_class && !super_method) {
        return;  // We don't allow a call with the sub class method with the super class argument.
      }
    }
    jobject o = ((super_object) ?
                 CallConstructor(super_, super_constructor_) :
                 CallConstructor(sub_, sub_constructor_));
    jclass c = (super_class) ? super_ : sub_;
    jmethodID m = (super_method) ? super_nonstatic_ : sub_nonstatic_;
    CallMethod(o, c, m, true, test_case);
    jboolean super_field = GetBooleanField(o, super_field_);
    jboolean sub_field = GetBooleanField(o, sub_field_);
    CHECK_EQ(super_field, super_method);
    CHECK_NE(sub_field, super_method);
  }

  void TestnonstaticCallNonvirtualMethod() {
    TestnonstaticCallNonvirtualMethod(truetruetrue"super object, super class, super nonstatic");
    TestnonstaticCallNonvirtualMethod(truefalsetrue"super object, sub class, super nonstatic");
    TestnonstaticCallNonvirtualMethod(truefalsefalse"super object, sub class, sub nonstatic");
    TestnonstaticCallNonvirtualMethod(truetruefalse"super object, super class, sub nonstatic");

    TestnonstaticCallNonvirtualMethod(falsetruetrue"sub object, super class, super nonstatic");
    TestnonstaticCallNonvirtualMethod(falsefalsetrue"sub object, sub class, super nonstatic");
    TestnonstaticCallNonvirtualMethod(falsefalsefalse"sub object, sub class, sub nonstatic");
    TestnonstaticCallNonvirtualMethod(falsetruefalse"sub object, super class, sub nonstatic");
  }
};

extern "C" void JNICALL Java_Main_testCallNonvirtual(JNIEnv* env, jclass) {
  JniCallNonvirtualVoidMethodTest(env).Test();
}

extern "C" JNIEXPORT void JNICALL Java_Main_testNewStringObject(JNIEnv* env, jclass) {
  jclass c = env->FindClass("java/lang/String");
  CHECK(c != nullptr);

  jmethodID mid1 = env->GetMethodID(c, "<init>""()V");
  CHECK(mid1 != nullptr);
  CHECK(!env->ExceptionCheck());
  jmethodID mid2 = env->GetMethodID(c, "<init>""([B)V");
  CHECK(mid2 != nullptr);
  CHECK(!env->ExceptionCheck());
  jmethodID mid3 = env->GetMethodID(c, "<init>""([C)V");
  CHECK(mid3 != nullptr);
  CHECK(!env->ExceptionCheck());
  jmethodID mid4 = env->GetMethodID(c, "<init>""(Ljava/lang/String;)V");
  CHECK(mid4 != nullptr);
  CHECK(!env->ExceptionCheck());

  const char* test_array = "Test";
  int byte_array_length = strlen(test_array);
  jbyteArray byte_array = env->NewByteArray(byte_array_length);
  env->SetByteArrayRegion(byte_array, 0, byte_array_length, reinterpret_cast<const jbyte*>(test_array));

  // Test NewObject
  jstring s = reinterpret_cast<jstring>(env->NewObject(c, mid2, byte_array));
  CHECK(s != nullptr);
  CHECK_EQ(env->GetStringLength(s), byte_array_length);
  CHECK_EQ(env->GetStringUTFLength(s), byte_array_length);
  const char* chars = env->GetStringUTFChars(s, nullptr);
  CHECK_EQ(strcmp(test_array, chars), 0);
  env->ReleaseStringUTFChars(s, chars);

  // Test AllocObject and Call(Nonvirtual)VoidMethod
  jstring s1 = reinterpret_cast<jstring>(env->AllocObject(c));
  CHECK(s1 != nullptr);
  jstring s2 = reinterpret_cast<jstring>(env->AllocObject(c));
  CHECK(s2 != nullptr);
  jstring s3 = reinterpret_cast<jstring>(env->AllocObject(c));
  CHECK(s3 != nullptr);
  jstring s4 = reinterpret_cast<jstring>(env->AllocObject(c));
  CHECK(s4 != nullptr);

  jcharArray char_array = env->NewCharArray(5);
  jstring string_arg = env->NewStringUTF("helloworld");

  // With Var Args
  env->CallVoidMethod(s1, mid1);
  env->CallNonvirtualVoidMethod(s2, c, mid2, byte_array);

  // With JValues
  jvalue args3[1];
  args3[0].l = char_array;
  jvalue args4[1];
  args4[0].l = string_arg;
  env->CallVoidMethodA(s3, mid3, args3);
  env->CallNonvirtualVoidMethodA(s4, c, mid4, args4);

  // Test with global and weak global references
  jstring s5 = reinterpret_cast<jstring>(env->AllocObject(c));
  CHECK(s5 != nullptr);
  s5 = reinterpret_cast<jstring>(env->NewGlobalRef(s5));
  jstring s6 = reinterpret_cast<jstring>(env->AllocObject(c));
  CHECK(s6 != nullptr);
  s6 = reinterpret_cast<jstring>(env->NewWeakGlobalRef(s6));

  env->CallVoidMethod(s5, mid1);
  env->CallNonvirtualVoidMethod(s6, c, mid2, byte_array);
  CHECK_EQ(env->GetStringLength(s5), 0);
  CHECK_EQ(env->GetStringLength(s6), byte_array_length);
  const char* chars6 = env->GetStringUTFChars(s6, nullptr);
  CHECK_EQ(strcmp(test_array, chars6), 0);
  env->ReleaseStringUTFChars(s6, chars6);
}

extern "C" JNIEXPORT jlong JNICALL Java_Main_testGetMethodID(JNIEnv* env, jclass, jclass c) {
  return reinterpret_cast<jlong>(env->GetMethodID(c, "a""()V"));
}

extern "C" JNIEXPORT void JNICALL Java_Main_enterJniCriticalSection(JNIEnv* env, jclass,
                                                                    jint arraySize,
                                                                    jbyteArray array0,
                                                                    jbyteArray array1) {
  for (int i = 0; i < 50000; ++i) {
    char* data0 = reinterpret_cast<char*>(env->GetPrimitiveArrayCritical(array0, nullptr));
    char* data1 = reinterpret_cast<char*>(env->GetPrimitiveArrayCritical(array1, nullptr));
    bool up = i % 2 == 0;
    for (int j = 0; j < arraySize; ++j) {
      if (up) {
        data1[j] = data0[j] + 1;
      } else {
        data0[j] = data1[j] + 1;
      }
    }
    env->ReleasePrimitiveArrayCritical(array1, data1, 0);
    env->ReleasePrimitiveArrayCritical(array0, data0, 0);
  }
}

class JniCallDefaultMethodsTest {
 public:
  explicit JniCallDefaultMethodsTest(JNIEnv* env)
      : env_(env), concrete_class_(env_->FindClass("ConcreteClass")) {
    CHECK(!env_->ExceptionCheck());
    CHECK(concrete_class_ != nullptr);
  }

  void Test() {
    TestCalls("ConcreteClass", { "JniCallNonOverridenDefaultMethod",
                                 "JniCallOverridenDefaultMethod",
                                 "JniCallOverridenDefaultMethodWithSuper",
                                 "JniCallOverridenAbstractMethod",
                                 "JniCallConflictDefaultMethod",
                                 "JniCallSoftConflictMethod" });
    TestCalls("DefaultInterface", { "JniCallNonOverridenDefaultMethod",
                                    "JniCallOverridenDefaultMethod",
                                    "JniCallOverridenAbstractMethod",
                                    "JniCallConflictDefaultMethod",
                                    "JniCallSoftConflictMethod" });
    TestCalls("AbstractInterface", { "JniCallSoftConflictMethod" });
    TestCalls("ConflictInterface", { "JniCallConflictDefaultMethod" });
  }

 private:
  void TestCalls(const char* declaring_class, const std::vector<const char*>& methods) {
    jmethodID new_method = env_->GetMethodID(concrete_class_, "<init>""()V");
    jobject obj = env_->NewObject(concrete_class_, new_method);
    CHECK(!env_->ExceptionCheck());
    CHECK(obj != nullptr);
    jclass decl_class = env_->FindClass(declaring_class);
    CHECK(!env_->ExceptionCheck());
    CHECK(decl_class != nullptr);
    for (const char* method : methods) {
      jmethodID method_id = env_->GetMethodID(decl_class, method, "()V");
      CHECK(!env_->ExceptionCheck());
      printf("Calling method %s->%s on object of type ConcreteClass\n", declaring_class, method);
      env_->CallVoidMethod(obj, method_id);
      if (env_->ExceptionCheck()) {
        jthrowable thrown = env_->ExceptionOccurred();
        env_->ExceptionClear();
        jmethodID to_string = env_->GetMethodID(
            env_->FindClass("java/lang/Object"), "toString""()Ljava/lang/String;");
        jstring exception_string = (jstring) env_->CallObjectMethod(thrown, to_string);
        CHECK(!env_->ExceptionCheck());
        const char* exception_string_utf8 = env_->GetStringUTFChars(exception_string, nullptr);
        CHECK(!env_->ExceptionCheck());
        CHECK(exception_string_utf8 != nullptr);
        printf("EXCEPTION OCCURED: %s\n", exception_string_utf8);
        env_->ReleaseStringUTFChars(exception_string, exception_string_utf8);
      }
    }
  }

  JNIEnv* env_;
  jclass concrete_class_;
};

extern "C" JNIEXPORT void JNICALL Java_Main_testCallDefaultMethods(JNIEnv* env) {
  JniCallDefaultMethodsTest(env).Test();
}

static void InvokeSpecificMethod(JNIEnv* env, jobject obj, const char* method) {
  jclass lambda_class = env->FindClass("LambdaInterface");
  CHECK(!env->ExceptionCheck());
  CHECK(lambda_class != nullptr);
  jmethodID method_id = env->GetMethodID(lambda_class, method, "()V");
  CHECK(!env->ExceptionCheck());
  env->CallVoidMethod(obj, method_id);
  CHECK(!env->ExceptionCheck());
}

extern "C" JNIEXPORT void JNICALL Java_Main_testInvokeLambdaDefaultMethod(
    JNIEnv* e, jclass, jobject l) {
  InvokeSpecificMethod(e, l, "sayHiTwice");
}

extern "C" JNIEXPORT void JNICALL Java_Main_testInvokeLambdaMethod(JNIEnv* e, jclass, jobject l) {
  InvokeSpecificMethod(e, l, "sayHi");
}

// Register on-demand because many tests share this JNI library and
// we can't unconditionally register them.
extern "C" JNIEXPORT jboolean JNICALL Java_Main_registerNativesJniTest(JNIEnv* e, jclass kls) {
  const size_t numMethods = sizeof(sMainMethods)/sizeof(JNINativeMethod);

  if (e->RegisterNatives(kls, sMainMethods, numMethods) < 0) {
      std::cerr << "RegisterNatives failed for 'Main'" << std::endl;
      return JNI_FALSE;
  }

  return JNI_TRUE;
}

// Annotated with @FastNative in Java code. Doesn't need to be explicitly registered with "!".
// NOTE: Has to be registered explicitly to avoid mutator lock check failures.
static jint Java_Main_intFastNativeMethod(JNIEnv*, jclass, jint a, jint b, jint c) {
  return a + b + c;
}

// Annotated with @CriticalNative in Java code. Doesn't need to be explicitly registered with "!".
// NOTE: Has to be registered explicitly to avoid mutator lock check failures.
static jint Java_Main_intCriticalNativeMethod(jint a, jint b, jint c) {
  // Note that unlike a "Fast Native" method this excludes JNIEnv and the jclass parameters.
  return a + b + c;
}

extern "C" JNIEXPORT jobject JNICALL Java_Main_lookupClinit(JNIEnv* env, jclass, jclass kls) {
  jmethodID clinit_id = env->GetStaticMethodID(kls, "<clinit>""()V");

  if (clinit_id != nullptr) {
    jobject obj = env->ToReflectedMethod(kls, clinit_id, /*isStatic*/ true);
    CHECK(obj != nullptr);
    return obj;
  } else {
    return nullptr;
  }
}

extern "C" JNIEXPORT jboolean JNICALL Java_Main_isSlowDebug(JNIEnv*, jclass) {
  // Return whether slow-debug is on. Only relevant for debug builds.
  if (kIsDebugBuild) {
    // Register a fake flag and get the default value it should be initialized with.
    static bool fake_flag = false;
    fake_flag = RegisterRuntimeDebugFlag(&fake_flag);

    return fake_flag ? JNI_TRUE : JNI_FALSE;
  }
  // To pass the Java-side test, just so "on" for release builds.
  return JNI_TRUE;
}

}  // namespace art


Messung V0.5 in Prozent
C=89 H=98 G=93

¤ Dauer der Verarbeitung: 0.15 Sekunden  (vorverarbeitet am  2026-06-29) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Quellcodebibliothek
     Eigene Quellcodes
     Fremde Quellcodes
     Suchen

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik