OpenjdkJvm.cc revision 18d209582e0bb1caed97102a86b416173f5aad42
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::DEBUG; 70using art::WARNING; 71using art::VERBOSE; 72using art::INFO; 73using art::ERROR; 74using art::FATAL; 75 76/* posix open() with extensions; used by e.g. ZipFile */ 77JNIEXPORT jint JVM_Open(const char* fname, jint flags, jint mode) { 78 LOG(DEBUG) << "JVM_Open fname='" << fname << "', flags=" << flags << ", mode=" << mode; 79 80 /* 81 * The call is expected to handle JVM_O_DELETE, which causes the file 82 * to be removed after it is opened. Also, some code seems to 83 * want the special return value JVM_EEXIST if the file open fails 84 * due to O_EXCL. 85 */ 86 int fd = TEMP_FAILURE_RETRY(open(fname, flags & ~JVM_O_DELETE, mode)); 87 if (fd < 0) { 88 int err = errno; 89 LOG(DEBUG) << "open(" << fname << ") failed: " << strerror(errno); 90 if (err == EEXIST) { 91 return JVM_EEXIST; 92 } else { 93 return -1; 94 } 95 } 96 97 if (flags & JVM_O_DELETE) { 98 LOG(DEBUG) << "Deleting '" << fname << "' after open\n"; 99 if (unlink(fname) != 0) { 100 LOG(WARNING) << "Post-open deletion of '" << fname << "' failed: " << strerror(errno); 101 } 102 /* ignore */ 103 } 104 105 LOG(VERBOSE) << "open(" << fname << ") --> " << fd; 106 return fd; 107} 108 109/* posix close() */ 110JNIEXPORT jint JVM_Close(jint fd) { 111 LOG(DEBUG) << "JVM_Close fd=" << fd; 112 // don't want TEMP_FAILURE_RETRY here -- file is closed even if EINTR 113 return close(fd); 114} 115 116/* posix read() */ 117JNIEXPORT jint JVM_Read(jint fd, char* buf, jint nbytes) { 118 LOG(DEBUG) << "JVM_Read fd=" << fd << ", buf='" << buf << "', nbytes=" << nbytes; 119 return TEMP_FAILURE_RETRY(read(fd, buf, nbytes)); 120} 121 122/* posix write(); is used to write messages to stderr */ 123JNIEXPORT jint JVM_Write(jint fd, char* buf, jint nbytes) { 124 LOG(DEBUG) << "JVM_Write fd=" << fd << ", buf='" << buf << "', nbytes=" << nbytes; 125 return TEMP_FAILURE_RETRY(write(fd, buf, nbytes)); 126} 127 128/* posix lseek() */ 129JNIEXPORT jlong JVM_Lseek(jint fd, jlong offset, jint whence) { 130 LOG(DEBUG) << "JVM_Lseek fd=" << fd << ", offset=" << offset << ", whence=" << whence; 131 return TEMP_FAILURE_RETRY(lseek(fd, offset, whence)); 132} 133 134/* 135 * "raw monitors" seem to be expected to behave like non-recursive pthread 136 * mutexes. They're used by ZipFile. 137 */ 138JNIEXPORT void* JVM_RawMonitorCreate(void) { 139 LOG(DEBUG) << "JVM_RawMonitorCreate"; 140 pthread_mutex_t* newMutex = 141 reinterpret_cast<pthread_mutex_t*>(malloc(sizeof(pthread_mutex_t))); 142 pthread_mutex_init(newMutex, NULL); 143 return newMutex; 144} 145 146JNIEXPORT void JVM_RawMonitorDestroy(void* mon) { 147 LOG(DEBUG) << "JVM_RawMonitorDestroy mon=" << mon; 148 pthread_mutex_destroy(reinterpret_cast<pthread_mutex_t*>(mon)); 149} 150 151JNIEXPORT jint JVM_RawMonitorEnter(void* mon) { 152 LOG(DEBUG) << "JVM_RawMonitorEnter mon=" << mon; 153 return pthread_mutex_lock(reinterpret_cast<pthread_mutex_t*>(mon)); 154} 155 156JNIEXPORT void JVM_RawMonitorExit(void* mon) { 157 LOG(DEBUG) << "JVM_RawMonitorExit mon=" << mon; 158 pthread_mutex_unlock(reinterpret_cast<pthread_mutex_t*>(mon)); 159} 160 161JNIEXPORT char* JVM_NativePath(char* path) { 162 LOG(DEBUG) << "JVM_NativePath path='" << path << "'"; 163 return path; 164} 165 166JNIEXPORT jint JVM_GetLastErrorString(char* buf, int len) { 167#if defined(__GLIBC__) || defined(__BIONIC__) 168 int err = errno; // grab before JVM_TRACE can trash it 169 LOG(DEBUG) << "JVM_GetLastErrorString buf=" << buf << ", len=" << len; 170 171 if (len == 0) { 172 return 0; 173 } 174 175 char* result = strerror_r(err, buf, len); 176 if (result != buf) { 177 strncpy(buf, result, len); 178 buf[len - 1] = '\0'; 179 } 180 181 return strlen(buf); 182#else 183 UNUSED(buf); 184 UNUSED(len); 185 return -1; 186#endif 187} 188 189JNIEXPORT int jio_fprintf(FILE* fp, const char* fmt, ...) { 190 va_list args; 191 192 va_start(args, fmt); 193 int len = jio_vfprintf(fp, fmt, args); 194 va_end(args); 195 196 return len; 197} 198 199JNIEXPORT int jio_vfprintf(FILE* fp, const char* fmt, va_list args) { 200 assert(fp != NULL); 201 return vfprintf(fp, fmt, args); 202} 203 204/* posix fsync() */ 205JNIEXPORT jint JVM_Sync(jint fd) { 206 LOG(DEBUG) << "JVM_Sync fd=" << fd; 207 return TEMP_FAILURE_RETRY(fsync(fd)); 208} 209 210JNIEXPORT void* JVM_FindLibraryEntry(void* handle, const char* name) { 211 LOG(DEBUG) << "JVM_FindLibraryEntry handle=" << handle << " name=" << name; 212 return dlsym(handle, name); 213} 214 215JNIEXPORT jlong JVM_CurrentTimeMillis(JNIEnv* env, jclass clazz ATTRIBUTE_UNUSED) { 216 LOG(DEBUG) << "JVM_CurrentTimeMillis env=" << env; 217 struct timeval tv; 218 219 gettimeofday(&tv, (struct timezone *) NULL); 220 jlong when = tv.tv_sec * 1000LL + tv.tv_usec / 1000; 221 return when; 222} 223 224JNIEXPORT jint JVM_Socket(jint domain, jint type, jint protocol) { 225 LOG(DEBUG) << "JVM_Socket domain=" << domain << ", type=" << type << ", protocol=" << protocol; 226 227 return TEMP_FAILURE_RETRY(socket(domain, type, protocol)); 228} 229 230JNIEXPORT jint JVM_InitializeSocketLibrary() { 231 return 0; 232} 233 234int jio_vsnprintf(char *str, size_t count, const char *fmt, va_list args) { 235 if ((intptr_t)count <= 0) return -1; 236 return vsnprintf(str, count, fmt, args); 237} 238 239int jio_snprintf(char *str, size_t count, const char *fmt, ...) { 240 va_list args; 241 int len; 242 va_start(args, fmt); 243 len = jio_vsnprintf(str, count, fmt, args); 244 va_end(args); 245 return len; 246} 247 248JNIEXPORT jint JVM_SetSockOpt(jint fd, int level, int optname, 249 const char* optval, int optlen) { 250 LOG(DEBUG) << "JVM_SetSockOpt fd=" << fd << ", level=" << level << ", optname=" << optname 251 << ", optval=" << optval << ", optlen=" << optlen; 252 return TEMP_FAILURE_RETRY(setsockopt(fd, level, optname, optval, optlen)); 253} 254 255JNIEXPORT jint JVM_SocketShutdown(jint fd, jint howto) { 256 LOG(DEBUG) << "JVM_SocketShutdown fd=" << fd << ", howto=" << howto; 257 return TEMP_FAILURE_RETRY(shutdown(fd, howto)); 258} 259 260JNIEXPORT jint JVM_GetSockOpt(jint fd, int level, int optname, char* optval, 261 int* optlen) { 262 LOG(DEBUG) << "JVM_GetSockOpt fd=" << fd << ", level=" << level << ", optname=" << optname 263 << ", optval=" << optval << ", optlen=" << optlen; 264 265 socklen_t len = *optlen; 266 int cc = TEMP_FAILURE_RETRY(getsockopt(fd, level, optname, optval, &len)); 267 *optlen = len; 268 return cc; 269} 270 271JNIEXPORT jint JVM_GetSockName(jint fd, struct sockaddr* addr, int* addrlen) { 272 LOG(DEBUG) << "JVM_GetSockName fd=" << fd << ", addr=" << addr << ", addrlen=" << addrlen; 273 274 socklen_t len = *addrlen; 275 int cc = TEMP_FAILURE_RETRY(getsockname(fd, addr, &len)); 276 *addrlen = len; 277 return cc; 278} 279 280JNIEXPORT jint JVM_SocketAvailable(jint fd, jint* result) { 281 LOG(DEBUG) << "JVM_SocketAvailable fd=" << fd << ", result=" << result; 282 283 if (TEMP_FAILURE_RETRY(ioctl(fd, FIONREAD, result)) < 0) { 284 LOG(DEBUG) << "ioctl(" << fd << ", FIONREAD) failed: " << strerror(errno); 285 return JNI_FALSE; 286 } 287 288 return JNI_TRUE; 289} 290 291JNIEXPORT jint JVM_Send(jint fd, char* buf, jint nBytes, jint flags) { 292 LOG(DEBUG) << "JVM_Send fd=" << fd << ", buf=" << buf << ", nBytes=" 293 << nBytes << ", flags=" << flags; 294 295 return TEMP_FAILURE_RETRY(send(fd, buf, nBytes, flags)); 296} 297 298JNIEXPORT jint JVM_SocketClose(jint fd) { 299 LOG(DEBUG) << "JVM_SocketClose fd=" << fd; 300 301 // don't want TEMP_FAILURE_RETRY here -- file is closed even if EINTR 302 return close(fd); 303} 304 305JNIEXPORT jint JVM_Listen(jint fd, jint count) { 306 LOG(DEBUG) << "JVM_Listen fd=" << fd << ", count=" << count; 307 308 return TEMP_FAILURE_RETRY(listen(fd, count)); 309} 310 311JNIEXPORT jint JVM_Connect(jint fd, struct sockaddr* addr, jint addrlen) { 312 LOG(DEBUG) << "JVM_Connect fd=" << fd << ", addr=" << addr << ", addrlen=" << addrlen; 313 314 return TEMP_FAILURE_RETRY(connect(fd, addr, addrlen)); 315} 316 317JNIEXPORT int JVM_GetHostName(char* name, int namelen) { 318 LOG(DEBUG) << "JVM_GetHostName name=" << name << ", namelen=" << namelen; 319 320 return TEMP_FAILURE_RETRY(gethostname(name, namelen)); 321} 322 323JNIEXPORT jstring JVM_InternString(JNIEnv* env, jstring jstr) { 324 LOG(DEBUG) << "JVM_InternString env=" << env << ", jstr=" << jstr; 325 art::ScopedFastNativeObjectAccess soa(env); 326 art::mirror::String* s = soa.Decode<art::mirror::String*>(jstr); 327 art::mirror::String* result = s->Intern(); 328 return soa.AddLocalReference<jstring>(result); 329} 330 331JNIEXPORT jlong JVM_FreeMemory(void) { 332 return art::Runtime::Current()->GetHeap()->GetFreeMemory(); 333} 334 335JNIEXPORT jlong JVM_TotalMemory(void) { 336 return art::Runtime::Current()->GetHeap()->GetTotalMemory(); 337} 338 339JNIEXPORT jlong JVM_MaxMemory(void) { 340 return art::Runtime::Current()->GetHeap()->GetMaxMemory(); 341} 342 343JNIEXPORT void JVM_GC(void) { 344 if (art::Runtime::Current()->IsExplicitGcDisabled()) { 345 LOG(INFO) << "Explicit GC skipped."; 346 return; 347 } 348 art::Runtime::Current()->GetHeap()->CollectGarbage(false); 349} 350 351JNIEXPORT __attribute__((noreturn)) void JVM_Exit(jint status) { 352 LOG(INFO) << "System.exit called, status: " << status; 353 art::Runtime::Current()->CallExitHook(status); 354 exit(status); 355} 356 357static void SetLdLibraryPath(JNIEnv* env, jstring javaLdLibraryPath) { 358#ifdef __ANDROID__ 359 if (javaLdLibraryPath != nullptr) { 360 ScopedUtfChars ldLibraryPath(env, javaLdLibraryPath); 361 if (ldLibraryPath.c_str() != nullptr) { 362 android_update_LD_LIBRARY_PATH(ldLibraryPath.c_str()); 363 } 364 } 365 366#else 367 LOG(WARNING) << "android_update_LD_LIBRARY_PATH not found; .so dependencies will not work!"; 368 UNUSED(javaLdLibraryPath, env); 369#endif 370} 371 372 373JNIEXPORT jstring JVM_NativeLoad(JNIEnv* env, jstring javaFilename, jobject javaLoader, 374 jboolean isSharedNamespace, jstring javaLibrarySearchPath, 375 jstring javaLibraryPermittedPath) { 376 ScopedUtfChars filename(env, javaFilename); 377 if (filename.c_str() == NULL) { 378 return NULL; 379 } 380 381 int32_t target_sdk_version = art::Runtime::Current()->GetTargetSdkVersion(); 382 383 // Starting with N nativeLoad uses classloader local 384 // linker namespace instead of global LD_LIBRARY_PATH 385 // (23 is Marshmallow) 386 if (target_sdk_version <= 23) { 387 SetLdLibraryPath(env, javaLibrarySearchPath); 388 } 389 390 std::string error_msg; 391 { 392 art::ScopedObjectAccess soa(env); 393 art::StackHandleScope<1> hs(soa.Self()); 394 art::JavaVMExt* vm = art::Runtime::Current()->GetJavaVM(); 395 bool success = vm->LoadNativeLibrary(env, 396 filename.c_str(), 397 javaLoader, 398 isSharedNamespace == JNI_TRUE, 399 javaLibrarySearchPath, 400 javaLibraryPermittedPath, 401 &error_msg); 402 if (success) { 403 return nullptr; 404 } 405 } 406 407 // Don't let a pending exception from JNI_OnLoad cause a CheckJNI issue with NewStringUTF. 408 env->ExceptionClear(); 409 return env->NewStringUTF(error_msg.c_str()); 410} 411 412JNIEXPORT void JVM_StartThread(JNIEnv* env, jobject jthread, jlong stack_size, jboolean daemon) { 413 art::Thread::CreateNativeThread(env, jthread, stack_size, daemon == JNI_TRUE); 414} 415 416JNIEXPORT void JVM_SetThreadPriority(JNIEnv* env, jobject jthread, jint prio) { 417 art::ScopedObjectAccess soa(env); 418 art::MutexLock mu(soa.Self(), *art::Locks::thread_list_lock_); 419 art::Thread* thread = art::Thread::FromManagedThread(soa, jthread); 420 if (thread != NULL) { 421 thread->SetNativePriority(prio); 422 } 423} 424 425JNIEXPORT void JVM_Yield(JNIEnv* env ATTRIBUTE_UNUSED, jclass threadClass ATTRIBUTE_UNUSED) { 426 sched_yield(); 427} 428 429JNIEXPORT void JVM_Sleep(JNIEnv* env, jclass threadClass ATTRIBUTE_UNUSED, 430 jobject java_lock, jlong millis) { 431 art::ScopedFastNativeObjectAccess soa(env); 432 art::mirror::Object* lock = soa.Decode<art::mirror::Object*>(java_lock); 433 art::Monitor::Wait(art::Thread::Current(), lock, millis, 0, true, art::kSleeping); 434} 435 436JNIEXPORT jobject JVM_CurrentThread(JNIEnv* env, jclass unused ATTRIBUTE_UNUSED) { 437 art::ScopedFastNativeObjectAccess soa(env); 438 return soa.AddLocalReference<jobject>(soa.Self()->GetPeer()); 439} 440 441JNIEXPORT void JVM_Interrupt(JNIEnv* env, jobject jthread) { 442 art::ScopedFastNativeObjectAccess soa(env); 443 art::MutexLock mu(soa.Self(), *art::Locks::thread_list_lock_); 444 art::Thread* thread = art::Thread::FromManagedThread(soa, jthread); 445 if (thread != nullptr) { 446 thread->Interrupt(soa.Self()); 447 } 448} 449 450JNIEXPORT jboolean JVM_IsInterrupted(JNIEnv* env, jobject jthread, jboolean clearInterrupted) { 451 if (clearInterrupted) { 452 return static_cast<art::JNIEnvExt*>(env)->self->Interrupted() ? JNI_TRUE : JNI_FALSE; 453 } else { 454 art::ScopedFastNativeObjectAccess soa(env); 455 art::MutexLock mu(soa.Self(), *art::Locks::thread_list_lock_); 456 art::Thread* thread = art::Thread::FromManagedThread(soa, jthread); 457 return (thread != nullptr) ? thread->IsInterrupted() : JNI_FALSE; 458 } 459} 460 461JNIEXPORT jboolean JVM_HoldsLock(JNIEnv* env, jclass unused ATTRIBUTE_UNUSED, jobject jobj) { 462 art::ScopedObjectAccess soa(env); 463 art::mirror::Object* object = soa.Decode<art::mirror::Object*>(jobj); 464 if (object == NULL) { 465 art::ThrowNullPointerException("object == null"); 466 return JNI_FALSE; 467 } 468 return soa.Self()->HoldsLock(object); 469} 470 471JNIEXPORT void JVM_SetNativeThreadName(JNIEnv* env, jobject jthread, jstring java_name) { 472 ScopedUtfChars name(env, java_name); 473 { 474 art::ScopedObjectAccess soa(env); 475 if (soa.Decode<art::mirror::Object*>(jthread) == soa.Self()->GetPeer()) { 476 soa.Self()->SetThreadName(name.c_str()); 477 return; 478 } 479 } 480 // Suspend thread to avoid it from killing itself while we set its name. We don't just hold the 481 // thread list lock to avoid this, as setting the thread name causes mutator to lock/unlock 482 // in the DDMS send code. 483 art::ThreadList* thread_list = art::Runtime::Current()->GetThreadList(); 484 bool timed_out; 485 // Take suspend thread lock to avoid races with threads trying to suspend this one. 486 art::Thread* thread; 487 { 488 thread = thread_list->SuspendThreadByPeer(jthread, true, false, &timed_out); 489 } 490 if (thread != NULL) { 491 { 492 art::ScopedObjectAccess soa(env); 493 thread->SetThreadName(name.c_str()); 494 } 495 thread_list->Resume(thread, false); 496 } else if (timed_out) { 497 LOG(ERROR) << "Trying to set thread name to '" << name.c_str() << "' failed as the thread " 498 "failed to suspend within a generous timeout."; 499 } 500} 501 502JNIEXPORT jint JVM_IHashCode(JNIEnv* env ATTRIBUTE_UNUSED, 503 jobject javaObject ATTRIBUTE_UNUSED) { 504 UNIMPLEMENTED(FATAL) << "JVM_IHashCode is not implemented"; 505 return 0; 506} 507 508JNIEXPORT jlong JVM_NanoTime(JNIEnv* env ATTRIBUTE_UNUSED, jclass unused ATTRIBUTE_UNUSED) { 509 UNIMPLEMENTED(FATAL) << "JVM_NanoTime is not implemented"; 510 return 0L; 511} 512 513JNIEXPORT void JVM_ArrayCopy(JNIEnv* /* env */, jclass /* unused */, jobject /* javaSrc */, 514 jint /* srcPos */, jobject /* javaDst */, jint /* dstPos */, 515 jint /* length */) { 516 UNIMPLEMENTED(FATAL) << "JVM_ArrayCopy is not implemented"; 517} 518 519JNIEXPORT jint JVM_FindSignal(const char* name ATTRIBUTE_UNUSED) { 520 LOG(FATAL) << "JVM_FindSignal is not implemented"; 521 return 0; 522} 523 524JNIEXPORT void* JVM_RegisterSignal(jint signum ATTRIBUTE_UNUSED, void* handler ATTRIBUTE_UNUSED) { 525 LOG(FATAL) << "JVM_RegisterSignal is not implemented"; 526 return nullptr; 527} 528 529JNIEXPORT jboolean JVM_RaiseSignal(jint signum ATTRIBUTE_UNUSED) { 530 LOG(FATAL) << "JVM_RaiseSignal is not implemented"; 531 return JNI_FALSE; 532} 533 534JNIEXPORT __attribute__((noreturn)) void JVM_Halt(jint code) { 535 exit(code); 536} 537 538JNIEXPORT jboolean JVM_IsNaN(jdouble d) { 539 return isnan(d); 540} 541