Eine aufbereitete Darstellung der Quelle

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

Benutzer

Quelle  classes.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 <stdio.h>

#include <condition_variable>
#include <mutex>
#include <vector>

#include "android-base/macros.h"
#include "android-base/stringprintf.h"

#include "jni.h"
#include "jvmti.h"

// Test infrastructure
#include "jni_helper.h"
#include "jvmti_helper.h"
#include "scoped_local_ref.h"
#include "scoped_utf_chars.h"
#include "test_env.h"

namespace art {
namespace Test912Classes {

extern "C" JNIEXPORT jboolean JNICALL Java_art_Test912_isModifiableClass(
    JNIEnv* env, [[maybe_unused]] jclass Main_klass, jclass klass) {
  jboolean res = JNI_FALSE;
  jvmtiError result = jvmti_env->IsModifiableClass(klass, &res);
  JvmtiErrorToException(env, jvmti_env, result);
  return res;
}

extern "C" JNIEXPORT jobjectArray JNICALL Java_art_Test912_getClassSignature(
    JNIEnv* env, [[maybe_unused]] jclass Main_klass, jclass klass) {
  char* sig;
  char* gen;
  jvmtiError result = jvmti_env->GetClassSignature(klass, &sig, &gen);
  if (JvmtiErrorToException(env, jvmti_env, result)) {
    return nullptr;
  }

  auto callback = [&](jint i) {
    if (i == 0) {
      return sig == nullptr ? nullptr : env->NewStringUTF(sig);
    } else {
      return gen == nullptr ? nullptr : env->NewStringUTF(gen);
    }
  };
  jobjectArray ret = CreateObjectArray(env, 2"java/lang/String", callback);

  // Need to deallocate the strings.
  if (sig != nullptr) {
    jvmti_env->Deallocate(reinterpret_cast<unsigned char*>(sig));
  }
  if (gen != nullptr) {
    jvmti_env->Deallocate(reinterpret_cast<unsigned char*>(gen));
  }

  return ret;
}

extern "C" JNIEXPORT jboolean JNICALL Java_art_Test912_isInterface(
    JNIEnv* env, [[maybe_unused]] jclass Main_klass, jclass klass) {
  jboolean is_interface = JNI_FALSE;
  jvmtiError result = jvmti_env->IsInterface(klass, &is_interface);
  JvmtiErrorToException(env, jvmti_env, result);
  return is_interface;
}

extern "C" JNIEXPORT jboolean JNICALL Java_art_Test912_isArrayClass(
    JNIEnv* env, [[maybe_unused]] jclass Main_klass, jclass klass) {
  jboolean is_array_class = JNI_FALSE;
  jvmtiError result = jvmti_env->IsArrayClass(klass, &is_array_class);
  JvmtiErrorToException(env, jvmti_env, result);
  return is_array_class;
}

extern "C" JNIEXPORT jint JNICALL Java_art_Test912_getClassModifiers(
    JNIEnv* env, [[maybe_unused]] jclass Main_klass, jclass klass) {
  jint mod;
  jvmtiError result = jvmti_env->GetClassModifiers(klass, &mod);
  JvmtiErrorToException(env, jvmti_env, result);
  return mod;
}

extern "C" JNIEXPORT jobjectArray JNICALL Java_art_Test912_getClassFields(
    JNIEnv* env, [[maybe_unused]] jclass Main_klass, jclass klass) {
  jint count = 0;
  jfieldID* fields = nullptr;
  jvmtiError result = jvmti_env->GetClassFields(klass, &count, &fields);
  if (JvmtiErrorToException(env, jvmti_env, result)) {
    return nullptr;
  }

  auto callback = [&](jint i) {
    jint modifiers;
    // Ignore any errors for simplicity.
    jvmti_env->GetFieldModifiers(klass, fields[i], &modifiers);
    constexpr jint kStatic = 0x8;
    return env->ToReflectedField(klass,
                                 fields[i],
                                 (modifiers & kStatic) != 0 ? JNI_TRUE : JNI_FALSE);
  };
  jobjectArray ret = CreateObjectArray(env, count, "java/lang/Object", callback);
  if (fields != nullptr) {
    jvmti_env->Deallocate(reinterpret_cast<unsigned char*>(fields));
  }
  return ret;
}

extern "C" JNIEXPORT jobjectArray JNICALL Java_art_Test912_getClassMethods(
    JNIEnv* env, [[maybe_unused]] jclass Main_klass, jclass klass) {
  jint count = 0;
  jmethodID* methods = nullptr;
  jvmtiError result = jvmti_env->GetClassMethods(klass, &count, &methods);
  if (JvmtiErrorToException(env, jvmti_env, result)) {
    return nullptr;
  }

  auto callback = [&](jint i) {
    jint modifiers;
    // Ignore any errors for simplicity.
    jvmti_env->GetMethodModifiers(methods[i], &modifiers);
    constexpr jint kStatic = 0x8;
    return env->ToReflectedMethod(klass,
                                  methods[i],
                                  (modifiers & kStatic) != 0 ? JNI_TRUE : JNI_FALSE);
  };
  jobjectArray ret = CreateObjectArray(env, count, "java/lang/Object", callback);
  if (methods != nullptr) {
    jvmti_env->Deallocate(reinterpret_cast<unsigned char*>(methods));
  }
  return ret;
}

extern "C" JNIEXPORT jobjectArray JNICALL Java_art_Test912_getImplementedInterfaces(
    JNIEnv* env, [[maybe_unused]] jclass Main_klass, jclass klass) {
  jint count = 0;
  jclass* classes = nullptr;
  jvmtiError result = jvmti_env->GetImplementedInterfaces(klass, &count, &classes);
  if (JvmtiErrorToException(env, jvmti_env, result)) {
    return nullptr;
  }

  auto callback = [&](jint i) {
    return classes[i];
  };
  jobjectArray ret = CreateObjectArray(env, count, "java/lang/Class", callback);
  if (classes != nullptr) {
    jvmti_env->Deallocate(reinterpret_cast<unsigned char*>(classes));
  }
  return ret;
}

extern "C" JNIEXPORT jint JNICALL Java_art_Test912_getClassStatus(
    JNIEnv* env, [[maybe_unused]] jclass Main_klass , jclass klass) {
  jint status;
  jvmtiError result = jvmti_env->GetClassStatus(klass, &status);
  JvmtiErrorToException(env, jvmti_env, result);
  return status;
}

extern "C" JNIEXPORT jobject JNICALL Java_art_Test912_getClassLoader(
    JNIEnv* env, [[maybe_unused]] jclass Main_klass , jclass klass) {
  jobject classloader;
  jvmtiError result = jvmti_env->GetClassLoader(klass, &classloader);
  JvmtiErrorToException(env, jvmti_env, result);
  return classloader;
}

extern "C" JNIEXPORT jobjectArray JNICALL Java_art_Test912_getClassLoaderClasses(
    JNIEnv* env, [[maybe_unused]] jclass Main_klass , jobject jclassloader) {
  jint count = 0;
  jclass* classes = nullptr;
  jvmtiError result = jvmti_env->GetClassLoaderClasses(jclassloader, &count, &classes);
  if (JvmtiErrorToException(env, jvmti_env, result)) {
    return nullptr;
  }

  auto callback = [&](jint i) {
    return classes[i];
  };
  jobjectArray ret = CreateObjectArray(env, count, "java/lang/Class", callback);
  if (classes != nullptr) {
    jvmti_env->Deallocate(reinterpret_cast<unsigned char*>(classes));
  }
  return ret;
}

extern "C" JNIEXPORT jintArray JNICALL Java_art_Test912_getClassVersion(
    JNIEnv* env, [[maybe_unused]] jclass Main_klass , jclass klass) {
  jint major, minor;
  jvmtiError result = jvmti_env->GetClassVersionNumbers(klass, &minor, &major);
  if (JvmtiErrorToException(env, jvmti_env, result)) {
    return nullptr;
  }

  jintArray int_array = env->NewIntArray(2);
  if (int_array == nullptr) {
    return nullptr;
  }
  jint buf[2] = { major, minor };
  env->SetIntArrayRegion(int_array, 02, buf);

  return int_array;
}

static std::string GetClassName(jvmtiEnv* jenv, JNIEnv* jni_env, jclass klass) {
  char* name;
  jvmtiError result = jenv->GetClassSignature(klass, &name, nullptr);
  if (result != JVMTI_ERROR_NONE) {
    if (jni_env != nullptr) {
      JvmtiErrorToException(jni_env, jenv, result);
    } else {
      printf("Failed to get class signature.\n");
    }
    return "";
  }

  std::string tmp(name);
  jenv->Deallocate(reinterpret_cast<unsigned char*>(name));

  return tmp;
}

static void EnableEvents(JNIEnv* env,
                         jboolean enable,
                         decltype(jvmtiEventCallbacks().ClassLoad) class_load,
                         decltype(jvmtiEventCallbacks().ClassPrepare) class_prepare) {
  if (enable == JNI_FALSE) {
    jvmtiError ret = jvmti_env->SetEventNotificationMode(JVMTI_DISABLE,
                                                         JVMTI_EVENT_CLASS_LOAD,
                                                         nullptr);
    if (JvmtiErrorToException(env, jvmti_env, ret)) {
      return;
    }
    ret = jvmti_env->SetEventNotificationMode(JVMTI_DISABLE,
                                              JVMTI_EVENT_CLASS_PREPARE,
                                              nullptr);
    JvmtiErrorToException(env, jvmti_env, ret);
    return;
  }

  jvmtiEventCallbacks callbacks;
  memset(&callbacks, 0sizeof(jvmtiEventCallbacks));
  callbacks.ClassLoad = class_load;
  callbacks.ClassPrepare = class_prepare;
  jvmtiError ret = jvmti_env->SetEventCallbacks(&callbacks, sizeof(callbacks));
  if (JvmtiErrorToException(env, jvmti_env, ret)) {
    return;
  }

  ret = jvmti_env->SetEventNotificationMode(JVMTI_ENABLE,
                                            JVMTI_EVENT_CLASS_LOAD,
                                            nullptr);
  if (JvmtiErrorToException(env, jvmti_env, ret)) {
    return;
  }
  ret = jvmti_env->SetEventNotificationMode(JVMTI_ENABLE,
                                            JVMTI_EVENT_CLASS_PREPARE,
                                            nullptr);
  JvmtiErrorToException(env, jvmti_env, ret);
}

static std::mutex gEventsMutex;
static std::vector<std::string> gEvents;

extern "C" JNIEXPORT jobjectArray JNICALL Java_art_Test912_getClassLoadMessages(
    JNIEnv* env, [[maybe_unused]] jclass Main_klass) {
  std::lock_guard<std::mutex> guard(gEventsMutex);
  jobjectArray ret = CreateObjectArray(env,
                                       static_cast<jint>(gEvents.size()),
                                       "java/lang/String",
                                       [&](jint i) {
    return env->NewStringUTF(gEvents[i].c_str());
  });
  gEvents.clear();
  return ret;
}

class ClassLoadPreparePrinter {
 public:
  static void JNICALL ClassLoadCallback(jvmtiEnv* jenv,
                                        JNIEnv* jni_env,
                                        jthread thread,
                                        jclass klass) {
    std::string name = GetClassName(jenv, jni_env, klass);
    if (name == "") {
      return;
    }
    std::string thread_name = GetThreadName(jenv, jni_env, thread);
    if (thread_name == "") {
      return;
    }
    if (thread_name_filter_ != "" && thread_name_filter_ != thread_name) {
      return;
    }

    std::lock_guard<std::mutex> guard(gEventsMutex);
    gEvents.push_back(android::base::StringPrintf("Load: %s on %s",
                                                  name.c_str(),
                                                  thread_name.c_str()));
  }

  static void JNICALL ClassPrepareCallback(jvmtiEnv* jenv,
                                           JNIEnv* jni_env,
                                           jthread thread,
                                           jclass klass) {
    std::string name = GetClassName(jenv, jni_env, klass);
    if (name == "") {
      return;
    }
    std::string thread_name = GetThreadName(jenv, jni_env, thread);
    if (thread_name == "") {
      return;
    }
    if (thread_name_filter_ != "" && thread_name_filter_ != thread_name) {
      return;
    }
    std::string cur_thread_name = GetThreadName(jenv, jni_env, nullptr);

    std::lock_guard<std::mutex> guard(gEventsMutex);
    gEvents.push_back(android::base::StringPrintf("Prepare: %s on %s (cur=%s)",
                                                  name.c_str(),
                                                  thread_name.c_str(),
                                                  cur_thread_name.c_str()));
  }

  static std::string GetThreadName(jvmtiEnv* jenv, JNIEnv* jni_env, jthread thread) {
    jvmtiThreadInfo info;
    jvmtiError result = jenv->GetThreadInfo(thread, &info);
    if (result != JVMTI_ERROR_NONE) {
      if (jni_env != nullptr) {
        JvmtiErrorToException(jni_env, jenv, result);
      } else {
        printf("Failed to get thread name.\n");
      }
      return "";
    }

    std::string tmp(info.name);
    jenv->Deallocate(reinterpret_cast<unsigned char*>(info.name));
    jni_env->DeleteLocalRef(info.context_class_loader);
    jni_env->DeleteLocalRef(info.thread_group);

    return tmp;
  }

  static std::string thread_name_filter_;
};
std::string ClassLoadPreparePrinter::thread_name_filter_;  // NOLINT [runtime/string] [4]

extern "C" JNIEXPORT void JNICALL Java_art_Test912_enableClassLoadPreparePrintEvents(
    JNIEnv* env, [[maybe_unused]] jclass Main_klass , jboolean enable, jthread thread) {
  if (thread != nullptr) {
    ClassLoadPreparePrinter::thread_name_filter_ =
        ClassLoadPreparePrinter::GetThreadName(jvmti_env, env, thread);
  } else {
    ClassLoadPreparePrinter::thread_name_filter_ = "";
  }

  EnableEvents(env,
               enable,
               ClassLoadPreparePrinter::ClassLoadCallback,
               ClassLoadPreparePrinter::ClassPrepareCallback);
}

template<typename T>
static jthread RunEventThread(const std::string& name,
                              jvmtiEnv* jvmti,
                              JNIEnv* env,
                              void (*func)(jvmtiEnv*, JNIEnv*, T*),
                              T* data) {
  // Create a Thread object.
  std::string name_str = name;
  name_str += ": JVMTI_THREAD-Test912";
  ScopedLocalRef<jobject> thread_name(env, env->NewStringUTF(name_str.c_str()));
  CHECK(thread_name.get() != nullptr);

  ScopedLocalRef<jclass> thread_klass(env, env->FindClass("java/lang/Thread"));
  CHECK(thread_klass.get() != nullptr);

  ScopedLocalRef<jobject> thread(env, env->AllocObject(thread_klass.get()));
  CHECK(thread.get() != nullptr);

  jmethodID initID = env->GetMethodID(thread_klass.get(), "<init>""(Ljava/lang/String;)V");
  CHECK(initID != nullptr);

  env->CallNonvirtualVoidMethod(thread.get(), thread_klass.get(), initID, thread_name.get());
  CHECK(!env->ExceptionCheck());

  // Run agent thread.
  CheckJvmtiError(jvmti, jvmti->RunAgentThread(thread.get(),
                                               reinterpret_cast<jvmtiStartFunction>(func),
                                               reinterpret_cast<void*>(data),
                                               JVMTI_THREAD_NORM_PRIORITY));
  return thread.release();
}

static void JoinTread(JNIEnv* env, jthread thr) {
  ScopedLocalRef<jclass> thread_klass(env, env->FindClass("java/lang/Thread"));
  CHECK(thread_klass.get() != nullptr);

  jmethodID joinID = env->GetMethodID(thread_klass.get(), "join""()V");
  CHECK(joinID != nullptr);

  env->CallVoidMethod(thr, joinID);
}

class ClassLoadPrepareEquality {
 public:
  static constexpr const char* kClassName = "Lart/Test912$ClassE;";
  static constexpr const char* kStorageFieldName = "STATIC";
  static constexpr const char* kStorageFieldSig = "Ljava/lang/Object;";
  static constexpr const char* kStorageWeakFieldName = "WEAK";
  static constexpr const char* kStorageWeakFieldSig = "Ljava/lang/ref/Reference;";
  static constexpr const char* kWeakClassName = "java/lang/ref/WeakReference";
  static constexpr const char* kWeakInitSig = "(Ljava/lang/Object;)V";
  static constexpr const char* kWeakGetSig = "()Ljava/lang/Object;";

  static void AgentThreadTest([[maybe_unused]] jvmtiEnv* jvmti,
                              JNIEnv* env,
                              jobject* obj_global) {
    jobject target = *obj_global;
    jobject target_local = env->NewLocalRef(target);
    {
      std::unique_lock<std::mutex> lk(mutex_);
      started_ = true;
      cond_started_.notify_all();
      cond_finished_.wait(lk, [] { return finished_; });
      CHECK(finished_);
    }
    CHECK(env->IsSameObject(target, target_local));
  }

  static void JNICALL ClassLoadCallback(jvmtiEnv* jenv,
                                        JNIEnv* jni_env,
                                        [[maybe_unused]] jthread thread,
                                        jclass klass) {
    std::string name = GetClassName(jenv, jni_env, klass);
    if (name == kClassName) {
      found_ = true;
      stored_class_ = jni_env->NewGlobalRef(klass);
      weakly_stored_class_ = jni_env->NewWeakGlobalRef(klass);
      // Check that we update the local refs.
      agent_thread_ = static_cast<jthread>(jni_env->NewGlobalRef(RunEventThread<jobject>(
          "local-ref", jenv, jni_env, &AgentThreadTest, static_cast<jobject*>(&stored_class_))));
      {
        std::unique_lock<std::mutex> lk(mutex_);
        cond_started_.wait(lk, [] { return started_; });
      }
      // Store the value into a field in the heap.
      SetOrCompare(jni_env, klass, true);
    }
  }

  static void JNICALL ClassPrepareCallback(jvmtiEnv* jenv,
                                           JNIEnv* jni_env,
                                           [[maybe_unused]] jthread thread,
                                           jclass klass) {
    std::string name = GetClassName(jenv, jni_env, klass);
    if (name == kClassName) {
      CHECK(stored_class_ != nullptr);
      CHECK(jni_env->IsSameObject(stored_class_, klass));
      CHECK(jni_env->IsSameObject(weakly_stored_class_, klass));
      {
        std::unique_lock<std::mutex> lk(mutex_);
        finished_ = true;
        cond_finished_.notify_all();
      }
      // Look up the value in a field in the heap.
      SetOrCompare(jni_env, klass, false);
      JoinTread(jni_env, agent_thread_);
      compared_ = true;
    }
  }

  static void SetOrCompare(JNIEnv* jni_env, jobject value, bool set) {
    CHECK(storage_class_ != nullptr);

    // Simple direct storage.
    jfieldID field = jni_env->GetStaticFieldID(storage_class_, kStorageFieldName, kStorageFieldSig);
    CHECK(field != nullptr);

    if (set) {
      jni_env->SetStaticObjectField(storage_class_, field, value);
      CHECK(!jni_env->ExceptionCheck());
    } else {
      ScopedLocalRef<jobject> stored(jni_env, jni_env->GetStaticObjectField(storage_class_, field));
      CHECK(jni_env->IsSameObject(value, stored.get()));
    }

    // Storage as a reference.
    ScopedLocalRef<jclass> weak_ref_class(jni_env, jni_env->FindClass(kWeakClassName));
    CHECK(weak_ref_class.get() != nullptr);
    jfieldID weak_field = jni_env->GetStaticFieldID(storage_class_,
                                                    kStorageWeakFieldName,
                                                    kStorageWeakFieldSig);
    CHECK(weak_field != nullptr);
    if (set) {
      // Create a WeakReference.
      jmethodID weak_init = jni_env->GetMethodID(weak_ref_class.get(), "<init>", kWeakInitSig);
      CHECK(weak_init != nullptr);
      ScopedLocalRef<jobject> weak_obj(jni_env, jni_env->NewObject(weak_ref_class.get(),
                                                                   weak_init,
                                                                   value));
      CHECK(weak_obj.get() != nullptr);
      jni_env->SetStaticObjectField(storage_class_, weak_field, weak_obj.get());
      CHECK(!jni_env->ExceptionCheck());
    } else {
      // Check the reference value.
      jmethodID get_referent = jni_env->GetMethodID(weak_ref_class.get(), "get", kWeakGetSig);
      CHECK(get_referent != nullptr);
      ScopedLocalRef<jobject> weak_obj(jni_env, jni_env->GetStaticObjectField(storage_class_,
                                                                              weak_field));
      CHECK(weak_obj.get() != nullptr);
      ScopedLocalRef<jobject> weak_referent(jni_env, jni_env->CallObjectMethod(weak_obj.get(),
                                                                               get_referent));
      CHECK(weak_referent.get() != nullptr);
      CHECK(jni_env->IsSameObject(value, weak_referent.get()));
    }
  }

  static void CheckFound() {
    CHECK(found_);
    CHECK(compared_);
  }

  static void Free(JNIEnv* env) {
    if (stored_class_ != nullptr) {
      env->DeleteGlobalRef(stored_class_);
      DCHECK(weakly_stored_class_ != nullptr);
      env->DeleteWeakGlobalRef(weakly_stored_class_);
      // Do not attempt to delete the local ref. It will be out of date by now.
    }
  }

  static jclass storage_class_;

 private:
  static jobject stored_class_;
  static jweak weakly_stored_class_;
  static jthread agent_thread_;
  static std::mutex mutex_;
  static bool started_;
  static std::condition_variable cond_finished_;
  static bool finished_;
  static std::condition_variable cond_started_;
  static bool found_;
  static bool compared_;
};

jclass ClassLoadPrepareEquality::storage_class_ = nullptr;
jobject ClassLoadPrepareEquality::stored_class_ = nullptr;
jweak ClassLoadPrepareEquality::weakly_stored_class_ = nullptr;
jthread ClassLoadPrepareEquality::agent_thread_ = nullptr;
std::mutex ClassLoadPrepareEquality::mutex_;
bool ClassLoadPrepareEquality::started_ = false;
std::condition_variable ClassLoadPrepareEquality::cond_started_;
bool ClassLoadPrepareEquality::finished_ = false;
std::condition_variable ClassLoadPrepareEquality::cond_finished_;
bool ClassLoadPrepareEquality::found_ = false;
bool ClassLoadPrepareEquality::compared_ = false;

extern "C" JNIEXPORT void JNICALL Java_art_Test912_setEqualityEventStorageClass(
    JNIEnv* env, [[maybe_unused]] jclass Main_klass, jclass klass) {
  ClassLoadPrepareEquality::storage_class_ =
      reinterpret_cast<jclass>(env->NewGlobalRef(klass));
}

extern "C" JNIEXPORT void JNICALL Java_art_Test912_enableClassLoadPrepareEqualityEvents(
    JNIEnv* env, [[maybe_unused]] jclass Main_klass, jboolean b) {
  EnableEvents(env,
               b,
               ClassLoadPrepareEquality::ClassLoadCallback,
               ClassLoadPrepareEquality::ClassPrepareCallback);
  if (b == JNI_FALSE) {
    ClassLoadPrepareEquality::Free(env);
    ClassLoadPrepareEquality::CheckFound();
    env->DeleteGlobalRef(ClassLoadPrepareEquality::storage_class_);
    ClassLoadPrepareEquality::storage_class_ = nullptr;
  }
}

// Global to pass information to the ClassPrepare event.
static jobject gRunnableGlobal = nullptr;
extern "C" JNIEXPORT void JNICALL Java_art_Test912_runRecursiveClassPrepareEvents(
    JNIEnv* env, [[maybe_unused]] jclass klass, jobject runnable) {
  CHECK(gRunnableGlobal == nullptr);
  gRunnableGlobal = env->NewGlobalRef(runnable);
  EnableEvents(
      env,
      true,
      nullptr,
      []([[maybe_unused]] jvmtiEnv* jenv,
         JNIEnv* jni_env,
         [[maybe_unused]] jthread thread,
         [[maybe_unused]] jclass klass) -> void {
        jclass runnable_class = jni_env->FindClass("java/lang/Runnable");
        jni_env->CallVoidMethod(
            gRunnableGlobal, jni_env->GetMethodID(runnable_class, "run""()V"));
      });
  jclass runnable_class = env->FindClass("java/lang/Runnable");
  env->CallVoidMethod(
      runnable, env->GetMethodID(runnable_class, "run""()V"));
  EnableEvents(env, false, nullptr, nullptr);
  env->DeleteGlobalRef(gRunnableGlobal);
  gRunnableGlobal = nullptr;
}

}  // namespace Test912Classes
}  // namespace art

Messung V0.5 in Prozent
C=91 H=97 G=93

¤ Dauer der Verarbeitung: 0.12 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