OpenjdkJvm.cc revision 6fb4c732f3fed182fdd4d9a725a9d039d42dce83
1/* Copyright (C) 2014 The Android Open Source Project 2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 3 * 4 * This file implements interfaces from the file jvm.h. This implementation 5 * is licensed under the same terms as the file jvm.h. The 6 * copyright and license information for the file jvm.h follows. 7 * 8 * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. 9 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 10 * 11 * This code is free software; you can redistribute it and/or modify it 12 * under the terms of the GNU General Public License version 2 only, as 13 * published by the Free Software Foundation. Oracle designates this 14 * particular file as subject to the "Classpath" exception as provided 15 * by Oracle in the LICENSE file that accompanied this code. 16 * 17 * This code is distributed in the hope that it will be useful, but WITHOUT 18 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 19 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 20 * version 2 for more details (a copy is included in the LICENSE file that 21 * accompanied this code). 22 * 23 * You should have received a copy of the GNU General Public License version 24 * 2 along with this work; if not, write to the Free Software Foundation, 25 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 26 * 27 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 28 * or visit www.oracle.com if you need additional information or have any 29 * questions. 30 */ 31 32/* 33 * Services that OpenJDK expects the VM to provide. 34 */ 35#include<stdio.h> 36#include <dlfcn.h> 37#include <limits.h> 38#include <unistd.h> 39 40#include "common_throws.h" 41#include "gc/heap.h" 42#include "thread.h" 43#include "thread_list.h" 44#include "runtime.h" 45#include "handle_scope-inl.h" 46#include "scoped_thread_state_change.h" 47#include "ScopedUtfChars.h" 48#include "mirror/class_loader.h" 49#include "verify_object-inl.h" 50#include "base/logging.h" 51#include "base/macros.h" 52#include "../../libcore/ojluni/src/main/native/jvm.h" // TODO(narayan): fix it 53#include "jni_internal.h" 54#include "mirror/string-inl.h" 55#include "native/scoped_fast_native_object_access.h" 56#include "ScopedLocalRef.h" 57#include <sys/time.h> 58#include <sys/socket.h> 59#include <sys/ioctl.h> 60 61#ifdef __ANDROID__ 62// This function is provided by android linker. 63extern "C" void android_update_LD_LIBRARY_PATH(const char* ld_library_path); 64#endif // __ANDROID__ 65 66#undef LOG_TAG 67#define LOG_TAG "artopenjdk" 68 69using art::WARNING; 70using art::INFO; 71using art::ERROR; 72using art::FATAL; 73 74/* posix open() with extensions; used by e.g. ZipFile */ 75JNIEXPORT jint JVM_Open(const char* fname, jint flags, jint mode) { 76 /* 77 * The call is expected to handle JVM_O_DELETE, which causes the file 78 * to be removed after it is opened. Also, some code seems to 79 * want the special return value JVM_EEXIST if the file open fails 80 * due to O_EXCL. 81 */ 82 int fd = TEMP_FAILURE_RETRY(open(fname, flags & ~JVM_O_DELETE, mode)); 83 if (fd < 0) { 84 int err = errno; 85 if (err == EEXIST) { 86 return JVM_EEXIST; 87 } else { 88 return -1; 89 } 90 } 91 92 if (flags & JVM_O_DELETE) { 93 if (unlink(fname) != 0) { 94 LOG(WARNING) << "Post-open deletion of '" << fname << "' failed: " << strerror(errno); 95 } 96 } 97 98 return fd; 99} 100 101/* posix close() */ 102JNIEXPORT jint JVM_Close(jint fd) { 103 // don't want TEMP_FAILURE_RETRY here -- file is closed even if EINTR 104 return close(fd); 105} 106 107/* posix read() */ 108JNIEXPORT jint JVM_Read(jint fd, char* buf, jint nbytes) { 109 return TEMP_FAILURE_RETRY(read(fd, buf, nbytes)); 110} 111 112/* posix write(); is used to write messages to stderr */ 113JNIEXPORT jint JVM_Write(jint fd, char* buf, jint nbytes) { 114 return TEMP_FAILURE_RETRY(write(fd, buf, nbytes)); 115} 116 117/* posix lseek() */ 118JNIEXPORT jlong JVM_Lseek(jint fd, jlong offset, jint whence) { 119 // NOTE: Using TEMP_FAILURE_RETRY here is busted for LP32 on glibc - the return 120 // value will be coerced into an int32_t. 121 // 122 // lseek64 isn't specified to return EINTR so it shouldn't be necessary 123 // anyway. 124 return lseek64(fd, offset, whence); 125} 126 127/* 128 * "raw monitors" seem to be expected to behave like non-recursive pthread 129 * mutexes. They're used by ZipFile. 130 */ 131JNIEXPORT void* JVM_RawMonitorCreate(void) { 132 pthread_mutex_t* mutex = 133 reinterpret_cast<pthread_mutex_t*>(malloc(sizeof(pthread_mutex_t))); 134 CHECK(mutex != nullptr); 135 CHECK_PTHREAD_CALL(pthread_mutex_init, (mutex, nullptr), "JVM_RawMonitorCreate"); 136 return mutex; 137} 138 139JNIEXPORT void JVM_RawMonitorDestroy(void* mon) { 140 CHECK_PTHREAD_CALL(pthread_mutex_destroy, 141 (reinterpret_cast<pthread_mutex_t*>(mon)), 142 "JVM_RawMonitorDestroy"); 143 free(mon); 144} 145 146JNIEXPORT jint JVM_RawMonitorEnter(void* mon) { 147 return pthread_mutex_lock(reinterpret_cast<pthread_mutex_t*>(mon)); 148} 149 150JNIEXPORT void JVM_RawMonitorExit(void* mon) { 151 CHECK_PTHREAD_CALL(pthread_mutex_unlock, 152 (reinterpret_cast<pthread_mutex_t*>(mon)), 153 "JVM_RawMonitorExit"); 154} 155 156JNIEXPORT char* JVM_NativePath(char* path) { 157 return path; 158} 159 160JNIEXPORT jint JVM_GetLastErrorString(char* buf, int len) { 161#if defined(__GLIBC__) || defined(__BIONIC__) 162 if (len == 0) { 163 return 0; 164 } 165 166 const int err = errno; 167 char* result = strerror_r(err, buf, len); 168 if (result != buf) { 169 strncpy(buf, result, len); 170 buf[len - 1] = '\0'; 171 } 172 173 return strlen(buf); 174#else 175 UNUSED(buf); 176 UNUSED(len); 177 return -1; 178#endif 179} 180 181JNIEXPORT int jio_fprintf(FILE* fp, const char* fmt, ...) { 182 va_list args; 183 184 va_start(args, fmt); 185 int len = jio_vfprintf(fp, fmt, args); 186 va_end(args); 187 188 return len; 189} 190 191JNIEXPORT int jio_vfprintf(FILE* fp, const char* fmt, va_list args) { 192 assert(fp != NULL); 193 return vfprintf(fp, fmt, args); 194} 195 196/* posix fsync() */ 197JNIEXPORT jint JVM_Sync(jint fd) { 198 return TEMP_FAILURE_RETRY(fsync(fd)); 199} 200 201JNIEXPORT void* JVM_FindLibraryEntry(void* handle, const char* name) { 202 return dlsym(handle, name); 203} 204 205JNIEXPORT jlong JVM_CurrentTimeMillis(JNIEnv* env ATTRIBUTE_UNUSED, 206 jclass clazz ATTRIBUTE_UNUSED) { 207 struct timeval tv; 208 gettimeofday(&tv, (struct timezone *) NULL); 209 jlong when = tv.tv_sec * 1000LL + tv.tv_usec / 1000; 210 return when; 211} 212 213JNIEXPORT jint JVM_Socket(jint domain, jint type, jint protocol) { 214 return TEMP_FAILURE_RETRY(socket(domain, type, protocol)); 215} 216 217JNIEXPORT jint JVM_InitializeSocketLibrary() { 218 return 0; 219} 220 221int jio_vsnprintf(char *str, size_t count, const char *fmt, va_list args) { 222 if ((intptr_t)count <= 0) return -1; 223 return vsnprintf(str, count, fmt, args); 224} 225 226int jio_snprintf(char *str, size_t count, const char *fmt, ...) { 227 va_list args; 228 int len; 229 va_start(args, fmt); 230 len = jio_vsnprintf(str, count, fmt, args); 231 va_end(args); 232 return len; 233} 234 235JNIEXPORT jint JVM_SetSockOpt(jint fd, int level, int optname, 236 const char* optval, int optlen) { 237 return TEMP_FAILURE_RETRY(setsockopt(fd, level, optname, optval, optlen)); 238} 239 240JNIEXPORT jint JVM_SocketShutdown(jint fd, jint howto) { 241 return TEMP_FAILURE_RETRY(shutdown(fd, howto)); 242} 243 244JNIEXPORT jint JVM_GetSockOpt(jint fd, int level, int optname, char* optval, 245 int* optlen) { 246 socklen_t len = *optlen; 247 int cc = TEMP_FAILURE_RETRY(getsockopt(fd, level, optname, optval, &len)); 248 *optlen = len; 249 return cc; 250} 251 252JNIEXPORT jint JVM_GetSockName(jint fd, struct sockaddr* addr, int* addrlen) { 253 socklen_t len = *addrlen; 254 int cc = TEMP_FAILURE_RETRY(getsockname(fd, addr, &len)); 255 *addrlen = len; 256 return cc; 257} 258 259JNIEXPORT jint JVM_SocketAvailable(jint fd, jint* result) { 260 if (TEMP_FAILURE_RETRY(ioctl(fd, FIONREAD, result)) < 0) { 261 return JNI_FALSE; 262 } 263 264 return JNI_TRUE; 265} 266 267JNIEXPORT jint JVM_Send(jint fd, char* buf, jint nBytes, jint flags) { 268 return TEMP_FAILURE_RETRY(send(fd, buf, nBytes, flags)); 269} 270 271JNIEXPORT jint JVM_SocketClose(jint fd) { 272 // Don't want TEMP_FAILURE_RETRY here -- file is closed even if EINTR. 273 return close(fd); 274} 275 276JNIEXPORT jint JVM_Listen(jint fd, jint count) { 277 return TEMP_FAILURE_RETRY(listen(fd, count)); 278} 279 280JNIEXPORT jint JVM_Connect(jint fd, struct sockaddr* addr, jint addrlen) { 281 return TEMP_FAILURE_RETRY(connect(fd, addr, addrlen)); 282} 283 284JNIEXPORT int JVM_GetHostName(char* name, int namelen) { 285 return TEMP_FAILURE_RETRY(gethostname(name, namelen)); 286} 287 288JNIEXPORT jstring JVM_InternString(JNIEnv* env, jstring jstr) { 289 art::ScopedFastNativeObjectAccess soa(env); 290 art::mirror::String* s = soa.Decode<art::mirror::String*>(jstr); 291 art::mirror::String* result = s->Intern(); 292 return soa.AddLocalReference<jstring>(result); 293} 294 295JNIEXPORT jlong JVM_FreeMemory(void) { 296 return art::Runtime::Current()->GetHeap()->GetFreeMemory(); 297} 298 299JNIEXPORT jlong JVM_TotalMemory(void) { 300 return art::Runtime::Current()->GetHeap()->GetTotalMemory(); 301} 302 303JNIEXPORT jlong JVM_MaxMemory(void) { 304 return art::Runtime::Current()->GetHeap()->GetMaxMemory(); 305} 306 307JNIEXPORT void JVM_GC(void) { 308 if (art::Runtime::Current()->IsExplicitGcDisabled()) { 309 LOG(INFO) << "Explicit GC skipped."; 310 return; 311 } 312 art::Runtime::Current()->GetHeap()->CollectGarbage(false); 313} 314 315JNIEXPORT __attribute__((noreturn)) void JVM_Exit(jint status) { 316 LOG(INFO) << "System.exit called, status: " << status; 317 art::Runtime::Current()->CallExitHook(status); 318 exit(status); 319} 320 321static void SetLdLibraryPath(JNIEnv* env, jstring javaLdLibraryPath) { 322#ifdef __ANDROID__ 323 if (javaLdLibraryPath != nullptr) { 324 ScopedUtfChars ldLibraryPath(env, javaLdLibraryPath); 325 if (ldLibraryPath.c_str() != nullptr) { 326 android_update_LD_LIBRARY_PATH(ldLibraryPath.c_str()); 327 } 328 } 329 330#else 331 LOG(WARNING) << "android_update_LD_LIBRARY_PATH not found; .so dependencies will not work!"; 332 UNUSED(javaLdLibraryPath, env); 333#endif 334} 335 336 337JNIEXPORT jstring JVM_NativeLoad(JNIEnv* env, 338 jstring javaFilename, 339 jobject javaLoader, 340 jstring javaLibrarySearchPath) { 341 ScopedUtfChars filename(env, javaFilename); 342 if (filename.c_str() == NULL) { 343 return NULL; 344 } 345 346 int32_t target_sdk_version = art::Runtime::Current()->GetTargetSdkVersion(); 347 348 // Starting with N nativeLoad uses classloader local 349 // linker namespace instead of global LD_LIBRARY_PATH 350 // (23 is Marshmallow). This call is here to preserve 351 // backwards compatibility for the apps targeting sdk 352 // version <= 23 353 if (target_sdk_version == 0) { 354 SetLdLibraryPath(env, javaLibrarySearchPath); 355 } 356 357 std::string error_msg; 358 { 359 art::JavaVMExt* vm = art::Runtime::Current()->GetJavaVM(); 360 bool success = vm->LoadNativeLibrary(env, 361 filename.c_str(), 362 javaLoader, 363 javaLibrarySearchPath, 364 &error_msg); 365 if (success) { 366 return nullptr; 367 } 368 } 369 370 // Don't let a pending exception from JNI_OnLoad cause a CheckJNI issue with NewStringUTF. 371 env->ExceptionClear(); 372 return env->NewStringUTF(error_msg.c_str()); 373} 374 375JNIEXPORT void JVM_StartThread(JNIEnv* env, jobject jthread, jlong stack_size, jboolean daemon) { 376 art::Thread::CreateNativeThread(env, jthread, stack_size, daemon == JNI_TRUE); 377} 378 379JNIEXPORT void JVM_SetThreadPriority(JNIEnv* env, jobject jthread, jint prio) { 380 art::ScopedObjectAccess soa(env); 381 art::MutexLock mu(soa.Self(), *art::Locks::thread_list_lock_); 382 art::Thread* thread = art::Thread::FromManagedThread(soa, jthread); 383 if (thread != NULL) { 384 thread->SetNativePriority(prio); 385 } 386} 387 388JNIEXPORT void JVM_Yield(JNIEnv* env ATTRIBUTE_UNUSED, jclass threadClass ATTRIBUTE_UNUSED) { 389 sched_yield(); 390} 391 392JNIEXPORT void JVM_Sleep(JNIEnv* env, jclass threadClass ATTRIBUTE_UNUSED, 393 jobject java_lock, jlong millis) { 394 art::ScopedFastNativeObjectAccess soa(env); 395 art::mirror::Object* lock = soa.Decode<art::mirror::Object*>(java_lock); 396 art::Monitor::Wait(art::Thread::Current(), lock, millis, 0, true, art::kSleeping); 397} 398 399JNIEXPORT jobject JVM_CurrentThread(JNIEnv* env, jclass unused ATTRIBUTE_UNUSED) { 400 art::ScopedFastNativeObjectAccess soa(env); 401 return soa.AddLocalReference<jobject>(soa.Self()->GetPeer()); 402} 403 404JNIEXPORT void JVM_Interrupt(JNIEnv* env, jobject jthread) { 405 art::ScopedFastNativeObjectAccess soa(env); 406 art::MutexLock mu(soa.Self(), *art::Locks::thread_list_lock_); 407 art::Thread* thread = art::Thread::FromManagedThread(soa, jthread); 408 if (thread != nullptr) { 409 thread->Interrupt(soa.Self()); 410 } 411} 412 413JNIEXPORT jboolean JVM_IsInterrupted(JNIEnv* env, jobject jthread, jboolean clearInterrupted) { 414 if (clearInterrupted) { 415 return static_cast<art::JNIEnvExt*>(env)->self->Interrupted() ? JNI_TRUE : JNI_FALSE; 416 } else { 417 art::ScopedFastNativeObjectAccess soa(env); 418 art::MutexLock mu(soa.Self(), *art::Locks::thread_list_lock_); 419 art::Thread* thread = art::Thread::FromManagedThread(soa, jthread); 420 return (thread != nullptr) ? thread->IsInterrupted() : JNI_FALSE; 421 } 422} 423 424JNIEXPORT jboolean JVM_HoldsLock(JNIEnv* env, jclass unused ATTRIBUTE_UNUSED, jobject jobj) { 425 art::ScopedObjectAccess soa(env); 426 art::mirror::Object* object = soa.Decode<art::mirror::Object*>(jobj); 427 if (object == NULL) { 428 art::ThrowNullPointerException("object == null"); 429 return JNI_FALSE; 430 } 431 return soa.Self()->HoldsLock(object); 432} 433 434JNIEXPORT void JVM_SetNativeThreadName(JNIEnv* env, jobject jthread, jstring java_name) { 435 ScopedUtfChars name(env, java_name); 436 { 437 art::ScopedObjectAccess soa(env); 438 if (soa.Decode<art::mirror::Object*>(jthread) == soa.Self()->GetPeer()) { 439 soa.Self()->SetThreadName(name.c_str()); 440 return; 441 } 442 } 443 // Suspend thread to avoid it from killing itself while we set its name. We don't just hold the 444 // thread list lock to avoid this, as setting the thread name causes mutator to lock/unlock 445 // in the DDMS send code. 446 art::ThreadList* thread_list = art::Runtime::Current()->GetThreadList(); 447 bool timed_out; 448 // Take suspend thread lock to avoid races with threads trying to suspend this one. 449 art::Thread* thread; 450 { 451 thread = thread_list->SuspendThreadByPeer(jthread, true, false, &timed_out); 452 } 453 if (thread != NULL) { 454 { 455 art::ScopedObjectAccess soa(env); 456 thread->SetThreadName(name.c_str()); 457 } 458 thread_list->Resume(thread, false); 459 } else if (timed_out) { 460 LOG(ERROR) << "Trying to set thread name to '" << name.c_str() << "' failed as the thread " 461 "failed to suspend within a generous timeout."; 462 } 463} 464 465JNIEXPORT jint JVM_IHashCode(JNIEnv* env ATTRIBUTE_UNUSED, 466 jobject javaObject ATTRIBUTE_UNUSED) { 467 UNIMPLEMENTED(FATAL) << "JVM_IHashCode is not implemented"; 468 return 0; 469} 470 471JNIEXPORT jlong JVM_NanoTime(JNIEnv* env ATTRIBUTE_UNUSED, jclass unused ATTRIBUTE_UNUSED) { 472 UNIMPLEMENTED(FATAL) << "JVM_NanoTime is not implemented"; 473 return 0L; 474} 475 476JNIEXPORT void JVM_ArrayCopy(JNIEnv* /* env */, jclass /* unused */, jobject /* javaSrc */, 477 jint /* srcPos */, jobject /* javaDst */, jint /* dstPos */, 478 jint /* length */) { 479 UNIMPLEMENTED(FATAL) << "JVM_ArrayCopy is not implemented"; 480} 481 482JNIEXPORT jint JVM_FindSignal(const char* name ATTRIBUTE_UNUSED) { 483 LOG(FATAL) << "JVM_FindSignal is not implemented"; 484 return 0; 485} 486 487JNIEXPORT void* JVM_RegisterSignal(jint signum ATTRIBUTE_UNUSED, void* handler ATTRIBUTE_UNUSED) { 488 LOG(FATAL) << "JVM_RegisterSignal is not implemented"; 489 return nullptr; 490} 491 492JNIEXPORT jboolean JVM_RaiseSignal(jint signum ATTRIBUTE_UNUSED) { 493 LOG(FATAL) << "JVM_RaiseSignal is not implemented"; 494 return JNI_FALSE; 495} 496 497JNIEXPORT __attribute__((noreturn)) void JVM_Halt(jint code) { 498 exit(code); 499} 500 501JNIEXPORT jboolean JVM_IsNaN(jdouble d) { 502 return isnan(d); 503} 504