--- a/.hgtags-top-repo Thu Aug 20 12:29:58 2015 -0700
+++ b/.hgtags-top-repo Wed Jul 05 20:46:25 2017 +0200
@@ -320,3 +320,4 @@
8fd6eeb878606e39c908f12535f34ebbfd225a4a jdk9-b75
d82072b699b880a1f647a5e2d7c0f86cec958941 jdk9-b76
7972dc8f2a47f0c4cd8f02fa5662af41f028aa14 jdk9-b77
+8c40d4143ee13bdf8170c68cc384c36ab1e9fadb jdk9-b78
--- a/common/bin/compare_exceptions.sh.incl Thu Aug 20 12:29:58 2015 -0700
+++ b/common/bin/compare_exceptions.sh.incl Wed Jul 05 20:46:25 2017 +0200
@@ -42,7 +42,6 @@
./demo/jvmti/gctest/lib/libgctest.so
./demo/jvmti/heapTracker/lib/libheapTracker.so
./demo/jvmti/heapViewer/lib/libheapViewer.so
-./demo/jvmti/hprof/lib/libhprof.so
./demo/jvmti/minst/lib/libminst.so
./demo/jvmti/mtrace/lib/libmtrace.so
./demo/jvmti/versionCheck/lib/libversionCheck.so
@@ -54,7 +53,6 @@
./demo/jvmti/gctest/lib/libgctest.so
./demo/jvmti/heapTracker/lib/libheapTracker.so
./demo/jvmti/heapViewer/lib/libheapViewer.so
-./demo/jvmti/hprof/lib/libhprof.so
./demo/jvmti/minst/lib/libminst.so
./demo/jvmti/mtrace/lib/libmtrace.so
./demo/jvmti/versionCheck/lib/libversionCheck.so
@@ -62,9 +60,7 @@
./lib/i386/client/libjvm.so
./lib/i386/libattach.so
./lib/i386/libdt_socket.so
-./lib/i386/libhprof.so
./lib/i386/libinstrument.so
-./lib/i386/libjava_crw_demo.so
./lib/i386/libjsdt.so
./lib/i386/libmanagement.so
./lib/i386/libnpt.so
@@ -118,7 +114,6 @@
./demo/jvmti/gctest/lib/libgctest.so
./demo/jvmti/heapTracker/lib/libheapTracker.so
./demo/jvmti/heapViewer/lib/libheapViewer.so
-./demo/jvmti/hprof/lib/libhprof.so
./demo/jvmti/minst/lib/libminst.so
./demo/jvmti/mtrace/lib/libmtrace.so
./demo/jvmti/versionCheck/lib/libversionCheck.so
@@ -130,16 +125,13 @@
./demo/jvmti/gctest/lib/libgctest.so
./demo/jvmti/heapTracker/lib/libheapTracker.so
./demo/jvmti/heapViewer/lib/libheapViewer.so
-./demo/jvmti/hprof/lib/libhprof.so
./demo/jvmti/minst/lib/libminst.so
./demo/jvmti/mtrace/lib/libmtrace.so
./demo/jvmti/versionCheck/lib/libversionCheck.so
./demo/jvmti/waiters/lib/libwaiters.so
./lib/amd64/libattach.so
./lib/amd64/libdt_socket.so
-./lib/amd64/libhprof.so
./lib/amd64/libinstrument.so
-./lib/amd64/libjava_crw_demo.so
./lib/amd64/libjsdt.so
./lib/amd64/libjsig.so
./lib/amd64/libmanagement.so
@@ -197,7 +189,6 @@
./demo/jvmti/gctest/lib/libgctest.so
./demo/jvmti/heapTracker/lib/libheapTracker.so
./demo/jvmti/heapViewer/lib/libheapViewer.so
-./demo/jvmti/hprof/lib/libhprof.so
./demo/jvmti/minst/lib/libminst.so
./demo/jvmti/mtrace/lib/libmtrace.so
./demo/jvmti/versionCheck/lib/libversionCheck.so
@@ -217,7 +208,6 @@
./demo/jvmti/gctest/lib/libgctest.so
./demo/jvmti/heapTracker/lib/libheapTracker.so
./demo/jvmti/heapViewer/lib/libheapViewer.so
-./demo/jvmti/hprof/lib/libhprof.so
./demo/jvmti/minst/lib/libminst.so
./demo/jvmti/mtrace/lib/libmtrace.so
./demo/jvmti/versionCheck/lib/libversionCheck.so
@@ -232,7 +222,6 @@
./lib/amd64/libdcpr.so
./lib/amd64/libdt_socket.so
./lib/amd64/libfontmanager.so
-./lib/amd64/libhprof.so
./lib/amd64/libinstrument.so
./lib/amd64/libj2gss.so
./lib/amd64/libj2pcsc.so
@@ -240,7 +229,6 @@
./lib/amd64/libj2ucrypto.so
./lib/amd64/libjaas_unix.so
./lib/amd64/libjava.so
-./lib/amd64/libjava_crw_demo.so
./lib/amd64/libjawt.so
./lib/amd64/libjdwp.so
./lib/amd64/libjfr.so
@@ -330,7 +318,6 @@
./demo/jvmti/gctest/lib/libgctest.so
./demo/jvmti/heapTracker/lib/libheapTracker.so
./demo/jvmti/heapViewer/lib/libheapViewer.so
-./demo/jvmti/hprof/lib/libhprof.so
./demo/jvmti/minst/lib/libminst.so
./demo/jvmti/mtrace/lib/libmtrace.so
./demo/jvmti/versionCheck/lib/libversionCheck.so
@@ -353,7 +340,6 @@
./demo/jvmti/gctest/lib/libgctest.so
./demo/jvmti/heapTracker/lib/libheapTracker.so
./demo/jvmti/heapViewer/lib/libheapViewer.so
-./demo/jvmti/hprof/lib/libhprof.so
./demo/jvmti/minst/lib/libminst.so
./demo/jvmti/mtrace/lib/libmtrace.so
./demo/jvmti/versionCheck/lib/libversionCheck.so
@@ -369,7 +355,6 @@
./lib/sparcv9/libdcpr.so
./lib/sparcv9/libdt_socket.so
./lib/sparcv9/libfontmanager.so
-./lib/sparcv9/libhprof.so
./lib/sparcv9/libinstrument.so
./lib/sparcv9/libj2gss.so
./lib/sparcv9/libj2pcsc.so
@@ -377,7 +362,6 @@
./lib/sparcv9/libj2ucrypto.so
./lib/sparcv9/libjaas_unix.so
./lib/sparcv9/libjava.so
-./lib/sparcv9/libjava_crw_demo.so
./lib/sparcv9/libjawt.so
./lib/sparcv9/libjdwp.so
./lib/sparcv9/libjfr.so
@@ -473,7 +457,6 @@
./demo/jvmti/heapTracker/lib/heapTracker.dll
./demo/jvmti/minst/lib/minst.dll
./bin/attach.dll
-./bin/java_crw_demo.dll
./bin/jsoundds.dll
./bin/server/jvm.dll
./bin/appletviewer.exe
@@ -611,9 +594,7 @@
./Contents/Home/lib/libawt_lwawt.dylib
./Contents/Home/lib/libdeploy.dylib
./Contents/Home/lib/libdt_socket.dylib
-./Contents/Home/lib/libhprof.dylib
./Contents/Home/lib/libinstrument.dylib
-./Contents/Home/lib/libjava_crw_demo.dylib
./Contents/Home/lib/libjdwp.dylib
./Contents/Home/lib/libjsdt.dylib
./Contents/Home/lib/libjsig.dylib
@@ -635,9 +616,7 @@
./lib/libawt_lwawt.dylib
./lib/libdeploy.dylib
./lib/libdt_socket.dylib
-./lib/libhprof.dylib
./lib/libinstrument.dylib
-./lib/libjava_crw_demo.dylib
./lib/libjdwp.dylib
./lib/libjsdt.dylib
./lib/libjsig.dylib
--- a/corba/.hgtags Thu Aug 20 12:29:58 2015 -0700
+++ b/corba/.hgtags Wed Jul 05 20:46:25 2017 +0200
@@ -320,3 +320,4 @@
960b56805abd8460598897481820bd6a75f979e7 jdk9-b75
d8126bc88fa5cd1ae4e44d86a4b1280ca1c9e2aa jdk9-b76
8bb2441c0fec8b28f7bf11a0ca3ec1642e7ef457 jdk9-b77
+182bb7accc5253bcfefd8edc1d4997ec8f9f8694 jdk9-b78
--- a/hotspot/.hgtags Thu Aug 20 12:29:58 2015 -0700
+++ b/hotspot/.hgtags Wed Jul 05 20:46:25 2017 +0200
@@ -480,3 +480,4 @@
2f354281e9915275693c4e519a959b8a6f22d3a3 jdk9-b75
0bc8d1656d6f2b1fdfe803c1305a108bb9939f35 jdk9-b76
e66c3813789debfc06f206afde1bf7a84cb08451 jdk9-b77
+20dc06b04fe5ec373879414d60ef82ac70faef98 jdk9-b78
--- a/hotspot/src/cpu/x86/vm/c1_CodeStubs_x86.cpp Thu Aug 20 12:29:58 2015 -0700
+++ b/hotspot/src/cpu/x86/vm/c1_CodeStubs_x86.cpp Wed Jul 05 20:46:25 2017 +0200
@@ -416,7 +416,8 @@
int jmp_off = __ offset();
__ jmp(_patch_site_entry);
// Add enough nops so deoptimization can overwrite the jmp above with a call
- // and not destroy the world.
+ // and not destroy the world. We cannot use fat nops here, since the concurrent
+ // code rewrite may transiently create the illegal instruction sequence.
for (int j = __ offset() ; j < jmp_off + 5 ; j++ ) {
__ nop();
}
--- a/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp Thu Aug 20 12:29:58 2015 -0700
+++ b/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp Wed Jul 05 20:46:25 2017 +0200
@@ -345,9 +345,7 @@
const bool do_post_padding = VerifyOops || UseCompressedClassPointers;
if (!do_post_padding) {
// insert some nops so that the verified entry point is aligned on CodeEntryAlignment
- while ((__ offset() + ic_cmp_size) % CodeEntryAlignment != 0) {
- __ nop();
- }
+ __ align(CodeEntryAlignment, __ offset() + ic_cmp_size);
}
int offset = __ offset();
__ inline_cache_check(receiver, IC_Klass);
@@ -2861,9 +2859,7 @@
case lir_virtual_call: // currently, sparc-specific for niagara
default: ShouldNotReachHere();
}
- while (offset++ % BytesPerWord != 0) {
- __ nop();
- }
+ __ align(BytesPerWord, offset);
}
}
@@ -2902,10 +2898,7 @@
int start = __ offset();
if (os::is_MP()) {
// make sure that the displacement word of the call ends up word aligned
- int offset = __ offset() + NativeMovConstReg::instruction_size + NativeCall::displacement_offset;
- while (offset++ % BytesPerWord != 0) {
- __ nop();
- }
+ __ align(BytesPerWord, __ offset() + NativeMovConstReg::instruction_size + NativeCall::displacement_offset);
}
__ relocate(static_stub_Relocation::spec(call_pc));
__ mov_metadata(rbx, (Metadata*)NULL);
--- a/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp Thu Aug 20 12:29:58 2015 -0700
+++ b/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp Wed Jul 05 20:46:25 2017 +0200
@@ -970,8 +970,12 @@
}
void MacroAssembler::align(int modulus) {
- if (offset() % modulus != 0) {
- nop(modulus - (offset() % modulus));
+ align(modulus, offset());
+}
+
+void MacroAssembler::align(int modulus, int target) {
+ if (target % modulus != 0) {
+ nop(modulus - (target % modulus));
}
}
--- a/hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp Thu Aug 20 12:29:58 2015 -0700
+++ b/hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp Wed Jul 05 20:46:25 2017 +0200
@@ -192,6 +192,7 @@
// Alignment
void align(int modulus);
+ void align(int modulus, int target);
// A 5 byte nop that is safe for patching (see patch_verified_entry)
void fat_nop();
--- a/hotspot/src/os/bsd/dtrace/generateJvmOffsets.cpp Thu Aug 20 12:29:58 2015 -0700
+++ b/hotspot/src/os/bsd/dtrace/generateJvmOffsets.cpp Wed Jul 05 20:46:25 2017 +0200
@@ -108,7 +108,7 @@
#define GEN_SIZE(Type) \
switch(gen_variant) { \
case GEN_OFFSET: \
- printf("#define SIZE_%-35s %ld\n", \
+ printf("#define SIZE_%-35s %ld\n", \
#Type, sizeof(Type)); \
break; \
case GEN_INDEX: \
@@ -134,7 +134,7 @@
}
void gen_prologue(GEN_variant gen_variant) {
- const char *suffix;
+ const char *suffix = "Undefined-Suffix";
switch(gen_variant) {
case GEN_OFFSET: suffix = ".h"; break;
@@ -228,10 +228,10 @@
printf("\n");
GEN_OFFS(Method, _constMethod);
- GEN_OFFS(Method, _constants);
GEN_OFFS(Method, _access_flags);
printf("\n");
+ GEN_OFFS(ConstMethod, _constants);
GEN_OFFS(ConstMethod, _flags);
GEN_OFFS(ConstMethod, _code_size);
GEN_OFFS(ConstMethod, _name_index);
@@ -264,7 +264,7 @@
GEN_OFFS(nmethod, _method);
GEN_OFFS(nmethod, _dependencies_offset);
- GEN_OFFS(nmethod, _oops_offset);
+ GEN_OFFS(nmethod, _metadata_offset);
GEN_OFFS(nmethod, _scopes_data_offset);
GEN_OFFS(nmethod, _scopes_pcs_offset);
GEN_OFFS(nmethod, _handler_table_offset);
--- a/hotspot/src/os/bsd/dtrace/jhelper.d Thu Aug 20 12:29:58 2015 -0700
+++ b/hotspot/src/os/bsd/dtrace/jhelper.d Wed Jul 05 20:46:25 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -49,7 +49,7 @@
extern pointer __1cIUniverseO_collectedHeap_;
extern pointer __1cHnmethodG__vtbl_;
-extern pointer __1cNMethodG__vtbl_;
+extern pointer __1cGMethodG__vtbl_;
extern pointer __1cKBufferBlobG__vtbl_;
#define copyin_ptr(ADDR) *(pointer*) copyin((pointer) (ADDR), sizeof(pointer))
@@ -164,7 +164,7 @@
this->number_of_heaps = copyin_uint32(this->code_heaps_address + OFFSET_GrowableArray_CodeHeap_len);
this->Method_vtbl = (pointer) &``__1cGMethodG__vtbl_;
-
+
/*
* Get Java heap bounds
*/
@@ -457,12 +457,15 @@
this->nameSymbol = copyin_ptr(this->constantPool +
this->nameIndex * sizeof (pointer) + SIZE_ConstantPool);
+ /* The symbol is a CPSlot and has lower bit set to indicate metadata */
+ this->nameSymbol &= (~1); /* remove metadata lsb */
this->nameSymbolLength = copyin_uint16(this->nameSymbol +
OFFSET_Symbol_length);
this->signatureSymbol = copyin_ptr(this->constantPool +
this->signatureIndex * sizeof (pointer) + SIZE_ConstantPool);
+ this->signatureSymbol &= (~1); /* remove metadata lsb */
this->signatureSymbolLength = copyin_uint16(this->signatureSymbol +
OFFSET_Symbol_length);
--- a/hotspot/src/os/bsd/dtrace/jvm_dtrace.c Thu Aug 20 12:29:58 2015 -0700
+++ b/hotspot/src/os/bsd/dtrace/jvm_dtrace.c Wed Jul 05 20:46:25 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -227,7 +227,7 @@
/* attach to given JVM */
jvm_t* jvm_attach(pid_t pid) {
jvm_t* jvm;
- int door_fd, attach_fd, i;
+ int door_fd, attach_fd, i = 0;
jvm = (jvm_t*) calloc(1, sizeof(jvm_t));
if (jvm == NULL) {
@@ -292,14 +292,13 @@
/* detach the givenb JVM */
int jvm_detach(jvm_t* jvm) {
if (jvm) {
- int res;
+ int res = 0;
if (jvm->door_fd != -1) {
if (file_close(jvm->door_fd) != 0) {
set_jvm_error(JVM_ERR_CANT_CLOSE_DOOR);
res = -1;
} else {
clear_jvm_error();
- res = 0;
}
}
free(jvm);
--- a/hotspot/src/os/bsd/dtrace/libjvm_db.c Thu Aug 20 12:29:58 2015 -0700
+++ b/hotspot/src/os/bsd/dtrace/libjvm_db.c Wed Jul 05 20:46:25 2017 +0200
@@ -882,7 +882,7 @@
/* Finds a PcDesc with real-pc equal to N->pc */
static int pc_desc_at(Nmethod_t *N)
{
- uint64_t pc_diff;
+ uint64_t pc_diff = 999;
int32_t offs;
int32_t err;
--- a/hotspot/src/os/linux/vm/perfMemory_linux.cpp Thu Aug 20 12:29:58 2015 -0700
+++ b/hotspot/src/os/linux/vm/perfMemory_linux.cpp Wed Jul 05 20:46:25 2017 +0200
@@ -217,9 +217,9 @@
//
return false;
}
- // See if the uid of the directory matches the effective uid of the process.
- //
- if (statp->st_uid != geteuid()) {
+ // If user is not root then see if the uid of the directory matches the effective uid of the process.
+ uid_t euid = geteuid();
+ if ((euid != 0) && (statp->st_uid != euid)) {
// The directory was not created by this user, declare it insecure.
//
return false;
--- a/hotspot/src/os/solaris/dtrace/generateJvmOffsets.cpp Thu Aug 20 12:29:58 2015 -0700
+++ b/hotspot/src/os/solaris/dtrace/generateJvmOffsets.cpp Wed Jul 05 20:46:25 2017 +0200
@@ -85,7 +85,7 @@
#define GEN_OFFS_NAME(Type,Name,OutputType) \
switch(gen_variant) { \
case GEN_OFFSET: \
- printf("#define OFFSET_%-33s %d\n", \
+ printf("#define OFFSET_%-33s %ld\n", \
#OutputType #Name, offset_of(Type, Name)); \
break; \
case GEN_INDEX: \
@@ -103,7 +103,7 @@
#define GEN_SIZE(Type) \
switch(gen_variant) { \
case GEN_OFFSET: \
- printf("#define SIZE_%-35s %d\n", \
+ printf("#define SIZE_%-35s %ld\n", \
#Type, sizeof(Type)); \
break; \
case GEN_INDEX: \
@@ -129,7 +129,7 @@
}
void gen_prologue(GEN_variant gen_variant) {
- const char *suffix;
+ const char *suffix = "Undefined-Suffix";
switch(gen_variant) {
case GEN_OFFSET: suffix = ".h"; break;
@@ -211,7 +211,7 @@
GEN_OFFS(ConstantPool, _pool_holder);
printf("\n");
- GEN_VALUE(OFFSET_HeapBlockHeader_used, offset_of(HeapBlock::Header, _used));
+ GEN_VALUE(OFFSET_HeapBlockHeader_used, (int) offset_of(HeapBlock::Header, _used));
GEN_OFFS(oopDesc, _metadata);
printf("\n");
@@ -275,7 +275,7 @@
GEN_OFFS(NarrowPtrStruct, _shift);
printf("\n");
- GEN_VALUE(SIZE_HeapBlockHeader, sizeof(HeapBlock::Header));
+ GEN_VALUE(SIZE_HeapBlockHeader, (int) sizeof(HeapBlock::Header));
GEN_SIZE(oopDesc);
GEN_SIZE(ConstantPool);
printf("\n");
--- a/hotspot/src/os/solaris/dtrace/jvm_dtrace.c Thu Aug 20 12:29:58 2015 -0700
+++ b/hotspot/src/os/solaris/dtrace/jvm_dtrace.c Wed Jul 05 20:46:25 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -227,7 +227,7 @@
/* attach to given JVM */
jvm_t* jvm_attach(pid_t pid) {
jvm_t* jvm;
- int door_fd, attach_fd, i;
+ int door_fd, attach_fd, i = 0;
jvm = (jvm_t*) calloc(1, sizeof(jvm_t));
if (jvm == NULL) {
@@ -292,14 +292,13 @@
/* detach the givenb JVM */
int jvm_detach(jvm_t* jvm) {
if (jvm) {
- int res;
+ int res = 0;
if (jvm->door_fd != -1) {
if (file_close(jvm->door_fd) != 0) {
set_jvm_error(JVM_ERR_CANT_CLOSE_DOOR);
res = -1;
} else {
clear_jvm_error();
- res = 0;
}
}
free(jvm);
--- a/hotspot/src/os/solaris/dtrace/libjvm_db.c Thu Aug 20 12:29:58 2015 -0700
+++ b/hotspot/src/os/solaris/dtrace/libjvm_db.c Wed Jul 05 20:46:25 2017 +0200
@@ -882,7 +882,7 @@
/* Finds a PcDesc with real-pc equal to N->pc */
static int pc_desc_at(Nmethod_t *N)
{
- uint64_t pc_diff;
+ uint64_t pc_diff = 999;
int32_t offs;
int32_t err;
--- a/hotspot/src/os/solaris/vm/os_solaris.cpp Thu Aug 20 12:29:58 2015 -0700
+++ b/hotspot/src/os/solaris/vm/os_solaris.cpp Wed Jul 05 20:46:25 2017 +0200
@@ -182,75 +182,6 @@
static void unpackTime(timespec* absTime, bool isAbsolute, jlong time);
-// Thread Local Storage
-// This is common to all Solaris platforms so it is defined here,
-// in this common file.
-// The declarations are in the os_cpu threadLS*.hpp files.
-//
-// Static member initialization for TLS
-Thread* ThreadLocalStorage::_get_thread_cache[ThreadLocalStorage::_pd_cache_size] = {NULL};
-
-#ifndef PRODUCT
- #define _PCT(n,d) ((100.0*(double)(n))/(double)(d))
-
-int ThreadLocalStorage::_tcacheHit = 0;
-int ThreadLocalStorage::_tcacheMiss = 0;
-
-void ThreadLocalStorage::print_statistics() {
- int total = _tcacheMiss+_tcacheHit;
- tty->print_cr("Thread cache hits %d misses %d total %d percent %f\n",
- _tcacheHit, _tcacheMiss, total, _PCT(_tcacheHit, total));
-}
- #undef _PCT
-#endif // PRODUCT
-
-Thread* ThreadLocalStorage::get_thread_via_cache_slowly(uintptr_t raw_id,
- int index) {
- Thread *thread = get_thread_slow();
- if (thread != NULL) {
- address sp = os::current_stack_pointer();
- guarantee(thread->_stack_base == NULL ||
- (sp <= thread->_stack_base &&
- sp >= thread->_stack_base - thread->_stack_size) ||
- is_error_reported(),
- "sp must be inside of selected thread stack");
-
- thread->set_self_raw_id(raw_id); // mark for quick retrieval
- _get_thread_cache[index] = thread;
- }
- return thread;
-}
-
-
-static const double all_zero[sizeof(Thread) / sizeof(double) + 1] = {0};
-#define NO_CACHED_THREAD ((Thread*)all_zero)
-
-void ThreadLocalStorage::pd_set_thread(Thread* thread) {
-
- // Store the new value before updating the cache to prevent a race
- // between get_thread_via_cache_slowly() and this store operation.
- os::thread_local_storage_at_put(ThreadLocalStorage::thread_index(), thread);
-
- // Update thread cache with new thread if setting on thread create,
- // or NO_CACHED_THREAD (zeroed) thread if resetting thread on exit.
- uintptr_t raw = pd_raw_thread_id();
- int ix = pd_cache_index(raw);
- _get_thread_cache[ix] = thread == NULL ? NO_CACHED_THREAD : thread;
-}
-
-void ThreadLocalStorage::pd_init() {
- for (int i = 0; i < _pd_cache_size; i++) {
- _get_thread_cache[i] = NO_CACHED_THREAD;
- }
-}
-
-// Invalidate all the caches (happens to be the same as pd_init).
-void ThreadLocalStorage::pd_invalidate_all() { pd_init(); }
-
-#undef NO_CACHED_THREAD
-
-// END Thread Local Storage
-
static inline size_t adjust_stack_size(address base, size_t size) {
if ((ssize_t)size < 0) {
// 4759953: Compensate for ridiculous stack size.
@@ -1289,67 +1220,6 @@
return (int)(_initial_pid ? _initial_pid : getpid());
}
-int os::allocate_thread_local_storage() {
- // %%% in Win32 this allocates a memory segment pointed to by a
- // register. Dan Stein can implement a similar feature in
- // Solaris. Alternatively, the VM can do the same thing
- // explicitly: malloc some storage and keep the pointer in a
- // register (which is part of the thread's context) (or keep it
- // in TLS).
- // %%% In current versions of Solaris, thr_self and TSD can
- // be accessed via short sequences of displaced indirections.
- // The value of thr_self is available as %g7(36).
- // The value of thr_getspecific(k) is stored in %g7(12)(4)(k*4-4),
- // assuming that the current thread already has a value bound to k.
- // It may be worth experimenting with such access patterns,
- // and later having the parameters formally exported from a Solaris
- // interface. I think, however, that it will be faster to
- // maintain the invariant that %g2 always contains the
- // JavaThread in Java code, and have stubs simply
- // treat %g2 as a caller-save register, preserving it in a %lN.
- thread_key_t tk;
- if (thr_keycreate(&tk, NULL)) {
- fatal(err_msg("os::allocate_thread_local_storage: thr_keycreate failed "
- "(%s)", strerror(errno)));
- }
- return int(tk);
-}
-
-void os::free_thread_local_storage(int index) {
- // %%% don't think we need anything here
- // if (pthread_key_delete((pthread_key_t) tk)) {
- // fatal("os::free_thread_local_storage: pthread_key_delete failed");
- // }
-}
-
-// libthread allocate for tsd_common is a version specific
-// small number - point is NO swap space available
-#define SMALLINT 32
-void os::thread_local_storage_at_put(int index, void* value) {
- // %%% this is used only in threadLocalStorage.cpp
- if (thr_setspecific((thread_key_t)index, value)) {
- if (errno == ENOMEM) {
- vm_exit_out_of_memory(SMALLINT, OOM_MALLOC_ERROR,
- "thr_setspecific: out of swap space");
- } else {
- fatal(err_msg("os::thread_local_storage_at_put: thr_setspecific failed "
- "(%s)", strerror(errno)));
- }
- } else {
- ThreadLocalStorage::set_thread_in_slot((Thread *) value);
- }
-}
-
-// This function could be called before TLS is initialized, for example, when
-// VM receives an async signal or when VM causes a fatal error during
-// initialization. Return NULL if thr_getspecific() fails.
-void* os::thread_local_storage_at(int index) {
- // %%% this is used only in threadLocalStorage.cpp
- void* r = NULL;
- return thr_getspecific((thread_key_t)index, &r) != 0 ? NULL : r;
-}
-
-
// gethrtime() should be monotonic according to the documentation,
// but some virtualized platforms are known to break this guarantee.
// getTimeNanos() must be guaranteed not to move backwards, so we
--- a/hotspot/src/os/solaris/vm/perfMemory_solaris.cpp Thu Aug 20 12:29:58 2015 -0700
+++ b/hotspot/src/os/solaris/vm/perfMemory_solaris.cpp Wed Jul 05 20:46:25 2017 +0200
@@ -219,9 +219,9 @@
//
return false;
}
- // See if the uid of the directory matches the effective uid of the process.
- //
- if (statp->st_uid != geteuid()) {
+ // If user is not root then see if the uid of the directory matches the effective uid of the process.
+ uid_t euid = geteuid();
+ if ((euid != 0) && (statp->st_uid != euid)) {
// The directory was not created by this user, declare it insecure.
//
return false;
--- a/hotspot/src/os/solaris/vm/thread_solaris.inline.hpp Thu Aug 20 12:29:58 2015 -0700
+++ b/hotspot/src/os/solaris/vm/thread_solaris.inline.hpp Wed Jul 05 20:46:25 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -39,19 +39,12 @@
// For SPARC, to avoid excessive register window spill-fill faults,
// we aggressively inline these routines.
-inline Thread* ThreadLocalStorage::thread() {
- // don't use specialized code if +UseMallocOnly -- may confuse Purify et al.
- debug_only(if (UseMallocOnly) return get_thread_slow(););
+inline void ThreadLocalStorage::set_thread(Thread* thread) {
+ _thr_current = thread;
+}
- uintptr_t raw = pd_raw_thread_id();
- int ix = pd_cache_index(raw);
- Thread* candidate = ThreadLocalStorage::_get_thread_cache[ix];
- if (candidate->self_raw_id() == raw) {
- // hit
- return candidate;
- } else {
- return ThreadLocalStorage::get_thread_via_cache_slowly(raw, ix);
- }
+inline Thread* ThreadLocalStorage::thread() {
+ return _thr_current;
}
#endif // OS_SOLARIS_VM_THREAD_SOLARIS_INLINE_HPP
--- a/hotspot/src/os_cpu/solaris_sparc/vm/threadLS_solaris_sparc.cpp Thu Aug 20 12:29:58 2015 -0700
+++ b/hotspot/src/os_cpu/solaris_sparc/vm/threadLS_solaris_sparc.cpp Wed Jul 05 20:46:25 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -26,19 +26,26 @@
#include "runtime/thread.inline.hpp"
#include "runtime/threadLocalStorage.hpp"
-// Provides an entry point we can link against and
-// a buffer we can emit code into. The buffer is
-// filled by ThreadLocalStorage::generate_code_for_get_thread
-// and called from ThreadLocalStorage::thread()
+// True thread-local variable
+__thread Thread * ThreadLocalStorage::_thr_current = NULL;
+
+// Implementations needed to support the shared API
-#include <sys/systeminfo.h>
+void ThreadLocalStorage::pd_invalidate_all() {} // nothing to do
-// The portable TLS mechanism (get_thread_via_cache) is enough on SPARC.
-// There is no need for hand-assembling a special function.
-void ThreadLocalStorage::generate_code_for_get_thread() {
+bool ThreadLocalStorage::_initialized = false;
+
+void ThreadLocalStorage::init() {
+ _initialized = true;
}
-void ThreadLocalStorage::set_thread_in_slot (Thread * self) {}
+bool ThreadLocalStorage::is_initialized() {
+ return _initialized;
+}
+
+Thread* ThreadLocalStorage::get_thread_slow() {
+ return thread();
+}
extern "C" Thread* get_thread() {
return ThreadLocalStorage::thread();
--- a/hotspot/src/os_cpu/solaris_sparc/vm/threadLS_solaris_sparc.hpp Thu Aug 20 12:29:58 2015 -0700
+++ b/hotspot/src/os_cpu/solaris_sparc/vm/threadLS_solaris_sparc.hpp Wed Jul 05 20:46:25 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -25,47 +25,15 @@
#ifndef OS_CPU_SOLARIS_SPARC_VM_THREADLS_SOLARIS_SPARC_HPP
#define OS_CPU_SOLARIS_SPARC_VM_THREADLS_SOLARIS_SPARC_HPP
-public:
- // Java Thread - force inlining
- static inline Thread* thread() ;
+// Solaris specific implementation involves simple, direct use
+// of a compiler-based thread-local variable
private:
- static Thread* _get_thread_cache[]; // index by [(raw_id>>9)^(raw_id>>20) % _pd_cache_size]
- static Thread* get_thread_via_cache_slowly(uintptr_t raw_id, int index);
+ static __thread Thread * _thr_current;
- NOT_PRODUCT(static int _tcacheHit;)
- NOT_PRODUCT(static int _tcacheMiss;)
+ static bool _initialized; // needed for shared API
public:
-
- // Print cache hit/miss statistics
- static void print_statistics() PRODUCT_RETURN;
-
- enum Constants {
- _pd_cache_size = 256*2 // projected typical # of threads * 2
- };
-
- static void set_thread_in_slot (Thread *) ;
-
- static uintptr_t pd_raw_thread_id() {
- return _raw_thread_id();
- }
-
- static int pd_cache_index(uintptr_t raw_id) {
- // Hash function: From email from Dave:
- // The hash function deserves an explanation. %g7 points to libthread's
- // "thread" structure. On T1 the thread structure is allocated on the
- // user's stack (yes, really!) so the ">>20" handles T1 where the JVM's
- // stack size is usually >= 1Mb. The ">>9" is for T2 where Roger allocates
- // globs of thread blocks contiguously. The "9" has to do with the
- // expected size of the T2 thread structure. If these constants are wrong
- // the worst thing that'll happen is that the hit rate for heavily threaded
- // apps won't be as good as it could be. If you want to burn another
- // shift+xor you could mix together _all of the %g7 bits to form the hash,
- // but I think that's excessive. Making the change above changed the
- // T$ miss rate on SpecJBB (on a 16X system) from about 3% to imperceptible.
- uintptr_t ix = (int) (((raw_id >> 9) ^ (raw_id >> 20)) % _pd_cache_size);
- return ix;
- }
+ static inline Thread* thread();
#endif // OS_CPU_SOLARIS_SPARC_VM_THREADLS_SOLARIS_SPARC_HPP
--- a/hotspot/src/os_cpu/solaris_x86/vm/assembler_solaris_x86.cpp Thu Aug 20 12:29:58 2015 -0700
+++ b/hotspot/src/os_cpu/solaris_x86/vm/assembler_solaris_x86.cpp Wed Jul 05 20:46:25 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -23,11 +23,10 @@
*/
#include "precompiled.hpp"
-#include "asm/macroAssembler.hpp"
#include "asm/macroAssembler.inline.hpp"
#include "runtime/os.hpp"
#include "runtime/threadLocalStorage.hpp"
-
+#include "runtime/thread.inline.hpp"
void MacroAssembler::int3() {
push(rax);
@@ -39,98 +38,32 @@
pop(rax);
}
-#define __ _masm->
-#ifndef _LP64
-static void slow_call_thr_specific(MacroAssembler* _masm, Register thread) {
-
- // slow call to of thr_getspecific
- // int thr_getspecific(thread_key_t key, void **value);
- // Consider using pthread_getspecific instead.
-
-__ push(0); // allocate space for return value
- if (thread != rax) __ push(rax); // save rax, if caller still wants it
-__ push(rcx); // save caller save
-__ push(rdx); // save caller save
+// This is simply a call to ThreadLocalStorage::thread()
+void MacroAssembler::get_thread(Register thread) {
if (thread != rax) {
-__ lea(thread, Address(rsp, 3 * sizeof(int))); // address of return value
- } else {
-__ lea(thread, Address(rsp, 2 * sizeof(int))); // address of return value
+ push(rax);
}
-__ push(thread); // and pass the address
-__ push(ThreadLocalStorage::thread_index()); // the key
-__ call(RuntimeAddress(CAST_FROM_FN_PTR(address, thr_getspecific)));
-__ increment(rsp, 2 * wordSize);
-__ pop(rdx);
-__ pop(rcx);
- if (thread != rax) __ pop(rax);
-__ pop(thread);
-
-}
-#else
-static void slow_call_thr_specific(MacroAssembler* _masm, Register thread) {
- // slow call to of thr_getspecific
- // int thr_getspecific(thread_key_t key, void **value);
- // Consider using pthread_getspecific instead.
+ push(rdi);
+ push(rsi);
+ push(rdx);
+ push(rcx);
+ push(r8);
+ push(r9);
+ push(r10);
+ push(r11);
+ call(RuntimeAddress(CAST_FROM_FN_PTR(address, ThreadLocalStorage::thread)));
+
+ pop(r11);
+ pop(r10);
+ pop(r9);
+ pop(r8);
+ pop(rcx);
+ pop(rdx);
+ pop(rsi);
+ pop(rdi);
if (thread != rax) {
-__ push(rax);
- }
-__ push(0); // space for return value
-__ push(rdi);
-__ push(rsi);
-__ lea(rsi, Address(rsp, 16)); // pass return value address
-__ push(rdx);
-__ push(rcx);
-__ push(r8);
-__ push(r9);
-__ push(r10);
- // XXX
-__ mov(r10, rsp);
-__ andptr(rsp, -16);
-__ push(r10);
-__ push(r11);
-
-__ movl(rdi, ThreadLocalStorage::thread_index());
-__ call(RuntimeAddress(CAST_FROM_FN_PTR(address, thr_getspecific)));
-
-__ pop(r11);
-__ pop(rsp);
-__ pop(r10);
-__ pop(r9);
-__ pop(r8);
-__ pop(rcx);
-__ pop(rdx);
-__ pop(rsi);
-__ pop(rdi);
-__ pop(thread); // load return value
- if (thread != rax) {
-__ pop(rax);
+ movl(thread, rax);
+ pop(rax);
}
}
-#endif //LP64
-
-void MacroAssembler::get_thread(Register thread) {
-
- int segment = NOT_LP64(Assembler::GS_segment) LP64_ONLY(Assembler::FS_segment);
- // Try to emit a Solaris-specific fast TSD/TLS accessor.
- ThreadLocalStorage::pd_tlsAccessMode tlsMode = ThreadLocalStorage::pd_getTlsAccessMode ();
- if (tlsMode == ThreadLocalStorage::pd_tlsAccessIndirect) { // T1
- // Use thread as a temporary: mov r, gs:[0]; mov r, [r+tlsOffset]
- emit_int8 (segment);
- // ExternalAddress doesn't work because it can't take NULL
- AddressLiteral null(0, relocInfo::none);
- movptr (thread, null);
- movptr(thread, Address(thread, ThreadLocalStorage::pd_getTlsOffset())) ;
- return ;
- } else
- if (tlsMode == ThreadLocalStorage::pd_tlsAccessDirect) { // T2
- // mov r, gs:[tlsOffset]
- emit_int8 (segment);
- AddressLiteral tls_off((address)ThreadLocalStorage::pd_getTlsOffset(), relocInfo::none);
- movptr (thread, tls_off);
- return ;
- }
-
- slow_call_thr_specific(this, thread);
-
-}
--- a/hotspot/src/os_cpu/solaris_x86/vm/threadLS_solaris_x86.cpp Thu Aug 20 12:29:58 2015 -0700
+++ b/hotspot/src/os_cpu/solaris_x86/vm/threadLS_solaris_x86.cpp Wed Jul 05 20:46:25 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -26,167 +26,27 @@
#include "runtime/thread.inline.hpp"
#include "runtime/threadLocalStorage.hpp"
-#ifdef AMD64
-extern "C" Thread* fs_load(ptrdiff_t tlsOffset);
-extern "C" intptr_t fs_thread();
-#else
-// From solaris_i486.s
-extern "C" Thread* gs_load(ptrdiff_t tlsOffset);
-extern "C" intptr_t gs_thread();
-#endif // AMD64
+// True thread-local variable
+__thread Thread * ThreadLocalStorage::_thr_current = NULL;
+
+// Implementations needed to support the shared API
-// tlsMode encoding:
-//
-// pd_tlsAccessUndefined : uninitialized
-// pd_tlsAccessSlow : not available
-// pd_tlsAccessIndirect :
-// old-style indirect access - present in "T1" libthread.
-// use thr_slot_sync_allocate() to attempt to allocate a slot.
-// pd_tlsAccessDirect :
-// new-style direct access - present in late-model "T2" libthread.
-// Allocate the offset (slot) via _thr_slot_offset() or by
-// defining an IE- or LE-mode TLS/TSD slot in the launcher and then passing
-// that offset into libjvm.so.
-// See http://sac.eng/Archives/CaseLog/arc/PSARC/2003/159/.
-//
-// Note that we have a capability gap - some early model T2 forms
-// (e.g., unpatched S9) have neither _thr_slot_sync_allocate() nor
-// _thr_slot_offset(). In that case we revert to the usual
-// thr_getspecific accessor.
-//
+void ThreadLocalStorage::pd_invalidate_all() {} // nothing to do
-static ThreadLocalStorage::pd_tlsAccessMode tlsMode = ThreadLocalStorage::pd_tlsAccessUndefined ;
-static ptrdiff_t tlsOffset = 0 ;
-static thread_key_t tlsKey ;
-
-typedef int (*TSSA_Entry) (ptrdiff_t *, int, int) ;
-typedef ptrdiff_t (*TSO_Entry) (int) ;
+bool ThreadLocalStorage::_initialized = false;
-ThreadLocalStorage::pd_tlsAccessMode ThreadLocalStorage::pd_getTlsAccessMode ()
-{
- guarantee (tlsMode != pd_tlsAccessUndefined, "tlsMode not set") ;
- return tlsMode ;
-}
-
-ptrdiff_t ThreadLocalStorage::pd_getTlsOffset () {
- guarantee (tlsMode != pd_tlsAccessUndefined, "tlsMode not set") ;
- return tlsOffset ;
+void ThreadLocalStorage::init() {
+ _initialized = true;
}
-// TODO: Consider the following improvements:
-//
-// 1. Convert from thr_*specific* to pthread_*specific*.
-// The pthread_ forms are slightly faster. Also, the
-// pthread_ forms have a pthread_key_delete() API which
-// would aid in clean JVM shutdown and the eventual goal
-// of permitting a JVM to reinstantiate itself withing a process.
-//
-// 2. See ThreadLocalStorage::init(). We end up allocating
-// two TLS keys during VM startup. That's benign, but we could collapse
-// down to one key without too much trouble.
-//
-// 3. MacroAssembler::get_thread() currently emits calls to thr_getspecific().
-// Modify get_thread() to call Thread::current() instead.
-//
-// 4. Thread::current() currently uses a cache keyed by %gs:[0].
-// (The JVM has PSARC permission to use %g7/%gs:[0]
-// as an opaque temporally unique thread identifier).
-// For C++ access to a thread's reflexive "self" pointer we
-// should consider using one of the following:
-// a. a radix tree keyed by %esp - as in EVM.
-// This requires two loads (the 2nd dependent on the 1st), but
-// is easily inlined and doesn't require a "miss" slow path.
-// b. a fast TLS/TSD slot allocated by _thr_slot_offset
-// or _thr_slot_sync_allocate.
-//
-// 5. 'generate_code_for_get_thread' is a misnomer.
-// We should change it to something more general like
-// pd_ThreadSelf_Init(), for instance.
-//
-
-static void AllocateTLSOffset ()
-{
- int rslt ;
- TSSA_Entry tssa ;
- TSO_Entry tso ;
- ptrdiff_t off ;
-
- guarantee (tlsMode == ThreadLocalStorage::pd_tlsAccessUndefined, "tlsMode not set") ;
- tlsMode = ThreadLocalStorage::pd_tlsAccessSlow ;
- tlsOffset = 0 ;
-#ifndef AMD64
-
- tssa = (TSSA_Entry) dlsym (RTLD_DEFAULT, "thr_slot_sync_allocate") ;
- if (tssa != NULL) {
- off = -1 ;
- rslt = (*tssa)(&off, NULL, NULL) ; // (off,dtor,darg)
- if (off != -1) {
- tlsOffset = off ;
- tlsMode = ThreadLocalStorage::pd_tlsAccessIndirect ;
- return ;
- }
- }
-
- rslt = thr_keycreate (&tlsKey, NULL) ;
- if (rslt != 0) {
- tlsMode = ThreadLocalStorage::pd_tlsAccessSlow ; // revert to slow mode
- return ;
- }
-
- tso = (TSO_Entry) dlsym (RTLD_DEFAULT, "_thr_slot_offset") ;
- if (tso != NULL) {
- off = (*tso)(tlsKey) ;
- if (off >= 0) {
- tlsOffset = off ;
- tlsMode = ThreadLocalStorage::pd_tlsAccessDirect ;
- return ;
- }
- }
-
- // Failure: Too bad ... we've allocated a TLS slot we don't need and there's
- // no provision in the ABI for returning the slot.
- //
- // If we didn't find a slot then then:
- // 1. We might be on liblwp.
- // 2. We might be on T2 libthread, but all "fast" slots are already
- // consumed
- // 3. We might be on T1, and all TSD (thr_slot_sync_allocate) slots are
- // consumed.
- // 4. We might be on T2 libthread, but it's be re-architected
- // so that fast slots are no longer g7-relative.
- //
-
- tlsMode = ThreadLocalStorage::pd_tlsAccessSlow ;
- return ;
-#endif // AMD64
+bool ThreadLocalStorage::is_initialized() {
+ return _initialized;
}
-void ThreadLocalStorage::generate_code_for_get_thread() {
- AllocateTLSOffset() ;
+Thread* ThreadLocalStorage::get_thread_slow() {
+ return thread();
}
-void ThreadLocalStorage::set_thread_in_slot(Thread *thread) {
- guarantee (tlsMode != pd_tlsAccessUndefined, "tlsMode not set") ;
- if (tlsMode == pd_tlsAccessIndirect) {
-#ifdef AMD64
- intptr_t tbase = fs_thread();
-#else
- intptr_t tbase = gs_thread();
-#endif // AMD64
- *((Thread**) (tbase + tlsOffset)) = thread ;
- } else
- if (tlsMode == pd_tlsAccessDirect) {
- thr_setspecific (tlsKey, (void *) thread) ;
- // set with thr_setspecific and then readback with gs_load to validate.
-#ifdef AMD64
- guarantee (thread == fs_load(tlsOffset), "tls readback failure") ;
-#else
- guarantee (thread == gs_load(tlsOffset), "tls readback failure") ;
-#endif // AMD64
- }
-}
-
-
extern "C" Thread* get_thread() {
return ThreadLocalStorage::thread();
}
--- a/hotspot/src/os_cpu/solaris_x86/vm/threadLS_solaris_x86.hpp Thu Aug 20 12:29:58 2015 -0700
+++ b/hotspot/src/os_cpu/solaris_x86/vm/threadLS_solaris_x86.hpp Wed Jul 05 20:46:25 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -25,61 +25,15 @@
#ifndef OS_CPU_SOLARIS_X86_VM_THREADLS_SOLARIS_X86_HPP
#define OS_CPU_SOLARIS_X86_VM_THREADLS_SOLARIS_X86_HPP
-// Processor dependent parts of ThreadLocalStorage
+// Solaris specific implementation involves simple, direct use
+// of a compiler-based thread-local variable
private:
- static Thread* _get_thread_cache[]; // index by [(raw_id>>9)^(raw_id>>20) % _pd_cache_size]
- static Thread* get_thread_via_cache_slowly(uintptr_t raw_id, int index);
+ static __thread Thread * _thr_current;
- NOT_PRODUCT(static int _tcacheHit;)
- NOT_PRODUCT(static int _tcacheMiss;)
+ static bool _initialized; // needed for shared API
public:
- // Cache hit/miss statistics
- static void print_statistics() PRODUCT_RETURN;
-
- enum Constants {
-#ifdef AMD64
- _pd_cache_size = 256*2 // projected typical # of threads * 2
-#else
- _pd_cache_size = 128*2 // projected typical # of threads * 2
-#endif // AMD64
- };
-
- enum pd_tlsAccessMode {
- pd_tlsAccessUndefined = -1,
- pd_tlsAccessSlow = 0,
- pd_tlsAccessIndirect = 1,
- pd_tlsAccessDirect = 2
- } ;
-
- static void set_thread_in_slot (Thread *) ;
-
- static pd_tlsAccessMode pd_getTlsAccessMode () ;
- static ptrdiff_t pd_getTlsOffset () ;
-
- static uintptr_t pd_raw_thread_id() {
-#ifdef _GNU_SOURCE
-#ifdef AMD64
- uintptr_t rv;
- __asm__ __volatile__ ("movq %%fs:0, %0" : "=r"(rv));
- return rv;
-#else
- return gs_thread();
-#endif // AMD64
-#else //_GNU_SOURCE
- return _raw_thread_id();
-#endif //_GNU_SOURCE
- }
-
- static int pd_cache_index(uintptr_t raw_id) {
- // Copied from the sparc version. Dave said it should also work fine
- // for solx86.
- int ix = (int) (((raw_id >> 9) ^ (raw_id >> 20)) % _pd_cache_size);
- return ix;
- }
-
- // Java Thread
static inline Thread* thread();
#endif // OS_CPU_SOLARIS_X86_VM_THREADLS_SOLARIS_X86_HPP
--- a/hotspot/src/share/vm/c1/c1_LIRAssembler.cpp Thu Aug 20 12:29:58 2015 -0700
+++ b/hotspot/src/share/vm/c1/c1_LIRAssembler.cpp Wed Jul 05 20:46:25 2017 +0200
@@ -33,7 +33,9 @@
#include "runtime/os.hpp"
void LIR_Assembler::patching_epilog(PatchingStub* patch, LIR_PatchCode patch_code, Register obj, CodeEmitInfo* info) {
- // we must have enough patching space so that call can be inserted
+ // We must have enough patching space so that call can be inserted.
+ // We cannot use fat nops here, since the concurrent code rewrite may transiently
+ // create the illegal instruction sequence.
while ((intx) _masm->pc() - (intx) patch->pc_start() < NativeCall::instruction_size) {
_masm->nop();
}
@@ -592,9 +594,7 @@
void LIR_Assembler::emit_op0(LIR_Op0* op) {
switch (op->code()) {
case lir_word_align: {
- while (code_offset() % BytesPerWord != 0) {
- _masm->nop();
- }
+ _masm->align(BytesPerWord);
break;
}
--- a/hotspot/src/share/vm/gc/cms/concurrentMarkSweepGeneration.cpp Thu Aug 20 12:29:58 2015 -0700
+++ b/hotspot/src/share/vm/gc/cms/concurrentMarkSweepGeneration.cpp Wed Jul 05 20:46:25 2017 +0200
@@ -620,12 +620,12 @@
// Support for parallelizing survivor space rescan
if ((CMSParallelRemarkEnabled && CMSParallelSurvivorRemarkEnabled) || CMSParallelInitialMarkEnabled) {
const size_t max_plab_samples =
- ((DefNewGeneration*)_young_gen)->max_survivor_size() / plab_sample_minimum_size();
+ _young_gen->max_survivor_size() / (ThreadLocalAllocBuffer::min_size() * HeapWordSize);
_survivor_plab_array = NEW_C_HEAP_ARRAY(ChunkArray, ParallelGCThreads, mtGC);
- _survivor_chunk_array = NEW_C_HEAP_ARRAY(HeapWord*, 2*max_plab_samples, mtGC);
+ _survivor_chunk_array = NEW_C_HEAP_ARRAY(HeapWord*, max_plab_samples, mtGC);
_cursor = NEW_C_HEAP_ARRAY(size_t, ParallelGCThreads, mtGC);
- _survivor_chunk_capacity = 2*max_plab_samples;
+ _survivor_chunk_capacity = max_plab_samples;
for (uint i = 0; i < ParallelGCThreads; i++) {
HeapWord** vec = NEW_C_HEAP_ARRAY(HeapWord*, max_plab_samples, mtGC);
ChunkArray* cur = ::new (&_survivor_plab_array[i]) ChunkArray(vec, max_plab_samples);
@@ -641,12 +641,6 @@
_inter_sweep_timer.start(); // start of time
}
-size_t CMSCollector::plab_sample_minimum_size() {
- // The default value of MinTLABSize is 2k, but there is
- // no way to get the default value if the flag has been overridden.
- return MAX2(ThreadLocalAllocBuffer::min_size() * HeapWordSize, 2 * K);
-}
-
const char* ConcurrentMarkSweepGeneration::name() const {
return "concurrent mark-sweep generation";
}
--- a/hotspot/src/share/vm/gc/cms/concurrentMarkSweepGeneration.hpp Thu Aug 20 12:29:58 2015 -0700
+++ b/hotspot/src/share/vm/gc/cms/concurrentMarkSweepGeneration.hpp Wed Jul 05 20:46:25 2017 +0200
@@ -739,10 +739,6 @@
size_t* _cursor;
ChunkArray* _survivor_plab_array;
- // A bounded minimum size of PLABs, should not return too small values since
- // this will affect the size of the data structures used for parallel young gen rescan
- size_t plab_sample_minimum_size();
-
// Support for marking stack overflow handling
bool take_from_overflow_list(size_t num, CMSMarkStack* to_stack);
bool par_take_from_overflow_list(size_t num,
--- a/hotspot/src/share/vm/gc/g1/g1AllocRegion.cpp Thu Aug 20 12:29:58 2015 -0700
+++ b/hotspot/src/share/vm/gc/g1/g1AllocRegion.cpp Wed Jul 05 20:46:25 2017 +0200
@@ -300,5 +300,3 @@
}
return G1AllocRegion::release();
}
-
-
--- a/hotspot/src/share/vm/gc/g1/g1Allocator.cpp Thu Aug 20 12:29:58 2015 -0700
+++ b/hotspot/src/share/vm/gc/g1/g1Allocator.cpp Wed Jul 05 20:46:25 2017 +0200
@@ -23,7 +23,7 @@
*/
#include "precompiled.hpp"
-#include "gc/g1/g1Allocator.hpp"
+#include "gc/g1/g1Allocator.inline.hpp"
#include "gc/g1/g1CollectedHeap.inline.hpp"
#include "gc/g1/g1CollectorPolicy.hpp"
#include "gc/g1/g1MarkSweep.hpp"
@@ -67,11 +67,11 @@
// retired. We have to remove it now, since we don't allow regions
// we allocate to in the region sets. We'll re-add it later, when
// it's retired again.
- _g1h->_old_set.remove(retained_region);
+ _g1h->old_set_remove(retained_region);
bool during_im = _g1h->collector_state()->during_initial_mark_pause();
retained_region->note_start_of_copying(during_im);
old->set(retained_region);
- _g1h->_hr_printer.reuse(retained_region);
+ _g1h->hr_printer()->reuse(retained_region);
evacuation_info.set_alloc_regions_used_before(retained_region->used());
}
}
@@ -116,15 +116,85 @@
G1PLAB::G1PLAB(size_t gclab_word_size) :
PLAB(gclab_word_size), _retired(true) { }
-HeapWord* G1ParGCAllocator::allocate_direct_or_new_plab(InCSetState dest,
- size_t word_sz,
- AllocationContext_t context) {
+size_t G1Allocator::unsafe_max_tlab_alloc(AllocationContext_t context) {
+ // Return the remaining space in the cur alloc region, but not less than
+ // the min TLAB size.
+
+ // Also, this value can be at most the humongous object threshold,
+ // since we can't allow tlabs to grow big enough to accommodate
+ // humongous objects.
+
+ HeapRegion* hr = mutator_alloc_region(context)->get();
+ size_t max_tlab = _g1h->max_tlab_size() * wordSize;
+ if (hr == NULL) {
+ return max_tlab;
+ } else {
+ return MIN2(MAX2(hr->free(), (size_t) MinTLABSize), max_tlab);
+ }
+}
+
+HeapWord* G1Allocator::par_allocate_during_gc(InCSetState dest,
+ size_t word_size,
+ AllocationContext_t context) {
+ switch (dest.value()) {
+ case InCSetState::Young:
+ return survivor_attempt_allocation(word_size, context);
+ case InCSetState::Old:
+ return old_attempt_allocation(word_size, context);
+ default:
+ ShouldNotReachHere();
+ return NULL; // Keep some compilers happy
+ }
+}
+
+HeapWord* G1Allocator::survivor_attempt_allocation(size_t word_size,
+ AllocationContext_t context) {
+ assert(!_g1h->is_humongous(word_size),
+ "we should not be seeing humongous-size allocations in this path");
+
+ HeapWord* result = survivor_gc_alloc_region(context)->attempt_allocation(word_size,
+ false /* bot_updates */);
+ if (result == NULL) {
+ MutexLockerEx x(FreeList_lock, Mutex::_no_safepoint_check_flag);
+ result = survivor_gc_alloc_region(context)->attempt_allocation_locked(word_size,
+ false /* bot_updates */);
+ }
+ if (result != NULL) {
+ _g1h->dirty_young_block(result, word_size);
+ }
+ return result;
+}
+
+HeapWord* G1Allocator::old_attempt_allocation(size_t word_size,
+ AllocationContext_t context) {
+ assert(!_g1h->is_humongous(word_size),
+ "we should not be seeing humongous-size allocations in this path");
+
+ HeapWord* result = old_gc_alloc_region(context)->attempt_allocation(word_size,
+ true /* bot_updates */);
+ if (result == NULL) {
+ MutexLockerEx x(FreeList_lock, Mutex::_no_safepoint_check_flag);
+ result = old_gc_alloc_region(context)->attempt_allocation_locked(word_size,
+ true /* bot_updates */);
+ }
+ return result;
+}
+
+G1PLABAllocator::G1PLABAllocator(G1Allocator* allocator) :
+ _g1h(G1CollectedHeap::heap()),
+ _allocator(allocator),
+ _survivor_alignment_bytes(calc_survivor_alignment_bytes()) {
+}
+
+HeapWord* G1PLABAllocator::allocate_direct_or_new_plab(InCSetState dest,
+ size_t word_sz,
+ AllocationContext_t context) {
size_t gclab_word_size = _g1h->desired_plab_sz(dest);
if (word_sz * 100 < gclab_word_size * ParallelGCBufferWastePct) {
G1PLAB* alloc_buf = alloc_buffer(dest, context);
alloc_buf->retire();
- HeapWord* buf = _g1h->par_allocate_during_gc(dest, gclab_word_size, context);
+ HeapWord* buf = _allocator->par_allocate_during_gc(dest, gclab_word_size, context);
if (buf == NULL) {
return NULL; // Let caller handle allocation failure.
}
@@ -136,14 +206,18 @@
assert(obj != NULL, "buffer was definitely big enough...");
return obj;
} else {
- return _g1h->par_allocate_during_gc(dest, word_sz, context);
+ return _allocator->par_allocate_during_gc(dest, word_sz, context);
}
}
-G1DefaultParGCAllocator::G1DefaultParGCAllocator(G1CollectedHeap* g1h) :
- G1ParGCAllocator(g1h),
- _surviving_alloc_buffer(g1h->desired_plab_sz(InCSetState::Young)),
- _tenured_alloc_buffer(g1h->desired_plab_sz(InCSetState::Old)) {
+void G1PLABAllocator::undo_allocation(InCSetState dest, HeapWord* obj, size_t word_sz, AllocationContext_t context) {
+ alloc_buffer(dest, context)->undo_allocation(obj, word_sz);
+}
+
+G1DefaultPLABAllocator::G1DefaultPLABAllocator(G1Allocator* allocator) :
+ G1PLABAllocator(allocator),
+ _surviving_alloc_buffer(_g1h->desired_plab_sz(InCSetState::Young)),
+ _tenured_alloc_buffer(_g1h->desired_plab_sz(InCSetState::Old)) {
for (uint state = 0; state < InCSetState::Num; state++) {
_alloc_buffers[state] = NULL;
}
@@ -151,7 +225,7 @@
_alloc_buffers[InCSetState::Old] = &_tenured_alloc_buffer;
}
-void G1DefaultParGCAllocator::retire_alloc_buffers() {
+void G1DefaultPLABAllocator::retire_alloc_buffers() {
for (uint state = 0; state < InCSetState::Num; state++) {
G1PLAB* const buf = _alloc_buffers[state];
if (buf != NULL) {
@@ -160,7 +234,7 @@
}
}
-void G1DefaultParGCAllocator::waste(size_t& wasted, size_t& undo_wasted) {
+void G1DefaultPLABAllocator::waste(size_t& wasted, size_t& undo_wasted) {
wasted = 0;
undo_wasted = 0;
for (uint state = 0; state < InCSetState::Num; state++) {
@@ -190,8 +264,8 @@
}
assert(hr->is_empty(), err_msg("expected empty region (index %u)", hr->hrm_index()));
hr->set_archive();
- _g1h->_old_set.add(hr);
- _g1h->_hr_printer.alloc(hr, G1HRPrinter::Archive);
+ _g1h->old_set_add(hr);
+ _g1h->hr_printer()->alloc(hr, G1HRPrinter::Archive);
_allocated_regions.append(hr);
_allocation_region = hr;
--- a/hotspot/src/share/vm/gc/g1/g1Allocator.hpp Thu Aug 20 12:29:58 2015 -0700
+++ b/hotspot/src/share/vm/gc/g1/g1Allocator.hpp Wed Jul 05 20:46:25 2017 +0200
@@ -33,17 +33,36 @@
class EvacuationInfo;
-// Base class for G1 allocators.
+// Interface to keep track of which regions G1 is currently allocating into. Provides
+// some accessors (e.g. allocating into them, or getting their occupancy).
+// Also keeps track of retained regions across GCs.
class G1Allocator : public CHeapObj<mtGC> {
friend class VMStructs;
protected:
G1CollectedHeap* _g1h;
+ virtual MutatorAllocRegion* mutator_alloc_region(AllocationContext_t context) = 0;
+
+ // Accessors to the allocation regions.
+ virtual SurvivorGCAllocRegion* survivor_gc_alloc_region(AllocationContext_t context) = 0;
+ virtual OldGCAllocRegion* old_gc_alloc_region(AllocationContext_t context) = 0;
+
+ // Allocation attempt during GC for a survivor object / PLAB.
+ inline HeapWord* survivor_attempt_allocation(size_t word_size,
+ AllocationContext_t context);
+ // Allocation attempt during GC for an old object / PLAB.
+ inline HeapWord* old_attempt_allocation(size_t word_size,
+ AllocationContext_t context);
public:
G1Allocator(G1CollectedHeap* heap) : _g1h(heap) { }
+ virtual ~G1Allocator() { }
static G1Allocator* create_allocator(G1CollectedHeap* g1h);
+#ifdef ASSERT
+ // Do we currently have an active mutator region to allocate into?
+ bool has_mutator_alloc_region(AllocationContext_t context) { return mutator_alloc_region(context)->get() != NULL; }
+#endif
virtual void init_mutator_alloc_region() = 0;
virtual void release_mutator_alloc_region() = 0;
@@ -51,24 +70,35 @@
virtual void release_gc_alloc_regions(EvacuationInfo& evacuation_info) = 0;
virtual void abandon_gc_alloc_regions() = 0;
- virtual MutatorAllocRegion* mutator_alloc_region(AllocationContext_t context) = 0;
- virtual SurvivorGCAllocRegion* survivor_gc_alloc_region(AllocationContext_t context) = 0;
- virtual OldGCAllocRegion* old_gc_alloc_region(AllocationContext_t context) = 0;
- virtual size_t used_in_alloc_regions() = 0;
- virtual bool is_retained_old_region(HeapRegion* hr) = 0;
+ // Management of retained regions.
+
+ virtual bool is_retained_old_region(HeapRegion* hr) = 0;
+ void reuse_retained_old_region(EvacuationInfo& evacuation_info,
+ OldGCAllocRegion* old,
+ HeapRegion** retained);
+
+ // Allocate blocks of memory during mutator time.
- void reuse_retained_old_region(EvacuationInfo& evacuation_info,
- OldGCAllocRegion* old,
- HeapRegion** retained);
+ inline HeapWord* attempt_allocation(size_t word_size, AllocationContext_t context);
+ inline HeapWord* attempt_allocation_locked(size_t word_size, AllocationContext_t context);
+ inline HeapWord* attempt_allocation_force(size_t word_size, AllocationContext_t context);
+
+ size_t unsafe_max_tlab_alloc(AllocationContext_t context);
- virtual HeapRegion* new_heap_region(uint hrs_index,
- G1BlockOffsetSharedArray* sharedOffsetArray,
- MemRegion mr) {
- return new HeapRegion(hrs_index, sharedOffsetArray, mr);
- }
+ // Allocate blocks of memory during garbage collection. Will ensure an
+ // allocation region, either by picking one or expanding the
+ // heap, and then allocate a block of the given size. The block
+ // may not be a humongous - it must fit into a single heap region.
+ HeapWord* par_allocate_during_gc(InCSetState dest,
+ size_t word_size,
+ AllocationContext_t context);
+
+ virtual size_t used_in_alloc_regions() = 0;
};
-// The default allocator for G1.
+// The default allocation region manager for G1. Provides a single mutator, survivor
+// and old generation allocation region.
+// Can retain the (single) old generation allocation region across GCs.
class G1DefaultAllocator : public G1Allocator {
protected:
// Alloc region used to satisfy mutator allocation requests.
@@ -152,10 +182,14 @@
}
};
-class G1ParGCAllocator : public CHeapObj<mtGC> {
+// Manages the PLABs used during garbage collection. Interface for allocation from PLABs.
+// Needs to handle multiple contexts, extra alignment in any "survivor" area and some
+// statistics.
+class G1PLABAllocator : public CHeapObj<mtGC> {
friend class G1ParScanThreadState;
protected:
G1CollectedHeap* _g1h;
+ G1Allocator* _allocator;
// The survivor alignment in effect in bytes.
// == 0 : don't align survivors
@@ -182,11 +216,10 @@
}
public:
- G1ParGCAllocator(G1CollectedHeap* g1h) :
- _g1h(g1h), _survivor_alignment_bytes(calc_survivor_alignment_bytes()) { }
- virtual ~G1ParGCAllocator() { }
+ G1PLABAllocator(G1Allocator* allocator);
+ virtual ~G1PLABAllocator() { }
- static G1ParGCAllocator* create_allocator(G1CollectedHeap* g1h);
+ static G1PLABAllocator* create_allocator(G1Allocator* allocator);
virtual void waste(size_t& wasted, size_t& undo_wasted) = 0;
@@ -219,18 +252,18 @@
return allocate_direct_or_new_plab(dest, word_sz, context);
}
- void undo_allocation(InCSetState dest, HeapWord* obj, size_t word_sz, AllocationContext_t context) {
- alloc_buffer(dest, context)->undo_allocation(obj, word_sz);
- }
+ void undo_allocation(InCSetState dest, HeapWord* obj, size_t word_sz, AllocationContext_t context);
};
-class G1DefaultParGCAllocator : public G1ParGCAllocator {
+// The default PLAB allocator for G1. Keeps the current (single) PLAB for survivor
+// and old generation allocation.
+class G1DefaultPLABAllocator : public G1PLABAllocator {
G1PLAB _surviving_alloc_buffer;
G1PLAB _tenured_alloc_buffer;
G1PLAB* _alloc_buffers[InCSetState::Num];
public:
- G1DefaultParGCAllocator(G1CollectedHeap* g1h);
+ G1DefaultPLABAllocator(G1Allocator* _allocator);
virtual G1PLAB* alloc_buffer(InCSetState dest, AllocationContext_t context) {
assert(dest.is_valid(),
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/gc/g1/g1Allocator.inline.hpp Wed Jul 05 20:46:25 2017 +0200
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef SHARE_VM_GC_G1_G1ALLOCATOR_INLINE_HPP
+#define SHARE_VM_GC_G1_G1ALLOCATOR_INLINE_HPP
+
+#include "gc/g1/g1Allocator.hpp"
+#include "gc/g1/g1AllocRegion.inline.hpp"
+
+HeapWord* G1Allocator::attempt_allocation(size_t word_size, AllocationContext_t context) {
+ return mutator_alloc_region(context)->attempt_allocation(word_size, false /* bot_updates */);
+}
+
+HeapWord* G1Allocator::attempt_allocation_locked(size_t word_size, AllocationContext_t context) {
+ HeapWord* result = mutator_alloc_region(context)->attempt_allocation_locked(word_size, false /* bot_updates */);
+ assert(result != NULL || mutator_alloc_region(context)->get() == NULL,
+ err_msg("Must not have a mutator alloc region if there is no memory, but is " PTR_FORMAT, p2i(mutator_alloc_region(context)->get())));
+ return result;
+}
+
+HeapWord* G1Allocator::attempt_allocation_force(size_t word_size, AllocationContext_t context) {
+ return mutator_alloc_region(context)->attempt_allocation_force(word_size, false /* bot_updates */);
+}
+
+#endif // SHARE_VM_GC_G1_G1ALLOCATOR_HPP
--- a/hotspot/src/share/vm/gc/g1/g1Allocator_ext.cpp Thu Aug 20 12:29:58 2015 -0700
+++ b/hotspot/src/share/vm/gc/g1/g1Allocator_ext.cpp Wed Jul 05 20:46:25 2017 +0200
@@ -30,6 +30,6 @@
return new G1DefaultAllocator(g1h);
}
-G1ParGCAllocator* G1ParGCAllocator::create_allocator(G1CollectedHeap* g1h) {
- return new G1DefaultParGCAllocator(g1h);
+G1PLABAllocator* G1PLABAllocator::create_allocator(G1Allocator* allocator) {
+ return new G1DefaultPLABAllocator(allocator);
}
--- a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp Thu Aug 20 12:29:58 2015 -0700
+++ b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp Wed Jul 05 20:46:25 2017 +0200
@@ -31,7 +31,7 @@
#include "gc/g1/concurrentG1Refine.hpp"
#include "gc/g1/concurrentG1RefineThread.hpp"
#include "gc/g1/concurrentMarkThread.inline.hpp"
-#include "gc/g1/g1AllocRegion.inline.hpp"
+#include "gc/g1/g1Allocator.inline.hpp"
#include "gc/g1/g1CollectedHeap.inline.hpp"
#include "gc/g1/g1CollectorPolicy.hpp"
#include "gc/g1/g1CollectorState.hpp"
@@ -815,22 +815,16 @@
{
MutexLockerEx x(Heap_lock);
- result = _allocator->mutator_alloc_region(context)->attempt_allocation_locked(word_size,
- false /* bot_updates */);
+ result = _allocator->attempt_allocation_locked(word_size, context);
if (result != NULL) {
return result;
}
- // If we reach here, attempt_allocation_locked() above failed to
- // allocate a new region. So the mutator alloc region should be NULL.
- assert(_allocator->mutator_alloc_region(context)->get() == NULL, "only way to get here");
-
if (GC_locker::is_active_and_needs_gc()) {
if (g1_policy()->can_expand_young_list()) {
// No need for an ergo verbose message here,
// can_expand_young_list() does this when it returns true.
- result = _allocator->mutator_alloc_region(context)->attempt_allocation_force(word_size,
- false /* bot_updates */);
+ result = _allocator->attempt_allocation_force(word_size, context);
if (result != NULL) {
return result;
}
@@ -890,8 +884,7 @@
// first attempt (without holding the Heap_lock) here and the
// follow-on attempt will be at the start of the next loop
// iteration (after taking the Heap_lock).
- result = _allocator->mutator_alloc_region(context)->attempt_allocation(word_size,
- false /* bot_updates */);
+ result = _allocator->attempt_allocation(word_size, context);
if (result != NULL) {
return result;
}
@@ -1109,6 +1102,29 @@
}
}
+inline HeapWord* G1CollectedHeap::attempt_allocation(size_t word_size,
+ uint* gc_count_before_ret,
+ uint* gclocker_retry_count_ret) {
+ assert_heap_not_locked_and_not_at_safepoint();
+ assert(!is_humongous(word_size), "attempt_allocation() should not "
+ "be called for humongous allocation requests");
+
+ AllocationContext_t context = AllocationContext::current();
+ HeapWord* result = _allocator->attempt_allocation(word_size, context);
+
+ if (result == NULL) {
+ result = attempt_allocation_slow(word_size,
+ context,
+ gc_count_before_ret,
+ gclocker_retry_count_ret);
+ }
+ assert_heap_not_locked();
+ if (result != NULL) {
+ dirty_young_block(result, word_size);
+ }
+ return result;
+}
+
HeapWord* G1CollectedHeap::attempt_allocation_humongous(size_t word_size,
uint* gc_count_before_ret,
uint* gclocker_retry_count_ret) {
@@ -1231,13 +1247,11 @@
AllocationContext_t context,
bool expect_null_mutator_alloc_region) {
assert_at_safepoint(true /* should_be_vm_thread */);
- assert(_allocator->mutator_alloc_region(context)->get() == NULL ||
- !expect_null_mutator_alloc_region,
+ assert(!_allocator->has_mutator_alloc_region(context) || !expect_null_mutator_alloc_region,
"the current alloc region was unexpectedly found to be non-NULL");
if (!is_humongous(word_size)) {
- return _allocator->mutator_alloc_region(context)->attempt_allocation_locked(word_size,
- false /* bot_updates */);
+ return _allocator->attempt_allocation_locked(word_size, context);
} else {
HeapWord* result = humongous_obj_allocate(word_size, context);
if (result != NULL && g1_policy()->need_to_start_conc_mark("STW humongous allocation")) {
@@ -2373,7 +2387,6 @@
assert(!dcqs.completed_buffers_exist_dirty(), "Completed buffers exist!");
}
-
// Computes the sum of the storage used by the various regions.
size_t G1CollectedHeap::used() const {
size_t result = _summary_bytes_used + _allocator->used_in_alloc_regions();
@@ -2632,6 +2645,11 @@
}
#endif
+bool G1CollectedHeap::obj_in_cs(oop obj) {
+ HeapRegion* r = _hrm.addr_to_region((HeapWord*) obj);
+ return r != NULL && r->in_collection_set();
+}
+
// Iteration functions.
// Applies an ExtendedOopClosure onto all references of objects within a HeapRegion.
@@ -2833,20 +2851,8 @@
}
size_t G1CollectedHeap::unsafe_max_tlab_alloc(Thread* ignored) const {
- // Return the remaining space in the cur alloc region, but not less than
- // the min TLAB size.
-
- // Also, this value can be at most the humongous object threshold,
- // since we can't allow tlabs to grow big enough to accommodate
- // humongous objects.
-
- HeapRegion* hr = _allocator->mutator_alloc_region(AllocationContext::current())->get();
- size_t max_tlab = max_tlab_size() * wordSize;
- if (hr == NULL) {
- return max_tlab;
- } else {
- return MIN2(MAX2(hr->free(), (size_t) MinTLABSize), max_tlab);
- }
+ AllocationContext_t context = AllocationContext::current();
+ return _allocator->unsafe_max_tlab_alloc(context);
}
size_t G1CollectedHeap::max_capacity() const {
@@ -4279,18 +4285,18 @@
g1_policy()->phase_times()->record_evac_fail_remove_self_forwards((os::elapsedTime() - remove_self_forwards_start) * 1000.0);
}
-void G1CollectedHeap::preserve_mark_during_evac_failure(uint queue_num, oop obj, markOop m) {
+void G1CollectedHeap::preserve_mark_during_evac_failure(uint worker_id, oop obj, markOop m) {
if (!_evacuation_failed) {
_evacuation_failed = true;
}
- _evacuation_failed_info_array[queue_num].register_copy_failure(obj->size());
+ _evacuation_failed_info_array[worker_id].register_copy_failure(obj->size());
// We want to call the "for_promotion_failure" version only in the
// case of a promotion failure.
if (m->must_be_preserved_for_promotion_failure(obj)) {
OopAndMarkOop elem(obj, m);
- _preserved_objs[queue_num].push(elem);
+ _preserved_objs[worker_id].push(elem);
}
}
@@ -4334,7 +4340,7 @@
oop obj = oopDesc::decode_heap_oop_not_null(heap_oop);
- assert(_worker_id == _par_scan_state->queue_num(), "sanity");
+ assert(_worker_id == _par_scan_state->worker_id(), "sanity");
const InCSetState state = _g1->in_cset_state(obj);
if (state.is_in_cset()) {
@@ -4443,9 +4449,6 @@
ParallelTaskTerminator _terminator;
uint _n_workers;
- Mutex _stats_lock;
- Mutex* stats_lock() { return &_stats_lock; }
-
public:
G1ParTask(G1CollectedHeap* g1h, RefToScanQueueSet *task_queues, G1RootProcessor* root_processor, uint n_workers)
: AbstractGangTask("G1 collection"),
@@ -4453,8 +4456,7 @@
_queues(task_queues),
_root_processor(root_processor),
_terminator(n_workers, _queues),
- _n_workers(n_workers),
- _stats_lock(Mutex::leaf, "parallel G1 stats lock", true)
+ _n_workers(n_workers)
{}
RefToScanQueueSet* queues() { return _queues; }
@@ -4581,8 +4583,8 @@
_g1h->update_surviving_young_words(pss.surviving_young_words()+1);
if (PrintTerminationStats) {
- MutexLocker x(stats_lock());
- pss.print_termination_stats(worker_id);
+ MutexLockerEx x(ParGCRareEvent_lock, Mutex::_no_safepoint_check_flag);
+ pss.print_termination_stats();
}
assert(pss.queue_is_empty(), "should be empty");
@@ -5009,7 +5011,7 @@
bool G1STWIsAliveClosure::do_object_b(oop p) {
// An object is reachable if it is outside the collection set,
// or is inside and copied.
- return !_g1->obj_in_cs(p) || p->is_forwarded();
+ return !_g1->is_in_cset(p) || p->is_forwarded();
}
// Non Copying Keep Alive closure
@@ -5498,7 +5500,9 @@
}
// The individual threads will set their evac-failure closures.
- if (PrintTerminationStats) G1ParScanThreadState::print_termination_stats_hdr();
+ if (PrintTerminationStats) {
+ G1ParScanThreadState::print_termination_stats_hdr();
+ }
workers()->run_task(&g1_par_task);
end_par_time_sec = os::elapsedTime();
@@ -6491,7 +6495,6 @@
return NULL;
}
-
// Heap region set verification
class VerifyRegionListsClosure : public HeapRegionClosure {
--- a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.hpp Thu Aug 20 12:29:58 2015 -0700
+++ b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.hpp Wed Jul 05 20:46:25 2017 +0200
@@ -27,7 +27,6 @@
#include "gc/g1/concurrentMark.hpp"
#include "gc/g1/evacuationInfo.hpp"
-#include "gc/g1/g1AllocRegion.hpp"
#include "gc/g1/g1AllocationContext.hpp"
#include "gc/g1/g1Allocator.hpp"
#include "gc/g1/g1BiasedArray.hpp"
@@ -187,13 +186,11 @@
friend class MutatorAllocRegion;
friend class SurvivorGCAllocRegion;
friend class OldGCAllocRegion;
- friend class G1Allocator;
- friend class G1ArchiveAllocator;
// Closures used in implementation.
friend class G1ParScanThreadState;
friend class G1ParTask;
- friend class G1ParGCAllocator;
+ friend class G1PLABAllocator;
friend class G1PrepareCompactClosure;
// Other related classes.
@@ -248,7 +245,7 @@
// The sequence of all heap regions in the heap.
HeapRegionManager _hrm;
- // Class that handles the different kinds of allocations.
+ // Handles non-humongous allocations in the G1CollectedHeap.
G1Allocator* _allocator;
// Outside of GC pauses, the number of bytes used in all regions other
@@ -280,22 +277,6 @@
// start of each GC.
bool _expand_heap_after_alloc_failure;
- // It resets the mutator alloc region before new allocations can take place.
- void init_mutator_alloc_region();
-
- // It releases the mutator alloc region.
- void release_mutator_alloc_region();
-
- // It initializes the GC alloc regions at the start of a GC.
- void init_gc_alloc_regions(EvacuationInfo& evacuation_info);
-
- // It releases the GC alloc regions at the end of a GC.
- void release_gc_alloc_regions(EvacuationInfo& evacuation_info);
-
- // It does any cleanup that needs to be done on the GC alloc regions
- // before a Full GC.
- void abandon_gc_alloc_regions();
-
// Helper for monitoring and management support.
G1MonitoringSupport* _g1mm;
@@ -551,31 +532,6 @@
AllocationContext_t context,
bool expect_null_mutator_alloc_region);
- // It dirties the cards that cover the block so that so that the post
- // write barrier never queues anything when updating objects on this
- // block. It is assumed (and in fact we assert) that the block
- // belongs to a young region.
- inline void dirty_young_block(HeapWord* start, size_t word_size);
-
- // Allocate blocks during garbage collection. Will ensure an
- // allocation region, either by picking one or expanding the
- // heap, and then allocate a block of the given size. The block
- // may not be a humongous - it must fit into a single heap region.
- inline HeapWord* par_allocate_during_gc(InCSetState dest,
- size_t word_size,
- AllocationContext_t context);
- // Ensure that no further allocations can happen in "r", bearing in mind
- // that parallel threads might be attempting allocations.
- void par_allocate_remaining_space(HeapRegion* r);
-
- // Allocation attempt during GC for a survivor object / PLAB.
- inline HeapWord* survivor_attempt_allocation(size_t word_size,
- AllocationContext_t context);
-
- // Allocation attempt during GC for an old object / PLAB.
- inline HeapWord* old_attempt_allocation(size_t word_size,
- AllocationContext_t context);
-
// These methods are the "callbacks" from the G1AllocRegion class.
// For mutator alloc regions.
@@ -589,10 +545,6 @@
void retire_gc_alloc_region(HeapRegion* alloc_region,
size_t allocated_bytes, InCSetState dest);
- // Allocate the highest free region in the reserved heap. This will commit
- // regions as necessary.
- HeapRegion* alloc_highest_free_region();
-
// - if explicit_gc is true, the GC is for a System.gc() or a heap
// inspection request and should collect the entire heap
// - if clear_all_soft_refs is true, all soft references should be
@@ -725,6 +677,13 @@
G1HRPrinter* hr_printer() { return &_hr_printer; }
+ // Allocates a new heap region instance.
+ HeapRegion* new_heap_region(uint hrs_index, MemRegion mr);
+
+ // Allocate the highest free region in the reserved heap. This will commit
+ // regions as necessary.
+ HeapRegion* alloc_highest_free_region();
+
// Frees a non-humongous region by initializing its contents and
// adding it to the free list that's passed as a parameter (this is
// usually a local list which will be appended to the master free
@@ -738,6 +697,12 @@
bool par,
bool locked = false);
+ // It dirties the cards that cover the block so that the post
+ // write barrier never queues anything when updating objects on this
+ // block. It is assumed (and in fact we assert) that the block
+ // belongs to a young region.
+ inline void dirty_young_block(HeapWord* start, size_t word_size);
+
// Frees a humongous region by collapsing it into individual regions
// and calling free_region() for each of them. The freed regions
// will be added to the free list that's passed as a parameter (this
@@ -887,7 +852,7 @@
// Preserve the mark of "obj", if necessary, in preparation for its mark
// word being overwritten with a self-forwarding-pointer.
- void preserve_mark_during_evac_failure(uint queue, oop obj, markOop m);
+ void preserve_mark_during_evac_failure(uint worker_id, oop obj, markOop m);
#ifndef PRODUCT
// Support for forcing evacuation failures. Analogous to
@@ -1216,6 +1181,7 @@
}
}
+ inline void old_set_add(HeapRegion* hr);
inline void old_set_remove(HeapRegion* hr);
size_t non_young_capacity_bytes() {
@@ -1263,7 +1229,7 @@
// Return "TRUE" iff the given object address is within the collection
// set. Slow implementation.
- inline bool obj_in_cs(oop obj);
+ bool obj_in_cs(oop obj);
inline bool is_in_cset(const HeapRegion *hr);
inline bool is_in_cset(oop obj);
--- a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.inline.hpp Thu Aug 20 12:29:58 2015 -0700
+++ b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.inline.hpp Wed Jul 05 20:46:25 2017 +0200
@@ -26,7 +26,6 @@
#define SHARE_VM_GC_G1_G1COLLECTEDHEAP_INLINE_HPP
#include "gc/g1/concurrentMark.hpp"
-#include "gc/g1/g1AllocRegion.inline.hpp"
#include "gc/g1/g1CollectedHeap.hpp"
#include "gc/g1/g1CollectorPolicy.hpp"
#include "gc/g1/g1CollectorState.hpp"
@@ -57,20 +56,6 @@
return MIN2(_humongous_object_threshold_in_words, gclab_word_size);
}
-HeapWord* G1CollectedHeap::par_allocate_during_gc(InCSetState dest,
- size_t word_size,
- AllocationContext_t context) {
- switch (dest.value()) {
- case InCSetState::Young:
- return survivor_attempt_allocation(word_size, context);
- case InCSetState::Old:
- return old_attempt_allocation(word_size, context);
- default:
- ShouldNotReachHere();
- return NULL; // Keep some compilers happy
- }
-}
-
// Inline functions for G1CollectedHeap
inline AllocationContextStats& G1CollectedHeap::allocation_context_stats() {
@@ -122,69 +107,12 @@
OrderAccess::fence();
}
-inline void G1CollectedHeap::old_set_remove(HeapRegion* hr) {
- _old_set.remove(hr);
-}
-
-inline bool G1CollectedHeap::obj_in_cs(oop obj) {
- HeapRegion* r = _hrm.addr_to_region((HeapWord*) obj);
- return r != NULL && r->in_collection_set();
-}
-
-inline HeapWord* G1CollectedHeap::attempt_allocation(size_t word_size,
- uint* gc_count_before_ret,
- uint* gclocker_retry_count_ret) {
- assert_heap_not_locked_and_not_at_safepoint();
- assert(!is_humongous(word_size), "attempt_allocation() should not "
- "be called for humongous allocation requests");
-
- AllocationContext_t context = AllocationContext::current();
- HeapWord* result = _allocator->mutator_alloc_region(context)->attempt_allocation(word_size,
- false /* bot_updates */);
- if (result == NULL) {
- result = attempt_allocation_slow(word_size,
- context,
- gc_count_before_ret,
- gclocker_retry_count_ret);
- }
- assert_heap_not_locked();
- if (result != NULL) {
- dirty_young_block(result, word_size);
- }
- return result;
+inline void G1CollectedHeap::old_set_add(HeapRegion* hr) {
+ _old_set.add(hr);
}
-inline HeapWord* G1CollectedHeap::survivor_attempt_allocation(size_t word_size,
- AllocationContext_t context) {
- assert(!is_humongous(word_size),
- "we should not be seeing humongous-size allocations in this path");
-
- HeapWord* result = _allocator->survivor_gc_alloc_region(context)->attempt_allocation(word_size,
- false /* bot_updates */);
- if (result == NULL) {
- MutexLockerEx x(FreeList_lock, Mutex::_no_safepoint_check_flag);
- result = _allocator->survivor_gc_alloc_region(context)->attempt_allocation_locked(word_size,
- false /* bot_updates */);
- }
- if (result != NULL) {
- dirty_young_block(result, word_size);
- }
- return result;
-}
-
-inline HeapWord* G1CollectedHeap::old_attempt_allocation(size_t word_size,
- AllocationContext_t context) {
- assert(!is_humongous(word_size),
- "we should not be seeing humongous-size allocations in this path");
-
- HeapWord* result = _allocator->old_gc_alloc_region(context)->attempt_allocation(word_size,
- true /* bot_updates */);
- if (result == NULL) {
- MutexLockerEx x(FreeList_lock, Mutex::_no_safepoint_check_flag);
- result = _allocator->old_gc_alloc_region(context)->attempt_allocation_locked(word_size,
- true /* bot_updates */);
- }
- return result;
+inline void G1CollectedHeap::old_set_remove(HeapRegion* hr) {
+ _old_set.remove(hr);
}
// It dirties the cards that cover the block so that so that the post
--- a/hotspot/src/share/vm/gc/g1/g1CollectedHeap_ext.cpp Thu Aug 20 12:29:58 2015 -0700
+++ b/hotspot/src/share/vm/gc/g1/g1CollectedHeap_ext.cpp Wed Jul 05 20:46:25 2017 +0200
@@ -24,6 +24,7 @@
#include "precompiled.hpp"
#include "gc/g1/g1CollectedHeap.hpp"
+#include "gc/g1/heapRegion.inline.hpp"
bool G1CollectedHeap::copy_allocation_context_stats(const jint* contexts,
jlong* totals,
@@ -31,3 +32,8 @@
jint len) {
return false;
}
+
+HeapRegion* G1CollectedHeap::new_heap_region(uint hrs_index,
+ MemRegion mr) {
+ return new HeapRegion(hrs_index, bot_shared(), mr);
+}
--- a/hotspot/src/share/vm/gc/g1/g1CollectorPolicy.cpp Thu Aug 20 12:29:58 2015 -0700
+++ b/hotspot/src/share/vm/gc/g1/g1CollectorPolicy.cpp Wed Jul 05 20:46:25 2017 +0200
@@ -31,6 +31,7 @@
#include "gc/g1/g1ErgoVerbose.hpp"
#include "gc/g1/g1GCPhaseTimes.hpp"
#include "gc/g1/g1Log.hpp"
+#include "gc/g1/heapRegion.inline.hpp"
#include "gc/g1/heapRegionRemSet.hpp"
#include "gc/shared/gcPolicyCounters.hpp"
#include "runtime/arguments.hpp"
--- a/hotspot/src/share/vm/gc/g1/g1OopClosures.cpp Thu Aug 20 12:29:58 2015 -0700
+++ b/hotspot/src/share/vm/gc/g1/g1OopClosures.cpp Wed Jul 05 20:46:25 2017 +0200
@@ -48,7 +48,7 @@
assert(par_scan_state != NULL, "Must set par_scan_state to non-NULL.");
_par_scan_state = par_scan_state;
- _worker_id = par_scan_state->queue_num();
+ _worker_id = par_scan_state->worker_id();
assert(_worker_id < ParallelGCThreads,
err_msg("The given worker id %u must be less than the number of threads %u", _worker_id, ParallelGCThreads));
--- a/hotspot/src/share/vm/gc/g1/g1OopClosures.inline.hpp Thu Aug 20 12:29:58 2015 -0700
+++ b/hotspot/src/share/vm/gc/g1/g1OopClosures.inline.hpp Wed Jul 05 20:46:25 2017 +0200
@@ -31,6 +31,7 @@
#include "gc/g1/g1ParScanThreadState.inline.hpp"
#include "gc/g1/g1RemSet.hpp"
#include "gc/g1/g1RemSet.inline.hpp"
+#include "gc/g1/heapRegion.inline.hpp"
#include "gc/g1/heapRegionRemSet.hpp"
#include "memory/iterator.inline.hpp"
#include "runtime/prefetch.inline.hpp"
--- a/hotspot/src/share/vm/gc/g1/g1ParScanThreadState.cpp Thu Aug 20 12:29:58 2015 -0700
+++ b/hotspot/src/share/vm/gc/g1/g1ParScanThreadState.cpp Wed Jul 05 20:46:25 2017 +0200
@@ -31,13 +31,13 @@
#include "oops/oop.inline.hpp"
#include "runtime/prefetch.inline.hpp"
-G1ParScanThreadState::G1ParScanThreadState(G1CollectedHeap* g1h, uint queue_num, ReferenceProcessor* rp)
+G1ParScanThreadState::G1ParScanThreadState(G1CollectedHeap* g1h, uint worker_id, ReferenceProcessor* rp)
: _g1h(g1h),
- _refs(g1h->task_queue(queue_num)),
+ _refs(g1h->task_queue(worker_id)),
_dcq(&g1h->dirty_card_queue_set()),
_ct_bs(g1h->g1_barrier_set()),
_g1_rem(g1h->g1_rem_set()),
- _hash_seed(17), _queue_num(queue_num),
+ _hash_seed(17), _worker_id(worker_id),
_term_attempts(0),
_tenuring_threshold(g1h->g1_policy()->tenuring_threshold()),
_age_table(false), _scanner(g1h, rp),
@@ -59,7 +59,7 @@
_surviving_young_words = _surviving_young_words_base + PADDING_ELEM_NUM;
memset(_surviving_young_words, 0, (size_t) real_length * sizeof(size_t));
- _g1_par_allocator = G1ParGCAllocator::create_allocator(_g1h);
+ _plab_allocator = G1PLABAllocator::create_allocator(_g1h->allocator());
_dest[InCSetState::NotInCSet] = InCSetState::NotInCSet;
// The dest for Young is used when the objects are aged enough to
@@ -71,37 +71,29 @@
}
G1ParScanThreadState::~G1ParScanThreadState() {
- _g1_par_allocator->retire_alloc_buffers();
- delete _g1_par_allocator;
+ _plab_allocator->retire_alloc_buffers();
+ delete _plab_allocator;
FREE_C_HEAP_ARRAY(size_t, _surviving_young_words_base);
}
-void
-G1ParScanThreadState::print_termination_stats_hdr(outputStream* const st)
-{
+void G1ParScanThreadState::print_termination_stats_hdr(outputStream* const st) {
st->print_raw_cr("GC Termination Stats");
- st->print_raw_cr(" elapsed --strong roots-- -------termination-------"
- " ------waste (KiB)------");
- st->print_raw_cr("thr ms ms % ms % attempts"
- " total alloc undo");
- st->print_raw_cr("--- --------- --------- ------ --------- ------ --------"
- " ------- ------- -------");
+ st->print_raw_cr(" elapsed --strong roots-- -------termination------- ------waste (KiB)------");
+ st->print_raw_cr("thr ms ms % ms % attempts total alloc undo");
+ st->print_raw_cr("--- --------- --------- ------ --------- ------ -------- ------- ------- -------");
}
-void
-G1ParScanThreadState::print_termination_stats(int i,
- outputStream* const st) const
-{
+void G1ParScanThreadState::print_termination_stats(outputStream* const st) const {
const double elapsed_ms = elapsed_time() * 1000.0;
const double s_roots_ms = strong_roots_time() * 1000.0;
const double term_ms = term_time() * 1000.0;
size_t alloc_buffer_waste = 0;
size_t undo_waste = 0;
- _g1_par_allocator->waste(alloc_buffer_waste, undo_waste);
- st->print_cr("%3d %9.2f %9.2f %6.2f "
+ _plab_allocator->waste(alloc_buffer_waste, undo_waste);
+ st->print_cr("%3u %9.2f %9.2f %6.2f "
"%9.2f %6.2f " SIZE_FORMAT_W(8) " "
SIZE_FORMAT_W(7) " " SIZE_FORMAT_W(7) " " SIZE_FORMAT_W(7),
- i, elapsed_ms, s_roots_ms, s_roots_ms * 100 / elapsed_ms,
+ _worker_id, elapsed_ms, s_roots_ms, s_roots_ms * 100 / elapsed_ms,
term_ms, term_ms * 100 / elapsed_ms, term_attempts(),
(alloc_buffer_waste + undo_waste) * HeapWordSize / K,
alloc_buffer_waste * HeapWordSize / K,
@@ -167,8 +159,9 @@
// Right now we only have two types of regions (young / old) so
// let's keep the logic here simple. We can generalize it when necessary.
if (dest->is_young()) {
- HeapWord* const obj_ptr = _g1_par_allocator->allocate(InCSetState::Old,
- word_sz, context);
+ HeapWord* const obj_ptr = _plab_allocator->allocate(InCSetState::Old,
+ word_sz,
+ context);
if (obj_ptr == NULL) {
return NULL;
}
@@ -209,12 +202,12 @@
uint age = 0;
InCSetState dest_state = next_state(state, old_mark, age);
- HeapWord* obj_ptr = _g1_par_allocator->plab_allocate(dest_state, word_sz, context);
+ HeapWord* obj_ptr = _plab_allocator->plab_allocate(dest_state, word_sz, context);
// PLAB allocations should succeed most of the time, so we'll
// normally check against NULL once and that's it.
if (obj_ptr == NULL) {
- obj_ptr = _g1_par_allocator->allocate_direct_or_new_plab(dest_state, word_sz, context);
+ obj_ptr = _plab_allocator->allocate_direct_or_new_plab(dest_state, word_sz, context);
if (obj_ptr == NULL) {
obj_ptr = allocate_in_next_plab(state, &dest_state, word_sz, context);
if (obj_ptr == NULL) {
@@ -233,7 +226,7 @@
if (_g1h->evacuation_should_fail()) {
// Doing this after all the allocation attempts also tests the
// undo_allocation() method too.
- _g1_par_allocator->undo_allocation(dest_state, obj_ptr, word_sz, context);
+ _plab_allocator->undo_allocation(dest_state, obj_ptr, word_sz, context);
return handle_evacuation_failure_par(old, old_mark);
}
#endif // !PRODUCT
@@ -274,7 +267,7 @@
"sanity");
G1StringDedup::enqueue_from_evacuation(is_from_young,
is_to_young,
- queue_num(),
+ _worker_id,
obj);
}
@@ -295,7 +288,7 @@
}
return obj;
} else {
- _g1_par_allocator->undo_allocation(dest_state, obj_ptr, word_sz, context);
+ _plab_allocator->undo_allocation(dest_state, obj_ptr, word_sz, context);
return forward_ptr;
}
}
@@ -314,7 +307,7 @@
_g1h->hr_printer()->evac_failure(r);
}
- _g1h->preserve_mark_during_evac_failure(_queue_num, old, m);
+ _g1h->preserve_mark_during_evac_failure(_worker_id, old, m);
_scanner.set_region(r);
old->oop_iterate_backwards(&_scanner);
--- a/hotspot/src/share/vm/gc/g1/g1ParScanThreadState.hpp Thu Aug 20 12:29:58 2015 -0700
+++ b/hotspot/src/share/vm/gc/g1/g1ParScanThreadState.hpp Wed Jul 05 20:46:25 2017 +0200
@@ -46,7 +46,7 @@
G1SATBCardTableModRefBS* _ct_bs;
G1RemSet* _g1_rem;
- G1ParGCAllocator* _g1_par_allocator;
+ G1PLABAllocator* _plab_allocator;
ageTable _age_table;
InCSetState _dest[InCSetState::Num];
@@ -55,7 +55,7 @@
G1ParScanClosure _scanner;
int _hash_seed;
- uint _queue_num;
+ uint _worker_id;
size_t _term_attempts;
@@ -85,7 +85,7 @@
}
public:
- G1ParScanThreadState(G1CollectedHeap* g1h, uint queue_num, ReferenceProcessor* rp);
+ G1ParScanThreadState(G1CollectedHeap* g1h, uint worker_id, ReferenceProcessor* rp);
~G1ParScanThreadState();
ageTable* age_table() { return &_age_table; }
@@ -112,8 +112,7 @@
}
}
- int* hash_seed() { return &_hash_seed; }
- uint queue_num() { return _queue_num; }
+ uint worker_id() { return _worker_id; }
size_t term_attempts() const { return _term_attempts; }
void note_term_attempt() { _term_attempts++; }
@@ -139,8 +138,11 @@
return os::elapsedTime() - _start;
}
+ // Print the header for the per-thread termination statistics.
static void print_termination_stats_hdr(outputStream* const st = gclog_or_tty);
- void print_termination_stats(int i, outputStream* const st = gclog_or_tty) const;
+
+ // Print actual per-thread termination statistics.
+ void print_termination_stats(outputStream* const st = gclog_or_tty) const;
size_t* surviving_young_words() {
// We add on to hide entry 0 which accumulates surviving words for
--- a/hotspot/src/share/vm/gc/g1/g1ParScanThreadState.inline.hpp Thu Aug 20 12:29:58 2015 -0700
+++ b/hotspot/src/share/vm/gc/g1/g1ParScanThreadState.inline.hpp Wed Jul 05 20:46:25 2017 +0200
@@ -56,7 +56,7 @@
}
assert(obj != NULL, "Must be");
- update_rs(from, p, queue_num());
+ update_rs(from, p, _worker_id);
}
template <class T> inline void G1ParScanThreadState::push_on_queue(T* ref) {
@@ -136,7 +136,7 @@
void G1ParScanThreadState::steal_and_trim_queue(RefToScanQueueSet *task_queues) {
StarTask stolen_task;
- while (task_queues->steal(queue_num(), hash_seed(), stolen_task)) {
+ while (task_queues->steal(_worker_id, &_hash_seed, stolen_task)) {
assert(verify_task(stolen_task), "sanity");
dispatch_reference(stolen_task);
--- a/hotspot/src/share/vm/gc/g1/g1RootProcessor.cpp Thu Aug 20 12:29:58 2015 -0700
+++ b/hotspot/src/share/vm/gc/g1/g1RootProcessor.cpp Wed Jul 05 20:46:25 2017 +0200
@@ -34,6 +34,7 @@
#include "gc/g1/g1GCPhaseTimes.hpp"
#include "gc/g1/g1RemSet.inline.hpp"
#include "gc/g1/g1RootProcessor.hpp"
+#include "gc/g1/heapRegion.inline.hpp"
#include "memory/allocation.inline.hpp"
#include "runtime/fprofiler.hpp"
#include "runtime/mutex.hpp"
--- a/hotspot/src/share/vm/gc/g1/heapRegion.hpp Thu Aug 20 12:29:58 2015 -0700
+++ b/hotspot/src/share/vm/gc/g1/heapRegion.hpp Wed Jul 05 20:46:25 2017 +0200
@@ -497,20 +497,10 @@
return _rem_set;
}
- bool in_collection_set() const;
+ inline bool in_collection_set() const;
- HeapRegion* next_in_collection_set() {
- assert(in_collection_set(), "should only invoke on member of CS.");
- assert(_next_in_special_set == NULL ||
- _next_in_special_set->in_collection_set(),
- "Malformed CS.");
- return _next_in_special_set;
- }
- void set_next_in_collection_set(HeapRegion* r) {
- assert(in_collection_set(), "should only invoke on member of CS.");
- assert(r == NULL || r->in_collection_set(), "Malformed CS.");
- _next_in_special_set = r;
- }
+ inline HeapRegion* next_in_collection_set() const;
+ inline void set_next_in_collection_set(HeapRegion* r);
void set_allocation_context(AllocationContext_t context) {
_allocation_context = context;
--- a/hotspot/src/share/vm/gc/g1/heapRegion.inline.hpp Thu Aug 20 12:29:58 2015 -0700
+++ b/hotspot/src/share/vm/gc/g1/heapRegion.inline.hpp Wed Jul 05 20:46:25 2017 +0200
@@ -26,7 +26,7 @@
#define SHARE_VM_GC_G1_HEAPREGION_INLINE_HPP
#include "gc/g1/g1BlockOffsetTable.inline.hpp"
-#include "gc/g1/g1CollectedHeap.hpp"
+#include "gc/g1/g1CollectedHeap.inline.hpp"
#include "gc/g1/heapRegion.hpp"
#include "gc/shared/space.hpp"
#include "oops/oop.inline.hpp"
@@ -200,4 +200,18 @@
return G1CollectedHeap::heap()->is_in_cset(this);
}
+inline HeapRegion* HeapRegion::next_in_collection_set() const {
+ assert(in_collection_set(), "should only invoke on member of CS.");
+ assert(_next_in_special_set == NULL ||
+ _next_in_special_set->in_collection_set(),
+ "Malformed CS.");
+ return _next_in_special_set;
+}
+
+void HeapRegion::set_next_in_collection_set(HeapRegion* r) {
+ assert(in_collection_set(), "should only invoke on member of CS.");
+ assert(r == NULL || r->in_collection_set(), "Malformed CS.");
+ _next_in_special_set = r;
+}
+
#endif // SHARE_VM_GC_G1_HEAPREGION_INLINE_HPP
--- a/hotspot/src/share/vm/gc/g1/heapRegionManager.cpp Thu Aug 20 12:29:58 2015 -0700
+++ b/hotspot/src/share/vm/gc/g1/heapRegionManager.cpp Wed Jul 05 20:46:25 2017 +0200
@@ -70,7 +70,7 @@
HeapWord* bottom = g1h->bottom_addr_for_region(hrm_index);
MemRegion mr(bottom, bottom + HeapRegion::GrainWords);
assert(reserved().contains(mr), "invariant");
- return g1h->allocator()->new_heap_region(hrm_index, g1h->bot_shared(), mr);
+ return g1h->new_heap_region(hrm_index, mr);
}
void HeapRegionManager::commit_regions(uint index, size_t num_regions) {
--- a/hotspot/src/share/vm/gc/g1/vm_operations_g1.cpp Thu Aug 20 12:29:58 2015 -0700
+++ b/hotspot/src/share/vm/gc/g1/vm_operations_g1.cpp Wed Jul 05 20:46:25 2017 +0200
@@ -94,8 +94,9 @@
if (_word_size > 0) {
// An allocation has been requested. So, try to do that first.
- _result = g1h->attempt_allocation_at_safepoint(_word_size, allocation_context(),
- false /* expect_null_cur_alloc_region */);
+ _result = g1h->attempt_allocation_at_safepoint(_word_size,
+ allocation_context(),
+ false /* expect_null_cur_alloc_region */);
if (_result != NULL) {
// If we can successfully allocate before we actually do the
// pause then we will consider this pause successful.
@@ -147,8 +148,9 @@
g1h->do_collection_pause_at_safepoint(_target_pause_time_ms);
if (_pause_succeeded && _word_size > 0) {
// An allocation had been requested.
- _result = g1h->attempt_allocation_at_safepoint(_word_size, allocation_context(),
- true /* expect_null_cur_alloc_region */);
+ _result = g1h->attempt_allocation_at_safepoint(_word_size,
+ allocation_context(),
+ true /* expect_null_cur_alloc_region */);
} else {
assert(_result == NULL, "invariant");
if (!_pause_succeeded) {
--- a/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp Thu Aug 20 12:29:58 2015 -0700
+++ b/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp Wed Jul 05 20:46:25 2017 +0200
@@ -1303,7 +1303,7 @@
if (handler_index < 0) {
if (PrintSignatureHandlers && (handler != Interpreter::slow_signature_handler())) {
tty->cr();
- tty->print_cr("argument handler #%d at "PTR_FORMAT" for fingerprint " UINT64_FORMAT,
+ tty->print_cr("argument handler #%d at " PTR_FORMAT " for fingerprint " UINT64_FORMAT,
_handlers->length(),
handler,
fingerprint);
@@ -1313,7 +1313,7 @@
} else {
if (PrintSignatureHandlers) {
tty->cr();
- tty->print_cr("duplicate argument handler #%d for fingerprint " UINT64_FORMAT "(old: "PTR_FORMAT", new : "PTR_FORMAT")",
+ tty->print_cr("duplicate argument handler #%d for fingerprint " UINT64_FORMAT "(old: " PTR_FORMAT ", new : " PTR_FORMAT ")",
_handlers->length(),
fingerprint,
_handlers->at(handler_index),
--- a/hotspot/src/share/vm/interpreter/linkResolver.cpp Thu Aug 20 12:29:58 2015 -0700
+++ b/hotspot/src/share/vm/interpreter/linkResolver.cpp Wed Jul 05 20:46:25 2017 +0200
@@ -379,7 +379,8 @@
if (!resolved_method->is_abstract() &&
(InstanceKlass::cast(klass())->default_methods() != NULL)) {
int index = InstanceKlass::find_method_index(InstanceKlass::cast(klass())->default_methods(),
- name, signature, Klass::find_overpass, Klass::find_static);
+ name, signature, Klass::find_overpass,
+ Klass::find_static, Klass::find_private);
if (index >= 0 ) {
vtable_index = InstanceKlass::cast(klass())->default_vtable_indices()->at(index);
}
@@ -1189,7 +1190,7 @@
assert(resolved_method->method_holder()->is_linked(), "must be linked");
// do lookup based on receiver klass using the vtable index
- if (resolved_method->method_holder()->is_interface()) { // miranda method
+ if (resolved_method->method_holder()->is_interface()) { // default or miranda method
vtable_index = vtable_index_of_interface_method(resolved_klass,
resolved_method);
assert(vtable_index >= 0 , "we should have valid vtable index at this point");
@@ -1198,7 +1199,7 @@
selected_method = methodHandle(THREAD, inst->method_at_vtable(vtable_index));
} else {
// at this point we are sure that resolved_method is virtual and not
- // a miranda method; therefore, it must have a valid vtable index.
+ // a default or miranda method; therefore, it must have a valid vtable index.
assert(!resolved_method->has_itable_index(), "");
vtable_index = resolved_method->vtable_index();
// We could get a negative vtable_index for final methods,
--- a/hotspot/src/share/vm/oops/instanceKlass.cpp Thu Aug 20 12:29:58 2015 -0700
+++ b/hotspot/src/share/vm/oops/instanceKlass.cpp Wed Jul 05 20:46:25 2017 +0200
@@ -1381,12 +1381,14 @@
// find_method looks up the name/signature in the local methods array
Method* InstanceKlass::find_method(Symbol* name, Symbol* signature) const {
- return find_method_impl(name, signature, find_overpass, find_static);
+ return find_method_impl(name, signature, find_overpass, find_static, find_private);
}
Method* InstanceKlass::find_method_impl(Symbol* name, Symbol* signature,
- OverpassLookupMode overpass_mode, StaticLookupMode static_mode) const {
- return InstanceKlass::find_method_impl(methods(), name, signature, overpass_mode, static_mode);
+ OverpassLookupMode overpass_mode,
+ StaticLookupMode static_mode,
+ PrivateLookupMode private_mode) const {
+ return InstanceKlass::find_method_impl(methods(), name, signature, overpass_mode, static_mode, private_mode);
}
// find_instance_method looks up the name/signature in the local methods array
@@ -1394,7 +1396,7 @@
Method* InstanceKlass::find_instance_method(
Array<Method*>* methods, Symbol* name, Symbol* signature) {
Method* meth = InstanceKlass::find_method_impl(methods, name, signature,
- find_overpass, skip_static);
+ find_overpass, skip_static, find_private);
assert(((meth == NULL) || !meth->is_static()), "find_instance_method should have skipped statics");
return meth;
}
@@ -1405,22 +1407,51 @@
return InstanceKlass::find_instance_method(methods(), name, signature);
}
+// Find looks up the name/signature in the local methods array
+// and filters on the overpass, static and private flags
+// This returns the first one found
+// note that the local methods array can have up to one overpass, one static
+// and one instance (private or not) with the same name/signature
+Method* InstanceKlass::find_local_method(Symbol* name, Symbol* signature,
+ OverpassLookupMode overpass_mode,
+ StaticLookupMode static_mode,
+ PrivateLookupMode private_mode) const {
+ return InstanceKlass::find_method_impl(methods(), name, signature, overpass_mode, static_mode, private_mode);
+}
+
+// Find looks up the name/signature in the local methods array
+// and filters on the overpass, static and private flags
+// This returns the first one found
+// note that the local methods array can have up to one overpass, one static
+// and one instance (private or not) with the same name/signature
+Method* InstanceKlass::find_local_method(Array<Method*>* methods,
+ Symbol* name, Symbol* signature,
+ OverpassLookupMode overpass_mode,
+ StaticLookupMode static_mode,
+ PrivateLookupMode private_mode) {
+ return InstanceKlass::find_method_impl(methods, name, signature, overpass_mode, static_mode, private_mode);
+}
+
+
// find_method looks up the name/signature in the local methods array
Method* InstanceKlass::find_method(
Array<Method*>* methods, Symbol* name, Symbol* signature) {
- return InstanceKlass::find_method_impl(methods, name, signature, find_overpass, find_static);
+ return InstanceKlass::find_method_impl(methods, name, signature, find_overpass, find_static, find_private);
}
Method* InstanceKlass::find_method_impl(
- Array<Method*>* methods, Symbol* name, Symbol* signature, OverpassLookupMode overpass_mode, StaticLookupMode static_mode) {
- int hit = find_method_index(methods, name, signature, overpass_mode, static_mode);
+ Array<Method*>* methods, Symbol* name, Symbol* signature,
+ OverpassLookupMode overpass_mode, StaticLookupMode static_mode,
+ PrivateLookupMode private_mode) {
+ int hit = find_method_index(methods, name, signature, overpass_mode, static_mode, private_mode);
return hit >= 0 ? methods->at(hit): NULL;
}
-bool InstanceKlass::method_matches(Method* m, Symbol* signature, bool skipping_overpass, bool skipping_static) {
- return (m->signature() == signature) &&
+bool InstanceKlass::method_matches(Method* m, Symbol* signature, bool skipping_overpass, bool skipping_static, bool skipping_private) {
+ return ((m->signature() == signature) &&
(!skipping_overpass || !m->is_overpass()) &&
- (!skipping_static || !m->is_static());
+ (!skipping_static || !m->is_static()) &&
+ (!skipping_private || !m->is_private()));
}
// Used directly for default_methods to find the index into the
@@ -1430,17 +1461,25 @@
// the search continues to find a potential non-overpass match. This capability
// is important during method resolution to prefer a static method, for example,
// over an overpass method.
+// There is the possibility in any _method's array to have the same name/signature
+// for a static method, an overpass method and a local instance method
+// To correctly catch a given method, the search criteria may need
+// to explicitly skip the other two. For local instance methods, it
+// is often necessary to skip private methods
int InstanceKlass::find_method_index(
- Array<Method*>* methods, Symbol* name, Symbol* signature, OverpassLookupMode overpass_mode, StaticLookupMode static_mode) {
+ Array<Method*>* methods, Symbol* name, Symbol* signature,
+ OverpassLookupMode overpass_mode, StaticLookupMode static_mode,
+ PrivateLookupMode private_mode) {
bool skipping_overpass = (overpass_mode == skip_overpass);
bool skipping_static = (static_mode == skip_static);
+ bool skipping_private = (private_mode == skip_private);
int hit = binary_search(methods, name);
if (hit != -1) {
Method* m = methods->at(hit);
// Do linear search to find matching signature. First, quick check
// for common case, ignoring overpasses if requested.
- if (method_matches(m, signature, skipping_overpass, skipping_static)) return hit;
+ if (method_matches(m, signature, skipping_overpass, skipping_static, skipping_private)) return hit;
// search downwards through overloaded methods
int i;
@@ -1448,18 +1487,18 @@
Method* m = methods->at(i);
assert(m->is_method(), "must be method");
if (m->name() != name) break;
- if (method_matches(m, signature, skipping_overpass, skipping_static)) return i;
+ if (method_matches(m, signature, skipping_overpass, skipping_static, skipping_private)) return i;
}
// search upwards
for (i = hit + 1; i < methods->length(); ++i) {
Method* m = methods->at(i);
assert(m->is_method(), "must be method");
if (m->name() != name) break;
- if (method_matches(m, signature, skipping_overpass, skipping_static)) return i;
+ if (method_matches(m, signature, skipping_overpass, skipping_static, skipping_private)) return i;
}
// not found
#ifdef ASSERT
- int index = (skipping_overpass || skipping_static) ? -1 : linear_search(methods, name, signature);
+ int index = (skipping_overpass || skipping_static || skipping_private) ? -1 : linear_search(methods, name, signature);
assert(index == -1, err_msg("binary search should have found entry %d", index));
#endif
}
@@ -1489,7 +1528,7 @@
OverpassLookupMode overpass_local_mode = overpass_mode;
Klass* klass = const_cast<InstanceKlass*>(this);
while (klass != NULL) {
- Method* method = InstanceKlass::cast(klass)->find_method_impl(name, signature, overpass_local_mode, find_static);
+ Method* method = InstanceKlass::cast(klass)->find_method_impl(name, signature, overpass_local_mode, find_static, find_private);
if (method != NULL) {
return method;
}
--- a/hotspot/src/share/vm/oops/instanceKlass.hpp Thu Aug 20 12:29:58 2015 -0700
+++ b/hotspot/src/share/vm/oops/instanceKlass.hpp Wed Jul 05 20:46:25 2017 +0200
@@ -503,12 +503,28 @@
Method* find_instance_method(Symbol* name, Symbol* signature);
static Method* find_instance_method(Array<Method*>* methods, Symbol* name, Symbol* signature);
- // true if method matches signature and conforms to skipping_X conditions.
- static bool method_matches(Method* m, Symbol* signature, bool skipping_overpass, bool skipping_static);
+ // find a local method (returns NULL if not found)
+ Method* find_local_method(Symbol* name, Symbol* signature,
+ OverpassLookupMode overpass_mode,
+ StaticLookupMode static_mode,
+ PrivateLookupMode private_mode) const;
- // find a local method index in default_methods (returns -1 if not found)
- static int find_method_index(Array<Method*>* methods, Symbol* name, Symbol* signature,
- OverpassLookupMode overpass_mode, StaticLookupMode static_mode);
+ // find a local method from given methods array (returns NULL if not found)
+ static Method* find_local_method(Array<Method*>* methods,
+ Symbol* name, Symbol* signature,
+ OverpassLookupMode overpass_mode,
+ StaticLookupMode static_mode,
+ PrivateLookupMode private_mode);
+
+ // true if method matches signature and conforms to skipping_X conditions.
+ static bool method_matches(Method* m, Symbol* signature, bool skipping_overpass, bool skipping_static, bool skipping_private);
+
+ // find a local method index in methods or default_methods (returns -1 if not found)
+ static int find_method_index(Array<Method*>* methods,
+ Symbol* name, Symbol* signature,
+ OverpassLookupMode overpass_mode,
+ StaticLookupMode static_mode,
+ PrivateLookupMode private_mode);
// lookup operation (returns NULL if not found)
Method* uncached_lookup_method(Symbol* name, Symbol* signature, OverpassLookupMode overpass_mode) const;
@@ -1153,9 +1169,14 @@
// find a local method (returns NULL if not found)
Method* find_method_impl(Symbol* name, Symbol* signature,
- OverpassLookupMode overpass_mode, StaticLookupMode static_mode) const;
- static Method* find_method_impl(Array<Method*>* methods, Symbol* name, Symbol* signature,
- OverpassLookupMode overpass_mode, StaticLookupMode static_mode);
+ OverpassLookupMode overpass_mode,
+ StaticLookupMode static_mode,
+ PrivateLookupMode private_mode) const;
+ static Method* find_method_impl(Array<Method*>* methods,
+ Symbol* name, Symbol* signature,
+ OverpassLookupMode overpass_mode,
+ StaticLookupMode static_mode,
+ PrivateLookupMode private_mode);
// Free CHeap allocated fields.
void release_C_heap_structures();
--- a/hotspot/src/share/vm/oops/klass.hpp Thu Aug 20 12:29:58 2015 -0700
+++ b/hotspot/src/share/vm/oops/klass.hpp Wed Jul 05 20:46:25 2017 +0200
@@ -161,6 +161,7 @@
enum DefaultsLookupMode { find_defaults, skip_defaults };
enum OverpassLookupMode { find_overpass, skip_overpass };
enum StaticLookupMode { find_static, skip_static };
+ enum PrivateLookupMode { find_private, skip_private };
bool is_klass() const volatile { return true; }
--- a/hotspot/src/share/vm/oops/klassVtable.cpp Thu Aug 20 12:29:58 2015 -0700
+++ b/hotspot/src/share/vm/oops/klassVtable.cpp Wed Jul 05 20:46:25 2017 +0200
@@ -683,7 +683,6 @@
if (mhk->is_interface()) {
assert(m->is_public(), "should be public");
assert(ik()->implements_interface(method_holder) , "this class should implement the interface");
- // the search could find a miranda or a default method
if (is_miranda(m, ik()->methods(), ik()->default_methods(), ik()->super())) {
return true;
}
@@ -691,25 +690,57 @@
return false;
}
-// check if a method is a miranda method, given a class's methods table,
-// its default_method table and its super
-// Miranda methods are calculated twice:
-// first: before vtable size calculation: including abstract and superinterface default
+// Check if a method is a miranda method, given a class's methods array,
+// its default_method table and its super class.
+// "Miranda" means an abstract non-private method that would not be
+// overridden for the local class.
+// A "miranda" method should only include non-private interface
+// instance methods, i.e. not private methods, not static methods,
+// not default methods (concrete interface methods), not overpass methods.
+// If a given class already has a local (including overpass) method, a
+// default method, or any of its superclasses has the same which would have
+// overridden an abstract method, then this is not a miranda method.
+//
+// Miranda methods are checked multiple times.
+// Pass 1: during class load/class file parsing: before vtable size calculation:
+// include superinterface abstract and default methods (non-private instance).
// We include potential default methods to give them space in the vtable.
-// During the first run, the default_methods list is empty
-// This is seen by default method creation
-// Second: recalculated during vtable initialization: only include abstract methods.
+// During the first run, the current instanceKlass has not yet been
+// created, the superclasses and superinterfaces do have instanceKlasses
+// but may not have vtables, the default_methods list is empty, no overpasses.
+// This is seen by default method creation.
+//
+// Pass 2: recalculated during vtable initialization: only include abstract methods.
+// The goal of pass 2 is to walk through the superinterfaces to see if any of
+// the superinterface methods (which were all abstract pre-default methods)
+// need to be added to the vtable.
+// With the addition of default methods, we have three new challenges:
+// overpasses, static interface methods and private interface methods.
+// Static and private interface methods do not get added to the vtable and
+// are not seen by the method resolution process, so we skip those.
+// Overpass methods are already in the vtable, so vtable lookup will
+// find them and we don't need to add a miranda method to the end of
+// the vtable. So we look for overpass methods and if they are found we
+// return false. Note that we inherit our superclasses vtable, so
+// the superclass' search also needs to use find_overpass so that if
+// one is found we return false.
+// False means - we don't need a miranda method added to the vtable.
+//
// During the second run, default_methods is set up, so concrete methods from
// superinterfaces with matching names/signatures to default_methods are already
// in the default_methods list and do not need to be appended to the vtable
-// as mirandas
-// This is seen by link resolution and selection.
-// "miranda" means not static, not defined by this class.
-// private methods in interfaces do not belong in the miranda list.
-// the caller must make sure that the method belongs to an interface implemented by the class
-// Miranda methods only include public interface instance methods
-// Not private methods, not static methods, not default == concrete abstract
-// Miranda methods also do not include overpass methods in interfaces
+// as mirandas. Abstract methods may already have been handled via
+// overpasses - either local or superclass overpasses, which may be
+// in the vtable already.
+//
+// Pass 3: They are also checked by link resolution and selection,
+// for invocation on a method (not interface method) reference that
+// resolves to a method with an interface as its method_holder.
+// Used as part of walking from the bottom of the vtable to find
+// the vtable index for the miranda method.
+//
+// Part of the Miranda Rights in the US mean that if you do not have
+// an attorney one will be appointed for you.
bool klassVtable::is_miranda(Method* m, Array<Method*>* class_methods,
Array<Method*>* default_methods, Klass* super) {
if (m->is_static() || m->is_private() || m->is_overpass()) {
@@ -717,44 +748,36 @@
}
Symbol* name = m->name();
Symbol* signature = m->signature();
- Method* mo;
- if ((mo = InstanceKlass::find_instance_method(class_methods, name, signature)) == NULL) {
- // did not find it in the method table of the current class
- if ((default_methods == NULL) ||
- InstanceKlass::find_method(default_methods, name, signature) == NULL) {
- if (super == NULL) {
- // super doesn't exist
- return true;
- }
-
- mo = InstanceKlass::cast(super)->lookup_method(name, signature);
- while (mo != NULL && mo->access_flags().is_static()
- && mo->method_holder() != NULL
- && mo->method_holder()->super() != NULL)
- {
- mo = mo->method_holder()->super()->uncached_lookup_method(name, signature, Klass::find_overpass);
- }
- if (mo == NULL || mo->access_flags().is_private() ) {
- // super class hierarchy does not implement it or protection is different
- return true;
- }
- }
- } else {
- // if the local class has a private method, the miranda will not
- // override it, so a vtable slot is needed
- if (mo->access_flags().is_private()) {
-
- // Second round, weed out any superinterface methods that turned
- // into default methods, i.e. were concrete not abstract in the end
- if ((default_methods == NULL) ||
- InstanceKlass::find_method(default_methods, name, signature) == NULL) {
- return true;
- }
- }
+ // First look in local methods to see if already covered
+ if (InstanceKlass::find_local_method(class_methods, name, signature,
+ Klass::find_overpass, Klass::skip_static, Klass::skip_private) != NULL)
+ {
+ return false;
}
- return false;
+ // Check local default methods
+ if ((default_methods != NULL) &&
+ (InstanceKlass::find_method(default_methods, name, signature) != NULL))
+ {
+ return false;
+ }
+
+ InstanceKlass* cursuper;
+ // Iterate on all superclasses, which should have instanceKlasses
+ // Note that we explicitly look for overpasses at each level.
+ // Overpasses may or may not exist for supers for pass 1,
+ // they should have been created for pass 2 and later.
+
+ for (cursuper = InstanceKlass::cast(super); cursuper != NULL; cursuper = (InstanceKlass*)cursuper->super())
+ {
+ if (cursuper->find_local_method(name, signature,
+ Klass::find_overpass, Klass::skip_static, Klass::skip_private) != NULL) {
+ return false;
+ }
+ }
+
+ return true;
}
// Scans current_interface_methods for miranda methods that do not
--- a/hotspot/src/share/vm/opto/block.cpp Thu Aug 20 12:29:58 2015 -0700
+++ b/hotspot/src/share/vm/opto/block.cpp Wed Jul 05 20:46:25 2017 +0200
@@ -393,7 +393,7 @@
VectorSet visited(a);
// Allocate stack with enough space to avoid frequent realloc
- Node_Stack nstack(a, C->unique() >> 1);
+ Node_Stack nstack(a, C->live_nodes() >> 1);
nstack.push(_root, 0);
uint sum = 0; // Counter for blocks
--- a/hotspot/src/share/vm/opto/cfgnode.cpp Thu Aug 20 12:29:58 2015 -0700
+++ b/hotspot/src/share/vm/opto/cfgnode.cpp Wed Jul 05 20:46:25 2017 +0200
@@ -802,7 +802,7 @@
Compile *C = igvn->C;
Arena *a = Thread::current()->resource_area();
Node_Array node_map = new Node_Array(a);
- Node_Stack stack(a, C->unique() >> 4);
+ Node_Stack stack(a, C->live_nodes() >> 4);
PhiNode *nphi = slice_memory(at);
igvn->register_new_node_with_optimizer( nphi );
node_map.map(_idx, nphi);
--- a/hotspot/src/share/vm/opto/compile.cpp Thu Aug 20 12:29:58 2015 -0700
+++ b/hotspot/src/share/vm/opto/compile.cpp Wed Jul 05 20:46:25 2017 +0200
@@ -3315,7 +3315,7 @@
// Visit everybody reachable!
// Allocate stack of size C->unique()/2 to avoid frequent realloc
- Node_Stack nstack(unique() >> 1);
+ Node_Stack nstack(live_nodes() >> 1);
final_graph_reshaping_walk(nstack, root(), frc);
// Check for unreachable (from below) code (i.e., infinite loops).
--- a/hotspot/src/share/vm/opto/domgraph.cpp Thu Aug 20 12:29:58 2015 -0700
+++ b/hotspot/src/share/vm/opto/domgraph.cpp Wed Jul 05 20:46:25 2017 +0200
@@ -507,7 +507,7 @@
// 'semi' as vertex to DFS mapping. Set 'parent' to DFS parent.
int NTarjan::DFS( NTarjan *ntarjan, VectorSet &visited, PhaseIdealLoop *pil, uint *dfsorder) {
// Allocate stack of size C->unique()/8 to avoid frequent realloc
- GrowableArray <Node *> dfstack(pil->C->unique() >> 3);
+ GrowableArray <Node *> dfstack(pil->C->live_nodes() >> 3);
Node *b = pil->C->root();
int dfsnum = 1;
dfsorder[b->_idx] = dfsnum; // Cache parent's dfsnum for a later use
--- a/hotspot/src/share/vm/opto/gcm.cpp Thu Aug 20 12:29:58 2015 -0700
+++ b/hotspot/src/share/vm/opto/gcm.cpp Wed Jul 05 20:46:25 2017 +0200
@@ -107,8 +107,8 @@
//------------------------------schedule_pinned_nodes--------------------------
// Set the basic block for Nodes pinned into blocks
void PhaseCFG::schedule_pinned_nodes(VectorSet &visited) {
- // Allocate node stack of size C->unique()+8 to avoid frequent realloc
- GrowableArray <Node *> spstack(C->unique() + 8);
+ // Allocate node stack of size C->live_nodes()+8 to avoid frequent realloc
+ GrowableArray <Node *> spstack(C->live_nodes() + 8);
spstack.push(_root);
while (spstack.is_nonempty()) {
Node* node = spstack.pop();
@@ -1310,7 +1310,7 @@
visited.Clear();
Node_List stack(arena);
// Pre-grow the list
- stack.map((C->unique() >> 1) + 16, NULL);
+ stack.map((C->live_nodes() >> 1) + 16, NULL);
if (!schedule_early(visited, stack)) {
// Bailout without retry
C->record_method_not_compilable("early schedule failed");
--- a/hotspot/src/share/vm/opto/loopTransform.cpp Thu Aug 20 12:29:58 2015 -0700
+++ b/hotspot/src/share/vm/opto/loopTransform.cpp Wed Jul 05 20:46:25 2017 +0200
@@ -1282,7 +1282,7 @@
if (C->do_vector_loop() && (PrintOpto && VerifyLoopOptimizations || TraceLoopOpts)) {
Arena* arena = Thread::current()->resource_area();
- Node_Stack stack(arena, C->unique() >> 2);
+ Node_Stack stack(arena, C->live_nodes() >> 2);
Node_List rpo_list;
VectorSet visited(arena);
visited.set(loop_head->_idx);
--- a/hotspot/src/share/vm/opto/loopnode.cpp Thu Aug 20 12:29:58 2015 -0700
+++ b/hotspot/src/share/vm/opto/loopnode.cpp Wed Jul 05 20:46:25 2017 +0200
@@ -2231,7 +2231,7 @@
// _nodes array holds the earliest legal controlling CFG node.
// Allocate stack with enough space to avoid frequent realloc
- int stack_size = (C->unique() >> 1) + 16; // (unique>>1)+16 from Java2D stats
+ int stack_size = (C->live_nodes() >> 1) + 16; // (live_nodes>>1)+16 from Java2D stats
Node_Stack nstack( a, stack_size );
visited.Clear();
@@ -2691,7 +2691,7 @@
}
}
if (_dom_stk == NULL) {
- uint init_size = C->unique() / 100; // Guess that 1/100 is a reasonable initial size.
+ uint init_size = C->live_nodes() / 100; // Guess that 1/100 is a reasonable initial size.
if (init_size < 10) init_size = 10;
_dom_stk = new GrowableArray<uint>(init_size);
}
@@ -2781,8 +2781,8 @@
// The sort is of size number-of-control-children, which generally limits
// it to size 2 (i.e., I just choose between my 2 target loops).
void PhaseIdealLoop::build_loop_tree() {
- // Allocate stack of size C->unique()/2 to avoid frequent realloc
- GrowableArray <Node *> bltstack(C->unique() >> 1);
+ // Allocate stack of size C->live_nodes()/2 to avoid frequent realloc
+ GrowableArray <Node *> bltstack(C->live_nodes() >> 1);
Node *n = C->root();
bltstack.push(n);
int pre_order = 1;
@@ -3672,7 +3672,7 @@
void PhaseIdealLoop::dump( ) const {
ResourceMark rm;
Arena* arena = Thread::current()->resource_area();
- Node_Stack stack(arena, C->unique() >> 2);
+ Node_Stack stack(arena, C->live_nodes() >> 2);
Node_List rpo_list;
VectorSet visited(arena);
visited.set(C->top()->_idx);
--- a/hotspot/src/share/vm/opto/matcher.cpp Thu Aug 20 12:29:58 2015 -0700
+++ b/hotspot/src/share/vm/opto/matcher.cpp Wed Jul 05 20:46:25 2017 +0200
@@ -2050,7 +2050,7 @@
// Set bits if Node is shared or otherwise a root
void Matcher::find_shared( Node *n ) {
// Allocate stack of size C->unique() * 2 to avoid frequent realloc
- MStack mstack(C->unique() * 2);
+ MStack mstack(C->live_nodes() * 2);
// Mark nodes as address_visited if they are inputs to an address expression
VectorSet address_visited(Thread::current()->resource_area());
mstack.push(n, Visit); // Don't need to pre-visit root node
--- a/hotspot/src/share/vm/opto/node.cpp Thu Aug 20 12:29:58 2015 -0700
+++ b/hotspot/src/share/vm/opto/node.cpp Wed Jul 05 20:46:25 2017 +0200
@@ -1799,7 +1799,7 @@
static void dump_nodes(const Node* start, int d, bool only_ctrl) {
if (NotANode(start)) return;
- GrowableArray <Node *> nstack(Compile::current()->unique());
+ GrowableArray <Node *> nstack(Compile::current()->live_nodes());
collect_nodes_i(&nstack, start, d, (uint) ABS(d), true, only_ctrl, false);
int end = nstack.length();
--- a/hotspot/src/share/vm/opto/phaseX.cpp Thu Aug 20 12:29:58 2015 -0700
+++ b/hotspot/src/share/vm/opto/phaseX.cpp Wed Jul 05 20:46:25 2017 +0200
@@ -791,7 +791,7 @@
//------------------------------PhaseIterGVN-----------------------------------
// Initialize hash table to fresh and clean for +VerifyOpto
PhaseIterGVN::PhaseIterGVN( PhaseIterGVN *igvn, const char *dummy ) : PhaseGVN(igvn,dummy), _worklist( ),
- _stack(C->unique() >> 1),
+ _stack(C->live_nodes() >> 1),
_delay_transform(false) {
}
@@ -808,7 +808,11 @@
// Initialize with previous PhaseGVN info from Parser
PhaseIterGVN::PhaseIterGVN( PhaseGVN *gvn ) : PhaseGVN(gvn),
_worklist(*C->for_igvn()),
- _stack(C->unique() >> 1),
+// TODO: Before incremental inlining it was allocated only once and it was fine. Now that
+// the constructor is used in incremental inlining, this consumes too much memory:
+// _stack(C->live_nodes() >> 1),
+// So, as a band-aid, we replace this by:
+ _stack(C->comp_arena(), 32),
_delay_transform(false)
{
uint max;
@@ -1638,7 +1642,7 @@
_nodes.map( n->_idx, new_node ); // Flag as having been cloned
// Allocate stack of size _nodes.Size()/2 to avoid frequent realloc
- GrowableArray <Node *> trstack(C->unique() >> 1);
+ GrowableArray <Node *> trstack(C->live_nodes() >> 1);
trstack.push(new_node); // Process children of cloned node
while ( trstack.is_nonempty() ) {
--- a/hotspot/src/share/vm/runtime/arguments.cpp Thu Aug 20 12:29:58 2015 -0700
+++ b/hotspot/src/share/vm/runtime/arguments.cpp Wed Jul 05 20:46:25 2017 +0200
@@ -2295,13 +2295,13 @@
}
// Checks if name in command-line argument -agent{lib,path}:name[=options]
-// represents a valid HPROF of JDWP agent. is_path==true denotes that we
+// represents a valid JDWP agent. is_path==true denotes that we
// are dealing with -agentpath (case where name is a path), otherwise with
// -agentlib
-bool valid_hprof_or_jdwp_agent(char *name, bool is_path) {
+bool valid_jdwp_agent(char *name, bool is_path) {
char *_name;
- const char *_hprof = "hprof", *_jdwp = "jdwp";
- size_t _len_hprof, _len_jdwp, _len_prefix;
+ const char *_jdwp = "jdwp";
+ size_t _len_jdwp, _len_prefix;
if (is_path) {
if ((_name = strrchr(name, (int) *os::file_separator())) == NULL) {
@@ -2316,13 +2316,9 @@
}
_name += _len_prefix;
- _len_hprof = strlen(_hprof);
_len_jdwp = strlen(_jdwp);
- if (strncmp(_name, _hprof, _len_hprof) == 0) {
- _name += _len_hprof;
- }
- else if (strncmp(_name, _jdwp, _len_jdwp) == 0) {
+ if (strncmp(_name, _jdwp, _len_jdwp) == 0) {
_name += _len_jdwp;
}
else {
@@ -2336,7 +2332,7 @@
return true;
}
- if (strcmp(name, _hprof) == 0 || strcmp(name, _jdwp) == 0) {
+ if (strcmp(name, _jdwp) == 0) {
return true;
}
@@ -2427,9 +2423,9 @@
options = (char*)memcpy(NEW_C_HEAP_ARRAY(char, len2, mtInternal), pos+1, len2);
}
#if !INCLUDE_JVMTI
- if ((strcmp(name, "hprof") == 0) || (strcmp(name, "jdwp") == 0)) {
+ if (strcmp(name, "jdwp") == 0) {
jio_fprintf(defaultStream::error_stream(),
- "Profiling and debugging agents are not supported in this VM\n");
+ "Debugging agents are not supported in this VM\n");
return JNI_ERR;
}
#endif // !INCLUDE_JVMTI
@@ -2449,9 +2445,9 @@
options = os::strdup_check_oom(pos + 1, mtInternal);
}
#if !INCLUDE_JVMTI
- if (valid_hprof_or_jdwp_agent(name, is_absolute_path)) {
+ if (valid_jdwp_agent(name, is_absolute_path)) {
jio_fprintf(defaultStream::error_stream(),
- "Profiling and debugging agents are not supported in this VM\n");
+ "Debugging agents are not supported in this VM\n");
return JNI_ERR;
}
#endif // !INCLUDE_JVMTI
@@ -3305,7 +3301,9 @@
if (scp_assembly_required) {
// Assemble the bootclasspath elements into the final path.
- Arguments::set_sysclasspath(scp_p->combined_path());
+ char *combined_path = scp_p->combined_path();
+ Arguments::set_sysclasspath(combined_path);
+ FREE_C_HEAP_ARRAY(char, combined_path);
}
// This must be done after all arguments have been processed.
--- a/hotspot/src/share/vm/runtime/os.cpp Thu Aug 20 12:29:58 2015 -0700
+++ b/hotspot/src/share/vm/runtime/os.cpp Wed Jul 05 20:46:25 2017 +0200
@@ -1271,6 +1271,7 @@
bool has_jimage = (os::stat(jimage, &st) == 0);
if (has_jimage) {
Arguments::set_sysclasspath(jimage);
+ FREE_C_HEAP_ARRAY(char, jimage);
return true;
}
FREE_C_HEAP_ARRAY(char, jimage);
@@ -1282,6 +1283,7 @@
sysclasspath = expand_entries_to_path(modules_dir, fileSep, pathSep);
}
}
+ FREE_C_HEAP_ARRAY(char, modules_dir);
// fallback to classes
if (sysclasspath == NULL)
@@ -1289,6 +1291,7 @@
if (sysclasspath == NULL) return false;
Arguments::set_sysclasspath(sysclasspath);
+ FREE_C_HEAP_ARRAY(char, sysclasspath);
return true;
}
--- a/hotspot/src/share/vm/runtime/threadLocalStorage.cpp Thu Aug 20 12:29:58 2015 -0700
+++ b/hotspot/src/share/vm/runtime/threadLocalStorage.cpp Wed Jul 05 20:46:25 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -27,6 +27,11 @@
#include "runtime/thread.inline.hpp"
#include "runtime/threadLocalStorage.hpp"
+// Solaris no longer has this kind of ThreadLocalStorage implementation.
+// This will be removed from all platforms in the near future.
+
+#ifndef SOLARIS
+
// static member initialization
int ThreadLocalStorage::_thread_index = -1;
@@ -54,3 +59,5 @@
bool ThreadLocalStorage::is_initialized() {
return (thread_index() != -1);
}
+
+#endif // SOLARIS
--- a/hotspot/src/share/vm/runtime/threadLocalStorage.hpp Thu Aug 20 12:29:58 2015 -0700
+++ b/hotspot/src/share/vm/runtime/threadLocalStorage.hpp Wed Jul 05 20:46:25 2017 +0200
@@ -38,10 +38,14 @@
extern "C" uintptr_t _raw_thread_id();
class ThreadLocalStorage : AllStatic {
+
+ // Exported API
public:
static void set_thread(Thread* thread);
static Thread* get_thread_slow();
static void invalidate_all() { pd_invalidate_all(); }
+ static void init();
+ static bool is_initialized();
// Machine dependent stuff
#ifdef TARGET_OS_ARCH_linux_x86
@@ -81,17 +85,12 @@
# include "threadLS_bsd_zero.hpp"
#endif
-
+#ifndef SOLARIS
public:
// Accessor
static inline int thread_index() { return _thread_index; }
static inline void set_thread_index(int index) { _thread_index = index; }
- // Initialization
- // Called explicitly from VMThread::activate_system instead of init_globals.
- static void init();
- static bool is_initialized();
-
private:
static int _thread_index;
@@ -100,6 +99,9 @@
// Processor dependent parts of set_thread and initialization
static void pd_set_thread(Thread* thread);
static void pd_init();
+
+#endif // SOLARIS
+
// Invalidate any thread cacheing or optimization schemes.
static void pd_invalidate_all();
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/SharedArchiveFile/BasicJarBuilder.java Wed Jul 05 20:46:25 2017 +0200
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @summary Simple jar builder
+ * Input: jarName className1 className2 ...
+ * do not specify extensions, just the names
+ * E.g. prot_domain ProtDomainA ProtDomainB
+ * Output: A jar containing compiled classes, placed in a test classes folder
+ */
+
+import jdk.test.lib.*;
+
+import java.io.File;
+import java.util.ArrayList;
+import sun.tools.jar.Main;
+
+public class BasicJarBuilder {
+ private static final String classDir = System.getProperty("test.classes");
+
+ public static void build(String jarName, String ...classNames)
+ throws Exception {
+
+ createSimpleJar(classDir, classDir + File.separator + jarName +
+ ".jar", classNames);
+ }
+
+ private static void createSimpleJar(String jarclassDir, String jarName,
+ String[] classNames) throws Exception {
+ ArrayList<String> args = new ArrayList<String>();
+ args.add("cf");
+ args.add(jarName);
+ addClassArgs(args, jarclassDir, classNames);
+ createJar(args);
+ }
+
+ private static void addClassArgs(ArrayList<String> args, String jarclassDir,
+ String[] classNames) {
+
+ for (String name : classNames) {
+ args.add("-C");
+ args.add(jarclassDir);
+ args.add(name + ".class");
+ }
+ }
+
+ private static void createJar(ArrayList<String> args) {
+ Main jarTool = new Main(System.out, System.err, "jar");
+ if (!jarTool.run(args.toArray(new String[1]))) {
+ throw new RuntimeException("jar operation failed");
+ }
+ }
+
+ // helpers
+ public static String getTestJar(String jar) {
+ File dir = new File(System.getProperty("test.classes", "."));
+ File jarFile = new File(dir, jar);
+ if (!jarFile.exists()) {
+ throw new RuntimeException("Cannot find " + jarFile.getPath());
+ }
+ if (!jarFile.isFile()) {
+ throw new RuntimeException("Not a regular file: " + jarFile.getPath());
+ }
+ return jarFile.getPath();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/SharedArchiveFile/SharedStrings.java Wed Jul 05 20:46:25 2017 +0200
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary Check to make sure that shared strings in the bootstrap CDS archive
+ * are actually shared
+ * Feature support: G1GC only, compressed oops/kptrs, 64-bit os, not on windows
+ * @requires (sun.arch.data.model != "32") & (os.family != "windows")
+ * @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true)
+ * @requires (vm.gc=="G1" | vm.gc=="null")
+ * @library /testlibrary /../../test/lib
+ * @modules java.base/sun.misc
+ * java.management
+ * @ignore - 8133180
+ * @build SharedStringsWb SharedStrings BasicJarBuilder
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * @run main SharedStrings
+ */
+
+import jdk.test.lib.*;
+
+public class SharedStrings {
+ public static void main(String[] args) throws Exception {
+ BasicJarBuilder.build("whitebox", "sun/hotspot/WhiteBox");
+
+ ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
+ "-XX:+UnlockDiagnosticVMOptions",
+ "-XX:SharedArchiveFile=./SharedStrings.jsa",
+ "-XX:+PrintSharedSpaces",
+ // Needed for bootclasspath match, for CDS to work with WhiteBox API
+ "-Xbootclasspath/a:" + BasicJarBuilder.getTestJar("whitebox.jar"),
+ "-Xshare:dump");
+
+ new OutputAnalyzer(pb.start())
+ .shouldContain("Loading classes to share")
+ .shouldContain("Shared string table stats")
+ .shouldHaveExitValue(0);
+
+ pb = ProcessTools.createJavaProcessBuilder(
+ "-XX:+UnlockDiagnosticVMOptions",
+ "-XX:SharedArchiveFile=./SharedStrings.jsa",
+ // these are required modes for shared strings
+ "-XX:+UseCompressedOops", "-XX:+UseG1GC",
+ // needed for access to white box test API
+ "-Xbootclasspath/a:" + BasicJarBuilder.getTestJar("whitebox.jar"),
+ "-XX:+UnlockDiagnosticVMOptions", "-XX:+WhiteBoxAPI",
+ "-Xshare:on", "-showversion", "SharedStringsWb");
+
+ OutputAnalyzer output = new OutputAnalyzer(pb.start());
+
+ try {
+ output.shouldContain("sharing");
+ output.shouldHaveExitValue(0);
+ } catch (RuntimeException e) {
+ output.shouldContain("Unable to use shared archive");
+ output.shouldHaveExitValue(1);
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/SharedArchiveFile/SharedStringsWb.java Wed Jul 05 20:46:25 2017 +0200
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import sun.hotspot.WhiteBox;
+
+// This class is used by the test SharedStrings.java
+// It should be launched in CDS mode
+public class SharedStringsWb {
+ public static void main(String[] args) throws Exception {
+ WhiteBox wb = WhiteBox.getWhiteBox();
+
+ if (wb.areSharedStringsIgnored()) {
+ System.out.println("Shared strings are ignored, assuming PASS");
+ return;
+ }
+
+ // The string "java" is known to be interened and added to CDS archive
+ String s = "java";
+ String internedS = s.intern();
+
+ if (wb.isShared(internedS)) {
+ System.out.println("Found shared string, result: PASS");
+ } else {
+ throw new RuntimeException("String is not shared, result: FAIL");
+ }
+ }
+}
+
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/lambda-features/TestStaticandInstance.java Wed Jul 05 20:46:25 2017 +0200
@@ -0,0 +1,272 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+/*
+ * @test
+ * @bug 8087342
+ * @summary Test linkresolver search static, instance and overpass duplicates
+ * @run main/othervm -Xverify:none TestStaticandInstance
+ */
+
+
+import java.util.*;
+import jdk.internal.org.objectweb.asm.*;
+import static jdk.internal.org.objectweb.asm.Opcodes.*;
+
+public class TestStaticandInstance {
+ static final String stringC = "C";
+ static final String stringD = "D";
+ static final String stringI = "I";
+
+ public static void main(String args[]) throws Throwable {
+ ClassLoader cl = new ClassLoader() {
+ public Class<?> loadClass(String name) throws ClassNotFoundException {
+ Class retClass;
+ if ((retClass = findLoadedClass(name)) != null) {
+ return retClass;
+ }
+ if (stringC.equals(name)) {
+ byte[] classFile=dumpC();
+ return defineClass(stringC, classFile, 0, classFile.length);
+ }
+ if (stringD.equals(name)) {
+ byte[] classFile=dumpD();
+ return defineClass(stringD, classFile, 0, classFile.length);
+ }
+ if (stringI.equals(name)) {
+ byte[] classFile=dumpI();
+ return defineClass(stringI, classFile, 0, classFile.length);
+ }
+ return super.loadClass(name);
+ }
+ };
+
+ Class classC = cl.loadClass(stringC);
+ Class classI = cl.loadClass(stringI);
+
+ try {
+ int staticret = (Integer)cl.loadClass(stringD).getDeclaredMethod("CallStatic").invoke(null);
+ if (staticret != 1) {
+ throw new RuntimeException("invokestatic failed to call correct method");
+ }
+ System.out.println("staticret: " + staticret); // should be 1
+
+ int invokeinterfaceret = (Integer)cl.loadClass(stringD).getDeclaredMethod("CallInterface").invoke(null);
+ if (invokeinterfaceret != 0) {
+ throw new RuntimeException(String.format("Expected java.lang.AbstractMethodError, got %d", invokeinterfaceret));
+ }
+ System.out.println("invokeinterfaceret: AbstractMethodError");
+
+ int invokevirtualret = (Integer)cl.loadClass(stringD).getDeclaredMethod("CallVirtual").invoke(null);
+ if (invokevirtualret != 0) {
+ throw new RuntimeException(String.format("Expected java.lang.IncompatibleClassChangeError, got %d", invokevirtualret));
+ }
+ System.out.println("invokevirtualret: IncompatibleClassChangeError");
+ } catch (java.lang.Throwable e) {
+ throw new RuntimeException("Unexpected exception: " + e.getMessage());
+ }
+ }
+
+/*
+interface I {
+ public int m(); // abstract
+ default int q() { return 3; } // trigger defmeth processing: C gets AME overpass
+}
+
+// C gets static, private and AME overpass m()I with -Xverify:none
+class C implements I {
+ static int m() { return 1;} // javac with "n()" and patch to "m()"
+ private int m() { return 2;} // javac with public and patch to private
+}
+
+public class D {
+ public static int CallStatic() {
+ int staticret = C.m(); // javac with "C.n" and patch to "C.m"
+ return staticret;
+ }
+ public static int CallInterface() throws AbstractMethodError{
+ try {
+ I myI = new C();
+ return myI.m();
+ } catch (java.lang.AbstractMethodError e) {
+ return 0; // for success
+ }
+ }
+ public static int CallVirtual() {
+ try {
+ C myC = new C();
+ return myC.m();
+ } catch (java.lang.IncompatibleClassChangeError e) {
+ return 0; // for success
+ }
+ }
+}
+*/
+
+ public static byte[] dumpC() {
+
+ ClassWriter cw = new ClassWriter(0);
+ FieldVisitor fv;
+ MethodVisitor mv;
+ AnnotationVisitor av0;
+
+ cw.visit(52, ACC_SUPER, "C", null, "java/lang/Object", new String[] { "I" });
+
+ {
+ mv = cw.visitMethod(0, "<init>", "()V", null, null);
+ mv.visitCode();
+ mv.visitVarInsn(ALOAD, 0);
+ mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
+ mv.visitInsn(RETURN);
+ mv.visitMaxs(1, 1);
+ mv.visitEnd();
+ }
+ {
+ mv = cw.visitMethod(ACC_STATIC, "m", "()I", null, null);
+ mv.visitCode();
+ mv.visitInsn(ICONST_1);
+ mv.visitInsn(IRETURN);
+ mv.visitMaxs(1, 0);
+ mv.visitEnd();
+ }
+ {
+ mv = cw.visitMethod(ACC_PRIVATE, "m", "()I", null, null);
+ mv.visitCode();
+ mv.visitInsn(ICONST_2);
+ mv.visitInsn(IRETURN);
+ mv.visitMaxs(1, 1);
+ mv.visitEnd();
+ }
+ cw.visitEnd();
+
+ return cw.toByteArray();
+ }
+
+ public static byte[] dumpD () {
+
+ ClassWriter cw = new ClassWriter(0);
+ FieldVisitor fv;
+ MethodVisitor mv;
+ AnnotationVisitor av0;
+
+ cw.visit(52, ACC_PUBLIC + ACC_SUPER, "D", null, "java/lang/Object", null);
+
+ {
+ mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
+ mv.visitCode();
+ mv.visitVarInsn(ALOAD, 0);
+ mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
+ mv.visitInsn(RETURN);
+ mv.visitMaxs(1, 1);
+ mv.visitEnd();
+ }
+ {
+ mv = cw.visitMethod(ACC_PUBLIC + ACC_STATIC, "CallStatic", "()I", null, null);
+ mv.visitCode();
+ mv.visitMethodInsn(INVOKESTATIC, "C", "m", "()I", false);
+ mv.visitVarInsn(ISTORE, 0);
+ mv.visitVarInsn(ILOAD, 0);
+ mv.visitInsn(IRETURN);
+ mv.visitMaxs(1, 1);
+ mv.visitEnd();
+ }
+ {
+ mv = cw.visitMethod(ACC_PUBLIC + ACC_STATIC, "CallInterface", "()I", null, new String[] { "java/lang/AbstractMethodError" });
+ mv.visitCode();
+ Label l0 = new Label();
+ Label l1 = new Label();
+ Label l2 = new Label();
+ mv.visitTryCatchBlock(l0, l1, l2, "java/lang/AbstractMethodError");
+ mv.visitLabel(l0);
+ mv.visitTypeInsn(NEW, "C");
+ mv.visitInsn(DUP);
+ mv.visitMethodInsn(INVOKESPECIAL, "C", "<init>", "()V", false);
+ mv.visitVarInsn(ASTORE, 0);
+ mv.visitVarInsn(ALOAD, 0);
+ mv.visitMethodInsn(INVOKEINTERFACE, "I", "m", "()I", true);
+ mv.visitLabel(l1);
+ mv.visitInsn(IRETURN);
+ mv.visitLabel(l2);
+ mv.visitFrame(Opcodes.F_SAME1, 0, null, 1, new Object[] {"java/lang/AbstractMethodError"});
+ mv.visitVarInsn(ASTORE, 0);
+ mv.visitInsn(ICONST_0);
+ mv.visitInsn(IRETURN);
+ mv.visitMaxs(2, 1);
+ mv.visitEnd();
+ }
+ {
+ mv = cw.visitMethod(ACC_PUBLIC + ACC_STATIC, "CallVirtual", "()I", null, null);
+ mv.visitCode();
+ Label l0 = new Label();
+ Label l1 = new Label();
+ Label l2 = new Label();
+ mv.visitTryCatchBlock(l0, l1, l2, "java/lang/IncompatibleClassChangeError");
+ mv.visitLabel(l0);
+ mv.visitTypeInsn(NEW, "C");
+ mv.visitInsn(DUP);
+ mv.visitMethodInsn(INVOKESPECIAL, "C", "<init>", "()V", false);
+ mv.visitVarInsn(ASTORE, 0);
+ mv.visitVarInsn(ALOAD, 0);
+ mv.visitMethodInsn(INVOKEVIRTUAL, "C", "m", "()I", false);
+ mv.visitLabel(l1);
+ mv.visitInsn(IRETURN);
+ mv.visitLabel(l2);
+ mv.visitFrame(Opcodes.F_SAME1, 0, null, 1, new Object[] {"java/lang/IncompatibleClassChangeError"});
+ mv.visitVarInsn(ASTORE, 0);
+ mv.visitInsn(ICONST_0);
+ mv.visitInsn(IRETURN);
+ mv.visitMaxs(2, 1);
+ mv.visitEnd();
+ }
+ cw.visitEnd();
+
+ return cw.toByteArray();
+ }
+
+ public static byte[] dumpI() {
+
+ ClassWriter cw = new ClassWriter(0);
+ FieldVisitor fv;
+ MethodVisitor mv;
+ AnnotationVisitor av0;
+
+ cw.visit(52, ACC_ABSTRACT + ACC_INTERFACE, "I", null, "java/lang/Object", null);
+
+ {
+ mv = cw.visitMethod(ACC_PUBLIC + ACC_ABSTRACT, "m", "()I", null, null);
+ mv.visitEnd();
+ }
+ {
+ mv = cw.visitMethod(ACC_PUBLIC, "q", "()I", null, null);
+ mv.visitCode();
+ mv.visitInsn(ICONST_3);
+ mv.visitInsn(IRETURN);
+ mv.visitMaxs(1, 1);
+ mv.visitEnd();
+ }
+ cw.visitEnd();
+
+ return cw.toByteArray();
+ }
+}
--- a/jdk/.hgtags Thu Aug 20 12:29:58 2015 -0700
+++ b/jdk/.hgtags Wed Jul 05 20:46:25 2017 +0200
@@ -320,3 +320,4 @@
4dd09cb5f7c2a2a23a9958ea7a602dd74d5709b2 jdk9-b75
4526c0da8fb362eebd7e88f4d44e86858cf9b80b jdk9-b76
7fd081100f48828431e7c1bff65c906ee759069b jdk9-b77
+0940ce86c614458f5bdd72278b190abbf36b7b45 jdk9-b78
--- a/jdk/make/copy/Copy-jdk.hprof.agent.gmk Thu Aug 20 12:29:58 2015 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,37 +0,0 @@
-#
-# Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-#
-# This code is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License version 2 only, as
-# published by the Free Software Foundation. Oracle designates this
-# particular file as subject to the "Classpath" exception as provided
-# by Oracle in the LICENSE file that accompanied this code.
-#
-# This code is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-# version 2 for more details (a copy is included in the LICENSE file that
-# accompanied this code).
-#
-# You should have received a copy of the GNU General Public License version
-# 2 along with this work; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
-# or visit www.oracle.com if you need additional information or have any
-# questions.
-#
-
-include CopyCommon.gmk
-
-################################################################################
-
-HPROF_SRC := $(JDK_TOPDIR)/src/jdk.hprof.agent/share/native/libhprof/jvm.hprof.txt
-
-$(LIB_DST_DIR)/jvm.hprof.txt: $(HPROF_SRC)
- $(call install-file)
-
-TARGETS := $(LIB_DST_DIR)/jvm.hprof.txt
-
-################################################################################
--- a/jdk/make/data/tzdata/VERSION Thu Aug 20 12:29:58 2015 -0700
+++ b/jdk/make/data/tzdata/VERSION Wed Jul 05 20:46:25 2017 +0200
@@ -21,4 +21,4 @@
# or visit www.oracle.com if you need additional information or have any
# questions.
#
-tzdata2015e
+tzdata2015f
--- a/jdk/make/data/tzdata/africa Thu Aug 20 12:29:58 2015 -0700
+++ b/jdk/make/data/tzdata/africa Wed Jul 05 20:46:25 2017 +0200
@@ -561,7 +561,7 @@
# From Alex Krivenyshev (2008-07-11):
# Seems that English language article "The revival of daylight saving
-# time: Energy conservation?"-# No. 16578 (07/11/2008) was originally
+# time: Energy conservation?"- No. 16578 (07/11/2008) was originally
# published on Monday, June 30, 2008...
#
# I guess that article in French "Le gouvernement avance l'introduction
@@ -693,7 +693,7 @@
# Here is a link to official document from Royaume du Maroc Premier Ministre,
# Ministère de la Modernisation des Secteurs Publics
#
-# Under Article 1 of Royal Decree No. 455-67 of Act 23 safar 1387 (2 june 1967)
+# Under Article 1 of Royal Decree No. 455-67 of Act 23 safar 1387 (2 June 1967)
# concerning the amendment of the legal time, the Ministry of Modernization of
# Public Sectors announced that the official time in the Kingdom will be
# advanced 60 minutes from Sunday 31 May 2009 at midnight.
--- a/jdk/make/data/tzdata/asia Thu Aug 20 12:29:58 2015 -0700
+++ b/jdk/make/data/tzdata/asia Wed Jul 05 20:46:25 2017 +0200
@@ -29,7 +29,7 @@
# tz@iana.org for general use in the future). For more, please see
# the file CONTRIBUTING in the tz distribution.
-# From Paul Eggert (2014-10-31):
+# From Paul Eggert (2015-08-08):
#
# Unless otherwise specified, the source for data through 1990 is:
# Thomas G. Shanks and Rique Pottenger, The International Atlas (6th edition),
@@ -66,7 +66,7 @@
# 2:00 EET EEST Eastern European Time
# 2:00 IST IDT Israel
# 3:00 AST ADT Arabia*
-# 3:30 IRST IRDT Iran
+# 3:30 IRST IRDT Iran*
# 4:00 GST Gulf*
# 5:30 IST India
# 7:00 ICT Indochina, most times and locations*
@@ -75,10 +75,11 @@
# 8:00 CST China
# 8:00 IDT Indochina, 1943-45, 1947-55, 1960-75 (some locations)*
# 8:00 JWST Western Standard Time (Japan, 1896/1937)*
+# 8:30 KST KDT Korea when at +0830*
# 9:00 JCST Central Standard Time (Japan, 1896/1937)
# 9:00 WIT east Indonesia (Waktu Indonesia Timur)
# 9:00 JST JDT Japan
-# 9:00 KST KDT Korea
+# 9:00 KST KDT Korea when at +09
# 9:30 ACST Australian Central Standard Time
#
# See the 'europe' file for Russia and Turkey in Asia.
@@ -1050,7 +1051,7 @@
#
# From Roozbeh Pournader (2007-11-05):
# This is quoted from Official Gazette of the Islamic Republic of
-# Iran, Volume 63, Number 18242, dated Tuesday 1386/6/24
+# Iran, Volume 63, No. 18242, dated Tuesday 1386/6/24
# [2007-10-16]. I am doing the best translation I can:...
# The official time of the country will be moved forward for one hour
# on the 24 hours of the first day of the month of Farvardin and will
@@ -1580,7 +1581,7 @@
# - Qyzylorda switched from +5:00 to +6:00 on 1992-01-19 02:00.
# - Oral switched from +5:00 to +4:00 in spring 1989.
-# From Kazakhstan Embassy's News Bulletin #11
+# From Kazakhstan Embassy's News Bulletin No. 11
# <http://www.kazsociety.org.uk/news/2005/03/30.htm> (2005-03-21):
# The Government of Kazakhstan passed a resolution March 15 abolishing
# daylight saving time citing lack of economic benefits and health
@@ -1734,6 +1735,17 @@
#
# For Pyongyang we have no information; guess no changes since World War II.
+# From Steffen Thorsen (2015-08-07):
+# According to many news sources, North Korea is going to change to
+# the 8:30 time zone on August 15, one example:
+# http://www.bbc.com/news/world-asia-33815049
+#
+# From Paul Eggert (2015-08-07):
+# No transition time is specified; assume 00:00.
+# There is no common English-language abbreviation for this time zone.
+# Use %z rather than invent one. We can't assume %z works everywhere yet,
+# so for now substitute its output manually.
+
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
Zone Asia/Seoul 8:27:52 - LMT 1908 Apr 1
8:30 - KST 1912 Jan 1
@@ -1746,7 +1758,8 @@
8:30 - KST 1912 Jan 1
9:00 - JCST 1937 Oct 1
9:00 - JST 1945 Aug 24
- 9:00 - KST
+ 9:00 - KST 2015 Aug 15
+ 8:30 - KST
###############################################################################
--- a/jdk/make/data/tzdata/europe Thu Aug 20 12:29:58 2015 -0700
+++ b/jdk/make/data/tzdata/europe Wed Jul 05 20:46:25 2017 +0200
@@ -216,11 +216,14 @@
# republished in Finest Hour (Spring 2002) 1(114):26
# http://www.winstonchurchill.org/images/finesthour/Vol.01%20No.114.pdf
-# From Paul Eggert (1996-09-03):
+# From Paul Eggert (2015-08-08):
# The OED Supplement says that the English originally said "Daylight Saving"
# when they were debating the adoption of DST in 1908; but by 1916 this
# term appears only in quotes taken from DST's opponents, whereas the
# proponents (who eventually won the argument) are quoted as using "Summer".
+# The term "Summer Time" was introduced by Herbert Samuel, Home Secretary; see:
+# Viscount Samuel. Leisure in a Democracy. Cambridge University Press
+# ISBN 978-1-107-49471-8 (1949, reissued 2015), p 8.
# From Arthur David Olson (1989-01-19):
# A source at the British Information Office in New York avers that it's
@@ -366,7 +369,7 @@
# From an anonymous contributor (1996-06-02):
# The law governing time in Ireland is under Statutory Instrument SI 395/94,
-# which gives force to European Union 7th Council Directive # 94/21/EC.
+# which gives force to European Union 7th Council Directive No. 94/21/EC.
# Under this directive, the Minister for Justice in Ireland makes appropriate
# regulations. I spoke this morning with the Secretary of the Department of
# Justice (tel +353 1 678 9711) who confirmed to me that the correct name is
@@ -615,11 +618,11 @@
Rule Russia 1921 only - Mar 20 23:00 2:00 MSM # Midsummer
Rule Russia 1921 only - Sep 1 0:00 1:00 MSD
Rule Russia 1921 only - Oct 1 0:00 0 -
-# Act No.925 of the Council of Ministers of the USSR (1980-10-24):
+# Act No. 925 of the Council of Ministers of the USSR (1980-10-24):
Rule Russia 1981 1984 - Apr 1 0:00 1:00 S
Rule Russia 1981 1983 - Oct 1 0:00 0 -
-# Act No.967 of the Council of Ministers of the USSR (1984-09-13), repeated in
-# Act No.227 of the Council of Ministers of the USSR (1989-03-14):
+# Act No. 967 of the Council of Ministers of the USSR (1984-09-13), repeated in
+# Act No. 227 of the Council of Ministers of the USSR (1989-03-14):
Rule Russia 1984 1991 - Sep lastSun 2:00s 0 -
Rule Russia 1985 1991 - Mar lastSun 2:00s 1:00 S
#
@@ -851,7 +854,7 @@
# Bulgaria
#
# From Plamen Simenov via Steffen Thorsen (1999-09-09):
-# A document of Government of Bulgaria (No.94/1997) says:
+# A document of Government of Bulgaria (No. 94/1997) says:
# EET -> EETDST is in 03:00 Local time in last Sunday of March ...
# EETDST -> EET is in 04:00 Local time in last Sunday of October
#
@@ -868,7 +871,7 @@
1:00 C-Eur CE%sT 1945
1:00 - CET 1945 Apr 2 3:00
2:00 - EET 1979 Mar 31 23:00
- 2:00 Bulg EE%sT 1982 Sep 26 2:00
+ 2:00 Bulg EE%sT 1982 Sep 26 3:00
2:00 C-Eur EE%sT 1991
2:00 E-Eur EE%sT 1997
2:00 EU EE%sT
@@ -1085,8 +1088,8 @@
# after that.
# From Mart Oruaas (2000-01-29):
-# Regulation no. 301 (1999-10-12) obsoletes previous regulation
-# no. 206 (1998-09-22) and thus sticks Estonia to +02:00 GMT for all
+# Regulation No. 301 (1999-10-12) obsoletes previous regulation
+# No. 206 (1998-09-22) and thus sticks Estonia to +02:00 GMT for all
# the year round. The regulation is effective 1999-11-01.
# From Toomas Soome (2002-02-21):
@@ -1107,7 +1110,7 @@
3:00 Russia MSK/MSD 1989 Mar 26 2:00s
2:00 1:00 EEST 1989 Sep 24 2:00s
2:00 C-Eur EE%sT 1998 Sep 22
- 2:00 EU EE%sT 1999 Nov 1
+ 2:00 EU EE%sT 1999 Oct 31 4:00
2:00 - EET 2002 Feb 21
2:00 EU EE%sT
@@ -1550,21 +1553,21 @@
# correct data in juridical acts and I found some juridical documents about
# changes in the counting of time in Latvia from 1981....
#
-# Act No.35 of the Council of Ministers of Latvian SSR of 1981-01-22 ...
-# according to the Act No.925 of the Council of Ministers of USSR of 1980-10-24
+# Act No. 35 of the Council of Ministers of Latvian SSR of 1981-01-22 ...
+# according to the Act No. 925 of the Council of Ministers of USSR of 1980-10-24
# ...: all year round the time of 2nd time zone + 1 hour, in addition turning
# the hands of the clock 1 hour forward on 1 April at 00:00 (GMT 31 March 21:00)
# and 1 hour backward on the 1 October at 00:00 (GMT 30 September 20:00).
#
-# Act No.592 of the Council of Ministers of Latvian SSR of 1984-09-24 ...
-# according to the Act No.967 of the Council of Ministers of USSR of 1984-09-13
+# Act No. 592 of the Council of Ministers of Latvian SSR of 1984-09-24 ...
+# according to the Act No. 967 of the Council of Ministers of USSR of 1984-09-13
# ...: all year round the time of 2nd time zone + 1 hour, in addition turning
# the hands of the clock 1 hour forward on the last Sunday of March at 02:00
# (GMT 23:00 on the previous day) and 1 hour backward on the last Sunday of
# September at 03:00 (GMT 23:00 on the previous day).
#
-# Act No.81 of the Council of Ministers of Latvian SSR of 1989-03-22 ...
-# according to the Act No.227 of the Council of Ministers of USSR of 1989-03-14
+# Act No. 81 of the Council of Ministers of Latvian SSR of 1989-03-22 ...
+# according to the Act No. 227 of the Council of Ministers of USSR of 1989-03-14
# ...: since the last Sunday of March 1989 in Lithuanian SSR, Latvian SSR,
# Estonian SSR and Kaliningrad region of Russian Federation all year round the
# time of 2nd time zone (Moscow time minus one hour). On the territory of Latvia
@@ -1581,7 +1584,7 @@
# From Andrei Ivanov (2000-03-06):
# This year Latvia will not switch to Daylight Savings Time (as specified in
# The Regulations of the Cabinet of Ministers of the Rep. of Latvia of
-# 29-Feb-2000 (#79) <http://www.lv-laiks.lv/wwwraksti/2000/071072/vd4.htm>,
+# 29-Feb-2000 (No. 79) <http://www.lv-laiks.lv/wwwraksti/2000/071072/vd4.htm>,
# in Latvian for subscribers only).
# From RFE/RL Newsline
@@ -1786,6 +1789,18 @@
# News from Moldova (in russian):
# http://ru.publika.md/link_317061.html
+# From Roman Tudos (2015-07-02):
+# http://lex.justice.md/index.php?action=view&view=doc&lang=1&id=355077
+# From Paul Eggert (2015-07-01):
+# The abovementioned official link to IGO1445-868/2014 states that
+# 2014-10-26's fallback transition occurred at 03:00 local time. Also,
+# http://www.trm.md/en/social/la-30-martie-vom-trece-la-ora-de-vara
+# says the 2014-03-30 spring-forward transition was at 02:00 local time.
+# Guess that since 1997 Moldova has switched one hour before the EU.
+
+# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
+Rule Moldova 1997 max - Mar lastSun 2:00 1:00 S
+Rule Moldova 1997 max - Oct lastSun 3:00 0 -
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
Zone Europe/Chisinau 1:55:20 - LMT 1880
@@ -1800,7 +1815,7 @@
2:00 Russia EE%sT 1992
2:00 E-Eur EE%sT 1997
# See Romania commentary for the guessed 1997 transition to EU rules.
- 2:00 EU EE%sT
+ 2:00 Moldova EE%sT
# Monaco
# Shanks & Pottenger give 0:09:20 for Paris Mean Time; go with Howse's
@@ -2146,7 +2161,7 @@
# Russia
# From Alexander Krivenyshev (2011-09-15):
-# Based on last Russian Government Decree # 725 on August 31, 2011
+# Based on last Russian Government Decree No. 725 on August 31, 2011
# (Government document
# http://www.government.ru/gov/results/16355/print/
# in Russian)
@@ -2156,7 +2171,7 @@
# http://www.worldtimezone.com/dst_news/dst_news_russia36.htm
# From Sanjeev Gupta (2011-09-27):
-# Scans of [Decree #23 of January 8, 1992] are available at:
+# Scans of [Decree No. 23 of January 8, 1992] are available at:
# http://government.consultant.ru/page.aspx?1223966
# They are in Cyrillic letters (presumably Russian).
@@ -2167,19 +2182,19 @@
# One source is
# http://government.ru/gov/results/16355/
# which, according to translate.google.com, begins "Decree of August 31,
-# 2011 No 725" and contains no other dates or "effective date" information.
+# 2011 No. 725" and contains no other dates or "effective date" information.
#
# Another source is
# http://www.rg.ru/2011/09/06/chas-zona-dok.html
# which, according to translate.google.com, begins "Resolution of the
# Government of the Russian Federation on August 31, 2011 N 725" and also
# contains "Date first official publication: September 6, 2011 Posted on:
-# in the 'RG' - Federal Issue number 5573 September 6, 2011" but which
+# in the 'RG' - Federal Issue No. 5573 September 6, 2011" but which
# does not contain any "effective date" information.
#
# Another source is
# http://en.wikipedia.org/wiki/Oymyakonsky_District#cite_note-RuTime-7
-# which, in note 8, contains "Resolution #725 of August 31, 2011...
+# which, in note 8, contains "Resolution No. 725 of August 31, 2011...
# Effective as of after 7 days following the day of the official publication"
# but which does not contain any reference to September 6, 2011.
#
@@ -2387,7 +2402,7 @@
# changed in May.
2:00 E-Eur EE%sT 1994 May
# From IATA SSIM (1994/1997), which also says that Kerch is still like Kiev.
- 3:00 E-Eur MSK/MSD 1996 Mar 31 3:00s
+ 3:00 E-Eur MSK/MSD 1996 Mar 31 0:00s
3:00 1:00 MSD 1996 Oct 27 3:00s
# IATA SSIM (1997-09) says Crimea switched to EET/EEST.
# Assume it happened in March by not changing the clocks.
@@ -2522,7 +2537,7 @@
# from current Russia Zone 6 - Krasnoyarsk Time Zone (KRA) UTC +0700
# to Russia Zone 5 - Novosibirsk Time Zone (NOV) UTC +0600
#
-# This is according to Government of Russia decree # 740, on September
+# This is according to Government of Russia decree No. 740, on September
# 14, 2009 "Application in the territory of the Kemerovo region the Fifth
# time zone." ("Russia Zone 5" or old "USSR Zone 5" is GMT +0600)
#
@@ -2945,7 +2960,7 @@
Zone Atlantic/Canary -1:01:36 - LMT 1922 Mar # Las Palmas de Gran C.
-1:00 - CANT 1946 Sep 30 1:00 # Canaries T
0:00 - WET 1980 Apr 6 0:00s
- 0:00 1:00 WEST 1980 Sep 28 0:00s
+ 0:00 1:00 WEST 1980 Sep 28 1:00u
0:00 EU WE%sT
# IATA SSIM (1996-09) says the Canaries switch at 2:00u, not 1:00u.
# Ignore this for now, as the Canaries are part of the EU.
@@ -3235,7 +3250,7 @@
# From Igor Karpov, who works for the Ukrainian Ministry of Justice,
# via Garrett Wollman (2003-01-27):
# BTW, I've found the official document on this matter. It's government
-# regulations number 509, May 13, 1996. In my poor translation it says:
+# regulations No. 509, May 13, 1996. In my poor translation it says:
# "Time in Ukraine is set to second timezone (Kiev time). Each last Sunday
# of March at 3am the time is changing to 4am and each last Sunday of
# October the time at 4am is changing to 3am"
@@ -3244,7 +3259,7 @@
# On September 20, 2011 the deputies of the Verkhovna Rada agreed to
# abolish the transfer clock to winter time.
#
-# Bill number 8330 of MP from the Party of Regions Oleg Nadoshi got
+# Bill No. 8330 of MP from the Party of Regions Oleg Nadoshi got
# approval from 266 deputies.
#
# Ukraine abolishes transfer back to the winter time (in Russian)
--- a/jdk/make/data/tzdata/leapseconds Thu Aug 20 12:29:58 2015 -0700
+++ b/jdk/make/data/tzdata/leapseconds Wed Jul 05 20:46:25 2017 +0200
@@ -79,5 +79,5 @@
Leap 2012 Jun 30 23:59:60 + S
Leap 2015 Jun 30 23:59:60 + S
-# Updated through IERS Bulletin C49
-# File expires on: 28 December 2015
+# Updated through IERS Bulletin C50
+# File expires on: 28 June 2016
--- a/jdk/make/data/tzdata/northamerica Thu Aug 20 12:29:58 2015 -0700
+++ b/jdk/make/data/tzdata/northamerica Wed Jul 05 20:46:25 2017 +0200
@@ -1258,10 +1258,19 @@
# west Labrador, Nova Scotia, Prince Edward I
-# From Paul Eggert (2006-03-22):
+# From Brian Inglis (2015-07-20):
+# From the historical weather station records available at:
+# https://weatherspark.com/history/28351/1971/Sydney-Nova-Scotia-Canada
+# Sydney shares the same time history as Glace Bay, so was
+# likely to be the same across the island....
+# Sydney, as the capital and most populous location, or Cape Breton, would
+# have been better names for the zone had we known this in 1996.
+
+# From Paul Eggert (2015-07-20):
# Shanks & Pottenger write that since 1970 most of this region has been like
# Halifax. Many locales did not observe peacetime DST until 1972;
-# Glace Bay, NS is the largest that we know of.
+# the Cape Breton area, represented by Glace Bay, is the largest we know of
+# (Glace Bay was perhaps not the best name choice but no point changing now).
# Shanks & Pottenger also write that Liverpool, NS was the only town
# in Canada to observe DST in 1971 but not 1970; for now we'll assume
# this is a typo.
@@ -1819,13 +1828,13 @@
# Exact date in October unknown; Sunday October 1 is a reasonable guess.
# 3. June 1918: switch to Pacific Daylight Time (GMT-7)
# Exact date in June unknown; Sunday June 2 is a reasonable guess.
-# note#1:
+# note 1:
# On Oct 27/1918 when daylight saving ended in the rest of Canada,
# Creston did not change its clocks.
-# note#2:
+# note 2:
# During WWII when the Federal Government legislated a mandatory clock change,
# Creston did not oblige.
-# note#3:
+# note 3:
# There is no guarantee that Creston will remain on Mountain Standard Time
# (UTC-7) forever.
# The subject was debated at least once this year by the town Council.
--- a/jdk/make/data/tzdata/southamerica Thu Aug 20 12:29:58 2015 -0700
+++ b/jdk/make/data/tzdata/southamerica Wed Jul 05 20:46:25 2017 +0200
@@ -154,7 +154,7 @@
# Timezone Law (which never was effectively applied) will (would?) be
# in effect.... The article is at
# http://ar.clarin.com/diario/2001-06-06/e-01701.htm
-# ... The Law itself is "Ley No 25155", sanctioned on 1999-08-25, enacted
+# ... The Law itself is "Ley No. 25155", sanctioned on 1999-08-25, enacted
# 1999-09-17, and published 1999-09-21. The official publication is at:
# http://www.boletin.jus.gov.ar/BON/Primera/1999/09-Septiembre/21/PDF/BO21-09-99LEG.PDF
# Regretfully, you have to subscribe (and pay) for the on-line version....
@@ -198,15 +198,11 @@
# http://www.worldtimezone.com/dst_news/dst_news_argentina03.html
# http://www.impulsobaires.com.ar/nota.php?id=57832 (in spanish)
-# From Rodrigo Severo (2008-10-06):
-# Here is some info available at a Gentoo bug related to TZ on Argentina's DST:
-# ...
-# ------- Comment #1 from [jmdocile] 2008-10-06 16:28 0000 -------
-# Hi, there is a problem with timezone-data-2008e and maybe with
-# timezone-data-2008f
-# Argentinian law [Number] 25.155 is no longer valid.
+# From Juan Manuel Docile in https://bugs.gentoo.org/240339 (2008-10-07)
+# via Rodrigo Severo:
+# Argentinian law No. 25.155 is no longer valid.
# http://www.infoleg.gov.ar/infolegInternet/anexos/60000-64999/60036/norma.htm
-# The new one is law [Number] 26.350
+# The new one is law No. 26.350
# http://www.infoleg.gov.ar/infolegInternet/anexos/135000-139999/136191/norma.htm
# So there is no summer time in Argentina for now.
@@ -794,7 +790,7 @@
# [ and in a second message (same day): ]
# I found the decree.
#
-# DECRETO No- 7.584, DE 13 DE OUTUBRO DE 2011
+# DECRETO No. 7.584, DE 13 DE OUTUBRO DE 2011
# Link :
# http://www.in.gov.br/visualiza/index.jsp?data=13/10/2011&jornal=1000&pagina=6&totalArquivos=6
@@ -1148,7 +1144,7 @@
# Conflicts between [1] and [2] were resolved as follows:
#
# - [1] says the 1910 transition was Jan 1, [2] says Jan 10 and cites
-# Boletín Nº 1, Aviso Nº 1 (1910). Go with [2].
+# Boletín No. 1, Aviso No. 1 (1910). Go with [2].
#
# - [1] says SMT was -4:42:45, [2] says Chile's official time from
# 1916 to 1919 was -4:42:46.3, the meridian of Chile's National
@@ -1156,7 +1152,7 @@
# Quinta Normal in Santiago. Go with [2], rounding it to -4:42:46.
#
# - [1] says the 1918 transition was Sep 1, [2] says Sep 10 and cites
-# Boletín Nº 22, Aviso Nº 129/1918 (1918-08-23). Go with [2].
+# Boletín No. 22, Aviso No. 129/1918 (1918-08-23). Go with [2].
#
# - [1] does not give times for transitions; assume they occur
# at midnight mainland time, the current common practice. However,
@@ -1556,7 +1552,7 @@
# (1999-09) reports no date; go with above sources and Gerd Knops (2001-02-27).
Rule Para 1998 2001 - Mar Sun>=1 0:00 0 -
# From Rives McDow (2002-02-28):
-# A decree was issued in Paraguay (no. 16350) on 2002-02-26 that changed the
+# A decree was issued in Paraguay (No. 16350) on 2002-02-26 that changed the
# dst method to be from the first Sunday in September to the first Sunday in
# April.
Rule Para 2002 2004 - Apr Sun>=1 0:00 0 -
@@ -1736,8 +1732,19 @@
Rule Uruguay 2006 only - Mar 12 2:00 0 -
# From Jesper Nørgaard Welen (2006-09-06):
# http://www.presidencia.gub.uy/_web/decretos/2006/09/CM%20210_08%2006%202006_00001.PDF
-Rule Uruguay 2006 max - Oct Sun>=1 2:00 1:00 S
-Rule Uruguay 2007 max - Mar Sun>=8 2:00 0 -
+#
+# From Steffen Thorsen (2015-06-30):
+# ... it looks like they will not be using DST the coming summer:
+# http://www.elobservador.com.uy/gobierno-resolvio-que-no-habra-cambio-horario-verano-n656787
+# http://www.republica.com.uy/este-ano-no-se-modificara-el-huso-horario-en-uruguay/523760/
+# From Paul Eggert (2015-06-30):
+# Apparently restaurateurs complained that DST caused people to go to the beach
+# instead of out to dinner.
+# From Pablo Camargo (2015-07-13):
+# http://archivo.presidencia.gub.uy/sci/decretos/2015/06/cons_min_201.pdf
+# [dated 2015-06-29; repeals Decree 311/006 dated 2006-09-04]
+Rule Uruguay 2006 2014 - Oct Sun>=1 2:00 1:00 S
+Rule Uruguay 2007 2015 - Mar Sun>=8 2:00 0 -
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
Zone America/Montevideo -3:44:44 - LMT 1898 Jun 28
-3:44:44 - MMT 1920 May 1 # Montevideo MT
@@ -1746,6 +1753,10 @@
# Venezuela
#
+# From Paul Eggert (2015-07-28):
+# For the 1965 transition see Gaceta Oficial No. 27.619 (1964-12-15), p 205.533
+# http://www.pgr.gob.ve/dmdocuments/1964/27619.pdf
+#
# From John Stainforth (2007-11-28):
# ... the change for Venezuela originally expected for 2007-12-31 has
# been brought forward to 2007-12-09. The official announcement was
@@ -1757,6 +1768,6 @@
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
Zone America/Caracas -4:27:44 - LMT 1890
-4:27:40 - CMT 1912 Feb 12 # Caracas Mean Time?
- -4:30 - VET 1965 # Venezuela Time
+ -4:30 - VET 1965 Jan 1 0:00 # Venezuela T.
-4:00 - VET 2007 Dec 9 3:00
-4:30 - VET
--- a/jdk/make/data/tzdata/zone.tab Thu Aug 20 12:29:58 2015 -0700
+++ b/jdk/make/data/tzdata/zone.tab Wed Jul 05 20:46:25 2017 +0200
@@ -129,8 +129,8 @@
BY +5354+02734 Europe/Minsk
BZ +1730-08812 America/Belize
CA +4734-05243 America/St_Johns Newfoundland Time, including SE Labrador
-CA +4439-06336 America/Halifax Atlantic Time - Nova Scotia (most places), PEI
-CA +4612-05957 America/Glace_Bay Atlantic Time - Nova Scotia - places that did not observe DST 1966-1971
+CA +4439-06336 America/Halifax Atlantic Time - Nova Scotia (peninsula), PEI
+CA +4612-05957 America/Glace_Bay Atlantic Time - Nova Scotia (Cape Breton)
CA +4606-06447 America/Moncton Atlantic Time - New Brunswick
CA +5320-06025 America/Goose_Bay Atlantic Time - Labrador - most locations
CA +5125-05707 America/Blanc-Sablon Atlantic Standard Time - Quebec - Lower North Shore
--- a/jdk/make/lib/Lib-java.base.gmk Thu Aug 20 12:29:58 2015 -0700
+++ b/jdk/make/lib/Lib-java.base.gmk Wed Jul 05 20:46:25 2017 +0200
@@ -32,3 +32,4 @@
include CoreLibraries.gmk
include NetworkingLibraries.gmk
include NioLibraries.gmk
+include SecurityLibraries.gmk
--- a/jdk/make/lib/Lib-jdk.deploy.osx.gmk Thu Aug 20 12:29:58 2015 -0700
+++ b/jdk/make/lib/Lib-jdk.deploy.osx.gmk Wed Jul 05 20:46:25 2017 +0200
@@ -80,7 +80,6 @@
-framework ApplicationServices \
-framework JavaNativeFoundation \
-framework JavaRuntimeSupport \
- -framework Security \
-framework SystemConfiguration \
$(LDFLAGS_JDKLIB_SUFFIX), \
OBJECT_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/libosx, \
--- a/jdk/make/lib/Lib-jdk.hprof.agent.gmk Thu Aug 20 12:29:58 2015 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,94 +0,0 @@
-#
-# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-#
-# This code is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License version 2 only, as
-# published by the Free Software Foundation. Oracle designates this
-# particular file as subject to the "Classpath" exception as provided
-# by Oracle in the LICENSE file that accompanied this code.
-#
-# This code is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-# version 2 for more details (a copy is included in the LICENSE file that
-# accompanied this code).
-#
-# You should have received a copy of the GNU General Public License version
-# 2 along with this work; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
-# or visit www.oracle.com if you need additional information or have any
-# questions.
-#
-
-include LibCommon.gmk
-
-################################################################################
-
-BUILD_LIBHPROF_SRC := $(call FindSrcDirsForLib, jdk.hprof.agent, hprof)
-
-BUILD_LIBHPROF_CFLAGS := $(addprefix -I, $(BUILD_LIBHPROF_SRC)) \
- -I$(JDK_TOPDIR)/src/demo/share/jvmti/java_crw_demo
-
-BUILD_LIBHPROF_LDFLAGS :=
-
-LIBHPROF_OPTIMIZATION := HIGHEST
-ifneq ($(findstring $(OPENJDK_TARGET_OS), solaris linux), )
- ifeq ($(ENABLE_DEBUG_SYMBOLS), true)
- LIBHPROF_OPTIMIZATION := LOW
- endif
-endif
-
-$(eval $(call SetupNativeCompilation,BUILD_LIBHPROF, \
- LIBRARY := hprof, \
- OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \
- SRC := $(BUILD_LIBHPROF_SRC), \
- OPTIMIZATION := $(LIBHPROF_OPTIMIZATION), \
- CFLAGS := $(CFLAGS_JDKLIB) \
- $(BUILD_LIBHPROF_CFLAGS), \
- CFLAGS_debug := -DHPROF_LOGGING, \
- MAPFILE := $(JDK_TOPDIR)/make/mapfiles/libhprof/mapfile-vers, \
- LDFLAGS := $(LDFLAGS_JDKLIB) \
- $(call SET_SHARED_LIBRARY_ORIGIN), \
- LDFLAGS_windows := wsock32.lib winmm.lib advapi32.lib, \
- LDFLAGS_SUFFIX_linux := $(LIBDL), \
- LDFLAGS_SUFFIX_macosx := $(LIBDL), \
- LDFLAGS_SUFFIX_solaris := -lsocket -lnsl $(LIBDL) -lc, \
- VERSIONINFO_RESOURCE := $(GLOBAL_VERSION_INFO_RESOURCE), \
- RC_FLAGS := $(RC_FLAGS) \
- -D "JDK_FNAME=hprof.dll" \
- -D "JDK_INTERNAL_NAME=hprof" \
- -D "JDK_FTYPE=0x2L", \
- OBJECT_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/libhprof_jvmti, \
- DEBUG_SYMBOLS := true))
-
-TARGETS += $(BUILD_LIBHPROF)
-
-################################################################################
-
-LIBJAVA_CRW_DEMO_SRC := $(JDK_TOPDIR)/src/demo/share/jvmti/java_crw_demo
-
-$(eval $(call SetupNativeCompilation,BUILD_LIBJAVA_CRW_DEMO, \
- LIBRARY := java_crw_demo, \
- OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \
- SRC := $(LIBJAVA_CRW_DEMO_SRC), \
- OPTIMIZATION := LOW, \
- CFLAGS := $(CFLAGS_JDKLIB) \
- $(addprefix -I, $(LIBJAVA_CRW_DEMO_SRC)), \
- MAPFILE := $(JDK_TOPDIR)/make/mapfiles/libjava_crw_demo/mapfile-vers, \
- LDFLAGS := $(LDFLAGS_JDKLIB) \
- $(call SET_SHARED_LIBRARY_ORIGIN), \
- LDFLAGS_SUFFIX_solaris := -lc, \
- VERSIONINFO_RESOURCE := $(GLOBAL_VERSION_INFO_RESOURCE), \
- RC_FLAGS := $(RC_FLAGS) \
- -D "JDK_FNAME=java_crw_demo.dll" \
- -D "JDK_INTERNAL_NAME=java_crw_demo" \
- -D "JDK_FTYPE=0x2L", \
- OBJECT_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/libjava_crw_demo, \
- DEBUG_SYMBOLS := true))
-
-TARGETS += $(BUILD_LIBJAVA_CRW_DEMO)
-
-################################################################################
--- a/jdk/make/lib/NioLibraries.gmk Thu Aug 20 12:29:58 2015 -0700
+++ b/jdk/make/lib/NioLibraries.gmk Wed Jul 05 20:46:25 2017 +0200
@@ -69,9 +69,6 @@
OPTIMIZATION := HIGH, \
CFLAGS := $(CFLAGS_JDKLIB) \
$(BUILD_LIBNIO_CFLAGS), \
- DISABLED_WARNINGS_gcc := type-limits, \
- DISABLED_WARNINGS_clang := tautological-compare, \
- DISABLED_WARNINGS_microsoft := 4244 4996, \
MAPFILE := $(BUILD_LIBNIO_MAPFILE), \
LDFLAGS := $(LDFLAGS_JDKLIB) $(BUILD_LIBNIO_LDFLAGS) \
$(call SET_SHARED_LIBRARY_ORIGIN), \
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/make/lib/SecurityLibraries.gmk Wed Jul 05 20:46:25 2017 +0200
@@ -0,0 +1,63 @@
+#
+# Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation. Oracle designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Oracle in the LICENSE file that accompanied this code.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+
+include LibCommon.gmk
+
+ifeq ($(OPENJDK_TARGET_OS), macosx)
+
+ ################################################################################
+
+ LIBOSXSECURITY_DIRS := $(JDK_TOPDIR)/src/java.base/macosx/native/libosxsecurity
+ LIBOSXSECURITY_CFLAGS := -I$(LIBOSXSECURITY_DIRS) \
+ $(LIBJAVA_HEADER_FLAGS) \
+ -I$(SUPPORT_OUTPUTDIR)/headers/java.base \
+
+ $(eval $(call SetupNativeCompilation,BUILD_LIBOSXSECURITY, \
+ LIBRARY := osxsecurity, \
+ OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \
+ SRC := $(LIBOSXSECURITY_DIRS), \
+ OPTIMIZATION := LOW, \
+ CFLAGS := $(CFLAGS_JDKLIB) \
+ $(LIBOSXSECURITY_CFLAGS), \
+ DISABLED_WARNINGS_clang := deprecated-declarations, \
+ LDFLAGS := $(LDFLAGS_JDKLIB) \
+ -L$(SUPPORT_OUTPUTDIR)/modules_libs/java.base \
+ $(call SET_SHARED_LIBRARY_ORIGIN), \
+ LDFLAGS_SUFFIX_macosx := \
+ -fobjc-link-runtime \
+ -framework JavaNativeFoundation \
+ -framework CoreServices \
+ -framework Security \
+ $(LDFLAGS_JDKLIB_SUFFIX), \
+ OBJECT_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/libosxsecurity, \
+ DEBUG_SYMBOLS := $(DEBUG_ALL_BINARIES)))
+
+ $(BUILD_LIBOSXSECURITY): $(BUILD_LIBJAVA)
+
+ TARGETS += $(BUILD_LIBOSXSECURITY)
+
+ ################################################################################
+
+endif
--- a/jdk/make/mapfiles/libhprof/mapfile-vers Thu Aug 20 12:29:58 2015 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,34 +0,0 @@
-#
-# Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-#
-# This code is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License version 2 only, as
-# published by the Free Software Foundation. Oracle designates this
-# particular file as subject to the "Classpath" exception as provided
-# by Oracle in the LICENSE file that accompanied this code.
-#
-# This code is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-# version 2 for more details (a copy is included in the LICENSE file that
-# accompanied this code).
-#
-# You should have received a copy of the GNU General Public License version
-# 2 along with this work; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
-# or visit www.oracle.com if you need additional information or have any
-# questions.
-#
-
-# Define public interface.
-
-SUNWprivate_1.1 {
- global:
- Agent_OnLoad;
- Agent_OnUnload;
- local:
- *;
-};
--- a/jdk/make/mapfiles/libjava_crw_demo/mapfile-vers Thu Aug 20 12:29:58 2015 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,34 +0,0 @@
-#
-# Copyright (c) 2004, 2013, Oracle and/or its affiliates. All rights reserved.
-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-#
-# This code is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License version 2 only, as
-# published by the Free Software Foundation. Oracle designates this
-# particular file as subject to the "Classpath" exception as provided
-# by Oracle in the LICENSE file that accompanied this code.
-#
-# This code is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-# version 2 for more details (a copy is included in the LICENSE file that
-# accompanied this code).
-#
-# You should have received a copy of the GNU General Public License version
-# 2 along with this work; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
-# or visit www.oracle.com if you need additional information or have any
-# questions.
-#
-
-# Define public interface.
-
-SUNWprivate_1.1 {
- global:
- java_crw_demo;
- java_crw_demo_classname;
- local:
- *;
-};
--- a/jdk/make/src/classes/build/tools/module/boot.modules Thu Aug 20 12:29:58 2015 -0700
+++ b/jdk/make/src/classes/build/tools/module/boot.modules Wed Jul 05 20:46:25 2017 +0200
@@ -19,7 +19,6 @@
jdk.charsets
jdk.deploy
jdk.deploy.osx
-jdk.hprof.agent
jdk.httpserver
jdk.jfr
jdk.management
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/aix/native/libjava/ProcessHandleImpl_aix.c Wed Jul 05 20:46:25 2017 +0200
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include "jni.h"
+
+#include "ProcessHandleImpl_unix.h"
+
+#include <sys/procfs.h>
+
+/*
+ * Implementation of native ProcessHandleImpl functions for AIX.
+ * See ProcessHandleImpl_unix.c for more details.
+ */
+
+void os_initNative(JNIEnv *env, jclass clazz) {}
+
+jint os_getChildren(JNIEnv *env, jlong jpid, jlongArray jarray,
+ jlongArray jparentArray, jlongArray jstimesArray) {
+ return unix_getChildren(env, jpid, jarray, jparentArray, jstimesArray);
+}
+
+pid_t os_getParentPidAndTimings(JNIEnv *env, pid_t pid, jlong *total, jlong *start) {
+ return unix_getParentPidAndTimings(env, pid, total, start);
+}
+
+void os_getCmdlineAndUserInfo(JNIEnv *env, jobject jinfo, pid_t pid) {
+ unix_getCmdlineAndUserInfo(env, jinfo, pid);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/linux/native/libjava/ProcessHandleImpl_linux.c Wed Jul 05 20:46:25 2017 +0200
@@ -0,0 +1,266 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include "jni.h"
+#include "jni_util.h"
+#include "java_lang_ProcessHandleImpl.h"
+#include "java_lang_ProcessHandleImpl_Info.h"
+
+#include "ProcessHandleImpl_unix.h"
+
+
+#include <fcntl.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <string.h>
+#include <ctype.h>
+
+/*
+ * Implementation of native ProcessHandleImpl functions for Linux.
+ * See ProcessHandleImpl_unix.c for more details.
+ */
+
+/* Signatures for internal OS specific functions. */
+static long long getBoottime(JNIEnv *env);
+
+/* A static offset in milliseconds since boot. */
+static long long bootTime_ms;
+static long clock_ticks_per_second;
+static int pageSize;
+
+void os_initNative(JNIEnv *env, jclass clazz) {
+ bootTime_ms = getBoottime(env);
+ clock_ticks_per_second = sysconf(_SC_CLK_TCK);
+ pageSize = sysconf(_SC_PAGESIZE);
+}
+
+jint os_getChildren(JNIEnv *env, jlong jpid, jlongArray jarray,
+ jlongArray jparentArray, jlongArray jstimesArray) {
+ return unix_getChildren(env, jpid, jarray, jparentArray, jstimesArray);
+}
+
+/**
+ * Read /proc/<pid>/stat and return the ppid, total cputime and start time.
+ * -1 is fail; >= 0 is parent pid
+ * 'total' will contain the running time of 'pid' in nanoseconds.
+ * 'start' will contain the start time of 'pid' in milliseconds since epoch.
+ */
+pid_t os_getParentPidAndTimings(JNIEnv *env, pid_t pid,
+ jlong *totalTime, jlong* startTime) {
+ FILE* fp;
+ char buffer[2048];
+ int statlen;
+ char fn[32];
+ char* s;
+ int parentPid;
+ long unsigned int utime = 0; // clock tics
+ long unsigned int stime = 0; // clock tics
+ long long unsigned int start = 0; // microseconds
+
+ /*
+ * Try to stat and then open /proc/%d/stat
+ */
+ snprintf(fn, sizeof fn, "/proc/%d/stat", pid);
+
+ fp = fopen(fn, "r");
+ if (fp == NULL) {
+ return -1; // fail, no such /proc/pid/stat
+ }
+
+ /*
+ * The format is: pid (command) state ppid ...
+ * As the command could be anything we must find the right most
+ * ")" and then skip the white spaces that follow it.
+ */
+ statlen = fread(buffer, 1, (sizeof buffer - 1), fp);
+ fclose(fp);
+ if (statlen < 0) {
+ return -1; // parent pid is not available
+ }
+
+ buffer[statlen] = '\0';
+ s = strchr(buffer, '(');
+ if (s == NULL) {
+ return -1; // parent pid is not available
+ }
+ // Found start of command, skip to end
+ s++;
+ s = strrchr(s, ')');
+ if (s == NULL) {
+ return -1; // parent pid is not available
+ }
+ s++;
+
+ // Scan the needed fields from status, retaining only ppid(4),
+ // utime (14), stime(15), starttime(22)
+ if (4 != sscanf(s, " %*c %d %*d %*d %*d %*d %*d %*u %*u %*u %*u %lu %lu %*d %*d %*d %*d %*d %*d %llu",
+ &parentPid, &utime, &stime, &start)) {
+ return 0; // not all values parsed; return error
+ }
+
+ *totalTime = (utime + stime) * (jlong)(1000000000 / clock_ticks_per_second);
+
+ *startTime = bootTime_ms + ((start * 1000) / clock_ticks_per_second);
+
+ return parentPid;
+}
+
+void os_getCmdlineAndUserInfo(JNIEnv *env, jobject jinfo, pid_t pid) {
+ int fd;
+ int cmdlen = 0;
+ char *cmdline = NULL, *cmdEnd = NULL; // used for command line args and exe
+ char *args = NULL;
+ jstring cmdexe = NULL;
+ char fn[32];
+ struct stat stat_buf;
+
+ /*
+ * Try to open /proc/<pid>/cmdline
+ */
+ snprintf(fn, sizeof fn, "/proc/%d/cmdline", pid);
+ if ((fd = open(fn, O_RDONLY)) < 0) {
+ return;
+ }
+
+ if (fstat(fd, &stat_buf) == 0) {
+ unix_getUserInfo(env, jinfo, stat_buf.st_uid);
+ }
+
+ do { // Block to break out of on errors
+ int i, truncated = 0;
+ int count;
+ char *s;
+
+ /*
+ * The path name read by readlink() is limited to PATH_MAX characters.
+ * The content of /proc/<pid>/cmdline is limited to PAGE_SIZE characters.
+ */
+ cmdline = (char*)malloc((PATH_MAX > pageSize ? PATH_MAX : pageSize) + 1);
+ if (cmdline == NULL) {
+ break;
+ }
+
+ /*
+ * On Linux, the full path to the executable command is the link in
+ * /proc/<pid>/exe. But it is only readable for processes we own.
+ */
+ snprintf(fn, sizeof fn, "/proc/%d/exe", pid);
+ if ((cmdlen = readlink(fn, cmdline, PATH_MAX)) > 0) {
+ // null terminate and create String to store for command
+ cmdline[cmdlen] = '\0';
+ cmdexe = JNU_NewStringPlatform(env, cmdline);
+ (*env)->ExceptionClear(env); // unconditionally clear any exception
+ }
+
+ /*
+ * The command-line arguments appear as a set of strings separated by
+ * null bytes ('\0'), with a further null byte after the last
+ * string. The last string is only null terminated if the whole command
+ * line is not exceeding (PAGE_SIZE - 1) characters.
+ */
+ cmdlen = 0;
+ s = cmdline;
+ while ((count = read(fd, s, pageSize - cmdlen)) > 0) {
+ cmdlen += count;
+ s += count;
+ }
+ if (count < 0) {
+ break;
+ }
+ // We have to null-terminate because the process may have changed argv[]
+ // or because the content in /proc/<pid>/cmdline is truncated.
+ cmdline[cmdlen] = '\0';
+ if (cmdlen == pageSize && cmdline[pageSize - 1] != '\0') {
+ truncated = 1;
+ } else if (cmdlen == 0) {
+ // /proc/<pid>/cmdline was empty. This usually happens for kernel processes
+ // like '[kthreadd]'. We could try to read /proc/<pid>/comm in the future.
+ }
+ if (cmdlen > 0 && (cmdexe == NULL || truncated)) {
+ // We have no exact command or the arguments are truncated.
+ // In this case we save the command line from /proc/<pid>/cmdline.
+ args = (char*)malloc(pageSize + 1);
+ if (args != NULL) {
+ memcpy(args, cmdline, cmdlen + 1);
+ for (i = 0; i < cmdlen; i++) {
+ if (args[i] == '\0') {
+ args[i] = ' ';
+ }
+ }
+ }
+ }
+ i = 0;
+ if (!truncated) {
+ // Count the arguments
+ cmdEnd = &cmdline[cmdlen];
+ for (s = cmdline; *s != '\0' && (s < cmdEnd); i++) {
+ s += strnlen(s, (cmdEnd - s)) + 1;
+ }
+ }
+ unix_fillArgArray(env, jinfo, i, cmdline, cmdEnd, cmdexe, args);
+ } while (0);
+
+ if (cmdline != NULL) {
+ free(cmdline);
+ }
+ if (args != NULL) {
+ free(args);
+ }
+ if (fd >= 0) {
+ close(fd);
+ }
+}
+
+/**
+ * Read the boottime from /proc/stat.
+ */
+static long long getBoottime(JNIEnv *env) {
+ FILE *fp;
+ char *line = NULL;
+ size_t len = 0;
+ long long bootTime = 0;
+
+ fp = fopen("/proc/stat", "r");
+ if (fp == NULL) {
+ return -1;
+ }
+
+ while (getline(&line, &len, fp) != -1) {
+ if (sscanf(line, "btime %llu", &bootTime) == 1) {
+ break;
+ }
+ }
+ free(line);
+
+ if (fp != 0) {
+ fclose(fp);
+ }
+
+ return bootTime * 1000;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/macosx/classes/apple/security/AppleProvider.java Wed Jul 05 20:46:25 2017 +0200
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package apple.security;
+
+import java.security.*;
+
+/**
+ * The Apple Security Provider.
+ */
+
+/**
+ * Defines the Apple provider.
+ *
+ * This provider only exists to provide access to the Apple keychain-based KeyStore implementation
+ */
+@SuppressWarnings("serial") // JDK implementation class
+public final class AppleProvider extends Provider {
+
+ private static final String info = "Apple Provider";
+
+ private static final class ProviderService extends Provider.Service {
+ ProviderService(Provider p, String type, String algo, String cn) {
+ super(p, type, algo, cn, null, null);
+ }
+
+ @Override
+ public Object newInstance(Object ctrParamObj)
+ throws NoSuchAlgorithmException {
+ String type = getType();
+ if (ctrParamObj != null) {
+ throw new InvalidParameterException
+ ("constructorParameter not used with " + type + " engines");
+ }
+
+ String algo = getAlgorithm();
+ try {
+ if (type.equals("KeyStore")) {
+ if (algo.equals("KeychainStore")) {
+ return new KeychainStore();
+ }
+ }
+ } catch (Exception ex) {
+ throw new NoSuchAlgorithmException("Error constructing " +
+ type + " for " + algo + " using Apple", ex);
+ }
+ throw new ProviderException("No impl for " + algo +
+ " " + type);
+ }
+ }
+
+
+ public AppleProvider() {
+ /* We are the Apple provider */
+ super("Apple", 1.9d, info);
+
+ final Provider p = this;
+ AccessController.doPrivileged(new PrivilegedAction<Void>() {
+ public Void run() {
+ putService(new ProviderService(p, "KeyStore",
+ "KeychainStore", "apple.security.KeychainStore"));
+ return null;
+ }
+ });
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/macosx/classes/apple/security/KeychainStore.java Wed Jul 05 20:46:25 2017 +0200
@@ -0,0 +1,1149 @@
+/*
+ * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package apple.security;
+
+import java.io.*;
+import java.security.*;
+import java.security.cert.*;
+import java.security.cert.Certificate;
+import java.security.spec.*;
+import java.util.*;
+
+import javax.crypto.*;
+import javax.crypto.spec.*;
+import javax.security.auth.x500.*;
+
+import sun.security.pkcs.*;
+import sun.security.pkcs.EncryptedPrivateKeyInfo;
+import sun.security.util.*;
+import sun.security.x509.*;
+
+/**
+ * This class provides the keystore implementation referred to as "KeychainStore".
+ * It uses the current user's keychain as its backing storage, and does NOT support
+ * a file-based implementation.
+ */
+
+public final class KeychainStore extends KeyStoreSpi {
+
+ // Private keys and their supporting certificate chains
+ // If a key came from the keychain it has a SecKeyRef and one or more
+ // SecCertificateRef. When we delete the key we have to delete all of the corresponding
+ // native objects.
+ class KeyEntry {
+ Date date; // the creation date of this entry
+ byte[] protectedPrivKey;
+ char[] password;
+ long keyRef; // SecKeyRef for this key
+ Certificate chain[];
+ long chainRefs[]; // SecCertificateRefs for this key's chain.
+ };
+
+ // Trusted certificates
+ class TrustedCertEntry {
+ Date date; // the creation date of this entry
+
+ Certificate cert;
+ long certRef; // SecCertificateRef for this key
+ };
+
+ /**
+ * Entries that have been deleted. When something calls engineStore we'll
+ * remove them from the keychain.
+ */
+ private Hashtable<String, Object> deletedEntries = new Hashtable<>();
+
+ /**
+ * Entries that have been added. When something calls engineStore we'll
+ * add them to the keychain.
+ */
+ private Hashtable<String, Object> addedEntries = new Hashtable<>();
+
+ /**
+ * Private keys and certificates are stored in a hashtable.
+ * Hash entries are keyed by alias names.
+ */
+ private Hashtable<String, Object> entries = new Hashtable<>();
+
+ /**
+ * Algorithm identifiers and corresponding OIDs for the contents of the PKCS12 bag we get from the Keychain.
+ */
+ private static final int keyBag[] = {1, 2, 840, 113549, 1, 12, 10, 1, 2};
+ private static final int pbeWithSHAAnd3KeyTripleDESCBC[] = {1, 2, 840, 113549, 1, 12, 1, 3};
+ private static ObjectIdentifier PKCS8ShroudedKeyBag_OID;
+ private static ObjectIdentifier pbeWithSHAAnd3KeyTripleDESCBC_OID;
+
+ /**
+ * Constnats used in PBE decryption.
+ */
+ private static final int iterationCount = 1024;
+ private static final int SALT_LEN = 20;
+
+ static {
+ AccessController.doPrivileged(
+ new PrivilegedAction<Void>() {
+ public Void run() {
+ System.loadLibrary("osxsecurity");
+ return null;
+ }
+ });
+ try {
+ PKCS8ShroudedKeyBag_OID = new ObjectIdentifier(keyBag);
+ pbeWithSHAAnd3KeyTripleDESCBC_OID = new ObjectIdentifier(pbeWithSHAAnd3KeyTripleDESCBC);
+ } catch (IOException ioe) {
+ // should not happen
+ }
+ }
+
+ private static void permissionCheck() {
+ SecurityManager sec = System.getSecurityManager();
+
+ if (sec != null) {
+ sec.checkPermission(new RuntimePermission("useKeychainStore"));
+ }
+ }
+
+
+ /**
+ * Verify the Apple provider in the constructor.
+ *
+ * @exception SecurityException if fails to verify
+ * its own integrity
+ */
+ public KeychainStore() { }
+
+ /**
+ * Returns the key associated with the given alias, using the given
+ * password to recover it.
+ *
+ * @param alias the alias name
+ * @param password the password for recovering the key. This password is
+ * used internally as the key is exported in a PKCS12 format.
+ *
+ * @return the requested key, or null if the given alias does not exist
+ * or does not identify a <i>key entry</i>.
+ *
+ * @exception NoSuchAlgorithmException if the algorithm for recovering the
+ * key cannot be found
+ * @exception UnrecoverableKeyException if the key cannot be recovered
+ * (e.g., the given password is wrong).
+ */
+ public Key engineGetKey(String alias, char[] password)
+ throws NoSuchAlgorithmException, UnrecoverableKeyException
+ {
+ permissionCheck();
+
+ // An empty password is rejected by MacOS API, no private key data
+ // is exported. If no password is passed (as is the case when
+ // this implementation is used as browser keystore in various
+ // deployment scenarios like Webstart, JFX and applets), create
+ // a dummy password so MacOS API is happy.
+ if (password == null || password.length == 0) {
+ // Must not be a char array with only a 0, as this is an empty
+ // string.
+ if (random == null) {
+ random = new SecureRandom();
+ }
+ password = Long.toString(random.nextLong()).toCharArray();
+ }
+
+ Object entry = entries.get(alias.toLowerCase());
+
+ if (entry == null || !(entry instanceof KeyEntry)) {
+ return null;
+ }
+
+ // This call gives us a PKCS12 bag, with the key inside it.
+ byte[] exportedKeyInfo = _getEncodedKeyData(((KeyEntry)entry).keyRef, password);
+ if (exportedKeyInfo == null) {
+ return null;
+ }
+
+ PrivateKey returnValue = null;
+
+ try {
+ byte[] pkcs8KeyData = fetchPrivateKeyFromBag(exportedKeyInfo);
+ byte[] encryptedKey;
+ AlgorithmParameters algParams;
+ ObjectIdentifier algOid;
+ try {
+ // get the encrypted private key
+ EncryptedPrivateKeyInfo encrInfo = new EncryptedPrivateKeyInfo(pkcs8KeyData);
+ encryptedKey = encrInfo.getEncryptedData();
+
+ // parse Algorithm parameters
+ DerValue val = new DerValue(encrInfo.getAlgorithm().encode());
+ DerInputStream in = val.toDerInputStream();
+ algOid = in.getOID();
+ algParams = parseAlgParameters(in);
+
+ } catch (IOException ioe) {
+ UnrecoverableKeyException uke =
+ new UnrecoverableKeyException("Private key not stored as "
+ + "PKCS#8 EncryptedPrivateKeyInfo: " + ioe);
+ uke.initCause(ioe);
+ throw uke;
+ }
+
+ // Use JCE to decrypt the data using the supplied password.
+ SecretKey skey = getPBEKey(password);
+ Cipher cipher = Cipher.getInstance(algOid.toString());
+ cipher.init(Cipher.DECRYPT_MODE, skey, algParams);
+ byte[] decryptedPrivateKey = cipher.doFinal(encryptedKey);
+ PKCS8EncodedKeySpec kspec = new PKCS8EncodedKeySpec(decryptedPrivateKey);
+
+ // Parse the key algorithm and then use a JCA key factory to create the private key.
+ DerValue val = new DerValue(decryptedPrivateKey);
+ DerInputStream in = val.toDerInputStream();
+
+ // Ignore this -- version should be 0.
+ int i = in.getInteger();
+
+ // Get the Algorithm ID next
+ DerValue[] value = in.getSequence(2);
+ AlgorithmId algId = new AlgorithmId(value[0].getOID());
+ String algName = algId.getName();
+
+ // Get a key factory for this algorithm. It's likely to be 'RSA'.
+ KeyFactory kfac = KeyFactory.getInstance(algName);
+ returnValue = kfac.generatePrivate(kspec);
+ } catch (Exception e) {
+ UnrecoverableKeyException uke =
+ new UnrecoverableKeyException("Get Key failed: " +
+ e.getMessage());
+ uke.initCause(e);
+ throw uke;
+ }
+
+ return returnValue;
+ }
+
+ private native byte[] _getEncodedKeyData(long secKeyRef, char[] password);
+
+ /**
+ * Returns the certificate chain associated with the given alias.
+ *
+ * @param alias the alias name
+ *
+ * @return the certificate chain (ordered with the user's certificate first
+ * and the root certificate authority last), or null if the given alias
+ * does not exist or does not contain a certificate chain (i.e., the given
+ * alias identifies either a <i>trusted certificate entry</i> or a
+ * <i>key entry</i> without a certificate chain).
+ */
+ public Certificate[] engineGetCertificateChain(String alias) {
+ permissionCheck();
+
+ Object entry = entries.get(alias.toLowerCase());
+
+ if (entry != null && entry instanceof KeyEntry) {
+ if (((KeyEntry)entry).chain == null) {
+ return null;
+ } else {
+ return ((KeyEntry)entry).chain.clone();
+ }
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Returns the certificate associated with the given alias.
+ *
+ * <p>If the given alias name identifies a
+ * <i>trusted certificate entry</i>, the certificate associated with that
+ * entry is returned. If the given alias name identifies a
+ * <i>key entry</i>, the first element of the certificate chain of that
+ * entry is returned, or null if that entry does not have a certificate
+ * chain.
+ *
+ * @param alias the alias name
+ *
+ * @return the certificate, or null if the given alias does not exist or
+ * does not contain a certificate.
+ */
+ public Certificate engineGetCertificate(String alias) {
+ permissionCheck();
+
+ Object entry = entries.get(alias.toLowerCase());
+
+ if (entry != null) {
+ if (entry instanceof TrustedCertEntry) {
+ return ((TrustedCertEntry)entry).cert;
+ } else {
+ KeyEntry ke = (KeyEntry)entry;
+ if (ke.chain == null || ke.chain.length == 0) {
+ return null;
+ }
+ return ke.chain[0];
+ }
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Returns the creation date of the entry identified by the given alias.
+ *
+ * @param alias the alias name
+ *
+ * @return the creation date of this entry, or null if the given alias does
+ * not exist
+ */
+ public Date engineGetCreationDate(String alias) {
+ permissionCheck();
+
+ Object entry = entries.get(alias.toLowerCase());
+
+ if (entry != null) {
+ if (entry instanceof TrustedCertEntry) {
+ return new Date(((TrustedCertEntry)entry).date.getTime());
+ } else {
+ return new Date(((KeyEntry)entry).date.getTime());
+ }
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Assigns the given key to the given alias, protecting it with the given
+ * password.
+ *
+ * <p>If the given key is of type <code>java.security.PrivateKey</code>,
+ * it must be accompanied by a certificate chain certifying the
+ * corresponding public key.
+ *
+ * <p>If the given alias already exists, the keystore information
+ * associated with it is overridden by the given key (and possibly
+ * certificate chain).
+ *
+ * @param alias the alias name
+ * @param key the key to be associated with the alias
+ * @param password the password to protect the key
+ * @param chain the certificate chain for the corresponding public
+ * key (only required if the given key is of type
+ * <code>java.security.PrivateKey</code>).
+ *
+ * @exception KeyStoreException if the given key cannot be protected, or
+ * this operation fails for some other reason
+ */
+ public void engineSetKeyEntry(String alias, Key key, char[] password,
+ Certificate[] chain)
+ throws KeyStoreException
+ {
+ permissionCheck();
+
+ synchronized(entries) {
+ try {
+ KeyEntry entry = new KeyEntry();
+ entry.date = new Date();
+
+ if (key instanceof PrivateKey) {
+ if ((key.getFormat().equals("PKCS#8")) ||
+ (key.getFormat().equals("PKCS8"))) {
+ entry.protectedPrivKey = encryptPrivateKey(key.getEncoded(), password);
+ entry.password = password.clone();
+ } else {
+ throw new KeyStoreException("Private key is not encoded as PKCS#8");
+ }
+ } else {
+ throw new KeyStoreException("Key is not a PrivateKey");
+ }
+
+ // clone the chain
+ if (chain != null) {
+ if ((chain.length > 1) && !validateChain(chain)) {
+ throw new KeyStoreException("Certificate chain does not validate");
+ }
+
+ entry.chain = chain.clone();
+ entry.chainRefs = new long[entry.chain.length];
+ }
+
+ String lowerAlias = alias.toLowerCase();
+ if (entries.get(lowerAlias) != null) {
+ deletedEntries.put(lowerAlias, entries.get(lowerAlias));
+ }
+
+ entries.put(lowerAlias, entry);
+ addedEntries.put(lowerAlias, entry);
+ } catch (Exception nsae) {
+ KeyStoreException ke = new KeyStoreException("Key protection algorithm not found: " + nsae);
+ ke.initCause(nsae);
+ throw ke;
+ }
+ }
+ }
+
+ /**
+ * Assigns the given key (that has already been protected) to the given
+ * alias.
+ *
+ * <p>If the protected key is of type
+ * <code>java.security.PrivateKey</code>, it must be accompanied by a
+ * certificate chain certifying the corresponding public key. If the
+ * underlying keystore implementation is of type <code>jks</code>,
+ * <code>key</code> must be encoded as an
+ * <code>EncryptedPrivateKeyInfo</code> as defined in the PKCS #8 standard.
+ *
+ * <p>If the given alias already exists, the keystore information
+ * associated with it is overridden by the given key (and possibly
+ * certificate chain).
+ *
+ * @param alias the alias name
+ * @param key the key (in protected format) to be associated with the alias
+ * @param chain the certificate chain for the corresponding public
+ * key (only useful if the protected key is of type
+ * <code>java.security.PrivateKey</code>).
+ *
+ * @exception KeyStoreException if this operation fails.
+ */
+ public void engineSetKeyEntry(String alias, byte[] key,
+ Certificate[] chain)
+ throws KeyStoreException
+ {
+ permissionCheck();
+
+ synchronized(entries) {
+ // key must be encoded as EncryptedPrivateKeyInfo as defined in
+ // PKCS#8
+ KeyEntry entry = new KeyEntry();
+ try {
+ EncryptedPrivateKeyInfo privateKey = new EncryptedPrivateKeyInfo(key);
+ entry.protectedPrivKey = privateKey.getEncoded();
+ } catch (IOException ioe) {
+ throw new KeyStoreException("key is not encoded as "
+ + "EncryptedPrivateKeyInfo");
+ }
+
+ entry.date = new Date();
+
+ if ((chain != null) &&
+ (chain.length != 0)) {
+ entry.chain = chain.clone();
+ entry.chainRefs = new long[entry.chain.length];
+ }
+
+ String lowerAlias = alias.toLowerCase();
+ if (entries.get(lowerAlias) != null) {
+ deletedEntries.put(lowerAlias, entries.get(alias));
+ }
+ entries.put(lowerAlias, entry);
+ addedEntries.put(lowerAlias, entry);
+ }
+ }
+
+ /**
+ * Assigns the given certificate to the given alias.
+ *
+ * <p>If the given alias already exists in this keystore and identifies a
+ * <i>trusted certificate entry</i>, the certificate associated with it is
+ * overridden by the given certificate.
+ *
+ * @param alias the alias name
+ * @param cert the certificate
+ *
+ * @exception KeyStoreException if the given alias already exists and does
+ * not identify a <i>trusted certificate entry</i>, or this operation
+ * fails for some other reason.
+ */
+ public void engineSetCertificateEntry(String alias, Certificate cert)
+ throws KeyStoreException
+ {
+ permissionCheck();
+
+ synchronized(entries) {
+
+ Object entry = entries.get(alias.toLowerCase());
+ if ((entry != null) && (entry instanceof KeyEntry)) {
+ throw new KeyStoreException
+ ("Cannot overwrite key entry with certificate");
+ }
+
+ // This will be slow, but necessary. Enumerate the values and then see if the cert matches the one in the trusted cert entry.
+ // Security framework doesn't support the same certificate twice in a keychain.
+ Collection<Object> allValues = entries.values();
+
+ for (Object value : allValues) {
+ if (value instanceof TrustedCertEntry) {
+ TrustedCertEntry tce = (TrustedCertEntry)value;
+ if (tce.cert.equals(cert)) {
+ throw new KeyStoreException("Keychain does not support mulitple copies of same certificate.");
+ }
+ }
+ }
+
+ TrustedCertEntry trustedCertEntry = new TrustedCertEntry();
+ trustedCertEntry.cert = cert;
+ trustedCertEntry.date = new Date();
+ String lowerAlias = alias.toLowerCase();
+ if (entries.get(lowerAlias) != null) {
+ deletedEntries.put(lowerAlias, entries.get(lowerAlias));
+ }
+ entries.put(lowerAlias, trustedCertEntry);
+ addedEntries.put(lowerAlias, trustedCertEntry);
+ }
+ }
+
+ /**
+ * Deletes the entry identified by the given alias from this keystore.
+ *
+ * @param alias the alias name
+ *
+ * @exception KeyStoreException if the entry cannot be removed.
+ */
+ public void engineDeleteEntry(String alias)
+ throws KeyStoreException
+ {
+ permissionCheck();
+
+ synchronized(entries) {
+ Object entry = entries.remove(alias.toLowerCase());
+ deletedEntries.put(alias.toLowerCase(), entry);
+ }
+ }
+
+ /**
+ * Lists all the alias names of this keystore.
+ *
+ * @return enumeration of the alias names
+ */
+ public Enumeration<String> engineAliases() {
+ permissionCheck();
+ return entries.keys();
+ }
+
+ /**
+ * Checks if the given alias exists in this keystore.
+ *
+ * @param alias the alias name
+ *
+ * @return true if the alias exists, false otherwise
+ */
+ public boolean engineContainsAlias(String alias) {
+ permissionCheck();
+ return entries.containsKey(alias.toLowerCase());
+ }
+
+ /**
+ * Retrieves the number of entries in this keystore.
+ *
+ * @return the number of entries in this keystore
+ */
+ public int engineSize() {
+ permissionCheck();
+ return entries.size();
+ }
+
+ /**
+ * Returns true if the entry identified by the given alias is a
+ * <i>key entry</i>, and false otherwise.
+ *
+ * @return true if the entry identified by the given alias is a
+ * <i>key entry</i>, false otherwise.
+ */
+ public boolean engineIsKeyEntry(String alias) {
+ permissionCheck();
+ Object entry = entries.get(alias.toLowerCase());
+ if ((entry != null) && (entry instanceof KeyEntry)) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Returns true if the entry identified by the given alias is a
+ * <i>trusted certificate entry</i>, and false otherwise.
+ *
+ * @return true if the entry identified by the given alias is a
+ * <i>trusted certificate entry</i>, false otherwise.
+ */
+ public boolean engineIsCertificateEntry(String alias) {
+ permissionCheck();
+ Object entry = entries.get(alias.toLowerCase());
+ if ((entry != null) && (entry instanceof TrustedCertEntry)) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Returns the (alias) name of the first keystore entry whose certificate
+ * matches the given certificate.
+ *
+ * <p>This method attempts to match the given certificate with each
+ * keystore entry. If the entry being considered
+ * is a <i>trusted certificate entry</i>, the given certificate is
+ * compared to that entry's certificate. If the entry being considered is
+ * a <i>key entry</i>, the given certificate is compared to the first
+ * element of that entry's certificate chain (if a chain exists).
+ *
+ * @param cert the certificate to match with.
+ *
+ * @return the (alias) name of the first entry with matching certificate,
+ * or null if no such entry exists in this keystore.
+ */
+ public String engineGetCertificateAlias(Certificate cert) {
+ permissionCheck();
+ Certificate certElem;
+
+ for (Enumeration<String> e = entries.keys(); e.hasMoreElements(); ) {
+ String alias = e.nextElement();
+ Object entry = entries.get(alias);
+ if (entry instanceof TrustedCertEntry) {
+ certElem = ((TrustedCertEntry)entry).cert;
+ } else {
+ KeyEntry ke = (KeyEntry)entry;
+ if (ke.chain == null || ke.chain.length == 0) {
+ continue;
+ }
+ certElem = ke.chain[0];
+ }
+ if (certElem.equals(cert)) {
+ return alias;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Stores this keystore to the given output stream, and protects its
+ * integrity with the given password.
+ *
+ * @param stream Ignored. the output stream to which this keystore is written.
+ * @param password the password to generate the keystore integrity check
+ *
+ * @exception IOException if there was an I/O problem with data
+ * @exception NoSuchAlgorithmException if the appropriate data integrity
+ * algorithm could not be found
+ * @exception CertificateException if any of the certificates included in
+ * the keystore data could not be stored
+ */
+ public void engineStore(OutputStream stream, char[] password)
+ throws IOException, NoSuchAlgorithmException, CertificateException
+ {
+ permissionCheck();
+
+ // Delete items that do have a keychain item ref.
+ for (Enumeration<String> e = deletedEntries.keys(); e.hasMoreElements(); ) {
+ String alias = e.nextElement();
+ Object entry = deletedEntries.get(alias);
+ if (entry instanceof TrustedCertEntry) {
+ if (((TrustedCertEntry)entry).certRef != 0) {
+ _removeItemFromKeychain(((TrustedCertEntry)entry).certRef);
+ _releaseKeychainItemRef(((TrustedCertEntry)entry).certRef);
+ }
+ } else {
+ Certificate certElem;
+ KeyEntry keyEntry = (KeyEntry)entry;
+
+ if (keyEntry.chain != null) {
+ for (int i = 0; i < keyEntry.chain.length; i++) {
+ if (keyEntry.chainRefs[i] != 0) {
+ _removeItemFromKeychain(keyEntry.chainRefs[i]);
+ _releaseKeychainItemRef(keyEntry.chainRefs[i]);
+ }
+ }
+
+ if (keyEntry.keyRef != 0) {
+ _removeItemFromKeychain(keyEntry.keyRef);
+ _releaseKeychainItemRef(keyEntry.keyRef);
+ }
+ }
+ }
+ }
+
+ // Add all of the certs or keys in the added entries.
+ // No need to check for 0 refs, as they are in the added list.
+ for (Enumeration<String> e = addedEntries.keys(); e.hasMoreElements(); ) {
+ String alias = e.nextElement();
+ Object entry = addedEntries.get(alias);
+ if (entry instanceof TrustedCertEntry) {
+ TrustedCertEntry tce = (TrustedCertEntry)entry;
+ Certificate certElem;
+ certElem = tce.cert;
+ tce.certRef = addCertificateToKeychain(alias, certElem);
+ } else {
+ KeyEntry keyEntry = (KeyEntry)entry;
+
+ if (keyEntry.chain != null) {
+ for (int i = 0; i < keyEntry.chain.length; i++) {
+ keyEntry.chainRefs[i] = addCertificateToKeychain(alias, keyEntry.chain[i]);
+ }
+
+ keyEntry.keyRef = _addItemToKeychain(alias, false, keyEntry.protectedPrivKey, keyEntry.password);
+ }
+ }
+ }
+
+ // Clear the added and deletedEntries hashtables here, now that we're done with the updates.
+ // For the deleted entries, we freed up the native references above.
+ deletedEntries.clear();
+ addedEntries.clear();
+ }
+
+ private long addCertificateToKeychain(String alias, Certificate cert) {
+ byte[] certblob = null;
+ long returnValue = 0;
+
+ try {
+ certblob = cert.getEncoded();
+ returnValue = _addItemToKeychain(alias, true, certblob, null);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ return returnValue;
+ }
+
+ private native long _addItemToKeychain(String alias, boolean isCertificate, byte[] datablob, char[] password);
+ private native int _removeItemFromKeychain(long certRef);
+ private native void _releaseKeychainItemRef(long keychainItemRef);
+
+ /**
+ * Loads the keystore from the Keychain.
+ *
+ * @param stream Ignored - here for API compatibility.
+ * @param password Ignored - if user needs to unlock keychain Security
+ * framework will post any dialogs.
+ *
+ * @exception IOException if there is an I/O or format problem with the
+ * keystore data
+ * @exception NoSuchAlgorithmException if the algorithm used to check
+ * the integrity of the keystore cannot be found
+ * @exception CertificateException if any of the certificates in the
+ * keystore could not be loaded
+ */
+ public void engineLoad(InputStream stream, char[] password)
+ throws IOException, NoSuchAlgorithmException, CertificateException
+ {
+ permissionCheck();
+
+ // Release any stray keychain references before clearing out the entries.
+ synchronized(entries) {
+ for (Enumeration<String> e = entries.keys(); e.hasMoreElements(); ) {
+ String alias = e.nextElement();
+ Object entry = entries.get(alias);
+ if (entry instanceof TrustedCertEntry) {
+ if (((TrustedCertEntry)entry).certRef != 0) {
+ _releaseKeychainItemRef(((TrustedCertEntry)entry).certRef);
+ }
+ } else {
+ KeyEntry keyEntry = (KeyEntry)entry;
+
+ if (keyEntry.chain != null) {
+ for (int i = 0; i < keyEntry.chain.length; i++) {
+ if (keyEntry.chainRefs[i] != 0) {
+ _releaseKeychainItemRef(keyEntry.chainRefs[i]);
+ }
+ }
+
+ if (keyEntry.keyRef != 0) {
+ _releaseKeychainItemRef(keyEntry.keyRef);
+ }
+ }
+ }
+ }
+
+ entries.clear();
+ _scanKeychain();
+ }
+ }
+
+ private native void _scanKeychain();
+
+ /**
+ * Callback method from _scanKeychain. If a trusted certificate is found, this method will be called.
+ */
+ private void createTrustedCertEntry(String alias, long keychainItemRef, long creationDate, byte[] derStream) {
+ TrustedCertEntry tce = new TrustedCertEntry();
+
+ try {
+ CertificateFactory cf = CertificateFactory.getInstance("X.509");
+ InputStream input = new ByteArrayInputStream(derStream);
+ X509Certificate cert = (X509Certificate) cf.generateCertificate(input);
+ input.close();
+ tce.cert = cert;
+ tce.certRef = keychainItemRef;
+
+ // Make a creation date.
+ if (creationDate != 0)
+ tce.date = new Date(creationDate);
+ else
+ tce.date = new Date();
+
+ int uniqueVal = 1;
+ String originalAlias = alias;
+
+ while (entries.containsKey(alias.toLowerCase())) {
+ alias = originalAlias + " " + uniqueVal;
+ uniqueVal++;
+ }
+
+ entries.put(alias.toLowerCase(), tce);
+ } catch (Exception e) {
+ // The certificate will be skipped.
+ System.err.println("KeychainStore Ignored Exception: " + e);
+ }
+ }
+
+ /**
+ * Callback method from _scanKeychain. If an identity is found, this method will be called to create Java certificate
+ * and private key objects from the keychain data.
+ */
+ private void createKeyEntry(String alias, long creationDate, long secKeyRef, long[] secCertificateRefs, byte[][] rawCertData)
+ throws IOException, NoSuchAlgorithmException, UnrecoverableKeyException {
+ KeyEntry ke = new KeyEntry();
+
+ // First, store off the private key information. This is the easy part.
+ ke.protectedPrivKey = null;
+ ke.keyRef = secKeyRef;
+
+ // Make a creation date.
+ if (creationDate != 0)
+ ke.date = new Date(creationDate);
+ else
+ ke.date = new Date();
+
+ // Next, create X.509 Certificate objects from the raw data. This is complicated
+ // because a certificate's public key may be too long for Java's default encryption strength.
+ List<CertKeychainItemPair> createdCerts = new ArrayList<>();
+
+ try {
+ CertificateFactory cf = CertificateFactory.getInstance("X.509");
+
+ for (int i = 0; i < rawCertData.length; i++) {
+ try {
+ InputStream input = new ByteArrayInputStream(rawCertData[i]);
+ X509Certificate cert = (X509Certificate) cf.generateCertificate(input);
+ input.close();
+
+ // We successfully created the certificate, so track it and its corresponding SecCertificateRef.
+ createdCerts.add(new CertKeychainItemPair(secCertificateRefs[i], cert));
+ } catch (CertificateException e) {
+ // The certificate will be skipped.
+ System.err.println("KeychainStore Ignored Exception: " + e);
+ }
+ }
+ } catch (CertificateException e) {
+ e.printStackTrace();
+ } catch (IOException ioe) {
+ ioe.printStackTrace(); // How would this happen?
+ }
+
+ // We have our certificates in the List, so now extract them into an array of
+ // Certificates and SecCertificateRefs.
+ CertKeychainItemPair[] objArray = createdCerts.toArray(new CertKeychainItemPair[0]);
+ Certificate[] certArray = new Certificate[objArray.length];
+ long[] certRefArray = new long[objArray.length];
+
+ for (int i = 0; i < objArray.length; i++) {
+ CertKeychainItemPair addedItem = objArray[i];
+ certArray[i] = addedItem.mCert;
+ certRefArray[i] = addedItem.mCertificateRef;
+ }
+
+ ke.chain = certArray;
+ ke.chainRefs = certRefArray;
+
+ // If we don't have already have an item with this item's alias
+ // create a new one for it.
+ int uniqueVal = 1;
+ String originalAlias = alias;
+
+ while (entries.containsKey(alias.toLowerCase())) {
+ alias = originalAlias + " " + uniqueVal;
+ uniqueVal++;
+ }
+
+ entries.put(alias.toLowerCase(), ke);
+ }
+
+ private class CertKeychainItemPair {
+ long mCertificateRef;
+ Certificate mCert;
+
+ CertKeychainItemPair(long inCertRef, Certificate cert) {
+ mCertificateRef = inCertRef;
+ mCert = cert;
+ }
+ }
+
+ /*
+ * Validate Certificate Chain
+ */
+ private boolean validateChain(Certificate[] certChain)
+ {
+ for (int i = 0; i < certChain.length-1; i++) {
+ X500Principal issuerDN =
+ ((X509Certificate)certChain[i]).getIssuerX500Principal();
+ X500Principal subjectDN =
+ ((X509Certificate)certChain[i+1]).getSubjectX500Principal();
+ if (!(issuerDN.equals(subjectDN)))
+ return false;
+ }
+ return true;
+ }
+
+ @SuppressWarnings("deprecation")
+ private byte[] fetchPrivateKeyFromBag(byte[] privateKeyInfo) throws IOException, NoSuchAlgorithmException, CertificateException
+ {
+ byte[] returnValue = null;
+ DerValue val = new DerValue(new ByteArrayInputStream(privateKeyInfo));
+ DerInputStream s = val.toDerInputStream();
+ int version = s.getInteger();
+
+ if (version != 3) {
+ throw new IOException("PKCS12 keystore not in version 3 format");
+ }
+
+ /*
+ * Read the authSafe.
+ */
+ byte[] authSafeData;
+ ContentInfo authSafe = new ContentInfo(s);
+ ObjectIdentifier contentType = authSafe.getContentType();
+
+ if (contentType.equals(ContentInfo.DATA_OID)) {
+ authSafeData = authSafe.getData();
+ } else /* signed data */ {
+ throw new IOException("public key protected PKCS12 not supported");
+ }
+
+ DerInputStream as = new DerInputStream(authSafeData);
+ DerValue[] safeContentsArray = as.getSequence(2);
+ int count = safeContentsArray.length;
+
+ /*
+ * Spin over the ContentInfos.
+ */
+ for (int i = 0; i < count; i++) {
+ byte[] safeContentsData;
+ ContentInfo safeContents;
+ DerInputStream sci;
+ byte[] eAlgId = null;
+
+ sci = new DerInputStream(safeContentsArray[i].toByteArray());
+ safeContents = new ContentInfo(sci);
+ contentType = safeContents.getContentType();
+ safeContentsData = null;
+
+ if (contentType.equals(ContentInfo.DATA_OID)) {
+ safeContentsData = safeContents.getData();
+ } else if (contentType.equals(ContentInfo.ENCRYPTED_DATA_OID)) {
+ // The password was used to export the private key from the keychain.
+ // The Keychain won't export the key with encrypted data, so we don't need
+ // to worry about it.
+ continue;
+ } else {
+ throw new IOException("public key protected PKCS12" +
+ " not supported");
+ }
+ DerInputStream sc = new DerInputStream(safeContentsData);
+ returnValue = extractKeyData(sc);
+ }
+
+ return returnValue;
+ }
+
+ @SuppressWarnings("deprecation")
+ private byte[] extractKeyData(DerInputStream stream)
+ throws IOException, NoSuchAlgorithmException, CertificateException
+ {
+ byte[] returnValue = null;
+ DerValue[] safeBags = stream.getSequence(2);
+ int count = safeBags.length;
+
+ /*
+ * Spin over the SafeBags.
+ */
+ for (int i = 0; i < count; i++) {
+ ObjectIdentifier bagId;
+ DerInputStream sbi;
+ DerValue bagValue;
+ Object bagItem = null;
+
+ sbi = safeBags[i].toDerInputStream();
+ bagId = sbi.getOID();
+ bagValue = sbi.getDerValue();
+ if (!bagValue.isContextSpecific((byte)0)) {
+ throw new IOException("unsupported PKCS12 bag value type "
+ + bagValue.tag);
+ }
+ bagValue = bagValue.data.getDerValue();
+ if (bagId.equals(PKCS8ShroudedKeyBag_OID)) {
+ // got what we were looking for. Return it.
+ returnValue = bagValue.toByteArray();
+ } else {
+ // log error message for "unsupported PKCS12 bag type"
+ System.out.println("Unsupported bag type '" + bagId + "'");
+ }
+ }
+
+ return returnValue;
+ }
+
+ /*
+ * Generate PBE Algorithm Parameters
+ */
+ private AlgorithmParameters getAlgorithmParameters(String algorithm)
+ throws IOException
+ {
+ AlgorithmParameters algParams = null;
+
+ // create PBE parameters from salt and iteration count
+ PBEParameterSpec paramSpec =
+ new PBEParameterSpec(getSalt(), iterationCount);
+ try {
+ algParams = AlgorithmParameters.getInstance(algorithm);
+ algParams.init(paramSpec);
+ } catch (Exception e) {
+ IOException ioe =
+ new IOException("getAlgorithmParameters failed: " +
+ e.getMessage());
+ ioe.initCause(e);
+ throw ioe;
+ }
+ return algParams;
+ }
+
+ // the source of randomness
+ private SecureRandom random;
+
+ /*
+ * Generate random salt
+ */
+ private byte[] getSalt()
+ {
+ // Generate a random salt.
+ byte[] salt = new byte[SALT_LEN];
+ if (random == null) {
+ random = new SecureRandom();
+ }
+ salt = random.generateSeed(SALT_LEN);
+ return salt;
+ }
+
+ /*
+ * parse Algorithm Parameters
+ */
+ private AlgorithmParameters parseAlgParameters(DerInputStream in)
+ throws IOException
+ {
+ AlgorithmParameters algParams = null;
+ try {
+ DerValue params;
+ if (in.available() == 0) {
+ params = null;
+ } else {
+ params = in.getDerValue();
+ if (params.tag == DerValue.tag_Null) {
+ params = null;
+ }
+ }
+ if (params != null) {
+ algParams = AlgorithmParameters.getInstance("PBE");
+ algParams.init(params.toByteArray());
+ }
+ } catch (Exception e) {
+ IOException ioe =
+ new IOException("parseAlgParameters failed: " +
+ e.getMessage());
+ ioe.initCause(e);
+ throw ioe;
+ }
+ return algParams;
+ }
+
+ /*
+ * Generate PBE key
+ */
+ private SecretKey getPBEKey(char[] password) throws IOException
+ {
+ SecretKey skey = null;
+
+ try {
+ PBEKeySpec keySpec = new PBEKeySpec(password);
+ SecretKeyFactory skFac = SecretKeyFactory.getInstance("PBE");
+ skey = skFac.generateSecret(keySpec);
+ } catch (Exception e) {
+ IOException ioe = new IOException("getSecretKey failed: " +
+ e.getMessage());
+ ioe.initCause(e);
+ throw ioe;
+ }
+ return skey;
+ }
+
+ /*
+ * Encrypt private key using Password-based encryption (PBE)
+ * as defined in PKCS#5.
+ *
+ * NOTE: Currently pbeWithSHAAnd3-KeyTripleDES-CBC algorithmID is
+ * used to derive the key and IV.
+ *
+ * @return encrypted private key encoded as EncryptedPrivateKeyInfo
+ */
+ private byte[] encryptPrivateKey(byte[] data, char[] password)
+ throws IOException, NoSuchAlgorithmException, UnrecoverableKeyException
+ {
+ byte[] key = null;
+
+ try {
+ // create AlgorithmParameters
+ AlgorithmParameters algParams =
+ getAlgorithmParameters("PBEWithSHA1AndDESede");
+
+ // Use JCE
+ SecretKey skey = getPBEKey(password);
+ Cipher cipher = Cipher.getInstance("PBEWithSHA1AndDESede");
+ cipher.init(Cipher.ENCRYPT_MODE, skey, algParams);
+ byte[] encryptedKey = cipher.doFinal(data);
+
+ // wrap encrypted private key in EncryptedPrivateKeyInfo
+ // as defined in PKCS#8
+ AlgorithmId algid =
+ new AlgorithmId(pbeWithSHAAnd3KeyTripleDESCBC_OID, algParams);
+ EncryptedPrivateKeyInfo encrInfo =
+ new EncryptedPrivateKeyInfo(algid, encryptedKey);
+ key = encrInfo.getEncoded();
+ } catch (Exception e) {
+ UnrecoverableKeyException uke =
+ new UnrecoverableKeyException("Encrypt Private Key failed: "
+ + e.getMessage());
+ uke.initCause(e);
+ throw uke;
+ }
+
+ return key;
+ }
+
+
+}
+
--- a/jdk/src/java.base/macosx/native/libjava/ProcessHandleImpl_macosx.c Thu Aug 20 12:29:58 2015 -0700
+++ b/jdk/src/java.base/macosx/native/libjava/ProcessHandleImpl_macosx.c Wed Jul 05 20:46:25 2017 +0200
@@ -28,6 +28,8 @@
#include "java_lang_ProcessHandleImpl.h"
#include "java_lang_ProcessHandleImpl_Info.h"
+#include "ProcessHandleImpl_unix.h"
+
#include <stdio.h>
#include <errno.h>
#include <signal.h>
@@ -38,144 +40,15 @@
#include <sys/sysctl.h>
/**
- * Implementations of ProcessHandleImpl functions for MAC OS X;
- * are NOT common to all Unix variants.
+ * Implementation of native ProcessHandleImpl functions for MAC OS X.
+ * See ProcessHandleImpl_unix.c for more details.
*/
-static void getStatInfo(JNIEnv *env, jobject jinfo, pid_t pid);
-static void getCmdlineInfo(JNIEnv *env, jobject jinfo, pid_t pid);
-
-/*
- * Common Unix function to lookup the uid and return the user name.
- */
-extern jstring uidToUser(JNIEnv* env, uid_t uid);
-
-/* Field id for jString 'command' in java.lang.ProcessHandle.Info */
-static jfieldID ProcessHandleImpl_Info_commandID;
-
-/* Field id for jString[] 'arguments' in java.lang.ProcessHandle.Info */
-static jfieldID ProcessHandleImpl_Info_argumentsID;
-
-/* Field id for jlong 'totalTime' in java.lang.ProcessHandle.Info */
-static jfieldID ProcessHandleImpl_Info_totalTimeID;
-
-/* Field id for jlong 'startTime' in java.lang.ProcessHandle.Info */
-static jfieldID ProcessHandleImpl_Info_startTimeID;
-
-/* Field id for jString 'user' in java.lang.ProcessHandleImpl.Info */
-static jfieldID ProcessHandleImpl_Info_userID;
-
-/* static value for clock ticks per second. */
-static long clock_ticks_per_second;
-
-/**************************************************************
- * Static method to initialize field IDs and the ticks per second rate.
- *
- * Class: java_lang_ProcessHandleImpl_Info
- * Method: initIDs
- * Signature: ()V
- */
-JNIEXPORT void JNICALL
-Java_java_lang_ProcessHandleImpl_00024Info_initIDs(JNIEnv *env, jclass clazz) {
- CHECK_NULL(ProcessHandleImpl_Info_commandID =
- (*env)->GetFieldID(env, clazz, "command", "Ljava/lang/String;"));
- CHECK_NULL(ProcessHandleImpl_Info_argumentsID =
- (*env)->GetFieldID(env, clazz, "arguments", "[Ljava/lang/String;"));
- CHECK_NULL(ProcessHandleImpl_Info_totalTimeID =
- (*env)->GetFieldID(env, clazz, "totalTime", "J"));
- CHECK_NULL(ProcessHandleImpl_Info_startTimeID =
- (*env)->GetFieldID(env, clazz, "startTime", "J"));
- CHECK_NULL(ProcessHandleImpl_Info_userID =
- (*env)->GetFieldID(env, clazz, "user", "Ljava/lang/String;"));
-}
-/**************************************************************
- * Static method to initialize the ticks per second rate.
- *
- * Class: java_lang_ProcessHandleImpl
- * Method: initNative
- * Signature: ()V
- */
-JNIEXPORT void JNICALL
-Java_java_lang_ProcessHandleImpl_initNative(JNIEnv *env, jclass clazz) {
- clock_ticks_per_second = sysconf(_SC_CLK_TCK);
-}
-
-/*
- * Check if a process is alive.
- * Return the start time (ms since 1970) if it is available.
- * If the start time is not available return 0.
- * If the pid is invalid, return -1.
- *
- * Class: java_lang_ProcessHandleImpl
- * Method: isAlive0
- * Signature: (J)J
- */
-JNIEXPORT jlong JNICALL
-Java_java_lang_ProcessHandleImpl_isAlive0(JNIEnv *env, jobject obj, jlong jpid) {
- pid_t pid = (pid_t) jpid;
- struct kinfo_proc kp;
- size_t bufSize = sizeof kp;
-
- // Read the process info for the specific pid
- int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PID, pid};
-
- if (sysctl(mib, 4, &kp, &bufSize, NULL, 0) < 0) {
- return (errno == EINVAL) ? -1 : 0;
- } else {
- return (bufSize == 0) ? -1 :
- (jlong) (kp.kp_proc.p_starttime.tv_sec * 1000
- + kp.kp_proc.p_starttime.tv_usec / 1000);
- }
-}
-
-/*
- * Returns the parent pid of the requested pid.
- *
- * Class: java_lang_ProcessHandleImpl
- * Method: parent0
- * Signature: (J)J
- */
-JNIEXPORT jlong JNICALL
-Java_java_lang_ProcessHandleImpl_parent0(JNIEnv *env,
- jobject obj,
- jlong jpid,
- jlong startTime) {
- pid_t pid = (pid_t) jpid;
- pid_t ppid = -1;
-
- if (pid == getpid()) {
- ppid = getppid();
- } else {
- const pid_t pid = (pid_t) jpid;
- struct kinfo_proc kp;
- size_t bufSize = sizeof kp;
-
- // Read the process info for the specific pid
- int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PID, pid};
- if (sysctl(mib, 4, &kp, &bufSize, NULL, 0) < 0) {
- JNU_ThrowByNameWithLastError(env,
- "java/lang/RuntimeException", "sysctl failed");
- return -1;
- }
- // If the buffer is full and for the pid requested then check the start
- if (bufSize > 0 && kp.kp_proc.p_pid == pid) {
- jlong start = (jlong) (kp.kp_proc.p_starttime.tv_sec * 1000
- + kp.kp_proc.p_starttime.tv_usec / 1000);
- if (start == startTime || start == 0 || startTime == 0) {
- ppid = kp.kp_eproc.e_ppid;
- }
- }
- }
- return (jlong) ppid;
-}
+void os_initNative(JNIEnv *env, jclass clazz) {}
/*
* Returns the children of the requested pid and optionally each parent.
*
- * Class: java_lang_ProcessHandleImpl
- * Method: getProcessPids0
- * Signature: (J[J[J)I
- *
* Use sysctl to accumulate any process whose parent pid is zero or matches.
* The resulting pids are stored into the array of longs.
* The number of pids is returned if they all fit.
@@ -183,13 +56,8 @@
* If the array is too short, excess pids are not stored and
* the desired length is returned.
*/
-JNIEXPORT jint JNICALL
-Java_java_lang_ProcessHandleImpl_getProcessPids0(JNIEnv *env,
- jclass clazz,
- jlong jpid,
- jlongArray jarray,
- jlongArray jparentArray,
- jlongArray jstimesArray) {
+jint os_getChildren(JNIEnv *env, jlong jpid, jlongArray jarray,
+ jlongArray jparentArray, jlongArray jstimesArray) {
jlong* pids = NULL;
jlong* ppids = NULL;
jlong* stimes = NULL;
@@ -303,35 +171,17 @@
return count;
}
-/**************************************************************
- * Implementation of ProcessHandleImpl_Info native methods.
- */
-
-/*
- * Fill in the Info object from the OS information about the process.
- *
- * Class: java_lang_ProcessHandleImpl
- * Method: info0
- * Signature: (J)I
+/**
+ * Use sysctl and return the ppid, total cputime and start time.
+ * Return: -1 is fail; >= 0 is parent pid
+ * 'total' will contain the running time of 'pid' in nanoseconds.
+ * 'start' will contain the start time of 'pid' in milliseconds since epoch.
*/
-JNIEXPORT void JNICALL
-Java_java_lang_ProcessHandleImpl_00024Info_info0(JNIEnv *env,
- jobject jinfo,
- jlong jpid) {
- pid_t pid = (pid_t) jpid;
- getStatInfo(env, jinfo, pid);
- getCmdlineInfo(env, jinfo, pid);
-}
-
-/**
- * Read /proc/<pid>/stat and fill in the fields of the Info object.
- * The executable name, plus the user, system, and start times are gathered.
- */
-static void getStatInfo(JNIEnv *env, jobject jinfo, pid_t jpid) {
- jlong totalTime; // nanoseconds
- unsigned long long startTime; // milliseconds
+pid_t os_getParentPidAndTimings(JNIEnv *env, pid_t jpid,
+ jlong *totalTime, jlong *startTime) {
const pid_t pid = (pid_t) jpid;
+ pid_t ppid = -1;
struct kinfo_proc kp;
size_t bufSize = sizeof kp;
@@ -339,92 +189,70 @@
int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PID, pid};
if (sysctl(mib, 4, &kp, &bufSize, NULL, 0) < 0) {
- if (errno == EINVAL) {
- return;
- } else {
- JNU_ThrowByNameWithLastError(env,
- "java/lang/RuntimeException", "sysctl failed");
- }
- return;
+ JNU_ThrowByNameWithLastError(env,
+ "java/lang/RuntimeException", "sysctl failed");
+ return -1;
}
-
- // Convert the UID to the username
- jstring name = NULL;
- CHECK_NULL((name = uidToUser(env, kp.kp_eproc.e_ucred.cr_uid)));
- (*env)->SetObjectField(env, jinfo, ProcessHandleImpl_Info_userID, name);
- JNU_CHECK_EXCEPTION(env);
-
- startTime = kp.kp_proc.p_starttime.tv_sec * 1000 +
- kp.kp_proc.p_starttime.tv_usec / 1000;
-
- (*env)->SetLongField(env, jinfo, ProcessHandleImpl_Info_startTimeID, startTime);
- JNU_CHECK_EXCEPTION(env);
+ if (bufSize > 0 && kp.kp_proc.p_pid == pid) {
+ *startTime = (jlong) (kp.kp_proc.p_starttime.tv_sec * 1000 +
+ kp.kp_proc.p_starttime.tv_usec / 1000);
+ ppid = kp.kp_eproc.e_ppid;
+ }
// Get cputime if for current process
if (pid == getpid()) {
struct rusage usage;
- if (getrusage(RUSAGE_SELF, &usage) != 0) {
- return;
+ if (getrusage(RUSAGE_SELF, &usage) == 0) {
+ jlong microsecs =
+ usage.ru_utime.tv_sec * 1000 * 1000 + usage.ru_utime.tv_usec +
+ usage.ru_stime.tv_sec * 1000 * 1000 + usage.ru_stime.tv_usec;
+ *totalTime = microsecs * 1000;
}
- jlong microsecs =
- usage.ru_utime.tv_sec * 1000 * 1000 + usage.ru_utime.tv_usec +
- usage.ru_stime.tv_sec * 1000 * 1000 + usage.ru_stime.tv_usec;
- totalTime = microsecs * 1000;
- (*env)->SetLongField(env, jinfo, ProcessHandleImpl_Info_totalTimeID, totalTime);
- JNU_CHECK_EXCEPTION(env);
}
+
+ return ppid;
+
}
/**
- * Construct the argument array by parsing the arguments from the sequence of arguments.
+ * Return the uid of a process or -1 on error
*/
-static int fillArgArray(JNIEnv *env, jobject jinfo, int nargs,
- const char *cp, const char *argsEnd) {
- jstring str = NULL;
- jobject argsArray;
- int i;
-
- if (nargs < 1) {
- return 0;
- }
- // Create a String array for nargs-1 elements
- CHECK_NULL_RETURN((argsArray = (*env)->NewObjectArray(env,
- nargs - 1, JNU_ClassString(env), NULL)), -1);
+static uid_t getUID(pid_t pid) {
+ struct kinfo_proc kp;
+ size_t bufSize = sizeof kp;
- for (i = 0; i < nargs - 1; i++) {
- // skip to the next argument; omits arg[0]
- cp += strnlen(cp, (argsEnd - cp)) + 1;
-
- if (cp > argsEnd || *cp == '\0') {
- return -2; // Off the end pointer or an empty argument is an error
- }
+ // Read the process info for the specific pid
+ int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PID, pid};
- CHECK_NULL_RETURN((str = JNU_NewStringPlatform(env, cp)), -1);
-
- (*env)->SetObjectArrayElement(env, argsArray, i, str);
- JNU_CHECK_EXCEPTION_RETURN(env, -3);
+ if (sysctl(mib, 4, &kp, &bufSize, NULL, 0) == 0) {
+ if (bufSize > 0 && kp.kp_proc.p_pid == pid) {
+ return kp.kp_eproc.e_ucred.cr_uid;
+ }
}
- (*env)->SetObjectField(env, jinfo, ProcessHandleImpl_Info_argumentsID, argsArray);
- JNU_CHECK_EXCEPTION_RETURN(env, -4);
- return 0;
+ return (uid_t)-1;
}
/**
* Retrieve the command and arguments for the process and store them
* into the Info object.
*/
-static void getCmdlineInfo(JNIEnv *env, jobject jinfo, pid_t pid) {
+void os_getCmdlineAndUserInfo(JNIEnv *env, jobject jinfo, pid_t pid) {
int mib[3], maxargs, nargs, i;
size_t size;
char *args, *cp, *sp, *np;
+ // Get the UID first. This is done here because it is cheap to do it here
+ // on other platforms like Linux/Solaris/AIX where the uid comes from the
+ // same source like the command line info.
+ unix_getUserInfo(env, jinfo, getUID(pid));
+
// Get the maximum size of the arguments
mib[0] = CTL_KERN;
mib[1] = KERN_ARGMAX;
size = sizeof(maxargs);
if (sysctl(mib, 2, &maxargs, &size, NULL, 0) == -1) {
JNU_ThrowByNameWithLastError(env,
- "java/lang/RuntimeException", "sysctl failed");
+ "java/lang/RuntimeException", "sysctl failed");
return;
}
@@ -437,7 +265,7 @@
do { // a block to break out of on error
char *argsEnd;
- jstring str = NULL;
+ jstring cmdexe = NULL;
mib[0] = CTL_KERN;
mib[1] = KERN_PROCARGS2;
@@ -445,7 +273,7 @@
size = (size_t) maxargs;
if (sysctl(mib, 3, args, &size, NULL, 0) == -1) {
if (errno != EINVAL) {
- JNU_ThrowByNameWithLastError(env,
+ JNU_ThrowByNameWithLastError(env,
"java/lang/RuntimeException", "sysctl failed");
}
break;
@@ -456,11 +284,7 @@
argsEnd = &args[size];
// Store the command executable path
- if ((str = JNU_NewStringPlatform(env, cp)) == NULL) {
- break;
- }
- (*env)->SetObjectField(env, jinfo, ProcessHandleImpl_Info_commandID, str);
- if ((*env)->ExceptionCheck(env)) {
+ if ((cmdexe = JNU_NewStringPlatform(env, cp)) == NULL) {
break;
}
@@ -471,7 +295,7 @@
}
}
- fillArgArray(env, jinfo, nargs, cp, argsEnd);
+ unix_fillArgArray(env, jinfo, nargs, cp, argsEnd, cmdexe, NULL);
} while (0);
// Free the arg buffer
free(args);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/macosx/native/libosxsecurity/KeystoreImpl.m Wed Jul 05 20:46:25 2017 +0200
@@ -0,0 +1,589 @@
+/*
+ * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#import "apple_security_KeychainStore.h"
+
+#import <Security/Security.h>
+#import <Security/SecImportExport.h>
+#import <CoreServices/CoreServices.h> // (for require() macros)
+#import <JavaNativeFoundation/JavaNativeFoundation.h>
+
+
+static JNF_CLASS_CACHE(jc_KeychainStore, "apple/security/KeychainStore");
+static JNF_MEMBER_CACHE(jm_createTrustedCertEntry, jc_KeychainStore, "createTrustedCertEntry", "(Ljava/lang/String;JJ[B)V");
+static JNF_MEMBER_CACHE(jm_createKeyEntry, jc_KeychainStore, "createKeyEntry", "(Ljava/lang/String;JJ[J[[B)V");
+
+static jstring getLabelFromItem(JNIEnv *env, SecKeychainItemRef inItem)
+{
+ OSStatus status;
+ jstring returnValue = NULL;
+ char *attribCString = NULL;
+
+ SecKeychainAttribute itemAttrs[] = { { kSecLabelItemAttr, 0, NULL } };
+ SecKeychainAttributeList attrList = { sizeof(itemAttrs) / sizeof(itemAttrs[0]), itemAttrs };
+
+ status = SecKeychainItemCopyContent(inItem, NULL, &attrList, NULL, NULL);
+
+ if(status) {
+ cssmPerror("getLabelFromItem: SecKeychainItemCopyContent", status);
+ goto errOut;
+ }
+
+ attribCString = malloc(itemAttrs[0].length + 1);
+ strncpy(attribCString, itemAttrs[0].data, itemAttrs[0].length);
+ attribCString[itemAttrs[0].length] = '\0';
+ returnValue = (*env)->NewStringUTF(env, attribCString);
+
+errOut:
+ SecKeychainItemFreeContent(&attrList, NULL);
+ if (attribCString) free(attribCString);
+ return returnValue;
+}
+
+static jlong getModDateFromItem(JNIEnv *env, SecKeychainItemRef inItem)
+{
+ OSStatus status;
+ SecKeychainAttribute itemAttrs[] = { { kSecModDateItemAttr, 0, NULL } };
+ SecKeychainAttributeList attrList = { sizeof(itemAttrs) / sizeof(itemAttrs[0]), itemAttrs };
+ jlong returnValue = 0;
+
+ status = SecKeychainItemCopyContent(inItem, NULL, &attrList, NULL, NULL);
+
+ if(status) {
+ // This is almost always missing, so don't dump an error.
+ // cssmPerror("getModDateFromItem: SecKeychainItemCopyContent", status);
+ goto errOut;
+ }
+
+ memcpy(&returnValue, itemAttrs[0].data, itemAttrs[0].length);
+
+errOut:
+ SecKeychainItemFreeContent(&attrList, NULL);
+ return returnValue;
+}
+
+static void setLabelForItem(NSString *inLabel, SecKeychainItemRef inItem)
+{
+ OSStatus status;
+ const char *labelCString = [inLabel UTF8String];
+
+ // Set up attribute vector (each attribute consists of {tag, length, pointer}):
+ SecKeychainAttribute attrs[] = {
+ { kSecLabelItemAttr, strlen(labelCString), (void *)labelCString }
+ };
+
+ const SecKeychainAttributeList attributes = { sizeof(attrs) / sizeof(attrs[0]), attrs };
+
+ // Not changing data here, just attributes.
+ status = SecKeychainItemModifyContent(inItem, &attributes, 0, NULL);
+
+ if(status) {
+ cssmPerror("setLabelForItem: SecKeychainItemModifyContent", status);
+ }
+}
+
+/*
+ * Given a SecIdentityRef, do our best to construct a complete, ordered, and
+ * verified cert chain, returning the result in a CFArrayRef. The result is
+ * can be passed back to Java as a chain for a private key.
+ */
+static OSStatus completeCertChain(
+ SecIdentityRef identity,
+ SecCertificateRef trustedAnchor, // optional additional trusted anchor
+ bool includeRoot, // include the root in outArray
+ CFArrayRef *outArray) // created and RETURNED
+{
+ SecTrustRef secTrust = NULL;
+ SecPolicyRef policy = NULL;
+ SecPolicySearchRef policySearch = NULL;
+ SecTrustResultType secTrustResult;
+ CSSM_TP_APPLE_EVIDENCE_INFO *dummyEv; // not used
+ CFArrayRef certChain = NULL; // constructed chain, CERTS ONLY
+ CFMutableArrayRef subjCerts; // passed to SecTrust
+ CFMutableArrayRef certArray; // returned array starting with
+ // identity
+ CFIndex numResCerts;
+ CFIndex dex;
+ OSStatus ortn;
+ SecCertificateRef certRef;
+
+ /* First element in out array is the SecIdentity */
+ certArray = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+ CFArrayAppendValue(certArray, identity);
+
+ /* the single element in certs-to-be-evaluated comes from the identity */
+ ortn = SecIdentityCopyCertificate(identity, &certRef);
+ if(ortn) {
+ /* should never happen */
+ cssmPerror("SecIdentityCopyCertificate", ortn);
+ return ortn;
+ }
+
+ /*
+ * Now use SecTrust to get a complete cert chain, using all of the
+ * user's keychains to look for intermediate certs.
+ * NOTE this does NOT handle root certs which are not in the system
+ * root cert DB.
+ */
+ subjCerts = CFArrayCreateMutable(NULL, 1, &kCFTypeArrayCallBacks);
+ CFArraySetValueAtIndex(subjCerts, 0, certRef);
+
+ /* the array owns the subject cert ref now */
+ CFRelease(certRef);
+
+ /* Get a SecPolicyRef for generic X509 cert chain verification */
+ ortn = SecPolicySearchCreate(CSSM_CERT_X_509v3,
+ &CSSMOID_APPLE_X509_BASIC,
+ NULL, // value
+ &policySearch);
+ if(ortn) {
+ /* should never happen */
+ cssmPerror("SecPolicySearchCreate", ortn);
+ goto errOut;
+ }
+ ortn = SecPolicySearchCopyNext(policySearch, &policy);
+ if(ortn) {
+ /* should never happen */
+ cssmPerror("SecPolicySearchCopyNext", ortn);
+ goto errOut;
+ }
+
+ /* build a SecTrustRef for specified policy and certs */
+ ortn = SecTrustCreateWithCertificates(subjCerts,
+ policy, &secTrust);
+ if(ortn) {
+ cssmPerror("SecTrustCreateWithCertificates", ortn);
+ goto errOut;
+ }
+
+ if(trustedAnchor) {
+ /*
+ * Tell SecTrust to trust this one in addition to the current
+ * trusted system-wide anchors.
+ */
+ CFMutableArrayRef newAnchors;
+ CFArrayRef currAnchors;
+
+ ortn = SecTrustCopyAnchorCertificates(&currAnchors);
+ if(ortn) {
+ /* should never happen */
+ cssmPerror("SecTrustCopyAnchorCertificates", ortn);
+ goto errOut;
+ }
+ newAnchors = CFArrayCreateMutableCopy(NULL,
+ CFArrayGetCount(currAnchors) + 1,
+ currAnchors);
+ CFRelease(currAnchors);
+ CFArrayAppendValue(newAnchors, trustedAnchor);
+ ortn = SecTrustSetAnchorCertificates(secTrust, newAnchors);
+ CFRelease(newAnchors);
+ if(ortn) {
+ cssmPerror("SecTrustSetAnchorCertificates", ortn);
+ goto errOut;
+ }
+ }
+
+ /* evaluate: GO */
+ ortn = SecTrustEvaluate(secTrust, &secTrustResult);
+ if(ortn) {
+ cssmPerror("SecTrustEvaluate", ortn);
+ goto errOut;
+ }
+ switch(secTrustResult) {
+ case kSecTrustResultUnspecified:
+ /* cert chain valid, no special UserTrust assignments; drop thru */
+ case kSecTrustResultProceed:
+ /* cert chain valid AND user explicitly trusts this */
+ break;
+ default:
+ /*
+ * Cert chain construction failed.
+ * Just go with the single subject cert we were given; maybe the
+ * peer can complete the chain.
+ */
+ ortn = noErr;
+ goto errOut;
+ }
+
+ /* get resulting constructed cert chain */
+ ortn = SecTrustGetResult(secTrust, &secTrustResult, &certChain, &dummyEv);
+ if(ortn) {
+ cssmPerror("SecTrustEvaluate", ortn);
+ goto errOut;
+ }
+
+ /*
+ * Copy certs from constructed chain to our result array, skipping
+ * the leaf (which is already there, as a SecIdentityRef) and possibly
+ * a root.
+ */
+ numResCerts = CFArrayGetCount(certChain);
+ if(numResCerts < 1) {
+ /*
+ * Can't happen: If chain doesn't verify to a root, we'd
+ * have bailed after SecTrustEvaluate().
+ */
+ ortn = noErr;
+ goto errOut;
+ }
+ if(!includeRoot) {
+ /* skip the last (root) cert) */
+ numResCerts--;
+ }
+ for(dex=1; dex<numResCerts; dex++) {
+ certRef = (SecCertificateRef)CFArrayGetValueAtIndex(certChain, dex);
+ CFArrayAppendValue(certArray, certRef);
+ }
+errOut:
+ /* clean up */
+ if(secTrust) {
+ CFRelease(secTrust);
+ }
+ if(subjCerts) {
+ CFRelease(subjCerts);
+ }
+ if(policy) {
+ CFRelease(policy);
+ }
+ if(policySearch) {
+ CFRelease(policySearch);
+ }
+ *outArray = certArray;
+ return ortn;
+}
+
+static void addIdentitiesToKeystore(JNIEnv *env, jobject keyStore)
+{
+ // Search the user keychain list for all identities. Identities are a certificate/private key association that
+ // can be chosen for a purpose such as signing or an SSL connection.
+ SecIdentitySearchRef identitySearch = NULL;
+ // Pass 0 if you want all identities returned by this search
+ OSStatus err = SecIdentitySearchCreate(NULL, 0, &identitySearch);
+ SecIdentityRef theIdentity = NULL;
+ OSErr searchResult = noErr;
+
+ do {
+ searchResult = SecIdentitySearchCopyNext(identitySearch, &theIdentity);
+
+ if (searchResult == noErr) {
+ // Get the cert from the identity, then generate a chain.
+ SecCertificateRef certificate;
+ SecIdentityCopyCertificate(theIdentity, &certificate);
+ CFArrayRef certChain = NULL;
+
+ // *** Should do something with this error...
+ err = completeCertChain(theIdentity, NULL, TRUE, &certChain);
+
+ CFIndex i, certCount = CFArrayGetCount(certChain);
+
+ // Make a java array of certificate data from the chain.
+ jclass byteArrayClass = (*env)->FindClass(env, "[B");
+ if (byteArrayClass == NULL) {
+ goto errOut;
+ }
+ jobjectArray javaCertArray = (*env)->NewObjectArray(env, certCount, byteArrayClass, NULL);
+ // Cleanup first then check for a NULL return code
+ (*env)->DeleteLocalRef(env, byteArrayClass);
+ if (javaCertArray == NULL) {
+ goto errOut;
+ }
+
+ // And, make an array of the certificate refs.
+ jlongArray certRefArray = (*env)->NewLongArray(env, certCount);
+ if (certRefArray == NULL) {
+ goto errOut;
+ }
+
+ SecCertificateRef currCertRef = NULL;
+
+ for (i = 0; i < certCount; i++) {
+ CSSM_DATA currCertData;
+
+ if (i == 0)
+ currCertRef = certificate;
+ else
+ currCertRef = (SecCertificateRef)CFArrayGetValueAtIndex(certChain, i);
+
+ bzero(&currCertData, sizeof(CSSM_DATA));
+ err = SecCertificateGetData(currCertRef, &currCertData);
+ jbyteArray encodedCertData = (*env)->NewByteArray(env, currCertData.Length);
+ if (encodedCertData == NULL) {
+ goto errOut;
+ }
+ (*env)->SetByteArrayRegion(env, encodedCertData, 0, currCertData.Length, (jbyte *)currCertData.Data);
+ (*env)->SetObjectArrayElement(env, javaCertArray, i, encodedCertData);
+ jlong certRefElement = ptr_to_jlong(currCertRef);
+ (*env)->SetLongArrayRegion(env, certRefArray, i, 1, &certRefElement);
+ }
+
+ // Get the private key. When needed we'll export the data from it later.
+ SecKeyRef privateKeyRef;
+ err = SecIdentityCopyPrivateKey(theIdentity, &privateKeyRef);
+
+ // Find the label. It's a 'blob', but we interpret as characters.
+ jstring alias = getLabelFromItem(env, (SecKeychainItemRef)certificate);
+ if (alias == NULL) {
+ goto errOut;
+ }
+
+ // Find the creation date.
+ jlong creationDate = getModDateFromItem(env, (SecKeychainItemRef)certificate);
+
+ // Call back to the Java object to create Java objects corresponding to this security object.
+ jlong nativeKeyRef = ptr_to_jlong(privateKeyRef);
+ JNFCallVoidMethod(env, keyStore, jm_createKeyEntry, alias, creationDate, nativeKeyRef, certRefArray, javaCertArray);
+ }
+ } while (searchResult == noErr);
+
+errOut:
+ if (identitySearch != NULL) {
+ CFRelease(identitySearch);
+ }
+}
+
+static void addCertificatesToKeystore(JNIEnv *env, jobject keyStore)
+{
+ // Search the user keychain list for all X509 certificates.
+ SecKeychainSearchRef keychainItemSearch = NULL;
+ OSStatus err = SecKeychainSearchCreateFromAttributes(NULL, kSecCertificateItemClass, NULL, &keychainItemSearch);
+ SecKeychainItemRef theItem = NULL;
+ OSErr searchResult = noErr;
+
+ do {
+ searchResult = SecKeychainSearchCopyNext(keychainItemSearch, &theItem);
+
+ if (searchResult == noErr) {
+ // Make a byte array with the DER-encoded contents of the certificate.
+ SecCertificateRef certRef = (SecCertificateRef)theItem;
+ CSSM_DATA currCertificate;
+ err = SecCertificateGetData(certRef, &currCertificate);
+ jbyteArray certData = (*env)->NewByteArray(env, currCertificate.Length);
+ if (certData == NULL) {
+ goto errOut;
+ }
+ (*env)->SetByteArrayRegion(env, certData, 0, currCertificate.Length, (jbyte *)currCertificate.Data);
+
+ // Find the label. It's a 'blob', but we interpret as characters.
+ jstring alias = getLabelFromItem(env, theItem);
+ if (alias == NULL) {
+ goto errOut;
+ }
+
+ // Find the creation date.
+ jlong creationDate = getModDateFromItem(env, theItem);
+
+ // Call back to the Java object to create Java objects corresponding to this security object.
+ jlong nativeRef = ptr_to_jlong(certRef);
+ JNFCallVoidMethod(env, keyStore, jm_createTrustedCertEntry, alias, nativeRef, creationDate, certData);
+ }
+ } while (searchResult == noErr);
+
+errOut:
+ if (keychainItemSearch != NULL) {
+ CFRelease(keychainItemSearch);
+ }
+}
+
+/*
+ * Class: apple_security_KeychainStore
+ * Method: _getEncodedKeyData
+ * Signature: (J)[B
+ */
+JNIEXPORT jbyteArray JNICALL Java_apple_security_KeychainStore__1getEncodedKeyData
+(JNIEnv *env, jobject this, jlong keyRefLong, jcharArray passwordObj)
+{
+ SecKeyRef keyRef = (SecKeyRef)jlong_to_ptr(keyRefLong);
+ SecKeyImportExportParameters paramBlock;
+ OSStatus err = noErr;
+ CFDataRef exportedData = NULL;
+ jbyteArray returnValue = NULL;
+ CFStringRef passwordStrRef = NULL;
+
+ jsize passwordLen = 0;
+ jchar *passwordChars = NULL;
+
+ if (passwordObj) {
+ passwordLen = (*env)->GetArrayLength(env, passwordObj);
+
+ if (passwordLen > 0) {
+ passwordChars = (*env)->GetCharArrayElements(env, passwordObj, NULL);
+ if (passwordChars == NULL) {
+ goto errOut;
+ }
+ passwordStrRef = CFStringCreateWithCharacters(kCFAllocatorDefault, passwordChars, passwordLen);
+ }
+ }
+
+ paramBlock.version = SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION;
+ // Note that setting the flags field **requires** you to pass in a password of some kind. The keychain will not prompt you.
+ paramBlock.flags = 0;
+ paramBlock.passphrase = passwordStrRef;
+ paramBlock.alertTitle = NULL;
+ paramBlock.alertPrompt = NULL;
+ paramBlock.accessRef = NULL;
+ paramBlock.keyUsage = CSSM_KEYUSE_ANY;
+ paramBlock.keyAttributes = CSSM_KEYATTR_RETURN_DEFAULT;
+
+ err = SecKeychainItemExport(keyRef, kSecFormatPKCS12, 0, ¶mBlock, &exportedData);
+
+ if (err == noErr) {
+ CFIndex size = CFDataGetLength(exportedData);
+ returnValue = (*env)->NewByteArray(env, size);
+ if (returnValue == NULL) {
+ goto errOut;
+ }
+ (*env)->SetByteArrayRegion(env, returnValue, 0, size, (jbyte *)CFDataGetBytePtr(exportedData));
+ }
+
+errOut:
+ if (exportedData) CFRelease(exportedData);
+ if (passwordStrRef) CFRelease(passwordStrRef);
+
+ return returnValue;
+}
+
+
+/*
+ * Class: apple_security_KeychainStore
+ * Method: _scanKeychain
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_apple_security_KeychainStore__1scanKeychain
+(JNIEnv *env, jobject this)
+{
+ // Look for 'identities' -- private key and certificate chain pairs -- and add those.
+ // Search for these first, because a certificate that's found here as part of an identity will show up
+ // again later as a certificate.
+ addIdentitiesToKeystore(env, this);
+
+ // Scan current keychain for trusted certificates.
+ addCertificatesToKeystore(env, this);
+
+}
+
+/*
+ * Class: apple_security_KeychainStore
+ * Method: _addItemToKeychain
+ * Signature: (Ljava/lang/String;[B)I
+*/
+JNIEXPORT jlong JNICALL Java_apple_security_KeychainStore__1addItemToKeychain
+(JNIEnv *env, jobject this, jstring alias, jboolean isCertificate, jbyteArray rawDataObj, jcharArray passwordObj)
+{
+ OSStatus err;
+ jlong returnValue = 0;
+
+JNF_COCOA_ENTER(env);
+
+ jsize dataSize = (*env)->GetArrayLength(env, rawDataObj);
+ jbyte *rawData = (*env)->GetByteArrayElements(env, rawDataObj, NULL);
+ if (rawData == NULL) {
+ goto errOut;
+ }
+
+ CFDataRef cfDataToImport = CFDataCreate(kCFAllocatorDefault, (UInt8 *)rawData, dataSize);
+ CFArrayRef createdItems = NULL;
+
+ SecKeychainRef defaultKeychain = NULL;
+ SecKeychainCopyDefault(&defaultKeychain);
+
+ SecExternalItemType dataType = (isCertificate == JNI_TRUE ? kSecFormatX509Cert : kSecFormatWrappedPKCS8);
+
+ // Convert the password obj into a CFStringRef that the keychain importer can use for encryption.
+ SecKeyImportExportParameters paramBlock;
+ CFStringRef passwordStrRef = NULL;
+
+ jsize passwordLen = 0;
+ jchar *passwordChars = NULL;
+
+ if (passwordObj) {
+ passwordLen = (*env)->GetArrayLength(env, passwordObj);
+ passwordChars = (*env)->GetCharArrayElements(env, passwordObj, NULL);
+ passwordStrRef = CFStringCreateWithCharacters(kCFAllocatorDefault, passwordChars, passwordLen);
+ }
+
+ paramBlock.version = SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION;
+ // Note that setting the flags field **requires** you to pass in a password of some kind. The keychain will not prompt you.
+ paramBlock.flags = 0;
+ paramBlock.passphrase = passwordStrRef;
+ paramBlock.alertTitle = NULL;
+ paramBlock.alertPrompt = NULL;
+ paramBlock.accessRef = NULL;
+ paramBlock.keyUsage = CSSM_KEYUSE_ANY;
+ paramBlock.keyAttributes = CSSM_KEYATTR_RETURN_DEFAULT;
+
+ err = SecKeychainItemImport(cfDataToImport, NULL, &dataType, NULL,
+ 0, ¶mBlock, defaultKeychain, &createdItems);
+
+ if (err == noErr) {
+ SecKeychainItemRef anItem = (SecKeychainItemRef)CFArrayGetValueAtIndex(createdItems, 0);
+
+ // Don't bother labeling keys. They become part of an identity, and are not an accessible part of the keychain.
+ if (CFGetTypeID(anItem) == SecCertificateGetTypeID()) {
+ setLabelForItem(JNFJavaToNSString(env, alias), anItem);
+ }
+
+ // Retain the item, since it will be released once when the array holding it gets released.
+ CFRetain(anItem);
+ returnValue = ptr_to_jlong(anItem);
+ } else {
+ cssmPerror("_addItemToKeychain: SecKeychainItemImport", err);
+ }
+
+ (*env)->ReleaseByteArrayElements(env, rawDataObj, rawData, JNI_ABORT);
+
+ if (createdItems != NULL) {
+ CFRelease(createdItems);
+ }
+
+errOut: ;
+
+JNF_COCOA_EXIT(env);
+
+ return returnValue;
+}
+
+/*
+ * Class: apple_security_KeychainStore
+ * Method: _removeItemFromKeychain
+ * Signature: (J)I
+*/
+JNIEXPORT jint JNICALL Java_apple_security_KeychainStore__1removeItemFromKeychain
+(JNIEnv *env, jobject this, jlong keychainItem)
+{
+ SecKeychainItemRef itemToRemove = jlong_to_ptr(keychainItem);
+ return SecKeychainItemDelete(itemToRemove);
+}
+
+/*
+ * Class: apple_security_KeychainStore
+ * Method: _releaseKeychainItemRef
+ * Signature: (J)V
+ */
+JNIEXPORT void JNICALL Java_apple_security_KeychainStore__1releaseKeychainItemRef
+(JNIEnv *env, jobject this, jlong keychainItem)
+{
+ SecKeychainItemRef itemToFree = jlong_to_ptr(keychainItem);
+ CFRelease(itemToFree);
+}
--- a/jdk/src/java.base/share/classes/java/lang/ProcessHandle.java Thu Aug 20 12:29:58 2015 -0700
+++ b/jdk/src/java.base/share/classes/java/lang/ProcessHandle.java Wed Jul 05 20:46:25 2017 +0200
@@ -225,8 +225,34 @@
public Optional<String> command();
/**
+ * Returns the command line of the process.
+ * <p>
+ * If {@link #command command()} and {@link #arguments arguments()} return
+ * non-empty optionals, this is simply a convenience method which concatenates
+ * the values of the two functions separated by spaces. Otherwise it will return a
+ * best-effort, platform dependent representation of the command line.
+ *
+ * @apiNote Note that the returned executable pathname and the
+ * arguments may be truncated on some platforms due to system
+ * limitations.
+ * <p>
+ * The executable pathname may contain only the
+ * name of the executable without the full path information.
+ * It is undecideable whether white space separates different
+ * arguments or is part of a single argument.
+ *
+ * @return an {@code Optional<String>} of the command line
+ * of the process
+ */
+ public Optional<String> commandLine();
+
+ /**
* Returns an array of Strings of the arguments of the process.
*
+ * @apiNote On some platforms, native applications are free to change
+ * the arguments array after startup and this method may only
+ * show the changed values.
+ *
* @return an {@code Optional<String[]>} of the arguments of the process
*/
public Optional<String[]> arguments();
--- a/jdk/src/java.base/share/classes/java/lang/ProcessHandleImpl.java Thu Aug 20 12:29:58 2015 -0700
+++ b/jdk/src/java.base/share/classes/java/lang/ProcessHandleImpl.java Wed Jul 05 20:46:25 2017 +0200
@@ -472,7 +472,7 @@
/**
* Implementation of ProcessHandle.Info.
* Information snapshot about a process.
- * The attributes of a process vary by operating system and not available
+ * The attributes of a process vary by operating system and are not available
* in all implementations. Additionally, information about other processes
* is limited by the operating system privileges of the process making the request.
* If a value is not available, either a {@code null} or {@code -1} is stored.
@@ -496,6 +496,7 @@
private native void info0(long pid);
String command;
+ String commandLine;
String[] arguments;
long startTime;
long totalTime;
@@ -503,6 +504,7 @@
Info() {
command = null;
+ commandLine = null;
arguments = null;
startTime = -1L;
totalTime = -1L;
@@ -539,6 +541,15 @@
}
@Override
+ public Optional<String> commandLine() {
+ if (command != null && arguments != null) {
+ return Optional.of(command + " " + String.join(" ", arguments));
+ } else {
+ return Optional.ofNullable(commandLine);
+ }
+ }
+
+ @Override
public Optional<String[]> arguments() {
return Optional.ofNullable(arguments);
}
@@ -580,6 +591,11 @@
sb.append("args: ");
sb.append(Arrays.toString(arguments));
}
+ if (commandLine != null) {
+ if (sb.length() != 0) sb.append(", ");
+ sb.append("cmdLine: ");
+ sb.append(commandLine);
+ }
if (startTime > 0) {
if (sb.length() != 0) sb.append(", ");
sb.append("startTime: ");
--- a/jdk/src/java.base/share/classes/java/lang/Shutdown.java Thu Aug 20 12:29:58 2015 -0700
+++ b/jdk/src/java.base/share/classes/java/lang/Shutdown.java Wed Jul 05 20:46:25 2017 +0200
@@ -86,10 +86,10 @@
* to be registered even if the shutdown is in progress.
* @params hook the hook to be registered
*
- * @throw IllegalStateException
- * if registerShutdownInProgress is false and shutdown is in progress; or
- * if registerShutdownInProgress is true and the shutdown process
- * already passes the given slot
+ * @throws IllegalStateException
+ * if registerShutdownInProgress is false and shutdown is in progress; or
+ * if registerShutdownInProgress is true and the shutdown process
+ * already passes the given slot
*/
static void add(int slot, boolean registerShutdownInProgress, Runnable hook) {
synchronized (lock) {
--- a/jdk/src/java.base/share/classes/java/lang/ref/ReferenceQueue.java Thu Aug 20 12:29:58 2015 -0700
+++ b/jdk/src/java.base/share/classes/java/lang/ref/ReferenceQueue.java Wed Jul 05 20:46:25 2017 +0200
@@ -65,10 +65,13 @@
return false;
}
assert queue == this;
- r.queue = ENQUEUED;
r.next = (head == null) ? r : head;
head = r;
queueLength++;
+ // Update r.queue *after* adding to list, to avoid race
+ // with concurrent enqueued checks and fast-path poll().
+ // Volatiles ensure ordering.
+ r.queue = ENQUEUED;
if (r instanceof FinalReference) {
sun.misc.VM.addFinalRefCount(1);
}
@@ -80,10 +83,13 @@
private Reference<? extends T> reallyPoll() { /* Must hold lock */
Reference<? extends T> r = head;
if (r != null) {
+ r.queue = NULL;
+ // Update r.queue *before* removing from list, to avoid
+ // race with concurrent enqueued checks and fast-path
+ // poll(). Volatiles ensure ordering.
@SuppressWarnings("unchecked")
Reference<? extends T> rn = r.next;
head = (rn == r) ? null : rn;
- r.queue = NULL;
r.next = r;
queueLength--;
if (r instanceof FinalReference) {
--- a/jdk/src/java.base/share/classes/java/net/ContentHandler.java Thu Aug 20 12:29:58 2015 -0700
+++ b/jdk/src/java.base/share/classes/java/net/ContentHandler.java Wed Jul 05 20:46:25 2017 +0200
@@ -47,7 +47,7 @@
* If no content handler could be {@linkplain URLConnection#getContent() found},
* URLConnection will look for a content handler in a user-definable set of places.
* Users can define a vertical-bar delimited set of class prefixes
- * to search through by defining the <i>{@value java.net.URLConnection#contentPathProp}</i>
+ * to search through by defining the <i>{@link java.net.URLConnection#contentPathProp}</i>
* property. The class name must be of the form:
* <blockquote>
* <i>{package-prefix}.{major}.{minor}</i>
--- a/jdk/src/java.base/share/classes/java/net/InetSocketAddress.java Thu Aug 20 12:29:58 2015 -0700
+++ b/jdk/src/java.base/share/classes/java/net/InetSocketAddress.java Wed Jul 05 20:46:25 2017 +0200
@@ -206,7 +206,7 @@
* @param hostname the Host name
* @param port The port number
* @throws IllegalArgumentException if the port parameter is outside the range
- * of valid port values, or if the hostname parameter is <TT>null</TT>.
+ * of valid port values, or if the hostname parameter is {@code null}.
* @throws SecurityException if a security manager is present and
* permission to resolve the host name is
* denied.
@@ -244,7 +244,7 @@
* @param port The port number
* @throws IllegalArgumentException if the port parameter is outside
* the range of valid port values, or if the hostname
- * parameter is <TT>null</TT>.
+ * parameter is {@code null}.
* @see #isUnresolved()
* @return a {@code InetSocketAddress} representing the unresolved
* socket address
--- a/jdk/src/java.base/share/classes/java/net/spi/package-info.java Thu Aug 20 12:29:58 2015 -0700
+++ b/jdk/src/java.base/share/classes/java/net/spi/package-info.java Wed Jul 05 20:46:25 2017 +0200
@@ -24,7 +24,7 @@
*/
/**
- * Service-provider classes for the <tt>{@link java.net}</tt> package.
+ * Service-provider classes for the {@link java.net} package.
*
* <p> Only developers who are defining new URL stream handler providers
* should need to make direct use of this package.
--- a/jdk/src/java.base/share/classes/java/nio/Buffer.java Thu Aug 20 12:29:58 2015 -0700
+++ b/jdk/src/java.base/share/classes/java/nio/Buffer.java Wed Jul 05 20:46:25 2017 +0200
@@ -215,8 +215,8 @@
* {@code put(src)} when the parameter is the {@code Buffer} on which the
* method is being invoked.
*
- * @returns IllegalArgumentException
- * With a message indicating equal source and target buffers
+ * @return IllegalArgumentException
+ * With a message indicating equal source and target buffers
*/
static IllegalArgumentException createSameBufferException() {
return new IllegalArgumentException("The source buffer is this buffer");
--- a/jdk/src/java.base/share/classes/java/security/KeyStoreSpi.java Thu Aug 20 12:29:58 2015 -0700
+++ b/jdk/src/java.base/share/classes/java/security/KeyStoreSpi.java Wed Jul 05 20:46:25 2017 +0200
@@ -618,9 +618,12 @@
* @throws IOException if there is an I/O problem with the keystore data.
* @throws NullPointerException if stream is {@code null}.
*
- * @since 1.9
+ * @since 9
*/
public boolean engineProbe(InputStream stream) throws IOException {
+ if (stream == null) {
+ throw new NullPointerException("input stream must not be null");
+ }
return false;
}
}
--- a/jdk/src/java.base/share/classes/java/util/Formatter.java Thu Aug 20 12:29:58 2015 -0700
+++ b/jdk/src/java.base/share/classes/java/util/Formatter.java Wed Jul 05 20:46:25 2017 +0200
@@ -273,6 +273,10 @@
*
* </ol>
*
+ * <p> For category <i>General</i>, <i>Character</i>, <i>Numberic</i>,
+ * <i>Integral</i> and <i>Date/Time</i> conversion, unless otherwise specified,
+ * if the argument <i>arg</i> is {@code null}, then the result is "{@code null}".
+ *
* <p> The following table summarizes the supported conversions. Conversions
* denoted by an upper-case character (i.e. {@code 'B'}, {@code 'H'},
* {@code 'S'}, {@code 'C'}, {@code 'X'}, {@code 'E'}, {@code 'G'},
@@ -301,14 +305,12 @@
*
* <tr><td valign="top"> {@code 'h'}, {@code 'H'}
* <td valign="top"> general
- * <td> If the argument <i>arg</i> is {@code null}, then the result is
- * "{@code null}". Otherwise, the result is obtained by invoking
+ * <td> The result is obtained by invoking
* {@code Integer.toHexString(arg.hashCode())}.
*
* <tr><td valign="top"> {@code 's'}, {@code 'S'}
* <td valign="top"> general
- * <td> If the argument <i>arg</i> is {@code null}, then the result is
- * "{@code null}". If <i>arg</i> implements {@link Formattable}, then
+ * <td> If <i>arg</i> implements {@link Formattable}, then
* {@link Formattable#formatTo arg.formatTo} is invoked. Otherwise, the
* result is obtained by invoking {@code arg.toString()}.
*
@@ -683,6 +685,10 @@
* methods such as {@link String#format(String,Object...) String.format} and
* {@link java.io.PrintStream#printf(String,Object...) PrintStream.printf}.
*
+ * <p> For category <i>General</i>, <i>Character</i>, <i>Numberic</i>,
+ * <i>Integral</i> and <i>Date/Time</i> conversion, unless otherwise specified,
+ * if the argument <i>arg</i> is {@code null}, then the result is "{@code null}".
+ *
* <p> Conversions denoted by an upper-case character (i.e. {@code 'B'},
* {@code 'H'}, {@code 'S'}, {@code 'C'}, {@code 'X'}, {@code 'E'},
* {@code 'G'}, {@code 'A'}, and {@code 'T'}) are the same as those for the
@@ -722,9 +728,8 @@
* <td valign="top"> <code>'\u0068'</code>
* <td> Produces a string representing the hash code value of the object.
*
- * <p> If the argument, <i>arg</i> is {@code null}, then the
- * result is "{@code null}". Otherwise, the result is obtained
- * by invoking {@code Integer.toHexString(arg.hashCode())}.
+ * <p> The result is obtained by invoking
+ * {@code Integer.toHexString(arg.hashCode())}.
*
* <p> If the {@code '#'} flag is given, then a {@link
* FormatFlagsConversionMismatchException} will be thrown.
@@ -737,8 +742,7 @@
* <td valign="top"> <code>'\u0073'</code>
* <td> Produces a string.
*
- * <p> If the argument is {@code null}, then the result is
- * "{@code null}". If the argument implements {@link Formattable}, then
+ * <p> If the argument implements {@link Formattable}, then
* its {@link Formattable#formatTo formatTo} method is invoked.
* Otherwise, the result is obtained by invoking the argument's
* {@code toString()} method.
--- a/jdk/src/java.base/share/classes/javax/net/ssl/SSLContext.java Thu Aug 20 12:29:58 2015 -0700
+++ b/jdk/src/java.base/share/classes/javax/net/ssl/SSLContext.java Wed Jul 05 20:46:25 2017 +0200
@@ -39,7 +39,7 @@
* <p> Every implementation of the Java platform is required to support the
* following standard {@code SSLContext} protocol:
* <ul>
- * <li><tt>TLSv1</tt></li>
+ * <li>{@code TLSv1}</li>
* </ul>
* This protocol is described in the <a href=
* "{@docRoot}/../technotes/guides/security/StandardNames.html#SSLContext">
--- a/jdk/src/java.base/share/classes/javax/net/ssl/SSLException.java Thu Aug 20 12:29:58 2015 -0700
+++ b/jdk/src/java.base/share/classes/javax/net/ssl/SSLException.java Wed Jul 05 20:46:25 2017 +0200
@@ -53,13 +53,13 @@
}
/**
- * Creates a <code>SSLException</code> with the specified
+ * Creates a {@code SSLException} with the specified
* detail message and cause.
*
* @param message the detail message (which is saved for later retrieval
* by the {@link #getMessage()} method).
* @param cause the cause (which is saved for later retrieval by the
- * {@link #getCause()} method). (A <tt>null</tt> value is
+ * {@link #getCause()} method). (A {@code null} value is
* permitted, and indicates that the cause is nonexistent or
* unknown.)
* @since 1.5
@@ -70,13 +70,13 @@
}
/**
- * Creates a <code>SSLException</code> with the specified cause
- * and a detail message of <tt>(cause==null ? null : cause.toString())</tt>
+ * Creates a {@code SSLException} with the specified cause
+ * and a detail message of {@code (cause==null ? null : cause.toString())}
* (which typically contains the class and detail message of
- * <tt>cause</tt>).
+ * {@code cause}).
*
* @param cause the cause (which is saved for later retrieval by the
- * {@link #getCause()} method). (A <tt>null</tt> value is
+ * {@link #getCause()} method). (A {@code null} value is
* permitted, and indicates that the cause is nonexistent or
* unknown.)
* @since 1.5
--- a/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageFileCreator.java Thu Aug 20 12:29:58 2015 -0700
+++ b/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageFileCreator.java Wed Jul 05 20:46:25 2017 +0200
@@ -139,6 +139,7 @@
}
public static void recreateJimage(Path jimageFile,
+ String jdataName,
Set<Archive> archives,
Map<String, Set<String>> modulePackages)
throws IOException {
@@ -159,12 +160,7 @@
throw new UnsupportedOperationException("Not supported, no external file "
+ "in a jimage file");
}, entriesForModule, order);
- String fileName = jimageFile.getFileName().toString();
- if (fileName.endsWith(IMAGE_EXT)) {
- fileName = fileName.substring(0, fileName.length()
- - BasicImageWriter.IMAGE_EXT.length());
- }
- generateJImage(jimageFile, fileName, resources, order);
+ generateJImage(jimageFile, jdataName, resources, order);
}
private void writeImage(String fileName,
--- a/jdk/src/java.base/share/classes/sun/net/ftp/FtpClientProvider.java Thu Aug 20 12:29:58 2015 -0700
+++ b/jdk/src/java.base/share/classes/sun/net/ftp/FtpClientProvider.java Wed Jul 05 20:46:25 2017 +0200
@@ -52,7 +52,7 @@
* Initializes a new instance of this class.
*
* @throws SecurityException if a security manager is installed and it denies
- * {@link RuntimePermission}<tt>("ftpClientProvider")</tt>
+ * {@link RuntimePermission}{@code ("ftpClientProvider")}
*/
protected FtpClientProvider() {
SecurityManager sm = System.getSecurityManager();
@@ -108,7 +108,7 @@
* <ol>
*
* <li><p> If the system property
- * <tt>java.net.FtpClientProvider</tt> is defined then it is
+ * {@code java.net.FtpClientProvider} is defined then it is
* taken to be the fully-qualified name of a concrete provider class.
* The class is loaded and instantiated; if this process fails then an
* unspecified unchecked error or exception is thrown. </p></li>
@@ -116,8 +116,8 @@
* <li><p> If a provider class has been installed in a jar file that is
* visible to the system class loader, and that jar file contains a
* provider-configuration file named
- * <tt>java.net.FtpClientProvider</tt> in the resource
- * directory <tt>META-INF/services</tt>, then the first class name
+ * {@code java.net.FtpClientProvider} in the resource
+ * directory {@code META-INF/services}, then the first class name
* specified in that file is taken. The class is loaded and
* instantiated; if this process fails then an unspecified unchecked error or exception is
* thrown. </p></li>
--- a/jdk/src/java.base/share/classes/sun/net/www/protocol/http/NegotiateAuthentication.java Thu Aug 20 12:29:58 2015 -0700
+++ b/jdk/src/java.base/share/classes/sun/net/www/protocol/http/NegotiateAuthentication.java Wed Jul 05 20:46:25 2017 +0200
@@ -191,7 +191,7 @@
/**
* return the first token.
- * @returns the token
+ * @return the token
* @throws IOException if <code>Negotiator.getNegotiator()</code> or
* <code>Negotiator.firstToken()</code> failed.
*/
@@ -219,7 +219,7 @@
/**
* return more tokens
* @param token the token to be fed into <code>negotiator.nextToken()</code>
- * @returns the token
+ * @return the token
* @throws IOException if <code>negotiator.nextToken()</code> throws Exception.
* May happen if the input token is invalid.
*/
--- a/jdk/src/java.base/share/classes/sun/nio/ch/Net.java Thu Aug 20 12:29:58 2015 -0700
+++ b/jdk/src/java.base/share/classes/sun/nio/ch/Net.java Wed Jul 05 20:46:25 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -391,8 +391,7 @@
private static native boolean isIPv6Available0();
/*
- * Returns 1 for Windows versions that support exclusive binding by default, 0
- * for those that do not, and -1 for Solaris/Linux/Mac OS
+ * Returns 1 for Windows and -1 for Solaris/Linux/Mac OS
*/
private static native int isExclusiveBindAvailable();
--- a/jdk/src/java.base/share/classes/sun/reflect/annotation/AnnotationType.java Thu Aug 20 12:29:58 2015 -0700
+++ b/jdk/src/java.base/share/classes/sun/reflect/annotation/AnnotationType.java Wed Jul 05 20:46:25 2017 +0200
@@ -98,8 +98,8 @@
* Sole constructor.
*
* @param annotationClass the class object for the annotation type
- * @throw IllegalArgumentException if the specified class object for
- * does not represent a valid annotation type
+ * @throws IllegalArgumentException if the specified class object for
+ * does not represent a valid annotation type
*/
private AnnotationType(final Class<? extends Annotation> annotationClass) {
if (!annotationClass.isAnnotation())
--- a/jdk/src/java.base/share/classes/sun/security/jca/ProviderConfig.java Thu Aug 20 12:29:58 2015 -0700
+++ b/jdk/src/java.base/share/classes/sun/security/jca/ProviderConfig.java Wed Jul 05 20:46:25 2017 +0200
@@ -178,6 +178,26 @@
p = new com.sun.crypto.provider.SunJCE();
} else if (provName.equals("SunJSSE") || provName.equals("com.sun.net.ssl.internal.ssl.Provider")) {
p = new com.sun.net.ssl.internal.ssl.Provider();
+ } else if (provName.equals("Apple") || provName.equals("apple.security.AppleProvider")) {
+ // need to use reflection since this class only exists on MacOsx
+ p = AccessController.doPrivileged(new PrivilegedAction<Provider>() {
+ public Provider run() {
+ try {
+ Class<?> c = Class.forName("apple.security.AppleProvider");
+ if (Provider.class.isAssignableFrom(c)) {
+ return (Provider) c.newInstance();
+ } else {
+ return null;
+ }
+ } catch (Exception ex) {
+ if (debug != null) {
+ debug.println("Error loading provider Apple");
+ ex.printStackTrace();
+ }
+ return null;
+ }
+ }
+ });
} else {
if (isLoading) {
// because this method is synchronized, this can only
--- a/jdk/src/java.base/share/classes/sun/security/rsa/RSAPadding.java Thu Aug 20 12:29:58 2015 -0700
+++ b/jdk/src/java.base/share/classes/sun/security/rsa/RSAPadding.java Wed Jul 05 20:46:25 2017 +0200
@@ -319,18 +319,17 @@
}
// generate non-zero padding bytes
// use a buffer to reduce calls to SecureRandom
- byte[] r = new byte[64];
- int i = -1;
- while (psSize-- > 0) {
- int b;
- do {
- if (i < 0) {
- random.nextBytes(r);
- i = r.length - 1;
+ while (psSize > 0) {
+ // extra bytes to avoid zero bytes,
+ // number of zero bytes <= 4 in 98% cases
+ byte[] r = new byte[psSize + 4];
+ random.nextBytes(r);
+ for (int i = 0; i < r.length && psSize > 0; i++) {
+ if (r[i] != 0) {
+ padded[k++] = r[i];
+ psSize--;
}
- b = r[i--] & 0xff;
- } while (b == 0);
- padded[k++] = (byte)b;
+ }
}
}
return padded;
--- a/jdk/src/java.base/share/classes/sun/util/CoreResourceBundleControl-XLocales.java.template Thu Aug 20 12:29:58 2015 -0700
+++ b/jdk/src/java.base/share/classes/sun/util/CoreResourceBundleControl-XLocales.java.template Wed Jul 05 20:46:25 2017 +0200
@@ -92,7 +92,7 @@
}
/**
- * @returns a list of candidate locales to search from.
+ * @return a list of candidate locales to search from.
* @exception NullPointerException if baseName or locale is null.
*/
@Override
--- a/jdk/src/java.base/share/classes/sun/util/PreHashedMap.java Thu Aug 20 12:29:58 2015 -0700
+++ b/jdk/src/java.base/share/classes/sun/util/PreHashedMap.java Wed Jul 05 20:46:25 2017 +0200
@@ -56,7 +56,7 @@
*
* }</pre></blockquote>
*
- * <p> The <tt>init</tt> method is invoked by the <tt>PreHashedMap</tt>
+ * <p> The {@code init} method is invoked by the {@code PreHashedMap}
* constructor with an object array long enough for the map's rows. The method
* must construct the hash chain for each row and store it in the appropriate
* element of the array.
@@ -73,7 +73,7 @@
* methods in the {@link java.util.Collections} utility class.
*
* <p> In the JDK build, subclasses of this class are typically created via the
- * <tt>Hasher</tt> program in the <tt>make/tools/Hasher</tt> directory.
+ * {@code Hasher} program in the {@code make/tools/Hasher} directory.
*
* @author Mark Reinhold
* @since 1.5
@@ -95,7 +95,7 @@
* Creates a new map.
*
* <p> This constructor invokes the {@link #init init} method, passing it a
- * newly-constructed row array that is <tt>rows</tt> elements long.
+ * newly-constructed row array that is {@code rows} elements long.
*
* @param rows
* The number of rows in the map
--- a/jdk/src/java.base/share/classes/sun/util/resources/LocaleData.java Thu Aug 20 12:29:58 2015 -0700
+++ b/jdk/src/java.base/share/classes/sun/util/resources/LocaleData.java Wed Jul 05 20:46:25 2017 +0200
@@ -201,7 +201,7 @@
*
* @param baseName the resource bundle base name.
* locale the requested locale for the resource bundle.
- * @returns a list of candidate locales to search from.
+ * @return a list of candidate locales to search from.
* @exception NullPointerException if baseName or locale is null.
*/
@Override
--- a/jdk/src/java.base/share/native/libjli/java.c Thu Aug 20 12:29:58 2015 -0700
+++ b/jdk/src/java.base/share/native/libjli/java.c Wed Jul 05 20:46:25 2017 +0200
@@ -1082,15 +1082,6 @@
AddOption("-Xverify:remote", NULL);
} else if (JLI_StrCmp(arg, "-noverify") == 0) {
AddOption("-Xverify:none", NULL);
- } else if (JLI_StrCCmp(arg, "-prof") == 0) {
- char *p = arg + 5;
- char *tmp = JLI_MemAlloc(JLI_StrLen(arg) + 50);
- if (*p) {
- sprintf(tmp, "-Xrunhprof:cpu=old,file=%s", p + 1);
- } else {
- sprintf(tmp, "-Xrunhprof:cpu=old,file=java.prof");
- }
- AddOption(tmp, NULL);
} else if (JLI_StrCCmp(arg, "-ss") == 0 ||
JLI_StrCCmp(arg, "-oss") == 0 ||
JLI_StrCCmp(arg, "-ms") == 0 ||
--- a/jdk/src/java.base/solaris/native/libjava/ProcessHandleImpl_solaris.c Thu Aug 20 12:29:58 2015 -0700
+++ b/jdk/src/java.base/solaris/native/libjava/ProcessHandleImpl_solaris.c Wed Jul 05 20:46:25 2017 +0200
@@ -24,368 +24,28 @@
*/
#include "jni.h"
-#include "jni_util.h"
-#include "java_lang_ProcessHandleImpl.h"
-#include "java_lang_ProcessHandleImpl_Info.h"
-
-
-#include <stdio.h>
-#include <ctype.h>
-#include <dirent.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <procfs.h>
-#include <signal.h>
-#include <stdlib.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <unistd.h>
-#include <limits.h>
-
-/**
- * Implementations of ProcessHandleImpl functions that are
- * NOT common to all Unix variants:
- * - getProcessPids0(pid, pidArray)
- *
- * Implementations of ProcessHandleImpl_Info
- * - totalTime, startTime
- * - Command
- * - Arguments
- */
-
-/*
- * Signatures for internal OS specific functions.
- */
-static pid_t getStatInfo(JNIEnv *env, pid_t pid,
- jlong *totalTime, jlong* startTime,
- uid_t *uid);
-static void getCmdlineInfo(JNIEnv *env, jobject jinfo, pid_t pid);
-
-extern jstring uidToUser(JNIEnv* env, uid_t uid);
-
-/* Field id for jString 'command' in java.lang.ProcessHandle.Info */
-static jfieldID ProcessHandleImpl_Info_commandID;
-
-/* Field id for jString[] 'arguments' in java.lang.ProcessHandle.Info */
-static jfieldID ProcessHandleImpl_Info_argumentsID;
-
-/* Field id for jlong 'totalTime' in java.lang.ProcessHandle.Info */
-static jfieldID ProcessHandleImpl_Info_totalTimeID;
-
-/* Field id for jlong 'startTime' in java.lang.ProcessHandle.Info */
-static jfieldID ProcessHandleImpl_Info_startTimeID;
-
-/* Field id for jString 'user' in java.lang.ProcessHandleImpl.Info */
-static jfieldID ProcessHandleImpl_Info_userID;
-
-/* static value for clock ticks per second. */
-static long clock_ticks_per_second;
-/**************************************************************
- * Static method to initialize field IDs and the ticks per second rate.
- *
- * Class: java_lang_ProcessHandleImpl_Info
- * Method: initIDs
- * Signature: ()V
- */
-JNIEXPORT void JNICALL
-Java_java_lang_ProcessHandleImpl_00024Info_initIDs(JNIEnv *env, jclass clazz) {
- CHECK_NULL(ProcessHandleImpl_Info_commandID = (*env)->GetFieldID(env,
- clazz, "command", "Ljava/lang/String;"));
- CHECK_NULL(ProcessHandleImpl_Info_argumentsID = (*env)->GetFieldID(env,
- clazz, "arguments", "[Ljava/lang/String;"));
- CHECK_NULL(ProcessHandleImpl_Info_totalTimeID = (*env)->GetFieldID(env,
- clazz, "totalTime", "J"));
- CHECK_NULL(ProcessHandleImpl_Info_startTimeID = (*env)->GetFieldID(env,
- clazz, "startTime", "J"));
- CHECK_NULL(ProcessHandleImpl_Info_userID = (*env)->GetFieldID(env,
- clazz, "user", "Ljava/lang/String;"));
-}
-
-/**************************************************************
- * Static method to initialize the ticks per second rate.
- *
- * Class: java_lang_ProcessHandleImpl
- * Method: initNative
- * Signature: ()V
- */
-JNIEXPORT void JNICALL
-Java_java_lang_ProcessHandleImpl_initNative(JNIEnv *env, jclass clazz) {
- clock_ticks_per_second = sysconf(_SC_CLK_TCK);
-}
+#include "ProcessHandleImpl_unix.h"
-/*
- * Check if a process is alive.
- * Return the start time (ms since 1970) if it is available.
- * If the start time is not available return 0.
- * If the pid is invalid, return -1.
- *
- * Class: java_lang_ProcessHandleImpl
- * Method: isAlive0
- * Signature: (J)J
- */
-JNIEXPORT jlong JNICALL
-Java_java_lang_ProcessHandleImpl_isAlive0(JNIEnv *env, jobject obj, jlong jpid) {
- pid_t pid = (pid_t) jpid;
- jlong startTime = 0L;
- jlong totalTime = 0L;
- uid_t uid = -1;
- pid_t ppid = getStatInfo(env, pid, &totalTime, &startTime, &uid);
- return (ppid < 0) ? -1 : startTime;
-}
-
-/*
- * Returns the parent pid of the requested pid.
- *
- * Class: java_lang_ProcessHandleImpl
- * Method: parent0
- * Signature: (J)J
- */
-JNIEXPORT jlong JNICALL
-Java_java_lang_ProcessHandleImpl_parent0(JNIEnv *env,
- jobject obj,
- jlong jpid,
- jlong startTime) {
- pid_t pid = (pid_t) jpid;
- pid_t ppid = -1;
-
- if (pid == getpid()) {
- ppid = getppid();
- } else {
- jlong start = 0L;
- jlong total = 0L;
- uid_t uid = -1;
-
- pid_t ppid = getStatInfo(env, pid, &total, &start, &uid);
- if (start != startTime
- && start != 0
- && startTime != 0) {
- ppid = -1;
- }
- }
- return (jlong) ppid;
-}
+#include <procfs.h>
/*
- * Returns the children of the requested pid and optionally each parent.
- *
- * Class: java_lang_ProcessHandleImpl
- * Method: getChildPids
- * Signature: (J[J)I
- *
- * Reads /proc and accumulates any process who parent pid matches.
- * The resulting pids are stored into the array of longs.
- * The number of pids is returned if they all fit.
- * If the array is too short, the desired length is returned.
+ * Implementation of native ProcessHandleImpl functions for Solaris.
+ * See ProcessHandleImpl_unix.c for more details.
*/
-JNIEXPORT jint JNICALL
-Java_java_lang_ProcessHandleImpl_getProcessPids0(JNIEnv *env,
- jclass clazz,
- jlong jpid,
- jlongArray jarray,
- jlongArray jparentArray,
- jlongArray jstimesArray) {
- DIR* dir;
- struct dirent* ptr;
- pid_t pid = (pid_t) jpid;
- jlong* pids = NULL;
- jlong* ppids = NULL;
- jlong* stimes = NULL;
- jsize parentArraySize = 0;
- jsize arraySize = 0;
- jsize stimesSize = 0;
- jsize count = 0;
- char procname[32];
-
- arraySize = (*env)->GetArrayLength(env, jarray);
- JNU_CHECK_EXCEPTION_RETURN(env, 0);
- if (jparentArray != NULL) {
- parentArraySize = (*env)->GetArrayLength(env, jparentArray);
- JNU_CHECK_EXCEPTION_RETURN(env, 0);
-
- if (arraySize != parentArraySize) {
- JNU_ThrowIllegalArgumentException(env, "array sizes not equal");
- return 0;
- }
- }
- if (jstimesArray != NULL) {
- stimesSize = (*env)->GetArrayLength(env, jstimesArray);
- JNU_CHECK_EXCEPTION_RETURN(env, -1);
-
- if (arraySize != stimesSize) {
- JNU_ThrowIllegalArgumentException(env, "array sizes not equal");
- return 0;
- }
- }
-
- /*
- * To locate the children we scan /proc looking for files that have a
- * positive integer as a filename.
- */
- if ((dir = opendir("/proc")) == NULL) {
- JNU_ThrowByNameWithLastError(env,
- "java/lang/Runtime", "Unable to open /proc");
- return 0;
- }
- do { // Block to break out of on Exception
- pids = (*env)->GetLongArrayElements(env, jarray, NULL);
- if (pids == NULL) {
- break;
- }
- if (jparentArray != NULL) {
- ppids = (*env)->GetLongArrayElements(env, jparentArray, NULL);
- if (ppids == NULL) {
- break;
- }
- }
- if (jstimesArray != NULL) {
- stimes = (*env)->GetLongArrayElements(env, jstimesArray, NULL);
- if (stimes == NULL) {
- break;
- }
- }
-
- while ((ptr = readdir(dir)) != NULL) {
- pid_t ppid = 0;
- jlong totalTime = 0L;
- jlong startTime = 0L;
- uid_t uid; // value unused
-
- /* skip files that aren't numbers */
- pid_t childpid = (pid_t) atoi(ptr->d_name);
- if ((int) childpid <= 0) {
- continue;
- }
+void os_initNative(JNIEnv *env, jclass clazz) {}
- // Read /proc/pid/stat and get the parent pid, and start time
- ppid = getStatInfo(env, childpid, &totalTime, &startTime, &uid);
- if (ppid >= 0 && (pid == 0 || ppid == pid)) {
- if (count < arraySize) {
- // Only store if it fits
- pids[count] = (jlong) childpid;
-
- if (ppids != NULL) {
- // Store the parent Pid
- ppids[count] = (jlong) ppid;
- }
- if (stimes != NULL) {
- // Store the process start time
- stimes[count] = startTime;
- }
- }
- count++; // Count to tabulate size needed
- }
- }
- } while (0);
-
- if (pids != NULL) {
- (*env)->ReleaseLongArrayElements(env, jarray, pids, 0);
- }
- if (ppids != NULL) {
- (*env)->ReleaseLongArrayElements(env, jparentArray, ppids, 0);
- }
- if (stimes != NULL) {
- (*env)->ReleaseLongArrayElements(env, jstimesArray, stimes, 0);
- }
-
- closedir(dir);
- // If more pids than array had size for; count will be greater than array size
- return count;
+jint os_getChildren(JNIEnv *env, jlong jpid, jlongArray jarray,
+ jlongArray jparentArray, jlongArray jstimesArray) {
+ return unix_getChildren(env, jpid, jarray, jparentArray, jstimesArray);
}
-/**************************************************************
- * Implementation of ProcessHandleImpl_Info native methods.
- */
-
-/*
- * Fill in the Info object from the OS information about the process.
- *
- * Class: java_lang_ProcessHandleImpl_Info
- * Method: info0
- * Signature: (J)V
- */
-JNIEXPORT void JNICALL
-Java_java_lang_ProcessHandleImpl_00024Info_info0(JNIEnv *env,
- jobject jinfo,
- jlong jpid) {
- pid_t pid = (pid_t) jpid;
- jlong startTime = 0L;
- jlong totalTime = 0L;
- uid_t uid = -1;
- pid_t ppid = getStatInfo(env, pid, &totalTime, &startTime, &uid);
-
- getCmdlineInfo(env, jinfo, pid);
-
- if (ppid > 0) {
- jstring str;
- (*env)->SetLongField(env, jinfo, ProcessHandleImpl_Info_startTimeID, startTime);
- JNU_CHECK_EXCEPTION(env);
-
- (*env)->SetLongField(env, jinfo, ProcessHandleImpl_Info_totalTimeID, totalTime);
- JNU_CHECK_EXCEPTION(env);
-
- CHECK_NULL((str = uidToUser(env, uid)));
- (*env)->SetObjectField(env, jinfo, ProcessHandleImpl_Info_userID, str);
- JNU_CHECK_EXCEPTION(env);
- }
+pid_t os_getParentPidAndTimings(JNIEnv *env, pid_t pid, jlong *total, jlong *start) {
+ return unix_getParentPidAndTimings(env, pid, total, start);
}
-/**
- * Read /proc/<pid>/status and return the ppid, total cputime and start time.
- * Return: -1 is fail; zero is unknown; > 0 is parent pid
- */
-static pid_t getStatInfo(JNIEnv *env, pid_t pid,
- jlong *totalTime, jlong* startTime,
- uid_t* uid) {
- FILE* fp;
- psinfo_t psinfo;
- char fn[32];
- int ret;
-
- /*
- * Try to open /proc/%d/status
- */
- snprintf(fn, sizeof fn, "/proc/%d/psinfo", pid);
- fp = fopen(fn, "r");
- if (fp == NULL) {
- return -1;
- }
-
- ret = fread(&psinfo, 1, (sizeof psinfo), fp);
- fclose(fp);
- if (ret < (sizeof psinfo)) {
- return -1;
- }
-
- *totalTime = psinfo.pr_time.tv_sec * 1000000000L + psinfo.pr_time.tv_nsec;
-
- *startTime = psinfo.pr_start.tv_sec * (jlong)1000 +
- psinfo.pr_start.tv_nsec / 1000000;
-
- *uid = psinfo.pr_uid;
-
- return (pid_t) psinfo.pr_ppid;
+void os_getCmdlineAndUserInfo(JNIEnv *env, jobject jinfo, pid_t pid) {
+ unix_getCmdlineAndUserInfo(env, jinfo, pid);
}
-static void getCmdlineInfo(JNIEnv *env, jobject jinfo, pid_t pid) {
- char fn[32];
- char exePath[PATH_MAX];
- jstring str = NULL;
- int ret;
-
- /*
- * The path to the executable command is the link in /proc/<pid>/paths/a.out.
- */
- snprintf(fn, sizeof fn, "/proc/%d/path/a.out", pid);
- if ((ret = readlink(fn, exePath, PATH_MAX - 1)) < 0) {
- return;
- }
-
- // null terminate and create String to store for command
- exePath[ret] = '\0';
- CHECK_NULL(str = JNU_NewStringPlatform(env, exePath));
- (*env)->SetObjectField(env, jinfo, ProcessHandleImpl_Info_commandID, str);
- JNU_CHECK_EXCEPTION(env);
-}
-
--- a/jdk/src/java.base/unix/classes/sun/net/www/protocol/file/Handler.java Thu Aug 20 12:29:58 2015 -0700
+++ b/jdk/src/java.base/unix/classes/sun/net/www/protocol/file/Handler.java Wed Jul 05 20:46:25 2017 +0200
@@ -116,8 +116,8 @@
* Compares the host components of two URLs.
* @param u1 the URL of the first host to compare
* @param u2 the URL of the second host to compare
- * @return <tt>true</tt> if and only if they
- * are equal, <tt>false</tt> otherwise.
+ * @return {@code true} if and only if they
+ * are equal, {@code false} otherwise.
*/
protected boolean hostsEqual(URL u1, URL u2) {
/*
--- a/jdk/src/java.base/unix/native/libjava/ProcessHandleImpl_unix.c Thu Aug 20 12:29:58 2015 -0700
+++ b/jdk/src/java.base/unix/native/libjava/ProcessHandleImpl_unix.c Wed Jul 05 20:46:25 2017 +0200
@@ -28,31 +28,87 @@
#include "java_lang_ProcessHandleImpl.h"
#include "java_lang_ProcessHandleImpl_Info.h"
+#include "ProcessHandleImpl_unix.h"
+
#include <stdio.h>
-
#include <errno.h>
#include <fcntl.h>
#include <pwd.h>
#include <signal.h>
#include <stdlib.h>
#include <unistd.h>
+#include <string.h>
+#include <dirent.h>
+#include <ctype.h>
+#include <limits.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
-#include <string.h>
-#include <dirent.h>
-#include <ctype.h>
+#ifdef _AIX
+#include <sys/procfs.h>
+#endif
+#ifdef __solaris__
+#include <procfs.h>
+#endif
/**
- * Implementations of ProcessHandleImpl functions that are common to all
- * Unix variants:
- * - waitForProcessExit0(pid, reap)
- * - getCurrentPid0()
- * - destroy0(pid, force)
+ * This file contains the implementation of the native ProcessHandleImpl
+ * functions which are common to all Unix variants.
+ *
+ * The currently supported Unix variants are Solaris, Linux, MaxOS X and AIX.
+ * The various similarities and differences between these systems make it hard
+ * to find a clear boundary between platform specific and shared code.
+ *
+ * In order to ease code sharing between the platforms while still keeping the
+ * code as clean as possible (i.e. free of preprocessor macros) we use the
+ * following source code layout (remember that ProcessHandleImpl_unix.c will
+ * be compiled on EVERY Unix platform while ProcessHandleImpl_<os>.c will be
+ * only compiled on the specific OS):
+ *
+ * - all the JNI wrappers for the ProcessHandleImpl functions go into this file
+ * - if their implementation is common on ALL the supported Unix platforms it
+ * goes right into the JNI wrappers
+ * - if the whole function or substantial parts of it are platform dependent,
+ * the implementation goes into os_<function_name> functions in
+ * ProcessHandleImpl_<os>.c
+ * - if at least two platforms implement an os_<function_name> function in the
+ * same way, this implementation is factored out into unix_<function_name>,
+ * placed into this file and called from the corresponding os_<function_name>
+ * function.
+ * - For convenience, all the os_ and unix_ functions are declared in
+ * ProcessHandleImpl_unix.h which is included into every
+ * ProcessHandleImpl_<os>.c file.
+ *
+ * Example 1:
+ * ----------
+ * The implementation of Java_java_lang_ProcessHandleImpl_initNative()
+ * is the same on all platforms except on Linux where it initilizes one
+ * additional field. So we place the implementation right into
+ * Java_java_lang_ProcessHandleImpl_initNative() but add call to
+ * os_init() at the end of the function which is empty on all platforms
+ * except Linux where it performs the additionally initializations.
+ *
+ * Example 2:
+ * ----------
+ * The implementation of Java_java_lang_ProcessHandleImpl_00024Info_info0 is the
+ * same on Solaris and AIX but different on Linux and MacOSX. We therefore simply
+ * call the helpers os_getParentPidAndTimings() and os_getCmdlineAndUserInfo().
+ * The Linux and MaxOS X versions of these functions (in the corresponding files
+ * ProcessHandleImpl_linux.c and ProcessHandleImpl_macosx.c) directly contain
+ * the platform specific implementations while the Solaris and AIX
+ * implementations simply call back to unix_getParentPidAndTimings() and
+ * unix_getCmdlineAndUserInfo() which are implemented right in this file.
+ *
+ * The term "same implementation" is still a question of interpretation. It my
+ * be acceptable to have a few ifdef'ed lines if that allows the sharing of a
+ * huge function. On the other hand, if the platform specific code in a shared
+ * function grows over a certain limit, it may be better to refactor that
+ * functionality into corresponding, platform-specific os_ functions.
*/
+
#ifndef WIFEXITED
#define WIFEXITED(status) (((status)&0xFF) == 0)
#endif
@@ -69,6 +125,19 @@
#define WTERMSIG(status) ((status)&0x7F)
#endif
+#ifdef __solaris__
+/* The child exited because of a signal.
+ * The best value to return is 0x80 + signal number,
+ * because that is what all Unix shells do, and because
+ * it allows callers to distinguish between process exit and
+ * process death by signal.
+ * Unfortunately, the historical behavior on Solaris is to return
+ * the signal number, and we preserve this for compatibility. */
+#define WTERMSIG_RETURN(status) WTERMSIG(status)
+#else
+#define WTERMSIG_RETURN(status) (WTERMSIG(status) + 0x80)
+#endif
+
#define RESTARTABLE(_cmd, _result) do { \
do { \
_result = _cmd; \
@@ -81,21 +150,83 @@
} while((_result == NULL) && (errno == EINTR)); \
} while(0)
-#ifdef __solaris__
- #define STAT_FILE "/proc/%d/status"
-#else
- #define STAT_FILE "/proc/%d/stat"
-#endif
+
+/* Field id for jString 'command' in java.lang.ProcessHandleImpl.Info */
+jfieldID ProcessHandleImpl_Info_commandID;
+
+/* Field id for jString 'commandLine' in java.lang.ProcessHandleImpl.Info */
+jfieldID ProcessHandleImpl_Info_commandLineID;
+
+/* Field id for jString[] 'arguments' in java.lang.ProcessHandleImpl.Info */
+jfieldID ProcessHandleImpl_Info_argumentsID;
+
+/* Field id for jlong 'totalTime' in java.lang.ProcessHandleImpl.Info */
+jfieldID ProcessHandleImpl_Info_totalTimeID;
+
+/* Field id for jlong 'startTime' in java.lang.ProcessHandleImpl.Info */
+jfieldID ProcessHandleImpl_Info_startTimeID;
+
+/* Field id for jString 'user' in java.lang.ProcessHandleImpl.Info */
+jfieldID ProcessHandleImpl_Info_userID;
+
+/* Size of password or group entry when not available via sysconf */
+#define ENT_BUF_SIZE 1024
+/* The value for the size of the buffer used by getpwuid_r(). The result of */
+/* sysconf(_SC_GETPW_R_SIZE_MAX) if available or ENT_BUF_SIZE otherwise. */
+static long getpw_buf_size;
+
+/**************************************************************
+ * Static method to initialize field IDs and the ticks per second rate.
+ *
+ * Class: java_lang_ProcessHandleImpl_Info
+ * Method: initIDs
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL
+Java_java_lang_ProcessHandleImpl_00024Info_initIDs(JNIEnv *env, jclass clazz) {
+
+ CHECK_NULL(ProcessHandleImpl_Info_commandID =
+ (*env)->GetFieldID(env, clazz, "command", "Ljava/lang/String;"));
+ CHECK_NULL(ProcessHandleImpl_Info_commandLineID =
+ (*env)->GetFieldID(env, clazz, "commandLine", "Ljava/lang/String;"));
+ CHECK_NULL(ProcessHandleImpl_Info_argumentsID =
+ (*env)->GetFieldID(env, clazz, "arguments", "[Ljava/lang/String;"));
+ CHECK_NULL(ProcessHandleImpl_Info_totalTimeID =
+ (*env)->GetFieldID(env, clazz, "totalTime", "J"));
+ CHECK_NULL(ProcessHandleImpl_Info_startTimeID =
+ (*env)->GetFieldID(env, clazz, "startTime", "J"));
+ CHECK_NULL(ProcessHandleImpl_Info_userID =
+ (*env)->GetFieldID(env, clazz, "user", "Ljava/lang/String;"));
+}
+
+/***********************************************************
+ * Static method to initialize platform dependent constants.
+ *
+ * Class: java_lang_ProcessHandleImpl
+ * Method: initNative
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL
+Java_java_lang_ProcessHandleImpl_initNative(JNIEnv *env, jclass clazz) {
+ getpw_buf_size = sysconf(_SC_GETPW_R_SIZE_MAX);
+ if (getpw_buf_size == -1) {
+ getpw_buf_size = ENT_BUF_SIZE;
+ }
+ os_initNative(env, clazz);
+}
/* Block until a child process exits and return its exit code.
* Note, can only be called once for any given pid if reapStatus = true.
+ *
+ * Class: java_lang_ProcessHandleImpl
+ * Method: waitForProcessExit0
+ * Signature: (JZ)I
*/
JNIEXPORT jint JNICALL
Java_java_lang_ProcessHandleImpl_waitForProcessExit0(JNIEnv* env,
jclass junk,
jlong jpid,
- jboolean reapStatus)
-{
+ jboolean reapStatus) {
pid_t pid = (pid_t)jpid;
errno = 0;
@@ -117,18 +248,7 @@
if (WIFEXITED(status)) {
return WEXITSTATUS(status);
} else if (WIFSIGNALED(status)) {
- /* The child exited because of a signal.
- * The best value to return is 0x80 + signal number,
- * because that is what all Unix shells do, and because
- * it allows callers to distinguish between process exit and
- * process death by signal.
- * Unfortunately, the historical behavior on Solaris is to return
- * the signal number, and we preserve this for compatibility. */
-#ifdef __solaris__
- return WTERMSIG(status);
-#else
- return 0x80 + WTERMSIG(status);
-#endif
+ return WTERMSIG_RETURN(status);
} else {
return status;
}
@@ -156,18 +276,7 @@
*/
return siginfo.si_status;
} else if (siginfo.si_code == CLD_KILLED || siginfo.si_code == CLD_DUMPED) {
- /* The child exited because of a signal.
- * The best value to return is 0x80 + signal number,
- * because that is what all Unix shells do, and because
- * it allows callers to distinguish between process exit and
- * process death by signal.
- * Unfortunately, the historical behavior on Solaris is to return
- * the signal number, and we preserve this for compatibility. */
- #ifdef __solaris__
- return WTERMSIG(siginfo.si_status);
- #else
- return 0x80 + WTERMSIG(siginfo.si_status);
- #endif
+ return WTERMSIG_RETURN(siginfo.si_status);
} else {
/*
* Unknown exit code; pass it through.
@@ -191,7 +300,7 @@
/*
* Class: java_lang_ProcessHandleImpl
* Method: destroy0
- * Signature: (Z)Z
+ * Signature: (JJZ)Z
*/
JNIEXPORT jboolean JNICALL
Java_java_lang_ProcessHandleImpl_destroy0(JNIEnv *env,
@@ -210,119 +319,52 @@
}
}
-/**
- * Size of password or group entry when not available via sysconf
- */
-#define ENT_BUF_SIZE 1024
-
-/**
- * Return a strong username for the uid_t or null.
+/*
+ * Returns the children of the requested pid and optionally each parent and
+ * start time.
+ * Accumulates any process who parent pid matches.
+ * The resulting pids are stored into the array of longs.
+ * The number of pids is returned if they all fit.
+ * If the array is too short, the negative of the desired length is returned.
+ * Class: java_lang_ProcessHandleImpl
+ * Method: getProcessPids0
+ * Signature: (J[J[J[J)I
*/
-jstring uidToUser(JNIEnv* env, uid_t uid) {
- int result = 0;
- int buflen;
- char* pwbuf;
- jstring name = NULL;
-
- /* allocate buffer for password record */
- buflen = (int)sysconf(_SC_GETPW_R_SIZE_MAX);
- if (buflen == -1)
- buflen = ENT_BUF_SIZE;
- pwbuf = (char*)malloc(buflen);
- if (pwbuf == NULL) {
- JNU_ThrowOutOfMemoryError(env, "Unable to open getpwent");
- } else {
- struct passwd pwent;
- struct passwd* p = NULL;
-
-#ifdef __solaris__
- RESTARTABLE_RETURN_PTR(getpwuid_r(uid, &pwent, pwbuf, (size_t)buflen), p);
-#else
- RESTARTABLE(getpwuid_r(uid, &pwent, pwbuf, (size_t)buflen, &p), result);
-#endif
-
- // Return the Java String if a name was found
- if (result == 0 && p != NULL &&
- p->pw_name != NULL && *(p->pw_name) != '\0') {
- name = JNU_NewStringPlatform(env, p->pw_name);
- }
- free(pwbuf);
- }
- return name;
+JNIEXPORT jint JNICALL
+Java_java_lang_ProcessHandleImpl_getProcessPids0(JNIEnv *env,
+ jclass clazz,
+ jlong jpid,
+ jlongArray jarray,
+ jlongArray jparentArray,
+ jlongArray jstimesArray) {
+ return os_getChildren(env, jpid, jarray, jparentArray, jstimesArray);
}
-/**
- * Implementations of ProcessHandleImpl functions that are common to
- * (some) Unix variants:
- * - getProcessPids0(pid, pidArray, parentArray)
- */
-
-#if defined(__linux__) || defined(__AIX__)
-
/*
- * Signatures for internal OS specific functions.
- */
-static pid_t getStatInfo(JNIEnv *env, pid_t pid,
- jlong *totalTime, jlong* startTime);
-static void getCmdlineInfo(JNIEnv *env, pid_t pid, jobject jinfo);
-static long long getBoottime(JNIEnv *env);
-
-jstring uidToUser(JNIEnv* env, uid_t uid);
-
-/* Field id for jString 'command' in java.lang.ProcessHandleImpl.Info */
-static jfieldID ProcessHandleImpl_Info_commandID;
-
-/* Field id for jString[] 'arguments' in java.lang.ProcessHandleImpl.Info */
-static jfieldID ProcessHandleImpl_Info_argumentsID;
-
-/* Field id for jlong 'totalTime' in java.lang.ProcessHandleImpl.Info */
-static jfieldID ProcessHandleImpl_Info_totalTimeID;
-
-/* Field id for jlong 'startTime' in java.lang.ProcessHandleImpl.Info */
-static jfieldID ProcessHandleImpl_Info_startTimeID;
-
-/* Field id for jString 'user' in java.lang.ProcessHandleImpl.Info */
-static jfieldID ProcessHandleImpl_Info_userID;
-
-/* static value for clock ticks per second. */
-static long clock_ticks_per_second;
-
-/* A static offset in milliseconds since boot. */
-static long long bootTime_ms;
-
-/**************************************************************
- * Static method to initialize field IDs and the ticks per second rate.
+ * Fill in the Info object from the OS information about the process.
*
* Class: java_lang_ProcessHandleImpl_Info
- * Method: initIDs
- * Signature: ()V
+ * Method: info0
+ * Signature: (Ljava/lang/ProcessHandle/Info;J)I
*/
JNIEXPORT void JNICALL
-Java_java_lang_ProcessHandleImpl_00024Info_initIDs(JNIEnv *env, jclass clazz) {
+Java_java_lang_ProcessHandleImpl_00024Info_info0(JNIEnv *env,
+ jobject jinfo,
+ jlong jpid) {
+ pid_t pid = (pid_t) jpid;
+ pid_t ppid;
+ jlong totalTime = -1L;
+ jlong startTime = -1L;
- CHECK_NULL(ProcessHandleImpl_Info_commandID = (*env)->GetFieldID(env,
- clazz, "command", "Ljava/lang/String;"));
- CHECK_NULL(ProcessHandleImpl_Info_argumentsID = (*env)->GetFieldID(env,
- clazz, "arguments", "[Ljava/lang/String;"));
- CHECK_NULL(ProcessHandleImpl_Info_totalTimeID = (*env)->GetFieldID(env,
- clazz, "totalTime", "J"));
- CHECK_NULL(ProcessHandleImpl_Info_startTimeID = (*env)->GetFieldID(env,
- clazz, "startTime", "J"));
- CHECK_NULL(ProcessHandleImpl_Info_userID = (*env)->GetFieldID(env,
- clazz, "user", "Ljava/lang/String;"));
-}
+ ppid = os_getParentPidAndTimings(env, pid, &totalTime, &startTime);
+ if (ppid >= 0) {
+ (*env)->SetLongField(env, jinfo, ProcessHandleImpl_Info_totalTimeID, totalTime);
+ JNU_CHECK_EXCEPTION(env);
-/**************************************************************
- * Static method to initialize the ticks per second rate.
- *
- * Class: java_lang_ProcessHandleImpl
- * Method: initNative
- * Signature: ()V
- */
-JNIEXPORT void JNICALL
-Java_java_lang_ProcessHandleImpl_initNative(JNIEnv *env, jclass clazz) {
- clock_ticks_per_second = sysconf(_SC_CLK_TCK);
- bootTime_ms = getBoottime(env);
+ (*env)->SetLongField(env, jinfo, ProcessHandleImpl_Info_startTimeID, startTime);
+ JNU_CHECK_EXCEPTION(env);
+ }
+ os_getCmdlineAndUserInfo(env, jinfo, pid);
}
/*
@@ -340,8 +382,8 @@
pid_t pid = (pid_t) jpid;
jlong startTime = 0L;
jlong totalTime = 0L;
- pid_t ppid = getStatInfo(env, pid, &totalTime, &startTime);
- return (ppid <= 0) ? -1 : startTime;
+ pid_t ppid = os_getParentPidAndTimings(env, pid, &totalTime, &startTime);
+ return (ppid < 0) ? -1 : startTime;
}
/*
@@ -350,7 +392,7 @@
*
* Class: java_lang_ProcessHandleImpl
* Method: parent0
- * Signature: (J)J
+ * Signature: (JJ)J
*/
JNIEXPORT jlong JNICALL
Java_java_lang_ProcessHandleImpl_parent0(JNIEnv *env,
@@ -360,13 +402,12 @@
pid_t pid = (pid_t) jpid;
pid_t ppid;
- pid_t mypid = getpid();
- if (pid == mypid) {
+ if (pid == getpid()) {
ppid = getppid();
} else {
- jlong start = 0L;;
+ jlong start = 0L;
jlong total = 0L; // unused
- ppid = getStatInfo(env, pid, &total, &start);
+ ppid = os_getParentPidAndTimings(env, pid, &total, &start);
if (start != startTime && start != 0 && startTime != 0) {
ppid = -1;
}
@@ -374,24 +415,94 @@
return (jlong) ppid;
}
+/**
+ * Construct the argument array by parsing the arguments from the sequence
+ * of arguments.
+ */
+void unix_fillArgArray(JNIEnv *env, jobject jinfo, int nargs, char *cp,
+ char *argsEnd, jstring cmdexe, char *cmdline) {
+ jobject argsArray;
+ int i;
+
+ (*env)->SetObjectField(env, jinfo, ProcessHandleImpl_Info_commandID, cmdexe);
+ JNU_CHECK_EXCEPTION(env);
+
+ if (nargs >= 1) {
+ // Create a String array for nargs-1 elements
+ argsArray = (*env)->NewObjectArray(env, nargs - 1, JNU_ClassString(env), NULL);
+ CHECK_NULL(argsArray);
+
+ for (i = 0; i < nargs - 1; i++) {
+ jstring str = NULL;
+
+ cp += strlen(cp) + 1;
+ if (cp > argsEnd || *cp == '\0') {
+ return; // Off the end pointer or an empty argument is an error
+ }
+
+ CHECK_NULL((str = JNU_NewStringPlatform(env, cp)));
+
+ (*env)->SetObjectArrayElement(env, argsArray, i, str);
+ JNU_CHECK_EXCEPTION(env);
+ }
+ (*env)->SetObjectField(env, jinfo, ProcessHandleImpl_Info_argumentsID, argsArray);
+ JNU_CHECK_EXCEPTION(env);
+ }
+ if (cmdline != NULL) {
+ jstring commandLine = NULL;
+ CHECK_NULL((commandLine = JNU_NewStringPlatform(env, cmdline)));
+ (*env)->SetObjectField(env, jinfo, ProcessHandleImpl_Info_commandLineID, commandLine);
+ JNU_CHECK_EXCEPTION(env);
+ }
+}
+
+void unix_getUserInfo(JNIEnv* env, jobject jinfo, uid_t uid) {
+ int result = 0;
+ char* pwbuf;
+ jstring name = NULL;
+
+ /* allocate buffer for password record */
+ pwbuf = (char*)malloc(getpw_buf_size);
+ if (pwbuf == NULL) {
+ JNU_ThrowOutOfMemoryError(env, "Unable to open getpwent");
+ } else {
+ struct passwd pwent;
+ struct passwd* p = NULL;
+
+#ifdef __solaris__
+ RESTARTABLE_RETURN_PTR(getpwuid_r(uid, &pwent, pwbuf, (size_t)getpw_buf_size), p);
+#else
+ RESTARTABLE(getpwuid_r(uid, &pwent, pwbuf, (size_t)getpw_buf_size, &p), result);
+#endif
+
+ // Create the Java String if a name was found
+ if (result == 0 && p != NULL &&
+ p->pw_name != NULL && *(p->pw_name) != '\0') {
+ name = JNU_NewStringPlatform(env, p->pw_name);
+ }
+ free(pwbuf);
+ }
+ if (name != NULL) {
+ (*env)->SetObjectField(env, jinfo, ProcessHandleImpl_Info_userID, name);
+ }
+}
+
/*
- * Returns the children of the requested pid and optionally each parent.
+ * The following functions are common on Solaris, Linux and AIX.
+ */
+
+#if defined(__solaris__) || defined (__linux__) || defined(_AIX)
+
+/*
+ * Returns the children of the requested pid and optionally each parent and
+ * start time.
* Reads /proc and accumulates any process who parent pid matches.
* The resulting pids are stored into the array of longs.
* The number of pids is returned if they all fit.
- * If the array is too short, the negative of the desired length is returned. *
- * Class: java_lang_ProcessHandleImpl
- * Method: getChildPids
- * Signature: (J[J[J)I
+ * If the array is too short, the negative of the desired length is returned.
*/
-JNIEXPORT jint JNICALL
-Java_java_lang_ProcessHandleImpl_getProcessPids0(JNIEnv *env,
- jclass clazz,
- jlong jpid,
- jlongArray jarray,
- jlongArray jparentArray,
- jlongArray jstimesArray) {
-
+jint unix_getChildren(JNIEnv *env, jlong jpid, jlongArray jarray,
+ jlongArray jparentArray, jlongArray jstimesArray) {
DIR* dir;
struct dirent* ptr;
pid_t pid = (pid_t) jpid;
@@ -462,9 +573,10 @@
if ((int) childpid <= 0) {
continue;
}
- // Read /proc/pid/stat and get the parent pid, and start time
- ppid = getStatInfo(env, childpid, &totalTime, &startTime);
- if (ppid > 0 && (pid == 0 || ppid == pid)) {
+
+ // Get the parent pid, and start time
+ ppid = os_getParentPidAndTimings(env, childpid, &totalTime, &startTime);
+ if (ppid >= 0 && (pid == 0 || ppid == pid)) {
if (count < arraySize) {
// Only store if it fits
pids[count] = (jlong) childpid;
@@ -498,293 +610,110 @@
return count;
}
-
-/**************************************************************
- * Implementation of ProcessHandleImpl_Info native methods.
- */
+#endif // defined(__solaris__) || defined (__linux__) || defined(_AIX)
/*
- * Fill in the Info object from the OS information about the process.
- *
- * Class: java_lang_ProcessHandleImpl_Info
- * Method: info0
- * Signature: (JLjava/lang/ProcessHandle/Info;)I
+ * The following functions are common on Solaris and AIX.
*/
-JNIEXPORT void JNICALL
-Java_java_lang_ProcessHandleImpl_00024Info_info0(JNIEnv *env,
- jobject jinfo,
- jlong jpid) {
- pid_t pid = (pid_t) jpid;
- pid_t ppid;
- jlong totalTime = 0L;
- jlong startTime = -1L;
-
- ppid = getStatInfo(env, pid, &totalTime, &startTime);
- if (ppid > 0) {
- (*env)->SetLongField(env, jinfo, ProcessHandleImpl_Info_totalTimeID, totalTime);
- JNU_CHECK_EXCEPTION(env);
-
- (*env)->SetLongField(env, jinfo, ProcessHandleImpl_Info_startTimeID, startTime);
- JNU_CHECK_EXCEPTION(env);
-
- getCmdlineInfo(env, pid, jinfo);
- }
-}
-
-/**
- * Read /proc/<pid>/stat and return the ppid, total cputime and start time.
- * -1 is fail; zero is unknown; > 0 is parent pid
- */
-static pid_t getStatInfo(JNIEnv *env, pid_t pid,
- jlong *totalTime, jlong* startTime) {
- FILE* fp;
- char buffer[2048];
- int statlen;
- char fn[32];
- char* s;
- int parentPid;
- long unsigned int utime = 0; // clock tics
- long unsigned int stime = 0; // clock tics
- long long unsigned int start = 0; // microseconds
- /*
- * Try to stat and then open /proc/%d/stat
- */
- snprintf(fn, sizeof fn, STAT_FILE, pid);
-
- fp = fopen(fn, "r");
- if (fp == NULL) {
- return -1; // fail, no such /proc/pid/stat
- }
-
- /*
- * The format is: pid (command) state ppid ...
- * As the command could be anything we must find the right most
- * ")" and then skip the white spaces that follow it.
- */
- statlen = fread(buffer, 1, (sizeof buffer - 1), fp);
- fclose(fp);
- if (statlen < 0) {
- return 0; // parent pid is not available
- }
-
- buffer[statlen] = '\0';
- s = strchr(buffer, '(');
- if (s == NULL) {
- return 0; // parent pid is not available
- }
- // Found start of command, skip to end
- s++;
- s = strrchr(s, ')');
- if (s == NULL) {
- return 0; // parent pid is not available
- }
- s++;
-
- // Scan the needed fields from status, retaining only ppid(4),
- // utime (14), stime(15), starttime(22)
- if (4 != sscanf(s, " %*c %d %*d %*d %*d %*d %*d %*u %*u %*u %*u %lu %lu %*d %*d %*d %*d %*d %*d %llu",
- &parentPid, &utime, &stime, &start)) {
- return 0; // not all values parsed; return error
- }
-
- *totalTime = (utime + stime) * (jlong)(1000000000 / clock_ticks_per_second);
-
- *startTime = bootTime_ms + ((start * 1000) / clock_ticks_per_second);
-
- return parentPid;
-}
+#if defined(__solaris__) || defined(_AIX)
/**
- * Construct the argument array by parsing the arguments from the sequence
- * of arguments. The zero'th arg is the command executable
+ * Helper function to get the 'psinfo_t' data from "/proc/%d/psinfo".
+ * Returns 0 on success and -1 on error.
*/
-static int fillArgArray(JNIEnv *env, jobject jinfo,
- int nargs, char *cp, char *argsEnd, jstring cmdexe) {
- jobject argsArray;
- int i;
-
- if (nargs < 1) {
- return 0;
- }
-
- if (cmdexe == NULL) {
- // Create a string from arg[0]
- CHECK_NULL_RETURN((cmdexe = JNU_NewStringPlatform(env, cp)), -1);
- }
- (*env)->SetObjectField(env, jinfo, ProcessHandleImpl_Info_commandID, cmdexe);
- JNU_CHECK_EXCEPTION_RETURN(env, -3);
-
- // Create a String array for nargs-1 elements
- argsArray = (*env)->NewObjectArray(env, nargs - 1, JNU_ClassString(env), NULL);
- CHECK_NULL_RETURN(argsArray, -1);
-
- for (i = 0; i < nargs - 1; i++) {
- jstring str = NULL;
-
- cp += strnlen(cp, (argsEnd - cp)) + 1;
- if (cp > argsEnd || *cp == '\0') {
- return -2; // Off the end pointer or an empty argument is an error
- }
-
- CHECK_NULL_RETURN((str = JNU_NewStringPlatform(env, cp)), -1);
-
- (*env)->SetObjectArrayElement(env, argsArray, i, str);
- JNU_CHECK_EXCEPTION_RETURN(env, -3);
- }
- (*env)->SetObjectField(env, jinfo, ProcessHandleImpl_Info_argumentsID, argsArray);
- JNU_CHECK_EXCEPTION_RETURN(env, -4);
- return 0;
-}
-
-
-static void getCmdlineInfo(JNIEnv *env, pid_t pid, jobject jinfo) {
- int fd;
- int cmdlen = 0;
- char *cmdline = NULL, *cmdEnd; // used for command line args and exe
- jstring cmdexe = NULL;
+static int getPsinfo(pid_t pid, psinfo_t *psinfo) {
+ FILE* fp;
char fn[32];
- struct stat stat_buf;
+ int ret;
/*
- * Try to open /proc/%d/cmdline
+ * Try to open /proc/%d/psinfo
*/
- snprintf(fn, sizeof fn, "/proc/%d/cmdline", pid);
- if ((fd = open(fn, O_RDONLY)) < 0) {
- return;
- }
-
- do { // Block to break out of on errors
- int i;
- char *s;
-
- cmdline = (char*)malloc(PATH_MAX);
- if (cmdline == NULL) {
- break;
- }
-
- /*
- * The path to the executable command is the link in /proc/<pid>/exe.
- */
- snprintf(fn, sizeof fn, "/proc/%d/exe", pid);
- if ((cmdlen = readlink(fn, cmdline, PATH_MAX - 1)) > 0) {
- // null terminate and create String to store for command
- cmdline[cmdlen] = '\0';
- cmdexe = JNU_NewStringPlatform(env, cmdline);
- (*env)->ExceptionClear(env); // unconditionally clear any exception
- }
-
- /*
- * The buffer format is the arguments nul terminated with an extra nul.
- */
- cmdlen = read(fd, cmdline, PATH_MAX-1);
- if (cmdlen < 0) {
- break;
- }
-
- // Terminate the buffer and count the arguments
- cmdline[cmdlen] = '\0';
- cmdEnd = &cmdline[cmdlen + 1];
- for (s = cmdline,i = 0; *s != '\0' && (s < cmdEnd); i++) {
- s += strnlen(s, (cmdEnd - s)) + 1;
- }
-
- if (fillArgArray(env, jinfo, i, cmdline, cmdEnd, cmdexe) < 0) {
- break;
- }
-
- // Get and store the user name
- if (fstat(fd, &stat_buf) == 0) {
- jstring name = uidToUser(env, stat_buf.st_uid);
- if (name != NULL) {
- (*env)->SetObjectField(env, jinfo, ProcessHandleImpl_Info_userID, name);
- }
- }
- } while (0);
-
- if (cmdline != NULL) {
- free(cmdline);
- }
- if (fd >= 0) {
- close(fd);
- }
-}
-
-/**
- * Read the boottime from /proc/stat.
- */
-static long long getBoottime(JNIEnv *env) {
- FILE *fp;
- char *line = NULL;
- size_t len = 0;
- long long bootTime = 0;
-
- fp = fopen("/proc/stat", "r");
+ snprintf(fn, sizeof fn, "/proc/%d/psinfo", pid);
+ fp = fopen(fn, "r");
if (fp == NULL) {
return -1;
}
- while (getline(&line, &len, fp) != -1) {
- if (sscanf(line, "btime %llu", &bootTime) == 1) {
- break;
- }
+ ret = fread(psinfo, 1, sizeof(psinfo_t), fp);
+ fclose(fp);
+ if (ret < sizeof(psinfo_t)) {
+ return -1;
}
- free(line);
+ return 0;
+}
- if (fp != 0) {
- fclose(fp);
+/**
+ * Read /proc/<pid>/psinfo and return the ppid, total cputime and start time.
+ * Return: -1 is fail; >= 0 is parent pid
+ * 'total' will contain the running time of 'pid' in nanoseconds.
+ * 'start' will contain the start time of 'pid' in milliseconds since epoch.
+ */
+pid_t unix_getParentPidAndTimings(JNIEnv *env, pid_t pid,
+ jlong *totalTime, jlong* startTime) {
+ psinfo_t psinfo;
+
+ if (getPsinfo(pid, &psinfo) < 0) {
+ return -1;
}
- return bootTime * 1000;
+ *totalTime = psinfo.pr_time.tv_sec * 1000000000L + psinfo.pr_time.tv_nsec;
+
+ *startTime = psinfo.pr_start.tv_sec * (jlong)1000 +
+ psinfo.pr_start.tv_nsec / 1000000;
+
+ return (pid_t) psinfo.pr_ppid;
}
-#endif // defined(__linux__) || defined(__AIX__)
-
+void unix_getCmdlineAndUserInfo(JNIEnv *env, jobject jinfo, pid_t pid) {
+ psinfo_t psinfo;
+ char fn[32];
+ char exePath[PATH_MAX];
+ char prargs[PRARGSZ + 1];
+ jstring cmdexe = NULL;
+ int ret;
-/* Block until a child process exits and return its exit code.
- Note, can only be called once for any given pid. */
-JNIEXPORT jint JNICALL
-Java_java_lang_ProcessImpl_waitForProcessExit(JNIEnv* env,
- jobject junk,
- jint pid)
-{
- /* We used to use waitid() on Solaris, waitpid() on Linux, but
- * waitpid() is more standard, so use it on all POSIX platforms. */
- int status;
- /* Wait for the child process to exit. This returns immediately if
- the child has already exited. */
- while (waitpid(pid, &status, 0) < 0) {
- switch (errno) {
- case ECHILD: return 0;
- case EINTR: break;
- default: return -1;
- }
+ /*
+ * On Solaris, the full path to the executable command is the link in
+ * /proc/<pid>/paths/a.out. But it is only readable for processes we own.
+ */
+#if defined(__solaris__)
+ snprintf(fn, sizeof fn, "/proc/%d/path/a.out", pid);
+ if ((ret = readlink(fn, exePath, PATH_MAX - 1)) > 0) {
+ // null terminate and create String to store for command
+ exePath[ret] = '\0';
+ CHECK_NULL(cmdexe = JNU_NewStringPlatform(env, exePath));
+ }
+#endif
+
+ /*
+ * Now try to open /proc/%d/psinfo
+ */
+ if (getPsinfo(pid, &psinfo) < 0) {
+ unix_fillArgArray(env, jinfo, 0, NULL, NULL, cmdexe, NULL);
+ return;
}
- if (WIFEXITED(status)) {
- /*
- * The child exited normally; get its exit code.
+ unix_getUserInfo(env, jinfo, psinfo.pr_uid);
+
+ /*
+ * Now read psinfo.pr_psargs which contains the first PRARGSZ characters of the
+ * argument list (i.e. arg[0] arg[1] ...). Unfortunately, PRARGSZ is usually set
+ * to 80 characters only. Nevertheless it's better than nothing :)
+ */
+ strncpy(prargs, psinfo.pr_psargs, PRARGSZ);
+ prargs[PRARGSZ] = '\0';
+ if (prargs[0] == '\0') {
+ /* If psinfo.pr_psargs didn't contain any strings, use psinfo.pr_fname
+ * (which only contains the last component of exec()ed pathname) as a
+ * last resort. This is true for AIX kernel processes for example.
*/
- return WEXITSTATUS(status);
- } else if (WIFSIGNALED(status)) {
- /* The child exited because of a signal.
- * The best value to return is 0x80 + signal number,
- * because that is what all Unix shells do, and because
- * it allows callers to distinguish between process exit and
- * process death by signal.
- * Unfortunately, the historical behavior on Solaris is to return
- * the signal number, and we preserve this for compatibility. */
-#ifdef __solaris__
- return WTERMSIG(status);
-#else
- return 0x80 + WTERMSIG(status);
-#endif
- } else {
- /*
- * Unknown exit code; pass it through.
- */
- return status;
+ strncpy(prargs, psinfo.pr_fname, PRARGSZ);
+ prargs[PRARGSZ] = '\0';
}
+ unix_fillArgArray(env, jinfo, 0, NULL, NULL, cmdexe,
+ prargs[0] == '\0' ? NULL : prargs);
}
-
+#endif // defined(__solaris__) || defined(_AIX)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/unix/native/libjava/ProcessHandleImpl_unix.h Wed Jul 05 20:46:25 2017 +0200
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include <sys/types.h>
+
+/*
+ * Declaration of ProcessHandleImpl functions common on all Unix platforms.
+ * 'unix_' functions have a single implementation in ProcessHandleImpl_unix.c
+ * 'os_' prefixed functions have different, os-specific implementations in the
+ * various ProcessHandleImpl_{linux,macosx,solaris,aix}.c files.
+ * See ProcessHandleImpl_unix.c for more details.
+ */
+
+/* Field id for jString 'command' in java.lang.ProcessHandleImpl.Info */
+extern jfieldID ProcessHandleImpl_Info_commandID;
+
+/* Field id for jString 'commandLine' in java.lang.ProcessHandleImpl.Info */
+extern jfieldID ProcessHandleImpl_Info_commandLineID;
+
+/* Field id for jString[] 'arguments' in java.lang.ProcessHandleImpl.Info */
+extern jfieldID ProcessHandleImpl_Info_argumentsID;
+
+/* Field id for jlong 'totalTime' in java.lang.ProcessHandleImpl.Info */
+extern jfieldID ProcessHandleImpl_Info_totalTimeID;
+
+/* Field id for jlong 'startTime' in java.lang.ProcessHandleImpl.Info */
+extern jfieldID ProcessHandleImpl_Info_startTimeID;
+
+/* Field id for jString 'user' in java.lang.ProcessHandleImpl.Info */
+extern jfieldID ProcessHandleImpl_Info_userID;
+
+/**
+ * Return: -1 is fail; >= 0 is parent pid
+ * 'total' will contain the running time of 'pid' in nanoseconds.
+ * 'start' will contain the start time of 'pid' in milliseconds since epoch.
+ */
+extern pid_t unix_getParentPidAndTimings(JNIEnv *env, pid_t pid,
+ jlong *total, jlong *start);
+extern pid_t os_getParentPidAndTimings(JNIEnv *env, pid_t pid,
+ jlong *total, jlong *start);
+
+extern void unix_getCmdlineAndUserInfo(JNIEnv *env, jobject jinfo, pid_t pid);
+extern void os_getCmdlineAndUserInfo(JNIEnv *env, jobject jinfo, pid_t pid);
+
+extern jint unix_getChildren(JNIEnv *env, jlong jpid, jlongArray array,
+ jlongArray jparentArray, jlongArray jstimesArray);
+extern jint os_getChildren(JNIEnv *env, jlong jpid, jlongArray array,
+ jlongArray jparentArray, jlongArray jstimesArray);
+
+extern void unix_getUserInfo(JNIEnv* env, jobject jinfo, uid_t uid);
+extern void unix_fillArgArray(JNIEnv *env, jobject jinfo, int nargs, char *cp,
+ char *argsEnd, jstring cmdexe, char *cmdline);
+
+extern void os_initNative(JNIEnv *env, jclass clazz);
--- a/jdk/src/java.base/unix/native/libnio/ch/IOUtil.c Thu Aug 20 12:29:58 2015 -0700
+++ b/jdk/src/java.base/unix/native/libnio/ch/IOUtil.c Wed Jul 05 20:46:25 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -129,7 +129,8 @@
JNU_ThrowIOExceptionWithLastError(env, "getrlimit failed");
return -1;
}
- if (rlp.rlim_max < 0 || rlp.rlim_max > java_lang_Integer_MAX_VALUE) {
+ if (rlp.rlim_max == RLIM_INFINITY ||
+ rlp.rlim_max > (rlim_t)java_lang_Integer_MAX_VALUE) {
return java_lang_Integer_MAX_VALUE;
} else {
return (jint)rlp.rlim_max;
--- a/jdk/src/java.base/windows/classes/sun/io/Win32ErrorMode.java Thu Aug 20 12:29:58 2015 -0700
+++ b/jdk/src/java.base/windows/classes/sun/io/Win32ErrorMode.java Wed Jul 05 20:46:25 2017 +0200
@@ -59,8 +59,8 @@
* Invoke at VM initialization time to disable the critical error message box.
* <p>
* The critial error message box is disabled unless the system property
- * <tt>sun.io.allowCriticalErrorMessageBox</tt> is set to something other than
- * <code>false</code>. This includes the empty string.
+ * {@code sun.io.allowCriticalErrorMessageBox} is set to something other than
+ * {@code false}. This includes the empty string.
* <p>
* This method does nothing if invoked after VM and class library initialization
* has completed.
--- a/jdk/src/java.base/windows/classes/sun/net/www/protocol/file/Handler.java Thu Aug 20 12:29:58 2015 -0700
+++ b/jdk/src/java.base/windows/classes/sun/net/www/protocol/file/Handler.java Wed Jul 05 20:46:25 2017 +0200
@@ -134,8 +134,8 @@
* Compares the host components of two URLs.
* @param u1 the URL of the first host to compare
* @param u2 the URL of the second host to compare
- * @return <tt>true</tt> if and only if they
- * are equal, <tt>false</tt> otherwise.
+ * @return {@code true} if and only if they
+ * are equal, {@code false} otherwise.
*/
protected boolean hostsEqual(URL u1, URL u2) {
/*
--- a/jdk/src/java.base/windows/native/libjava/ProcessHandleImpl_win.c Thu Aug 20 12:29:58 2015 -0700
+++ b/jdk/src/java.base/windows/native/libjava/ProcessHandleImpl_win.c Wed Jul 05 20:46:25 2017 +0200
@@ -45,6 +45,9 @@
/* Field id for jString 'command' in java.lang.ProcessHandle.Info */
static jfieldID ProcessHandleImpl_Info_commandID;
+/* Field id for jString 'commandLine' in java.lang.ProcessHandleImpl.Info */
+static jfieldID ProcessHandleImpl_Info_commandLineID;
+
/* Field id for jString[] 'arguments' in java.lang.ProcessHandle.Info */
static jfieldID ProcessHandleImpl_Info_argumentsID;
@@ -69,6 +72,8 @@
CHECK_NULL(ProcessHandleImpl_Info_commandID = (*env)->GetFieldID(env,
clazz, "command", "Ljava/lang/String;"));
+ CHECK_NULL(ProcessHandleImpl_Info_commandLineID = (*env)->GetFieldID(env,
+ clazz, "commandLine", "Ljava/lang/String;"));
CHECK_NULL(ProcessHandleImpl_Info_argumentsID = (*env)->GetFieldID(env,
clazz, "arguments", "[Ljava/lang/String;"));
CHECK_NULL(ProcessHandleImpl_Info_totalTimeID = (*env)->GetFieldID(env,
--- a/jdk/src/java.base/windows/native/libnio/ch/Iocp.c Thu Aug 20 12:29:58 2015 -0700
+++ b/jdk/src/java.base/windows/native/libnio/ch/Iocp.c Wed Jul 05 20:46:25 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -57,16 +57,6 @@
CHECK_NULL(completionStatus_overlapped);
}
-JNIEXPORT jint JNICALL
-Java_sun_nio_ch_Iocp_osMajorVersion(JNIEnv* env, jclass this)
-{
- OSVERSIONINFOEX ver;
- ver.dwOSVersionInfoSize = sizeof(ver);
- GetVersionEx((OSVERSIONINFO *) &ver);
- return (ver.dwPlatformId == VER_PLATFORM_WIN32_NT) ?
- (jint)(ver.dwMajorVersion) : (jint)0;
-}
-
JNIEXPORT jlong JNICALL
Java_sun_nio_ch_Iocp_createIoCompletionPort(JNIEnv* env, jclass this,
jlong handle, jlong existingPort, jint completionKey, jint concurrency)
--- a/jdk/src/java.base/windows/native/libnio/ch/Net.c Thu Aug 20 12:29:58 2015 -0700
+++ b/jdk/src/java.base/windows/native/libnio/ch/Net.c Wed Jul 05 20:46:25 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -88,28 +88,14 @@
Java_sun_nio_ch_Net_isIPv6Available0(JNIEnv* env, jclass cl)
{
/*
- * Return true if Windows Vista or newer, and IPv6 is configured
+ * Return true if IPv6 is configured
*/
- OSVERSIONINFO ver;
- ver.dwOSVersionInfoSize = sizeof(ver);
- GetVersionEx(&ver);
- if ((ver.dwPlatformId == VER_PLATFORM_WIN32_NT) &&
- (ver.dwMajorVersion >= 6) && ipv6_available())
- {
- return JNI_TRUE;
- }
- return JNI_FALSE;
+ return ipv6_available() ? JNI_TRUE : JNI_FALSE;
}
JNIEXPORT jint JNICALL
Java_sun_nio_ch_Net_isExclusiveBindAvailable(JNIEnv *env, jclass clazz) {
- OSVERSIONINFO ver;
- int version;
- ver.dwOSVersionInfoSize = sizeof(ver);
- GetVersionEx(&ver);
- version = ver.dwMajorVersion * 10 + ver.dwMinorVersion;
- //if os <= xp exclusive binding is off by default
- return version >= 60 ? 1 : 0;
+ return 1;
}
@@ -567,7 +553,7 @@
fd_set rd, wr, ex;
jint fd = fdval(env, fdo);
- t.tv_sec = timeout / 1000;
+ t.tv_sec = (long)(timeout / 1000);
t.tv_usec = (timeout % 1000) * 1000;
FD_ZERO(&rd);
--- a/jdk/src/java.corba/share/classes/com/sun/jndi/cosnaming/RemoteToCorba.java Thu Aug 20 12:29:58 2015 -0700
+++ b/jdk/src/java.corba/share/classes/com/sun/jndi/cosnaming/RemoteToCorba.java Wed Jul 05 20:46:25 2017 +0200
@@ -56,7 +56,7 @@
* @param name Ignored
* @param ctx The non-null CNCtx whose ORB to use.
* @param env Ignored
- * @return The CORBA object for <tt>orig</tt> or null.
+ * @return The CORBA object for {@code orig} or null.
* @exception ConfigurationException If the CORBA object cannot be obtained
* due to configuration problems, for instance, if RMI-IIOP not available.
* @exception NamingException If some other problem prevented a CORBA
--- a/jdk/src/java.corba/share/classes/com/sun/jndi/toolkit/corba/CorbaUtils.java Thu Aug 20 12:29:58 2015 -0700
+++ b/jdk/src/java.corba/share/classes/com/sun/jndi/toolkit/corba/CorbaUtils.java Wed Jul 05 20:46:25 2017 +0200
@@ -76,7 +76,7 @@
*
* @param remoteObj The non-null remote object for
* @param orb The non-null ORB to connect the remote object to
- * @return The CORBA Object for remoteObj; null if <tt>remoteObj</tt>
+ * @return The CORBA Object for remoteObj; null if {@code remoteObj}
* is a JRMP implementation or JRMP stub.
* @exception ConfigurationException The CORBA Object cannot be obtained
* because of configuration problems.
--- a/jdk/src/java.management/share/classes/javax/management/InstanceOfQueryExp.java Thu Aug 20 12:29:58 2015 -0700
+++ b/jdk/src/java.management/share/classes/javax/management/InstanceOfQueryExp.java Wed Jul 05 20:46:25 2017 +0200
@@ -65,7 +65,7 @@
/**
* Returns the class name.
- * @returns The {@link StringValueExp} returning the name of
+ * @return The {@link StringValueExp} returning the name of
* the class of which selected MBeans should be instances.
*/
public StringValueExp getClassNameValue() {
--- a/jdk/src/java.naming/share/classes/com/sun/jndi/ldap/LdapCtx.java Thu Aug 20 12:29:58 2015 -0700
+++ b/jdk/src/java.naming/share/classes/com/sun/jndi/ldap/LdapCtx.java Wed Jul 05 20:46:25 2017 +0200
@@ -909,7 +909,7 @@
* @param dn The non-null DN of the entry to add
* @param attrs The non-null attributes of entry to add
* @param directUpdate Whether attrs can be updated directly
- * @returns Non-null attributes with attributes from the RDN added
+ * @return Non-null attributes with attributes from the RDN added
*/
private static Attributes addRdnAttributes(String dn, Attributes attrs,
boolean directUpdate) throws NamingException {
--- a/jdk/src/java.naming/share/classes/com/sun/jndi/ldap/ServiceLocator.java Thu Aug 20 12:29:58 2015 -0700
+++ b/jdk/src/java.naming/share/classes/com/sun/jndi/ldap/ServiceLocator.java Wed Jul 05 20:46:25 2017 +0200
@@ -62,7 +62,7 @@
*
* @param dn A string distinguished name (RFC 2253).
* @return A domain name or null if none can be derived.
- * @throw InvalidNameException If the distinguished name is invalid.
+ * @throws InvalidNameException If the distinguished name is invalid.
*/
static String mapDnToDomainName(String dn) throws InvalidNameException {
if (dn == null) {
--- a/jdk/src/java.naming/share/classes/com/sun/jndi/ldap/ext/StartTlsResponseImpl.java Thu Aug 20 12:29:58 2015 -0700
+++ b/jdk/src/java.naming/share/classes/com/sun/jndi/ldap/ext/StartTlsResponseImpl.java Wed Jul 05 20:46:25 2017 +0200
@@ -297,7 +297,7 @@
* Returns the default SSL socket factory.
*
* @return The default SSL socket factory.
- * @throw IOException If TLS is not supported.
+ * @throws IOException If TLS is not supported.
*/
private SSLSocketFactory getDefaultFactory() throws IOException {
@@ -314,7 +314,7 @@
*
* @param factory The SSL socket factory to use.
* @return The SSL socket.
- * @throw IOException If an exception occurred while performing the
+ * @throws IOException If an exception occurred while performing the
* TLS handshake.
*/
private SSLSocket startHandshake(SSLSocketFactory factory)
--- a/jdk/src/java.prefs/share/classes/java/util/prefs/Base64.java Thu Aug 20 12:29:58 2015 -0700
+++ b/jdk/src/java.prefs/share/classes/java/util/prefs/Base64.java Wed Jul 05 20:46:25 2017 +0200
@@ -124,8 +124,8 @@
* Translates the specified Base64 string (as per Preferences.get(byte[]))
* into a byte array.
*
- * @throw IllegalArgumentException if {@code s} is not a valid Base64
- * string.
+ * @throws IllegalArgumentException if {@code s} is not a valid Base64
+ * string.
*/
static byte[] base64ToByteArray(String s) {
return base64ToByteArray(s, false);
@@ -135,9 +135,9 @@
* Translates the specified "alternate representation" Base64 string
* into a byte array.
*
- * @throw IllegalArgumentException or ArrayOutOfBoundsException
- * if {@code s} is not a valid alternate representation
- * Base64 string.
+ * @throws IllegalArgumentException or ArrayOutOfBoundsException
+ * if {@code s} is not a valid alternate representation
+ * Base64 string.
*/
static byte[] altBase64ToByteArray(String s) {
return base64ToByteArray(s, true);
@@ -194,8 +194,8 @@
* Translates the specified character, which is assumed to be in the
* "Base 64 Alphabet" into its equivalent 6-bit positive integer.
*
- * @throw IllegalArgumentException or ArrayOutOfBoundsException if
- * c is not in the Base64 Alphabet.
+ * @throws IllegalArgumentException or ArrayOutOfBoundsException if
+ * c is not in the Base64 Alphabet.
*/
private static int base64toInt(char c, byte[] alphaToInt) {
int result = alphaToInt[c];
--- a/jdk/src/java.rmi/share/classes/java/rmi/RemoteException.java Thu Aug 20 12:29:58 2015 -0700
+++ b/jdk/src/java.rmi/share/classes/java/rmi/RemoteException.java Wed Jul 05 20:46:25 2017 +0200
@@ -26,11 +26,11 @@
package java.rmi;
/**
- * A <code>RemoteException</code> is the common superclass for a number of
+ * A {@code RemoteException} is the common superclass for a number of
* communication-related exceptions that may occur during the execution of a
* remote method call. Each method of a remote interface, an interface that
- * extends <code>java.rmi.Remote</code>, must list
- * <code>RemoteException</code> in its throws clause.
+ * extends {@code java.rmi.Remote}, must list
+ * {@code RemoteException} in its throws clause.
*
* <p>As of release 1.4, this exception has been retrofitted to conform to
* the general purpose exception-chaining mechanism. The "wrapped remote
@@ -40,7 +40,7 @@
* the aforementioned "legacy field."
*
* <p>Invoking the method {@link Throwable#initCause(Throwable)} on an
- * instance of <code>RemoteException</code> always throws {@link
+ * instance of {@code RemoteException} always throws {@link
* IllegalStateException}.
*
* @author Ann Wollrath
@@ -63,14 +63,14 @@
public Throwable detail;
/**
- * Constructs a <code>RemoteException</code>.
+ * Constructs a {@code RemoteException}.
*/
public RemoteException() {
initCause(null); // Disallow subsequent initCause
}
/**
- * Constructs a <code>RemoteException</code> with the specified
+ * Constructs a {@code RemoteException} with the specified
* detail message.
*
* @param s the detail message
@@ -81,9 +81,9 @@
}
/**
- * Constructs a <code>RemoteException</code> with the specified detail
+ * Constructs a {@code RemoteException} with the specified detail
* message and cause. This constructor sets the {@link #detail}
- * field to the specified <code>Throwable</code>.
+ * field to the specified {@code Throwable}.
*
* @param s the detail message
* @param cause the cause
@@ -113,7 +113,7 @@
* Returns the cause of this exception. This method returns the value
* of the {@link #detail} field.
*
- * @return the cause, which may be <tt>null</tt>.
+ * @return the cause, which may be {@code null}.
* @since 1.4
*/
public Throwable getCause() {
--- a/jdk/src/java.rmi/share/classes/java/rmi/activation/ActivationException.java Thu Aug 20 12:29:58 2015 -0700
+++ b/jdk/src/java.rmi/share/classes/java/rmi/activation/ActivationException.java Wed Jul 05 20:46:25 2017 +0200
@@ -36,7 +36,7 @@
* the aforementioned "legacy field."
*
* <p>Invoking the method {@link Throwable#initCause(Throwable)} on an
- * instance of <code>ActivationException</code> always throws {@link
+ * instance of {@code ActivationException} always throws {@link
* IllegalStateException}.
*
* @author Ann Wollrath
@@ -59,14 +59,14 @@
private static final long serialVersionUID = -4320118837291406071L;
/**
- * Constructs an <code>ActivationException</code>.
+ * Constructs an {@code ActivationException}.
*/
public ActivationException() {
initCause(null); // Disallow subsequent initCause
}
/**
- * Constructs an <code>ActivationException</code> with the specified
+ * Constructs an {@code ActivationException} with the specified
* detail message.
*
* @param s the detail message
@@ -77,9 +77,9 @@
}
/**
- * Constructs an <code>ActivationException</code> with the specified
+ * Constructs an {@code ActivationException} with the specified
* detail message and cause. This constructor sets the {@link #detail}
- * field to the specified <code>Throwable</code>.
+ * field to the specified {@code Throwable}.
*
* @param s the detail message
* @param cause the cause
@@ -109,7 +109,7 @@
* Returns the cause of this exception. This method returns the value
* of the {@link #detail} field.
*
- * @return the cause, which may be <tt>null</tt>.
+ * @return the cause, which may be {@code null}.
* @since 1.4
*/
public Throwable getCause() {
--- a/jdk/src/java.rmi/share/classes/java/rmi/server/ServerCloneException.java Thu Aug 20 12:29:58 2015 -0700
+++ b/jdk/src/java.rmi/share/classes/java/rmi/server/ServerCloneException.java Wed Jul 05 20:46:25 2017 +0200
@@ -26,8 +26,8 @@
package java.rmi.server;
/**
- * A <code>ServerCloneException</code> is thrown if a remote exception occurs
- * during the cloning of a <code>UnicastRemoteObject</code>.
+ * A {@code ServerCloneException} is thrown if a remote exception occurs
+ * during the cloning of a {@code UnicastRemoteObject}.
*
* <p>As of release 1.4, this exception has been retrofitted to conform to
* the general purpose exception-chaining mechanism. The "nested exception"
@@ -37,7 +37,7 @@
* the aforementioned "legacy field."
*
* <p>Invoking the method {@link Throwable#initCause(Throwable)} on an
- * instance of <code>ServerCloneException</code> always throws {@link
+ * instance of {@code ServerCloneException} always throws {@link
* IllegalStateException}.
*
* @author Ann Wollrath
@@ -61,7 +61,7 @@
private static final long serialVersionUID = 6617456357664815945L;
/**
- * Constructs a <code>ServerCloneException</code> with the specified
+ * Constructs a {@code ServerCloneException} with the specified
* detail message.
*
* @param s the detail message.
@@ -72,7 +72,7 @@
}
/**
- * Constructs a <code>ServerCloneException</code> with the specified
+ * Constructs a {@code ServerCloneException} with the specified
* detail message and cause.
*
* @param s the detail message.
@@ -103,7 +103,7 @@
* Returns the cause of this exception. This method returns the value
* of the {@link #detail} field.
*
- * @return the cause, which may be <tt>null</tt>.
+ * @return the cause, which may be {@code null}.
* @since 1.4
*/
public Throwable getCause() {
--- a/jdk/src/java.sql.rowset/share/classes/com/sun/rowset/package.html Thu Aug 20 12:29:58 2015 -0700
+++ b/jdk/src/java.sql.rowset/share/classes/com/sun/rowset/package.html Wed Jul 05 20:46:25 2017 +0200
@@ -26,51 +26,51 @@
<!DOCTYPE doctype PUBLIC "-//w3c//dtd html 4.0 transitional//en">
<html>
<head>
-
+
<meta http-equiv="Content-Type"
content="text/html; charset=iso-8859-1">
<title>com.sun.rowset Package</title>
</head>
<body bgcolor="#ffffff">
-Provides five standard implementations of the standard JDBC <tt>RowSet</tt> implementation
-interface definitions. These reference implementations are included with the J2SE version
-1.5 platform and represent the benchmark standard <tt>RowSet</tt> implementations as verified
+Provides five standard implementations of the standard JDBC <code>RowSet</code> implementation
+interface definitions. These reference implementations are included with the J2SE version
+1.5 platform and represent the benchmark standard <code>RowSet</code> implementations as verified
by the Test Compatibility Kit (TCK) as mandated by the Java Community Process.
- <br>
-
+<br>
+
<h3>1.0 Available JDBC RowSet Reference Implementations </h3>
- The following implementations are provided:<br>
-
-<blockquote><tt><b>JdbcRowSetImpl</b></tt> - The <tt>javax.sql.rowset.JdbcRowSet</tt>
+The following implementations are provided:<br>
+
+<blockquote><code><b>JdbcRowSetImpl</b></code> - The <code>javax.sql.rowset.JdbcRowSet</code>
interface reference implementation. <br>
<br>
-<tt><b>CachedRowSetImpl </b></tt>- The <tt>javax.sql.rowset.CachedRowSet</tt> interface
+<code><b>CachedRowSetImpl</b></code> - The <code>javax.sql.rowset.CachedRowSet</code> interface
reference implementation.<br>
<br>
-<tt><b>WebRowSetImpl</b></tt> - The <tt>javax.sql.rowset.WebRowSet</tt> interface
+<code><b>WebRowSetImpl</b></code> - The <code>javax.sql.rowset.WebRowSet</code> interface
reference implementation.<br>
<br>
-<tt><b>FilteredRowSetImpl</b></tt> - The <tt>javax.sql.rowset.FilteredRowSet</tt>
+<code><b>FilteredRowSetImpl</b></code> - The <code>javax.sql.rowset.FilteredRowSet</code>
interface reference implementation.<br>
<br>
-<tt><b>JoinRowSetImpl</b></tt> - The <tt>javax.sql.rowset.JoinRowSet</tt> interface
+<code><b>JoinRowSetImpl</b></code> - The <code>javax.sql.rowset.JoinRowSet</code> interface
reference implementation.<br>
</blockquote>
-All details on their expected behavior, including their interactions with the <tt>SyncProvider</tt>
-SPI and helper classes are provided in the interface definitions in the <tt>javax.sql.rowset</tt>
+All details on their expected behavior, including their interactions with the <code>SyncProvider</code>
+SPI and helper classes are provided in the interface definitions in the <code>javax.sql.rowset</code>
package specification.<br>
-
+
<h3>2.0 Usage</h3>
The reference implementations represent robust implementations of the standard
-<code>RowSet</code> interfaces defined in the <code>javax.sql.rowset</code> package.
-All disconnected <code>RowSet</code> implementations, such as the <tt>CachedRowSetImpl</tt>
-and <tt>WebRowSetImpl</tt>, are flexible enough to use the <tt>SyncFactory</tt> SPIs to
-leverage non-reference implementation <tt>SyncProvider</tt> implementations to obtain
-differing synchronization semantics. Furthermore, developers and vendors alike are free
+<code>RowSet</code> interfaces defined in the <code>javax.sql.rowset</code> package.
+All disconnected <code>RowSet</code> implementations, such as the <code>CachedRowSetImpl</code>
+and <code>WebRowSetImpl</code>, are flexible enough to use the <code>SyncFactory</code> SPIs to
+leverage non-reference implementation <code>SyncProvider</code> implementations to obtain
+differing synchronization semantics. Furthermore, developers and vendors alike are free
to use these implementations and integrate them into their products just as they
can with to other components of the Java platform.<br>
-
+
<h3>3.0 Extending the JDBC RowSet Implementations</h3>
The JDBC <code>RowSet</code> reference implementations are provided as non-final
@@ -81,6 +81,6 @@
provider a portal where implementations can be listed, similar to the way it
provides a site for JDBC drivers.
<br>
- <br>
+<br>
</body>
</html>
--- a/jdk/src/java.sql.rowset/share/classes/com/sun/rowset/providers/package.html Thu Aug 20 12:29:58 2015 -0700
+++ b/jdk/src/java.sql.rowset/share/classes/com/sun/rowset/providers/package.html Wed Jul 05 20:46:25 2017 +0200
@@ -1,10 +1,10 @@
<!DOCTYPE doctype PUBLIC "-//w3c//dtd html 4.0 transitional//en">
<html>
<head>
-
+
<meta http-equiv="Content-Type"
content="text/html; charset=iso-8859-1">
-
+
<meta name="GENERATOR"
content="Mozilla/4.79 [en] (Windows NT 5.0; U) [Netscape]">
<!--
@@ -35,21 +35,21 @@
<title>javax.sql.rowset.providers Package</title>
</head>
<body bgcolor="#ffffff">
- Repository for the <tt>RowSet</tt> reference implementations of the
- <tt>SyncProvider</tt> abstract class. These implementations provide a
- disconnected <code>RowSet</code>
- object with the ability to synchronize the data in the underlying data
- source with its data. These implementations are provided as
-the default <tt>SyncProvider</tt> implementations and are accessible via the
-<tt>SyncProvider</tt> SPI managed by the <tt>SyncFactory</tt>.
+Repository for the <code>RowSet</code> reference implementations of the
+<code>SyncProvider</code> abstract class. These implementations provide a
+disconnected <code>RowSet</code>
+object with the ability to synchronize the data in the underlying data
+source with its data. These implementations are provided as
+the default <code>SyncProvider</code> implementations and are accessible via the
+<code>SyncProvider</code> SPI managed by the <code>SyncFactory</code>.
<h3>1.0 <code>SyncProvider</code> Reference Implementations</h3>
- The main job of a <tt>SyncProvider</tt> implementation is to manage
+ The main job of a <code>SyncProvider</code> implementation is to manage
the reader and writer mechanisms.
- The <tt>SyncProvider</tt> SPI, as specified in the <tt>javax.sql.rowset.spi</tt>
-package, provides a pluggable mechanism by which <tt>javax.sql.RowSetReader</tt>
-and <tt>javax.sql.RowSetWriter</tt> implementations can be supplied to a disconnected
-<tt>RowSet</tt> object.
+ The <code>SyncProvider</code> SPI, as specified in the <code>javax.sql.rowset.spi</code>
+package, provides a pluggable mechanism by which <code>javax.sql.RowSetReader</code>
+and <code>javax.sql.RowSetWriter</code> implementations can be supplied to a disconnected
+<code>RowSet</code> object.
<P>
A reader, a <code>javax.sql.RowSetReader</code>
object, does the work necessary to populate a <code>RowSet</code> object with data.
@@ -100,24 +100,24 @@
<UL>
<LI>
-<b><tt>RIOptimisticProvider </tt></b>- provides the <tt>javax.sql.RowSetReader</tt>
- and <tt>javax.sql.RowSetWriter</tt> interface implementations and provides
+<b><code>RIOptimisticProvider</code></b> - provides the <code>javax.sql.RowSetReader</code>
+and <code>javax.sql.RowSetWriter</code> interface implementations and provides
an optimistic concurrency model for synchronization. This model assumes that there
will be few conflicts and therefore uses a relatively low grade of synchronization.
If no other provider is available, this is the default provider that the
<code>SyncFactory</code> will supply to a <code>RowSet</code> object.
<br>
<LI>
- <b><tt>RIXMLProvider </tt></b>- provides the <tt>XmlReader</tt> (an extension
-of the <tt>javax.sql.RowSetReader</tt> interface) and the <tt>XmlWriter</tt>
-(an extension of the <tt>javax.sql.RowSetWriter</tt> interface) to enable
- <tt>WebRowSet</tt> objects to write their state to a
-well formed XML document according to the <tt>WebRowSet</tt> XML schema
+<b><code>RIXMLProvider</code></b> - provides the <code>XmlReader</code> (an extension
+of the <code>javax.sql.RowSetReader</code> interface) and the <code>XmlWriter</code>
+(an extension of the <code>javax.sql.RowSetWriter</code> interface) to enable
+<code>WebRowSet</code> objects to write their state to a
+well formed XML document according to the <code>WebRowSet</code> XML schema
definition.<br>
</UL>
<h3>2.0 Basics in RowSet Population & Synchronization</h3>
- A rowset's first task is to populate itself with rows of column values.
+A rowset's first task is to populate itself with rows of column values.
Generally, these rows will come from a relational database, so a rowset
has properties that supply what is necessary for making a connection to
a database and executing a query. A rowset that does not need to establish
@@ -127,28 +127,28 @@
properties. The general rule is that a RowSet is required to set only the
properties that it uses.<br>
<br>
- The <tt>command</tt> property contains the query that determines what
+The <code>command</code> property contains the query that determines what
data a <code>RowSet</code> will contain. Rowsets have methods for setting a query's
parameter(s), which means that a query can be executed multiple times with
different parameters to produce different result sets. Or the query can be
changed to something completely new to get a new result set.
-<p>Once a rowset contains the rows from a <tt>ResultSet</tt> object or some
- other data source, its column values can be updated, and its rows can be
- inserted or deleted. Any method that causes a change in the rowset's values
- or cursor position also notifies any object that has been registered as
-a listener with the rowset. So, for example, a table that displays the rowset's
- data in an applet can be notified of changes and make updates as they
- occur.<br>
+<p>Once a rowset contains the rows from a <code>ResultSet</code> object or some
+other data source, its column values can be updated, and its rows can be
+inserted or deleted. Any method that causes a change in the rowset's values
+or cursor position also notifies any object that has been registered as
+a listener with the rowset. So, for example, a table that displays the rowset's
+data in an applet can be notified of changes and make updates as they
+occur.<br>
<br>
- The changes made to a rowset can be propagated back to the original data
- source to keep the rowset and its data source synchronized. Although this
- involves many operations behind the scenes, it is completely transparent
- to the application programmer and remains the concern of the RowSet provider
- developer. All an application has to do is invoke the method <tt>acceptChanges</tt>,
- and the data source backing the rowset will be updated to match the current
- values in the rowset. </p>
-
-<p>A disconnected rowset, such as a <tt>CachedRowSet</tt> or <tt>WebRowSet</tt>
+The changes made to a rowset can be propagated back to the original data
+source to keep the rowset and its data source synchronized. Although this
+involves many operations behind the scenes, it is completely transparent
+to the application programmer and remains the concern of the RowSet provider
+developer. All an application has to do is invoke the method <code>acceptChanges</code>,
+and the data source backing the rowset will be updated to match the current
+values in the rowset. </p>
+
+<p>A disconnected rowset, such as a <code>CachedRowSet</code> or <code>WebRowSet</code>
object, establishes a connection to populate itself with data from a database
and then closes the connection. The <code>RowSet</code> object will remain
disconnected until it wants to propagate changes back to its database table,
@@ -156,9 +156,9 @@
the database), the rowset establishes a connection, write the changes, and then
once again disconnects itself.<br>
</p>
-
+
<h3> 3.0 Other Possible Implementations</h3>
- There are many other possible implementations of the <tt>SyncProvider</tt> abstract
+ There are many other possible implementations of the <code>SyncProvider</code> abstract
class. One possibility is to employ a more robust synchronization model, which
would give a <code>RowSet</code> object increased trust in the provider's
ability to get any updates back to the original data source. Another possibility
--- a/jdk/src/java.sql.rowset/share/classes/javax/sql/rowset/package.html Thu Aug 20 12:29:58 2015 -0700
+++ b/jdk/src/java.sql.rowset/share/classes/javax/sql/rowset/package.html Wed Jul 05 20:46:25 2017 +0200
@@ -1,7 +1,7 @@
<!DOCTYPE doctype PUBLIC "-//w3c//dtd html 4.0 transitional//en">
<html>
<head>
-
+
<meta http-equiv="Content-Type"
content="text/html; charset=iso-8859-1">
<!--
@@ -53,40 +53,40 @@
All five extend the
<a href="../RowSet.html">RowSet</a> interface described in the JDBC 3.0
specification. It is anticipated that additional definitions
-of more specialized JDBC <code>RowSet</code> types will emerge as this technology
-matures. Future definitions <i>should</i> be specified as subinterfaces using
+of more specialized JDBC <code>RowSet</code> types will emerge as this technology
+matures. Future definitions <i>should</i> be specified as subinterfaces using
inheritance similar to the way it is used in this specification.
<p>
<i>Note:</i> The interface definitions provided in this package form the basis for
all compliant JDBC <code>RowSet</code> implementations. Vendors and more advanced
-developers who intend to provide their own compliant <code>RowSet</code> implementations
+developers who intend to provide their own compliant <code>RowSet</code> implementations
should pay particular attention to the assertions detailed in specification
interfaces.
<h3><a name="stdrowset">2.0 Standard RowSet Definitions</a></h3>
<ul>
-<li><a href="JdbcRowSet.html"><b><code>JdbcRowSet</code></b></a> - A wrapper around
-a <tt>ResultSet</tt> object that makes it possible to use the result set as a
+<li><a href="JdbcRowSet.html"><b><code>JdbcRowSet</code></b></a> - A wrapper around
+a <code>ResultSet</code> object that makes it possible to use the result set as a
JavaBeans™ component. Thus,
-a <tt>JdbcRowSet</tt> object can be a Bean that any tool
+a <code>JdbcRowSet</code> object can be a Bean that any tool
makes available for assembling an application as part of a component based
-architecture . A <tt>JdbcRowSet</tt> object is a connected <code>RowSet</code>
+architecture. A <code>JdbcRowSet</code> object is a connected <code>RowSet</code>
object, that is, it
<b>must</b> continually maintain its connection to its data source using a JDBC
technology-enabled driver ("JDBC driver"). In addition, a <code>JdbcRowSet</code>
-object provides a fully updatable and scrollable tabular
+object provides a fully updatable and scrollable tabular
data structure as defined in the JDBC 3.0 specification.
<li><a href="CachedRowSet.html">
<b><code>CachedRowSet</code>™</b></a>
- - A <tt>CachedRowSet</tt> object is a JavaBeans™
+ - A <code>CachedRowSet</code> object is a JavaBeans™
component that is scrollable, updatable, serializable, and generally disconnected from
- the source of its data. A <tt>CachedRowSet</tt> object
+ the source of its data. A <code>CachedRowSet</code> object
typically contains rows from a result set, but it can also contain rows from any
-file with a tabular format, such as a spreadsheet. <tt>CachedRowSet</tt> implementations
-<b>must</b> use the <tt>SyncFactory</tt> to manage and obtain pluggable
+file with a tabular format, such as a spreadsheet. <code>CachedRowSet</code> implementations
+<b>must</b> use the <code>SyncFactory</code> to manage and obtain pluggable
<code>SyncProvider</code> objects to provide synchronization between the
-disconnected <code>RowSet</code> object and the originating data source.
+disconnected <code>RowSet</code> object and the originating data source.
Typically a <code>SyncProvider</code> implementation relies upon a JDBC
driver to obtain connectivity to a particular data source.
Further details on this mechanism are discussed in the <a
@@ -94,13 +94,13 @@
specification.
<li><a href="WebRowSet.html"><b><code>WebRowSet</code></b></a> - A
-<code>WebRowSet</code> object is an extension of <tt>CachedRowSet</tt>
+<code>WebRowSet</code> object is an extension of <code>CachedRowSet</code>
that can read and write a <code>RowSet</code> object in a well formed XML format.
-This class calls an <a href="spi/XmlReader.html"><code>XmlReader</code></a> object
+This class calls an <a href="spi/XmlReader.html"><code>XmlReader</code></a> object
(an extension of the <a href="../RowSetReader.html"><code>RowSetReader</code></a>
interface) to read a rowset in XML format. It calls an
-<a href="spi/XmlWriter.html"><code>XmlWriter</code></a> object (an extension of the
-<a href="../RowSetWriter.html"><code>RowSetWriter</code></a> interface)
+<a href="spi/XmlWriter.html"><code>XmlWriter</code></a> object (an extension of the
+<a href="../RowSetWriter.html"><code>RowSetWriter</code></a> interface)
to write a rowset in XML format. The reader and writer required by
<code>WebRowSet</code> objects are provided by the
<code>SyncFactory</code> in the form of <code>SyncProvider</code>
@@ -110,14 +110,14 @@
<code>http://java.sun.com/xml/ns/jdbc/webrowset.xsd</code></a>.
<li><a href="FilteredRowSet.html"><b><code>FilteredRowSet</code></b></a> - A
-<tt>FilteredRowSet</tt> object provides filtering functionality in a programmatic
-and extensible way. There are many instances when a <tt>RowSet</tt> <code>object</code>
+<code>FilteredRowSet</code> object provides filtering functionality in a programmatic
+and extensible way. There are many instances when a <code>RowSet</code> <code>object</code>
has a need to provide filtering in its contents without sacrificing the disconnected
environment, thus saving the expense of having to create a connection to the data source.
Solutions to this need vary from providing heavyweight full scale
SQL query abilities, to portable components, to more lightweight
approaches. A <code>FilteredRowSet</code> object consumes
-an implementation of the <a href="Predicate.html"><code>Predicate</code></a>
+an implementation of the <a href="Predicate.html"><code>Predicate</code></a>
interface, which <b>may</b> define a filter at run time. In turn, a
<code>FilteredRowSet</code> object is tasked with enforcing the set filter for both
inbound and outbound read and write operations. That is, all filters can be
@@ -125,19 +125,19 @@
however, sufficient mechanics are specified to permit any required filter to be
implemented.
-<li><a href="JoinRowSet.html"><b><code>JoinRowSet</code></b></a> - The <tt>JoinRowSet</tt>
-interface describes a mechanism by which relationships can be established between
-two or more standard <code>RowSet</code> implementations. Any number of <tt>RowSet</tt>
- objects can be added to a <tt>JoinRowSet</tt> object provided the <tt>RowSet</tt>objects
-can be related in a SQL <tt>JOIN</tt> like fashion. By definition, the SQL <tt>JOIN</tt>
+<li><a href="JoinRowSet.html"><b><code>JoinRowSet</code></b></a> - The <code>JoinRowSet</code>
+interface describes a mechanism by which relationships can be established between
+two or more standard <code>RowSet</code> implementations. Any number of <code>RowSet</code>
+ objects can be added to a <code>JoinRowSet</code> object provided the <code>RowSet</code>objects
+can be related in a SQL <code>JOIN</code> like fashion. By definition, the SQL <code>JOIN</code>
statement is used to combine the data contained in two (<i>or more</i>) relational
database tables based upon a common attribute. By establishing and then enforcing
-column matches, a <tt>JoinRowSet</tt> object establishes relationships between
-<tt>RowSet</tt> instances without the need to touch the originating data source.
+column matches, a <code>JoinRowSet</code> object establishes relationships between
+<code>RowSet</code> instances without the need to touch the originating data source.
</ul>
<h3><a name="impl">3.0 Implementer's Guide</a></h3>
-Compliant implementations of JDBC <code>RowSet</code> Implementations
+Compliant implementations of JDBC <code>RowSet</code> Implementations
<b>must</b> follow the assertions described in this specification. In accordance
with the terms of the <a href="http://www.jcp.org">Java Community Process</a>, a
Test Compatibility Kit (TCK) can be licensed to ensure compatibility with the
@@ -155,24 +155,24 @@
</li>
<li><b>3.2 Role of the <code>BaseRowSet</code> Class</b>
<p>
-A compliant JDBC <code>RowSet</code> implementation <b>must</b> implement one or more
-standard interfaces specified in this package and <b>may</b> extend the
-<a href="BaseRowSet.html"><code>BaseRowSet</code></a> abstract class. For example, a
+A compliant JDBC <code>RowSet</code> implementation <b>must</b> implement one or more
+standard interfaces specified in this package and <b>may</b> extend the
+<a href="BaseRowSet.html"><code>BaseRowSet</code></a> abstract class. For example, a
<code>CachedRowSet</code> implementation must implement the <code>CachedRowSet</code>
interface and extend the <code>BaseRowSet</code> abstract class. The
<code>BaseRowSet</code> class provides the standard architecture on which all
<code>RowSet</code> implementations should be built, regardless of whether the
<code>RowSet</code> objects exist in a connected or disconnected environment.
-The <tt>BaseRowSet</tt> abstract class provides any <tt>RowSet</tt> implementation
+The <code>BaseRowSet</code> abstract class provides any <code>RowSet</code> implementation
with its base functionality, including property manipulation and event notification
-that is fully compliant with <a href="http://java.sun.com/products/javabeans">JavaBeans</a>
+that is fully compliant with <a href="http://java.sun.com/products/javabeans">JavaBeans</a>
component requirements. As an example, all implementations provided in the
-reference implementations (contained in the <tt>com.sun.rowset</tt> package) use
-the <tt>BaseRowSet</tt> class as a basis for their implementations.
+reference implementations (contained in the <code>com.sun.rowset</code> package) use
+the <code>BaseRowSet</code> class as a basis for their implementations.
<P>
The following table illustrates the features that the <code>BaseRowSet</code>
abstract class provides.
- <blockquote>
+ <blockquote>
<table cellpadding="2" cellspacing="2" border="1" width="75%">
<tbody>
<tr>
@@ -185,8 +185,8 @@
<td valign="top">Properties<br>
</td>
<td valign="top">Provides standard JavaBeans property manipulation
- mechanisms to allow applications to get and set <code>RowSet</code> command and
-property values. Refer to the documentation of the <tt>javax.sql.RowSet</tt>
+mechanisms to allow applications to get and set <code>RowSet</code> command and
+property values. Refer to the documentation of the <code>javax.sql.RowSet</code>
interface (available in the JDBC 3.0 specification) for more details on
the standard <code>RowSet</code> properties.<br>
</td>
@@ -195,9 +195,9 @@
<td valign="top">Event notification<br>
</td>
<td valign="top">Provides standard JavaBeans event notifications
- to registered event listeners. Refer to the documentation of <tt>javax.sql.RowSetEvent
- </tt> interface (available in the JDBC 3.0 specification) for
-more details on how to register and handle standard RowSet events generated
+to registered event listeners. Refer to the documentation of <code>javax.sql.RowSetEvent</code>
+interface (available in the JDBC 3.0 specification) for
+more details on how to register and handle standard RowSet events generated
by compliant implementations.<br>
</td>
</tr>
@@ -223,8 +223,8 @@
<p>
The <code>JdbcRowSet</code> describes a <code>RowSet</code> object that <b>must</b> always
be connected to the originating data source. Implementations of the <code>JdbcRowSet</code>
-should ensure that this connection is provided solely by a JDBC driver.
-Furthermore, <code>RowSet</code> objects that are implementations of the
+should ensure that this connection is provided solely by a JDBC driver.
+Furthermore, <code>RowSet</code> objects that are implementations of the
<code>JdbcRowSet</code> interface and are therefore operating in a connected environment
do not use the <code>SyncFactory</code> to obtain a <code>RowSetReader</code> object
or a <code>RowSetWriter</code> object. They can safely rely on the JDBC driver to
@@ -234,24 +234,24 @@
<li>
<b>3.4 Disconnected RowSet Requirements</b>
<p>
-A disconnected <code>RowSet</code> object, such as a <code>CachedRowSet</code> object,
+A disconnected <code>RowSet</code> object, such as a <code>CachedRowSet</code> object,
<b>should</b> delegate
-connection management to a <code>SyncProvider</code> object provided by the
-<code>SyncFactory</code>. To ensure fully disconnected semantics, all
+connection management to a <code>SyncProvider</code> object provided by the
+<code>SyncFactory</code>. To ensure fully disconnected semantics, all
disconnected <code>RowSet</code> objects <b>must</b> ensure
-that the original connection made to the data source to populate the <code>RowSet</code>
+that the original connection made to the data source to populate the <code>RowSet</code>
object is closed to permit the garbage collector to recover and release resources. The
-<code>SyncProvider</code> object ensures that the critical JDBC properties are
-maintained in order to re-establish a connection to the data source when a
-synchronization is required. A disconnected <code>RowSet</code> object should
-therefore ensure that no
+<code>SyncProvider</code> object ensures that the critical JDBC properties are
+maintained in order to re-establish a connection to the data source when a
+synchronization is required. A disconnected <code>RowSet</code> object should
+therefore ensure that no
extraneous references remain on the <code>Connection</code> object.
<li><b>3.5 Role of RowSetMetaDataImpl</b>
<p>
The <code>RowsetMetaDataImpl</code> class is a utility class that provides an implementation of the
<a href="../RowSetMetaData.html">RowSetMetaData</a> interface, supplying standard setter
-method implementations for metadata for both connected and disconnected
+method implementations for metadata for both connected and disconnected
<code>RowSet</code> objects. All implementations are free to use this standard
implementation but are not required to do so.
@@ -261,10 +261,10 @@
on <code>RowSet</code> implementations.
Similar to <a href="../../../java/sql/SQLWarning.html">SQLWarning</a> objects,
<code>RowSetWarning</code> objects are silently chained to the object whose method
-caused the warning to be thrown. All <code>RowSet</code> implementations <b>should</b>
+caused the warning to be thrown. All <code>RowSet</code> implementations <b>should</b>
ensure that this chaining occurs if a warning is generated and also ensure that the
warnings are available via the <code>getRowSetWarnings</code> method defined in either
-the <code>JdbcRowSet</code> interface or the <code>CachedRowSet</code> interface.
+the <code>JdbcRowSet</code> interface or the <code>CachedRowSet</code> interface.
After a warning has been retrieved with one of the
<code>getRowSetWarnings</code> methods, the <code>RowSetWarning</code> method
<code>getNextWarning</code> can be called on it to retrieve any warnings that might
@@ -273,10 +273,10 @@
<li><b>3.7 The Joinable Interface</b>
<P>
-The <code>Joinable</code> interface provides both connected and disconnected
-<code>RowSet</code> objects with the capability to be added to a
+The <code>Joinable</code> interface provides both connected and disconnected
+<code>RowSet</code> objects with the capability to be added to a
<code>JoinRowSet</code> object in an SQL <code>JOIN</code> operation.
-A <code>RowSet</code> object that has implemented the <code>Joinable</code>
+A <code>RowSet</code> object that has implemented the <code>Joinable</code>
interface can set a match column, retrieve a match column, or unset a match column.
A <code>JoinRowSet</code> object can then use the <code>RowSet</code> object's
match column as a basis for adding the <code>RowSet</code> object.
@@ -298,7 +298,7 @@
<h3><a name="reldocs">5.0 Related Documentation</a></h3>
<ul>
<li><a href="http://docs.oracle.com/javase/tutorial/jdbc/basics/rowset.html">
-JDBC RowSet Tutorial</a>
+JDBC RowSet Tutorial</a>
</ul>
</body>
</html>
--- a/jdk/src/java.sql.rowset/share/classes/javax/sql/rowset/serial/package.html Thu Aug 20 12:29:58 2015 -0700
+++ b/jdk/src/java.sql.rowset/share/classes/javax/sql/rowset/serial/package.html Wed Jul 05 20:46:25 2017 +0200
@@ -1,10 +1,10 @@
<!DOCTYPE doctype PUBLIC "-//w3c//dtd html 4.0 transitional//en">
<html>
<head>
-
+
<meta http-equiv="Content-Type"
content="text/html; charset=iso-8859-1">
-
+
<meta name="GENERATOR"
content="Mozilla/4.79 [en] (Windows NT 5.0; U) [Netscape]">
<!--
@@ -36,52 +36,52 @@
<body bgcolor="#ffffff">
Provides utility classes to allow serializable mappings between SQL types
and data types in the Java programming language.
-<p> Standard JDBC <code>RowSet</code> implementations may use these utility
+<p> Standard JDBC <code>RowSet</code> implementations may use these utility
classes to
-assist in the serialization of disconnected <code>RowSet</code> objects.
+assist in the serialization of disconnected <code>RowSet</code> objects.
This is useful
-when transmitting a disconnected <tt>RowSet</tt> object over the wire to
+when transmitting a disconnected <code>RowSet</code> object over the wire to
a different VM or across layers within an application.<br>
</p>
<h3>1.0 SerialArray</h3>
-A serializable mapping in the Java programming language of an SQL ARRAY
+A serializable mapping in the Java programming language of an SQL ARRAY
value. <br>
<br>
-The <tt>SerialArray </tt>class provides a constructor for creating a <tt>SerialArray
-</tt>instance from an Array object, methods for getting the base type and
+The <code>SerialArray</code> class provides a constructor for creating a <code>SerialArray</code>
+instance from an Array object, methods for getting the base type and
the SQL name for the base type, and methods for copying all or part of a
-<tt>SerialArray </tt>object. <br>
+<code>SerialArray</code> object. <br>
<h3>2.0 SerialBlob</h3>
A serializable mapping in the Java programming language of an SQL BLOB
value. <br>
<br>
-The <tt>SerialBlob </tt>class provides a constructor for creating an instance
+The <code>SerialBlob</code>class provides a constructor for creating an instance
from a Blob object. Note that the Blob object should have brought the SQL
-BLOB value's data over to the client before a <tt>SerialBlob </tt>object
+BLOB value's data over to the client before a <code>SerialBlob</code>object
is constructed from it. The data of an SQL BLOB value can be materialized
-on the client as an array of bytes (using the method <tt>Blob.getBytes</tt>)
-or as a stream of uninterpreted bytes (using the method <tt>Blob.getBinaryStream</tt>).
+on the client as an array of bytes (using the method <code>Blob.getBytes</code>)
+or as a stream of uninterpreted bytes (using the method <code>Blob.getBinaryStream</code>).
<br>
<br>
-<tt>SerialBlob </tt>methods make it possible to make a copy of a <tt>SerialBlob
-</tt>object as an array of bytes or as a stream. They also make it possible
-to locate a given pattern of bytes or a <tt>Blob </tt>object within a <tt>SerialBlob
-</tt>object. <br>
+<code>SerialBlob</code> methods make it possible to make a copy of a <code>SerialBlob</code>
+object as an array of bytes or as a stream. They also make it possible
+to locate a given pattern of bytes or a <code>Blob</code> object within a <code>SerialBlob</code>
+object. <br>
<h3>3.0 SerialClob</h3>
A serializable mapping in the Java programming language of an SQL CLOB
value. <br>
<br>
-The <tt>SerialClob </tt>class provides a constructor for creating an instance
-from a <tt>Clob </tt>object. Note that the <tt>Clob </tt>object should have
-brought the SQL CLOB value's data over to the client before a <tt>SerialClob
-</tt>object is constructed from it. The data of an SQL CLOB value can be
+The <code>SerialClob</code> class provides a constructor for creating an instance
+from a <code>Clob</code> object. Note that the <code>Clob</code> object should have
+brought the SQL CLOB value's data over to the client before a <code>SerialClob</code>
+object is constructed from it. The data of an SQL CLOB value can be
materialized on the client as a stream of Unicode characters. <br>
<br>
-<tt>SerialClob </tt>methods make it possible to get a substring from a
-<tt>SerialClob </tt>object or to locate the start of a pattern of characters.
+<code>SerialClob</code> methods make it possible to get a substring from a
+<code>SerialClob</code> object or to locate the start of a pattern of characters.
<br>
<h3>5.0 SerialDatalink</h3>
@@ -89,11 +89,11 @@
value. A DATALINK value references a file outside of the underlying data source
that the originating data source manages. <br>
<br>
-<code>RowSet</code> implementations can use the method <tt>RowSet.getURL() </tt>to retrieve
+<code>RowSet</code> implementations can use the method <code>RowSet.getURL()</code> to retrieve
a <code>java.net.URL</code> object, which can be used to manipulate the external data.
<br>
<br>
- <tt> java.net.URL url = rowset.getURL(1);</tt><br>
+ <code> java.net.URL url = rowset.getURL(1);</code><br>
<h3>6.0 SerialJavaObject</h3>
A serializable mapping in the Java programming language of an SQL JAVA_OBJECT
@@ -103,16 +103,16 @@
If however, the serialization is not possible in the case where the Java
object is not immediately serializable, this class will attempt to serialize
all non static members to permit the object instance state to be serialized.
-Static or transient fields cannot be serialized and attempting to do so
-will result in a <tt>SerialException </tt>being thrown. <br>
+Static or transient fields cannot be serialized and attempting to do so
+will result in a <code>SerialException</code> being thrown. <br>
<h3>7.0 SerialRef</h3>
A serializable mapping between the SQL REF type and the Java programming
language. <br>
<br>
-The <tt>SerialRef </tt>class provides a constructor for creating a <tt>SerialRef
-</tt>instance from a <tt>Ref</tt> type and provides methods for getting
-and setting the <tt>Ref</tt> object type. <br>
+The <code>SerialRef</code> class provides a constructor for creating a <code>SerialRef</code>
+instance from a <code>Ref</code> type and provides methods for getting
+and setting the <code>Ref</code> object type. <br>
<h3>8.0 SerialStruct</h3>
A serializable mapping in the Java programming language of an SQL structured
@@ -121,58 +121,58 @@
that is not already serializable is mapped to a serializable form. <br>
<br>
In addition, if a <code>Map</code> object is passed to one of the constructors or
-to the method <code>getAttributes</code>, the structured type is custom mapped
+to the method <code>getAttributes</code>, the structured type is custom mapped
according to the mapping specified in the <code>Map</code> object.
- <br>
- The <tt>SerialStruct </tt>class provides a constructor for creating an
-instance from a <tt>Struct</tt> object, a method for retrieving the SQL
+<br>
+The <code>SerialStruct</code> class provides a constructor for creating an
+instance from a <code>Struct</code> object, a method for retrieving the SQL
type name of the SQL structured type in the database, and methods for retrieving
its attribute values. <br>
-
+
<h3>9.0 SQLInputImpl</h3>
- An input stream used for custom mapping user-defined types (UDTs). An
- <tt>SQLInputImpl</tt> object is an input stream that contains a stream of
+ An input stream used for custom mapping user-defined types (UDTs). An
+ <code>SQLInputImpl</code> object is an input stream that contains a stream of
values that are
the attributes of a UDT. This class is used by the driver behind the scenes
-when the method <tt>getObject</tt> is called on an SQL structured or distinct
-type that has a custom mapping; a programmer never invokes <tt>SQLInputImpl
-</tt> methods directly. <br>
+when the method <code>getObject</code> is called on an SQL structured or distinct
+type that has a custom mapping; a programmer never invokes <code>SQLInputImpl</code>
+methods directly. <br>
<br>
- The <tt>SQLInputImpl</tt> class provides a set of reader methods
- analogous to the <tt>ResultSet</tt> getter methods. These methods make it
- possible to read the values in an <tt>SQLInputImpl</tt> object. The method
+The <code>SQLInputImpl</code> class provides a set of reader methods
+analogous to the <code>ResultSet</code> getter methods. These methods make it
+possible to read the values in an <code>SQLInputImpl</code> object. The method
<code>wasNull</code> is used to determine whether the last value read was SQL NULL.
+<br>
<br>
- <br>
- When a constructor or getter method that takes a <code>Map</code> object is called,
+When a constructor or getter method that takes a <code>Map</code> object is called,
the JDBC driver calls the method
-<tt>SQLData.getSQLType</tt> to determine the SQL type of the UDT being custom
+<code>SQLData.getSQLType</code> to determine the SQL type of the UDT being custom
mapped. The driver creates an instance of <code>SQLInputImpl</code>, populating it with
the attributes of the UDT. The driver then passes the input stream to the
-method <tt>SQLData.readSQL</tt>, which in turn calls the <tt>SQLInputImpl</tt>
+method <code>SQLData.readSQL</code>, which in turn calls the <code>SQLInputImpl</code>
methods to read the attributes from the input stream. <br>
-
+
<h3>10.0 SQLOutputImpl</h3>
The output stream for writing the attributes of a custom mapped user-defined
type (UDT) back to the database. The driver uses this interface internally,
and its methods are never directly invoked by an application programmer.
<br>
<br>
- When an application calls the method <tt>PreparedStatement.setObject, </tt>the
- driver checks to see whether the value to be written is a UDT with a custom
- mapping. If it is, there will be an entry in a type map containing the Class
- object for the class that implements <tt>SQLData </tt>for this UDT. If the
- value to be written is an instance of <tt>SQLData</tt>, the driver will
-create an instance of <code>SQLOutputImpl</code> and pass it to the method
-<tt>SQLData.writeSQL</tt>.
- The method <code>writeSQL</code> in turn calls the appropriate <tt>SQLOutputImpl</tt>
-writer methods to write data from the <code>SQLData</code> object to the
+When an application calls the method <code>PreparedStatement.setObject</code>, the
+driver checks to see whether the value to be written is a UDT with a custom
+mapping. If it is, there will be an entry in a type map containing the Class
+object for the class that implements <code>SQLData</code> for this UDT. If the
+value to be written is an instance of <code>SQLData</code>, the driver will
+create an instance of <code>SQLOutputImpl</code> and pass it to the method
+<code>SQLData.writeSQL</code>.
+The method <code>writeSQL</code> in turn calls the appropriate <code>SQLOutputImpl</code>
+writer methods to write data from the <code>SQLData</code> object to the
<code>SQLOutputImpl</code>
-output stream as the representation of an SQL user-defined type.
-
+output stream as the representation of an SQL user-defined type.
+
<h3>Custom Mapping</h3>
-The JDBC API provides mechanisms for mapping an SQL structured type or DISTINCT
-type to the Java programming language. Typically, a structured type is mapped
+The JDBC API provides mechanisms for mapping an SQL structured type or DISTINCT
+type to the Java programming language. Typically, a structured type is mapped
to a class, and its attributes are mapped to fields in the class.
(A DISTINCT type can thought of as having one attribute.) However, there are
many other possibilities, and there may be any number of different mappings.
@@ -181,7 +181,7 @@
For example, if an SQL structured type named AUTHORS has the attributes NAME,
TITLE, and PUBLISHER, it could be mapped to a Java class named Authors. The
Authors class could have the fields name, title, and publisher, to which the
-attributes of AUTHORS are mapped. In such a case, the implementation of
+attributes of AUTHORS are mapped. In such a case, the implementation of
<code>SQLData</code> could look like the following:
<PRE>
public class Authors implements SQLData {
@@ -213,27 +213,27 @@
A <code>java.util.Map</code> object is used to associate the SQL structured
type with its mapping to the class <code>Authors</code>. The following code fragment shows
how a <code>Map</code> object might be created and given an entry associating
-<code>AUTHORS</code> and <code>Authors</code>.
+<code>AUTHORS</code> and <code>Authors</code>.
<PRE>
java.util.Map map = new java.util.HashMap();
map.put("SCHEMA_NAME.AUTHORS", Class.forName("Authors");
</PRE>
-
-The <code>Map</code> object <i>map</i> now contains an entry with the
+
+The <code>Map</code> object <i>map</i> now contains an entry with the
fully qualified name of the SQL structured type and the <code>Class</code>
object for the class <code>Authors</code>. It can be passed to a method
-to tell the driver how to map <code>AUTHORS</code> to <code>Authors</code>.
+to tell the driver how to map <code>AUTHORS</code> to <code>Authors</code>.
<P>
For a disconnected <code>RowSet</code> object, custom mapping can be done
only when a <code>Map</code> object is passed to the method or constructor
that will be doing the custom mapping. The situation is different for
connected <code>RowSet</code> objects because they maintain a connection
-with the data source. A method that does custom mapping and is called by
+with the data source. A method that does custom mapping and is called by
a disconnected <code>RowSet</code> object may use the <code>Map</code>
object that is associated with the <code>Connection</code> object being
-used. So, in other words, if no map is specified, the connection's type
+used. So, in other words, if no map is specified, the connection's type
map can be used by default.
-
+
<br>
</body>
</html>
--- a/jdk/src/java.sql.rowset/share/classes/javax/sql/rowset/spi/package.html Thu Aug 20 12:29:58 2015 -0700
+++ b/jdk/src/java.sql.rowset/share/classes/javax/sql/rowset/spi/package.html Wed Jul 05 20:46:25 2017 +0200
@@ -37,14 +37,14 @@
<body bgcolor="#ffffff">
The standard classes and interfaces that a third party vendor has to
-use in its implementation of a synchronization provider. These classes and
-interfaces are referred to as the Service Provider Interface (SPI). A vendor may
+use in its implementation of a synchronization provider. These classes and
+interfaces are referred to as the Service Provider Interface (SPI). A vendor may
have its implementation included on the JDBC web page that lists available
<code>SyncProvider</code> implementations by sending email to <code>jdbc@sun.com</code>.
Doing this helps make developers aware of the implementation. To make it possible
for a <code>RowSet</code> object to use an implementation, the vendor must register
it with the <code>SyncFactory</code> singleton. (See the class comment for
-<code>SyncProvider</code> for a full explanation of the registration process and
+<code>SyncProvider</code> for a full explanation of the registration process and
the naming convention to be used.)
<h2>Table of Contents</h2>
@@ -81,10 +81,10 @@
object with the mechanisms for reading data into it and for writing data that has been
modified in it
back to the underlying data source. A <i>reader</i>, a <code>RowSetReader</code> or
-<code>XMLReader</code> object, reads data into a <code>RowSet</code> object when the
-<code>CachedRowSet</code> methods <code>execute</code> or <code>populate</code>
+<code>XMLReader</code> object, reads data into a <code>RowSet</code> object when the
+<code>CachedRowSet</code> methods <code>execute</code> or <code>populate</code>
are called. A <i>writer</i>, a <code>RowSetWriter</code> or <code>XMLWriter</code>
-object, writes changes back to the underlying data source when the
+object, writes changes back to the underlying data source when the
<code>CachedRowSet</code> method <code>acceptChanges</code> is called.
<P>
The process of writing changes in a <code>RowSet</code> object to its data source
@@ -96,9 +96,9 @@
The lower grades of synchronization are
known as <i>optimistic</i> concurrency levels because they optimistically
assume that there will be no conflicts or very few conflicts. A conflict exists when
-the same data modified in the <code>RowSet</code> object has also been modified
+the same data modified in the <code>RowSet</code> object has also been modified
in the data source. Using the optimistic concurrency model means that if there
-is a conflict, modifications to either the data source or the <code>RowSet</code>
+is a conflict, modifications to either the data source or the <code>RowSet</code>
object will be lost.
<P>
Higher grades of synchronization are called <i>pessimistic</i> because they assume
@@ -106,7 +106,7 @@
grades set varying levels of locks to increase the chances that no conflicts
occur.
<P>
-The lowest level of synchronization is simply writing any changes made to the
+The lowest level of synchronization is simply writing any changes made to the
<code>RowSet</code> object to its underlying data source. The writer does
nothing to check for conflicts.
If there is a conflict and the data
@@ -116,69 +116,69 @@
The <code>RIXMLProvider</code> implementation uses the lowest level
of synchronization and just writes <code>RowSet</code> changes to the data source.
This is true because typically XML data sources do not enable transaction
-techniques for maintaining the integrity of data. However, specific standards
+techniques for maintaining the integrity of data. However, specific standards
groups have considered offering XML-based synchronization. For details, see
<PRE>
<a href="http://www.syncml.org">http://www.syncml.org</a>
</PRE>
<P>
For the next level up, the
-writer checks to see if there are any conflicts, and if there are,
+writer checks to see if there are any conflicts, and if there are,
it does not write anything to the data source. The problem with this concurrency
-level is that if another party has modified the corresponding data in the data source
+level is that if another party has modified the corresponding data in the data source
since the <code>RowSet</code> object got its data,
the changes made to the <code>RowSet</code> object are lost. The
<code>RIOptimisticProvider</code> implementation uses this level of synchronization.
<P>
At higher levels of synchronization, referred to as pessimistic concurrency,
the writer take steps to avoid conflicts by setting locks. Setting locks
-can vary from setting a lock on a single row to setting a lock on a table
-or the entire data source. The level of synchronization is therefore a tradeoff
+can vary from setting a lock on a single row to setting a lock on a table
+or the entire data source. The level of synchronization is therefore a tradeoff
between the ability of users to access the data source concurrently and the ability
of the writer to keep the data in the <code>RowSet</code> object and its data source
synchronized.
<P>
-It is a requirement that all disconnected <code>RowSet</code> objects
-(<code>CachedRowSet</code>, <code>FilteredRowSet</code>, <code>JoinRowSet</code>,
+It is a requirement that all disconnected <code>RowSet</code> objects
+(<code>CachedRowSet</code>, <code>FilteredRowSet</code>, <code>JoinRowSet</code>,
and <code>WebRowSet</code> objects) obtain their <code>SyncProvider</code> objects
from the <code>SyncFactory</code> mechanism.
<P>
The reference implementation (RI) provides two synchronization providers.
- <UL>
- <LI><b><tt>RIOptimisticProvider</tt></b> <br>
+ <UL>
+ <LI><b><code>RIOptimisticProvider</code></b> <br>
The default provider that the <code>SyncFactory</code> instance will
supply to a disconnected <code>RowSet</code> object when no provider
implementation is specified.<BR>
This synchronization provider uses an optimistic concurrency model,
- assuming that there will be few conflicts among users
+ assuming that there will be few conflicts among users
who are accessing the same data in a database. It avoids
using locks; rather, it checks to see if there is a conflict
before trying to synchronize the <code>RowSet</code> object and the
data source. If there is a conflict, it does nothing, meaning that
changes to the <code>RowSet</code> object are not persisted to the data
source.
- <LI><B><tt>RIXMLProvider</tt></B> <BR>
+ <LI><B><code>RIXMLProvider</code></B> <BR>
A synchronization provider that can be used with a
- <code>WebRowSet</code> object, which is a rowset that can be written
- in XML format or read from XML format. The
+ <code>WebRowSet</code> object, which is a rowset that can be written
+ in XML format or read from XML format. The
<code>RIXMLProvider</code> implementation does no checking at all for
conflicts and simply writes any updated data in the
<code>WebRowSet</code> object to the underlying data source.
<code>WebRowSet</code> objects use this provider when they are
dealing with XML data.
- </UL>
+ </UL>
These <code>SyncProvider</code> implementations
are bundled with the reference implementation, which makes them always available to
-<code>RowSet</code> implementations.
+<code>RowSet</code> implementations.
<code>SyncProvider</code> implementations make themselves available by being
-registered with the <code>SyncFactory</code> singleton. When a <code>RowSet</code>
+registered with the <code>SyncFactory</code> singleton. When a <code>RowSet</code>
object requests a provider, by specifying it in the constructor or as an argument to the
-<code>CachedRowSet</code> method <code>setSyncProvider</code>,
+<code>CachedRowSet</code> method <code>setSyncProvider</code>,
the <code>SyncFactory</code> singleton
checks to see if the requested provider has been registered with it.
If it has, the <code>SyncFactory</code> creates an instance of it and passes it to the
-requesting <code>RowSet</code> object.
+requesting <code>RowSet</code> object.
If the <code>SyncProvider</code> implementation that is specified has not been registered,
the <code>SyncFactory</code> singleton causes a <code>SyncFactoryException</code> object
to be thrown. If no provider is specified,
@@ -189,18 +189,18 @@
<P>
If a <code>WebRowSet</code> object does not specify a provider in its constructor, the
<code>SyncFactory</code> will give it an instance of <code>RIOptimisticProvider</code>.
-However, the constructor for <code>WebRowSet</code> is implemented to set the provider
+However, the constructor for <code>WebRowSet</code> is implemented to set the provider
to the <code>RIXMLProvider</code>, which reads and writes a <code>RowSet</code> object
in XML format.
<P>
See the <a href="SyncProvider.html">SyncProvider</a> class
specification for further details.
<p>
-Vendors may develop a <tt>SyncProvider</tt> implementation with any one of the possible
+Vendors may develop a <code>SyncProvider</code> implementation with any one of the possible
levels of synchronization, thus giving <code>RowSet</code> objects a choice of
-synchronization mechanisms. A vendor can make its implementation available by
+synchronization mechanisms. A vendor can make its implementation available by
registering the fully qualified class name with Oracle Corporation at
-<code>jdbc@sun.com</code>. This process is discussed in further detail below.
+<code>jdbc@sun.com</code>. This process is discussed in further detail below.
<h3><a name="arch">2.0 Service Provider Interface Architecture</a></h3>
<b>2.1 Overview</b>
@@ -208,7 +208,7 @@
The Service Provider Interface provides a pluggable mechanism by which
<code>SyncProvider</code> implementations can be registered and then generated when
required. The lazy reference mechanism employed by the <code>SyncFactory</code> limits
-unnecessary resource consumption by not creating an instance until it is
+unnecessary resource consumption by not creating an instance until it is
required by a disconnected
<code>RowSet</code> object. The <code>SyncFactory</code> class also provides
a standard API to configure logging options and streams that <b>may</b> be provided
@@ -216,11 +216,11 @@
<p>
<b>2.2 Registering with the <code>SyncFactory</code></b>
<p>
-A third party <code>SyncProvider</code> implementation must be registered with the
-<code>SyncFactory</code> in order for a disconnected <code>RowSet</code> object
-to obtain it and thereby use its <code>javax.sql.RowSetReader</code> and
+A third party <code>SyncProvider</code> implementation must be registered with the
+<code>SyncFactory</code> in order for a disconnected <code>RowSet</code> object
+to obtain it and thereby use its <code>javax.sql.RowSetReader</code> and
<code>javax.sql.RowSetWriter</code>
-implementations. The following registration mechanisms are available to all
+implementations. The following registration mechanisms are available to all
<code>SyncProvider</code> implementations:
<ul>
<li><b>System properties</b> - Properties set at the command line. These
@@ -235,9 +235,9 @@
file than can be edited to add additional <code>SyncProvider</code> objects.
<li><b>JNDI Context</b> - Available providers can be registered on a JNDI
-context. The <tt>SyncFactory</tt> will attempt to load <tt>SyncProvider</tt>
+context. The <code>SyncFactory</code> will attempt to load <code>SyncProvider</code>
objects bound to the context and register them with the factory. This
-context must be supplied to the <code>SyncFactory</code> for the mechanism to
+context must be supplied to the <code>SyncFactory</code> for the mechanism to
function correctly.
</ul>
<p>
@@ -250,11 +250,11 @@
The <code>SyncFactory</code> generates a requested <code>SyncProvider</code>
object if the provider has been correctly registered. The
following policies are adhered to when either a disconnected <code>RowSet</code> object
-is instantiated with a specified <code>SyncProvider</code> implementation or is
+is instantiated with a specified <code>SyncProvider</code> implementation or is
reconfigured at runtime with an alternative <code>SyncProvider</code> object.
<ul>
<li> If a <code>SyncProvider</code> object is specified and the <code>SyncFactory</code>
-contains <i>no</i> reference to the provider, a <code>SyncFactoryException</code> is
+contains <i>no</i> reference to the provider, a <code>SyncFactoryException</code> is
thrown.
<li> If a <code>SyncProvider</code> object is specified and the <code>SyncFactory</code>
@@ -294,13 +294,13 @@
<li><b>GRADE_NONE</b> - No synchronization with the originating data source is
provided. A <code>SyncProvider</code> implementation returning this grade will simply
attempt to write any data that has changed in the <code>RowSet</code> object to the
-underlying data source, overwriting whatever is there. No attempt is made to compare
-original values with current values to see if there is a conflict. The
+underlying data source, overwriting whatever is there. No attempt is made to compare
+original values with current values to see if there is a conflict. The
<code>RIXMLProvider</code> is implemented with this grade.
<li><b>GRADE_CHECK_MODIFIED_AT_COMMIT</b> - A low grade of optimistic synchronization.
A <code>SyncProvider</code> implementation returning this grade
-will check for conflicts in rows that have changed between the last synchronization
+will check for conflicts in rows that have changed between the last synchronization
and the current synchronization under way. Any changes in the originating data source
that have been modified will not be reflected in the disconnected <code>RowSet</code>
object. If there are no conflicts, changes in the <code>RowSet</code> object will be
@@ -333,16 +333,16 @@
on which constructs the locks are placed. These locks will remain on the data
source while the <code>RowSet</code> object is disconnected from the data source.
<P>
-These constants <b>should</b> be considered complementary to the
+These constants <b>should</b> be considered complementary to the
grade constants. The default setting for the majority of grade settings requires
-that no data source locks remain when a <code>RowSet</code> object is disconnected
+that no data source locks remain when a <code>RowSet</code> object is disconnected
from its data source.
The grades <code>GRADE_LOCK_WHEN_MODIFIED</code> and
<code>GRADE_LOCK_WHEN_LOADED</code> allow a disconnected <code>RowSet</code> object
to have a fine-grained control over the degree of locking.
<ul>
-<li><b>DATASOURCE_NO_LOCK</b> - No locks remain on the originating data source.
-This is the default lock setting for all <code>SyncProvider</code> implementations
+<li><b>DATASOURCE_NO_LOCK</b> - No locks remain on the originating data source.
+This is the default lock setting for all <code>SyncProvider</code> implementations
unless otherwise directed by a <code>RowSet</code> object.
<li><b>DATASOURCE_ROW_LOCK</b> - A lock is placed on the rows that are touched by
@@ -364,26 +364,26 @@
<ul>
<li><b>UPDATABLE_VIEW_SYNC</b>
Indicates that a <code>SyncProvider</code> implementation supports synchronization
-to the table or tables from which the SQL <code>VIEW</code> used to populate a
+to the table or tables from which the SQL <code>VIEW</code> used to populate
a <code>RowSet</code> object is derived.
<li><b>NONUPDATABLE_VIEW_SYNC</b>
Indicates that a <code>SyncProvider</code> implementation does <b>not</b> support
-synchronization to the table or tables from which the SQL <code>VIEW</code>
+synchronization to the table or tables from which the SQL <code>VIEW</code>
used to populate a <code>RowSet</code> object is derived.
</ul>
<p>
<b>3.5 Usage of <code>SyncProvider</code> Grading and Locking</b>
<p>
-In the example below, the reference <tt>CachedRowSetImpl</tt> implementation
-reconfigures its current <tt>SyncProvider</tt> object by calling the
-<tt>setSyncProvider</tt> method.<br>
+In the example below, the reference <code>CachedRowSetImpl</code> implementation
+reconfigures its current <code>SyncProvider</code> object by calling the
+<code>setSyncProvider</code> method.<br>
<PRE>
CachedRowSetImpl crs = new CachedRowSetImpl();
crs.setSyncProvider("com.foo.bar.HASyncProvider");
</PRE>
- An application can retrieve the <tt>SyncProvider</tt> object currently in use
+ An application can retrieve the <code>SyncProvider</code> object currently in use
by a disconnected <code>RowSet</code> object. It can also retrieve the
grade of synchronization with which the provider was implemented and the degree of
locking currently in use. In addition, an application has the flexibility to set
@@ -396,14 +396,14 @@
case: SyncProvider.GRADE_CHECK_ALL_AT_COMMIT
//A high grade of optimistic synchronization
break;
- case: SyncProvider.GRADE_CHECK_MODIFIED_AT_COMMIT
- //A low grade of optimistic synchronization
+ case: SyncProvider.GRADE_CHECK_MODIFIED_AT_COMMIT
+ //A low grade of optimistic synchronization
break;
- case: SyncProvider.GRADE_LOCK_WHEN_LOADED
- // A pessimistic synchronization grade
+ case: SyncProvider.GRADE_LOCK_WHEN_LOADED
+ // A pessimistic synchronization grade
break;
- case: SyncProvider.GRADE_LOCK_WHEN_MODIFIED
- // A pessimistic synchronization grade
+ case: SyncProvider.GRADE_LOCK_WHEN_MODIFIED
+ // A pessimistic synchronization grade
break;
case: SyncProvider.GRADE_NONE
// No synchronization with the originating data source provided
@@ -421,13 +421,13 @@
break;
case: SyncProvider.DATASOURCE_ROW_LOCK
- // A lock is placed on the rows that are touched by the original
+ // A lock is placed on the rows that are touched by the original
// SQL statement used to populate
// the RowSet object that is using the SyncProvider
break;
case: DATASOURCE_TABLE_LOCK
- // A lock is placed on all tables that are touched by the original
+ // A lock is placed on all tables that are touched by the original
// SQL statement used to populated
// the RowSet object that is using the SyncProvider
break;
@@ -450,12 +450,12 @@
it throws a <code>SyncProviderException</code> object. An application can
catch the exception and
have it retrieve a <code>SyncResolver</code> object by calling the method
-<code>SyncProviderException.getSyncResolver()</code>.
+<code>SyncProviderException.getSyncResolver()</code>.
<P>
-A <code>SyncResolver</code> object, which is a special kind of
+A <code>SyncResolver</code> object, which is a special kind of
<code>CachedRowSet</code> object or
-a <code>JdbcRowSet</code> object that has implemented the <code>SyncResolver</code>
-interface, examines the conflicts row by row. It is a duplicate of the
+a <code>JdbcRowSet</code> object that has implemented the <code>SyncResolver</code>
+interface, examines the conflicts row by row. It is a duplicate of the
<code>RowSet</code> object being synchronized except that it contains only the data
from the data source this is causing a conflict. All of the other column values are
set to <code>null</code>. To navigate from one conflict value to another, a
@@ -472,18 +472,18 @@
to be changed
</UL>
<P>
-When the <code>CachedRowSet</code> method <code>acceptChanges</code> is called, it
+When the <code>CachedRowSet</code> method <code>acceptChanges</code> is called, it
delegates to the <code>RowSet</code> object's <code>SyncProvider</code> object.
How the writer provided by that <code>SyncProvider</code> object is implemented
-determines what level (grade) of checking for conflicts will be done. After all
+determines what level (grade) of checking for conflicts will be done. After all
checking for conflicts is completed and one or more conflicts has been found, the method
<code>acceptChanges</code> throws a <code>SyncProviderException</code> object. The
-application can catch the exception and use it to obtain a <code>SyncResolver</code> object.
+application can catch the exception and use it to obtain a <code>SyncResolver</code> object.
<P>
The application can then use <code>SyncResolver</code> methods to get information
about each conflict and decide what to do. If the application logic or the user
decides that a value in the <code>RowSet</code> object should be the one to
-persist, the application or user can overwrite the data source value with it.
+persist, the application or user can overwrite the data source value with it.
<P>
The comment for the <code>SyncResolver</code> interface has more detail.
--- a/jdk/src/java.sql/share/classes/java/sql/Timestamp.java Thu Aug 20 12:29:58 2015 -0700
+++ b/jdk/src/java.sql/share/classes/java/sql/Timestamp.java Wed Jul 05 20:46:25 2017 +0200
@@ -31,43 +31,43 @@
import sun.misc.JavaLangAccess;
/**
- * <P>A thin wrapper around <code>java.util.Date</code> that allows
- * the JDBC API to identify this as an SQL <code>TIMESTAMP</code> value.
+ * <P>A thin wrapper around {@code java.util.Date} that allows
+ * the JDBC API to identify this as an SQL {@code TIMESTAMP} value.
* It adds the ability
- * to hold the SQL <code>TIMESTAMP</code> fractional seconds value, by allowing
+ * to hold the SQL {@code TIMESTAMP} fractional seconds value, by allowing
* the specification of fractional seconds to a precision of nanoseconds.
* A Timestamp also provides formatting and
* parsing operations to support the JDBC escape syntax for timestamp values.
*
* <p>The precision of a Timestamp object is calculated to be either:
* <ul>
- * <li><code>19 </code>, which is the number of characters in yyyy-mm-dd hh:mm:ss
- * <li> <code> 20 + s </code>, which is the number
- * of characters in the yyyy-mm-dd hh:mm:ss.[fff...] and <code>s</code> represents the scale of the given Timestamp,
+ * <li>{@code 19 }, which is the number of characters in yyyy-mm-dd hh:mm:ss
+ * <li> {@code 20 + s }, which is the number
+ * of characters in the yyyy-mm-dd hh:mm:ss.[fff...] and {@code s} represents the scale of the given Timestamp,
* its fractional seconds precision.
*</ul>
*
- * <P><B>Note:</B> This type is a composite of a <code>java.util.Date</code> and a
+ * <P><B>Note:</B> This type is a composite of a {@code java.util.Date} and a
* separate nanoseconds value. Only integral seconds are stored in the
- * <code>java.util.Date</code> component. The fractional seconds - the nanos - are
- * separate. The <code>Timestamp.equals(Object)</code> method never returns
- * <code>true</code> when passed an object
- * that isn't an instance of <code>java.sql.Timestamp</code>,
+ * {@code java.util.Date} component. The fractional seconds - the nanos - are
+ * separate. The {@code Timestamp.equals(Object)} method never returns
+ * {@code true} when passed an object
+ * that isn't an instance of {@code java.sql.Timestamp},
* because the nanos component of a date is unknown.
- * As a result, the <code>Timestamp.equals(Object)</code>
+ * As a result, the {@code Timestamp.equals(Object)}
* method is not symmetric with respect to the
- * <code>java.util.Date.equals(Object)</code>
- * method. Also, the <code>hashCode</code> method uses the underlying
- * <code>java.util.Date</code>
+ * {@code java.util.Date.equals(Object)}
+ * method. Also, the {@code hashCode} method uses the underlying
+ * {@code java.util.Date}
* implementation and therefore does not include nanos in its computation.
* <P>
- * Due to the differences between the <code>Timestamp</code> class
- * and the <code>java.util.Date</code>
+ * Due to the differences between the {@code Timestamp} class
+ * and the {@code java.util.Date}
* class mentioned above, it is recommended that code not view
- * <code>Timestamp</code> values generically as an instance of
- * <code>java.util.Date</code>. The
- * inheritance relationship between <code>Timestamp</code>
- * and <code>java.util.Date</code> really
+ * {@code Timestamp} values generically as an instance of
+ * {@code java.util.Date}. The
+ * inheritance relationship between {@code Timestamp}
+ * and {@code java.util.Date} really
* denotes implementation inheritance, and not type inheritance.
*/
public class Timestamp extends java.util.Date {
@@ -75,7 +75,7 @@
private static final JavaLangAccess jla = SharedSecrets.getJavaLangAccess();
/**
- * Constructs a <code>Timestamp</code> object initialized
+ * Constructs a {@code Timestamp} object initialized
* with the given values.
*
* @param year the year minus 1900
@@ -85,7 +85,7 @@
* @param minute 0 to 59
* @param second 0 to 59
* @param nano 0 to 999,999,999
- * @deprecated instead use the constructor <code>Timestamp(long millis)</code>
+ * @deprecated instead use the constructor {@code Timestamp(long millis)}
* @exception IllegalArgumentException if the nano argument is out of bounds
*/
@Deprecated
@@ -99,11 +99,11 @@
}
/**
- * Constructs a <code>Timestamp</code> object
+ * Constructs a {@code Timestamp} object
* using a milliseconds time value. The
* integral seconds are stored in the underlying date value; the
- * fractional seconds are stored in the <code>nanos</code> field of
- * the <code>Timestamp</code> object.
+ * fractional seconds are stored in the {@code nanos} field of
+ * the {@code Timestamp} object.
*
* @param time milliseconds since January 1, 1970, 00:00:00 GMT.
* A negative number is the number of milliseconds before
@@ -120,8 +120,8 @@
}
/**
- * Sets this <code>Timestamp</code> object to represent a point in time that is
- * <tt>time</tt> milliseconds after January 1, 1970 00:00:00 GMT.
+ * Sets this {@code Timestamp} object to represent a point in time that is
+ * {@code time} milliseconds after January 1, 1970 00:00:00 GMT.
*
* @param time the number of milliseconds.
* @see #getTime
@@ -139,7 +139,7 @@
/**
* Returns the number of milliseconds since January 1, 1970, 00:00:00 GMT
- * represented by this <code>Timestamp</code> object.
+ * represented by this {@code Timestamp} object.
*
* @return the number of milliseconds since January 1, 1970, 00:00:00 GMT
* represented by this date.
@@ -157,16 +157,16 @@
private int nanos;
/**
- * Converts a <code>String</code> object in JDBC timestamp escape format to a
- * <code>Timestamp</code> value.
+ * Converts a {@code String} object in JDBC timestamp escape format to a
+ * {@code Timestamp} value.
*
- * @param s timestamp in format <code>yyyy-[m]m-[d]d hh:mm:ss[.f...]</code>. The
- * fractional seconds may be omitted. The leading zero for <code>mm</code>
- * and <code>dd</code> may also be omitted.
+ * @param s timestamp in format {@code yyyy-[m]m-[d]d hh:mm:ss[.f...]}. The
+ * fractional seconds may be omitted. The leading zero for {@code mm}
+ * and {@code dd} may also be omitted.
*
- * @return corresponding <code>Timestamp</code> value
+ * @return corresponding {@code Timestamp} value
* @exception java.lang.IllegalArgumentException if the given argument
- * does not have the format <code>yyyy-[m]m-[d]d hh:mm:ss[.f...]</code>
+ * does not have the format {@code yyyy-[m]m-[d]d hh:mm:ss[.f...]}
*/
public static Timestamp valueOf(String s) {
final int YEAR_LENGTH = 4;
@@ -258,11 +258,11 @@
/**
* Formats a timestamp in JDBC timestamp escape format.
- * <code>yyyy-mm-dd hh:mm:ss.fffffffff</code>,
- * where <code>ffffffffff</code> indicates nanoseconds.
+ * {@code yyyy-mm-dd hh:mm:ss.fffffffff},
+ * where {@code ffffffffff} indicates nanoseconds.
*
- * @return a <code>String</code> object in
- * <code>yyyy-mm-dd hh:mm:ss.fffffffff</code> format
+ * @return a {@code String} object in
+ * {@code yyyy-mm-dd hh:mm:ss.fffffffff} format
*/
@SuppressWarnings("deprecation")
public String toString() {
@@ -315,9 +315,9 @@
}
/**
- * Gets this <code>Timestamp</code> object's <code>nanos</code> value.
+ * Gets this {@code Timestamp} object's {@code nanos} value.
*
- * @return this <code>Timestamp</code> object's fractional seconds component
+ * @return this {@code Timestamp} object's fractional seconds component
* @see #setNanos
*/
public int getNanos() {
@@ -325,7 +325,7 @@
}
/**
- * Sets this <code>Timestamp</code> object's <code>nanos</code> field
+ * Sets this {@code Timestamp} object's {@code nanos} field
* to the given value.
*
* @param n the new fractional seconds component
@@ -341,13 +341,13 @@
}
/**
- * Tests to see if this <code>Timestamp</code> object is
- * equal to the given <code>Timestamp</code> object.
+ * Tests to see if this {@code Timestamp} object is
+ * equal to the given {@code Timestamp} object.
*
- * @param ts the <code>Timestamp</code> value to compare with
- * @return <code>true</code> if the given <code>Timestamp</code>
- * object is equal to this <code>Timestamp</code> object;
- * <code>false</code> otherwise
+ * @param ts the {@code Timestamp} value to compare with
+ * @return {@code true} if the given {@code Timestamp}
+ * object is equal to this {@code Timestamp} object;
+ * {@code false} otherwise
*/
public boolean equals(Timestamp ts) {
if (super.equals(ts)) {
@@ -362,22 +362,22 @@
}
/**
- * Tests to see if this <code>Timestamp</code> object is
+ * Tests to see if this {@code Timestamp} object is
* equal to the given object.
*
- * This version of the method <code>equals</code> has been added
+ * This version of the method {@code equals} has been added
* to fix the incorrect
- * signature of <code>Timestamp.equals(Timestamp)</code> and to preserve backward
+ * signature of {@code Timestamp.equals(Timestamp)} and to preserve backward
* compatibility with existing class files.
*
* Note: This method is not symmetric with respect to the
- * <code>equals(Object)</code> method in the base class.
+ * {@code equals(Object)} method in the base class.
*
- * @param ts the <code>Object</code> value to compare with
- * @return <code>true</code> if the given <code>Object</code> is an instance
- * of a <code>Timestamp</code> that
- * is equal to this <code>Timestamp</code> object;
- * <code>false</code> otherwise
+ * @param ts the {@code Object} value to compare with
+ * @return {@code true} if the given {@code Object} is an instance
+ * of a {@code Timestamp} that
+ * is equal to this {@code Timestamp} object;
+ * {@code false} otherwise
*/
public boolean equals(java.lang.Object ts) {
if (ts instanceof Timestamp) {
@@ -388,40 +388,40 @@
}
/**
- * Indicates whether this <code>Timestamp</code> object is
- * earlier than the given <code>Timestamp</code> object.
+ * Indicates whether this {@code Timestamp} object is
+ * earlier than the given {@code Timestamp} object.
*
- * @param ts the <code>Timestamp</code> value to compare with
- * @return <code>true</code> if this <code>Timestamp</code> object is earlier;
- * <code>false</code> otherwise
+ * @param ts the {@code Timestamp} value to compare with
+ * @return {@code true} if this {@code Timestamp} object is earlier;
+ * {@code false} otherwise
*/
public boolean before(Timestamp ts) {
return compareTo(ts) < 0;
}
/**
- * Indicates whether this <code>Timestamp</code> object is
- * later than the given <code>Timestamp</code> object.
+ * Indicates whether this {@code Timestamp} object is
+ * later than the given {@code Timestamp} object.
*
- * @param ts the <code>Timestamp</code> value to compare with
- * @return <code>true</code> if this <code>Timestamp</code> object is later;
- * <code>false</code> otherwise
+ * @param ts the {@code Timestamp} value to compare with
+ * @return {@code true} if this {@code Timestamp} object is later;
+ * {@code false} otherwise
*/
public boolean after(Timestamp ts) {
return compareTo(ts) > 0;
}
/**
- * Compares this <code>Timestamp</code> object to the given
- * <code>Timestamp</code> object.
+ * Compares this {@code Timestamp} object to the given
+ * {@code Timestamp} object.
*
- * @param ts the <code>Timestamp</code> object to be compared to
- * this <code>Timestamp</code> object
- * @return the value <code>0</code> if the two <code>Timestamp</code>
- * objects are equal; a value less than <code>0</code> if this
- * <code>Timestamp</code> object is before the given argument;
- * and a value greater than <code>0</code> if this
- * <code>Timestamp</code> object is after the given argument.
+ * @param ts the {@code Timestamp} object to be compared to
+ * this {@code Timestamp} object
+ * @return the value {@code 0} if the two {@code Timestamp}
+ * objects are equal; a value less than {@code 0} if this
+ * {@code Timestamp} object is before the given argument;
+ * and a value greater than {@code 0} if this
+ * {@code Timestamp} object is after the given argument.
* @since 1.4
*/
public int compareTo(Timestamp ts) {
@@ -439,16 +439,16 @@
}
/**
- * Compares this <code>Timestamp</code> object to the given
- * <code>Date</code> object.
+ * Compares this {@code Timestamp} object to the given
+ * {@code Date} object.
*
- * @param o the <code>Date</code> to be compared to
- * this <code>Timestamp</code> object
- * @return the value <code>0</code> if this <code>Timestamp</code> object
- * and the given object are equal; a value less than <code>0</code>
- * if this <code>Timestamp</code> object is before the given argument;
- * and a value greater than <code>0</code> if this
- * <code>Timestamp</code> object is after the given argument.
+ * @param o the {@code Date} to be compared to
+ * this {@code Timestamp} object
+ * @return the value {@code 0} if this {@code Timestamp} object
+ * and the given object are equal; a value less than {@code 0}
+ * if this {@code Timestamp} object is before the given argument;
+ * and a value greater than {@code 0} if this
+ * {@code Timestamp} object is after the given argument.
*
* @since 1.5
*/
--- a/jdk/src/jdk.attach/share/classes/com/sun/tools/attach/VirtualMachine.java Thu Aug 20 12:29:58 2015 -0700
+++ b/jdk/src/jdk.attach/share/classes/com/sun/tools/attach/VirtualMachine.java Wed Jul 05 20:46:25 2017 +0200
@@ -35,7 +35,7 @@
/**
* A Java virtual machine.
*
- * <p> A <code>VirtualMachine</code> represents a Java virtual machine to which this
+ * <p> A {@code VirtualMachine} represents a Java virtual machine to which this
* Java virtual machine has attached. The Java virtual machine to which it is
* attached is sometimes called the <i>target virtual machine</i>, or <i>target VM</i>.
* An application (typically a tool such as a managemet console or profiler) uses a
@@ -47,7 +47,7 @@
* with an identifier that identifies the target virtual machine. The identifier is
* implementation-dependent but is typically the process identifier (or pid) in
* environments where each Java virtual machine runs in its own operating system process.
- * Alternatively, a <code>VirtualMachine</code> instance is obtained by invoking the
+ * Alternatively, a {@code VirtualMachine} instance is obtained by invoking the
* {@link #attach(VirtualMachineDescriptor) attach} method with a {@link
* com.sun.tools.attach.VirtualMachineDescriptor VirtualMachineDescriptor} obtained
* from the list of virtual machine descriptors returned by the {@link #list list} method.
@@ -66,7 +66,7 @@
* <p> In addition to loading agents a VirtualMachine provides read access to the
* {@link java.lang.System#getProperties() system properties} in the target VM.
* This can be useful in some environments where properties such as
- * <code>java.home</code>, <code>os.name</code>, or <code>os.arch</code> are
+ * {@code java.home}, {@code os.name}, or {@code os.arch} are
* used to construct the path to agent that will be loaded into the target VM.
*
* <p> The following example demonstrates how VirtualMachine may be used:</p>
@@ -87,7 +87,7 @@
* </pre>
*
* <p> In this example we attach to a Java virtual machine that is identified by
- * the process identifier <code>2177</code>. Then the JMX management agent is
+ * the process identifier {@code 2177}. Then the JMX management agent is
* started in the target process using the supplied arguments. Finally, the
* client detaches from the target VM. </p>
*
@@ -111,7 +111,7 @@
* The abstract identifier that identifies the Java virtual machine.
*
* @throws NullPointerException
- * If <code>provider</code> or <code>id</code> is <code>null</code>.
+ * If {@code provider} or {@code id} is {@code null}.
*/
protected VirtualMachine(AttachProvider provider, String id) {
if (provider == null) {
@@ -160,10 +160,10 @@
* attachVirtualMachine} method in turn. If a provider successfully
* attaches then the iteration terminates, and the VirtualMachine created
* by the provider that successfully attached is returned by this method.
- * If the <code>attachVirtualMachine</code> method of all providers throws
+ * If the {@code attachVirtualMachine} method of all providers throws
* {@link com.sun.tools.attach.AttachNotSupportedException AttachNotSupportedException}
- * then this method also throws <code>AttachNotSupportedException</code>.
- * This means that <code>AttachNotSupportedException</code> is thrown when
+ * then this method also throws {@code AttachNotSupportedException}.
+ * This means that {@code AttachNotSupportedException} is thrown when
* the identifier provided to this method is invalid, or the identifier
* corresponds to a Java virtual machine that does not exist, or none
* of the providers can attach to it. This exception is also thrown if
@@ -178,19 +178,19 @@
* @throws SecurityException
* If a security manager has been installed and it denies
* {@link com.sun.tools.attach.AttachPermission AttachPermission}
- * <tt>("attachVirtualMachine")</tt>, or another permission
+ * {@code ("attachVirtualMachine")}, or another permission
* required by the implementation.
*
* @throws AttachNotSupportedException
- * If the <code>attachVirtualmachine</code> method of all installed
- * providers throws <code>AttachNotSupportedException</code>, or
+ * If the {@code attachVirtualmachine} method of all installed
+ * providers throws {@code AttachNotSupportedException}, or
* there aren't any providers installed.
*
* @throws IOException
* If an I/O error occurs
*
* @throws NullPointerException
- * If <code>id</code> is <code>null</code>.
+ * If {@code id} is {@code null}.
*/
public static VirtualMachine attach(String id)
throws AttachNotSupportedException, IOException
@@ -231,18 +231,18 @@
* @throws SecurityException
* If a security manager has been installed and it denies
* {@link com.sun.tools.attach.AttachPermission AttachPermission}
- * <tt>("attachVirtualMachine")</tt>, or another permission
+ * {@code ("attachVirtualMachine")}, or another permission
* required by the implementation.
*
* @throws AttachNotSupportedException
- * If the attach provider's <code>attachVirtualmachine</code>
- * throws <code>AttachNotSupportedException</code>.
+ * If the attach provider's {@code attachVirtualmachine}
+ * throws {@code AttachNotSupportedException}.
*
* @throws IOException
* If an I/O error occurs
*
* @throws NullPointerException
- * If <code>vmd</code> is <code>null</code>.
+ * If {@code vmd} is {@code null}.
*/
public static VirtualMachine attach(VirtualMachineDescriptor vmd)
throws AttachNotSupportedException, IOException
@@ -259,7 +259,7 @@
* loadAgent} for example) is in progress when this method is invoked then
* the behaviour is implementation dependent. In other words, it is
* implementation specific if the operation completes or throws
- * <tt>IOException</tt>.
+ * {@code IOException}.
*
* <p> If already detached from the virtual machine then invoking this
* method has no effect. </p>
@@ -296,26 +296,26 @@
* platform equivalent of a dynamic library. Alternatively, it may be statically linked into the VM.
* This method causes the given agent library to be loaded into the target
* VM (if not already loaded or if not statically linked into the VM).
- * It then causes the target VM to invoke the <code>Agent_OnAttach</code> function
- * or, for a statically linked agent named 'L', the <code>Agent_OnAttach_L</code> function
+ * It then causes the target VM to invoke the {@code Agent_OnAttach} function
+ * or, for a statically linked agent named 'L', the {@code Agent_OnAttach_L} function
* as specified in the
* <a href="../../../../../../../../technotes/guides/jvmti/index.html"> JVM Tools
- * Interface</a> specification. Note that the <code>Agent_OnAttach[_L]</code>
+ * Interface</a> specification. Note that the {@code Agent_OnAttach[_L]}
* function is invoked even if the agent library was loaded prior to invoking
* this method.
*
* <p> The agent library provided is the name of the agent library. It is interpreted
* in the target virtual machine in an implementation-dependent manner. Typically an
* implementation will expand the library name into an operating system specific file
- * name. For example, on UNIX systems, the name <tt>L</tt> might be expanded to
- * <tt>libL.so</tt>, and located using the search path specified by the
- * <tt>LD_LIBRARY_PATH</tt> environment variable. If the agent named 'L' is
+ * name. For example, on UNIX systems, the name {@code L} might be expanded to
+ * {@code libL.so}, and located using the search path specified by the
+ * {@code LD_LIBRARY_PATH} environment variable. If the agent named 'L' is
* statically linked into the VM then the VM must export a function named
- * <code>Agent_OnAttach_L</code>.</p>
+ * {@code Agent_OnAttach_L}.</p>
*
- * <p> If the <code>Agent_OnAttach[_L]</code> function in the agent library returns
+ * <p> If the {@code Agent_OnAttach[_L]} function in the agent library returns
* an error then an {@link com.sun.tools.attach.AgentInitializationException} is
- * thrown. The return value from the <code>Agent_OnAttach[_L]</code> can then be
+ * thrown. The return value from the {@code Agent_OnAttach[_L]} can then be
* obtained by invoking the {@link
* com.sun.tools.attach.AgentInitializationException#returnValue() returnValue}
* method on the exception. </p>
@@ -324,8 +324,8 @@
* The name of the agent library.
*
* @param options
- * The options to provide to the <code>Agent_OnAttach[_L]</code>
- * function (can be <code>null</code>).
+ * The options to provide to the {@code Agent_OnAttach[_L]}
+ * function (can be {@code null}).
*
* @throws AgentLoadException
* If the agent library does not exist, the agent library is not
@@ -333,13 +333,13 @@
* loaded for another reason.
*
* @throws AgentInitializationException
- * If the <code>Agent_OnAttach[_L]</code> function returns an error.
+ * If the {@code Agent_OnAttach[_L]} function returns an error.
*
* @throws IOException
* If an I/O error occurs
*
* @throws NullPointerException
- * If <code>agentLibrary</code> is <code>null</code>.
+ * If {@code agentLibrary} is {@code null}.
*
* @see com.sun.tools.attach.AgentInitializationException#returnValue()
*/
@@ -351,9 +351,9 @@
*
* <p> This convenience method works as if by invoking:
*
- * <blockquote><tt>
+ * <blockquote><code>
* {@link #loadAgentLibrary(String, String) loadAgentLibrary}(agentLibrary, null);
- * </tt></blockquote>
+ * </code></blockquote>
*
* @param agentLibrary
* The name of the agent library.
@@ -364,13 +364,13 @@
* loaded for another reason.
*
* @throws AgentInitializationException
- * If the <code>Agent_OnAttach[_L]</code> function returns an error.
+ * If the {@code Agent_OnAttach[_L]} function returns an error.
*
* @throws IOException
* If an I/O error occurs
*
* @throws NullPointerException
- * If <code>agentLibrary</code> is <code>null</code>.
+ * If {@code agentLibrary} is {@code null}.
*/
public void loadAgentLibrary(String agentLibrary)
throws AgentLoadException, AgentInitializationException, IOException
@@ -389,18 +389,18 @@
* linked with the VM. The parsing of the agentPath parameter into
* a statically linked library name is done in a platform
* specific manner in the VM. For example, in UNIX, an agentPath parameter
- * of <code>/a/b/libL.so</code> would name a library 'L'.
+ * of {@code /a/b/libL.so} would name a library 'L'.
*
* See the JVM TI Specification for more details.
*
* This method causes the given agent library to be loaded into the target
* VM (if not already loaded or if not statically linked into the VM).
- * It then causes the target VM to invoke the <code>Agent_OnAttach</code>
+ * It then causes the target VM to invoke the {@code Agent_OnAttach}
* function or, for a statically linked agent named 'L', the
- * <code>Agent_OnAttach_L</code> function as specified in the
+ * {@code Agent_OnAttach_L} function as specified in the
* <a href="../../../../../../../../technotes/guides/jvmti/index.html"> JVM Tools
* Interface</a> specification.
- * Note that the <code>Agent_OnAttach[_L]</code>
+ * Note that the {@code Agent_OnAttach[_L]}
* function is invoked even if the agent library was loaded prior to invoking
* this method.
*
@@ -408,9 +408,9 @@
* agent library. Unlike {@link #loadAgentLibrary loadAgentLibrary}, the library name
* is not expanded in the target virtual machine. </p>
*
- * <p> If the <code>Agent_OnAttach[_L]</code> function in the agent library returns
+ * <p> If the {@code Agent_OnAttach[_L]} function in the agent library returns
* an error then an {@link com.sun.tools.attach.AgentInitializationException} is
- * thrown. The return value from the <code>Agent_OnAttach[_L]</code> can then be
+ * thrown. The return value from the {@code Agent_OnAttach[_L]} can then be
* obtained by invoking the {@link
* com.sun.tools.attach.AgentInitializationException#returnValue() returnValue}
* method on the exception. </p>
@@ -419,8 +419,8 @@
* The full path of the agent library.
*
* @param options
- * The options to provide to the <code>Agent_OnAttach[_L]</code>
- * function (can be <code>null</code>).
+ * The options to provide to the {@code Agent_OnAttach[_L]}
+ * function (can be {@code null}).
*
* @throws AgentLoadException
* If the agent library does not exist, the agent library is not
@@ -428,13 +428,13 @@
* loaded for another reason.
*
* @throws AgentInitializationException
- * If the <code>Agent_OnAttach[_L]</code> function returns an error.
+ * If the {@code Agent_OnAttach[_L]} function returns an error.
*
* @throws IOException
* If an I/O error occurs
*
* @throws NullPointerException
- * If <code>agentPath</code> is <code>null</code>.
+ * If {@code agentPath} is {@code null}.
*
* @see com.sun.tools.attach.AgentInitializationException#returnValue()
*/
@@ -446,9 +446,9 @@
*
* <p> This convenience method works as if by invoking:
*
- * <blockquote><tt>
+ * <blockquote><code>
* {@link #loadAgentPath(String, String) loadAgentPath}(agentLibrary, null);
- * </tt></blockquote>
+ * </code></blockquote>
*
* @param agentPath
* The full path to the agent library.
@@ -459,13 +459,13 @@
* loaded for another reason.
*
* @throws AgentInitializationException
- * If the <code>Agent_OnAttach[_L]</code> function returns an error.
+ * If the {@code Agent_OnAttach[_L]} function returns an error.
*
* @throws IOException
* If an I/O error occurs
*
* @throws NullPointerException
- * If <code>agentPath</code> is <code>null</code>.
+ * If {@code agentPath} is {@code null}.
*/
public void loadAgentPath(String agentPath)
throws AgentLoadException, AgentInitializationException, IOException
@@ -482,29 +482,29 @@
* machine where it is interpreted. The target virtual machine attempts to start
* the agent as specified by the {@link java.lang.instrument} specification.
* That is, the specified JAR file is added to the system class path (of the target
- * virtual machine), and the <code>agentmain</code> method of the agent class, specified
- * by the <code>Agent-Class</code> attribute in the JAR manifest, is invoked. This
- * method completes when the <code>agentmain</code> method completes.
+ * virtual machine), and the {@code agentmain} method of the agent class, specified
+ * by the {@code Agent-Class} attribute in the JAR manifest, is invoked. This
+ * method completes when the {@code agentmain} method completes.
*
* @param agent
* Path to the JAR file containing the agent.
*
* @param options
- * The options to provide to the agent's <code>agentmain</code>
- * method (can be <code>null</code>).
+ * The options to provide to the agent's {@code agentmain}
+ * method (can be {@code null}).
*
* @throws AgentLoadException
* If the agent does not exist, or cannot be started in the manner
* specified in the {@link java.lang.instrument} specification.
*
* @throws AgentInitializationException
- * If the <code>agentmain</code> throws an exception
+ * If the {@code agentmain} throws an exception
*
* @throws IOException
* If an I/O error occurs
*
* @throws NullPointerException
- * If <code>agent</code> is <code>null</code>.
+ * If {@code agent} is {@code null}.
*/
public abstract void loadAgent(String agent, String options)
throws AgentLoadException, AgentInitializationException, IOException;
@@ -514,9 +514,9 @@
*
* <p> This convenience method works as if by invoking:
*
- * <blockquote><tt>
+ * <blockquote><code>
* {@link #loadAgent(String, String) loadAgent}(agent, null);
- * </tt></blockquote>
+ * </code></blockquote>
*
* @param agent
* Path to the JAR file containing the agent.
@@ -526,13 +526,13 @@
* specified in the {@link java.lang.instrument} specification.
*
* @throws AgentInitializationException
- * If the <code>agentmain</code> throws an exception
+ * If the {@code agentmain} throws an exception
*
* @throws IOException
* If an I/O error occurs
*
* @throws NullPointerException
- * If <code>agent</code> is <code>null</code>.
+ * If {@code agent} is {@code null}.
*/
public void loadAgent(String agent)
throws AgentLoadException, AgentInitializationException, IOException
@@ -544,16 +544,16 @@
* Returns the current system properties in the target virtual machine.
*
* <p> This method returns the system properties in the target virtual
- * machine. Properties whose key or value is not a <tt>String</tt> are
+ * machine. Properties whose key or value is not a {@code String} are
* omitted. The method is approximately equivalent to the invocation of the
* method {@link java.lang.System#getProperties System.getProperties}
* in the target virtual machine except that properties with a key or
- * value that is not a <tt>String</tt> are not included.
+ * value that is not a {@code String} are not included.
*
* <p> This method is typically used to decide which agent to load into
* the target virtual machine with {@link #loadAgent loadAgent}, or
* {@link #loadAgentLibrary loadAgentLibrary}. For example, the
- * <code>java.home</code> or <code>user.dir</code> properties might be
+ * {@code java.home} or {@code user.dir} properties might be
* use to create the path to the agent library or JAR file.
*
* @return The system properties
@@ -586,7 +586,7 @@
* agent might create an agent property for its transport address.
*
* <p> This method returns the agent properties whose key and value is a
- * <tt>String</tt>. Properties whose key or value is not a <tt>String</tt>
+ * {@code String}. Properties whose key or value is not a {@code String}
* are omitted. If there are no agent properties maintained in the target
* virtual machine then an empty property list is returned.
*
@@ -686,7 +686,7 @@
* Tests this VirtualMachine for equality with another object.
*
* <p> If the given object is not a VirtualMachine then this
- * method returns <tt>false</tt>. For two VirtualMachines to
+ * method returns {@code false}. For two VirtualMachines to
* be considered equal requires that they both reference the same
* provider, and their {@link VirtualMachineDescriptor#id() identifiers} are equal. </p>
*
@@ -695,7 +695,7 @@
*
* @param ob The object to which this object is to be compared
*
- * @return <tt>true</tt> if, and only if, the given object is
+ * @return {@code true} if, and only if, the given object is
* a VirtualMachine that is equal to this
* VirtualMachine.
*/
@@ -715,7 +715,7 @@
}
/**
- * Returns the string representation of the <code>VirtualMachine</code>.
+ * Returns the string representation of the {@code VirtualMachine}.
*/
public String toString() {
return provider.toString() + ": " + id;
--- a/jdk/src/jdk.attach/share/classes/com/sun/tools/attach/VirtualMachineDescriptor.java Thu Aug 20 12:29:58 2015 -0700
+++ b/jdk/src/jdk.attach/share/classes/com/sun/tools/attach/VirtualMachineDescriptor.java Wed Jul 05 20:46:25 2017 +0200
@@ -30,7 +30,7 @@
/**
* Describes a Java virtual machine.
*
- * <p> A <code>VirtualMachineDescriptor</code> is a container class used to
+ * <p> A {@code VirtualMachineDescriptor} is a container class used to
* describe a Java virtual machine. It encapsulates an identifier that identifies
* a target virtual machine, and a reference to the {@link
* com.sun.tools.attach.spi.AttachProvider AttachProvider} that should be used
@@ -39,15 +39,15 @@
* environments where each Java virtual machine runs in its own operating system
* process. </p>
*
- * <p> A <code>VirtualMachineDescriptor</code> also has a {@link #displayName() displayName}.
+ * <p> A {@code VirtualMachineDescriptor} also has a {@link #displayName() displayName}.
* The display name is typically a human readable string that a tool might
* display to a user. For example, a tool that shows a list of Java
* virtual machines running on a system might use the display name rather
- * than the identifier. A <code>VirtualMachineDescriptor</code> may be
+ * than the identifier. A {@code VirtualMachineDescriptor} may be
* created without a <i>display name</i>. In that case the identifier is
* used as the <i>display name</i>.
*
- * <p> <code>VirtualMachineDescriptor</code> instances are typically created by
+ * <p> {@code VirtualMachineDescriptor} instances are typically created by
* invoking the {@link com.sun.tools.attach.VirtualMachine#list VirtualMachine.list()}
* method. This returns the complete list of descriptors to describe the
* Java virtual machines known to all installed {@link
@@ -72,7 +72,7 @@
* @param displayName The display name.
*
* @throws NullPointerException
- * If any of the arguments are <code>null</code>
+ * If any of the arguments are {@code null}
*/
public VirtualMachineDescriptor(AttachProvider provider, String id, String displayName) {
if (provider == null) {
@@ -95,10 +95,10 @@
* <p> This convenience constructor works as if by invoking the
* three-argument constructor as follows:
*
- * <blockquote><tt>
+ * <blockquote><code>
* new {@link #VirtualMachineDescriptor(AttachProvider, String, String)
* VirtualMachineDescriptor}(provider, id, id);
- * </tt></blockquote>
+ * </code></blockquote>
*
* <p> That is, it creates a virtual machine descriptor such that
* the <i>display name</i> is the same as the virtual machine
@@ -108,16 +108,16 @@
* @param id The virtual machine identifier.
*
* @throws NullPointerException
- * If <tt>provider</tt> or <tt>id</tt> is <tt>null</tt>.
+ * If {@code provider} or {@code id} is {@code null}.
*/
public VirtualMachineDescriptor(AttachProvider provider, String id) {
this(provider, id, id);
}
/**
- * Return the <code>AttachProvider</code> that this descriptor references.
+ * Return the {@code AttachProvider} that this descriptor references.
*
- * @return The <code>AttachProvider</code> that this descriptor references.
+ * @return The {@code AttachProvider} that this descriptor references.
*/
public AttachProvider provider() {
return provider;
@@ -161,7 +161,7 @@
* Tests this VirtualMachineDescriptor for equality with another object.
*
* <p> If the given object is not a VirtualMachineDescriptor then this
- * method returns <tt>false</tt>. For two VirtualMachineDescriptors to
+ * method returns {@code false}. For two VirtualMachineDescriptors to
* be considered equal requires that they both reference the same
* provider, and their {@link #id() identifiers} are equal. </p>
*
@@ -170,7 +170,7 @@
*
* @param ob The object to which this object is to be compared
*
- * @return <tt>true</tt> if, and only if, the given object is
+ * @return {@code true} if, and only if, the given object is
* a VirtualMachineDescriptor that is equal to this
* VirtualMachineDescriptor.
*/
@@ -190,7 +190,7 @@
}
/**
- * Returns the string representation of the <code>VirtualMachineDescriptor</code>.
+ * Returns the string representation of the {@code VirtualMachineDescriptor}.
*/
public String toString() {
String s = provider.toString() + ": " + id;
--- a/jdk/src/jdk.deploy.osx/macosx/classes/apple/security/AppleProvider.java Thu Aug 20 12:29:58 2015 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,88 +0,0 @@
-/*
- * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package apple.security;
-
-import java.security.*;
-
-/**
- * The Apple Security Provider.
- */
-
-/**
- * Defines the Apple provider.
- *
- * This provider only exists to provide access to the Apple keychain-based KeyStore implementation
- */
-@SuppressWarnings("serial") // JDK implementation class
-public final class AppleProvider extends Provider {
-
- private static final String info = "Apple Provider";
-
- private static final class ProviderService extends Provider.Service {
- ProviderService(Provider p, String type, String algo, String cn) {
- super(p, type, algo, cn, null, null);
- }
-
- @Override
- public Object newInstance(Object ctrParamObj)
- throws NoSuchAlgorithmException {
- String type = getType();
- if (ctrParamObj != null) {
- throw new InvalidParameterException
- ("constructorParameter not used with " + type + " engines");
- }
-
- String algo = getAlgorithm();
- try {
- if (type.equals("KeyStore")) {
- if (algo.equals("KeychainStore")) {
- return new KeychainStore();
- }
- }
- } catch (Exception ex) {
- throw new NoSuchAlgorithmException("Error constructing " +
- type + " for " + algo + " using Apple", ex);
- }
- throw new ProviderException("No impl for " + algo +
- " " + type);
- }
- }
-
-
- public AppleProvider() {
- /* We are the Apple provider */
- super("Apple", 1.9d, info);
-
- final Provider p = this;
- AccessController.doPrivileged(new PrivilegedAction<Void>() {
- public Void run() {
- putService(new ProviderService(p, "KeyStore",
- "KeychainStore", "apple.security.KeychainStore"));
- return null;
- }
- });
- }
-}
--- a/jdk/src/jdk.deploy.osx/macosx/classes/apple/security/KeychainStore.java Thu Aug 20 12:29:58 2015 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,1149 +0,0 @@
-/*
- * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package apple.security;
-
-import java.io.*;
-import java.security.*;
-import java.security.cert.*;
-import java.security.cert.Certificate;
-import java.security.spec.*;
-import java.util.*;
-
-import javax.crypto.*;
-import javax.crypto.spec.*;
-import javax.security.auth.x500.*;
-
-import sun.security.pkcs.*;
-import sun.security.pkcs.EncryptedPrivateKeyInfo;
-import sun.security.util.*;
-import sun.security.x509.*;
-
-/**
- * This class provides the keystore implementation referred to as "KeychainStore".
- * It uses the current user's keychain as its backing storage, and does NOT support
- * a file-based implementation.
- */
-
-public final class KeychainStore extends KeyStoreSpi {
-
- // Private keys and their supporting certificate chains
- // If a key came from the keychain it has a SecKeyRef and one or more
- // SecCertificateRef. When we delete the key we have to delete all of the corresponding
- // native objects.
- class KeyEntry {
- Date date; // the creation date of this entry
- byte[] protectedPrivKey;
- char[] password;
- long keyRef; // SecKeyRef for this key
- Certificate chain[];
- long chainRefs[]; // SecCertificateRefs for this key's chain.
- };
-
- // Trusted certificates
- class TrustedCertEntry {
- Date date; // the creation date of this entry
-
- Certificate cert;
- long certRef; // SecCertificateRef for this key
- };
-
- /**
- * Entries that have been deleted. When something calls engineStore we'll
- * remove them from the keychain.
- */
- private Hashtable<String, Object> deletedEntries = new Hashtable<>();
-
- /**
- * Entries that have been added. When something calls engineStore we'll
- * add them to the keychain.
- */
- private Hashtable<String, Object> addedEntries = new Hashtable<>();
-
- /**
- * Private keys and certificates are stored in a hashtable.
- * Hash entries are keyed by alias names.
- */
- private Hashtable<String, Object> entries = new Hashtable<>();
-
- /**
- * Algorithm identifiers and corresponding OIDs for the contents of the PKCS12 bag we get from the Keychain.
- */
- private static final int keyBag[] = {1, 2, 840, 113549, 1, 12, 10, 1, 2};
- private static final int pbeWithSHAAnd3KeyTripleDESCBC[] = {1, 2, 840, 113549, 1, 12, 1, 3};
- private static ObjectIdentifier PKCS8ShroudedKeyBag_OID;
- private static ObjectIdentifier pbeWithSHAAnd3KeyTripleDESCBC_OID;
-
- /**
- * Constnats used in PBE decryption.
- */
- private static final int iterationCount = 1024;
- private static final int SALT_LEN = 20;
-
- static {
- AccessController.doPrivileged(
- new PrivilegedAction<Void>() {
- public Void run() {
- System.loadLibrary("osx");
- return null;
- }
- });
- try {
- PKCS8ShroudedKeyBag_OID = new ObjectIdentifier(keyBag);
- pbeWithSHAAnd3KeyTripleDESCBC_OID = new ObjectIdentifier(pbeWithSHAAnd3KeyTripleDESCBC);
- } catch (IOException ioe) {
- // should not happen
- }
- }
-
- private static void permissionCheck() {
- SecurityManager sec = System.getSecurityManager();
-
- if (sec != null) {
- sec.checkPermission(new RuntimePermission("useKeychainStore"));
- }
- }
-
-
- /**
- * Verify the Apple provider in the constructor.
- *
- * @exception SecurityException if fails to verify
- * its own integrity
- */
- public KeychainStore() { }
-
- /**
- * Returns the key associated with the given alias, using the given
- * password to recover it.
- *
- * @param alias the alias name
- * @param password the password for recovering the key. This password is
- * used internally as the key is exported in a PKCS12 format.
- *
- * @return the requested key, or null if the given alias does not exist
- * or does not identify a <i>key entry</i>.
- *
- * @exception NoSuchAlgorithmException if the algorithm for recovering the
- * key cannot be found
- * @exception UnrecoverableKeyException if the key cannot be recovered
- * (e.g., the given password is wrong).
- */
- public Key engineGetKey(String alias, char[] password)
- throws NoSuchAlgorithmException, UnrecoverableKeyException
- {
- permissionCheck();
-
- // An empty password is rejected by MacOS API, no private key data
- // is exported. If no password is passed (as is the case when
- // this implementation is used as browser keystore in various
- // deployment scenarios like Webstart, JFX and applets), create
- // a dummy password so MacOS API is happy.
- if (password == null || password.length == 0) {
- // Must not be a char array with only a 0, as this is an empty
- // string.
- if (random == null) {
- random = new SecureRandom();
- }
- password = Long.toString(random.nextLong()).toCharArray();
- }
-
- Object entry = entries.get(alias.toLowerCase());
-
- if (entry == null || !(entry instanceof KeyEntry)) {
- return null;
- }
-
- // This call gives us a PKCS12 bag, with the key inside it.
- byte[] exportedKeyInfo = _getEncodedKeyData(((KeyEntry)entry).keyRef, password);
- if (exportedKeyInfo == null) {
- return null;
- }
-
- PrivateKey returnValue = null;
-
- try {
- byte[] pkcs8KeyData = fetchPrivateKeyFromBag(exportedKeyInfo);
- byte[] encryptedKey;
- AlgorithmParameters algParams;
- ObjectIdentifier algOid;
- try {
- // get the encrypted private key
- EncryptedPrivateKeyInfo encrInfo = new EncryptedPrivateKeyInfo(pkcs8KeyData);
- encryptedKey = encrInfo.getEncryptedData();
-
- // parse Algorithm parameters
- DerValue val = new DerValue(encrInfo.getAlgorithm().encode());
- DerInputStream in = val.toDerInputStream();
- algOid = in.getOID();
- algParams = parseAlgParameters(in);
-
- } catch (IOException ioe) {
- UnrecoverableKeyException uke =
- new UnrecoverableKeyException("Private key not stored as "
- + "PKCS#8 EncryptedPrivateKeyInfo: " + ioe);
- uke.initCause(ioe);
- throw uke;
- }
-
- // Use JCE to decrypt the data using the supplied password.
- SecretKey skey = getPBEKey(password);
- Cipher cipher = Cipher.getInstance(algOid.toString());
- cipher.init(Cipher.DECRYPT_MODE, skey, algParams);
- byte[] decryptedPrivateKey = cipher.doFinal(encryptedKey);
- PKCS8EncodedKeySpec kspec = new PKCS8EncodedKeySpec(decryptedPrivateKey);
-
- // Parse the key algorithm and then use a JCA key factory to create the private key.
- DerValue val = new DerValue(decryptedPrivateKey);
- DerInputStream in = val.toDerInputStream();
-
- // Ignore this -- version should be 0.
- int i = in.getInteger();
-
- // Get the Algorithm ID next
- DerValue[] value = in.getSequence(2);
- AlgorithmId algId = new AlgorithmId(value[0].getOID());
- String algName = algId.getName();
-
- // Get a key factory for this algorithm. It's likely to be 'RSA'.
- KeyFactory kfac = KeyFactory.getInstance(algName);
- returnValue = kfac.generatePrivate(kspec);
- } catch (Exception e) {
- UnrecoverableKeyException uke =
- new UnrecoverableKeyException("Get Key failed: " +
- e.getMessage());
- uke.initCause(e);
- throw uke;
- }
-
- return returnValue;
- }
-
- private native byte[] _getEncodedKeyData(long secKeyRef, char[] password);
-
- /**
- * Returns the certificate chain associated with the given alias.
- *
- * @param alias the alias name
- *
- * @return the certificate chain (ordered with the user's certificate first
- * and the root certificate authority last), or null if the given alias
- * does not exist or does not contain a certificate chain (i.e., the given
- * alias identifies either a <i>trusted certificate entry</i> or a
- * <i>key entry</i> without a certificate chain).
- */
- public Certificate[] engineGetCertificateChain(String alias) {
- permissionCheck();
-
- Object entry = entries.get(alias.toLowerCase());
-
- if (entry != null && entry instanceof KeyEntry) {
- if (((KeyEntry)entry).chain == null) {
- return null;
- } else {
- return ((KeyEntry)entry).chain.clone();
- }
- } else {
- return null;
- }
- }
-
- /**
- * Returns the certificate associated with the given alias.
- *
- * <p>If the given alias name identifies a
- * <i>trusted certificate entry</i>, the certificate associated with that
- * entry is returned. If the given alias name identifies a
- * <i>key entry</i>, the first element of the certificate chain of that
- * entry is returned, or null if that entry does not have a certificate
- * chain.
- *
- * @param alias the alias name
- *
- * @return the certificate, or null if the given alias does not exist or
- * does not contain a certificate.
- */
- public Certificate engineGetCertificate(String alias) {
- permissionCheck();
-
- Object entry = entries.get(alias.toLowerCase());
-
- if (entry != null) {
- if (entry instanceof TrustedCertEntry) {
- return ((TrustedCertEntry)entry).cert;
- } else {
- KeyEntry ke = (KeyEntry)entry;
- if (ke.chain == null || ke.chain.length == 0) {
- return null;
- }
- return ke.chain[0];
- }
- } else {
- return null;
- }
- }
-
- /**
- * Returns the creation date of the entry identified by the given alias.
- *
- * @param alias the alias name
- *
- * @return the creation date of this entry, or null if the given alias does
- * not exist
- */
- public Date engineGetCreationDate(String alias) {
- permissionCheck();
-
- Object entry = entries.get(alias.toLowerCase());
-
- if (entry != null) {
- if (entry instanceof TrustedCertEntry) {
- return new Date(((TrustedCertEntry)entry).date.getTime());
- } else {
- return new Date(((KeyEntry)entry).date.getTime());
- }
- } else {
- return null;
- }
- }
-
- /**
- * Assigns the given key to the given alias, protecting it with the given
- * password.
- *
- * <p>If the given key is of type <code>java.security.PrivateKey</code>,
- * it must be accompanied by a certificate chain certifying the
- * corresponding public key.
- *
- * <p>If the given alias already exists, the keystore information
- * associated with it is overridden by the given key (and possibly
- * certificate chain).
- *
- * @param alias the alias name
- * @param key the key to be associated with the alias
- * @param password the password to protect the key
- * @param chain the certificate chain for the corresponding public
- * key (only required if the given key is of type
- * <code>java.security.PrivateKey</code>).
- *
- * @exception KeyStoreException if the given key cannot be protected, or
- * this operation fails for some other reason
- */
- public void engineSetKeyEntry(String alias, Key key, char[] password,
- Certificate[] chain)
- throws KeyStoreException
- {
- permissionCheck();
-
- synchronized(entries) {
- try {
- KeyEntry entry = new KeyEntry();
- entry.date = new Date();
-
- if (key instanceof PrivateKey) {
- if ((key.getFormat().equals("PKCS#8")) ||
- (key.getFormat().equals("PKCS8"))) {
- entry.protectedPrivKey = encryptPrivateKey(key.getEncoded(), password);
- entry.password = password.clone();
- } else {
- throw new KeyStoreException("Private key is not encoded as PKCS#8");
- }
- } else {
- throw new KeyStoreException("Key is not a PrivateKey");
- }
-
- // clone the chain
- if (chain != null) {
- if ((chain.length > 1) && !validateChain(chain)) {
- throw new KeyStoreException("Certificate chain does not validate");
- }
-
- entry.chain = chain.clone();
- entry.chainRefs = new long[entry.chain.length];
- }
-
- String lowerAlias = alias.toLowerCase();
- if (entries.get(lowerAlias) != null) {
- deletedEntries.put(lowerAlias, entries.get(lowerAlias));
- }
-
- entries.put(lowerAlias, entry);
- addedEntries.put(lowerAlias, entry);
- } catch (Exception nsae) {
- KeyStoreException ke = new KeyStoreException("Key protection algorithm not found: " + nsae);
- ke.initCause(nsae);
- throw ke;
- }
- }
- }
-
- /**
- * Assigns the given key (that has already been protected) to the given
- * alias.
- *
- * <p>If the protected key is of type
- * <code>java.security.PrivateKey</code>, it must be accompanied by a
- * certificate chain certifying the corresponding public key. If the
- * underlying keystore implementation is of type <code>jks</code>,
- * <code>key</code> must be encoded as an
- * <code>EncryptedPrivateKeyInfo</code> as defined in the PKCS #8 standard.
- *
- * <p>If the given alias already exists, the keystore information
- * associated with it is overridden by the given key (and possibly
- * certificate chain).
- *
- * @param alias the alias name
- * @param key the key (in protected format) to be associated with the alias
- * @param chain the certificate chain for the corresponding public
- * key (only useful if the protected key is of type
- * <code>java.security.PrivateKey</code>).
- *
- * @exception KeyStoreException if this operation fails.
- */
- public void engineSetKeyEntry(String alias, byte[] key,
- Certificate[] chain)
- throws KeyStoreException
- {
- permissionCheck();
-
- synchronized(entries) {
- // key must be encoded as EncryptedPrivateKeyInfo as defined in
- // PKCS#8
- KeyEntry entry = new KeyEntry();
- try {
- EncryptedPrivateKeyInfo privateKey = new EncryptedPrivateKeyInfo(key);
- entry.protectedPrivKey = privateKey.getEncoded();
- } catch (IOException ioe) {
- throw new KeyStoreException("key is not encoded as "
- + "EncryptedPrivateKeyInfo");
- }
-
- entry.date = new Date();
-
- if ((chain != null) &&
- (chain.length != 0)) {
- entry.chain = chain.clone();
- entry.chainRefs = new long[entry.chain.length];
- }
-
- String lowerAlias = alias.toLowerCase();
- if (entries.get(lowerAlias) != null) {
- deletedEntries.put(lowerAlias, entries.get(alias));
- }
- entries.put(lowerAlias, entry);
- addedEntries.put(lowerAlias, entry);
- }
- }
-
- /**
- * Assigns the given certificate to the given alias.
- *
- * <p>If the given alias already exists in this keystore and identifies a
- * <i>trusted certificate entry</i>, the certificate associated with it is
- * overridden by the given certificate.
- *
- * @param alias the alias name
- * @param cert the certificate
- *
- * @exception KeyStoreException if the given alias already exists and does
- * not identify a <i>trusted certificate entry</i>, or this operation
- * fails for some other reason.
- */
- public void engineSetCertificateEntry(String alias, Certificate cert)
- throws KeyStoreException
- {
- permissionCheck();
-
- synchronized(entries) {
-
- Object entry = entries.get(alias.toLowerCase());
- if ((entry != null) && (entry instanceof KeyEntry)) {
- throw new KeyStoreException
- ("Cannot overwrite key entry with certificate");
- }
-
- // This will be slow, but necessary. Enumerate the values and then see if the cert matches the one in the trusted cert entry.
- // Security framework doesn't support the same certificate twice in a keychain.
- Collection<Object> allValues = entries.values();
-
- for (Object value : allValues) {
- if (value instanceof TrustedCertEntry) {
- TrustedCertEntry tce = (TrustedCertEntry)value;
- if (tce.cert.equals(cert)) {
- throw new KeyStoreException("Keychain does not support mulitple copies of same certificate.");
- }
- }
- }
-
- TrustedCertEntry trustedCertEntry = new TrustedCertEntry();
- trustedCertEntry.cert = cert;
- trustedCertEntry.date = new Date();
- String lowerAlias = alias.toLowerCase();
- if (entries.get(lowerAlias) != null) {
- deletedEntries.put(lowerAlias, entries.get(lowerAlias));
- }
- entries.put(lowerAlias, trustedCertEntry);
- addedEntries.put(lowerAlias, trustedCertEntry);
- }
- }
-
- /**
- * Deletes the entry identified by the given alias from this keystore.
- *
- * @param alias the alias name
- *
- * @exception KeyStoreException if the entry cannot be removed.
- */
- public void engineDeleteEntry(String alias)
- throws KeyStoreException
- {
- permissionCheck();
-
- synchronized(entries) {
- Object entry = entries.remove(alias.toLowerCase());
- deletedEntries.put(alias.toLowerCase(), entry);
- }
- }
-
- /**
- * Lists all the alias names of this keystore.
- *
- * @return enumeration of the alias names
- */
- public Enumeration<String> engineAliases() {
- permissionCheck();
- return entries.keys();
- }
-
- /**
- * Checks if the given alias exists in this keystore.
- *
- * @param alias the alias name
- *
- * @return true if the alias exists, false otherwise
- */
- public boolean engineContainsAlias(String alias) {
- permissionCheck();
- return entries.containsKey(alias.toLowerCase());
- }
-
- /**
- * Retrieves the number of entries in this keystore.
- *
- * @return the number of entries in this keystore
- */
- public int engineSize() {
- permissionCheck();
- return entries.size();
- }
-
- /**
- * Returns true if the entry identified by the given alias is a
- * <i>key entry</i>, and false otherwise.
- *
- * @return true if the entry identified by the given alias is a
- * <i>key entry</i>, false otherwise.
- */
- public boolean engineIsKeyEntry(String alias) {
- permissionCheck();
- Object entry = entries.get(alias.toLowerCase());
- if ((entry != null) && (entry instanceof KeyEntry)) {
- return true;
- } else {
- return false;
- }
- }
-
- /**
- * Returns true if the entry identified by the given alias is a
- * <i>trusted certificate entry</i>, and false otherwise.
- *
- * @return true if the entry identified by the given alias is a
- * <i>trusted certificate entry</i>, false otherwise.
- */
- public boolean engineIsCertificateEntry(String alias) {
- permissionCheck();
- Object entry = entries.get(alias.toLowerCase());
- if ((entry != null) && (entry instanceof TrustedCertEntry)) {
- return true;
- } else {
- return false;
- }
- }
-
- /**
- * Returns the (alias) name of the first keystore entry whose certificate
- * matches the given certificate.
- *
- * <p>This method attempts to match the given certificate with each
- * keystore entry. If the entry being considered
- * is a <i>trusted certificate entry</i>, the given certificate is
- * compared to that entry's certificate. If the entry being considered is
- * a <i>key entry</i>, the given certificate is compared to the first
- * element of that entry's certificate chain (if a chain exists).
- *
- * @param cert the certificate to match with.
- *
- * @return the (alias) name of the first entry with matching certificate,
- * or null if no such entry exists in this keystore.
- */
- public String engineGetCertificateAlias(Certificate cert) {
- permissionCheck();
- Certificate certElem;
-
- for (Enumeration<String> e = entries.keys(); e.hasMoreElements(); ) {
- String alias = e.nextElement();
- Object entry = entries.get(alias);
- if (entry instanceof TrustedCertEntry) {
- certElem = ((TrustedCertEntry)entry).cert;
- } else {
- KeyEntry ke = (KeyEntry)entry;
- if (ke.chain == null || ke.chain.length == 0) {
- continue;
- }
- certElem = ke.chain[0];
- }
- if (certElem.equals(cert)) {
- return alias;
- }
- }
- return null;
- }
-
- /**
- * Stores this keystore to the given output stream, and protects its
- * integrity with the given password.
- *
- * @param stream Ignored. the output stream to which this keystore is written.
- * @param password the password to generate the keystore integrity check
- *
- * @exception IOException if there was an I/O problem with data
- * @exception NoSuchAlgorithmException if the appropriate data integrity
- * algorithm could not be found
- * @exception CertificateException if any of the certificates included in
- * the keystore data could not be stored
- */
- public void engineStore(OutputStream stream, char[] password)
- throws IOException, NoSuchAlgorithmException, CertificateException
- {
- permissionCheck();
-
- // Delete items that do have a keychain item ref.
- for (Enumeration<String> e = deletedEntries.keys(); e.hasMoreElements(); ) {
- String alias = e.nextElement();
- Object entry = deletedEntries.get(alias);
- if (entry instanceof TrustedCertEntry) {
- if (((TrustedCertEntry)entry).certRef != 0) {
- _removeItemFromKeychain(((TrustedCertEntry)entry).certRef);
- _releaseKeychainItemRef(((TrustedCertEntry)entry).certRef);
- }
- } else {
- Certificate certElem;
- KeyEntry keyEntry = (KeyEntry)entry;
-
- if (keyEntry.chain != null) {
- for (int i = 0; i < keyEntry.chain.length; i++) {
- if (keyEntry.chainRefs[i] != 0) {
- _removeItemFromKeychain(keyEntry.chainRefs[i]);
- _releaseKeychainItemRef(keyEntry.chainRefs[i]);
- }
- }
-
- if (keyEntry.keyRef != 0) {
- _removeItemFromKeychain(keyEntry.keyRef);
- _releaseKeychainItemRef(keyEntry.keyRef);
- }
- }
- }
- }
-
- // Add all of the certs or keys in the added entries.
- // No need to check for 0 refs, as they are in the added list.
- for (Enumeration<String> e = addedEntries.keys(); e.hasMoreElements(); ) {
- String alias = e.nextElement();
- Object entry = addedEntries.get(alias);
- if (entry instanceof TrustedCertEntry) {
- TrustedCertEntry tce = (TrustedCertEntry)entry;
- Certificate certElem;
- certElem = tce.cert;
- tce.certRef = addCertificateToKeychain(alias, certElem);
- } else {
- KeyEntry keyEntry = (KeyEntry)entry;
-
- if (keyEntry.chain != null) {
- for (int i = 0; i < keyEntry.chain.length; i++) {
- keyEntry.chainRefs[i] = addCertificateToKeychain(alias, keyEntry.chain[i]);
- }
-
- keyEntry.keyRef = _addItemToKeychain(alias, false, keyEntry.protectedPrivKey, keyEntry.password);
- }
- }
- }
-
- // Clear the added and deletedEntries hashtables here, now that we're done with the updates.
- // For the deleted entries, we freed up the native references above.
- deletedEntries.clear();
- addedEntries.clear();
- }
-
- private long addCertificateToKeychain(String alias, Certificate cert) {
- byte[] certblob = null;
- long returnValue = 0;
-
- try {
- certblob = cert.getEncoded();
- returnValue = _addItemToKeychain(alias, true, certblob, null);
- } catch (Exception e) {
- e.printStackTrace();
- }
-
- return returnValue;
- }
-
- private native long _addItemToKeychain(String alias, boolean isCertificate, byte[] datablob, char[] password);
- private native int _removeItemFromKeychain(long certRef);
- private native void _releaseKeychainItemRef(long keychainItemRef);
-
- /**
- * Loads the keystore from the Keychain.
- *
- * @param stream Ignored - here for API compatibility.
- * @param password Ignored - if user needs to unlock keychain Security
- * framework will post any dialogs.
- *
- * @exception IOException if there is an I/O or format problem with the
- * keystore data
- * @exception NoSuchAlgorithmException if the algorithm used to check
- * the integrity of the keystore cannot be found
- * @exception CertificateException if any of the certificates in the
- * keystore could not be loaded
- */
- public void engineLoad(InputStream stream, char[] password)
- throws IOException, NoSuchAlgorithmException, CertificateException
- {
- permissionCheck();
-
- // Release any stray keychain references before clearing out the entries.
- synchronized(entries) {
- for (Enumeration<String> e = entries.keys(); e.hasMoreElements(); ) {
- String alias = e.nextElement();
- Object entry = entries.get(alias);
- if (entry instanceof TrustedCertEntry) {
- if (((TrustedCertEntry)entry).certRef != 0) {
- _releaseKeychainItemRef(((TrustedCertEntry)entry).certRef);
- }
- } else {
- KeyEntry keyEntry = (KeyEntry)entry;
-
- if (keyEntry.chain != null) {
- for (int i = 0; i < keyEntry.chain.length; i++) {
- if (keyEntry.chainRefs[i] != 0) {
- _releaseKeychainItemRef(keyEntry.chainRefs[i]);
- }
- }
-
- if (keyEntry.keyRef != 0) {
- _releaseKeychainItemRef(keyEntry.keyRef);
- }
- }
- }
- }
-
- entries.clear();
- _scanKeychain();
- }
- }
-
- private native void _scanKeychain();
-
- /**
- * Callback method from _scanKeychain. If a trusted certificate is found, this method will be called.
- */
- private void createTrustedCertEntry(String alias, long keychainItemRef, long creationDate, byte[] derStream) {
- TrustedCertEntry tce = new TrustedCertEntry();
-
- try {
- CertificateFactory cf = CertificateFactory.getInstance("X.509");
- InputStream input = new ByteArrayInputStream(derStream);
- X509Certificate cert = (X509Certificate) cf.generateCertificate(input);
- input.close();
- tce.cert = cert;
- tce.certRef = keychainItemRef;
-
- // Make a creation date.
- if (creationDate != 0)
- tce.date = new Date(creationDate);
- else
- tce.date = new Date();
-
- int uniqueVal = 1;
- String originalAlias = alias;
-
- while (entries.containsKey(alias.toLowerCase())) {
- alias = originalAlias + " " + uniqueVal;
- uniqueVal++;
- }
-
- entries.put(alias.toLowerCase(), tce);
- } catch (Exception e) {
- // The certificate will be skipped.
- System.err.println("KeychainStore Ignored Exception: " + e);
- }
- }
-
- /**
- * Callback method from _scanKeychain. If an identity is found, this method will be called to create Java certificate
- * and private key objects from the keychain data.
- */
- private void createKeyEntry(String alias, long creationDate, long secKeyRef, long[] secCertificateRefs, byte[][] rawCertData)
- throws IOException, NoSuchAlgorithmException, UnrecoverableKeyException {
- KeyEntry ke = new KeyEntry();
-
- // First, store off the private key information. This is the easy part.
- ke.protectedPrivKey = null;
- ke.keyRef = secKeyRef;
-
- // Make a creation date.
- if (creationDate != 0)
- ke.date = new Date(creationDate);
- else
- ke.date = new Date();
-
- // Next, create X.509 Certificate objects from the raw data. This is complicated
- // because a certificate's public key may be too long for Java's default encryption strength.
- List<CertKeychainItemPair> createdCerts = new ArrayList<>();
-
- try {
- CertificateFactory cf = CertificateFactory.getInstance("X.509");
-
- for (int i = 0; i < rawCertData.length; i++) {
- try {
- InputStream input = new ByteArrayInputStream(rawCertData[i]);
- X509Certificate cert = (X509Certificate) cf.generateCertificate(input);
- input.close();
-
- // We successfully created the certificate, so track it and its corresponding SecCertificateRef.
- createdCerts.add(new CertKeychainItemPair(secCertificateRefs[i], cert));
- } catch (CertificateException e) {
- // The certificate will be skipped.
- System.err.println("KeychainStore Ignored Exception: " + e);
- }
- }
- } catch (CertificateException e) {
- e.printStackTrace();
- } catch (IOException ioe) {
- ioe.printStackTrace(); // How would this happen?
- }
-
- // We have our certificates in the List, so now extract them into an array of
- // Certificates and SecCertificateRefs.
- CertKeychainItemPair[] objArray = createdCerts.toArray(new CertKeychainItemPair[0]);
- Certificate[] certArray = new Certificate[objArray.length];
- long[] certRefArray = new long[objArray.length];
-
- for (int i = 0; i < objArray.length; i++) {
- CertKeychainItemPair addedItem = objArray[i];
- certArray[i] = addedItem.mCert;
- certRefArray[i] = addedItem.mCertificateRef;
- }
-
- ke.chain = certArray;
- ke.chainRefs = certRefArray;
-
- // If we don't have already have an item with this item's alias
- // create a new one for it.
- int uniqueVal = 1;
- String originalAlias = alias;
-
- while (entries.containsKey(alias.toLowerCase())) {
- alias = originalAlias + " " + uniqueVal;
- uniqueVal++;
- }
-
- entries.put(alias.toLowerCase(), ke);
- }
-
- private class CertKeychainItemPair {
- long mCertificateRef;
- Certificate mCert;
-
- CertKeychainItemPair(long inCertRef, Certificate cert) {
- mCertificateRef = inCertRef;
- mCert = cert;
- }
- }
-
- /*
- * Validate Certificate Chain
- */
- private boolean validateChain(Certificate[] certChain)
- {
- for (int i = 0; i < certChain.length-1; i++) {
- X500Principal issuerDN =
- ((X509Certificate)certChain[i]).getIssuerX500Principal();
- X500Principal subjectDN =
- ((X509Certificate)certChain[i+1]).getSubjectX500Principal();
- if (!(issuerDN.equals(subjectDN)))
- return false;
- }
- return true;
- }
-
- @SuppressWarnings("deprecation")
- private byte[] fetchPrivateKeyFromBag(byte[] privateKeyInfo) throws IOException, NoSuchAlgorithmException, CertificateException
- {
- byte[] returnValue = null;
- DerValue val = new DerValue(new ByteArrayInputStream(privateKeyInfo));
- DerInputStream s = val.toDerInputStream();
- int version = s.getInteger();
-
- if (version != 3) {
- throw new IOException("PKCS12 keystore not in version 3 format");
- }
-
- /*
- * Read the authSafe.
- */
- byte[] authSafeData;
- ContentInfo authSafe = new ContentInfo(s);
- ObjectIdentifier contentType = authSafe.getContentType();
-
- if (contentType.equals(ContentInfo.DATA_OID)) {
- authSafeData = authSafe.getData();
- } else /* signed data */ {
- throw new IOException("public key protected PKCS12 not supported");
- }
-
- DerInputStream as = new DerInputStream(authSafeData);
- DerValue[] safeContentsArray = as.getSequence(2);
- int count = safeContentsArray.length;
-
- /*
- * Spin over the ContentInfos.
- */
- for (int i = 0; i < count; i++) {
- byte[] safeContentsData;
- ContentInfo safeContents;
- DerInputStream sci;
- byte[] eAlgId = null;
-
- sci = new DerInputStream(safeContentsArray[i].toByteArray());
- safeContents = new ContentInfo(sci);
- contentType = safeContents.getContentType();
- safeContentsData = null;
-
- if (contentType.equals(ContentInfo.DATA_OID)) {
- safeContentsData = safeContents.getData();
- } else if (contentType.equals(ContentInfo.ENCRYPTED_DATA_OID)) {
- // The password was used to export the private key from the keychain.
- // The Keychain won't export the key with encrypted data, so we don't need
- // to worry about it.
- continue;
- } else {
- throw new IOException("public key protected PKCS12" +
- " not supported");
- }
- DerInputStream sc = new DerInputStream(safeContentsData);
- returnValue = extractKeyData(sc);
- }
-
- return returnValue;
- }
-
- @SuppressWarnings("deprecation")
- private byte[] extractKeyData(DerInputStream stream)
- throws IOException, NoSuchAlgorithmException, CertificateException
- {
- byte[] returnValue = null;
- DerValue[] safeBags = stream.getSequence(2);
- int count = safeBags.length;
-
- /*
- * Spin over the SafeBags.
- */
- for (int i = 0; i < count; i++) {
- ObjectIdentifier bagId;
- DerInputStream sbi;
- DerValue bagValue;
- Object bagItem = null;
-
- sbi = safeBags[i].toDerInputStream();
- bagId = sbi.getOID();
- bagValue = sbi.getDerValue();
- if (!bagValue.isContextSpecific((byte)0)) {
- throw new IOException("unsupported PKCS12 bag value type "
- + bagValue.tag);
- }
- bagValue = bagValue.data.getDerValue();
- if (bagId.equals(PKCS8ShroudedKeyBag_OID)) {
- // got what we were looking for. Return it.
- returnValue = bagValue.toByteArray();
- } else {
- // log error message for "unsupported PKCS12 bag type"
- System.out.println("Unsupported bag type '" + bagId + "'");
- }
- }
-
- return returnValue;
- }
-
- /*
- * Generate PBE Algorithm Parameters
- */
- private AlgorithmParameters getAlgorithmParameters(String algorithm)
- throws IOException
- {
- AlgorithmParameters algParams = null;
-
- // create PBE parameters from salt and iteration count
- PBEParameterSpec paramSpec =
- new PBEParameterSpec(getSalt(), iterationCount);
- try {
- algParams = AlgorithmParameters.getInstance(algorithm);
- algParams.init(paramSpec);
- } catch (Exception e) {
- IOException ioe =
- new IOException("getAlgorithmParameters failed: " +
- e.getMessage());
- ioe.initCause(e);
- throw ioe;
- }
- return algParams;
- }
-
- // the source of randomness
- private SecureRandom random;
-
- /*
- * Generate random salt
- */
- private byte[] getSalt()
- {
- // Generate a random salt.
- byte[] salt = new byte[SALT_LEN];
- if (random == null) {
- random = new SecureRandom();
- }
- salt = random.generateSeed(SALT_LEN);
- return salt;
- }
-
- /*
- * parse Algorithm Parameters
- */
- private AlgorithmParameters parseAlgParameters(DerInputStream in)
- throws IOException
- {
- AlgorithmParameters algParams = null;
- try {
- DerValue params;
- if (in.available() == 0) {
- params = null;
- } else {
- params = in.getDerValue();
- if (params.tag == DerValue.tag_Null) {
- params = null;
- }
- }
- if (params != null) {
- algParams = AlgorithmParameters.getInstance("PBE");
- algParams.init(params.toByteArray());
- }
- } catch (Exception e) {
- IOException ioe =
- new IOException("parseAlgParameters failed: " +
- e.getMessage());
- ioe.initCause(e);
- throw ioe;
- }
- return algParams;
- }
-
- /*
- * Generate PBE key
- */
- private SecretKey getPBEKey(char[] password) throws IOException
- {
- SecretKey skey = null;
-
- try {
- PBEKeySpec keySpec = new PBEKeySpec(password);
- SecretKeyFactory skFac = SecretKeyFactory.getInstance("PBE");
- skey = skFac.generateSecret(keySpec);
- } catch (Exception e) {
- IOException ioe = new IOException("getSecretKey failed: " +
- e.getMessage());
- ioe.initCause(e);
- throw ioe;
- }
- return skey;
- }
-
- /*
- * Encrypt private key using Password-based encryption (PBE)
- * as defined in PKCS#5.
- *
- * NOTE: Currently pbeWithSHAAnd3-KeyTripleDES-CBC algorithmID is
- * used to derive the key and IV.
- *
- * @return encrypted private key encoded as EncryptedPrivateKeyInfo
- */
- private byte[] encryptPrivateKey(byte[] data, char[] password)
- throws IOException, NoSuchAlgorithmException, UnrecoverableKeyException
- {
- byte[] key = null;
-
- try {
- // create AlgorithmParameters
- AlgorithmParameters algParams =
- getAlgorithmParameters("PBEWithSHA1AndDESede");
-
- // Use JCE
- SecretKey skey = getPBEKey(password);
- Cipher cipher = Cipher.getInstance("PBEWithSHA1AndDESede");
- cipher.init(Cipher.ENCRYPT_MODE, skey, algParams);
- byte[] encryptedKey = cipher.doFinal(data);
-
- // wrap encrypted private key in EncryptedPrivateKeyInfo
- // as defined in PKCS#8
- AlgorithmId algid =
- new AlgorithmId(pbeWithSHAAnd3KeyTripleDESCBC_OID, algParams);
- EncryptedPrivateKeyInfo encrInfo =
- new EncryptedPrivateKeyInfo(algid, encryptedKey);
- key = encrInfo.getEncoded();
- } catch (Exception e) {
- UnrecoverableKeyException uke =
- new UnrecoverableKeyException("Encrypt Private Key failed: "
- + e.getMessage());
- uke.initCause(e);
- throw uke;
- }
-
- return key;
- }
-
-
-}
-
--- a/jdk/src/jdk.deploy.osx/macosx/native/libosx/KeystoreImpl.m Thu Aug 20 12:29:58 2015 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,589 +0,0 @@
-/*
- * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-#import "apple_security_KeychainStore.h"
-
-#import <Security/Security.h>
-#import <Security/SecImportExport.h>
-#import <CoreServices/CoreServices.h> // (for require() macros)
-#import <JavaNativeFoundation/JavaNativeFoundation.h>
-
-
-static JNF_CLASS_CACHE(jc_KeychainStore, "apple/security/KeychainStore");
-static JNF_MEMBER_CACHE(jm_createTrustedCertEntry, jc_KeychainStore, "createTrustedCertEntry", "(Ljava/lang/String;JJ[B)V");
-static JNF_MEMBER_CACHE(jm_createKeyEntry, jc_KeychainStore, "createKeyEntry", "(Ljava/lang/String;JJ[J[[B)V");
-
-static jstring getLabelFromItem(JNIEnv *env, SecKeychainItemRef inItem)
-{
- OSStatus status;
- jstring returnValue = NULL;
- char *attribCString = NULL;
-
- SecKeychainAttribute itemAttrs[] = { { kSecLabelItemAttr, 0, NULL } };
- SecKeychainAttributeList attrList = { sizeof(itemAttrs) / sizeof(itemAttrs[0]), itemAttrs };
-
- status = SecKeychainItemCopyContent(inItem, NULL, &attrList, NULL, NULL);
-
- if(status) {
- cssmPerror("getLabelFromItem: SecKeychainItemCopyContent", status);
- goto errOut;
- }
-
- attribCString = malloc(itemAttrs[0].length + 1);
- strncpy(attribCString, itemAttrs[0].data, itemAttrs[0].length);
- attribCString[itemAttrs[0].length] = '\0';
- returnValue = (*env)->NewStringUTF(env, attribCString);
-
-errOut:
- SecKeychainItemFreeContent(&attrList, NULL);
- if (attribCString) free(attribCString);
- return returnValue;
-}
-
-static jlong getModDateFromItem(JNIEnv *env, SecKeychainItemRef inItem)
-{
- OSStatus status;
- SecKeychainAttribute itemAttrs[] = { { kSecModDateItemAttr, 0, NULL } };
- SecKeychainAttributeList attrList = { sizeof(itemAttrs) / sizeof(itemAttrs[0]), itemAttrs };
- jlong returnValue = 0;
-
- status = SecKeychainItemCopyContent(inItem, NULL, &attrList, NULL, NULL);
-
- if(status) {
- // This is almost always missing, so don't dump an error.
- // cssmPerror("getModDateFromItem: SecKeychainItemCopyContent", status);
- goto errOut;
- }
-
- memcpy(&returnValue, itemAttrs[0].data, itemAttrs[0].length);
-
-errOut:
- SecKeychainItemFreeContent(&attrList, NULL);
- return returnValue;
-}
-
-static void setLabelForItem(NSString *inLabel, SecKeychainItemRef inItem)
-{
- OSStatus status;
- const char *labelCString = [inLabel UTF8String];
-
- // Set up attribute vector (each attribute consists of {tag, length, pointer}):
- SecKeychainAttribute attrs[] = {
- { kSecLabelItemAttr, strlen(labelCString), (void *)labelCString }
- };
-
- const SecKeychainAttributeList attributes = { sizeof(attrs) / sizeof(attrs[0]), attrs };
-
- // Not changing data here, just attributes.
- status = SecKeychainItemModifyContent(inItem, &attributes, 0, NULL);
-
- if(status) {
- cssmPerror("setLabelForItem: SecKeychainItemModifyContent", status);
- }
-}
-
-/*
- * Given a SecIdentityRef, do our best to construct a complete, ordered, and
- * verified cert chain, returning the result in a CFArrayRef. The result is
- * can be passed back to Java as a chain for a private key.
- */
-static OSStatus completeCertChain(
- SecIdentityRef identity,
- SecCertificateRef trustedAnchor, // optional additional trusted anchor
- bool includeRoot, // include the root in outArray
- CFArrayRef *outArray) // created and RETURNED
-{
- SecTrustRef secTrust = NULL;
- SecPolicyRef policy = NULL;
- SecPolicySearchRef policySearch = NULL;
- SecTrustResultType secTrustResult;
- CSSM_TP_APPLE_EVIDENCE_INFO *dummyEv; // not used
- CFArrayRef certChain = NULL; // constructed chain, CERTS ONLY
- CFMutableArrayRef subjCerts; // passed to SecTrust
- CFMutableArrayRef certArray; // returned array starting with
- // identity
- CFIndex numResCerts;
- CFIndex dex;
- OSStatus ortn;
- SecCertificateRef certRef;
-
- /* First element in out array is the SecIdentity */
- certArray = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
- CFArrayAppendValue(certArray, identity);
-
- /* the single element in certs-to-be-evaluated comes from the identity */
- ortn = SecIdentityCopyCertificate(identity, &certRef);
- if(ortn) {
- /* should never happen */
- cssmPerror("SecIdentityCopyCertificate", ortn);
- return ortn;
- }
-
- /*
- * Now use SecTrust to get a complete cert chain, using all of the
- * user's keychains to look for intermediate certs.
- * NOTE this does NOT handle root certs which are not in the system
- * root cert DB.
- */
- subjCerts = CFArrayCreateMutable(NULL, 1, &kCFTypeArrayCallBacks);
- CFArraySetValueAtIndex(subjCerts, 0, certRef);
-
- /* the array owns the subject cert ref now */
- CFRelease(certRef);
-
- /* Get a SecPolicyRef for generic X509 cert chain verification */
- ortn = SecPolicySearchCreate(CSSM_CERT_X_509v3,
- &CSSMOID_APPLE_X509_BASIC,
- NULL, // value
- &policySearch);
- if(ortn) {
- /* should never happen */
- cssmPerror("SecPolicySearchCreate", ortn);
- goto errOut;
- }
- ortn = SecPolicySearchCopyNext(policySearch, &policy);
- if(ortn) {
- /* should never happen */
- cssmPerror("SecPolicySearchCopyNext", ortn);
- goto errOut;
- }
-
- /* build a SecTrustRef for specified policy and certs */
- ortn = SecTrustCreateWithCertificates(subjCerts,
- policy, &secTrust);
- if(ortn) {
- cssmPerror("SecTrustCreateWithCertificates", ortn);
- goto errOut;
- }
-
- if(trustedAnchor) {
- /*
- * Tell SecTrust to trust this one in addition to the current
- * trusted system-wide anchors.
- */
- CFMutableArrayRef newAnchors;
- CFArrayRef currAnchors;
-
- ortn = SecTrustCopyAnchorCertificates(&currAnchors);
- if(ortn) {
- /* should never happen */
- cssmPerror("SecTrustCopyAnchorCertificates", ortn);
- goto errOut;
- }
- newAnchors = CFArrayCreateMutableCopy(NULL,
- CFArrayGetCount(currAnchors) + 1,
- currAnchors);
- CFRelease(currAnchors);
- CFArrayAppendValue(newAnchors, trustedAnchor);
- ortn = SecTrustSetAnchorCertificates(secTrust, newAnchors);
- CFRelease(newAnchors);
- if(ortn) {
- cssmPerror("SecTrustSetAnchorCertificates", ortn);
- goto errOut;
- }
- }
-
- /* evaluate: GO */
- ortn = SecTrustEvaluate(secTrust, &secTrustResult);
- if(ortn) {
- cssmPerror("SecTrustEvaluate", ortn);
- goto errOut;
- }
- switch(secTrustResult) {
- case kSecTrustResultUnspecified:
- /* cert chain valid, no special UserTrust assignments; drop thru */
- case kSecTrustResultProceed:
- /* cert chain valid AND user explicitly trusts this */
- break;
- default:
- /*
- * Cert chain construction failed.
- * Just go with the single subject cert we were given; maybe the
- * peer can complete the chain.
- */
- ortn = noErr;
- goto errOut;
- }
-
- /* get resulting constructed cert chain */
- ortn = SecTrustGetResult(secTrust, &secTrustResult, &certChain, &dummyEv);
- if(ortn) {
- cssmPerror("SecTrustEvaluate", ortn);
- goto errOut;
- }
-
- /*
- * Copy certs from constructed chain to our result array, skipping
- * the leaf (which is already there, as a SecIdentityRef) and possibly
- * a root.
- */
- numResCerts = CFArrayGetCount(certChain);
- if(numResCerts < 1) {
- /*
- * Can't happen: If chain doesn't verify to a root, we'd
- * have bailed after SecTrustEvaluate().
- */
- ortn = noErr;
- goto errOut;
- }
- if(!includeRoot) {
- /* skip the last (root) cert) */
- numResCerts--;
- }
- for(dex=1; dex<numResCerts; dex++) {
- certRef = (SecCertificateRef)CFArrayGetValueAtIndex(certChain, dex);
- CFArrayAppendValue(certArray, certRef);
- }
-errOut:
- /* clean up */
- if(secTrust) {
- CFRelease(secTrust);
- }
- if(subjCerts) {
- CFRelease(subjCerts);
- }
- if(policy) {
- CFRelease(policy);
- }
- if(policySearch) {
- CFRelease(policySearch);
- }
- *outArray = certArray;
- return ortn;
-}
-
-static void addIdentitiesToKeystore(JNIEnv *env, jobject keyStore)
-{
- // Search the user keychain list for all identities. Identities are a certificate/private key association that
- // can be chosen for a purpose such as signing or an SSL connection.
- SecIdentitySearchRef identitySearch = NULL;
- // Pass 0 if you want all identities returned by this search
- OSStatus err = SecIdentitySearchCreate(NULL, 0, &identitySearch);
- SecIdentityRef theIdentity = NULL;
- OSErr searchResult = noErr;
-
- do {
- searchResult = SecIdentitySearchCopyNext(identitySearch, &theIdentity);
-
- if (searchResult == noErr) {
- // Get the cert from the identity, then generate a chain.
- SecCertificateRef certificate;
- SecIdentityCopyCertificate(theIdentity, &certificate);
- CFArrayRef certChain = NULL;
-
- // *** Should do something with this error...
- err = completeCertChain(theIdentity, NULL, TRUE, &certChain);
-
- CFIndex i, certCount = CFArrayGetCount(certChain);
-
- // Make a java array of certificate data from the chain.
- jclass byteArrayClass = (*env)->FindClass(env, "[B");
- if (byteArrayClass == NULL) {
- goto errOut;
- }
- jobjectArray javaCertArray = (*env)->NewObjectArray(env, certCount, byteArrayClass, NULL);
- // Cleanup first then check for a NULL return code
- (*env)->DeleteLocalRef(env, byteArrayClass);
- if (javaCertArray == NULL) {
- goto errOut;
- }
-
- // And, make an array of the certificate refs.
- jlongArray certRefArray = (*env)->NewLongArray(env, certCount);
- if (certRefArray == NULL) {
- goto errOut;
- }
-
- SecCertificateRef currCertRef = NULL;
-
- for (i = 0; i < certCount; i++) {
- CSSM_DATA currCertData;
-
- if (i == 0)
- currCertRef = certificate;
- else
- currCertRef = (SecCertificateRef)CFArrayGetValueAtIndex(certChain, i);
-
- bzero(&currCertData, sizeof(CSSM_DATA));
- err = SecCertificateGetData(currCertRef, &currCertData);
- jbyteArray encodedCertData = (*env)->NewByteArray(env, currCertData.Length);
- if (encodedCertData == NULL) {
- goto errOut;
- }
- (*env)->SetByteArrayRegion(env, encodedCertData, 0, currCertData.Length, (jbyte *)currCertData.Data);
- (*env)->SetObjectArrayElement(env, javaCertArray, i, encodedCertData);
- jlong certRefElement = ptr_to_jlong(currCertRef);
- (*env)->SetLongArrayRegion(env, certRefArray, i, 1, &certRefElement);
- }
-
- // Get the private key. When needed we'll export the data from it later.
- SecKeyRef privateKeyRef;
- err = SecIdentityCopyPrivateKey(theIdentity, &privateKeyRef);
-
- // Find the label. It's a 'blob', but we interpret as characters.
- jstring alias = getLabelFromItem(env, (SecKeychainItemRef)certificate);
- if (alias == NULL) {
- goto errOut;
- }
-
- // Find the creation date.
- jlong creationDate = getModDateFromItem(env, (SecKeychainItemRef)certificate);
-
- // Call back to the Java object to create Java objects corresponding to this security object.
- jlong nativeKeyRef = ptr_to_jlong(privateKeyRef);
- JNFCallVoidMethod(env, keyStore, jm_createKeyEntry, alias, creationDate, nativeKeyRef, certRefArray, javaCertArray);
- }
- } while (searchResult == noErr);
-
-errOut:
- if (identitySearch != NULL) {
- CFRelease(identitySearch);
- }
-}
-
-static void addCertificatesToKeystore(JNIEnv *env, jobject keyStore)
-{
- // Search the user keychain list for all X509 certificates.
- SecKeychainSearchRef keychainItemSearch = NULL;
- OSStatus err = SecKeychainSearchCreateFromAttributes(NULL, kSecCertificateItemClass, NULL, &keychainItemSearch);
- SecKeychainItemRef theItem = NULL;
- OSErr searchResult = noErr;
-
- do {
- searchResult = SecKeychainSearchCopyNext(keychainItemSearch, &theItem);
-
- if (searchResult == noErr) {
- // Make a byte array with the DER-encoded contents of the certificate.
- SecCertificateRef certRef = (SecCertificateRef)theItem;
- CSSM_DATA currCertificate;
- err = SecCertificateGetData(certRef, &currCertificate);
- jbyteArray certData = (*env)->NewByteArray(env, currCertificate.Length);
- if (certData == NULL) {
- goto errOut;
- }
- (*env)->SetByteArrayRegion(env, certData, 0, currCertificate.Length, (jbyte *)currCertificate.Data);
-
- // Find the label. It's a 'blob', but we interpret as characters.
- jstring alias = getLabelFromItem(env, theItem);
- if (alias == NULL) {
- goto errOut;
- }
-
- // Find the creation date.
- jlong creationDate = getModDateFromItem(env, theItem);
-
- // Call back to the Java object to create Java objects corresponding to this security object.
- jlong nativeRef = ptr_to_jlong(certRef);
- JNFCallVoidMethod(env, keyStore, jm_createTrustedCertEntry, alias, nativeRef, creationDate, certData);
- }
- } while (searchResult == noErr);
-
-errOut:
- if (keychainItemSearch != NULL) {
- CFRelease(keychainItemSearch);
- }
-}
-
-/*
- * Class: apple_security_KeychainStore
- * Method: _getEncodedKeyData
- * Signature: (J)[B
- */
-JNIEXPORT jbyteArray JNICALL Java_apple_security_KeychainStore__1getEncodedKeyData
-(JNIEnv *env, jobject this, jlong keyRefLong, jcharArray passwordObj)
-{
- SecKeyRef keyRef = (SecKeyRef)jlong_to_ptr(keyRefLong);
- SecKeyImportExportParameters paramBlock;
- OSStatus err = noErr;
- CFDataRef exportedData = NULL;
- jbyteArray returnValue = NULL;
- CFStringRef passwordStrRef = NULL;
-
- jsize passwordLen = 0;
- jchar *passwordChars = NULL;
-
- if (passwordObj) {
- passwordLen = (*env)->GetArrayLength(env, passwordObj);
-
- if (passwordLen > 0) {
- passwordChars = (*env)->GetCharArrayElements(env, passwordObj, NULL);
- if (passwordChars == NULL) {
- goto errOut;
- }
- passwordStrRef = CFStringCreateWithCharacters(kCFAllocatorDefault, passwordChars, passwordLen);
- }
- }
-
- paramBlock.version = SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION;
- // Note that setting the flags field **requires** you to pass in a password of some kind. The keychain will not prompt you.
- paramBlock.flags = 0;
- paramBlock.passphrase = passwordStrRef;
- paramBlock.alertTitle = NULL;
- paramBlock.alertPrompt = NULL;
- paramBlock.accessRef = NULL;
- paramBlock.keyUsage = CSSM_KEYUSE_ANY;
- paramBlock.keyAttributes = CSSM_KEYATTR_RETURN_DEFAULT;
-
- err = SecKeychainItemExport(keyRef, kSecFormatPKCS12, 0, ¶mBlock, &exportedData);
-
- if (err == noErr) {
- CFIndex size = CFDataGetLength(exportedData);
- returnValue = (*env)->NewByteArray(env, size);
- if (returnValue == NULL) {
- goto errOut;
- }
- (*env)->SetByteArrayRegion(env, returnValue, 0, size, (jbyte *)CFDataGetBytePtr(exportedData));
- }
-
-errOut:
- if (exportedData) CFRelease(exportedData);
- if (passwordStrRef) CFRelease(passwordStrRef);
-
- return returnValue;
-}
-
-
-/*
- * Class: apple_security_KeychainStore
- * Method: _scanKeychain
- * Signature: ()V
- */
-JNIEXPORT void JNICALL Java_apple_security_KeychainStore__1scanKeychain
-(JNIEnv *env, jobject this)
-{
- // Look for 'identities' -- private key and certificate chain pairs -- and add those.
- // Search for these first, because a certificate that's found here as part of an identity will show up
- // again later as a certificate.
- addIdentitiesToKeystore(env, this);
-
- // Scan current keychain for trusted certificates.
- addCertificatesToKeystore(env, this);
-
-}
-
-/*
- * Class: apple_security_KeychainStore
- * Method: _addItemToKeychain
- * Signature: (Ljava/lang/String;[B)I
-*/
-JNIEXPORT jlong JNICALL Java_apple_security_KeychainStore__1addItemToKeychain
-(JNIEnv *env, jobject this, jstring alias, jboolean isCertificate, jbyteArray rawDataObj, jcharArray passwordObj)
-{
- OSStatus err;
- jlong returnValue = 0;
-
-JNF_COCOA_ENTER(env);
-
- jsize dataSize = (*env)->GetArrayLength(env, rawDataObj);
- jbyte *rawData = (*env)->GetByteArrayElements(env, rawDataObj, NULL);
- if (rawData == NULL) {
- goto errOut;
- }
-
- CFDataRef cfDataToImport = CFDataCreate(kCFAllocatorDefault, (UInt8 *)rawData, dataSize);
- CFArrayRef createdItems = NULL;
-
- SecKeychainRef defaultKeychain = NULL;
- SecKeychainCopyDefault(&defaultKeychain);
-
- SecExternalItemType dataType = (isCertificate == JNI_TRUE ? kSecFormatX509Cert : kSecFormatWrappedPKCS8);
-
- // Convert the password obj into a CFStringRef that the keychain importer can use for encryption.
- SecKeyImportExportParameters paramBlock;
- CFStringRef passwordStrRef = NULL;
-
- jsize passwordLen = 0;
- jchar *passwordChars = NULL;
-
- if (passwordObj) {
- passwordLen = (*env)->GetArrayLength(env, passwordObj);
- passwordChars = (*env)->GetCharArrayElements(env, passwordObj, NULL);
- passwordStrRef = CFStringCreateWithCharacters(kCFAllocatorDefault, passwordChars, passwordLen);
- }
-
- paramBlock.version = SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION;
- // Note that setting the flags field **requires** you to pass in a password of some kind. The keychain will not prompt you.
- paramBlock.flags = 0;
- paramBlock.passphrase = passwordStrRef;
- paramBlock.alertTitle = NULL;
- paramBlock.alertPrompt = NULL;
- paramBlock.accessRef = NULL;
- paramBlock.keyUsage = CSSM_KEYUSE_ANY;
- paramBlock.keyAttributes = CSSM_KEYATTR_RETURN_DEFAULT;
-
- err = SecKeychainItemImport(cfDataToImport, NULL, &dataType, NULL,
- 0, ¶mBlock, defaultKeychain, &createdItems);
-
- if (err == noErr) {
- SecKeychainItemRef anItem = (SecKeychainItemRef)CFArrayGetValueAtIndex(createdItems, 0);
-
- // Don't bother labeling keys. They become part of an identity, and are not an accessible part of the keychain.
- if (CFGetTypeID(anItem) == SecCertificateGetTypeID()) {
- setLabelForItem(JNFJavaToNSString(env, alias), anItem);
- }
-
- // Retain the item, since it will be released once when the array holding it gets released.
- CFRetain(anItem);
- returnValue = ptr_to_jlong(anItem);
- } else {
- cssmPerror("_addItemToKeychain: SecKeychainItemImport", err);
- }
-
- (*env)->ReleaseByteArrayElements(env, rawDataObj, rawData, JNI_ABORT);
-
- if (createdItems != NULL) {
- CFRelease(createdItems);
- }
-
-errOut: ;
-
-JNF_COCOA_EXIT(env);
-
- return returnValue;
-}
-
-/*
- * Class: apple_security_KeychainStore
- * Method: _removeItemFromKeychain
- * Signature: (J)I
-*/
-JNIEXPORT jint JNICALL Java_apple_security_KeychainStore__1removeItemFromKeychain
-(JNIEnv *env, jobject this, jlong keychainItem)
-{
- SecKeychainItemRef itemToRemove = jlong_to_ptr(keychainItem);
- return SecKeychainItemDelete(itemToRemove);
-}
-
-/*
- * Class: apple_security_KeychainStore
- * Method: _releaseKeychainItemRef
- * Signature: (J)V
- */
-JNIEXPORT void JNICALL Java_apple_security_KeychainStore__1releaseKeychainItemRef
-(JNIEnv *env, jobject this, jlong keychainItem)
-{
- SecKeychainItemRef itemToFree = jlong_to_ptr(keychainItem);
- CFRelease(itemToFree);
-}
--- a/jdk/src/jdk.dev/share/classes/jdk/tools/jimage/ExtractedImage.java Thu Aug 20 12:29:58 2015 -0700
+++ b/jdk/src/jdk.dev/share/classes/jdk/tools/jimage/ExtractedImage.java Wed Jul 05 20:46:25 2017 +0200
@@ -164,17 +164,19 @@
private Set<Archive> archives = new HashSet<>();
private final PrintWriter log;
private final boolean verbose;
-
+ private final String jdataName;
ExtractedImage(Path dirPath, PrintWriter log,
boolean verbose) throws IOException {
if (!Files.isDirectory(dirPath)) {
throw new IOException("Not a directory");
}
+ List<String> jdataNameHolder = new ArrayList<>();
Files.walk(dirPath, 1).forEach((p) -> {
try {
if (!dirPath.equals(p)) {
String name = getPathName(p);
if (name.endsWith(ImageModuleData.META_DATA_EXTENSION)) {
+ jdataNameHolder.add(p.getFileName().toString());
List<String> lines = Files.readAllLines(p);
for (Entry<String, List<String>> entry
: ImageModuleDataWriter.toModulePackages(lines).entrySet()) {
@@ -197,11 +199,22 @@
archives = Collections.unmodifiableSet(archives);
this.log = log;
this.verbose = verbose;
+ if (jdataNameHolder.size() != 1) {
+ throw new IOException("Wrong module information");
+ }
+ // The name of the metadata resource must be reused in the recreated jimage
+ String name = jdataNameHolder.get(0);
+ // Extension will be added when recreating the jimage
+ if (name.endsWith(ImageModuleData.META_DATA_EXTENSION)) {
+ name = name.substring(0, name.length()
+ - ImageModuleData.META_DATA_EXTENSION.length());
+ }
+ jdataName = name;
}
void recreateJImage(Path path) throws IOException {
- ImageFileCreator.recreateJimage(path, archives, modulePackages);
+ ImageFileCreator.recreateJimage(path, jdataName, archives, modulePackages);
}
private static String getPathName(Path path) {
--- a/jdk/src/jdk.hprof.agent/aix/native/libhprof/porting_aix.c Thu Aug 20 12:29:58 2015 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,86 +0,0 @@
-/*
- * Copyright 2012, 2013 SAP AG. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-#include <stdio.h>
-#include <sys/ldr.h>
-#include <errno.h>
-
-#include "porting_aix.h"
-
-static unsigned char dladdr_buffer[0x4000];
-
-static void fill_dll_info(void) {
- int rc = loadquery(L_GETINFO,dladdr_buffer, sizeof(dladdr_buffer));
- if (rc == -1) {
- fprintf(stderr, "loadquery failed (%d %s)", errno, strerror(errno));
- fflush(stderr);
- }
-}
-
-static int dladdr_dont_reload(void* addr, Dl_info* info) {
- const struct ld_info* p = (struct ld_info*) dladdr_buffer;
- info->dli_fbase = 0; info->dli_fname = 0;
- info->dli_sname = 0; info->dli_saddr = 0;
- for (;;) {
- if (addr >= p->ldinfo_textorg &&
- addr < (((char*)p->ldinfo_textorg) + p->ldinfo_textsize)) {
- info->dli_fname = p->ldinfo_filename;
- info->dli_fbase = p->ldinfo_textorg;
- return 1; /* [sic] */
- }
- if (!p->ldinfo_next) {
- break;
- }
- p = (struct ld_info*)(((char*)p) + p->ldinfo_next);
- }
- return 0; /* [sic] */
-}
-
-#ifdef __cplusplus
-extern "C"
-#endif
-int dladdr(void *addr, Dl_info *info) {
- static int loaded = 0;
- if (!loaded) {
- fill_dll_info();
- loaded = 1;
- }
- if (!addr) {
- return 0; /* [sic] */
- }
- /* Address could be AIX function descriptor? */
- void* const addr0 = *( (void**) addr );
- int rc = dladdr_dont_reload(addr, info);
- if (rc == 0) {
- rc = dladdr_dont_reload(addr0, info);
- if (rc == 0) { /* [sic] */
- fill_dll_info(); /* refill, maybe loadquery info is outdated */
- rc = dladdr_dont_reload(addr, info);
- if (rc == 0) {
- rc = dladdr_dont_reload(addr0, info);
- }
- }
- }
- return rc;
-}
--- a/jdk/src/jdk.hprof.agent/aix/native/libhprof/porting_aix.h Thu Aug 20 12:29:58 2015 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,59 +0,0 @@
-/*
- * Copyright 2012, 2013 SAP AG. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-/*
- * Header file to contain porting-relevant code which does not have a
- * home anywhere else.
- * This is intially based on hotspot/src/os/aix/vm/{loadlib,porting}_aix.{hpp,cpp}
- */
-
-/*
- * Aix' own version of dladdr().
- * This function tries to mimick dladdr(3) on Linux
- * (see http://linux.die.net/man/3/dladdr)
- * dladdr(3) is not POSIX but a GNU extension, and is not available on AIX.
- *
- * Differences between AIX dladdr and Linux dladdr:
- *
- * 1) Dl_info.dli_fbase: can never work, is disabled.
- * A loaded image on AIX is divided in multiple segments, at least two
- * (text and data) but potentially also far more. This is because the loader may
- * load each member into an own segment, as for instance happens with the libC.a
- * 2) Dl_info.dli_sname: This only works for code symbols (functions); for data, a
- * zero-length string is returned ("").
- * 3) Dl_info.dli_saddr: For code, this will return the entry point of the function,
- * not the function descriptor.
- */
-
-typedef struct {
- const char *dli_fname; /* file path of loaded library */
- void *dli_fbase; /* doesn't make sence on AIX */
- const char *dli_sname; /* symbol name; "" if not known */
- void *dli_saddr; /* address of *entry* of function; not function descriptor; */
-} Dl_info;
-
-#ifdef __cplusplus
-extern "C"
-#endif
-int dladdr(void *addr, Dl_info *info);
--- a/jdk/src/jdk.hprof.agent/share/classes/com/sun/demo/jvmti/hprof/Tracker.java Thu Aug 20 12:29:58 2015 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,124 +0,0 @@
-/*
- * Copyright (c) 2004, 2013, Oracle and/or its affiliates. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * - Neither the name of Oracle nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
- * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-package com.sun.demo.jvmti.hprof;
-
-/* This class and it's methods are used by hprof when injecting bytecodes
- * into class file images.
- * See the directory src/share/demo/jvmti/hprof and the file README.txt
- * for more details.
- */
-
-public class Tracker {
-
- /* Master switch that activates calls to native functions. */
-
- private static int engaged = 0;
-
- /* To track memory allocated, we need to catch object init's and arrays. */
-
- /* At the beginning of java.jang.Object.<init>(), a call to
- * Tracker.ObjectInit() is injected.
- */
-
- private static native void nativeObjectInit(Object thr, Object obj);
-
- public static void ObjectInit(Object obj)
- {
- if ( engaged != 0) {
- if (obj == null) {
- throw new IllegalArgumentException("Null object.");
- }
- nativeObjectInit(Thread.currentThread(), obj);
- }
- }
-
- /* Immediately following any of the newarray bytecodes, a call to
- * Tracker.NewArray() is injected.
- */
-
- private static native void nativeNewArray(Object thr, Object obj);
-
- public static void NewArray(Object obj)
- {
- if ( engaged != 0) {
- if (obj == null) {
- throw new IllegalArgumentException("Null object.");
- }
- nativeNewArray(Thread.currentThread(), obj);
- }
- }
-
- /* For cpu time spent in methods, we need to inject for every method. */
-
- /* At the very beginning of every method, a call to
- * Tracker.CallSite() is injected.
- */
-
- private static native void nativeCallSite(Object thr, int cnum, int mnum);
-
- public static void CallSite(int cnum, int mnum)
- {
- if ( engaged != 0 ) {
- if (cnum < 0) {
- throw new IllegalArgumentException("Negative class index");
- }
-
- if (mnum < 0) {
- throw new IllegalArgumentException("Negative method index");
- }
-
- nativeCallSite(Thread.currentThread(), cnum, mnum);
- }
- }
-
- /* Before any of the return bytecodes, a call to
- * Tracker.ReturnSite() is injected.
- */
-
- private static native void nativeReturnSite(Object thr, int cnum, int mnum);
-
- public static void ReturnSite(int cnum, int mnum)
- {
- if ( engaged != 0 ) {
- if (cnum < 0) {
- throw new IllegalArgumentException("Negative class index");
- }
-
- if (mnum < 0) {
- throw new IllegalArgumentException("Negative method index");
- }
-
- nativeReturnSite(Thread.currentThread(), cnum, mnum);
- }
- }
-
-}
--- a/jdk/src/jdk.hprof.agent/share/native/libhprof/README.txt Thu Aug 20 12:29:58 2015 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,113 +0,0 @@
-/*
- * Copyright (c) 2003, 2005, Oracle and/or its affiliates. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * - Neither the name of Oracle nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
- * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-README
-------
-
-Design and Implementation:
-
- * The Tracker Class (Tracker.java & hprof_tracker.c)
- It was added to the sun.tools.hprof.Tracker in JDK 5.0 FCS, then
- moved to a package that didn't cause classload errors due to
- the security manager not liking the sun.* package name.
- 5091195 detected that this class needs to be in com.sun.demo.jvmti.hprof.
- The BCI code will call these static methods, which will in turn
- (if engaged) call matching native methods in the hprof library,
- with the additional current Thread argument (Thread.currentThread()).
- Doing the currentThread call on the Java side was necessary due
- to the difficulty of getting the current thread while inside one
- of these Tracker native methods. This class lives in rt.jar.
-
- * Byte Code Instrumentation (BCI)
- Using the ClassFileLoadHook feature and a C language
- implementation of a byte code injection transformer, the following
- bytecodes get injections:
- - On entry to the java.lang.Object <init> method,
- a invokestatic call to
- Tracker.ObjectInit(this);
- is injected.
- - On any newarray type opcode, immediately following it,
- the array object is duplicated on the stack and an
- invokestatic call to
- Tracker.NewArray(obj);
- is injected.
- - On entry to all methods, a invokestatic call to
- Tracker.CallSite(cnum,mnum);
- is injected. The hprof agent can map the two integers
- (cnum,mnum) to a method in a class. This is the BCI based
- "method entry" event.
- - On return from any method (any return opcode),
- a invokestatic call to
- Tracker.ReturnSite(cnum,mnum);
- is injected.
- All classes found via ClassFileLoadHook are injected with the
- exception of some system class methods "<init>" and "finalize"
- whose length is 1 and system class methods with name "<clinit>",
- and also java.lang.Thread.currentThread() which is used in the
- class Tracker (preventing nasty recursion issue).
- System classes are currently defined as any class seen by the
- ClassFileLoadHook prior to VM_INIT. This does mean that
- objects created in the system classes inside <clinit> might not
- get tracked initially.
- See the java_crw_demo source and documentation for more info.
- The injections are based on what the hprof options
- are requesting, e.g. if heap=sites or heap=all is requested, the
- newarray and Object.<init> method injections happen.
- If cpu=times is requested, all methods get their entries and
- returns tracked. Options like cpu=samples or monitor=y
- do not require BCI.
-
- * BCI Allocation Tags (hprof_tag.c)
- The current jlong tag being used on allocated objects
- is an ObjectIndex, or an index into the object table inside
- the hprof code. Depending on whether heap=sites or heap=dump
- was asked for, these ObjectIndex's might represent unique
- objects, or unique allocation sites for types of objects.
- The heap=dump option requires considerable more space
- due to the one jobject per ObjectIndex mapping.
-
- * BCI Performance
- The cpu=times seems to have the most negative affect on
- performance, this could be improved by not having the
- Tracker class methods call native code directly, but accumulate
- the data in a file or memory somehow and letting it buffer down
- to the agent. The cpu=samples is probably a better way to
- measure cpu usage, varying the interval as needed.
- The heap=dump seems to use memory like crazy, but that's
- partially the way it has always been.
-
- * Sources in the JDK workspace
- The sources and Makefiles live in:
- src/jdk.hprof.agent/*
- src/share/demo/jvmti/java_crw_demo/*
- make/lib/Lib-jdk.hprof.agent.gmk
-
---------
--- a/jdk/src/jdk.hprof.agent/share/native/libhprof/debug_malloc.c Thu Aug 20 12:29:58 2015 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,769 +0,0 @@
-/*
- * Copyright (c) 2004, 2013, Oracle and/or its affiliates. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * - Neither the name of Oracle nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
- * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/*
- * This source code is provided to illustrate the usage of a given feature
- * or technique and has been deliberately simplified. Additional steps
- * required for a production-quality application, such as security checks,
- * input validation and proper error handling, might not be present in
- * this sample code.
- */
-
-
-/* **************************************************************************
- *
- * Set of malloc/realloc/calloc/strdup/free replacement macros that
- * insert some extra words around each allocation for debugging purposes
- * and also attempt to detect invalid uses of the malloc heap through
- * various tricks like inserting clobber words at the head and tail of
- * the user's area, delayed free() calls, and setting the memory to
- * a fixed pattern on allocation and when freed. The allocations also
- * can include warrants so that when an area is clobbered, this
- * package can report where the allocation took place.
- * The macros included are:
- * malloc(size)
- * realloc(ptr,size)
- * calloc(nelem,elsize)
- * strdup(s1)
- * free(ptr)
- * malloc_police() <--- Not a system function
- * The above macros match the standard behavior of the system functions.
- *
- * They should be used through the include file "debug_malloc.h".
- *
- * IMPORTANT: All source files that call any of these macros
- * should include debug_malloc.h. This package will
- * not work if the memory isn't allocated and freed
- * by the macros in debug_malloc.h. The important issue
- * is that any malloc() from debug_malloc.h must be
- * freed by the free() in debug_malloc.h.
- *
- * The macros in debug_malloc.h will override the normal use of
- * malloc, realloc, calloc, strdup, and free with the functions below.
- *
- * These functions include:
- * void *debug_malloc(size_t, void*, int);
- * void *debug_realloc(void*, size_t, void*, int);
- * void *debug_calloc(size_t, size_t, void*, int);
- * void debug_free(void *, void*, int);
- *
- * In addition the function debug_malloc_police() can be called to
- * tell you what memory has not been freed.
- * void debug_malloc_police(void*, int);
- * The function debug_malloc_police() is available through the macro
- * malloc_police(). Normally you would want to call this at exit()
- * time to find out what memory is still allocated.
- *
- * The variable malloc_watch determines if the warrants are generated.
- * warrants are structures that include the filename and line number
- * of the caller who allocated the memory. This structure is stored
- * at the tail of the malloc space, which is allocated large enough
- * to hold some clobber words at the head and tail, the user's request
- * and the warrant record (if malloc_watch is non-zero).
- *
- * The macro LEFT_OVER_CHAR is what the trailing bytes of an allocation
- * are set to (when the allocation is not a multiple of 8) on allocation.
- * At free(0 time, these bytes are double checked to make sure they were
- * not clobbered. To remove this feature #undef LEFT_OVER_CHAR.
- *
- * The memory freed will have the FREED_CHAR put into it. To remove this
- * feature #undef FREED_CHAR.
- *
- * The memory allocated (not calloc'd) will have the ALLOC_CHAR put into it
- * at the time of allocation. To remove this feature #undef ALLOC_CHAR.
- *
- * The macro MAX_FREE_DELAY_COUNT controls how many free blocks will
- * be kept around before being freed. This creates a delayed affect
- * so that free space that gets clobbered just might get detected.
- * The free() call will immediately set the user space to the FREED_CHAR,
- * leaving the clobber words and warrant in place (making sure they
- * haven't been clobbered). Then the free() pointer is added to a
- * queue of MAX_FREE_DELAY_COUNT long, and if the queue was full, the
- * oldest free()'d memory is actually freed, getting it's entire
- * memory length set to the FREED_CHAR.
- *
- * WARNING: This can significantly slow down an application, depending
- * on how many allocations are made. Also the additional memory
- * needed for the clobber words and the warrants can be significant
- * again, depending on how many allocations are made.
- * In addition, the delayed free calls can create situations
- * where you might run out of memory prematurely.
- *
- * **************************************************************************
- */
-
-#ifdef DEBUG
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-#include <stdarg.h>
-#include "hprof.h"
-
-/* ***************************************************************************
- * Space normally looks like (clobber Word is 64 bits and aligned to 8 bytes):
- *
- * -----------------
- * malloc/free get->| clobber Word | ---> contains -size requested by user
- * -----------------
- * User gets --->| user space |
- * | |
- * | | left_over | ---> left_over bytes will be <= 7
- * -----------------
- * | clobber Word | ---> contains -size requested by user
- * -----------------
- * | Warrant | ---> Optional (malloc_watch!=0)
- * | | Contains filename and line number
- * | | where allocation happened
- * | |
- * -----------------
- ***************************************************************************/
-
-/*
- * Flag that tells debug_malloc/debug_free/debug_realloc to police
- * heap space usage. (This is a dynamic flag that can be turned on/off)
- */
-static int malloc_watch = 1;
-
-/* Character to stuff into freed space */
-#define FREED_CHAR 'F'
-
-/* Character to stuff into allocated space */
-#define ALLOC_CHAR 'A'
-
-/* Character to stuff into left over trailing bytes */
-#define LEFT_OVER_CHAR 'Z'
-
-/* Number of 'free' calls that will be delayed until the end */
-#define MAX_FREE_DELAY_COUNT 1
-#undef MAX_FREE_DELAY_COUNT
-
-/* Maximum name of __FILE_ stored in each malloc'd area */
-#define WARRANT_NAME_MAX (32-1) /* 1 less than multiple of 8 is best */
-
-/* Macro to convert a user pointer to the malloc pointer */
-#define user2malloc_(uptr) (((char*)(void*)uptr)-sizeof(Word))
-
-/* Macro to convert a macro pointer to the user pointer */
-#define malloc2user_(mptr) (((char*)(void*)(mptr))+sizeof(Word))
-
-/* Size of the warrant record (this is dynamic) */
-#define warrant_space ( malloc_watch?sizeof(Warrant_Record):0 )
-
-/* Macro to round up a number of bytes to a multiple of sizeof(Word) bytes */
-#define round_up_(n) \
- ((n)==0?0:(sizeof(Word)+(((n)-1)/sizeof(Word))*sizeof(Word)))
-
-/* Macro to calculate the needed malloc bytes from the user's request. */
-#define rbytes_(nbytes) \
- (size_t)( sizeof(Word) + round_up_(nbytes) + sizeof(Word) + warrant_space )
-
-/* Macro to get the -size stored in space through the malloc pointer */
-#define nsize1_(mptr) (((Word*)(void*)(mptr))->nsize1)
-#define nsize2_(mptr) (((Word*)(void*)(mptr))->nsize2)
-
-/* Macro to get the -size stored in the tail of the space through */
-/* the malloc pointer */
-#define tail_nsize1_(mptr) \
- nsize1_(((char*)(void*)(mptr))+round_up_(-nsize1_(mptr))+sizeof(Word))
-#define tail_nsize2_(mptr) \
- nsize2_(((char*)(void*)(mptr))+round_up_(-nsize1_(mptr))+sizeof(Word))
-
-/* Macro to get the -size stored in space through the user pointer */
-#define user_nsize1_(uptr) nsize1_(user2malloc_(uptr))
-#define user_nsize2_(uptr) nsize2_(user2malloc_(uptr))
-
-/* Macro to get the -size stored in the tail of the space through */
-/* the user pointer */
-#define user_tail_nsize1_(uptr) tail_nsize1_(user2malloc_(uptr))
-#define user_tail_nsize2_(uptr) tail_nsize2_(user2malloc_(uptr))
-
-/* Macro to get the int* of the last 32bit word of user space */
-#define last_user_word_(mptr) \
- ((int*)(((char*)(void*)(mptr))+round_up_(-nsize1_(mptr))))
-
-/* Macros to get at the warrant contents from the malloc pointer */
-#define warrant_(mptr) \
- (*((Warrant_Record*)(void*)(((char*)(void*)(mptr))+round_up_(-nsize1_(mptr))+sizeof(Word)*2)))
-
-/* This struct is allocated after the tail clobber word if malloc_watch */
-/* is true. */
-typedef struct {
- void *link; /* Next mptr in list */
- char name[WARRANT_NAME_MAX + 1]; /* Name of allocator */
- int line; /* Line number where allocated */
- int id; /* Nth allocation */
-} Warrant_Record;
-#define warrant_link_(mptr) warrant_(mptr).link
-#define warrant_name_(mptr) warrant_(mptr).name
-#define warrant_line_(mptr) warrant_(mptr).line
-#define warrant_id_(mptr) warrant_(mptr).id
-#define MFILE(mptr) (malloc_watch?warrant_name_(mptr):"?")
-#define MLINE(mptr) (malloc_watch?warrant_line_(mptr):0)
-#define MID(mptr) (malloc_watch?warrant_id_(mptr):0)
-
-/* This should be one machine word and is also the clobber word struct */
-typedef struct {
- int nsize1;
- int nsize2;
-} Word; /* Largest basic type , sizeof(double)? */
-
-/* The first malloc pointer for the warrants */
-static void *first_warrant_mptr = NULL;
-
-/* Counter of allocations */
-static int id_counter = 0;
-static int largest_size = 0;
-static void * largest_addr = NULL;
-static void * smallest_addr = NULL;
-
-/* Used to isolate what the error is */
-static char *debug_check;
-static void *clobbered_ptr;
-
-/* Minimum macro */
-#define minimum(a,b) ((a)<(b)?(a):(b))
-
-/* Message routine */
-static void
-error_message(const char * format, ...)
-{
- FILE *error_fp = stderr; /* All debug_malloc.c messages */
- va_list ap;
- va_start(ap, format);
- (void)fprintf(error_fp, "debug_malloc: ");
- (void)vfprintf(error_fp, format, ap);
- (void)fprintf(error_fp, "\n");
- (void)fflush(error_fp);
- va_end(ap);
-}
-
-/* This function prints out a memory error for the memory function
- * 'name' which was called in file 'file' at line number 'line'. The malloc
- * pointer with the error is in 'mptr'.
- */
-static void
-memory_error(void *mptr, const char *name, int mid, const char *mfile, int mline, const char *file, int line)
-{
- char nice_words[512];
- char temp[256];
- int len;
- void *mptr_walk;
-
- if (name == NULL)
- name = "UNKNOWN_NAME";
- if (file == NULL)
- file = "UNKNOWN_FILE";
- md_system_error(temp, (int)sizeof(temp));
- (void)strcpy(nice_words, temp);
- if ( debug_check!=NULL ) {
- (void)md_snprintf(nice_words, sizeof(nice_words),
- "%s The %s at %p appears to have been hit.",
- temp, debug_check, clobbered_ptr);
- }
- len = -nsize1_(mptr);
- error_message("Error: "
- "%s The malloc space #%d is at %p [user size=%d(0x%x)],"
- " and was allocated from file \"%s\" at line %d."
- " [The debug function %s() detected this error "
- "in file \"%s\" at line %d.]",
- nice_words, mid, mptr, len, len, mfile, mline,
- name, file, line);
-
- /* Print out contents of this allocation */
- {
- int i;
- void *uptr = malloc2user_(mptr);
- char *pmess;
- pmess = temp;
- for(i=0;i<(int)sizeof(temp);i++) {
- int ch = ((unsigned char*)uptr)[i];
- if ( isprint(ch) ) {
- *pmess++ = ch;
- } else {
- *pmess++ = '\\';
- *pmess++ = 'x';
- (void)sprintf(pmess,"%02x",ch);
- pmess+=2;
- }
- }
- *pmess = 0;
- error_message("Error: %p contains user data: %s", uptr, temp);
- }
-
- /* Try and print out table */
- if (!malloc_watch) {
- return;
- }
- mptr_walk = first_warrant_mptr;
- if (mptr_walk != NULL) {
- error_message("Active allocations: "
- "count=%d, largest_size=%d, address range (%p,%p)",
- id_counter, largest_size, smallest_addr, largest_addr);
- do {
- int size1;
- int size2;
- char *mfile_walk;
-
- if ( mptr_walk > largest_addr || mptr_walk < smallest_addr ) {
- error_message("Terminating list due to pointer corruption");
- break;
- }
- size1 = -nsize1_(mptr_walk);
- size2 = -nsize2_(mptr_walk);
- mfile_walk = MFILE(mptr_walk);
- error_message("#%d: addr=%p size1=%d size2=%d file=\"%.*s\" line=%d",
- MID(mptr_walk), mptr_walk, size1, size2,
- WARRANT_NAME_MAX, mfile_walk, MLINE(mptr_walk));
- if ( size1 != size2 || size1 > largest_size || size1 < 0 ) {
- error_message("Terminating list due to size corruption");
- break;
- }
- mptr_walk = warrant_link_(mptr_walk);
- } while (mptr_walk != NULL);
- }
- abort();
-}
-
-/* This function sets the clobber word and sets up the warrant for the input
- * malloc pointer "mptr".
- */
-static void
-setup_space_and_issue_warrant(void *mptr, size_t size, const char *file, int line)
-{
- register int nbytes;
-
- /*LINTED*/
- nbytes = (int)size;
- if ( nbytes > largest_size || largest_addr == NULL ) largest_size = nbytes;
- /*LINTED*/
- if ( mptr > largest_addr ) largest_addr = mptr;
- /*LINTED*/
- if ( mptr < smallest_addr || smallest_addr == NULL ) smallest_addr = mptr;
-
- /* Must be done first: */
- nsize1_(mptr) = -nbytes;
- nsize2_(mptr) = -nbytes;
- tail_nsize1_(mptr) = -nbytes;
- tail_nsize2_(mptr) = -nbytes;
-
-#ifdef LEFT_OVER_CHAR
- /* Fill in those few extra bytes just before the tail Word structure */
- {
- register int trailing_extra_bytes;
- /* LINTED */
- trailing_extra_bytes = (int) (round_up_(nbytes) - nbytes);
- if ( trailing_extra_bytes > 0 ) {
- register char *p;
- register int i;
- p = ((char *) mptr) + sizeof(Word) + nbytes;
- for (i = 0; i < trailing_extra_bytes; i++)
- p[i] = LEFT_OVER_CHAR;
- }
- }
-#endif
-
- /* Fill out warrant */
- if (malloc_watch) {
- static Warrant_Record zero_warrant;
- register void *p1,
- *p2;
- size_t len;
- int start_pos = 0;
- warrant_(mptr) = zero_warrant;
- p1 = warrant_name_(mptr);
- len = strlen(file);
- if ( len > WARRANT_NAME_MAX ) {
- /*LINTED*/
- start_pos = (int)len - WARRANT_NAME_MAX;
- }
- p2 = ((char*)file) + start_pos;
- /*LINTED*/
- (void) memcpy(p1, p2, minimum(((int)len), WARRANT_NAME_MAX));
- warrant_line_(mptr) = line;
- warrant_id_(mptr) = ++id_counter;
- warrant_link_(mptr) = first_warrant_mptr;
- first_warrant_mptr = mptr;
- }
-}
-
-/* This function checks the clobber words at the beginning and end of the
- * allocated space.
- */
-static void
-memory_check(void *uptr, int mid, const char *mfile, int mline, const char *file, int line)
-{
- int neg_nbytes;
- int nbytes;
-
- debug_check = "pointer value itself";
- clobbered_ptr = uptr;
- if (uptr == NULL)
- memory_error((void *) NULL, "memory_check", mid, mfile, mline, file, line);
-
- /* Check both Word structures */
-
- debug_check = "first beginning clobber word";
- clobbered_ptr = (char*)&user_nsize1_(uptr);
- neg_nbytes = user_nsize1_(uptr);
- if (neg_nbytes >= 0)
- memory_error(user2malloc_(uptr), "memory_check", mid, mfile, mline, file, line);
-
- debug_check = "second beginning clobber word";
- clobbered_ptr = (char*)&user_nsize2_(uptr);
- if (neg_nbytes != user_nsize2_(uptr))
- memory_error(user2malloc_(uptr), "memory_check", mid, mfile, mline, file, line);
-
- debug_check = "first ending clobber word";
- clobbered_ptr = (char*)&user_tail_nsize1_(uptr);
- if (neg_nbytes != user_tail_nsize1_(uptr))
- memory_error(user2malloc_(uptr), "memory_check", mid, mfile, mline, file, line);
-
- debug_check = "second ending clobber word";
- clobbered_ptr = (char*)&user_tail_nsize2_(uptr);
- if (neg_nbytes != user_tail_nsize2_(uptr))
- memory_error(user2malloc_(uptr), "memory_check", mid, mfile, mline, file, line);
-
- /* Get a positive count of bytes */
- nbytes = -neg_nbytes;
-
-#ifdef LEFT_OVER_CHAR
- {
- /* Check those few extra bytes just before the tail Word structure */
- register int trailing_extra_bytes;
- register int i;
- register char *p;
- /* LINTED */
- trailing_extra_bytes = (int) (round_up_(nbytes) - nbytes);
- p = ((char *) (uptr)) + nbytes;
- debug_check = "trailing left over area";
- for (i = 0; i < trailing_extra_bytes; i++) {
- clobbered_ptr = p+1;
- if (p[i] != LEFT_OVER_CHAR) {
- memory_error(user2malloc_(uptr), "memory_check", mid, mfile, mline, file, line);
- }
- }
- }
-#endif
-
- /* Make sure debug_check is cleared */
- debug_check = NULL;
-}
-
-/* This function looks for the given malloc pointer in the police line up
- * and removes it from the warrant list.
- * mptr The pointer to the malloc space being removed
- */
-static int
-remove_warrant(void *mptr)
-{
- void *mptr1,
- *last_mptr1;
-
- /* Free it up from the list */
- if (malloc_watch && mptr != NULL) {
- int found;
-
- found = 0;
- last_mptr1 = NULL;
- mptr1 = first_warrant_mptr;
- while (mptr1 != NULL) {
- if (mptr1 == mptr) {
- if (last_mptr1 == NULL)
- first_warrant_mptr = warrant_link_(mptr1);
- else
- warrant_link_(last_mptr1) = warrant_link_(mptr1);
- found = 1;
- break;
- }
- last_mptr1 = mptr1;
- mptr1 = warrant_link_(mptr1);
- }
- return found;
- }
- return 1;
-}
-
-static void
-actual_free(void *uptr, const char *file, int line)
-{
- void *mptr;
- const char *mfile;
- int mline;
- int mid;
- if ( uptr == NULL )
- return;
- mptr = user2malloc_(uptr);
- memory_check(uptr, (mid=MID(mptr)), (mfile=MFILE(mptr)), (mline=MLINE(mptr)), file, line);
- if (malloc_watch && remove_warrant(mptr)==0 )
- memory_check(uptr, mid, mfile, mline, file, line);
-#ifdef FREED_CHAR
- if ( mptr!=NULL ) {
- size_t nbytes = -nsize1_(mptr);
- /* LINTED */
- (void)memset(mptr, FREED_CHAR, rbytes_(nbytes));
- }
-#endif
- free(mptr);
-}
-
-#ifdef MAX_FREE_DELAY_COUNT
-
-static void *free_delay[MAX_FREE_DELAY_COUNT];
-static int free_delay_pos = 0;
-
-static void
-delayed_free(void *uptr, const char* file, int line)
-{
- void *mptr;
- void *olduptr = free_delay[free_delay_pos];
- size_t nbytes;
- if ( uptr==NULL )
- return;
- mptr = user2malloc_(uptr);
- memory_check(uptr, MID(mptr), MFILE(mptr), MLINE(mptr), file, line);
- if ( olduptr!=NULL ) {
- actual_free(olduptr, file, line);
- }
- free_delay[free_delay_pos] = uptr;
- free_delay_pos++;
- free_delay_pos = free_delay_pos % MAX_FREE_DELAY_COUNT;
- nbytes = -user_nsize1_(uptr);
-#ifdef FREED_CHAR
- (void)memset(uptr, FREED_CHAR, (size_t)nbytes);
-#endif
-}
-
-static void
-delayed_free_all(const char *file, int line)
-{
- int i;
- for ( i=0; i< MAX_FREE_DELAY_COUNT; i++) {
- void *olduptr = free_delay[i];
- free_delay[i] = NULL;
- if ( olduptr!=NULL ) {
- actual_free(olduptr, file, line);
- }
- }
-}
-
-#endif
-
-void
-debug_free(void *uptr, const char *file, int line)
-{
- int mid = 0;
-
- if (uptr == NULL)
- memory_error((void *) NULL, "debug_free", mid, file, line, file, line);
-#ifdef MAX_FREE_DELAY_COUNT
- delayed_free(uptr, file, line);
-#else
- actual_free(uptr, file, line);
-#endif
-}
-
-/* This function calls malloc(). */
-void *
-debug_malloc(size_t nbytes, const char *file, int line)
-{
- void *mptr;
- void *uptr;
- int mid = id_counter;
-
- /*LINTED*/
- if ((int)nbytes <= 0)
- memory_error((void *) NULL, "debug_malloc", mid, file, line, file, line);
- /* LINTED */
- mptr = malloc(rbytes_(nbytes));
- if (mptr == NULL)
- memory_error((void *) NULL, "debug_malloc", mid, file, line, file, line);
- setup_space_and_issue_warrant(mptr, nbytes, file, line);
- uptr = malloc2user_(mptr);
-#ifdef ALLOC_CHAR
- (void)memset(uptr, ALLOC_CHAR, (size_t)nbytes);
-#endif
- return uptr;
-}
-
-void *
-debug_realloc(void *uptr, size_t nbytes, const char *file, int line)
-{
- void *mptr;
- void *oldmptr;
- void *newuptr;
- size_t oldnbytes;
- int mid = id_counter;
-
- oldmptr = user2malloc_(uptr);
- oldnbytes = 0;
- if ((int)nbytes <= 0)
- memory_error(oldmptr, "debug_realloc", mid, file, line, file, line);
- if (uptr != NULL) {
- memory_check(uptr, MID(oldmptr), MFILE(oldmptr), MLINE(oldmptr), file, line);
- oldnbytes = -user_nsize1_(uptr);
- if ( malloc_watch && remove_warrant(oldmptr)==0 )
- memory_check(uptr, MID(oldmptr), MFILE(oldmptr), MLINE(oldmptr), file, line);
- }
- if (uptr == NULL) {
- /* LINTED */
- mptr = malloc(rbytes_(nbytes));
- } else {
- /* LINTED */
- mptr = realloc(oldmptr, rbytes_(nbytes));
- }
- if (mptr == NULL)
- memory_error(oldmptr, "debug_realloc", mid, file, line, file, line);
- setup_space_and_issue_warrant(mptr, nbytes, file, line);
- newuptr = malloc2user_(mptr);
-#ifdef ALLOC_CHAR
- if (uptr == NULL)
- (void)memset(newuptr, ALLOC_CHAR, (size_t)nbytes);
- else if ( nbytes > oldnbytes )
- (void)memset(((char*)newuptr)+oldnbytes, ALLOC_CHAR, (size_t)nbytes-oldnbytes);
-#endif
- return newuptr;
-}
-
-/* This function calls calloc(). */
-void *
-debug_calloc(size_t nelem, size_t elsize, const char *file, int line)
-{
- void *mptr;
- size_t nbytes;
- int mid = id_counter;
-
- nbytes = nelem*elsize;
- /*LINTED*/
- if ((int)nbytes <= 0)
- memory_error((void *) NULL, "debug_calloc", mid, file, line, file, line);
- /* LINTED */
- mptr = calloc(rbytes_(nbytes),1);
- if (mptr == NULL)
- memory_error((void *) NULL, "debug_calloc", mid, file, line, file, line);
- setup_space_and_issue_warrant(mptr, nbytes, file, line);
- return malloc2user_(mptr);
-}
-
-/* This function replaces strdup(). */
-char *
-debug_strdup(const char *s1, const char *file, int line)
-{
- void *mptr;
- void *uptr;
- size_t nbytes;
- int mid = id_counter;
-
- if (s1 == NULL)
- memory_error((void *) NULL, "debug_strdup", mid, file, line, file, line);
- nbytes = strlen(s1)+1;
- /*LINTED*/
- if ((int)nbytes < 0)
- memory_error((void *) NULL, "debug_strdup", mid, file, line, file, line);
- /* LINTED */
- mptr = malloc(rbytes_(nbytes));
- if (mptr == NULL)
- memory_error((void *) NULL, "debug_strdup", mid, file, line, file, line);
- setup_space_and_issue_warrant(mptr, nbytes, file, line);
- uptr = malloc2user_(mptr);
- (void)strcpy((char*)uptr, s1);
- return (char*)uptr;
-}
-
-void
-debug_malloc_verify(const char *file, int line)
-{
- void *mptr;
-
-#ifdef MAX_FREE_DELAY_COUNT
- delayed_free_all(file,line);
-#endif
-
- if (!malloc_watch) {
- return;
- }
- mptr = first_warrant_mptr;
- if (mptr != NULL) {
- /* Check all this memory first */
- do {
- memory_check(malloc2user_(mptr), MID(mptr), MFILE(mptr), MLINE(mptr), file, line);
- mptr = warrant_link_(mptr);
- } while (mptr != NULL);
- }
-}
-
-/* Report outstanding space warrants to console. */
-void
-debug_malloc_police(const char *file, int line)
-{
- void *mptr;
-
-#ifdef MAX_FREE_DELAY_COUNT
- delayed_free_all(file,line);
-#endif
-
- if (!malloc_watch) {
- return;
- }
-
- mptr = first_warrant_mptr;
- if (mptr != NULL) {
- debug_malloc_verify(file, line);
- /* Now issue warrants */
- mptr = first_warrant_mptr;
- do {
- error_message("Outstanding space warrant: %p (%d bytes) allocated by %s at line %d, allocation #%d",
- mptr, -nsize1_(mptr), warrant_name_(mptr),
- warrant_line_(mptr), warrant_id_(mptr));
-
- mptr = warrant_link_(mptr);
- } while (mptr != NULL);
- }
-}
-
-#else
-
-void
-debug_malloc_verify(const char *file, int line)
-{
- file = file;
- line = line;
-}
-
-void
-debug_malloc_police(const char *file, int line)
-{
- file = file;
- line = line;
-}
-
-#endif
--- a/jdk/src/jdk.hprof.agent/share/native/libhprof/debug_malloc.h Thu Aug 20 12:29:58 2015 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,85 +0,0 @@
-/*
- * Copyright (c) 2004, 2012, Oracle and/or its affiliates. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * - Neither the name of Oracle nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
- * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/*
- * This source code is provided to illustrate the usage of a given feature
- * or technique and has been deliberately simplified. Additional steps
- * required for a production-quality application, such as security checks,
- * input validation and proper error handling, might not be present in
- * this sample code.
- */
-
-
-/* ***********************************************************************
- *
- * The source file debug_malloc.c should be included with your sources.
- *
- * The object file debug_malloc.o should be included with your object files.
- *
- * WARNING: Any memory allocattion from things like memalign(), valloc(),
- * or any memory not coming from these macros (malloc, realloc,
- * calloc, and strdup) will fail miserably.
- *
- * ***********************************************************************
- */
-
-#ifndef _DEBUG_MALLOC_H
-#define _DEBUG_MALLOC_H
-
-#ifdef DEBUG
-
-#include <stdlib.h>
-#include <string.h>
-
-/* Use THIS_FILE when it is available. */
-#ifndef THIS_FILE
- #define THIS_FILE __FILE__
-#endif
-
-/* The real functions behind the macro curtains. */
-
-void *debug_malloc(size_t, const char *, int);
-void *debug_realloc(void *, size_t, const char *, int);
-void *debug_calloc(size_t, size_t, const char *, int);
-char *debug_strdup(const char *, const char *, int);
-void debug_free(void *, const char *, int);
-
-#endif
-
-void debug_malloc_verify(const char*, int);
-#undef malloc_verify
-#define malloc_verify() debug_malloc_verify(THIS_FILE, __LINE__)
-
-void debug_malloc_police(const char*, int);
-#undef malloc_police
-#define malloc_police() debug_malloc_police(THIS_FILE, __LINE__)
-
-#endif
--- a/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof.h Thu Aug 20 12:29:58 2015 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,401 +0,0 @@
-/*
- * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * - Neither the name of Oracle nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
- * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/*
- * This source code is provided to illustrate the usage of a given feature
- * or technique and has been deliberately simplified. Additional steps
- * required for a production-quality application, such as security checks,
- * input validation and proper error handling, might not be present in
- * this sample code.
- */
-
-
-/* Primary hprof #include file, should be included by most if not
- * all hprof source files. Gives access to the global data structure
- * and all global macros, and everything declared in the #include
- * files of each of the source files.
- */
-
-#ifndef HPROF_H
-#define HPROF_H
-
-/* Standard C functions used throughout. */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <ctype.h>
-#include <string.h>
-#include <stddef.h>
-#include <stdarg.h>
-#include <limits.h>
-#include <time.h>
-#include <errno.h>
-
-/* General JVM/Java functions, types and macros. */
-
-#include <sys/types.h>
-#include "jni.h"
-#include "jvmti.h"
-#include "classfile_constants.h"
-#include "jvm_md.h"
-
-/* Macros to extract the upper and lower 32 bits of a jlong */
-
-#define jlong_high(a) ((jint)((a)>>32))
-#define jlong_low(a) ((jint)(a))
-#define jlong_to_jint(a) ((jint)(a))
-#define jint_to_jlong(a) ((jlong)(a))
-
-#define jlong_add(a, b) ((a) + (b))
-
-
-/* The type used to contain a generic 32bit "serial number". */
-
-typedef unsigned SerialNumber;
-
-/* How the options get to OnLoad: */
-
-#define AGENTNAME "hprof"
-#define XRUN "-Xrun" AGENTNAME
-#define AGENTLIB "-agentlib:" AGENTNAME
-
-/* Name of prelude file, found at runtime relative to java binary location */
-
-#define PRELUDE_FILE "jvm.hprof.txt"
-
-/* File I/O buffer size to be used with any file i/o operation */
-
-#define FILE_IO_BUFFER_SIZE (1024*64)
-
-/* Machine dependent functions. */
-
-#include "hprof_md.h"
-
-/* Table index types */
-
-typedef unsigned TableIndex;
-typedef TableIndex ClassIndex;
-typedef TableIndex FrameIndex;
-typedef TableIndex IoNameIndex;
-typedef TableIndex MonitorIndex;
-typedef TableIndex ObjectIndex;
-typedef TableIndex LoaderIndex;
-typedef TableIndex RefIndex;
-typedef TableIndex SiteIndex;
-typedef TableIndex StringIndex;
-typedef TableIndex TlsIndex;
-typedef TableIndex TraceIndex;
-
-/* Index for method tables in classes */
-
-typedef int MethodIndex;
-
-/* The different kinds of class status bits. */
-
-enum ClassStatus {
- CLASS_PREPARED = 0x00000001,
- CLASS_LOADED = 0x00000002,
- CLASS_UNLOADED = 0x00000004,
- CLASS_SPECIAL = 0x00000008,
- CLASS_IN_LOAD_LIST = 0x00000010,
- CLASS_SYSTEM = 0x00000020,
- CLASS_DUMPED = 0x00000040
-};
-typedef jint ClassStatus;
-
-/* The different kind of objects we track with heap=dump */
-
-typedef unsigned char ObjectKind;
-enum {
- OBJECT_NORMAL = 1,
- OBJECT_CLASS = 2,
- OBJECT_SYSTEM = 3,
- OBJECT_HPROF = 4,
- OBJECT_LOADER = 5
-};
-
-/* Used by site_write() when writing out the heap=sites data. */
-
-enum {
- SITE_DUMP_INCREMENTAL = 0x01,
- SITE_SORT_BY_ALLOC = 0x02,
- SITE_FORCE_GC = 0x04
-};
-
-/* Used to hold information about a field, and potentially a value too. */
-
-typedef struct FieldInfo {
- ClassIndex cnum;
- StringIndex name_index;
- StringIndex sig_index;
- unsigned short modifiers;
- unsigned char primType;
- unsigned char primSize;
-} FieldInfo;
-
-/* Used to hold information about a constant pool entry value for a class. */
-
-typedef struct ConstantPoolValue {
- unsigned constant_pool_index;
- StringIndex sig_index;
- jvalue value;
-} ConstantPoolValue;
-
-/* All machine independent functions */
-
-#include "hprof_error.h"
-#include "hprof_util.h"
-#include "hprof_blocks.h"
-#include "hprof_stack.h"
-#include "hprof_init.h"
-#include "hprof_table.h"
-#include "hprof_string.h"
-#include "hprof_class.h"
-#include "hprof_tracker.h"
-#include "hprof_frame.h"
-#include "hprof_monitor.h"
-#include "hprof_trace.h"
-#include "hprof_site.h"
-#include "hprof_event.h"
-#include "hprof_reference.h"
-#include "hprof_object.h"
-#include "hprof_loader.h"
-#include "hprof_tls.h"
-#include "hprof_check.h"
-#include "hprof_io.h"
-#include "hprof_listener.h"
-#include "hprof_cpu.h"
-#include "hprof_tag.h"
-
-/* Global data structure */
-
-struct LineTable;
-
-typedef struct {
-
- jvmtiEnv *jvmti; /* JVMTI env for this session */
- JavaVM *jvm; /* JavaVM* for this session */
- jint cachedJvmtiVersion; /* JVMTI version number */
-
- char *header; /* "JAVA PROFILE 1.0.[12]" */
- jboolean segmented; /* JNI_TRUE if 1.0.2 */
- jlong maxHeapSegment;
- jlong maxMemory;
-
- /* Option settings */
- char * options; /* option string copy */
- char * utf8_output_filename;/* file=filename */
- int net_port; /* net=hostname:port */
- char * net_hostname; /* net=hostname:port */
- char output_format; /* format=a|b */
- int max_trace_depth; /* depth=max_trace_depth */
- int prof_trace_depth; /* max_trace_depth or 2 (old) */
- int sample_interval; /* interval=sample_interval (ms) */
- double cutoff_point; /* cutoff=cutoff_point */
- jboolean cpu_sampling; /* cpu=samples|y */
- jboolean cpu_timing; /* cpu=times */
- jboolean old_timing_format; /* cpu=old (old) output format */
- jboolean heap_dump; /* heap=dump|all */
- jboolean alloc_sites; /* heap=sites|all */
- jboolean thread_in_traces; /* thread=y|n */
- jboolean lineno_in_traces; /* lineno=y|n */
- jboolean dump_on_exit; /* doe=y|n */
- jboolean micro_state_accounting; /* msa=y|n */
- jboolean force_output; /* force=y|n */
- jboolean monitor_tracing; /* monitor=y|n */
- jboolean gc_okay; /* gc_okay=y|n (Not used) */
-
- unsigned logflags; /* logflags=bitmask */
-
- #define DEBUGFLAG_UNPREPARED_CLASSES 0x001
- unsigned debugflags; /* debugflags=bitmask */
-
- jboolean coredump; /* coredump=y|n */
- jboolean errorexit; /* errorexit=y|n */
- jboolean pause; /* pause=y|n */
- jboolean debug; /* debug=y|n */
- jboolean verbose; /* verbose=y|n */
- jboolean primfields; /* primfields=y|n */
- jboolean primarrays; /* primarrays=y|n */
- jint experiment; /* X=NUMBER */
-
- int fd; /* file or socket (net=addr). */
- jboolean socket; /* True if fd is a socket (net=addr). */
- jboolean bci; /* True if any kind of BCI being done */
- jboolean obj_watch; /* True if bci and watching allocs */
-
- int bci_counter; /* Class BCI counter */
-
- int heap_fd;
- char *output_filename; /* file=filename */
- char *heapfilename;
-
- int check_fd;
- char *checkfilename;
-
- volatile jboolean dump_in_process; /* Dump in process */
- volatile jboolean jvm_initializing; /* VMInit happening */
- volatile jboolean jvm_initialized; /* VMInit happened */
- volatile jboolean jvm_shut_down; /* VMDeath happened */
- jboolean vm_death_callback_active; /* VMDeath happening */
-
- /* Stack of objects freed during GC */
- Stack * object_free_stack;
- jrawMonitorID object_free_lock;
-
- /* Lock for debug_malloc() */
- jrawMonitorID debug_malloc_lock;
-
- /* Count of classes that JVMTI thinks are active */
- jint class_count;
-
- /* Used to track callbacks for VM_DEATH */
- jrawMonitorID callbackBlock;
- jrawMonitorID callbackLock;
- jint active_callbacks;
-
- /* Running totals on all bytes allocated */
- jlong total_alloced_bytes;
- jlong total_alloced_instances;
- jint total_live_bytes;
- jint total_live_instances;
-
- /* Running total on all time spent in GC (very rough estimate) */
- jlong gc_start_time;
- jlong time_in_gc;
-
- /* Global Data access Lock */
- jrawMonitorID data_access_lock;
-
- /* Global Dump lock */
- jrawMonitorID dump_lock;
-
- /* Milli-second clock when hprof onload started */
- jlong micro_sec_ticks;
-
- /* Thread class (for starting agent threads) */
- ClassIndex thread_cnum;
-
- /* Agent threads started information */
- jboolean listener_loop_running;
- jrawMonitorID listener_loop_lock;
- jboolean cpu_loop_running;
- jrawMonitorID cpu_loop_lock;
- jrawMonitorID cpu_sample_lock; /* cpu=samples loop */
- jint gc_finish; /* Count of GC finish events */
- jboolean gc_finish_active; /* True if thread active */
- jboolean gc_finish_stop_request; /* True if we want it to stop */
- jrawMonitorID gc_finish_lock;
-
- jboolean pause_cpu_sampling; /* temp pause in cpu sampling */
-
- /* Output buffer, position, size, and position in dump if reading */
- char * write_buffer;
- int write_buffer_index;
- int write_buffer_size;
- char * heap_buffer;
- int heap_buffer_index;
- int heap_buffer_size;
- jlong heap_last_tag_position;
- jlong heap_write_count;
- char * check_buffer;
- int check_buffer_index;
- int check_buffer_size;
-
- /* Serial number counters for tables (see hprof_table.c), classes,
- * tls (thread local storage), and traces.
- */
- SerialNumber table_serial_number_start;
- SerialNumber class_serial_number_start;
- SerialNumber thread_serial_number_start;
- SerialNumber trace_serial_number_start;
- SerialNumber object_serial_number_start;
- SerialNumber frame_serial_number_start;
- SerialNumber gref_serial_number_start;
-
- SerialNumber table_serial_number_counter;
- SerialNumber class_serial_number_counter;
- SerialNumber thread_serial_number_counter;
- SerialNumber trace_serial_number_counter;
- SerialNumber object_serial_number_counter;
- SerialNumber frame_serial_number_counter;
- SerialNumber gref_serial_number_counter;
-
- /* The methodID for the Object <init> method. */
- jmethodID object_init_method;
-
- /* Keeping track of the tracker class and it's methods */
- volatile jint tracking_engaged; /* !=0 means it's on */
- ClassIndex tracker_cnum;
- int tracker_method_count;
- struct {
- StringIndex name; /* String index for name */
- StringIndex sig; /* String index for signature */
- jmethodID method; /* Method ID */
- } tracker_methods[12]; /* MAX 12 Tracker class methods */
-
- /* Index to some common items */
- LoaderIndex system_loader;
- SerialNumber unknown_thread_serial_num;
- TraceIndex system_trace_index;
- SiteIndex system_object_site_index;
- jint system_class_size;
- TraceIndex hprof_trace_index;
- SiteIndex hprof_site_index;
-
- /* Tables for strings, classes, sites, etc. */
- struct LookupTable * string_table;
- struct LookupTable * ioname_table;
- struct LookupTable * class_table;
- struct LookupTable * site_table;
- struct LookupTable * object_table;
- struct LookupTable * reference_table;
- struct LookupTable * frame_table;
- struct LookupTable * trace_table;
- struct LookupTable * monitor_table;
- struct LookupTable * tls_table;
- struct LookupTable * loader_table;
-
- /* Handles to java_crw_demo library */
- void * java_crw_demo_library;
- void * java_crw_demo_function;
- void * java_crw_demo_classname_function;
-
- /* Indication that the agent has been loaded */
- jboolean isLoaded;
-
-} GlobalData;
-
-/* This should be the only 'extern' in the library (not exported). */
-
-extern GlobalData * gdata;
-
-#endif
--- a/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_b_spec.h Thu Aug 20 12:29:58 2015 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,371 +0,0 @@
-/*
- * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * - Neither the name of Oracle nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
- * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef HPROF_B_SPEC_H
-#define HPROF_B_SPEC_H
-
-/* Hprof binary format enums and spec. */
-
-/* Need to #define or typedef HprofId before including this file.
- * hprof used ObjectIndex or 4 bytes, but it can be 4 or 8 byte type.
- */
-
-/* -------------------------------------------------------------------- */
-/* -------------------------------------------------------------------- */
-/* -------------------------------------------------------------------- */
-
-/*
- * hprof binary format: (result either written to a file or sent over
- * the network).
- *
- * WARNING: This format is still under development, and is subject to
- * change without notice.
- *
- * header "JAVA PROFILE 1.0.1" or "JAVA PROFILE 1.0.2" (0-terminated)
- * u4 size of identifiers. Identifiers are used to represent
- * UTF8 strings, objects, stack traces, etc. They usually
- * have the same size as host pointers. For example, on
- * Solaris and Win32, the size is 4.
- * u4 high word
- * u4 low word number of milliseconds since 0:00 GMT, 1/1/70
- * [record]* a sequence of records.
- */
-
-/*
- * Record format:
- *
- * u1 a TAG denoting the type of the record
- * u4 number of *microseconds* since the time stamp in the
- * header. (wraps around in a little more than an hour)
- * u4 number of bytes *remaining* in the record. Note that
- * this number excludes the tag and the length field itself.
- * [u1]* BODY of the record (a sequence of bytes)
- */
-
-/*
- * The following TAGs are supported:
- *
- * TAG BODY notes
- *----------------------------------------------------------
- * HPROF_UTF8 a UTF8-encoded name
- *
- * id name ID
- * [u1]* UTF8 characters (no trailing zero)
- *
- * HPROF_LOAD_CLASS a newly loaded class
- *
- * u4 class serial number (> 0)
- * id class object ID
- * u4 stack trace serial number
- * id class name ID
- *
- * HPROF_UNLOAD_CLASS an unloading class
- *
- * u4 class serial_number
- *
- * HPROF_FRAME a Java stack frame
- *
- * id stack frame ID
- * id method name ID
- * id method signature ID
- * id source file name ID
- * u4 class serial number
- * i4 line number. >0: normal
- * -1: unknown
- * -2: compiled method
- * -3: native method
- *
- * HPROF_TRACE a Java stack trace
- *
- * u4 stack trace serial number
- * u4 thread serial number
- * u4 number of frames
- * [id]* stack frame IDs
- *
- *
- * HPROF_ALLOC_SITES a set of heap allocation sites, obtained after GC
- *
- * u2 flags 0x0001: incremental vs. complete
- * 0x0002: sorted by allocation vs. live
- * 0x0004: whether to force a GC
- * u4 cutoff ratio
- * u4 total live bytes
- * u4 total live instances
- * u8 total bytes allocated
- * u8 total instances allocated
- * u4 number of sites that follow
- * [u1 is_array: 0: normal object
- * 2: object array
- * 4: boolean array
- * 5: char array
- * 6: float array
- * 7: double array
- * 8: byte array
- * 9: short array
- * 10: int array
- * 11: long array
- * u4 class serial number (may be zero during startup)
- * u4 stack trace serial number
- * u4 number of bytes alive
- * u4 number of instances alive
- * u4 number of bytes allocated
- * u4]* number of instance allocated
- *
- * HPROF_START_THREAD a newly started thread.
- *
- * u4 thread serial number (> 0)
- * id thread object ID
- * u4 stack trace serial number
- * id thread name ID
- * id thread group name ID
- * id thread group parent name ID
- *
- * HPROF_END_THREAD a terminating thread.
- *
- * u4 thread serial number
- *
- * HPROF_HEAP_SUMMARY heap summary
- *
- * u4 total live bytes
- * u4 total live instances
- * u8 total bytes allocated
- * u8 total instances allocated
- *
- * HPROF_HEAP_DUMP or HPROF_HEAP_DUMP_SEGMENT denote a heap dump
- *
- * [heap dump sub-records]*
- *
- * There are four kinds of heap dump sub-records:
- *
- * u1 sub-record type
- *
- * HPROF_GC_ROOT_UNKNOWN unknown root
- *
- * id object ID
- *
- * HPROF_GC_ROOT_THREAD_OBJ thread object
- *
- * id thread object ID (may be 0 for a
- * thread newly attached through JNI)
- * u4 thread sequence number
- * u4 stack trace sequence number
- *
- * HPROF_GC_ROOT_JNI_GLOBAL JNI global ref root
- *
- * id object ID
- * id JNI global ref ID
- *
- * HPROF_GC_ROOT_JNI_LOCAL JNI local ref
- *
- * id object ID
- * u4 thread serial number
- * u4 frame # in stack trace (-1 for empty)
- *
- * HPROF_GC_ROOT_JAVA_FRAME Java stack frame
- *
- * id object ID
- * u4 thread serial number
- * u4 frame # in stack trace (-1 for empty)
- *
- * HPROF_GC_ROOT_NATIVE_STACK Native stack
- *
- * id object ID
- * u4 thread serial number
- *
- * HPROF_GC_ROOT_STICKY_CLASS System class
- *
- * id object ID
- *
- * HPROF_GC_ROOT_THREAD_BLOCK Reference from thread block
- *
- * id object ID
- * u4 thread serial number
- *
- * HPROF_GC_ROOT_MONITOR_USED Busy monitor
- *
- * id object ID
- *
- * HPROF_GC_CLASS_DUMP dump of a class object
- *
- * id class object ID
- * u4 stack trace serial number
- * id super class object ID
- * id class loader object ID
- * id signers object ID
- * id protection domain object ID
- * id reserved
- * id reserved
- *
- * u4 instance size (in bytes)
- *
- * u2 size of constant pool
- * [u2, constant pool index,
- * ty, type
- * 2: object
- * 4: boolean
- * 5: char
- * 6: float
- * 7: double
- * 8: byte
- * 9: short
- * 10: int
- * 11: long
- * vl]* and value
- *
- * u2 number of static fields
- * [id, static field name,
- * ty, type,
- * vl]* and value
- *
- * u2 number of inst. fields (not inc. super)
- * [id, instance field name,
- * ty]* type
- *
- * HPROF_GC_INSTANCE_DUMP dump of a normal object
- *
- * id object ID
- * u4 stack trace serial number
- * id class object ID
- * u4 number of bytes that follow
- * [vl]* instance field values (class, followed
- * by super, super's super ...)
- *
- * HPROF_GC_OBJ_ARRAY_DUMP dump of an object array
- *
- * id array object ID
- * u4 stack trace serial number
- * u4 number of elements
- * id array class ID
- * [id]* elements
- *
- * HPROF_GC_PRIM_ARRAY_DUMP dump of a primitive array
- *
- * id array object ID
- * u4 stack trace serial number
- * u4 number of elements
- * u1 element type
- * 4: boolean array
- * 5: char array
- * 6: float array
- * 7: double array
- * 8: byte array
- * 9: short array
- * 10: int array
- * 11: long array
- * [u1]* elements
- *
- * HPROF_HEAP_DUMP_END terminates series of heap dump segments
- *
- * HPROF_CPU_SAMPLES a set of sample traces of running threads
- *
- * u4 total number of samples
- * u4 # of traces
- * [u4 # of samples
- * u4]* stack trace serial number
- *
- * HPROF_CONTROL_SETTINGS the settings of on/off switches
- *
- * u4 0x00000001: alloc traces on/off
- * 0x00000002: cpu sampling on/off
- * u2 stack trace depth
- *
- */
-
-typedef enum HprofTag {
- HPROF_UTF8 = 0x01,
- HPROF_LOAD_CLASS = 0x02,
- HPROF_UNLOAD_CLASS = 0x03,
- HPROF_FRAME = 0x04,
- HPROF_TRACE = 0x05,
- HPROF_ALLOC_SITES = 0x06,
- HPROF_HEAP_SUMMARY = 0x07,
- HPROF_START_THREAD = 0x0A,
- HPROF_END_THREAD = 0x0B,
- HPROF_HEAP_DUMP = 0x0C,
- HPROF_HEAP_DUMP_SEGMENT = 0x1C, /* 1.0.2 only */
- HPROF_HEAP_DUMP_END = 0x2C, /* 1.0.2 only */
- HPROF_CPU_SAMPLES = 0x0D,
- HPROF_CONTROL_SETTINGS = 0x0E
-} HprofTag;
-
-/*
- * Heap dump constants
- */
-
-typedef enum HprofGcTag {
- HPROF_GC_ROOT_UNKNOWN = 0xFF,
- HPROF_GC_ROOT_JNI_GLOBAL = 0x01,
- HPROF_GC_ROOT_JNI_LOCAL = 0x02,
- HPROF_GC_ROOT_JAVA_FRAME = 0x03,
- HPROF_GC_ROOT_NATIVE_STACK = 0x04,
- HPROF_GC_ROOT_STICKY_CLASS = 0x05,
- HPROF_GC_ROOT_THREAD_BLOCK = 0x06,
- HPROF_GC_ROOT_MONITOR_USED = 0x07,
- HPROF_GC_ROOT_THREAD_OBJ = 0x08,
- HPROF_GC_CLASS_DUMP = 0x20,
- HPROF_GC_INSTANCE_DUMP = 0x21,
- HPROF_GC_OBJ_ARRAY_DUMP = 0x22,
- HPROF_GC_PRIM_ARRAY_DUMP = 0x23
-} HprofGcTag;
-
-enum HprofType {
- HPROF_ARRAY_OBJECT = 1,
- HPROF_NORMAL_OBJECT = 2,
- HPROF_BOOLEAN = 4,
- HPROF_CHAR = 5,
- HPROF_FLOAT = 6,
- HPROF_DOUBLE = 7,
- HPROF_BYTE = 8,
- HPROF_SHORT = 9,
- HPROF_INT = 10,
- HPROF_LONG = 11
-};
-typedef unsigned char HprofType;
-
-#define HPROF_TYPE_SIZES \
- { \
- /*Object?*/ sizeof(HprofId), \
- /*Object?*/ sizeof(HprofId), \
- /*Array*/ sizeof(HprofId), \
- /*Object?*/ sizeof(HprofId), \
- /*jboolean*/ 1, \
- /*jchar*/ 2, \
- /*jfloat*/ 4, \
- /*jdouble*/ 8, \
- /*jbyte*/ 1, \
- /*jshort*/ 2, \
- /*jint*/ 4, \
- /*jlong*/ 8 \
- }
-
-#define HPROF_TYPE_IS_PRIMITIVE(ty) ((ty)>=HPROF_BOOLEAN)
-
-#endif
--- a/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_blocks.c Thu Aug 20 12:29:58 2015 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,163 +0,0 @@
-/*
- * Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * - Neither the name of Oracle nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
- * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/*
- * This source code is provided to illustrate the usage of a given feature
- * or technique and has been deliberately simplified. Additional steps
- * required for a production-quality application, such as security checks,
- * input validation and proper error handling, might not be present in
- * this sample code.
- */
-
-
-/* Allocations from large blocks, no individual free's */
-
-#include "hprof.h"
-
-/*
- * This file contains some allocation code that allows you
- * to have space allocated via larger blocks of space.
- * The only free allowed is of all the blocks and all the elements.
- * Elements can be of different alignments and fixed or variable sized.
- * The space allocated never moves.
- *
- */
-
-/* Get the real size allocated based on alignment and bytes needed */
-static int
-real_size(int alignment, int nbytes)
-{
- if ( alignment > 1 ) {
- int wasted;
-
- wasted = alignment - ( nbytes % alignment );
- if ( wasted != alignment ) {
- nbytes += wasted;
- }
- }
- return nbytes;
-}
-
-/* Add a new current_block to the Blocks* chain, adjust size if nbytes big. */
-static void
-add_block(Blocks *blocks, int nbytes)
-{
- int header_size;
- int block_size;
- BlockHeader *block_header;
-
- HPROF_ASSERT(blocks!=NULL);
- HPROF_ASSERT(nbytes>0);
-
- header_size = real_size(blocks->alignment, sizeof(BlockHeader));
- block_size = blocks->elem_size*blocks->population;
- if ( nbytes > block_size ) {
- block_size = real_size(blocks->alignment, nbytes);
- }
- block_header = (BlockHeader*)HPROF_MALLOC(block_size+header_size);
- block_header->next = NULL;
- block_header->bytes_left = block_size;
- block_header->next_pos = header_size;
-
- /* Link in new block */
- if ( blocks->current_block != NULL ) {
- blocks->current_block->next = block_header;
- }
- blocks->current_block = block_header;
- if ( blocks->first_block == NULL ) {
- blocks->first_block = block_header;
- }
-}
-
-/* Initialize a new Blocks */
-Blocks *
-blocks_init(int alignment, int elem_size, int population)
-{
- Blocks *blocks;
-
- HPROF_ASSERT(alignment>0);
- HPROF_ASSERT(elem_size>0);
- HPROF_ASSERT(population>0);
-
- blocks = (Blocks*)HPROF_MALLOC(sizeof(Blocks));
- blocks->alignment = alignment;
- blocks->elem_size = elem_size;
- blocks->population = population;
- blocks->first_block = NULL;
- blocks->current_block = NULL;
- return blocks;
-}
-
-/* Allocate bytes from a Blocks area. */
-void *
-blocks_alloc(Blocks *blocks, int nbytes)
-{
- BlockHeader *block;
- int pos;
- void *ptr;
-
- HPROF_ASSERT(blocks!=NULL);
- HPROF_ASSERT(nbytes>=0);
- if ( nbytes == 0 ) {
- return NULL;
- }
-
- block = blocks->current_block;
- nbytes = real_size(blocks->alignment, nbytes);
- if ( block == NULL || block->bytes_left < nbytes ) {
- add_block(blocks, nbytes);
- block = blocks->current_block;
- }
- pos = block->next_pos;
- ptr = (void*)(((char*)block)+pos);
- block->next_pos += nbytes;
- block->bytes_left -= nbytes;
- return ptr;
-}
-
-/* Terminate the Blocks */
-void
-blocks_term(Blocks *blocks)
-{
- BlockHeader *block;
-
- HPROF_ASSERT(blocks!=NULL);
-
- block = blocks->first_block;
- while ( block != NULL ) {
- BlockHeader *next_block;
-
- next_block = block->next;
- HPROF_FREE(block);
- block = next_block;
- }
- HPROF_FREE(blocks);
-}
--- a/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_blocks.h Thu Aug 20 12:29:58 2015 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,62 +0,0 @@
-/*
- * Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * - Neither the name of Oracle nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
- * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/*
- * This source code is provided to illustrate the usage of a given feature
- * or technique and has been deliberately simplified. Additional steps
- * required for a production-quality application, such as security checks,
- * input validation and proper error handling, might not be present in
- * this sample code.
- */
-
-
-#ifndef HPROF_BLOCKS_H
-#define HPROF_BLOCKS_H
-
-typedef struct BlockHeader {
- struct BlockHeader *next;
- int bytes_left;
- int next_pos;
-} BlockHeader;
-
-typedef struct Blocks {
- BlockHeader *first_block; /* Pointer to first BlockHeader */
- BlockHeader *current_block; /* Pointer to current BlockHeader */
- int alignment; /* Data alignment, 1, 2, 4, 8, 16 */
- int elem_size; /* Size in bytes, ==1 means variable sizes */
- int population; /* Number of elements to allow for per Block */
-} Blocks;
-
-Blocks * blocks_init(int alignment, int elem_size, int population);
-void * blocks_alloc(Blocks *blocks, int nbytes);
-void blocks_term(Blocks *blocks);
-
-#endif
--- a/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_check.c Thu Aug 20 12:29:58 2015 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,1152 +0,0 @@
-/*
- * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * - Neither the name of Oracle nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
- * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/*
- * This source code is provided to illustrate the usage of a given feature
- * or technique and has been deliberately simplified. Additional steps
- * required for a production-quality application, such as security checks,
- * input validation and proper error handling, might not be present in
- * this sample code.
- */
-
-
-/* Functionality for checking hprof format=b output. */
-
-/* ONLY used with logflags=4. */
-
-/* Verifies and write a verbose textual version of a format=b file.
- * Textual output file is gdata->checkfilename, fd is gdata->check_fd.
- * Buffer is in gdata too, see gdata->check* variables.
- * Could probably be isolated to a separate library or utility.
- */
-
-#include "hprof.h"
-
-typedef TableIndex HprofId;
-
-#include "hprof_b_spec.h"
-
-static int type_size[ /*HprofType*/ ] = HPROF_TYPE_SIZES;
-
-/* For map from HPROF_UTF8 to a string */
-typedef struct UmapInfo {
- char *str;
-} UmapInfo;
-
-/* Field information */
-typedef struct Finfo {
- HprofId id;
- HprofType ty;
-} Finfo;
-
-/* Class information map from class ID (ClassIndex) to class information */
-typedef struct CmapInfo {
- int max_finfo;
- int n_finfo;
- Finfo *finfo;
- int inst_size;
- HprofId sup;
-} CmapInfo;
-
-/* Read raw bytes from the file image, update the pointer */
-static void
-read_raw(unsigned char **pp, unsigned char *buf, int len)
-{
- while ( len > 0 ) {
- *buf = **pp;
- buf++;
- (*pp)++;
- len--;
- }
-}
-
-/* Read various sized elements, properly converted from big to right endian.
- * File will contain big endian format.
- */
-static unsigned
-read_u1(unsigned char **pp)
-{
- unsigned char b;
-
- read_raw(pp, &b, 1);
- return b;
-}
-static unsigned
-read_u2(unsigned char **pp)
-{
- unsigned short s;
-
- read_raw(pp, (void*)&s, 2);
- return md_htons(s);
-}
-static unsigned
-read_u4(unsigned char **pp)
-{
- unsigned int u;
-
- read_raw(pp, (void*)&u, 4);
- return md_htonl(u);
-}
-static jlong
-read_u8(unsigned char **pp)
-{
- unsigned int high;
- unsigned int low;
- jlong x;
-
- high = read_u4(pp);
- low = read_u4(pp);
- x = high;
- x = (x << 32) | low;
- return x;
-}
-static HprofId
-read_id(unsigned char **pp)
-{
- return (HprofId)read_u4(pp);
-}
-
-/* System error routine */
-static void
-system_error(const char *system_call, int rc, int errnum)
-{
- char buf[256];
- char details[256];
-
- details[0] = 0;
- if ( errnum != 0 ) {
- md_system_error(details, (int)sizeof(details));
- } else if ( rc >= 0 ) {
- (void)strcpy(details,"Only part of buffer processed");
- }
- if ( details[0] == 0 ) {
- (void)strcpy(details,"Unknown system error condition");
- }
- (void)md_snprintf(buf, sizeof(buf), "System %s failed: %s\n",
- system_call, details);
- HPROF_ERROR(JNI_TRUE, buf);
-}
-
-/* Write to a fd */
-static void
-system_write(int fd, void *buf, int len)
-{
- int res;
-
- HPROF_ASSERT(fd>=0);
- res = md_write(fd, buf, len);
- if (res < 0 || res!=len) {
- system_error("write", res, errno);
- }
-}
-
-/* Flush check buffer */
-static void
-check_flush(void)
-{
- if ( gdata->check_fd < 0 ) {
- return;
- }
- if (gdata->check_buffer_index) {
- system_write(gdata->check_fd, gdata->check_buffer, gdata->check_buffer_index);
- gdata->check_buffer_index = 0;
- }
-}
-
-/* Read out a given typed element */
-static jvalue
-read_val(unsigned char **pp, HprofType ty)
-{
- jvalue val;
- static jvalue empty_val;
-
- val = empty_val;
- switch ( ty ) {
- case 0:
- case HPROF_ARRAY_OBJECT:
- case HPROF_NORMAL_OBJECT:
- val.i = read_id(pp);
- break;
- case HPROF_BYTE:
- case HPROF_BOOLEAN:
- val.b = read_u1(pp);
- break;
- case HPROF_CHAR:
- case HPROF_SHORT:
- val.s = read_u2(pp);
- break;
- case HPROF_FLOAT:
- case HPROF_INT:
- val.i = read_u4(pp);
- break;
- case HPROF_DOUBLE:
- case HPROF_LONG:
- val.j = read_u8(pp);
- break;
- default:
- HPROF_ERROR(JNI_TRUE, "bad type number");
- break;
- }
- return val;
-}
-
-/* Move arbitrary byte stream into gdata->check_fd */
-static void
-check_raw(void *buf, int len)
-{
- if ( gdata->check_fd < 0 ) {
- return;
- }
-
- if ( len <= 0 ) {
- return;
- }
-
- if (gdata->check_buffer_index + len > gdata->check_buffer_size) {
- check_flush();
- if (len > gdata->check_buffer_size) {
- system_write(gdata->check_fd, buf, len);
- return;
- }
- }
- (void)memcpy(gdata->check_buffer + gdata->check_buffer_index, buf, len);
- gdata->check_buffer_index += len;
-}
-
-/* Printf for gdata->check_fd */
-static void
-check_printf(char *fmt, ...)
-{
- char buf[1024];
- va_list args;
-
- if ( gdata->check_fd < 0 ) {
- return;
- }
-
- va_start(args, fmt);
- (void)md_vsnprintf(buf, sizeof(buf), fmt, args);
- buf[sizeof(buf)-1] = 0;
- check_raw(buf, (int)strlen(buf));
- va_end(args);
-}
-
-/* Printf of an element for gdata->check_fd */
-static void
-check_printf_val(HprofType ty, jvalue val, int long_form)
-{
- jint low;
- jint high;
-
- switch ( ty ) {
- case HPROF_ARRAY_OBJECT:
- check_printf("0x%08x", val.i);
- break;
- case HPROF_NORMAL_OBJECT:
- check_printf("0x%08x", val.i);
- break;
- case HPROF_BOOLEAN:
- check_printf("0x%02x", val.b);
- break;
- case HPROF_CHAR:
- if ( long_form ) {
- if ( val.s < 0 || val.s > 0x7f || !isprint(val.s) ) {
- check_printf("0x%04x", val.s);
- } else {
- check_printf("0x%04x(%c)", val.s, val.s);
- }
- } else {
- if ( val.s < 0 || val.s > 0x7f || !isprint(val.s) ) {
- check_printf("\\u%04x", val.s);
- } else {
- check_printf("%c", val.s);
- }
- }
- break;
- case HPROF_FLOAT:
- low = jlong_low(val.j);
- check_printf("0x%08x(%f)", low, (double)val.f);
- break;
- case HPROF_DOUBLE:
- high = jlong_high(val.j);
- low = jlong_low(val.j);
- check_printf("0x%08x%08x(%f)", high, low, val.d);
- break;
- case HPROF_BYTE:
- check_printf("0x%02x", val.b);
- break;
- case HPROF_SHORT:
- check_printf("0x%04x", val.s);
- break;
- case HPROF_INT:
- check_printf("0x%08x", val.i);
- break;
- case HPROF_LONG:
- high = jlong_high(val.j);
- low = jlong_low(val.j);
- check_printf("0x%08x%08x", high, low);
- break;
- }
-}
-
-/* Printf of a string for gdata->check_fd */
-static void
-check_printf_str(char *str)
-{
- int len;
- int i;
-
- if ( str == NULL ) {
- check_printf("<null>");
- }
- check_printf("\"");
- len = (int)strlen(str);
- for (i = 0; i < len; i++) {
- unsigned char c;
- c = str[i];
- if ( isprint(c) ) {
- check_printf("%c", c);
- } else {
- check_printf("\\x%02x", c);
- }
- }
- check_printf("\"");
-}
-
-/* Printf of a utf8 id for gdata->check_fd */
-static void
-check_print_utf8(struct LookupTable *utab, char *prefix, HprofId id)
-{
- TableIndex uindex;
-
- if ( id == 0 ) {
- check_printf("%s0x%x", prefix, id);
- } else {
- uindex = table_find_entry(utab, &id, sizeof(id));
- if ( uindex == 0 ) {
- check_printf("%s0x%x", prefix, id);
- } else {
- UmapInfo *umap;
-
- umap = (UmapInfo*)table_get_info(utab, uindex);
- HPROF_ASSERT(umap!=NULL);
- HPROF_ASSERT(umap->str!=NULL);
- check_printf("%s0x%x->", prefix, id);
- check_printf_str(umap->str);
- }
- }
-}
-
-/* Add a instance field information to this cmap. */
-static void
-add_inst_field_to_cmap(CmapInfo *cmap, HprofId id, HprofType ty)
-{
- int i;
-
- HPROF_ASSERT(cmap!=NULL);
- i = cmap->n_finfo++;
- if ( i+1 >= cmap->max_finfo ) {
- int osize;
- Finfo *new_finfo;
-
- osize = cmap->max_finfo;
- cmap->max_finfo += 12;
- new_finfo = (Finfo*)HPROF_MALLOC(cmap->max_finfo*(int)sizeof(Finfo));
- (void)memset(new_finfo,0,cmap->max_finfo*(int)sizeof(Finfo));
- if ( i == 0 ) {
- cmap->finfo = new_finfo;
- } else {
- (void)memcpy(new_finfo,cmap->finfo,osize*(int)sizeof(Finfo));
- HPROF_FREE(cmap->finfo);
- cmap->finfo = new_finfo;
- }
- }
- cmap->finfo[i].id = id;
- cmap->finfo[i].ty = ty;
-}
-
-/* LookupTable callback for cmap entry cleanup */
-static void
-cmap_cleanup(TableIndex i, void *key_ptr, int key_len, void*info, void*data)
-{
- CmapInfo *cmap = info;
-
- if ( cmap == NULL ) {
- return;
- }
- if ( cmap->finfo != NULL ) {
- HPROF_FREE(cmap->finfo);
- cmap->finfo = NULL;
- }
-}
-
-/* Case label for a switch on hprof heap dump elements */
-#define CASE_HEAP(name) case name: label = #name;
-
-/* Given the heap dump data and the utf8 map, check/write the heap dump. */
-static int
-check_heap_tags(struct LookupTable *utab, unsigned char *pstart, int nbytes)
-{
- int nrecords;
- unsigned char *p;
- unsigned char *psave;
- struct LookupTable *ctab;
- CmapInfo cmap;
- char *label;
- unsigned tag;
- HprofType ty;
- HprofId id, id2, fr, sup;
- int num_elements;
- int num_bytes;
- SerialNumber trace_serial_num;
- SerialNumber thread_serial_num;
- int npos;
- int i;
- int inst_size;
-
- ctab = table_initialize("temp ctab", 64, 64, 512, sizeof(CmapInfo));
-
- /* First pass over heap records just fills in the CmapInfo table */
- nrecords = 0;
- p = pstart;
- while ( p < (pstart+nbytes) ) {
- nrecords++;
- /*LINTED*/
- npos = (int)(p - pstart);
- tag = read_u1(&p);
- switch ( tag ) {
- CASE_HEAP(HPROF_GC_ROOT_UNKNOWN)
- id = read_id(&p);
- break;
- CASE_HEAP(HPROF_GC_ROOT_JNI_GLOBAL)
- id = read_id(&p);
- id2 = read_id(&p);
- break;
- CASE_HEAP(HPROF_GC_ROOT_JNI_LOCAL)
- id = read_id(&p);
- thread_serial_num = read_u4(&p);
- fr = read_u4(&p);
- break;
- CASE_HEAP(HPROF_GC_ROOT_JAVA_FRAME)
- id = read_id(&p);
- thread_serial_num = read_u4(&p);
- fr = read_u4(&p);
- break;
- CASE_HEAP(HPROF_GC_ROOT_NATIVE_STACK)
- id = read_id(&p);
- thread_serial_num = read_u4(&p);
- break;
- CASE_HEAP(HPROF_GC_ROOT_STICKY_CLASS)
- id = read_id(&p);
- break;
- CASE_HEAP(HPROF_GC_ROOT_THREAD_BLOCK)
- id = read_id(&p);
- thread_serial_num = read_u4(&p);
- break;
- CASE_HEAP(HPROF_GC_ROOT_MONITOR_USED)
- id = read_id(&p);
- break;
- CASE_HEAP(HPROF_GC_ROOT_THREAD_OBJ)
- id = read_id(&p);
- thread_serial_num = read_u4(&p);
- trace_serial_num = read_u4(&p);
- break;
- CASE_HEAP(HPROF_GC_CLASS_DUMP)
- (void)memset((void*)&cmap, 0, sizeof(cmap));
- id = read_id(&p);
- trace_serial_num = read_u4(&p);
- {
- HprofId ld, si, pr, re1, re2;
-
- sup = read_id(&p);
- ld = read_id(&p);
- si = read_id(&p);
- pr = read_id(&p);
- re1 = read_id(&p);
- re2 = read_id(&p);
- cmap.sup = sup;
- }
- inst_size = read_u4(&p);
- cmap.inst_size = inst_size;
- num_elements = read_u2(&p);
- for(i=0; i<num_elements; i++) {
- (void)read_u2(&p);
- ty = read_u1(&p);
- (void)read_val(&p, ty);
- }
- num_elements = read_u2(&p);
- for(i=0; i<num_elements; i++) {
- (void)read_id(&p);
- ty = read_u1(&p);
- (void)read_val(&p, ty);
- }
- num_elements = read_u2(&p);
- for(i=0; i<num_elements; i++) {
- HprofType ty;
- HprofId id;
-
- id = read_id(&p);
- ty = read_u1(&p);
- add_inst_field_to_cmap(&cmap, id, ty);
- }
- (void)table_create_entry(ctab, &id, sizeof(id), &cmap);
- break;
- CASE_HEAP(HPROF_GC_INSTANCE_DUMP)
- id = read_id(&p);
- trace_serial_num = read_u4(&p);
- id2 = read_id(&p); /* class id */
- num_bytes = read_u4(&p);
- p += num_bytes;
- break;
- CASE_HEAP(HPROF_GC_OBJ_ARRAY_DUMP)
- id = read_id(&p);
- trace_serial_num = read_u4(&p);
- num_elements = read_u4(&p);
- id2 = read_id(&p);
- p += num_elements*(int)sizeof(HprofId);
- break;
- CASE_HEAP(HPROF_GC_PRIM_ARRAY_DUMP)
- id = read_id(&p);
- trace_serial_num = read_u4(&p);
- num_elements = read_u4(&p);
- ty = read_u1(&p);
- p += type_size[ty]*num_elements;
- break;
- default:
- label = "UNKNOWN";
- check_printf("H#%d@%d %s: ERROR!\n",
- nrecords, npos, label);
- HPROF_ERROR(JNI_TRUE, "unknown heap record type");
- break;
- }
- }
- CHECK_FOR_ERROR(p==pstart+nbytes);
-
- /* Scan again once we have our cmap */
- nrecords = 0;
- p = pstart;
- while ( p < (pstart+nbytes) ) {
- nrecords++;
- /*LINTED*/
- npos = (int)(p - pstart);
- tag = read_u1(&p);
- switch ( tag ) {
- CASE_HEAP(HPROF_GC_ROOT_UNKNOWN)
- id = read_id(&p);
- check_printf("H#%d@%d %s: id=0x%x\n",
- nrecords, npos, label, id);
- break;
- CASE_HEAP(HPROF_GC_ROOT_JNI_GLOBAL)
- id = read_id(&p);
- id2 = read_id(&p);
- check_printf("H#%d@%d %s: id=0x%x, id2=0x%x\n",
- nrecords, npos, label, id, id2);
- break;
- CASE_HEAP(HPROF_GC_ROOT_JNI_LOCAL)
- id = read_id(&p);
- thread_serial_num = read_u4(&p);
- fr = read_u4(&p);
- check_printf("H#%d@%d %s: id=0x%x, thread_serial_num=%u, fr=0x%x\n",
- nrecords, npos, label, id, thread_serial_num, fr);
- break;
- CASE_HEAP(HPROF_GC_ROOT_JAVA_FRAME)
- id = read_id(&p);
- thread_serial_num = read_u4(&p);
- fr = read_u4(&p);
- check_printf("H#%d@%d %s: id=0x%x, thread_serial_num=%u, fr=0x%x\n",
- nrecords, npos, label, id, thread_serial_num, fr);
- break;
- CASE_HEAP(HPROF_GC_ROOT_NATIVE_STACK)
- id = read_id(&p);
- thread_serial_num = read_u4(&p);
- check_printf("H#%d@%d %s: id=0x%x, thread_serial_num=%u\n",
- nrecords, npos, label, id, thread_serial_num);
- break;
- CASE_HEAP(HPROF_GC_ROOT_STICKY_CLASS)
- id = read_id(&p);
- check_printf("H#%d@%d %s: id=0x%x\n",
- nrecords, npos, label, id);
- break;
- CASE_HEAP(HPROF_GC_ROOT_THREAD_BLOCK)
- id = read_id(&p);
- thread_serial_num = read_u4(&p);
- check_printf("H#%d@%d %s: id=0x%x, thread_serial_num=%u\n",
- nrecords, npos, label, id, thread_serial_num);
- break;
- CASE_HEAP(HPROF_GC_ROOT_MONITOR_USED)
- id = read_id(&p);
- check_printf("H#%d@%d %s: id=0x%x\n",
- nrecords, npos, label, id);
- break;
- CASE_HEAP(HPROF_GC_ROOT_THREAD_OBJ)
- id = read_id(&p);
- thread_serial_num = read_u4(&p);
- trace_serial_num = read_u4(&p);
- CHECK_TRACE_SERIAL_NO(trace_serial_num);
- check_printf("H#%d@%d %s: id=0x%x, thread_serial_num=%u,"
- " trace_serial_num=%u\n",
- nrecords, npos, label, id, thread_serial_num,
- trace_serial_num);
- break;
- CASE_HEAP(HPROF_GC_CLASS_DUMP)
- id = read_id(&p);
- trace_serial_num = read_u4(&p);
- CHECK_TRACE_SERIAL_NO(trace_serial_num);
- check_printf("H#%d@%d %s: id=0x%x, trace_serial_num=%u\n",
- nrecords, npos, label, id, trace_serial_num);
- {
- HprofId ld, si, pr, re1, re2;
-
- sup = read_id(&p);
- ld = read_id(&p);
- si = read_id(&p);
- pr = read_id(&p);
- re1 = read_id(&p);
- re2 = read_id(&p);
- check_printf(" su=0x%x, ld=0x%x, si=0x%x,"
- " pr=0x%x, re1=0x%x, re2=0x%x\n",
- sup, ld, si, pr, re1, re2);
- }
- inst_size = read_u4(&p);
- check_printf(" instance_size=%d\n", inst_size);
-
- num_elements = read_u2(&p);
- for(i=0; i<num_elements; i++) {
- HprofType ty;
- unsigned cpi;
- jvalue val;
-
- cpi = read_u2(&p);
- ty = read_u1(&p);
- val = read_val(&p, ty);
- check_printf(" constant_pool %d: cpi=%d, ty=%d, val=",
- i, cpi, ty);
- check_printf_val(ty, val, 1);
- check_printf("\n");
- }
-
- num_elements = read_u2(&p);
- check_printf(" static_field_count=%d\n", num_elements);
- for(i=0; i<num_elements; i++) {
- HprofType ty;
- HprofId id;
- jvalue val;
-
- id = read_id(&p);
- ty = read_u1(&p);
- val = read_val(&p, ty);
- check_printf(" static field %d: ", i);
- check_print_utf8(utab, "id=", id);
- check_printf(", ty=%d, val=", ty);
- check_printf_val(ty, val, 1);
- check_printf("\n");
- }
-
- num_elements = read_u2(&p);
- check_printf(" instance_field_count=%d\n", num_elements);
- for(i=0; i<num_elements; i++) {
- HprofType ty;
- HprofId id;
-
- id = read_id(&p);
- ty = read_u1(&p);
- check_printf(" instance_field %d: ", i);
- check_print_utf8(utab, "id=", id);
- check_printf(", ty=%d\n", ty);
- }
- break;
- CASE_HEAP(HPROF_GC_INSTANCE_DUMP)
- id = read_id(&p);
- trace_serial_num = read_u4(&p);
- CHECK_TRACE_SERIAL_NO(trace_serial_num);
- id2 = read_id(&p); /* class id */
- num_bytes = read_u4(&p);
- check_printf("H#%d@%d %s: id=0x%x, trace_serial_num=%u,"
- " cid=0x%x, nbytes=%d\n",
- nrecords, npos, label, id, trace_serial_num,
- id2, num_bytes);
- /* This is a packed set of bytes for the instance fields */
- if ( num_bytes > 0 ) {
- TableIndex cindex;
- int ifield;
- CmapInfo *map;
-
- cindex = table_find_entry(ctab, &id2, sizeof(id2));
- HPROF_ASSERT(cindex!=0);
- map = (CmapInfo*)table_get_info(ctab, cindex);
- HPROF_ASSERT(map!=NULL);
- HPROF_ASSERT(num_bytes==map->inst_size);
-
- psave = p;
- ifield = 0;
-
- do {
- for(i=0;i<map->n_finfo;i++) {
- HprofType ty;
- HprofId id;
- jvalue val;
-
- ty = map->finfo[i].ty;
- id = map->finfo[i].id;
- HPROF_ASSERT(ty!=0);
- HPROF_ASSERT(id!=0);
- val = read_val(&p, ty);
- check_printf(" field %d: ", ifield);
- check_print_utf8(utab, "id=", id);
- check_printf(", ty=%d, val=", ty);
- check_printf_val(ty, val, 1);
- check_printf("\n");
- ifield++;
- }
- id2 = map->sup;
- map = NULL;
- cindex = 0;
- if ( id2 != 0 ) {
- cindex = table_find_entry(ctab, &id2, sizeof(id2));
- HPROF_ASSERT(cindex!=0);
- map = (CmapInfo*)table_get_info(ctab, cindex);
- HPROF_ASSERT(map!=NULL);
- }
- } while ( map != NULL );
- HPROF_ASSERT(num_bytes==(p-psave));
- }
- break;
- CASE_HEAP(HPROF_GC_OBJ_ARRAY_DUMP)
- id = read_id(&p);
- trace_serial_num = read_u4(&p);
- CHECK_TRACE_SERIAL_NO(trace_serial_num);
- num_elements = read_u4(&p);
- id2 = read_id(&p);
- check_printf("H#%d@%d %s: id=0x%x, trace_serial_num=%u, nelems=%d, eid=0x%x\n",
- nrecords, npos, label, id, trace_serial_num, num_elements, id2);
- for(i=0; i<num_elements; i++) {
- HprofId id;
-
- id = read_id(&p);
- check_printf(" [%d]: id=0x%x\n", i, id);
- }
- break;
- CASE_HEAP(HPROF_GC_PRIM_ARRAY_DUMP)
- id = read_id(&p);
- trace_serial_num = read_u4(&p);
- CHECK_TRACE_SERIAL_NO(trace_serial_num);
- num_elements = read_u4(&p);
- ty = read_u1(&p);
- psave = p;
- check_printf("H#%d@%d %s: id=0x%x, trace_serial_num=%u, "
- "nelems=%d, ty=%d\n",
- nrecords, npos, label, id, trace_serial_num, num_elements, ty);
- HPROF_ASSERT(HPROF_TYPE_IS_PRIMITIVE(ty));
- if ( num_elements > 0 ) {
- int count;
- int long_form;
- int max_count;
- char *quote;
-
- quote = "";
- long_form = 1;
- max_count = 8;
- count = 0;
- switch ( ty ) {
- case HPROF_CHAR:
- long_form = 0;
- max_count = 72;
- quote = "\"";
- /*FALLTHRU*/
- case HPROF_INT:
- case HPROF_DOUBLE:
- case HPROF_LONG:
- case HPROF_BYTE:
- case HPROF_BOOLEAN:
- case HPROF_SHORT:
- case HPROF_FLOAT:
- check_printf(" val=%s", quote);
- for(i=0; i<num_elements; i++) {
- jvalue val;
-
- if ( i > 0 && count == 0 ) {
- check_printf(" %s", quote);
- }
- val = read_val(&p, ty);
- check_printf_val(ty, val, long_form);
- count += 1;
- if ( count >= max_count ) {
- check_printf("\"\n");
- count = 0;
- }
- }
- if ( count != 0 ) {
- check_printf("%s\n", quote);
- }
- break;
- }
- }
- HPROF_ASSERT(type_size[ty]*num_elements==(p-psave));
- break;
- default:
- label = "UNKNOWN";
- check_printf("H#%d@%d %s: ERROR!\n",
- nrecords, npos, label);
- HPROF_ERROR(JNI_TRUE, "unknown heap record type");
- break;
- }
- }
- CHECK_FOR_ERROR(p==pstart+nbytes);
-
- table_cleanup(ctab, &cmap_cleanup, NULL);
-
- return nrecords;
-}
-
-/* LookupTable cleanup callback for utab */
-static void
-utab_cleanup(TableIndex i, void *key_ptr, int key_len, void*info, void*data)
-{
- UmapInfo *umap = info;
-
- if ( umap == NULL ) {
- return;
- }
- if ( umap->str != NULL ) {
- HPROF_FREE(umap->str);
- umap->str = NULL;
- }
-}
-
-/* Check all the heap tags in a heap dump */
-static int
-check_tags(unsigned char *pstart, int nbytes)
-{
- unsigned char *p;
- int nrecord;
- struct LookupTable *utab;
- UmapInfo umap;
-
- check_printf("\nCHECK TAGS: starting\n");
-
- utab = table_initialize("temp utf8 map", 64, 64, 512, sizeof(UmapInfo));
-
- /* Walk the tags, assumes UTF8 tags are defined before used */
- p = pstart;
- nrecord = 0;
- while ( p < (pstart+nbytes) ) {
- unsigned tag;
- unsigned size;
- int nheap_records;
- int npos;
- char *label;
- HprofId id, nm, sg, so, gr, gn;
- int i, li, num_elements;
- HprofType ty;
- SerialNumber trace_serial_num;
- SerialNumber thread_serial_num;
- SerialNumber class_serial_num;
- unsigned flags;
- unsigned depth;
- float cutoff;
- unsigned temp;
- jint nblive;
- jint nilive;
- jlong tbytes;
- jlong tinsts;
- jint total_samples;
- jint trace_count;
-
- nrecord++;
- /*LINTED*/
- npos = (int)(p - pstart);
- tag = read_u1(&p);
- (void)read_u4(&p); /* microsecs */
- size = read_u4(&p);
- #define CASE_TAG(name) case name: label = #name;
- switch ( tag ) {
- CASE_TAG(HPROF_UTF8)
- CHECK_FOR_ERROR(size>=(int)sizeof(HprofId));
- id = read_id(&p);
- check_printf("#%d@%d: %s, sz=%d, name_id=0x%x, \"",
- nrecord, npos, label, size, id);
- num_elements = size-(int)sizeof(HprofId);
- check_raw(p, num_elements);
- check_printf("\"\n");
- /* Create entry in umap */
- umap.str = HPROF_MALLOC(num_elements+1);
- (void)strncpy(umap.str, (char*)p, (size_t)num_elements);
- umap.str[num_elements] = 0;
- (void)table_create_entry(utab, &id, sizeof(id), &umap);
- p += num_elements;
- break;
- CASE_TAG(HPROF_LOAD_CLASS)
- CHECK_FOR_ERROR(size==2*4+2*(int)sizeof(HprofId));
- class_serial_num = read_u4(&p);
- CHECK_CLASS_SERIAL_NO(class_serial_num);
- id = read_id(&p);
- trace_serial_num = read_u4(&p);
- CHECK_TRACE_SERIAL_NO(trace_serial_num);
- nm = read_id(&p);
- check_printf("#%d@%d: %s, sz=%d, class_serial_num=%u,"
- " id=0x%x, trace_serial_num=%u, name_id=0x%x\n",
- nrecord, npos, label, size, class_serial_num,
- id, trace_serial_num, nm);
- break;
- CASE_TAG(HPROF_UNLOAD_CLASS)
- CHECK_FOR_ERROR(size==4);
- class_serial_num = read_u4(&p);
- CHECK_CLASS_SERIAL_NO(class_serial_num);
- check_printf("#%d@%d: %s, sz=%d, class_serial_num=%u\n",
- nrecord, npos, label, size, class_serial_num);
- break;
- CASE_TAG(HPROF_FRAME)
- CHECK_FOR_ERROR(size==2*4+4*(int)sizeof(HprofId));
- id = read_id(&p);
- nm = read_id(&p);
- sg = read_id(&p);
- so = read_id(&p);
- class_serial_num = read_u4(&p);
- CHECK_CLASS_SERIAL_NO(class_serial_num);
- li = read_u4(&p);
- check_printf("#%d@%d: %s, sz=%d, ", nrecord, npos, label, size);
- check_print_utf8(utab, "id=", id);
- check_printf(" name_id=0x%x, sig_id=0x%x, source_id=0x%x,"
- " class_serial_num=%u, lineno=%d\n",
- nm, sg, so, class_serial_num, li);
- break;
- CASE_TAG(HPROF_TRACE)
- CHECK_FOR_ERROR(size>=3*4);
- trace_serial_num = read_u4(&p);
- CHECK_TRACE_SERIAL_NO(trace_serial_num);
- thread_serial_num = read_u4(&p); /* Can be 0 */
- num_elements = read_u4(&p);
- check_printf("#%d@%d: %s, sz=%d, trace_serial_num=%u,"
- " thread_serial_num=%u, nelems=%d [",
- nrecord, npos, label, size,
- trace_serial_num, thread_serial_num, num_elements);
- for(i=0; i< num_elements; i++) {
- check_printf("0x%x,", read_id(&p));
- }
- check_printf("]\n");
- break;
- CASE_TAG(HPROF_ALLOC_SITES)
- CHECK_FOR_ERROR(size>=2+4*4+2*8);
- flags = read_u2(&p);
- temp = read_u4(&p);
- cutoff = *((float*)&temp);
- nblive = read_u4(&p);
- nilive = read_u4(&p);
- tbytes = read_u8(&p);
- tinsts = read_u8(&p);
- num_elements = read_u4(&p);
- check_printf("#%d@%d: %s, sz=%d, flags=0x%x, cutoff=%g,"
- " nblive=%d, nilive=%d, tbytes=(%d,%d),"
- " tinsts=(%d,%d), num_elements=%d\n",
- nrecord, npos, label, size,
- flags, cutoff, nblive, nilive,
- jlong_high(tbytes), jlong_low(tbytes),
- jlong_high(tinsts), jlong_low(tinsts),
- num_elements);
- for(i=0; i< num_elements; i++) {
- ty = read_u1(&p);
- class_serial_num = read_u4(&p);
- CHECK_CLASS_SERIAL_NO(class_serial_num);
- trace_serial_num = read_u4(&p);
- CHECK_TRACE_SERIAL_NO(trace_serial_num);
- nblive = read_u4(&p);
- nilive = read_u4(&p);
- tbytes = read_u4(&p);
- tinsts = read_u4(&p);
- check_printf("\t %d: ty=%d, class_serial_num=%u,"
- " trace_serial_num=%u, nblive=%d, nilive=%d,"
- " tbytes=%d, tinsts=%d\n",
- i, ty, class_serial_num, trace_serial_num,
- nblive, nilive, (jint)tbytes, (jint)tinsts);
- }
- break;
- CASE_TAG(HPROF_HEAP_SUMMARY)
- CHECK_FOR_ERROR(size==2*4+2*8);
- nblive = read_u4(&p);
- nilive = read_u4(&p);
- tbytes = read_u8(&p);
- tinsts = read_u8(&p);
- check_printf("#%d@%d: %s, sz=%d,"
- " nblive=%d, nilive=%d, tbytes=(%d,%d),"
- " tinsts=(%d,%d)\n",
- nrecord, npos, label, size,
- nblive, nilive,
- jlong_high(tbytes), jlong_low(tbytes),
- jlong_high(tinsts), jlong_low(tinsts));
- break;
- CASE_TAG(HPROF_START_THREAD)
- CHECK_FOR_ERROR(size==2*4+4*(int)sizeof(HprofId));
- thread_serial_num = read_u4(&p);
- CHECK_THREAD_SERIAL_NO(thread_serial_num);
- id = read_id(&p);
- trace_serial_num = read_u4(&p);
- CHECK_TRACE_SERIAL_NO(trace_serial_num);
- nm = read_id(&p);
- gr = read_id(&p);
- gn = read_id(&p);
- check_printf("#%d@%d: %s, sz=%d, thread_serial_num=%u,"
- " id=0x%x, trace_serial_num=%u, ",
- nrecord, npos, label, size,
- thread_serial_num, id, trace_serial_num);
- check_print_utf8(utab, "nm=", id);
- check_printf(" trace_serial_num=%u, nm=0x%x,"
- " gr=0x%x, gn=0x%x\n",
- trace_serial_num, nm, gr, gn);
- break;
- CASE_TAG(HPROF_END_THREAD)
- CHECK_FOR_ERROR(size==4);
- thread_serial_num = read_u4(&p);
- CHECK_THREAD_SERIAL_NO(thread_serial_num);
- check_printf("#%d@%d: %s, sz=%d, thread_serial_num=%u\n",
- nrecord, npos, label, size, thread_serial_num);
- break;
- CASE_TAG(HPROF_HEAP_DUMP)
- check_printf("#%d@%d: BEGIN: %s, sz=%d\n",
- nrecord, npos, label, size);
- nheap_records = check_heap_tags(utab, p, size);
- check_printf("#%d@%d: END: %s, sz=%d, nheap_recs=%d\n",
- nrecord, npos, label, size, nheap_records);
- p += size;
- break;
- CASE_TAG(HPROF_HEAP_DUMP_SEGMENT) /* 1.0.2 */
- check_printf("#%d@%d: BEGIN SEGMENT: %s, sz=%d\n",
- nrecord, npos, label, size);
- nheap_records = check_heap_tags(utab, p, size);
- check_printf("#%d@%d: END SEGMENT: %s, sz=%d, nheap_recs=%d\n",
- nrecord, npos, label, size, nheap_records);
- p += size;
- break;
- CASE_TAG(HPROF_HEAP_DUMP_END) /* 1.0.2 */
- check_printf("#%d@%d: SEGMENT END: %s, sz=%d\n",
- nrecord, npos, label, size);
- break;
- CASE_TAG(HPROF_CPU_SAMPLES)
- CHECK_FOR_ERROR(size>=2*4);
- total_samples = read_u4(&p);
- trace_count = read_u4(&p);
- check_printf("#%d@%d: %s, sz=%d, total_samples=%d,"
- " trace_count=%d\n",
- nrecord, npos, label, size,
- total_samples, trace_count);
- for(i=0; i< trace_count; i++) {
- num_elements = read_u4(&p);
- trace_serial_num = read_u4(&p);
- CHECK_TRACE_SERIAL_NO(trace_serial_num);
- check_printf("\t %d: samples=%d, trace_serial_num=%u\n",
- trace_serial_num, num_elements);
- }
- break;
- CASE_TAG(HPROF_CONTROL_SETTINGS)
- CHECK_FOR_ERROR(size==4+2);
- flags = read_u4(&p);
- depth = read_u2(&p);
- check_printf("#%d@%d: %s, sz=%d, flags=0x%x, depth=%d\n",
- nrecord, npos, label, size, flags, depth);
- break;
- default:
- label = "UNKNOWN";
- check_printf("#%d@%d: %s, sz=%d\n",
- nrecord, npos, label, size);
- HPROF_ERROR(JNI_TRUE, "unknown record type");
- p += size;
- break;
- }
- CHECK_FOR_ERROR(p<=(pstart+nbytes));
- }
- check_flush();
- CHECK_FOR_ERROR(p==(pstart+nbytes));
- table_cleanup(utab, &utab_cleanup, NULL);
- return nrecord;
-}
-
-/* Read the entire file into memory */
-static void *
-get_binary_file_image(char *filename, int *pnbytes)
-{
- unsigned char *image;
- int fd;
- jlong nbytes;
- int nread;
-
- *pnbytes = 0;
- fd = md_open_binary(filename);
- CHECK_FOR_ERROR(fd>=0);
- if ( (nbytes = md_seek(fd, (jlong)-1)) == (jlong)-1 ) {
- HPROF_ERROR(JNI_TRUE, "Cannot md_seek() to end of file");
- }
- CHECK_FOR_ERROR(((jint)nbytes)>512);
- if ( md_seek(fd, (jlong)0) != (jlong)0 ) {
- HPROF_ERROR(JNI_TRUE, "Cannot md_seek() to start of file");
- }
- image = HPROF_MALLOC(((jint)nbytes)+1);
- CHECK_FOR_ERROR(image!=NULL);
-
- /* Read the entire file image into memory */
- nread = md_read(fd, image, (jint)nbytes);
- if ( nread <= 0 ) {
- HPROF_ERROR(JNI_TRUE, "System read failed.");
- }
- CHECK_FOR_ERROR(((jint)nbytes)==nread);
- md_close(fd);
- *pnbytes = (jint)nbytes;
- return image;
-}
-
-/* ------------------------------------------------------------------ */
-
-void
-check_binary_file(char *filename)
-{
- unsigned char *image;
- unsigned char *p;
- unsigned idsize;
- int nbytes;
- int nrecords;
-
- image = get_binary_file_image(filename, &nbytes);
- if ( image == NULL ) {
- check_printf("No file image: %s\n", filename);
- return;
- }
- p = image;
- CHECK_FOR_ERROR(strcmp((char*)p, gdata->header)==0);
- check_printf("Filename=%s, nbytes=%d, header=\"%s\"\n",
- filename, nbytes, p);
- p+=((int)strlen((char*)p)+1);
- idsize = read_u4(&p);
- CHECK_FOR_ERROR(idsize==sizeof(HprofId));
- (void)read_u4(&p);
- (void)read_u4(&p);
- /* LINTED */
- nrecords = check_tags(p, nbytes - (int)( p - image ) );
- check_printf("#%d total records found in %d bytes\n", nrecords, nbytes);
- HPROF_FREE(image);
-}
--- a/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_check.h Thu Aug 20 12:29:58 2015 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,58 +0,0 @@
-/*
- * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * - Neither the name of Oracle nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
- * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/*
- * This source code is provided to illustrate the usage of a given feature
- * or technique and has been deliberately simplified. Additional steps
- * required for a production-quality application, such as security checks,
- * input validation and proper error handling, might not be present in
- * this sample code.
- */
-
-
-#ifndef HPROF_CHECK_H
-#define HPROF_CHECK_H
-
-#define CHECK_FOR_ERROR(condition) \
- ( (condition) ? \
- (void)0 : \
- HPROF_ERROR(JNI_TRUE, #condition) )
-#define CHECK_SERIAL_NO(name, sno) \
- CHECK_FOR_ERROR( (sno) >= gdata->name##_serial_number_start && \
- (sno) < gdata->name##_serial_number_counter)
-#define CHECK_CLASS_SERIAL_NO(sno) CHECK_SERIAL_NO(class,sno)
-#define CHECK_THREAD_SERIAL_NO(sno) CHECK_SERIAL_NO(thread,sno)
-#define CHECK_TRACE_SERIAL_NO(sno) CHECK_SERIAL_NO(trace,sno)
-#define CHECK_OBJECT_SERIAL_NO(sno) CHECK_SERIAL_NO(object,sno)
-
-void check_binary_file(char *filename);
-
-#endif
--- a/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_class.c Thu Aug 20 12:29:58 2015 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,686 +0,0 @@
-/*
- * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * - Neither the name of Oracle nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
- * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/*
- * This source code is provided to illustrate the usage of a given feature
- * or technique and has been deliberately simplified. Additional steps
- * required for a production-quality application, such as security checks,
- * input validation and proper error handling, might not be present in
- * this sample code.
- */
-
-
-/* Table of class information.
- *
- * Each element in this table is identified with a ClassIndex.
- * Each element is uniquely identified by it's signature and loader.
- * Every class load has a unique class serial number.
- * While loaded, each element will have a cache of a global reference
- * to it's jclass object, plus jmethodID's as needed.
- * Method signatures and names are obtained via BCI.
- * Methods can be identified with a ClassIndex and MethodIndex pair,
- * where the MethodIndex matches the index of the method name and
- * signature arrays obtained from the BCI pass.
- * Strings are stored in the string table and a StringIndex is used.
- * Class Loaders are stored in the loader table and a LoaderIndex is used.
- * Since the jclass object is an object, at some point an object table
- * entry may be allocated for the jclass as an ObjectIndex.
- */
-
-#include "hprof.h"
-
-/* Effectively represents a jclass object. */
-
-/* These table elements are made unique by and sorted by signature name. */
-
-typedef struct ClassKey {
- StringIndex sig_string_index; /* Signature of class */
- LoaderIndex loader_index; /* Index for class loader */
-} ClassKey;
-
-/* Each class could contain method information, gotten from BCI callback */
-
-typedef struct MethodInfo {
- StringIndex name_index; /* Method name, index into string table */
- StringIndex sig_index; /* Method signature, index into string table */
- jmethodID method_id; /* Method ID, possibly NULL at first */
-} MethodInfo;
-
-/* The basic class information we save */
-
-typedef struct ClassInfo {
- jclass classref; /* Global ref to jclass */
- MethodInfo *method; /* Array of method data */
- int method_count; /* Count of methods */
- ObjectIndex object_index; /* Optional object index for jclass */
- SerialNumber serial_num; /* Unique to the actual class load */
- ClassStatus status; /* Current class status (bit mask) */
- ClassIndex super; /* Super class in this table */
- StringIndex name; /* Name of class */
- jint inst_size; /* #bytes needed for instance fields */
- jint field_count; /* Number of all fields */
- FieldInfo *field; /* Pointer to all FieldInfo's */
-} ClassInfo;
-
-/* Private interfaces */
-
-static ClassKey*
-get_pkey(ClassIndex index)
-{
- void *key_ptr;
- int key_len;
-
- table_get_key(gdata->class_table, index, (void*)&key_ptr, &key_len);
- HPROF_ASSERT(key_len==sizeof(ClassKey));
- HPROF_ASSERT(key_ptr!=NULL);
- return (ClassKey*)key_ptr;
-}
-
-static void
-fillin_pkey(const char *sig, LoaderIndex loader_index, ClassKey *pkey)
-{
- static ClassKey empty_key;
-
- HPROF_ASSERT(loader_index!=0);
- *pkey = empty_key;
- pkey->sig_string_index = string_find_or_create(sig);
- pkey->loader_index = loader_index;
-}
-
-static ClassInfo *
-get_info(ClassIndex index)
-{
- ClassInfo *info;
-
- info = (ClassInfo*)table_get_info(gdata->class_table, index);
- return info;
-}
-
-static void
-fill_info(TableIndex index, ClassKey *pkey)
-{
- ClassInfo *info;
- char *sig;
-
- info = get_info(index);
- info->serial_num = gdata->class_serial_number_counter++;
- info->method_count = 0;
- info->inst_size = -1;
- info->field_count = -1;
- info->field = NULL;
- sig = string_get(pkey->sig_string_index);
- if ( sig[0] != JVM_SIGNATURE_CLASS ) {
- info->name = pkey->sig_string_index;
- } else {
- int len;
-
- len = string_get_len(pkey->sig_string_index);
- if ( len > 2 ) {
- char *name;
-
- /* Class signature looks like "Lname;", we want "name" here. */
- name = HPROF_MALLOC(len-1);
- (void)memcpy(name, sig+1, len-2);
- name[len-2] = 0;
- info->name = string_find_or_create(name);
- HPROF_FREE(name);
- } else {
- /* This would be strange, a class signature not in "Lname;" form? */
- info->name = pkey->sig_string_index;
- }
- }
-}
-
-static ClassIndex
-find_entry(ClassKey *pkey)
-{
- ClassIndex index;
-
- index = table_find_entry(gdata->class_table,
- (void*)pkey, (int)sizeof(ClassKey));
- return index;
-}
-
-static ClassIndex
-create_entry(ClassKey *pkey)
-{
- ClassIndex index;
-
- index = table_create_entry(gdata->class_table,
- (void*)pkey, (int)sizeof(ClassKey), NULL);
- fill_info(index, pkey);
- return index;
-}
-
-static ClassIndex
-find_or_create_entry(ClassKey *pkey)
-{
- ClassIndex index;
-
- HPROF_ASSERT(pkey!=NULL);
- HPROF_ASSERT(pkey->loader_index!=0);
- index = find_entry(pkey);
- if ( index == 0 ) {
- index = create_entry(pkey);
- }
- return index;
-}
-
-static void
-delete_classref(JNIEnv *env, ClassInfo *info, jclass klass)
-{
- jclass ref;
- int i;
-
- HPROF_ASSERT(env!=NULL);
- HPROF_ASSERT(info!=NULL);
-
- for ( i = 0 ; i < info->method_count ; i++ ) {
- info->method[i].method_id = NULL;
- }
- ref = info->classref;
- if ( klass != NULL ) {
- info->classref = newGlobalReference(env, klass);
- } else {
- info->classref = NULL;
- }
- if ( ref != NULL ) {
- deleteGlobalReference(env, ref);
- }
-}
-
-static void
-cleanup_item(TableIndex index, void *key_ptr, int key_len,
- void *info_ptr, void *arg)
-{
- ClassInfo *info;
-
- /* Cleanup any information in this ClassInfo structure. */
- HPROF_ASSERT(key_ptr!=NULL);
- HPROF_ASSERT(key_len==sizeof(ClassKey));
- HPROF_ASSERT(info_ptr!=NULL);
- info = (ClassInfo *)info_ptr;
- if ( info->method_count > 0 ) {
- HPROF_FREE((void*)info->method);
- info->method_count = 0;
- info->method = NULL;
- }
- if ( info->field != NULL ) {
- HPROF_FREE((void*)info->field);
- info->field_count = 0;
- info->field = NULL;
- }
-}
-
-static void
-delete_ref_item(TableIndex index, void *key_ptr, int key_len,
- void *info_ptr, void *arg)
-{
- delete_classref((JNIEnv*)arg, (ClassInfo*)info_ptr, NULL);
-}
-
-static void
-list_item(TableIndex index, void *key_ptr, int key_len,
- void *info_ptr, void *arg)
-{
- ClassInfo *info;
- ClassKey key;
- char *sig;
- int i;
-
- HPROF_ASSERT(key_ptr!=NULL);
- HPROF_ASSERT(key_len==sizeof(ClassKey));
- HPROF_ASSERT(info_ptr!=NULL);
- key = *((ClassKey*)key_ptr);
- sig = string_get(key.sig_string_index);
- info = (ClassInfo *)info_ptr;
- debug_message(
- "0x%08x: Class %s, SN=%u, status=0x%08x, ref=%p,"
- " method_count=%d\n",
- index,
- (const char *)sig,
- info->serial_num,
- info->status,
- (void*)info->classref,
- info->method_count);
- if ( info->method_count > 0 ) {
- for ( i = 0 ; i < info->method_count ; i++ ) {
- debug_message(
- " Method %d: \"%s\", sig=\"%s\", method=%p\n",
- i,
- string_get(info->method[i].name_index),
- string_get(info->method[i].sig_index),
- (void*)info->method[i].method_id);
- }
- }
-}
-
-static void
-all_status_remove(TableIndex index, void *key_ptr, int key_len,
- void *info_ptr, void *arg)
-{
- ClassInfo *info;
- ClassStatus status;
-
- HPROF_ASSERT(info_ptr!=NULL);
- /*LINTED*/
- status = (ClassStatus)(long)(ptrdiff_t)arg;
- info = (ClassInfo *)info_ptr;
- info->status &= (~status);
-}
-
-static void
-unload_walker(TableIndex index, void *key_ptr, int key_len,
- void *info_ptr, void *arg)
-{
- ClassInfo *info;
-
- HPROF_ASSERT(info_ptr!=NULL);
- info = (ClassInfo *)info_ptr;
- if ( ! ( info->status & CLASS_IN_LOAD_LIST ) ) {
- if ( ! (info->status & (CLASS_SPECIAL|CLASS_SYSTEM|CLASS_UNLOADED)) ) {
- io_write_class_unload(info->serial_num, info->object_index);
- info->status |= CLASS_UNLOADED;
- delete_classref((JNIEnv*)arg, info, NULL);
- }
- }
-}
-
-/* External interfaces */
-
-void
-class_init(void)
-{
- HPROF_ASSERT(gdata->class_table==NULL);
- gdata->class_table = table_initialize("Class", 512, 512, 511,
- (int)sizeof(ClassInfo));
-}
-
-ClassIndex
-class_find_or_create(const char *sig, LoaderIndex loader_index)
-{
- ClassKey key;
-
- fillin_pkey(sig, loader_index, &key);
- return find_or_create_entry(&key);
-}
-
-ClassIndex
-class_create(const char *sig, LoaderIndex loader_index)
-{
- ClassKey key;
-
- fillin_pkey(sig, loader_index, &key);
- return create_entry(&key);
-}
-
-void
-class_prime_system_classes(void)
-{
- /* Prime System classes? Anything before VM_START is System class.
- * Or classes loaded before env arg is non-NULL.
- * Or any of the classes listed below.
- */
- static const char * signatures[] =
- {
- "Ljava/lang/Object;",
- "Ljava/io/Serializable;",
- "Ljava/lang/String;",
- "Ljava/lang/Class;",
- "Ljava/lang/ClassLoader;",
- "Ljava/lang/System;",
- "Ljava/lang/Thread;",
- "Ljava/lang/ThreadGroup;",
- };
- int n_signatures;
- int i;
- LoaderIndex loader_index;
-
- n_signatures = (int)sizeof(signatures)/(int)sizeof(signatures[0]);
- loader_index = loader_find_or_create(NULL, NULL);
- for ( i = 0 ; i < n_signatures ; i++ ) {
- ClassInfo *info;
- ClassIndex index;
- ClassKey key;
-
- fillin_pkey(signatures[i], loader_index, &key);
- index = find_or_create_entry(&key);
- info = get_info(index);
- info->status |= CLASS_SYSTEM;
- }
-}
-
-void
-class_add_status(ClassIndex index, ClassStatus status)
-{
- ClassInfo *info;
-
- info = get_info(index);
- info->status |= status;
-}
-
-ClassStatus
-class_get_status(ClassIndex index)
-{
- ClassInfo *info;
-
- info = get_info(index);
- return info->status;
-}
-
-StringIndex
-class_get_signature(ClassIndex index)
-{
- ClassKey *pkey;
-
- pkey = get_pkey(index);
- return pkey->sig_string_index;
-}
-
-SerialNumber
-class_get_serial_number(ClassIndex index)
-{
- ClassInfo *info;
-
- if ( index == 0 ) {
- return 0;
- }
- info = get_info(index);
- return info->serial_num;
-}
-
-void
-class_all_status_remove(ClassStatus status)
-{
- table_walk_items(gdata->class_table, &all_status_remove,
- (void*)(ptrdiff_t)(long)status);
-}
-
-void
-class_do_unloads(JNIEnv *env)
-{
- table_walk_items(gdata->class_table, &unload_walker, (void*)env);
-}
-
-void
-class_list(void)
-{
- debug_message(
- "--------------------- Class Table ------------------------\n");
- table_walk_items(gdata->class_table, &list_item, NULL);
- debug_message(
- "----------------------------------------------------------\n");
-}
-
-void
-class_cleanup(void)
-{
- table_cleanup(gdata->class_table, &cleanup_item, NULL);
- gdata->class_table = NULL;
-}
-
-void
-class_delete_global_references(JNIEnv* env)
-{
- table_walk_items(gdata->class_table, &delete_ref_item, (void*)env);
-}
-
-void
-class_set_methods(ClassIndex index, const char **name, const char **sig,
- int count)
-{
- ClassInfo *info;
- int i;
-
- info = get_info(index);
- if ( info->method_count > 0 ) {
- HPROF_FREE((void*)info->method);
- info->method_count = 0;
- info->method = NULL;
- }
- info->method_count = count;
- if ( count > 0 ) {
- info->method = (MethodInfo *)HPROF_MALLOC(count*(int)sizeof(MethodInfo));
- for ( i = 0 ; i < count ; i++ ) {
- info->method[i].name_index = string_find_or_create(name[i]);
- info->method[i].sig_index = string_find_or_create(sig[i]);
- info->method[i].method_id = NULL;
- }
- }
-}
-
-jclass
-class_new_classref(JNIEnv *env, ClassIndex index, jclass classref)
-{
- ClassInfo *info;
-
- HPROF_ASSERT(classref!=NULL);
- info = get_info(index);
- if ( ! isSameObject(env, classref, info->classref) ) {
- delete_classref(env, info, classref);
- }
- return info->classref;
-}
-
-jclass
-class_get_class(JNIEnv *env, ClassIndex index)
-{
- ClassInfo *info;
- jclass clazz;
-
- info = get_info(index);
- clazz = info->classref;
- if ( env != NULL && clazz == NULL ) {
- WITH_LOCAL_REFS(env, 1) {
- jclass new_clazz;
- char *class_name;
-
- class_name = string_get(info->name);
- /* This really only makes sense for the bootclass classes,
- * since FindClass doesn't provide a way to load a class in
- * a specific class loader.
- */
- new_clazz = findClass(env, class_name);
- if ( new_clazz == NULL ) {
- HPROF_ERROR(JNI_TRUE, "Cannot load class with findClass");
- }
- HPROF_ASSERT(new_clazz!=NULL);
- clazz = class_new_classref(env, index, new_clazz);
- } END_WITH_LOCAL_REFS;
- HPROF_ASSERT(clazz!=NULL);
- }
- return clazz;
-}
-
-jmethodID
-class_get_methodID(JNIEnv *env, ClassIndex index, MethodIndex mnum)
-{
- ClassInfo *info;
- jmethodID method;
-
- info = get_info(index);
- if (mnum >= info->method_count) {
- jclass newExcCls = (*env)->FindClass(env, "java/lang/IllegalArgumentException");
- (*env)->ThrowNew(env, newExcCls, "Illegal mnum");
-
- return NULL;
- }
- method = info->method[mnum].method_id;
- if ( method == NULL ) {
- char * name;
- char * sig;
- jclass clazz;
-
- name = (char *)string_get(info->method[mnum].name_index);
- if (name==NULL) {
- jclass newExcCls = (*env)->FindClass(env, "java/lang/IllegalArgumentException");
- (*env)->ThrowNew(env, newExcCls, "Name not found");
-
- return NULL;
- }
- sig = (char *)string_get(info->method[mnum].sig_index);
- HPROF_ASSERT(sig!=NULL);
- clazz = class_get_class(env, index);
- if ( clazz != NULL ) {
- method = getMethodID(env, clazz, name, sig);
- HPROF_ASSERT(method!=NULL);
- info = get_info(index);
- info->method[mnum].method_id = method;
- }
- }
- return method;
-}
-
-void
-class_set_inst_size(ClassIndex index, jint inst_size)
-{
- ClassInfo *info;
-
- info = get_info(index);
- info->inst_size = inst_size;
-}
-
-jint
-class_get_inst_size(ClassIndex index)
-{
- ClassInfo *info;
-
- info = get_info(index);
- return info->inst_size;
-}
-
-void
-class_set_object_index(ClassIndex index, ObjectIndex object_index)
-{
- ClassInfo *info;
-
- info = get_info(index);
- info->object_index = object_index;
-}
-
-ObjectIndex
-class_get_object_index(ClassIndex index)
-{
- ClassInfo *info;
-
- info = get_info(index);
- return info->object_index;
-}
-
-ClassIndex
-class_get_super(ClassIndex index)
-{
- ClassInfo *info;
-
- info = get_info(index);
- return info->super;
-}
-
-void
-class_set_super(ClassIndex index, ClassIndex super)
-{
- ClassInfo *info;
-
- info = get_info(index);
- info->super = super;
-}
-
-LoaderIndex
-class_get_loader(ClassIndex index)
-{
- ClassKey *pkey;
-
- pkey = get_pkey(index);
- HPROF_ASSERT(pkey->loader_index!=0);
- return pkey->loader_index;
-}
-
-/* Get ALL class fields (supers too), return 1 on error, 0 if ok */
-jint
-class_get_all_fields(JNIEnv *env, ClassIndex index,
- jint *pfield_count, FieldInfo **pfield)
-{
- ClassInfo *info;
- FieldInfo *finfo;
- jint count;
- jint ret;
-
- count = 0;
- finfo = NULL;
- ret = 1; /* Default is to return an error condition */
-
- info = get_info(index);
- if ( info != NULL ) {
- if ( info->field_count >= 0 ) {
- /* Get cache */
- count = info->field_count;
- finfo = info->field;
- ret = 0; /* Return of cache data, no error */
- } else {
- jclass klass;
-
- klass = info->classref;
- if ( klass == NULL || isSameObject(env, klass, NULL) ) {
- /* This is probably an error because this will cause the field
- * index values to be off, but I'm hesitant to generate a
- * fatal error here, so I will issue something and continue.
- * I should have been holding a global reference to all the
- * jclass, so I'm not sure how this could happen.
- * Issuing a FindClass() here is just asking for trouble
- * because if the class went away, we aren't even sure
- * what ClassLoader to use.
- */
- HPROF_ERROR(JNI_FALSE, "Missing jclass when fields needed");
- } else {
- jint status;
-
- status = getClassStatus(klass);
- if ( status &
- (JVMTI_CLASS_STATUS_PRIMITIVE|JVMTI_CLASS_STATUS_ARRAY) ) {
- /* Set cache */
- info->field_count = count;
- info->field = finfo;
- ret = 0; /* Primitive or array ok */
- } else if ( status & JVMTI_CLASS_STATUS_PREPARED ) {
- /* Call JVMTI to get them */
- getAllClassFieldInfo(env, klass, &count, &finfo);
- /* Set cache */
- info->field_count = count;
- info->field = finfo;
- ret = 0;
- }
- }
- }
- }
- *pfield_count = count;
- *pfield = finfo;
- return ret;
-}
--- a/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_class.h Thu Aug 20 12:29:58 2015 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,77 +0,0 @@
-/*
- * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * - Neither the name of Oracle nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
- * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/*
- * This source code is provided to illustrate the usage of a given feature
- * or technique and has been deliberately simplified. Additional steps
- * required for a production-quality application, such as security checks,
- * input validation and proper error handling, might not be present in
- * this sample code.
- */
-
-
-#ifndef HPROF_CLASS_H
-#define HPROF_CLASS_H
-
-void class_init(void);
-ClassIndex class_find_or_create(const char *sig, LoaderIndex loader);
-ClassIndex class_create(const char *sig, LoaderIndex loader);
-SerialNumber class_get_serial_number(ClassIndex index);
-StringIndex class_get_signature(ClassIndex index);
-ClassStatus class_get_status(ClassIndex index);
-void class_add_status(ClassIndex index, ClassStatus status);
-void class_all_status_remove(ClassStatus status);
-void class_do_unloads(JNIEnv *env);
-void class_list(void);
-void class_delete_global_references(JNIEnv* env);
-void class_cleanup(void);
-void class_set_methods(ClassIndex index, const char**name,
- const char**descr, int count);
-jmethodID class_get_methodID(JNIEnv *env, ClassIndex index,
- MethodIndex mnum);
-jclass class_new_classref(JNIEnv *env, ClassIndex index,
- jclass classref);
-void class_delete_classref(JNIEnv *env, ClassIndex index);
-jclass class_get_class(JNIEnv *env, ClassIndex index);
-void class_set_inst_size(ClassIndex index, jint inst_size);
-jint class_get_inst_size(ClassIndex index);
-void class_set_object_index(ClassIndex index,
- ObjectIndex object_index);
-ObjectIndex class_get_object_index(ClassIndex index);
-ClassIndex class_get_super(ClassIndex index);
-void class_set_super(ClassIndex index, ClassIndex super);
-void class_set_loader(ClassIndex index, LoaderIndex loader);
-LoaderIndex class_get_loader(ClassIndex index);
-void class_prime_system_classes(void);
-jint class_get_all_fields(JNIEnv *env, ClassIndex cnum,
- jint *pfield_count, FieldInfo **pfield);
-
-#endif
--- a/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_cpu.c Thu Aug 20 12:29:58 2015 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,238 +0,0 @@
-/*
- * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * - Neither the name of Oracle nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
- * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/*
- * This source code is provided to illustrate the usage of a given feature
- * or technique and has been deliberately simplified. Additional steps
- * required for a production-quality application, such as security checks,
- * input validation and proper error handling, might not be present in
- * this sample code.
- */
-
-
-#include "hprof.h"
-
-/* This file contains the cpu loop for the option cpu=samples */
-
-/* The cpu_loop thread basically waits for gdata->sample_interval millisecs
- * then wakes up, and for each running thread it gets their stack trace,
- * and updates the traces with 'hits'.
- *
- * No threads are suspended or resumed, and the thread sampling is in the
- * file hprof_tls.c, which manages all active threads. The sampling
- * technique (what is sampled) is also in hprof_tls.c.
- *
- * No adjustments are made to the pause time or sample interval except
- * by the user via the interval=n option (default is 10ms).
- *
- * This thread can cause havoc when started prematurely or not terminated
- * properly, see cpu_sample_init() and cpu_term(), and their calls in hprof_init.c.
- *
- * The listener loop (hprof_listener.c) can dynamically turn on or off the
- * sampling of all or selected threads.
- *
- */
-
-/* Private functions */
-
-static void JNICALL
-cpu_loop_function(jvmtiEnv *jvmti, JNIEnv *env, void *p)
-{
- int loop_trip_counter;
- jboolean cpu_loop_running;
-
- loop_trip_counter = 0;
-
- rawMonitorEnter(gdata->cpu_loop_lock); {
- gdata->cpu_loop_running = JNI_TRUE;
- cpu_loop_running = gdata->cpu_loop_running;
- /* Notify cpu_sample_init() that we have started */
- rawMonitorNotifyAll(gdata->cpu_loop_lock);
- } rawMonitorExit(gdata->cpu_loop_lock);
-
- rawMonitorEnter(gdata->cpu_sample_lock); /* Only waits inside loop let go */
-
- while ( cpu_loop_running ) {
-
- ++loop_trip_counter;
-
- LOG3("cpu_loop()", "iteration", loop_trip_counter);
-
- /* If a dump is in progress, we pause sampling. */
- rawMonitorEnter(gdata->dump_lock); {
- if (gdata->dump_in_process) {
- gdata->pause_cpu_sampling = JNI_TRUE;
- }
- } rawMonitorExit(gdata->dump_lock);
-
- /* Check to see if we need to pause sampling (listener_loop command) */
- if (gdata->pause_cpu_sampling) {
-
- /*
- * Pause sampling for now. Reset sample controls if
- * sampling is resumed again.
- */
-
- rawMonitorWait(gdata->cpu_sample_lock, 0);
-
- rawMonitorEnter(gdata->cpu_loop_lock); {
- cpu_loop_running = gdata->cpu_loop_running;
- } rawMonitorExit(gdata->cpu_loop_lock);
-
- /* Continue the while loop, which will terminate if done. */
- continue;
- }
-
- /* This is the normal short timed wait before getting a sample */
- rawMonitorWait(gdata->cpu_sample_lock, (jlong)gdata->sample_interval);
-
- /* Make sure we really want to continue */
- rawMonitorEnter(gdata->cpu_loop_lock); {
- cpu_loop_running = gdata->cpu_loop_running;
- } rawMonitorExit(gdata->cpu_loop_lock);
-
- /* Break out if we are done */
- if ( !cpu_loop_running ) {
- break;
- }
-
- /*
- * If a dump request came in after we checked at the top of
- * the while loop, then we catch that fact here. We
- * don't want to perturb the data that is being dumped so
- * we just ignore the data from this sampling loop.
- */
- rawMonitorEnter(gdata->dump_lock); {
- if (gdata->dump_in_process) {
- gdata->pause_cpu_sampling = JNI_TRUE;
- }
- } rawMonitorExit(gdata->dump_lock);
-
- /* Sample all the threads and update trace costs */
- if ( !gdata->pause_cpu_sampling) {
- tls_sample_all_threads(env);
- }
-
- /* Check to see if we need to finish */
- rawMonitorEnter(gdata->cpu_loop_lock); {
- cpu_loop_running = gdata->cpu_loop_running;
- } rawMonitorExit(gdata->cpu_loop_lock);
-
- }
- rawMonitorExit(gdata->cpu_sample_lock);
-
- rawMonitorEnter(gdata->cpu_loop_lock); {
- /* Notify cpu_sample_term() that we are done. */
- rawMonitorNotifyAll(gdata->cpu_loop_lock);
- } rawMonitorExit(gdata->cpu_loop_lock);
-
- LOG2("cpu_loop()", "clean termination");
-}
-
-/* External functions */
-
-void
-cpu_sample_init(JNIEnv *env)
-{
- gdata->cpu_sampling = JNI_TRUE;
-
- /* Create the raw monitors needed */
- gdata->cpu_loop_lock = createRawMonitor("HPROF cpu loop lock");
- gdata->cpu_sample_lock = createRawMonitor("HPROF cpu sample lock");
-
- rawMonitorEnter(gdata->cpu_loop_lock); {
- createAgentThread(env, "HPROF cpu sampling thread",
- &cpu_loop_function);
- /* Wait for cpu_loop_function() to notify us it has started. */
- rawMonitorWait(gdata->cpu_loop_lock, 0);
- } rawMonitorExit(gdata->cpu_loop_lock);
-}
-
-void
-cpu_sample_off(JNIEnv *env, ObjectIndex object_index)
-{
- jint count;
-
- count = 1;
- if (object_index != 0) {
- tls_set_sample_status(object_index, 0);
- count = tls_sum_sample_status();
- }
- if ( count == 0 ) {
- gdata->pause_cpu_sampling = JNI_TRUE;
- } else {
- gdata->pause_cpu_sampling = JNI_FALSE;
- }
-}
-
-void
-cpu_sample_on(JNIEnv *env, ObjectIndex object_index)
-{
- if ( gdata->cpu_loop_lock == NULL ) {
- cpu_sample_init(env);
- }
-
- if (object_index == 0) {
- gdata->cpu_sampling = JNI_TRUE;
- gdata->pause_cpu_sampling = JNI_FALSE;
- } else {
- jint count;
-
- tls_set_sample_status(object_index, 1);
- count = tls_sum_sample_status();
- if ( count > 0 ) {
- gdata->pause_cpu_sampling = JNI_FALSE;
- }
- }
-
- /* Notify the CPU sampling thread that sampling is on */
- rawMonitorEnter(gdata->cpu_sample_lock); {
- rawMonitorNotifyAll(gdata->cpu_sample_lock);
- } rawMonitorExit(gdata->cpu_sample_lock);
-
-}
-
-void
-cpu_sample_term(JNIEnv *env)
-{
- gdata->pause_cpu_sampling = JNI_FALSE;
- rawMonitorEnter(gdata->cpu_sample_lock); {
- /* Notify the CPU sampling thread to get out of any sampling Wait */
- rawMonitorNotifyAll(gdata->cpu_sample_lock);
- } rawMonitorExit(gdata->cpu_sample_lock);
- rawMonitorEnter(gdata->cpu_loop_lock); {
- if ( gdata->cpu_loop_running ) {
- gdata->cpu_loop_running = JNI_FALSE;
- /* Wait for cpu_loop_function() thread to tell us it completed. */
- rawMonitorWait(gdata->cpu_loop_lock, 0);
- }
- } rawMonitorExit(gdata->cpu_loop_lock);
-}
--- a/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_cpu.h Thu Aug 20 12:29:58 2015 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,50 +0,0 @@
-/*
- * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * - Neither the name of Oracle nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
- * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/*
- * This source code is provided to illustrate the usage of a given feature
- * or technique and has been deliberately simplified. Additional steps
- * required for a production-quality application, such as security checks,
- * input validation and proper error handling, might not be present in
- * this sample code.
- */
-
-
-#ifndef HPROF_CPU_H
-#define HPROF_CPU_H
-
-void cpu_sample_off(JNIEnv *env, ObjectIndex object_index);
-void cpu_sample_on(JNIEnv *env, ObjectIndex object_index);
-
-void cpu_sample_init(JNIEnv *env);
-void cpu_sample_term(JNIEnv *env);
-
-#endif
--- a/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_error.c Thu Aug 20 12:29:58 2015 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,215 +0,0 @@
-/*
- * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * - Neither the name of Oracle nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
- * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/*
- * This source code is provided to illustrate the usage of a given feature
- * or technique and has been deliberately simplified. Additional steps
- * required for a production-quality application, such as security checks,
- * input validation and proper error handling, might not be present in
- * this sample code.
- */
-
-
-#include "hprof.h"
-
-/* The error handling logic. */
-
-/*
- * Most hprof error processing and error functions are kept here, along with
- * termination functions and signal handling (used in debug version only).
- *
- */
-
-#include <signal.h>
-
-static int p = 1; /* Used with pause=y|n option */
-
-/* Private functions */
-
-static void
-error_message(const char * format, ...)
-{
- va_list ap;
-
- va_start(ap, format);
- (void)vfprintf(stderr, format, ap);
- va_end(ap);
-}
-
-static void
-error_abort(void)
-{
- /* Important to remove existing signal handler */
- (void)signal(SIGABRT, NULL);
- error_message("HPROF DUMPING CORE\n");
- abort(); /* Sends SIGABRT signal, usually also caught by libjvm */
-}
-
-static void
-signal_handler(int sig)
-{
- /* Caught a signal, most likely a SIGABRT */
- error_message("HPROF SIGNAL %d TERMINATED PROCESS\n", sig);
- error_abort();
-}
-
-static void
-setup_signal_handler(int sig)
-{
- /* Only if debug version or debug=y */
- if ( gdata->debug ) {
- (void)signal(sig, (void(*)(int))(void*)&signal_handler);
- }
-}
-
-static void
-terminate_everything(jint exit_code)
-{
- if ( exit_code > 0 ) {
- /* Could be a fatal error or assert error or a sanity error */
- error_message("HPROF TERMINATED PROCESS\n");
- if ( gdata->coredump || gdata->debug ) {
- /* Core dump here by request */
- error_abort();
- }
- }
- /* Terminate the process */
- error_exit_process(exit_code);
-}
-
-/* External functions */
-
-void
-error_setup(void)
-{
- setup_signal_handler(SIGABRT);
-}
-
-void
-error_do_pause(void)
-{
- int pid = md_getpid();
- int timeleft = 600; /* 10 minutes max */
- int interval = 10; /* 10 second message check */
-
- /*LINTED*/
- error_message("\nHPROF pause for PID %d\n", (int)pid);
- while ( p && timeleft > 0 ) {
- md_sleep(interval); /* 'assign p=0' to stop pause loop */
- timeleft -= interval;
- }
- if ( timeleft <= 0 ) {
- error_message("\n HPROF pause got tired of waiting and gave up.\n");
- }
-}
-
-void
-error_exit_process(int exit_code)
-{
- exit(exit_code);
-}
-
-static const char *
-source_basename(const char *file)
-{
- const char *p;
-
- if ( file == NULL ) {
- return "UnknownSourceFile";
- }
- p = strrchr(file, '/');
- if ( p == NULL ) {
- p = strrchr(file, '\\');
- }
- if ( p == NULL ) {
- p = file;
- } else {
- p++; /* go past / */
- }
- return p;
-}
-
-void
-error_assert(const char *condition, const char *file, int line)
-{
- error_message("ASSERTION FAILURE: %s [%s:%d]\n", condition,
- source_basename(file), line);
- error_abort();
-}
-
-void
-error_handler(jboolean fatal, jvmtiError error,
- const char *message, const char *file, int line)
-{
- char *error_name;
-
- if ( message==NULL ) {
- message = "";
- }
- if ( error != JVMTI_ERROR_NONE ) {
- error_name = getErrorName(error);
- if ( error_name == NULL ) {
- error_name = "?";
- }
- error_message("HPROF ERROR: %s (JVMTI Error %s(%d)) [%s:%d]\n",
- message, error_name, error,
- source_basename(file), line);
- } else {
- error_message("HPROF ERROR: %s [%s:%d]\n", message,
- source_basename(file), line);
- }
- if ( fatal || gdata->errorexit ) {
- /* If it's fatal, or the user wants termination on any error, die */
- terminate_everything(9);
- }
-}
-
-void
-debug_message(const char * format, ...)
-{
- va_list ap;
-
- va_start(ap, format);
- (void)vfprintf(stderr, format, ap);
- va_end(ap);
-}
-
-void
-verbose_message(const char * format, ...)
-{
- if ( gdata->verbose ) {
- va_list ap;
-
- va_start(ap, format);
- (void)vfprintf(stderr, format, ap);
- va_end(ap);
- }
-}
--- a/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_error.h Thu Aug 20 12:29:58 2015 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,102 +0,0 @@
-/*
- * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * - Neither the name of Oracle nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
- * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/*
- * This source code is provided to illustrate the usage of a given feature
- * or technique and has been deliberately simplified. Additional steps
- * required for a production-quality application, such as security checks,
- * input validation and proper error handling, might not be present in
- * this sample code.
- */
-
-
-#ifndef HPROF_ERROR_H
-#define HPROF_ERROR_H
-
-/* Use THIS_FILE when it is available. */
-#ifndef THIS_FILE
- #define THIS_FILE __FILE__
-#endif
-
-/* Macros over assert and error functions so we can capture the source loc. */
-
-#define HPROF_BOOL(x) ((jboolean)((x)==0?JNI_FALSE:JNI_TRUE))
-
-#define HPROF_ERROR(fatal,msg) \
- error_handler(HPROF_BOOL(fatal), JVMTI_ERROR_NONE, msg, THIS_FILE, __LINE__)
-
-#define HPROF_JVMTI_ERROR(error,msg) \
- error_handler(HPROF_BOOL(error!=JVMTI_ERROR_NONE), \
- error, msg, THIS_FILE, __LINE__)
-
-#if defined(DEBUG) || !defined(NDEBUG)
- #define HPROF_ASSERT(cond) \
- (((int)(cond))?(void)0:error_assert(#cond, THIS_FILE, __LINE__))
-#else
- #define HPROF_ASSERT(cond)
-#endif
-
-#define LOG_DUMP_MISC 0x1 /* Misc. logging info */
-#define LOG_DUMP_LISTS 0x2 /* Dump tables at vm init and death */
-#define LOG_CHECK_BINARY 0x4 /* If format=b, verify binary format */
-
-#ifdef HPROF_LOGGING
- #define LOG_STDERR(args) \
- { \
- if ( gdata != NULL && (gdata->logflags & LOG_DUMP_MISC) ) { \
- (void)fprintf args ; \
- } \
- }
-#else
- #define LOG_STDERR(args)
-#endif
-
-#define LOG_FORMAT(format) "HPROF LOG: " format " [%s:%d]\n"
-
-#define LOG1(str1) LOG_STDERR((stderr, LOG_FORMAT("%s"), \
- str1, THIS_FILE, __LINE__ ))
-#define LOG2(str1,str2) LOG_STDERR((stderr, LOG_FORMAT("%s %s"), \
- str1, str2, THIS_FILE, __LINE__ ))
-#define LOG3(str1,str2,num) LOG_STDERR((stderr, LOG_FORMAT("%s %s 0x%x"), \
- str1, str2, num, THIS_FILE, __LINE__ ))
-
-#define LOG(str) LOG1(str)
-
-void error_handler(jboolean fatal, jvmtiError error,
- const char *message, const char *file, int line);
-void error_assert(const char *condition, const char *file, int line);
-void error_exit_process(int exit_code);
-void error_do_pause(void);
-void error_setup(void);
-void debug_message(const char * format, ...);
-void verbose_message(const char * format, ...);
-
-#endif
--- a/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_event.c Thu Aug 20 12:29:58 2015 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,450 +0,0 @@
-/*
- * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * - Neither the name of Oracle nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
- * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/*
- * This source code is provided to illustrate the usage of a given feature
- * or technique and has been deliberately simplified. Additional steps
- * required for a production-quality application, such as security checks,
- * input validation and proper error handling, might not be present in
- * this sample code.
- */
-
-
-/* This file contains all class, method and allocation event support functions,
- * both JVMTI and BCI events.
- * (See hprof_monitor.c for the monitor event handlers).
- */
-
-#include "hprof.h"
-
-/* Private internal functions. */
-
-/* Return a TraceIndex for the given thread. */
-static TraceIndex
-get_current(TlsIndex tls_index, JNIEnv *env, jboolean skip_init)
-{
- TraceIndex trace_index;
-
- trace_index = tls_get_trace(tls_index, env, gdata->max_trace_depth, skip_init);
- return trace_index;
-}
-
-/* Return a ClassIndex for the given jclass, loader supplied or looked up. */
-static ClassIndex
-find_cnum(JNIEnv *env, jclass klass, jobject loader)
-{
- LoaderIndex loader_index;
- ClassIndex cnum;
- char * signature;
-
- HPROF_ASSERT(klass!=NULL);
-
- /* Get the loader index */
- loader_index = loader_find_or_create(env, loader);
-
- /* Get the signature for this class */
- getClassSignature(klass, &signature, NULL);
-
- /* Find the ClassIndex for this class */
- cnum = class_find_or_create(signature, loader_index);
-
- /* Free the signature space */
- jvmtiDeallocate(signature);
-
- /* Make sure we save a global reference to this class in the table */
- HPROF_ASSERT(cnum!=0);
- (void)class_new_classref(env, cnum, klass);
- return cnum;
-}
-
-/* Get the ClassIndex for the superClass of this jclass. */
-static ClassIndex
-get_super(JNIEnv *env, jclass klass)
-{
- ClassIndex super_cnum;
-
- super_cnum = 0;
- WITH_LOCAL_REFS(env, 1) {
- jclass super_klass;
-
- super_klass = getSuperclass(env, klass);
- if ( super_klass != NULL ) {
- super_cnum = find_cnum(env, super_klass,
- getClassLoader(super_klass));
- }
- } END_WITH_LOCAL_REFS;
- return super_cnum;
-}
-
-/* Record an allocation. Could be jobject, jclass, jarray or primitive type. */
-static void
-any_allocation(JNIEnv *env, SerialNumber thread_serial_num,
- TraceIndex trace_index, jobject object)
-{
- SiteIndex site_index;
- ClassIndex cnum;
- jint size;
- jclass klass;
-
- /* NOTE: Normally the getObjectClass() and getClassLoader()
- * would require a
- * WITH_LOCAL_REFS(env, 1) {
- * } END_WITH_LOCAL_REFS;
- * but for performance reasons we skip it here.
- */
-
- /* Get and tag the klass */
- klass = getObjectClass(env, object);
- cnum = find_cnum(env, klass, getClassLoader(klass));
- site_index = site_find_or_create(cnum, trace_index);
- tag_class(env, klass, cnum, thread_serial_num, site_index);
-
- /* Tag the object */
- size = (jint)getObjectSize(object);
- tag_new_object(object, OBJECT_NORMAL, thread_serial_num, size, site_index);
-}
-
-/* Handle a java.lang.Object.<init> object allocation. */
-void
-event_object_init(JNIEnv *env, jthread thread, jobject object)
-{
- /* Called via BCI Tracker class */
-
- /* Be very careful what is called here, watch out for recursion. */
-
- jint *pstatus;
- TraceIndex trace_index;
- SerialNumber thread_serial_num;
-
- HPROF_ASSERT(env!=NULL);
- HPROF_ASSERT(thread!=NULL);
- HPROF_ASSERT(object!=NULL);
-
- /* Prevent recursion into any BCI function for this thread (pstatus). */
- if ( tls_get_tracker_status(env, thread, JNI_TRUE,
- &pstatus, NULL, &thread_serial_num, &trace_index) == 0 ) {
- (*pstatus) = 1;
- any_allocation(env, thread_serial_num, trace_index, object);
- (*pstatus) = 0;
- }
-}
-
-/* Handle any newarray opcode allocation. */
-void
-event_newarray(JNIEnv *env, jthread thread, jobject object)
-{
- /* Called via BCI Tracker class */
-
- /* Be very careful what is called here, watch out for recursion. */
-
- jint *pstatus;
- TraceIndex trace_index;
- SerialNumber thread_serial_num;
-
- HPROF_ASSERT(env!=NULL);
- HPROF_ASSERT(thread!=NULL);
- HPROF_ASSERT(object!=NULL);
-
- /* Prevent recursion into any BCI function for this thread (pstatus). */
- if ( tls_get_tracker_status(env, thread, JNI_FALSE,
- &pstatus, NULL, &thread_serial_num, &trace_index) == 0 ) {
- (*pstatus) = 1;
- any_allocation(env, thread_serial_num, trace_index, object);
- (*pstatus) = 0;
- }
-}
-
-/* Handle tracking of a method call. */
-void
-event_call(JNIEnv *env, jthread thread, ClassIndex cnum, MethodIndex mnum)
-{
- /* Called via BCI Tracker class */
-
- /* Be very careful what is called here, watch out for recursion. */
-
- TlsIndex tls_index;
- jint *pstatus;
-
- HPROF_ASSERT(env!=NULL);
- HPROF_ASSERT(thread!=NULL);
- if (cnum == 0 || cnum == gdata->tracker_cnum) {
- jclass newExcCls = (*env)->FindClass(env, "java/lang/IllegalArgumentException");
- (*env)->ThrowNew(env, newExcCls, "Illegal cnum.");
-
- return;
- }
-
- /* Prevent recursion into any BCI function for this thread (pstatus). */
- if ( tls_get_tracker_status(env, thread, JNI_FALSE,
- &pstatus, &tls_index, NULL, NULL) == 0 ) {
- jmethodID method;
-
- (*pstatus) = 1;
- method = class_get_methodID(env, cnum, mnum);
- if (method != NULL) {
- tls_push_method(tls_index, method);
- }
-
- (*pstatus) = 0;
- }
-}
-
-/* Handle tracking of an exception catch */
-void
-event_exception_catch(JNIEnv *env, jthread thread, jmethodID method,
- jlocation location, jobject exception)
-{
- /* Called via JVMTI_EVENT_EXCEPTION_CATCH callback */
-
- /* Be very careful what is called here, watch out for recursion. */
-
- TlsIndex tls_index;
- jint *pstatus;
-
- HPROF_ASSERT(env!=NULL);
- HPROF_ASSERT(thread!=NULL);
- HPROF_ASSERT(method!=NULL);
-
- /* Prevent recursion into any BCI function for this thread (pstatus). */
- if ( tls_get_tracker_status(env, thread, JNI_FALSE,
- &pstatus, &tls_index, NULL, NULL) == 0 ) {
- (*pstatus) = 1;
- tls_pop_exception_catch(tls_index, thread, method);
- (*pstatus) = 0;
- }
-}
-
-/* Handle tracking of a method return pop one (maybe more) methods. */
-void
-event_return(JNIEnv *env, jthread thread, ClassIndex cnum, MethodIndex mnum)
-{
- /* Called via BCI Tracker class */
-
- /* Be very careful what is called here, watch out for recursion. */
-
- TlsIndex tls_index;
- jint *pstatus;
-
- HPROF_ASSERT(env!=NULL);
- HPROF_ASSERT(thread!=NULL);
-
- if (cnum == 0 || cnum == gdata->tracker_cnum) {
- jclass newExcCls = (*env)->FindClass(env, "java/lang/IllegalArgumentException");
- (*env)->ThrowNew(env, newExcCls, "Illegal cnum.");
-
- return;
- }
-
- /* Prevent recursion into any BCI function for this thread (pstatus). */
- if ( tls_get_tracker_status(env, thread, JNI_FALSE,
- &pstatus, &tls_index, NULL, NULL) == 0 ) {
- jmethodID method;
-
- (*pstatus) = 1;
- method = class_get_methodID(env, cnum, mnum);
- if (method != NULL) {
- tls_pop_method(tls_index, thread, method);
- }
-
- (*pstatus) = 0;
- }
-}
-
-/* Handle a class prepare (should have been already loaded) */
-void
-event_class_prepare(JNIEnv *env, jthread thread, jclass klass, jobject loader)
-{
- /* Called via JVMTI_EVENT_CLASS_PREPARE event */
-
- ClassIndex cnum;
-
- HPROF_ASSERT(env!=NULL);
- HPROF_ASSERT(thread!=NULL);
- HPROF_ASSERT(klass!=NULL);
-
- /* Find the ClassIndex for this class */
- cnum = find_cnum(env, klass, loader);
- class_add_status(cnum, CLASS_PREPARED);
-
-}
-
-/* Handle a class load (could have been already loaded) */
-void
-event_class_load(JNIEnv *env, jthread thread, jclass klass, jobject loader)
-{
- /* Called via JVMTI_EVENT_CLASS_LOAD event or reset_class_load_status() */
-
- ClassIndex cnum;
-
- HPROF_ASSERT(env!=NULL);
- HPROF_ASSERT(klass!=NULL);
-
- /* Find the ClassIndex for this class */
- cnum = find_cnum(env, klass, loader);
-
- /* Always mark it as being in the load list */
- class_add_status(cnum, CLASS_IN_LOAD_LIST);
-
- /* If we are seeing this as a new loaded class, extra work */
- if ( ! ( class_get_status(cnum) & CLASS_LOADED ) ) {
- TraceIndex trace_index;
- SiteIndex site_index;
- ClassIndex super;
- SerialNumber class_serial_num;
- SerialNumber trace_serial_num;
- SerialNumber thread_serial_num;
- ObjectIndex class_object_index;
- char *signature;
-
- /* Get the TlsIndex and a TraceIndex for this location */
- if ( thread == NULL ) {
- /* This should be very rare, but if this class load was simulated
- * from hprof_init.c due to a reset of the class load status,
- * and it originated from a pre-VM_INIT event, the jthread
- * would be NULL, or it was a jclass created that didn't get
- * reported to us, like an array class or a primitive class?
- */
- trace_index = gdata->system_trace_index;
- thread_serial_num = gdata->unknown_thread_serial_num;
- } else {
- TlsIndex tls_index;
-
- tls_index = tls_find_or_create(env, thread);
- trace_index = get_current(tls_index, env, JNI_FALSE);
- thread_serial_num = tls_get_thread_serial_number(tls_index);
- }
-
- /* Get the SiteIndex for this location and a java.lang.Class object */
- /* Note that the target cnum, not the cnum for java.lang.Class. */
- site_index = site_find_or_create(cnum, trace_index);
-
- /* Tag this java.lang.Class object */
- tag_class(env, klass, cnum, thread_serial_num, site_index);
-
- class_add_status(cnum, CLASS_LOADED);
-
- class_serial_num = class_get_serial_number(cnum);
- class_object_index = class_get_object_index(cnum);
- trace_serial_num = trace_get_serial_number(trace_index);
- signature = string_get(class_get_signature(cnum));
-
- rawMonitorEnter(gdata->data_access_lock); {
- io_write_class_load(class_serial_num, class_object_index,
- trace_serial_num, signature);
- } rawMonitorExit(gdata->data_access_lock);
-
- super = get_super(env, klass);
- class_set_super(cnum, super);
- }
-
-}
-
-/* Handle a thread start event */
-void
-event_thread_start(JNIEnv *env, jthread thread)
-{
- /* Called via JVMTI_EVENT_THREAD_START event */
-
- TlsIndex tls_index;
- ObjectIndex object_index;
- TraceIndex trace_index;
- jlong tag;
- SerialNumber thread_serial_num;
-
- HPROF_ASSERT(env!=NULL);
- HPROF_ASSERT(thread!=NULL);
-
- tls_index = tls_find_or_create(env, thread);
- thread_serial_num = tls_get_thread_serial_number(tls_index);
- trace_index = get_current(tls_index, env, JNI_FALSE);
-
- tag = getTag(thread);
- if ( tag == (jlong)0 ) {
- SiteIndex site_index;
- jint size;
-
- size = (jint)getObjectSize(thread);
- site_index = site_find_or_create(gdata->thread_cnum, trace_index);
- /* We create a new object with this thread's serial number */
- object_index = object_new(site_index, size, OBJECT_NORMAL,
- thread_serial_num);
- } else {
- object_index = tag_extract(tag);
- /* Normally the Thread object is created and tagged before we get
- * here, but the thread_serial_number on this object isn't what
- * we want. So we update it to the serial number of this thread.
- */
- object_set_thread_serial_number(object_index, thread_serial_num);
- }
- tls_set_thread_object_index(tls_index, object_index);
-
- WITH_LOCAL_REFS(env, 1) {
- jvmtiThreadInfo threadInfo;
- jvmtiThreadGroupInfo threadGroupInfo;
- jvmtiThreadGroupInfo parentGroupInfo;
-
- getThreadInfo(thread, &threadInfo);
- getThreadGroupInfo(threadInfo.thread_group, &threadGroupInfo);
- if ( threadGroupInfo.parent != NULL ) {
- getThreadGroupInfo(threadGroupInfo.parent, &parentGroupInfo);
- } else {
- (void)memset(&parentGroupInfo, 0, sizeof(parentGroupInfo));
- }
-
- rawMonitorEnter(gdata->data_access_lock); {
- io_write_thread_start(thread_serial_num,
- object_index, trace_get_serial_number(trace_index),
- threadInfo.name, threadGroupInfo.name, parentGroupInfo.name);
- } rawMonitorExit(gdata->data_access_lock);
-
- jvmtiDeallocate(threadInfo.name);
- jvmtiDeallocate(threadGroupInfo.name);
- jvmtiDeallocate(parentGroupInfo.name);
-
- } END_WITH_LOCAL_REFS;
-}
-
-void
-event_thread_end(JNIEnv *env, jthread thread)
-{
- /* Called via JVMTI_EVENT_THREAD_END event */
- TlsIndex tls_index;
-
- HPROF_ASSERT(env!=NULL);
- HPROF_ASSERT(thread!=NULL);
-
- tls_index = tls_find_or_create(env, thread);
- rawMonitorEnter(gdata->data_access_lock); {
- io_write_thread_end(tls_get_thread_serial_number(tls_index));
- } rawMonitorExit(gdata->data_access_lock);
- tls_thread_ended(env, tls_index);
- setThreadLocalStorage(thread, (void*)NULL);
-}
--- a/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_event.h Thu Aug 20 12:29:58 2015 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,60 +0,0 @@
-/*
- * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * - Neither the name of Oracle nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
- * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/*
- * This source code is provided to illustrate the usage of a given feature
- * or technique and has been deliberately simplified. Additional steps
- * required for a production-quality application, such as security checks,
- * input validation and proper error handling, might not be present in
- * this sample code.
- */
-
-
-#ifndef HPROF_EVENT_H
-#define HPROF_EVENT_H
-
-/* From BCI: */
-void event_object_init(JNIEnv *env, jthread thread, jobject obj);
-void event_newarray(JNIEnv *env, jthread thread, jobject obj);
-void event_call(JNIEnv *env, jthread thread,
- ClassIndex cnum, MethodIndex mnum);
-void event_return(JNIEnv *env, jthread thread,
- ClassIndex cnum, MethodIndex mnum);
-
-/* From JVMTI: */
-void event_class_load(JNIEnv *env, jthread thread, jclass klass, jobject loader);
-void event_class_prepare(JNIEnv *env, jthread thread, jclass klass, jobject loader);
-void event_thread_start(JNIEnv *env_id, jthread thread);
-void event_thread_end(JNIEnv *env_id, jthread thread);
-void event_exception_catch(JNIEnv *env, jthread thread, jmethodID method,
- jlocation location, jobject exception);
-
-#endif
--- a/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_frame.c Thu Aug 20 12:29:58 2015 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,210 +0,0 @@
-/*
- * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * - Neither the name of Oracle nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
- * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/*
- * This source code is provided to illustrate the usage of a given feature
- * or technique and has been deliberately simplified. Additional steps
- * required for a production-quality application, such as security checks,
- * input validation and proper error handling, might not be present in
- * this sample code.
- */
-
-
-/* This file contains support for handling frames, or (method,location) pairs. */
-
-#include "hprof.h"
-
-/*
- * Frames map 1-to-1 to (methodID,location) pairs.
- * When no line number is known, -1 should be used.
- *
- * Frames are mostly used in traces (see hprof_trace.c) and will be marked
- * with their status flag as they are written out to the hprof output file.
- *
- */
-
-enum LinenoState {
- LINENUM_UNINITIALIZED = 0,
- LINENUM_AVAILABLE = 1,
- LINENUM_UNAVAILABLE = 2
-};
-
-typedef struct FrameKey {
- jmethodID method;
- jlocation location;
-} FrameKey;
-
-typedef struct FrameInfo {
- unsigned short lineno;
- unsigned char lineno_state; /* LinenoState */
- unsigned char status;
- SerialNumber serial_num;
-} FrameInfo;
-
-static FrameKey*
-get_pkey(FrameIndex index)
-{
- void *key_ptr;
- int key_len;
-
- table_get_key(gdata->frame_table, index, &key_ptr, &key_len);
- HPROF_ASSERT(key_len==sizeof(FrameKey));
- HPROF_ASSERT(key_ptr!=NULL);
- return (FrameKey*)key_ptr;
-}
-
-static FrameInfo *
-get_info(FrameIndex index)
-{
- FrameInfo *info;
-
- info = (FrameInfo*)table_get_info(gdata->frame_table, index);
- return info;
-}
-
-static void
-list_item(TableIndex i, void *key_ptr, int key_len, void *info_ptr, void *arg)
-{
- FrameKey key;
- FrameInfo *info;
-
- HPROF_ASSERT(key_ptr!=NULL);
- HPROF_ASSERT(key_len==sizeof(FrameKey));
- HPROF_ASSERT(info_ptr!=NULL);
-
- key = *((FrameKey*)key_ptr);
- info = (FrameInfo*)info_ptr;
- debug_message(
- "Frame 0x%08x: method=%p, location=%d, lineno=%d(%d), status=%d \n",
- i, (void*)key.method, (jint)key.location,
- info->lineno, info->lineno_state, info->status);
-}
-
-void
-frame_init(void)
-{
- gdata->frame_table = table_initialize("Frame",
- 1024, 1024, 1023, (int)sizeof(FrameInfo));
-}
-
-FrameIndex
-frame_find_or_create(jmethodID method, jlocation location)
-{
- FrameIndex index;
- static FrameKey empty_key;
- FrameKey key;
- jboolean new_one;
-
- key = empty_key;
- key.method = method;
- key.location = location;
- new_one = JNI_FALSE;
- index = table_find_or_create_entry(gdata->frame_table,
- &key, (int)sizeof(key), &new_one, NULL);
- if ( new_one ) {
- FrameInfo *info;
-
- info = get_info(index);
- info->lineno_state = LINENUM_UNINITIALIZED;
- if ( location < 0 ) {
- info->lineno_state = LINENUM_UNAVAILABLE;
- }
- info->serial_num = gdata->frame_serial_number_counter++;
- }
- return index;
-}
-
-void
-frame_list(void)
-{
- debug_message(
- "--------------------- Frame Table ------------------------\n");
- table_walk_items(gdata->frame_table, &list_item, NULL);
- debug_message(
- "----------------------------------------------------------\n");
-}
-
-void
-frame_cleanup(void)
-{
- table_cleanup(gdata->frame_table, NULL, NULL);
- gdata->frame_table = NULL;
-}
-
-void
-frame_set_status(FrameIndex index, jint status)
-{
- FrameInfo *info;
-
- info = get_info(index);
- info->status = (unsigned char)status;
-}
-
-void
-frame_get_location(FrameIndex index, SerialNumber *pserial_num,
- jmethodID *pmethod, jlocation *plocation, jint *plineno)
-{
- FrameKey *pkey;
- FrameInfo *info;
- jint lineno;
-
- pkey = get_pkey(index);
- *pmethod = pkey->method;
- *plocation = pkey->location;
- info = get_info(index);
- lineno = (jint)info->lineno;
- if ( info->lineno_state == LINENUM_UNINITIALIZED ) {
- info->lineno_state = LINENUM_UNAVAILABLE;
- if ( gdata->lineno_in_traces ) {
- if ( pkey->location >= 0 && !isMethodNative(pkey->method) ) {
- lineno = getLineNumber(pkey->method, pkey->location);
- if ( lineno >= 0 ) {
- info->lineno = (unsigned short)lineno; /* save it */
- info->lineno_state = LINENUM_AVAILABLE;
- }
- }
- }
- }
- if ( info->lineno_state == LINENUM_UNAVAILABLE ) {
- lineno = -1;
- }
- *plineno = lineno;
- *pserial_num = info->serial_num;
-}
-
-jint
-frame_get_status(FrameIndex index)
-{
- FrameInfo *info;
-
- info = get_info(index);
- return (jint)info->status;
-}
--- a/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_frame.h Thu Aug 20 12:29:58 2015 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,54 +0,0 @@
-/*
- * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * - Neither the name of Oracle nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
- * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/*
- * This source code is provided to illustrate the usage of a given feature
- * or technique and has been deliberately simplified. Additional steps
- * required for a production-quality application, such as security checks,
- * input validation and proper error handling, might not be present in
- * this sample code.
- */
-
-
-#ifndef HPROF_FRAME_H
-#define HPROF_FRAME_H
-
-void frame_init(void);
-FrameIndex frame_find_or_create(jmethodID method, jlocation location);
-void frame_list(void);
-void frame_cleanup(void);
-void frame_get_location(FrameIndex frame_num, SerialNumber *serial_num,
- jmethodID *pmethod,
- jlocation *plocation, jint *plineno);
-void frame_set_status(FrameIndex frame_num, jint status);
-jint frame_get_status(FrameIndex frame_num);
-
-#endif
--- a/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_init.c Thu Aug 20 12:29:58 2015 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,2145 +0,0 @@
-/*
- * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * - Neither the name of Oracle nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
- * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/*
- * This source code is provided to illustrate the usage of a given feature
- * or technique and has been deliberately simplified. Additional steps
- * required for a production-quality application, such as security checks,
- * input validation and proper error handling, might not be present in
- * this sample code.
- */
-
-
-/* Main source file, the basic JVMTI connection/startup code. */
-
-#include "hprof.h"
-
-#include "java_crw_demo.h"
-
-/*
- * This file contains all the startup logic (Agent_Onload) and
- * connection to the JVMTI interface.
- * All JVMTI Event callbacks are in this file.
- * All setting of global data (gdata) is done here.
- * Options are parsed here.
- * Option help messages are here.
- * Termination handled here (VM_DEATH) and shutdown (Agent_OnUnload).
- * Spawning of the cpu sample loop thread and listener thread is done here.
- *
- * Use of private 'static' data has been limited, most shared static data
- * should be found in the GlobalData structure pointed to by gdata
- * (see hprof.h).
- *
- */
-
-/* The default output filenames. */
-
-#define DEFAULT_TXT_SUFFIX ".txt"
-#define DEFAULT_OUTPUTFILE "java.hprof"
-#define DEFAULT_OUTPUTTEMP "java.hprof.temp"
-
-/* The only global variable, defined by this library */
-GlobalData *gdata;
-
-/* Experimental options */
-#define EXPERIMENT_NO_EARLY_HOOK 0x1
-
-/* Default trace depth */
-#define DEFAULT_TRACE_DEPTH 4
-
-/* Default sample interval */
-#define DEFAULT_SAMPLE_INTERVAL 10
-
-/* Default cutoff */
-#define DEFAULT_CUTOFF_POINT 0.0001
-
-/* Stringize macros for help. */
-#define _TO_STR(a) #a
-#define TO_STR(a) _TO_STR(a)
-
-/* Macros to surround callback code (non-VM_DEATH callbacks).
- * Note that this just keeps a count of the non-VM_DEATH callbacks that
- * are currently active, it does not prevent these callbacks from
- * operating in parallel. It's the VM_DEATH callback that will wait
- * for all these callbacks to either complete and block, or just block.
- * We need to hold back these threads so they don't die during the final
- * VM_DEATH processing.
- * If the VM_DEATH callback is active in the beginning, then this callback
- * just blocks to prevent further execution of the thread.
- * If the VM_DEATH callback is active at the end, then this callback
- * will notify the VM_DEATH callback if it's the last one.
- * In all cases, the last thing they do is Enter/Exit the monitor
- * gdata->callbackBlock, which will block this callback if VM_DEATH
- * is running.
- *
- * WARNING: No not 'return' or 'goto' out of the BEGIN_CALLBACK/END_CALLBACK
- * block, this will mess up the count.
- */
-
-#define BEGIN_CALLBACK() \
-{ /* BEGIN OF CALLBACK */ \
- jboolean bypass; \
- rawMonitorEnter(gdata->callbackLock); \
- if (gdata->vm_death_callback_active) { \
- /* VM_DEATH is active, we will bypass the CALLBACK CODE */ \
- bypass = JNI_TRUE; \
- rawMonitorExit(gdata->callbackLock); \
- /* Bypassed CALLBACKS block here until VM_DEATH done */ \
- rawMonitorEnter(gdata->callbackBlock); \
- rawMonitorExit(gdata->callbackBlock); \
- } else { \
- /* We will be executing the CALLBACK CODE in this case */ \
- gdata->active_callbacks++; \
- bypass = JNI_FALSE; \
- rawMonitorExit(gdata->callbackLock); \
- } \
- if ( !bypass ) { \
- /* BODY OF CALLBACK CODE (with no callback locks held) */
-
-#define END_CALLBACK() /* Part of bypass if body */ \
- rawMonitorEnter(gdata->callbackLock); \
- gdata->active_callbacks--; \
- /* If VM_DEATH is active, and last one, send notify. */ \
- if (gdata->vm_death_callback_active) { \
- if (gdata->active_callbacks == 0) { \
- rawMonitorNotifyAll(gdata->callbackLock); \
- } \
- } \
- rawMonitorExit(gdata->callbackLock); \
- /* Non-Bypassed CALLBACKS block here until VM_DEATH done */ \
- rawMonitorEnter(gdata->callbackBlock); \
- rawMonitorExit(gdata->callbackBlock); \
- } \
-} /* END OF CALLBACK */
-
-/* Forward declarations */
-static void set_callbacks(jboolean on);
-
-/* ------------------------------------------------------------------- */
-/* Global data initialization */
-
-/* Get initialized global data area */
-static GlobalData *
-get_gdata(void)
-{
- static GlobalData data;
-
- /* Create initial default values */
- (void)memset(&data, 0, sizeof(GlobalData));
-
- data.fd = -1; /* Non-zero file or socket. */
- data.heap_fd = -1; /* For heap=dump, see hprof_io */
- data.check_fd = -1; /* For heap=dump, see hprof_io */
- data.max_trace_depth = DEFAULT_TRACE_DEPTH;
- data.prof_trace_depth = DEFAULT_TRACE_DEPTH;
- data.sample_interval = DEFAULT_SAMPLE_INTERVAL;
- data.lineno_in_traces = JNI_TRUE;
- data.output_format = 'a'; /* 'b' for binary */
- data.cutoff_point = DEFAULT_CUTOFF_POINT;
- data.dump_on_exit = JNI_TRUE;
- data.gc_start_time = -1L;
-#ifdef DEBUG
- data.debug = JNI_TRUE;
- data.coredump = JNI_TRUE;
-#endif
- data.micro_state_accounting = JNI_FALSE;
- data.force_output = JNI_TRUE;
- data.verbose = JNI_TRUE;
- data.primfields = JNI_TRUE;
- data.primarrays = JNI_TRUE;
-
- data.table_serial_number_start = 1;
- data.class_serial_number_start = 100000;
- data.thread_serial_number_start = 200000;
- data.trace_serial_number_start = 300000;
- data.object_serial_number_start = 400000;
- data.frame_serial_number_start = 500000;
- data.gref_serial_number_start = 1;
-
- data.table_serial_number_counter = data.table_serial_number_start;
- data.class_serial_number_counter = data.class_serial_number_start;
- data.thread_serial_number_counter = data.thread_serial_number_start;
- data.trace_serial_number_counter = data.trace_serial_number_start;
- data.object_serial_number_counter = data.object_serial_number_start;
- data.frame_serial_number_counter = data.frame_serial_number_start;
- data.gref_serial_number_counter = data.gref_serial_number_start;
-
- data.unknown_thread_serial_num = data.thread_serial_number_counter++;
- return &data;
-}
-
-/* ------------------------------------------------------------------- */
-/* Error handler callback for the java_crw_demo (classfile read write) functions. */
-
-static void
-my_crw_fatal_error_handler(const char * msg, const char *file, int line)
-{
- char errmsg[256];
-
- (void)md_snprintf(errmsg, sizeof(errmsg),
- "%s [%s:%d]", msg, file, line);
- errmsg[sizeof(errmsg)-1] = 0;
- HPROF_ERROR(JNI_TRUE, errmsg);
-}
-
-static void
-list_all_tables(void)
-{
- string_list();
- class_list();
- frame_list();
- site_list();
- object_list();
- trace_list();
- monitor_list();
- tls_list();
- loader_list();
-}
-
-/* ------------------------------------------------------------------- */
-/* Option Parsing support */
-
-/**
- * Socket connection
- */
-
-/*
- * Return a socket connect()ed to a "hostname" that is
- * accept()ing heap profile data on "port." Return a value <= 0 if
- * such a connection can't be made.
- */
-static int
-connect_to_socket(char *hostname, int port)
-{
- int fd;
-
- if (port == 0 || port > 65535) {
- HPROF_ERROR(JNI_FALSE, "invalid port number");
- return -1;
- }
- if (hostname == NULL) {
- HPROF_ERROR(JNI_FALSE, "hostname is NULL");
- return -1;
- }
-
- /* create a socket */
- fd = md_connect(hostname, (unsigned short)port);
- return fd;
-}
-
-/* Accept a filename, and adjust the name so that it is unique for this PID */
-static void
-make_unique_filename(char **filename)
-{
- int fd;
-
- /* Find a file that doesn't exist */
- fd = md_open(*filename);
- if ( fd >= 0 ) {
- int pid;
- char *new_name;
- char *old_name;
- char *prefix;
- char suffix[5];
- int new_len;
-
- /* Close the file. */
- md_close(fd);
-
- /* Make filename name.PID[.txt] */
- pid = md_getpid();
- old_name = *filename;
- new_len = (int)strlen(old_name)+64;
- new_name = HPROF_MALLOC(new_len);
- prefix = old_name;
- suffix[0] = 0;
-
- /* Look for .txt suffix if not binary output */
- if (gdata->output_format != 'b') {
- char *dot;
- char *format_suffix;
-
- format_suffix = DEFAULT_TXT_SUFFIX;
-
- (void)strcpy(suffix, format_suffix);
-
- dot = strrchr(old_name, '.');
- if ( dot != NULL ) {
- int i;
- int slen;
- int match;
-
- slen = (int)strlen(format_suffix);
- match = 1;
- for ( i = 0; i < slen; i++ ) {
- if ( dot[i]==0 ||
- tolower(format_suffix[i]) != tolower(dot[i]) ) {
- match = 0;
- break;
- }
- }
- if ( match ) {
- (void)strcpy(suffix, dot);
- *dot = 0; /* truncates prefix and old_name */
- }
- }
- }
-
- /* Construct the name */
- (void)md_snprintf(new_name, new_len,
- "%s.%d%s", prefix, pid, suffix);
- *filename = new_name;
- HPROF_FREE(old_name);
-
- /* Odds are with Windows, this file may not be so unique. */
- (void)remove(gdata->output_filename);
- }
-}
-
-static int
-get_tok(char **src, char *buf, int buflen, int sep)
-{
- int len;
- char *p;
-
- buf[0] = 0;
- if ( **src == 0 ) {
- return 0;
- }
- p = strchr(*src, sep);
- if ( p==NULL ) {
- len = (int)strlen(*src);
- p = (*src) + len;
- } else {
- /*LINTED*/
- len = (int)(p - (*src));
- }
- if ( (len+1) > buflen ) {
- return 0;
- }
- (void)memcpy(buf, *src, len);
- buf[len] = 0;
- if ( *p != 0 && *p == sep ) {
- (*src) = p+1;
- } else {
- (*src) = p;
- }
- return len;
-}
-
-static jboolean
-setBinarySwitch(char **src, jboolean *ptr)
-{
- char buf[80];
-
- if (!get_tok(src, buf, (int)sizeof(buf), ',')) {
- return JNI_FALSE;
- }
- if (strcmp(buf, "y") == 0) {
- *ptr = JNI_TRUE;
- } else if (strcmp(buf, "n") == 0) {
- *ptr = JNI_FALSE;
- } else {
- return JNI_FALSE;
- }
- return JNI_TRUE;
-}
-
-static void
-print_usage(void)
-{
-
- (void)fprintf(stdout,
-"\n"
-" HPROF: Heap and CPU Profiling Agent (JVMTI Demonstration Code)\n"
-"\n"
-AGENTNAME " usage: java " AGENTLIB "=[help]|[<option>=<value>, ...]\n"
-"\n"
-"Option Name and Value Description Default\n"
-"--------------------- ----------- -------\n"
-"heap=dump|sites|all heap profiling all\n"
-"cpu=samples|times|old CPU usage off\n"
-"monitor=y|n monitor contention n\n"
-"format=a|b text(txt) or binary output a\n"
-"file=<file> write data to file " DEFAULT_OUTPUTFILE "[{" DEFAULT_TXT_SUFFIX "}]\n"
-"net=<host>:<port> send data over a socket off\n"
-"depth=<size> stack trace depth " TO_STR(DEFAULT_TRACE_DEPTH) "\n"
-"interval=<ms> sample interval in ms " TO_STR(DEFAULT_SAMPLE_INTERVAL) "\n"
-"cutoff=<value> output cutoff point " TO_STR(DEFAULT_CUTOFF_POINT) "\n"
-"lineno=y|n line number in traces? y\n"
-"thread=y|n thread in traces? n\n"
-"doe=y|n dump on exit? y\n"
-"msa=y|n Solaris micro state accounting n\n"
-"force=y|n force output to <file> y\n"
-"verbose=y|n print messages about dumps y\n"
-"\n"
-"Obsolete Options\n"
-"----------------\n"
-"gc_okay=y|n\n"
-
-#ifdef DEBUG
-"\n"
-"DEBUG Option Description Default\n"
-"------------ ----------- -------\n"
-"primfields=y|n include primitive field values y\n"
-"primarrays=y|n include primitive array values y\n"
-"debugflags=MASK Various debug flags 0\n"
-" 0x01 Report refs in and of unprepared classes\n"
-"logflags=MASK Logging to stderr 0\n"
-" " TO_STR(LOG_DUMP_MISC) " Misc logging\n"
-" " TO_STR(LOG_DUMP_LISTS) " Dump out the tables\n"
-" " TO_STR(LOG_CHECK_BINARY) " Verify & dump format=b\n"
-"coredump=y|n Core dump on fatal n\n"
-"errorexit=y|n Exit on any error n\n"
-"pause=y|n Pause on onload & echo PID n\n"
-"debug=y|n Turn on all debug checking n\n"
-"X=MASK Internal use only 0\n"
-
-"\n"
-"Environment Variables\n"
-"---------------------\n"
-"_JAVA_HPROF_OPTIONS\n"
-" Options can be added externally via this environment variable.\n"
-" Anything contained in it will get a comma prepended to it (if needed),\n"
-" then it will be added to the end of the options supplied via the\n"
-" " XRUN " or " AGENTLIB " command line option.\n"
-
-#endif
-
-"\n"
-"Examples\n"
-"--------\n"
-" - Get sample cpu information every 20 millisec, with a stack depth of 3:\n"
-" java " AGENTLIB "=cpu=samples,interval=20,depth=3 classname\n"
-" - Get heap usage information based on the allocation sites:\n"
-" java " AGENTLIB "=heap=sites classname\n"
-
-#ifdef DEBUG
-" - Using the external option addition with csh, log details on all runs:\n"
-" setenv _JAVA_HPROF_OPTIONS \"logflags=0xC\"\n"
-" java " AGENTLIB "=cpu=samples classname\n"
-" is the same as:\n"
-" java " AGENTLIB "=cpu=samples,logflags=0xC classname\n"
-#endif
-
-"\n"
-"Notes\n"
-"-----\n"
-" - The option format=b cannot be used with monitor=y.\n"
-" - The option format=b cannot be used with cpu=old|times.\n"
-" - Use of the " XRUN " interface can still be used, e.g.\n"
-" java " XRUN ":[help]|[<option>=<value>, ...]\n"
-" will behave exactly the same as:\n"
-" java " AGENTLIB "=[help]|[<option>=<value>, ...]\n"
-
-#ifdef DEBUG
-" - The debug options and environment variables are available with both java\n"
-" and java_g versions.\n"
-#endif
-
-"\n"
-"Warnings\n"
-"--------\n"
-" - This is demonstration code for the JVMTI interface and use of BCI,\n"
-" it is not an official product or formal part of the JDK.\n"
-" - The " XRUN " interface will be removed in a future release.\n"
-" - The option format=b is considered experimental, this format may change\n"
-" in a future release.\n"
-
-#ifdef DEBUG
-" - The obsolete options may be completely removed in a future release.\n"
-" - The debug options and environment variables are not considered public\n"
-" interfaces and can change or be removed with any type of update of\n"
-" " AGENTNAME ", including patches.\n"
-#endif
-
- );
-}
-
-static void
-option_error(char *description)
-{
- char errmsg[FILENAME_MAX+80];
-
- (void)md_snprintf(errmsg, sizeof(errmsg),
- "%s option error: %s (%s)", AGENTNAME, description, gdata->options);
- errmsg[sizeof(errmsg)-1] = 0;
- HPROF_ERROR(JNI_FALSE, errmsg);
- error_exit_process(1);
-}
-
-static void
-parse_options(char *command_line_options)
-{
- int file_or_net_option_seen = JNI_FALSE;
- char *all_options;
- char *extra_options;
- char *options;
- char *default_filename;
- int ulen;
-
- if (command_line_options == 0)
- command_line_options = "";
-
- if ((strcmp(command_line_options, "help")) == 0) {
- print_usage();
- error_exit_process(0);
- }
-
- extra_options = getenv("_JAVA_HPROF_OPTIONS");
- if ( extra_options == NULL ) {
- extra_options = "";
- }
-
- all_options = HPROF_MALLOC((int)strlen(command_line_options) +
- (int)strlen(extra_options) + 2);
- gdata->options = all_options;
- (void)strcpy(all_options, command_line_options);
- if ( extra_options[0] != 0 ) {
- if ( all_options[0] != 0 ) {
- (void)strcat(all_options, ",");
- }
- (void)strcat(all_options, extra_options);
- }
- options = all_options;
-
- LOG2("parse_options()", all_options);
-
- while (*options) {
- char option[16];
- char suboption[FILENAME_MAX+1];
- char *endptr;
-
- if (!get_tok(&options, option, (int)sizeof(option), '=')) {
- option_error("general syntax error parsing options");
- }
- if (strcmp(option, "file") == 0) {
- if ( file_or_net_option_seen ) {
- option_error("file or net options should only appear once");
- }
- if (!get_tok(&options, suboption, (int)sizeof(suboption), ',')) {
- option_error("syntax error parsing file=filename");
- }
- gdata->utf8_output_filename = HPROF_MALLOC((int)strlen(suboption)+1);
- (void)strcpy(gdata->utf8_output_filename, suboption);
- file_or_net_option_seen = JNI_TRUE;
- } else if (strcmp(option, "net") == 0) {
- char port_number[16];
- if (file_or_net_option_seen ) {
- option_error("file or net options should only appear once");
- }
- if (!get_tok(&options, suboption, (int)sizeof(suboption), ':')) {
- option_error("net option missing ':'");
- }
- if (!get_tok(&options, port_number, (int)sizeof(port_number), ',')) {
- option_error("net option missing port");
- }
- gdata->net_hostname = HPROF_MALLOC((int)strlen(suboption)+1);
- (void)strcpy(gdata->net_hostname, suboption);
- gdata->net_port = (int)strtol(port_number, NULL, 10);
- file_or_net_option_seen = JNI_TRUE;
- } else if (strcmp(option, "format") == 0) {
- if (!get_tok(&options, suboption, (int)sizeof(suboption), ',')) {
- option_error("syntax error parsing format=a|b");
- }
- if (strcmp(suboption, "a") == 0) {
- gdata->output_format = 'a';
- } else if (strcmp(suboption, "b") == 0) {
- gdata->output_format = 'b';
- } else {
- option_error("format option value must be a|b");
- }
- } else if (strcmp(option, "depth") == 0) {
- if (!get_tok(&options, suboption, (int)sizeof(suboption), ',')) {
- option_error("syntax error parsing depth=DECIMAL");
- }
- gdata->max_trace_depth = (int)strtol(suboption, &endptr, 10);
- if ((endptr != NULL && *endptr != 0) || gdata->max_trace_depth < 0) {
- option_error("depth option value must be decimal and >= 0");
- }
- gdata->prof_trace_depth = gdata->max_trace_depth;
- } else if (strcmp(option, "interval") == 0) {
- if (!get_tok(&options, suboption, (int)sizeof(suboption), ',')) {
- option_error("syntax error parsing interval=DECIMAL");
- }
- gdata->sample_interval = (int)strtol(suboption, &endptr, 10);
- if ((endptr != NULL && *endptr != 0) || gdata->sample_interval <= 0) {
- option_error("interval option value must be decimal and > 0");
- }
- } else if (strcmp(option, "cutoff") == 0) {
- if (!get_tok(&options, suboption, (int)sizeof(suboption), ',')) {
- option_error("syntax error parsing cutoff=DOUBLE");
- }
- gdata->cutoff_point = strtod(suboption, &endptr);
- if ((endptr != NULL && *endptr != 0) || gdata->cutoff_point < 0) {
- option_error("cutoff option value must be floating point and >= 0");
- }
- } else if (strcmp(option, "cpu") == 0) {
- if (!get_tok(&options, suboption, (int)sizeof(suboption), ',')) {
- option_error("syntax error parsing cpu=y|samples|times|old");
- }
- if ((strcmp(suboption, "samples") == 0) ||
- (strcmp(suboption, "y") == 0)) {
- gdata->cpu_sampling = JNI_TRUE;
- } else if (strcmp(suboption, "times") == 0) {
- gdata->cpu_timing = JNI_TRUE;
- gdata->old_timing_format = JNI_FALSE;
- } else if (strcmp(suboption, "old") == 0) {
- gdata->cpu_timing = JNI_TRUE;
- gdata->old_timing_format = JNI_TRUE;
- } else {
- option_error("cpu option value must be y|samples|times|old");
- }
- } else if (strcmp(option, "heap") == 0) {
- if (!get_tok(&options, suboption, (int)sizeof(suboption), ',')) {
- option_error("syntax error parsing heap=dump|sites|all");
- }
- if (strcmp(suboption, "dump") == 0) {
- gdata->heap_dump = JNI_TRUE;
- } else if (strcmp(suboption, "sites") == 0) {
- gdata->alloc_sites = JNI_TRUE;
- } else if (strcmp(suboption, "all") == 0) {
- gdata->heap_dump = JNI_TRUE;
- gdata->alloc_sites = JNI_TRUE;
- } else {
- option_error("heap option value must be dump|sites|all");
- }
- } else if( strcmp(option,"lineno") == 0) {
- if ( !setBinarySwitch(&options, &(gdata->lineno_in_traces)) ) {
- option_error("lineno option value must be y|n");
- }
- } else if( strcmp(option,"thread") == 0) {
- if ( !setBinarySwitch(&options, &(gdata->thread_in_traces)) ) {
- option_error("thread option value must be y|n");
- }
- } else if( strcmp(option,"doe") == 0) {
- if ( !setBinarySwitch(&options, &(gdata->dump_on_exit)) ) {
- option_error("doe option value must be y|n");
- }
- } else if( strcmp(option,"msa") == 0) {
- if ( !setBinarySwitch(&options, &(gdata->micro_state_accounting)) ) {
- option_error("msa option value must be y|n");
- }
- } else if( strcmp(option,"force") == 0) {
- if ( !setBinarySwitch(&options, &(gdata->force_output)) ) {
- option_error("force option value must be y|n");
- }
- } else if( strcmp(option,"verbose") == 0) {
- if ( !setBinarySwitch(&options, &(gdata->verbose)) ) {
- option_error("verbose option value must be y|n");
- }
- } else if( strcmp(option,"primfields") == 0) {
- if ( !setBinarySwitch(&options, &(gdata->primfields)) ) {
- option_error("primfields option value must be y|n");
- }
- } else if( strcmp(option,"primarrays") == 0) {
- if ( !setBinarySwitch(&options, &(gdata->primarrays)) ) {
- option_error("primarrays option value must be y|n");
- }
- } else if( strcmp(option,"monitor") == 0) {
- if ( !setBinarySwitch(&options, &(gdata->monitor_tracing)) ) {
- option_error("monitor option value must be y|n");
- }
- } else if( strcmp(option,"gc_okay") == 0) {
- if ( !setBinarySwitch(&options, &(gdata->gc_okay)) ) {
- option_error("gc_okay option value must be y|n");
- }
- } else if (strcmp(option, "logflags") == 0) {
- if (!get_tok(&options, suboption, (int)sizeof(suboption), ',')) {
- option_error("logflags option value must be numeric");
- }
- gdata->logflags = (int)strtol(suboption, NULL, 0);
- } else if (strcmp(option, "debugflags") == 0) {
- if (!get_tok(&options, suboption, (int)sizeof(suboption), ',')) {
- option_error("debugflags option value must be numeric");
- }
- gdata->debugflags = (int)strtol(suboption, NULL, 0);
- } else if (strcmp(option, "coredump") == 0) {
- if ( !setBinarySwitch(&options, &(gdata->coredump)) ) {
- option_error("coredump option value must be y|n");
- }
- } else if (strcmp(option, "exitpause") == 0) {
- option_error("The exitpause option was removed, use -XX:OnError='cmd %%p'");
- } else if (strcmp(option, "errorexit") == 0) {
- if ( !setBinarySwitch(&options, &(gdata->errorexit)) ) {
- option_error("errorexit option value must be y|n");
- }
- } else if (strcmp(option, "pause") == 0) {
- if ( !setBinarySwitch(&options, &(gdata->pause)) ) {
- option_error("pause option value must be y|n");
- }
- } else if (strcmp(option, "debug") == 0) {
- if ( !setBinarySwitch(&options, &(gdata->debug)) ) {
- option_error("debug option value must be y|n");
- }
- } else if (strcmp(option, "precrash") == 0) {
- option_error("The precrash option was removed, use -XX:OnError='precrash -p %%p'");
- } else if (strcmp(option, "X") == 0) {
- if (!get_tok(&options, suboption, (int)sizeof(suboption), ',')) {
- option_error("X option value must be numeric");
- }
- gdata->experiment = (int)strtol(suboption, NULL, 0);
- } else {
- char errmsg[80];
- (void)strcpy(errmsg, "Unknown option: ");
- (void)strcat(errmsg, option);
- option_error(errmsg);
- }
- }
-
- if (gdata->output_format == 'b') {
- if (gdata->cpu_timing) {
- option_error("cpu=times|old is not supported with format=b");
- }
- if (gdata->monitor_tracing) {
- option_error("monitor=y is not supported with format=b");
- }
- }
-
- if (gdata->old_timing_format) {
- gdata->prof_trace_depth = 2;
- }
-
- if (gdata->output_format == 'b') {
- default_filename = DEFAULT_OUTPUTFILE;
- } else {
- default_filename = DEFAULT_OUTPUTFILE DEFAULT_TXT_SUFFIX;
- }
-
- if (!file_or_net_option_seen) {
- gdata->utf8_output_filename = HPROF_MALLOC((int)strlen(default_filename)+1);
- (void)strcpy(gdata->utf8_output_filename, default_filename);
- }
-
- if ( gdata->utf8_output_filename != NULL ) {
- // Don't attempt to convert output filename.
- // If fileystem uses the same encoding as the rest of the OS it will work as is.
- ulen = (int)strlen(gdata->utf8_output_filename);
- gdata->output_filename = (char*)HPROF_MALLOC(ulen*3+3);
- (void)strcpy(gdata->output_filename, gdata->utf8_output_filename);
- }
-
- /* By default we turn on gdata->alloc_sites and gdata->heap_dump */
- if ( !gdata->cpu_timing &&
- !gdata->cpu_sampling &&
- !gdata->monitor_tracing &&
- !gdata->alloc_sites &&
- !gdata->heap_dump) {
- gdata->heap_dump = JNI_TRUE;
- gdata->alloc_sites = JNI_TRUE;
- }
-
- if ( gdata->alloc_sites || gdata->heap_dump ) {
- gdata->obj_watch = JNI_TRUE;
- }
- if ( gdata->obj_watch || gdata->cpu_timing ) {
- gdata->bci = JNI_TRUE;
- }
-
- /* Create files & sockets needed */
- if (gdata->heap_dump) {
- char *base;
- int len;
-
- /* Get a fast tempfile for the heap information */
- base = gdata->output_filename;
- if ( base==NULL ) {
- base = default_filename;
- }
- len = (int)strlen(base);
- gdata->heapfilename = HPROF_MALLOC(len + 5);
- (void)strcpy(gdata->heapfilename, base);
- (void)strcat(gdata->heapfilename, ".TMP");
- make_unique_filename(&(gdata->heapfilename));
- (void)remove(gdata->heapfilename);
- if (gdata->output_format == 'b') {
- if ( gdata->logflags & LOG_CHECK_BINARY ) {
- char * check_suffix;
-
- check_suffix = ".check" DEFAULT_TXT_SUFFIX;
- gdata->checkfilename =
- HPROF_MALLOC((int)strlen(default_filename)+
- (int)strlen(check_suffix)+1);
- (void)strcpy(gdata->checkfilename, default_filename);
- (void)strcat(gdata->checkfilename, check_suffix);
- (void)remove(gdata->checkfilename);
- gdata->check_fd = md_creat(gdata->checkfilename);
- }
- if ( gdata->debug ) {
- gdata->logflags |= LOG_CHECK_BINARY;
- }
- gdata->heap_fd = md_creat_binary(gdata->heapfilename);
- } else {
- gdata->heap_fd = md_creat(gdata->heapfilename);
- }
- if ( gdata->heap_fd < 0 ) {
- char errmsg[FILENAME_MAX+80];
-
- (void)md_snprintf(errmsg, sizeof(errmsg),
- "can't create temp heap file: %s", gdata->heapfilename);
- errmsg[sizeof(errmsg)-1] = 0;
- HPROF_ERROR(JNI_TRUE, errmsg);
- }
- }
-
- if ( gdata->net_port > 0 ) {
- LOG2("Agent_OnLoad", "Connecting to socket");
- gdata->fd = connect_to_socket(gdata->net_hostname, gdata->net_port);
- if (gdata->fd <= 0) {
- char errmsg[120];
-
- (void)md_snprintf(errmsg, sizeof(errmsg),
- "can't connect to %s:%u", gdata->net_hostname, gdata->net_port);
- errmsg[sizeof(errmsg)-1] = 0;
- HPROF_ERROR(JNI_FALSE, errmsg);
- error_exit_process(1);
- }
- gdata->socket = JNI_TRUE;
- } else {
- /* If going out to a file, obey the force=y|n option */
- if ( !gdata->force_output ) {
- make_unique_filename(&(gdata->output_filename));
- }
- /* Make doubly sure this file does NOT exist */
- (void)remove(gdata->output_filename);
- /* Create the file */
- if (gdata->output_format == 'b') {
- gdata->fd = md_creat_binary(gdata->output_filename);
- } else {
- gdata->fd = md_creat(gdata->output_filename);
- }
- if (gdata->fd < 0) {
- char errmsg[FILENAME_MAX+80];
-
- (void)md_snprintf(errmsg, sizeof(errmsg),
- "can't create profile file: %s", gdata->output_filename);
- errmsg[sizeof(errmsg)-1] = 0;
- HPROF_ERROR(JNI_FALSE, errmsg);
- error_exit_process(1);
- }
- }
-
-}
-
-/* ------------------------------------------------------------------- */
-/* Data reset and dump functions */
-
-static void
-reset_all_data(void)
-{
- if (gdata->cpu_sampling || gdata->cpu_timing || gdata->monitor_tracing) {
- rawMonitorEnter(gdata->data_access_lock);
- }
-
- if (gdata->cpu_sampling || gdata->cpu_timing) {
- trace_clear_cost();
- }
- if (gdata->monitor_tracing) {
- monitor_clear();
- }
-
- if (gdata->cpu_sampling || gdata->cpu_timing || gdata->monitor_tracing) {
- rawMonitorExit(gdata->data_access_lock);
- }
-}
-
-static void reset_class_load_status(JNIEnv *env, jthread thread);
-
-static void
-dump_all_data(JNIEnv *env)
-{
- verbose_message("Dumping");
- if (gdata->monitor_tracing) {
- verbose_message(" contended monitor usage ...");
- tls_dump_monitor_state(env);
- monitor_write_contended_time(env, gdata->cutoff_point);
- }
- if (gdata->heap_dump) {
- verbose_message(" Java heap ...");
- /* Update the class table */
- reset_class_load_status(env, NULL);
- site_heapdump(env);
- }
- if (gdata->alloc_sites) {
- verbose_message(" allocation sites ...");
- site_write(env, 0, gdata->cutoff_point);
- }
- if (gdata->cpu_sampling) {
- verbose_message(" CPU usage by sampling running threads ...");
- trace_output_cost(env, gdata->cutoff_point);
- }
- if (gdata->cpu_timing) {
- if (!gdata->old_timing_format) {
- verbose_message(" CPU usage by timing methods ...");
- trace_output_cost(env, gdata->cutoff_point);
- } else {
- verbose_message(" CPU usage in old prof format ...");
- trace_output_cost_in_prof_format(env);
- }
- }
- reset_all_data();
- io_flush();
- verbose_message(" done.\n");
-}
-
-/* ------------------------------------------------------------------- */
-/* Dealing with class load and unload status */
-
-static void
-reset_class_load_status(JNIEnv *env, jthread thread)
-{
-
- WITH_LOCAL_REFS(env, 1) {
- jint class_count;
- jclass *classes;
- jint i;
-
- /* Get all classes from JVMTI, make sure they are in the class table. */
- getLoadedClasses(&classes, &class_count);
-
- /* We don't know if the class list has changed really, so we
- * guess by the class count changing. Don't want to do
- * a bunch of work on classes when it's unnecessary.
- * I assume that even though we have global references on the
- * jclass object that the class is still considered unloaded.
- * (e.g. GC of jclass isn't required for it to be included
- * in the unloaded list, or not in the load list)
- * [Note: Use of Weak references was a performance problem.]
- */
- if ( class_count != gdata->class_count ) {
-
- rawMonitorEnter(gdata->data_access_lock); {
-
- /* Unmark the classes in the load list */
- class_all_status_remove(CLASS_IN_LOAD_LIST);
-
- /* Pretend like it was a class load event */
- for ( i = 0 ; i < class_count ; i++ ) {
- jobject loader;
-
- loader = getClassLoader(classes[i]);
- event_class_load(env, thread, classes[i], loader);
- }
-
- /* Process the classes that have been unloaded */
- class_do_unloads(env);
-
- } rawMonitorExit(gdata->data_access_lock);
-
- }
-
- /* Free the space and save the count. */
- jvmtiDeallocate(classes);
- gdata->class_count = class_count;
-
- } END_WITH_LOCAL_REFS;
-
-}
-
-/* A GC or Death event has happened, so do some cleanup */
-static void
-object_free_cleanup(JNIEnv *env, jboolean force_class_table_reset)
-{
- Stack *stack;
-
- /* Then we process the ObjectFreeStack */
- rawMonitorEnter(gdata->object_free_lock); {
- stack = gdata->object_free_stack;
- gdata->object_free_stack = NULL; /* Will trigger new stack */
- } rawMonitorExit(gdata->object_free_lock);
-
- /* Notice we just grabbed the stack of freed objects so
- * any object free events will create a new stack.
- */
- if ( stack != NULL ) {
- int count;
- int i;
-
- count = stack_depth(stack);
-
- /* If we saw something freed in this GC */
- if ( count > 0 ) {
-
- for ( i = 0 ; i < count ; i++ ) {
- ObjectIndex object_index;
- jlong tag;
-
- tag = *(jlong*)stack_element(stack,i);
- object_index = tag_extract(tag);
-
- (void)object_free(object_index);
- }
-
- /* We reset the class load status (only do this once) */
- reset_class_load_status(env, NULL);
- force_class_table_reset = JNI_FALSE;
-
- }
-
- /* Just terminate this stack object */
- stack_term(stack);
- }
-
- /* We reset the class load status if we haven't and need to */
- if ( force_class_table_reset ) {
- reset_class_load_status(env, NULL);
- }
-
-}
-
-/* Main function for thread that watches for GC finish events */
-static void JNICALL
-gc_finish_watcher(jvmtiEnv *jvmti, JNIEnv *env, void *p)
-{
- jboolean active;
-
- active = JNI_TRUE;
-
- /* Indicate the watcher thread is active */
- rawMonitorEnter(gdata->gc_finish_lock); {
- gdata->gc_finish_active = JNI_TRUE;
- } rawMonitorExit(gdata->gc_finish_lock);
-
- /* Loop while active */
- while ( active ) {
- jboolean do_cleanup;
-
- do_cleanup = JNI_FALSE;
- rawMonitorEnter(gdata->gc_finish_lock); {
- /* Don't wait if VM_DEATH wants us to quit */
- if ( gdata->gc_finish_stop_request ) {
- /* Time to terminate */
- active = JNI_FALSE;
- } else {
- /* Wait for notification to do cleanup, or terminate */
- rawMonitorWait(gdata->gc_finish_lock, 0);
- /* After wait, check to see if VM_DEATH wants us to quit */
- if ( gdata->gc_finish_stop_request ) {
- /* Time to terminate */
- active = JNI_FALSE;
- }
- }
- if ( active && gdata->gc_finish > 0 ) {
- /* Time to cleanup, reset count and prepare for cleanup */
- gdata->gc_finish = 0;
- do_cleanup = JNI_TRUE;
- }
- } rawMonitorExit(gdata->gc_finish_lock);
-
- /* Do the cleanup if requested outside gc_finish_lock */
- if ( do_cleanup ) {
- /* Free up all freed objects, don't force class table reset
- * We cannot let the VM_DEATH complete while we are doing
- * this cleanup. So if during this, VM_DEATH happens,
- * the VM_DEATH callback should block waiting for this
- * loop to terminate, and send a notification to the
- * VM_DEATH thread.
- */
- object_free_cleanup(env, JNI_FALSE);
-
- /* Cleanup the tls table where the Thread objects were GC'd */
- tls_garbage_collect(env);
- }
-
- }
-
- /* Falling out means VM_DEATH is happening, we need to notify VM_DEATH
- * that we are done doing the cleanup. VM_DEATH is waiting on this
- * notify.
- */
- rawMonitorEnter(gdata->gc_finish_lock); {
- gdata->gc_finish_active = JNI_FALSE;
- rawMonitorNotifyAll(gdata->gc_finish_lock);
- } rawMonitorExit(gdata->gc_finish_lock);
-}
-
-/* ------------------------------------------------------------------- */
-/* JVMTI Event callback functions */
-
-static void
-setup_event_mode(jboolean onload_set_only, jvmtiEventMode state)
-{
- if ( onload_set_only ) {
- setEventNotificationMode(state,
- JVMTI_EVENT_VM_INIT, NULL);
- setEventNotificationMode(state,
- JVMTI_EVENT_VM_DEATH, NULL);
- if (gdata->bci) {
- setEventNotificationMode(state,
- JVMTI_EVENT_CLASS_FILE_LOAD_HOOK, NULL);
- }
- } else {
- /* Enable all other JVMTI events of interest now. */
- setEventNotificationMode(state,
- JVMTI_EVENT_THREAD_START, NULL);
- setEventNotificationMode(state,
- JVMTI_EVENT_THREAD_END, NULL);
- setEventNotificationMode(state,
- JVMTI_EVENT_CLASS_LOAD, NULL);
- setEventNotificationMode(state,
- JVMTI_EVENT_CLASS_PREPARE, NULL);
- setEventNotificationMode(state,
- JVMTI_EVENT_DATA_DUMP_REQUEST, NULL);
- if (gdata->cpu_timing) {
- setEventNotificationMode(state,
- JVMTI_EVENT_EXCEPTION_CATCH, NULL);
- }
- if (gdata->monitor_tracing) {
- setEventNotificationMode(state,
- JVMTI_EVENT_MONITOR_WAIT, NULL);
- setEventNotificationMode(state,
- JVMTI_EVENT_MONITOR_WAITED, NULL);
- setEventNotificationMode(state,
- JVMTI_EVENT_MONITOR_CONTENDED_ENTER, NULL);
- setEventNotificationMode(state,
- JVMTI_EVENT_MONITOR_CONTENDED_ENTERED, NULL);
- }
- if (gdata->obj_watch) {
- setEventNotificationMode(state,
- JVMTI_EVENT_OBJECT_FREE, NULL);
- }
- setEventNotificationMode(state,
- JVMTI_EVENT_GARBAGE_COLLECTION_START, NULL);
- setEventNotificationMode(state,
- JVMTI_EVENT_GARBAGE_COLLECTION_FINISH, NULL);
- }
-}
-
-/* JVMTI_EVENT_VM_INIT */
-static void JNICALL
-cbVMInit(jvmtiEnv *jvmti, JNIEnv *env, jthread thread)
-{
- rawMonitorEnter(gdata->data_access_lock); {
-
- LoaderIndex loader_index;
- ClassIndex cnum;
- TlsIndex tls_index;
-
- gdata->jvm_initializing = JNI_TRUE;
-
- /* Header to use in heap dumps */
- gdata->header = "JAVA PROFILE 1.0.1";
- gdata->segmented = JNI_FALSE;
- if (gdata->output_format == 'b') {
- /* We need JNI here to call in and get the current maximum memory */
- gdata->maxMemory = getMaxMemory(env);
- gdata->maxHeapSegment = (jlong)2000000000;
- /* More than 2Gig triggers segments and 1.0.2 */
- if ( gdata->maxMemory >= gdata->maxHeapSegment ) {
- gdata->header = "JAVA PROFILE 1.0.2";
- gdata->segmented = JNI_TRUE; /* 1.0.2 */
- }
- }
-
- /* We write the initial header after the VM initializes now
- * because we needed to use JNI to get maxMemory and determine if
- * a 1.0.1 or a 1.0.2 header will be used.
- * This used to be done in Agent_OnLoad.
- */
- io_write_file_header();
-
- LOG("cbVMInit begin");
-
- /* Create a system loader entry first */
- loader_index = loader_find_or_create(NULL,NULL);
-
- /* Find the thread jclass (does JNI calls) */
- gdata->thread_cnum = class_find_or_create("Ljava/lang/Thread;",
- loader_index);
- class_add_status(gdata->thread_cnum, CLASS_SYSTEM);
-
- /* Issue fake system thread start */
- tls_index = tls_find_or_create(env, thread);
-
- /* Setup the Tracker class (should be first class in table) */
- tracker_setup_class();
-
- /* Find selected system classes to keep track of */
- gdata->system_class_size = 0;
- cnum = class_find_or_create("Ljava/lang/Object;", loader_index);
-
- gdata->system_trace_index = tls_get_trace(tls_index, env,
- gdata->max_trace_depth, JNI_FALSE);
- gdata->system_object_site_index = site_find_or_create(
- cnum, gdata->system_trace_index);
-
- /* Used to ID HPROF generated items */
- gdata->hprof_trace_index = tls_get_trace(tls_index, env,
- gdata->max_trace_depth, JNI_FALSE);
- gdata->hprof_site_index = site_find_or_create(
- cnum, gdata->hprof_trace_index);
-
- if ( gdata->logflags & LOG_DUMP_LISTS ) {
- list_all_tables();
- }
-
- /* Prime the class table */
- reset_class_load_status(env, thread);
-
- /* Find the tracker jclass and jmethodID's (does JNI calls) */
- if ( gdata->bci ) {
- tracker_setup_methods(env);
- }
-
- /* Start any agent threads (does JNI, JVMTI, and Java calls) */
-
- /* Thread to watch for gc_finish events */
- rawMonitorEnter(gdata->gc_finish_lock); {
- createAgentThread(env, "HPROF gc_finish watcher",
- &gc_finish_watcher);
- } rawMonitorExit(gdata->gc_finish_lock);
-
- /* Start up listener thread if we need it */
- if ( gdata->socket ) {
- listener_init(env);
- }
-
- /* Start up cpu sampling thread if we need it */
- if ( gdata->cpu_sampling ) {
- /* Note: this could also get started later (see cpu) */
- cpu_sample_init(env);
- }
-
- /* Setup event modes */
- setup_event_mode(JNI_FALSE, JVMTI_ENABLE);
-
- /* Engage tracking (sets Java Tracker field so injections call into
- * agent library).
- */
- if ( gdata->bci ) {
- tracker_engage(env);
- }
-
- /* Indicate the VM is initialized now */
- gdata->jvm_initialized = JNI_TRUE;
- gdata->jvm_initializing = JNI_FALSE;
-
- LOG("cbVMInit end");
-
- } rawMonitorExit(gdata->data_access_lock);
-}
-
-/* JVMTI_EVENT_VM_DEATH */
-static void JNICALL
-cbVMDeath(jvmtiEnv *jvmti, JNIEnv *env)
-{
- /*
- * Use local flag to minimize gdata->dump_lock hold time.
- */
- jboolean need_to_dump = JNI_FALSE;
-
- LOG("cbVMDeath");
-
- /* Shutdown thread watching gc_finish, outside CALLBACK locks.
- * We need to make sure the watcher thread is done doing any cleanup
- * work before we continue here.
- */
- rawMonitorEnter(gdata->gc_finish_lock); {
- /* Notify watcher thread to finish up, it will send
- * another notify when done. If the watcher thread is busy
- * cleaning up, it will detect gc_finish_stop_request when it's done.
- * Then it sets gc_finish_active to JNI_FALSE and will notify us.
- * If the watcher thread is waiting to be notified, then the
- * notification wakes it up.
- * We do not want to do the VM_DEATH while the gc_finish
- * watcher thread is in the middle of a cleanup.
- */
- gdata->gc_finish_stop_request = JNI_TRUE;
- rawMonitorNotifyAll(gdata->gc_finish_lock);
- /* Wait for the gc_finish watcher thread to notify us it's done */
- while ( gdata->gc_finish_active ) {
- rawMonitorWait(gdata->gc_finish_lock,0);
- }
- } rawMonitorExit(gdata->gc_finish_lock);
-
- /* The gc_finish watcher thread should be done now, or done shortly. */
-
-
- /* BEGIN_CALLBACK/END_CALLBACK handling. */
-
- /* The callbackBlock prevents any active callbacks from returning
- * back to the VM, and also blocks all new callbacks.
- * We want to prevent any threads from premature death, so
- * that we don't have worry about that during thread queries
- * in this final dump process.
- */
- rawMonitorEnter(gdata->callbackBlock); {
-
- /* We need to wait for all callbacks actively executing to block
- * on exit, and new ones will block on entry.
- * The BEGIN_CALLBACK/END_CALLBACK macros keep track of callbacks
- * that are active.
- * Once the last active callback is done, it will notify this
- * thread and block.
- */
-
- rawMonitorEnter(gdata->callbackLock); {
- /* Turn off native calls */
- if ( gdata->bci ) {
- tracker_disengage(env);
- }
- gdata->vm_death_callback_active = JNI_TRUE;
- while (gdata->active_callbacks > 0) {
- rawMonitorWait(gdata->callbackLock, 0);
- }
- } rawMonitorExit(gdata->callbackLock);
-
- /* Now we know that no threads will die on us, being blocked
- * on some event callback, at a minimum ThreadEnd.
- */
-
- /* Make some basic checks. */
- rawMonitorEnter(gdata->data_access_lock); {
- if ( gdata->jvm_initializing ) {
- HPROF_ERROR(JNI_TRUE, "VM Death during VM Init");
- return;
- }
- if ( !gdata->jvm_initialized ) {
- HPROF_ERROR(JNI_TRUE, "VM Death before VM Init");
- return;
- }
- if (gdata->jvm_shut_down) {
- HPROF_ERROR(JNI_TRUE, "VM Death more than once?");
- return;
- }
- } rawMonitorExit(gdata->data_access_lock);
-
- /* Shutdown the cpu loop thread */
- if ( gdata->cpu_sampling ) {
- cpu_sample_term(env);
- }
-
- /* Time to dump the final data */
- rawMonitorEnter(gdata->dump_lock); {
-
- gdata->jvm_shut_down = JNI_TRUE;
-
- if (!gdata->dump_in_process) {
- need_to_dump = JNI_TRUE;
- gdata->dump_in_process = JNI_TRUE;
- /*
- * Setting gdata->dump_in_process will cause cpu sampling to pause
- * (if we are sampling). We don't resume sampling after the
- * dump_all_data() call below because the VM is shutting
- * down.
- */
- }
-
- } rawMonitorExit(gdata->dump_lock);
-
- /* Dump everything if we need to */
- if (gdata->dump_on_exit && need_to_dump) {
-
- dump_all_data(env);
- }
-
- /* Disable all events and callbacks now, all of them.
- * NOTE: It's important that this be done after the dump
- * it prevents other threads from messing up the data
- * because they will block on ThreadStart and ThreadEnd
- * events due to the CALLBACK block.
- */
- set_callbacks(JNI_FALSE);
- setup_event_mode(JNI_FALSE, JVMTI_DISABLE);
- setup_event_mode(JNI_TRUE, JVMTI_DISABLE);
-
- /* Write tail of file */
- io_write_file_footer();
-
- } rawMonitorExit(gdata->callbackBlock);
-
- /* Shutdown the listener thread and socket, or flush I/O buffers */
- if (gdata->socket) {
- listener_term(env);
- } else {
- io_flush();
- }
-
- /* Close the file descriptors down */
- if ( gdata->fd >= 0 ) {
- (void)md_close(gdata->fd);
- gdata->fd = -1;
- if ( gdata->logflags & LOG_CHECK_BINARY ) {
- if (gdata->output_format == 'b' && gdata->output_filename != NULL) {
- check_binary_file(gdata->output_filename);
- }
- }
- }
- if ( gdata->heap_fd >= 0 ) {
- (void)md_close(gdata->heap_fd);
- gdata->heap_fd = -1;
- }
-
- if ( gdata->check_fd >= 0 ) {
- (void)md_close(gdata->check_fd);
- gdata->check_fd = -1;
- }
-
- /* Remove the temporary heap file */
- if (gdata->heap_dump) {
- (void)remove(gdata->heapfilename);
- }
-
- /* If logging, dump the tables */
- if ( gdata->logflags & LOG_DUMP_LISTS ) {
- list_all_tables();
- }
-
- /* Make sure all global references are deleted */
- class_delete_global_references(env);
- loader_delete_global_references(env);
- tls_delete_global_references(env);
-
-}
-
-/* JVMTI_EVENT_THREAD_START */
-static void JNICALL
-cbThreadStart(jvmtiEnv *jvmti, JNIEnv *env, jthread thread)
-{
- LOG3("cbThreadStart", "thread is", (int)(long)(ptrdiff_t)thread);
-
- BEGIN_CALLBACK() {
- event_thread_start(env, thread);
- } END_CALLBACK();
-}
-
-/* JVMTI_EVENT_THREAD_END */
-static void JNICALL
-cbThreadEnd(jvmtiEnv *jvmti, JNIEnv *env, jthread thread)
-{
- LOG3("cbThreadEnd", "thread is", (int)(long)(ptrdiff_t)thread);
-
- BEGIN_CALLBACK() {
- event_thread_end(env, thread);
- } END_CALLBACK();
-}
-
-/* JVMTI_EVENT_CLASS_FILE_LOAD_HOOK */
-static void JNICALL
-cbClassFileLoadHook(jvmtiEnv *jvmti_env, JNIEnv* env,
- jclass class_being_redefined, jobject loader,
- const char* name, jobject protection_domain,
- jint class_data_len, const unsigned char* class_data,
- jint* new_class_data_len, unsigned char** new_class_data)
-{
-
- /* WARNING: This will be called before VM_INIT. */
-
- LOG2("cbClassFileLoadHook:",(name==NULL?"Unknown":name));
-
- if (!gdata->bci) {
- return;
- }
-
- BEGIN_CALLBACK() {
- rawMonitorEnter(gdata->data_access_lock); {
- const char *classname;
-
- if ( gdata->bci_counter == 0 ) {
- /* Prime the system classes */
- class_prime_system_classes();
- }
-
- gdata->bci_counter++;
-
- *new_class_data_len = 0;
- *new_class_data = NULL;
-
- /* Name could be NULL */
- if ( name == NULL ) {
- classname = ((JavaCrwDemoClassname)
- (gdata->java_crw_demo_classname_function))
- (class_data, class_data_len, &my_crw_fatal_error_handler);
- if ( classname == NULL ) {
- HPROF_ERROR(JNI_TRUE, "No classname in classfile");
- }
- } else {
- classname = strdup(name);
- if ( classname == NULL ) {
- HPROF_ERROR(JNI_TRUE, "Ran out of malloc() space");
- }
- }
-
- /* The tracker class itself? */
- if ( strcmp(classname, TRACKER_CLASS_NAME) != 0 ) {
- ClassIndex cnum;
- int system_class;
- unsigned char * new_image;
- long new_length;
- int len;
- char *signature;
- LoaderIndex loader_index;
-
- LOG2("cbClassFileLoadHook injecting class" , classname);
-
- /* Define a unique class number for this class */
- len = (int)strlen(classname);
- signature = HPROF_MALLOC(len+3);
- signature[0] = JVM_SIGNATURE_CLASS;
- (void)memcpy(signature+1, classname, len);
- signature[len+1] = JVM_SIGNATURE_ENDCLASS;
- signature[len+2] = 0;
- loader_index = loader_find_or_create(env,loader);
- if ( class_being_redefined != NULL ) {
- cnum = class_find_or_create(signature, loader_index);
- } else {
- cnum = class_create(signature, loader_index);
- }
- HPROF_FREE(signature);
- signature = NULL;
-
- /* Make sure class doesn't get unloaded by accident */
- class_add_status(cnum, CLASS_IN_LOAD_LIST);
-
- /* Is it a system class? */
- system_class = 0;
- if ( (!gdata->jvm_initialized)
- && (!gdata->jvm_initializing)
- && ( ( class_get_status(cnum) & CLASS_SYSTEM) != 0
- || gdata->bci_counter < 8 ) ) {
- system_class = 1;
- LOG2(classname, " is a system class");
- }
-
- new_image = NULL;
- new_length = 0;
-
- /* Call the class file reader/write demo code */
- ((JavaCrwDemo)(gdata->java_crw_demo_function))(
- cnum,
- classname,
- class_data,
- class_data_len,
- system_class,
- TRACKER_CLASS_NAME,
- TRACKER_CLASS_SIG,
- (gdata->cpu_timing)?TRACKER_CALL_NAME:NULL,
- (gdata->cpu_timing)?TRACKER_CALL_SIG:NULL,
- (gdata->cpu_timing)?TRACKER_RETURN_NAME:NULL,
- (gdata->cpu_timing)?TRACKER_RETURN_SIG:NULL,
- (gdata->obj_watch)?TRACKER_OBJECT_INIT_NAME:NULL,
- (gdata->obj_watch)?TRACKER_OBJECT_INIT_SIG:NULL,
- (gdata->obj_watch)?TRACKER_NEWARRAY_NAME:NULL,
- (gdata->obj_watch)?TRACKER_NEWARRAY_SIG:NULL,
- &new_image,
- &new_length,
- &my_crw_fatal_error_handler,
- &class_set_methods);
-
- if ( new_length > 0 ) {
- unsigned char *jvmti_space;
-
- LOG2("cbClassFileLoadHook DID inject this class", classname);
- jvmti_space = (unsigned char *)jvmtiAllocate((jint)new_length);
- (void)memcpy((void*)jvmti_space, (void*)new_image, (int)new_length);
- *new_class_data_len = (jint)new_length;
- *new_class_data = jvmti_space; /* VM will deallocate */
- } else {
- LOG2("cbClassFileLoadHook DID NOT inject this class", classname);
- *new_class_data_len = 0;
- *new_class_data = NULL;
- }
- if ( new_image != NULL ) {
- (void)free((void*)new_image); /* Free malloc() space with free() */
- }
- }
- (void)free((void*)classname);
- } rawMonitorExit(gdata->data_access_lock);
- } END_CALLBACK();
-}
-
-/* JVMTI_EVENT_CLASS_LOAD */
-static void JNICALL
-cbClassLoad(jvmtiEnv *jvmti, JNIEnv *env, jthread thread, jclass klass)
-{
-
- /* WARNING: This MAY be called before VM_INIT. */
-
- LOG("cbClassLoad");
-
- BEGIN_CALLBACK() {
- rawMonitorEnter(gdata->data_access_lock); {
-
- WITH_LOCAL_REFS(env, 1) {
- jobject loader;
-
- loader = getClassLoader(klass);
- event_class_load(env, thread, klass, loader);
- } END_WITH_LOCAL_REFS;
-
- } rawMonitorExit(gdata->data_access_lock);
- } END_CALLBACK();
-}
-
-/* JVMTI_EVENT_CLASS_PREPARE */
-static void JNICALL
-cbClassPrepare(jvmtiEnv *jvmti, JNIEnv *env, jthread thread, jclass klass)
-{
-
- /* WARNING: This will be called before VM_INIT. */
-
- LOG("cbClassPrepare");
-
- BEGIN_CALLBACK() {
- rawMonitorEnter(gdata->data_access_lock); {
-
- WITH_LOCAL_REFS(env, 1) {
- jobject loader;
-
- loader = NULL;
- loader = getClassLoader(klass);
- event_class_prepare(env, thread, klass, loader);
- } END_WITH_LOCAL_REFS;
-
- } rawMonitorExit(gdata->data_access_lock);
- } END_CALLBACK();
-
-}
-
-/* JVMTI_EVENT_DATA_DUMP_REQUEST */
-static void JNICALL
-cbDataDumpRequest(jvmtiEnv *jvmti)
-{
- jboolean need_to_dump;
-
- LOG("cbDataDumpRequest");
-
- BEGIN_CALLBACK() {
- need_to_dump = JNI_FALSE;
- rawMonitorEnter(gdata->dump_lock); {
- if (!gdata->dump_in_process) {
- need_to_dump = JNI_TRUE;
- gdata->dump_in_process = JNI_TRUE;
- }
- } rawMonitorExit(gdata->dump_lock);
-
- if (need_to_dump) {
- dump_all_data(getEnv());
-
- rawMonitorEnter(gdata->dump_lock); {
- gdata->dump_in_process = JNI_FALSE;
- } rawMonitorExit(gdata->dump_lock);
-
- if (gdata->cpu_sampling && !gdata->jvm_shut_down) {
- cpu_sample_on(NULL, 0); /* resume sampling */
- }
- }
- } END_CALLBACK();
-
-}
-
-/* JVMTI_EVENT_EXCEPTION_CATCH */
-static void JNICALL
-cbExceptionCatch(jvmtiEnv *jvmti, JNIEnv* env,
- jthread thread, jmethodID method, jlocation location,
- jobject exception)
-{
- LOG("cbExceptionCatch");
-
- BEGIN_CALLBACK() {
- event_exception_catch(env, thread, method, location, exception);
- } END_CALLBACK();
-}
-
-/* JVMTI_EVENT_MONITOR_WAIT */
-static void JNICALL
-cbMonitorWait(jvmtiEnv *jvmti, JNIEnv* env,
- jthread thread, jobject object, jlong timeout)
-{
- LOG("cbMonitorWait");
-
- BEGIN_CALLBACK() {
- monitor_wait_event(env, thread, object, timeout);
- } END_CALLBACK();
-}
-
-/* JVMTI_EVENT_MONITOR_WAITED */
-static void JNICALL
-cbMonitorWaited(jvmtiEnv *jvmti, JNIEnv* env,
- jthread thread, jobject object, jboolean timed_out)
-{
- LOG("cbMonitorWaited");
-
- BEGIN_CALLBACK() {
- monitor_waited_event(env, thread, object, timed_out);
- } END_CALLBACK();
-}
-
-/* JVMTI_EVENT_MONITOR_CONTENDED_ENTER */
-static void JNICALL
-cbMonitorContendedEnter(jvmtiEnv *jvmti, JNIEnv* env,
- jthread thread, jobject object)
-{
- LOG("cbMonitorContendedEnter");
-
- BEGIN_CALLBACK() {
- monitor_contended_enter_event(env, thread, object);
- } END_CALLBACK();
-}
-
-/* JVMTI_EVENT_MONITOR_CONTENDED_ENTERED */
-static void JNICALL
-cbMonitorContendedEntered(jvmtiEnv *jvmti, JNIEnv* env,
- jthread thread, jobject object)
-{
- LOG("cbMonitorContendedEntered");
-
- BEGIN_CALLBACK() {
- monitor_contended_entered_event(env, thread, object);
- } END_CALLBACK();
-}
-
-/* JVMTI_EVENT_GARBAGE_COLLECTION_START */
-static void JNICALL
-cbGarbageCollectionStart(jvmtiEnv *jvmti)
-{
- LOG("cbGarbageCollectionStart");
-
- /* Only calls to Allocate, Deallocate, RawMonitorEnter & RawMonitorExit
- * are allowed here (see the JVMTI Spec).
- */
-
- gdata->gc_start_time = md_get_timemillis();
-}
-
-/* JVMTI_EVENT_GARBAGE_COLLECTION_FINISH */
-static void JNICALL
-cbGarbageCollectionFinish(jvmtiEnv *jvmti)
-{
- LOG("cbGarbageCollectionFinish");
-
- /* Only calls to Allocate, Deallocate, RawMonitorEnter & RawMonitorExit
- * are allowed here (see the JVMTI Spec).
- */
-
- if ( gdata->gc_start_time != -1L ) {
- gdata->time_in_gc += (md_get_timemillis() - gdata->gc_start_time);
- gdata->gc_start_time = -1L;
- }
-
- /* Increment gc_finish counter, notify watcher thread */
- rawMonitorEnter(gdata->gc_finish_lock); {
- /* If VM_DEATH is trying to shut it down, don't do anything at all.
- * Never send notify if VM_DEATH wants the watcher thread to quit.
- */
- if ( gdata->gc_finish_active ) {
- gdata->gc_finish++;
- rawMonitorNotifyAll(gdata->gc_finish_lock);
- }
- } rawMonitorExit(gdata->gc_finish_lock);
-}
-
-/* JVMTI_EVENT_OBJECT_FREE */
-static void JNICALL
-cbObjectFree(jvmtiEnv *jvmti, jlong tag)
-{
- LOG3("cbObjectFree", "tag", (int)tag);
-
- /* Only calls to Allocate, Deallocate, RawMonitorEnter & RawMonitorExit
- * are allowed here (see the JVMTI Spec).
- */
-
- HPROF_ASSERT(tag!=(jlong)0);
- rawMonitorEnter(gdata->object_free_lock); {
- if ( !gdata->jvm_shut_down ) {
- Stack *stack;
-
- stack = gdata->object_free_stack;
- if ( stack == NULL ) {
- gdata->object_free_stack = stack_init(512, 512, sizeof(jlong));
- stack = gdata->object_free_stack;
- }
- stack_push(stack, (void*)&tag);
- }
- } rawMonitorExit(gdata->object_free_lock);
-}
-
-static void
-set_callbacks(jboolean on)
-{
- jvmtiEventCallbacks callbacks;
-
- (void)memset(&callbacks,0,sizeof(callbacks));
- if ( ! on ) {
- setEventCallbacks(&callbacks);
- return;
- }
-
- /* JVMTI_EVENT_VM_INIT */
- callbacks.VMInit = &cbVMInit;
- /* JVMTI_EVENT_VM_DEATH */
- callbacks.VMDeath = &cbVMDeath;
- /* JVMTI_EVENT_THREAD_START */
- callbacks.ThreadStart = &cbThreadStart;
- /* JVMTI_EVENT_THREAD_END */
- callbacks.ThreadEnd = &cbThreadEnd;
- /* JVMTI_EVENT_CLASS_FILE_LOAD_HOOK */
- callbacks.ClassFileLoadHook = &cbClassFileLoadHook;
- /* JVMTI_EVENT_CLASS_LOAD */
- callbacks.ClassLoad = &cbClassLoad;
- /* JVMTI_EVENT_CLASS_PREPARE */
- callbacks.ClassPrepare = &cbClassPrepare;
- /* JVMTI_EVENT_DATA_DUMP_REQUEST */
- callbacks.DataDumpRequest = &cbDataDumpRequest;
- /* JVMTI_EVENT_EXCEPTION_CATCH */
- callbacks.ExceptionCatch = &cbExceptionCatch;
- /* JVMTI_EVENT_MONITOR_WAIT */
- callbacks.MonitorWait = &cbMonitorWait;
- /* JVMTI_EVENT_MONITOR_WAITED */
- callbacks.MonitorWaited = &cbMonitorWaited;
- /* JVMTI_EVENT_MONITOR_CONTENDED_ENTER */
- callbacks.MonitorContendedEnter = &cbMonitorContendedEnter;
- /* JVMTI_EVENT_MONITOR_CONTENDED_ENTERED */
- callbacks.MonitorContendedEntered = &cbMonitorContendedEntered;
- /* JVMTI_EVENT_GARBAGE_COLLECTION_START */
- callbacks.GarbageCollectionStart = &cbGarbageCollectionStart;
- /* JVMTI_EVENT_GARBAGE_COLLECTION_FINISH */
- callbacks.GarbageCollectionFinish = &cbGarbageCollectionFinish;
- /* JVMTI_EVENT_OBJECT_FREE */
- callbacks.ObjectFree = &cbObjectFree;
-
- setEventCallbacks(&callbacks);
-
-}
-
-static void
-getCapabilities(void)
-{
- jvmtiCapabilities needed_capabilities;
- jvmtiCapabilities potential_capabilities;
-
- /* Fill in ones that we must have */
- (void)memset(&needed_capabilities,0,sizeof(needed_capabilities));
- needed_capabilities.can_generate_garbage_collection_events = 1;
- needed_capabilities.can_tag_objects = 1;
- if (gdata->bci) {
- needed_capabilities.can_generate_all_class_hook_events = 1;
- }
- if (gdata->obj_watch) {
- needed_capabilities.can_generate_object_free_events = 1;
- }
- if (gdata->cpu_timing || gdata->cpu_sampling) {
- #if 0 /* Not needed until we call JVMTI for CpuTime */
- needed_capabilities.can_get_thread_cpu_time = 1;
- needed_capabilities.can_get_current_thread_cpu_time = 1;
- #endif
- needed_capabilities.can_generate_exception_events = 1;
- }
- if (gdata->monitor_tracing) {
- #if 0 /* Not needed until we call JVMTI for CpuTime */
- needed_capabilities.can_get_thread_cpu_time = 1;
- needed_capabilities.can_get_current_thread_cpu_time = 1;
- #endif
- needed_capabilities.can_get_owned_monitor_info = 1;
- needed_capabilities.can_get_current_contended_monitor = 1;
- needed_capabilities.can_get_monitor_info = 1;
- needed_capabilities.can_generate_monitor_events = 1;
- }
-
- /* Get potential capabilities */
- getPotentialCapabilities(&potential_capabilities);
-
- /* Some capabilities would be nicer to have */
- needed_capabilities.can_get_source_file_name =
- potential_capabilities.can_get_source_file_name;
- needed_capabilities.can_get_line_numbers =
- potential_capabilities.can_get_line_numbers;
-
- /* Add the capabilities */
- addCapabilities(&needed_capabilities);
-
-}
-
-/* Dynamic library loading */
-static void *
-load_library(char *name)
-{
- char lname[FILENAME_MAX+1];
- char err_buf[256+FILENAME_MAX+1];
- char *boot_path;
- void *handle;
-
- handle = NULL;
-
- /* The library may be located in different ways, try both, but
- * if it comes from outside the SDK/jre it isn't ours.
- */
- getSystemProperty("sun.boot.library.path", &boot_path);
- md_build_library_name(lname, FILENAME_MAX, boot_path, name);
- if ( strlen(lname) == 0 ) {
- HPROF_ERROR(JNI_TRUE, "Could not find library");
- }
- jvmtiDeallocate(boot_path);
- handle = md_load_library(lname, err_buf, (int)sizeof(err_buf));
- if ( handle == NULL ) {
- /* This may be necessary on Windows. */
- md_build_library_name(lname, FILENAME_MAX, "", name);
- if ( strlen(lname) == 0 ) {
- HPROF_ERROR(JNI_TRUE, "Could not find library");
- }
- handle = md_load_library(lname, err_buf, (int)sizeof(err_buf));
- if ( handle == NULL ) {
- HPROF_ERROR(JNI_TRUE, err_buf);
- }
- }
- return handle;
-}
-
-/* Lookup dynamic function pointer in shared library */
-static void *
-lookup_library_symbol(void *library, char **symbols, int nsymbols)
-{
- void *addr;
- int i;
-
- addr = NULL;
- for( i = 0 ; i < nsymbols; i++ ) {
- addr = md_find_library_entry(library, symbols[i]);
- if ( addr != NULL ) {
- break;
- }
- }
- if ( addr == NULL ) {
- char errmsg[256];
-
- (void)md_snprintf(errmsg, sizeof(errmsg),
- "Cannot find library symbol '%s'", symbols[0]);
- HPROF_ERROR(JNI_TRUE, errmsg);
- }
- return addr;
-}
-
-/* ------------------------------------------------------------------- */
-/* The OnLoad interface */
-
-JNIEXPORT jint JNICALL
-Agent_OnLoad(JavaVM *vm, char *options, void *reserved)
-{
- char *boot_path = NULL;
-
- /* See if it's already loaded */
- if ( gdata!=NULL && gdata->isLoaded==JNI_TRUE ) {
- HPROF_ERROR(JNI_TRUE, "Cannot load this JVM TI agent twice, check your java command line for duplicate hprof options.");
- return JNI_ERR;
- }
-
- gdata = get_gdata();
-
- gdata->isLoaded = JNI_TRUE;
-
- error_setup();
-
- LOG2("Agent_OnLoad", "gdata setup");
-
- gdata->jvm = vm;
-
- /* Get the JVMTI environment */
- getJvmti();
-
- /* Lock needed to protect debug_malloc() code, which is not MT safe */
- #ifdef DEBUG
- gdata->debug_malloc_lock = createRawMonitor("HPROF debug_malloc lock");
- #endif
-
- parse_options(options);
-
- LOG2("Agent_OnLoad", "Has jvmtiEnv and options parsed");
-
- /* Initialize machine dependent code (micro state accounting) */
- md_init();
-
- string_init(); /* Table index values look like: 0x10000000 */
-
- class_init(); /* Table index values look like: 0x20000000 */
- tls_init(); /* Table index values look like: 0x30000000 */
- trace_init(); /* Table index values look like: 0x40000000 */
- object_init(); /* Table index values look like: 0x50000000 */
-
- site_init(); /* Table index values look like: 0x60000000 */
- frame_init(); /* Table index values look like: 0x70000000 */
- monitor_init(); /* Table index values look like: 0x80000000 */
- loader_init(); /* Table index values look like: 0x90000000 */
-
- LOG2("Agent_OnLoad", "Tables initialized");
-
- if ( gdata->pause ) {
- error_do_pause();
- }
-
- getCapabilities();
-
- /* Set the JVMTI callback functions (do this only once)*/
- set_callbacks(JNI_TRUE);
-
- /* Create basic locks */
- gdata->dump_lock = createRawMonitor("HPROF dump lock");
- gdata->data_access_lock = createRawMonitor("HPROF data access lock");
- gdata->callbackLock = createRawMonitor("HPROF callback lock");
- gdata->callbackBlock = createRawMonitor("HPROF callback block");
- gdata->object_free_lock = createRawMonitor("HPROF object free lock");
- gdata->gc_finish_lock = createRawMonitor("HPROF gc_finish lock");
-
- /* Set Onload events mode. */
- setup_event_mode(JNI_TRUE, JVMTI_ENABLE);
-
- LOG2("Agent_OnLoad", "JVMTI capabilities, callbacks and initial notifications setup");
-
- /* Used in VM_DEATH to wait for callbacks to complete */
- gdata->jvm_initializing = JNI_FALSE;
- gdata->jvm_initialized = JNI_FALSE;
- gdata->vm_death_callback_active = JNI_FALSE;
- gdata->active_callbacks = 0;
-
- /* Write the header information */
- io_setup();
-
- /* We sample the start time now so that the time increments can be
- * placed in the various heap dump segments in micro seconds.
- */
- gdata->micro_sec_ticks = md_get_microsecs();
-
- /* Load java_crw_demo library and find function "java_crw_demo" */
- if ( gdata->bci ) {
-
- /* Load the library or get the handle to it */
- gdata->java_crw_demo_library = load_library("java_crw_demo");
-
- { /* "java_crw_demo" */
- static char *symbols[] = JAVA_CRW_DEMO_SYMBOLS;
- gdata->java_crw_demo_function =
- lookup_library_symbol(gdata->java_crw_demo_library,
- symbols, (int)(sizeof(symbols)/sizeof(char*)));
- }
- { /* "java_crw_demo_classname" */
- static char *symbols[] = JAVA_CRW_DEMO_CLASSNAME_SYMBOLS;
- gdata->java_crw_demo_classname_function =
- lookup_library_symbol(gdata->java_crw_demo_library,
- symbols, (int)(sizeof(symbols)/sizeof(char*)));
- }
- }
-
- return JNI_OK;
-}
-
-JNIEXPORT void JNICALL
-Agent_OnUnload(JavaVM *vm)
-{
- Stack *stack;
-
- LOG("Agent_OnUnload");
-
- gdata->isLoaded = JNI_FALSE;
-
- stack = gdata->object_free_stack;
- gdata->object_free_stack = NULL;
- if ( stack != NULL ) {
- stack_term(stack);
- }
-
- io_cleanup();
- loader_cleanup();
- tls_cleanup();
- monitor_cleanup();
- trace_cleanup();
- site_cleanup();
- object_cleanup();
- frame_cleanup();
- class_cleanup();
- string_cleanup();
-
- /* Deallocate any memory in gdata */
- if ( gdata->net_hostname != NULL ) {
- HPROF_FREE(gdata->net_hostname);
- }
- if ( gdata->utf8_output_filename != NULL ) {
- HPROF_FREE(gdata->utf8_output_filename);
- }
- if ( gdata->output_filename != NULL ) {
- HPROF_FREE(gdata->output_filename);
- }
- if ( gdata->heapfilename != NULL ) {
- HPROF_FREE(gdata->heapfilename);
- }
- if ( gdata->checkfilename != NULL ) {
- HPROF_FREE(gdata->checkfilename);
- }
- if ( gdata->options != NULL ) {
- HPROF_FREE(gdata->options);
- }
-
- /* Verify all allocated memory has been taken care of. */
- malloc_police();
-
- /* Cleanup is hard to do when other threads might still be running
- * so we skip destroying some raw monitors which still might be in use
- * and we skip disposal of the jvmtiEnv* which might still be needed.
- * Only raw monitors that could be held by other threads are left
- * alone. So we explicitly do NOT do this:
- * destroyRawMonitor(gdata->callbackLock);
- * destroyRawMonitor(gdata->callbackBlock);
- * destroyRawMonitor(gdata->gc_finish_lock);
- * destroyRawMonitor(gdata->object_free_lock);
- * destroyRawMonitor(gdata->listener_loop_lock);
- * destroyRawMonitor(gdata->cpu_loop_lock);
- * disposeEnvironment();
- * gdata->jvmti = NULL;
- */
-
- /* Destroy basic locks */
- destroyRawMonitor(gdata->dump_lock);
- gdata->dump_lock = NULL;
- destroyRawMonitor(gdata->data_access_lock);
- gdata->data_access_lock = NULL;
- if ( gdata->cpu_sample_lock != NULL ) {
- destroyRawMonitor(gdata->cpu_sample_lock);
- gdata->cpu_sample_lock = NULL;
- }
- #ifdef DEBUG
- destroyRawMonitor(gdata->debug_malloc_lock);
- gdata->debug_malloc_lock = NULL;
- #endif
-
- /* Unload java_crw_demo library */
- if ( gdata->bci && gdata->java_crw_demo_library != NULL ) {
- md_unload_library(gdata->java_crw_demo_library);
- gdata->java_crw_demo_library = NULL;
- }
-
- /* You would think you could clear out gdata and set it to NULL, but
- * turns out that isn't a good idea. Some of the threads could be
- * blocked inside the CALLBACK*() macros, where they got blocked up
- * waiting for the VM_DEATH callback to complete. They only have
- * some raw monitor actions to do, but they need access to gdata to do it.
- * So do not do this:
- * (void)memset(gdata, 0, sizeof(GlobalData));
- * gdata = NULL;
- */
-}
--- a/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_init.h Thu Aug 20 12:29:58 2015 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,47 +0,0 @@
-/*
- * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * - Neither the name of Oracle nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
- * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/*
- * This source code is provided to illustrate the usage of a given feature
- * or technique and has been deliberately simplified. Additional steps
- * required for a production-quality application, such as security checks,
- * input validation and proper error handling, might not be present in
- * this sample code.
- */
-
-
-#ifndef HPROF_INIT_H
-#define HPROF_INIT_H
-
-JNIEXPORT jint JNICALL Agent_OnLoad(JavaVM *vm, char *options, void *reserved);
-JNIEXPORT void JNICALL Agent_OnUnload(JavaVM *vm);
-
-#endif
--- a/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_io.c Thu Aug 20 12:29:58 2015 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,1980 +0,0 @@
-/*
- * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * - Neither the name of Oracle nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
- * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/*
- * This source code is provided to illustrate the usage of a given feature
- * or technique and has been deliberately simplified. Additional steps
- * required for a production-quality application, such as security checks,
- * input validation and proper error handling, might not be present in
- * this sample code.
- */
-
-
-/* All I/O functionality for hprof. */
-
-/*
- * The hprof agent has many forms of output:
- *
- * format=b gdata->output_format=='b'
- * Binary format. Defined below. This is used by HAT.
- * This is NOT the same format as emitted by JVMPI.
- *
- * format=a gdata->output_format=='a'
- * Ascii format. Not exactly an ascii representation of the binary format.
- *
- * And many forms of dumps:
- *
- * heap=dump
- * A large dump that in this implementation is written to a separate
- * file first before being placed in the output file. Several reasons,
- * the binary form needs a byte count of the length in the header, and
- * references in this dump to other items need to be emitted first.
- * So it's two pass, or use a temp file and copy.
- * heap=sites
- * Dumps the sites in the order of most allocations.
- * cpu=samples
- * Dumps the traces in order of most hits
- * cpu=times
- * Dumps the traces in the order of most time spent there.
- * cpu=old (format=a only)
- * Dumps out an older form of cpu output (old -prof format)
- * monitor=y (format=a only)
- * Dumps out a list of monitors in order of most contended.
- *
- * This file also includes a binary format check function that will read
- * back in the hprof binary format and verify the syntax looks correct.
- *
- * WARNING: Besides the comments below, there is little format spec on this,
- * however see:
- * http://java.sun.com/j2se/1.4.2/docs/guide/jvmpi/jvmpi.html#hprof
- */
-
-#include "hprof.h"
-
-typedef TableIndex HprofId;
-
-#include "hprof_ioname.h"
-#include "hprof_b_spec.h"
-
-static int type_size[ /*HprofType*/ ] = HPROF_TYPE_SIZES;
-
-static void dump_heap_segment_and_reset(jlong segment_size);
-
-static void
-not_implemented(void)
-{
-}
-
-static IoNameIndex
-get_name_index(char *name)
-{
- if (name != NULL && gdata->output_format == 'b') {
- return ioname_find_or_create(name, NULL);
- }
- return 0;
-}
-
-static char *
-signature_to_name(char *sig)
-{
- char *ptr;
- char *basename;
- char *name;
- int i;
- int len;
- int name_len;
-
- if ( sig != NULL ) {
- switch ( sig[0] ) {
- case JVM_SIGNATURE_CLASS:
- ptr = strchr(sig+1, JVM_SIGNATURE_ENDCLASS);
- if ( ptr == NULL ) {
- basename = "Unknown_class";
- break;
- }
- /*LINTED*/
- name_len = (jint)(ptr - (sig+1));
- name = HPROF_MALLOC(name_len+1);
- (void)memcpy(name, sig+1, name_len);
- name[name_len] = 0;
- for ( i = 0 ; i < name_len ; i++ ) {
- if ( name[i] == '/' ) name[i] = '.';
- }
- return name;
- case JVM_SIGNATURE_ARRAY:
- basename = signature_to_name(sig+1);
- len = (int)strlen(basename);
- name_len = len+2;
- name = HPROF_MALLOC(name_len+1);
- (void)memcpy(name, basename, len);
- (void)memcpy(name+len, "[]", 2);
- name[name_len] = 0;
- HPROF_FREE(basename);
- return name;
- case JVM_SIGNATURE_FUNC:
- ptr = strchr(sig+1, JVM_SIGNATURE_ENDFUNC);
- if ( ptr == NULL ) {
- basename = "Unknown_method";
- break;
- }
- basename = "()"; /* Someday deal with method signatures */
- break;
- case JVM_SIGNATURE_BYTE:
- basename = "byte";
- break;
- case JVM_SIGNATURE_CHAR:
- basename = "char";
- break;
- case JVM_SIGNATURE_ENUM:
- basename = "enum";
- break;
- case JVM_SIGNATURE_FLOAT:
- basename = "float";
- break;
- case JVM_SIGNATURE_DOUBLE:
- basename = "double";
- break;
- case JVM_SIGNATURE_INT:
- basename = "int";
- break;
- case JVM_SIGNATURE_LONG:
- basename = "long";
- break;
- case JVM_SIGNATURE_SHORT:
- basename = "short";
- break;
- case JVM_SIGNATURE_VOID:
- basename = "void";
- break;
- case JVM_SIGNATURE_BOOLEAN:
- basename = "boolean";
- break;
- default:
- basename = "Unknown_class";
- break;
- }
- } else {
- basename = "Unknown_class";
- }
-
- /* Simple basename */
- name_len = (int)strlen(basename);
- name = HPROF_MALLOC(name_len+1);
- (void)strcpy(name, basename);
- return name;
-}
-
-static int
-size_from_field_info(int size)
-{
- if ( size == 0 ) {
- size = (int)sizeof(HprofId);
- }
- return size;
-}
-
-static void
-type_from_signature(const char *sig, HprofType *kind, jint *size)
-{
- *kind = HPROF_NORMAL_OBJECT;
- *size = 0;
- switch ( sig[0] ) {
- case JVM_SIGNATURE_ENUM:
- case JVM_SIGNATURE_CLASS:
- case JVM_SIGNATURE_ARRAY:
- *kind = HPROF_NORMAL_OBJECT;
- break;
- case JVM_SIGNATURE_BOOLEAN:
- *kind = HPROF_BOOLEAN;
- break;
- case JVM_SIGNATURE_CHAR:
- *kind = HPROF_CHAR;
- break;
- case JVM_SIGNATURE_FLOAT:
- *kind = HPROF_FLOAT;
- break;
- case JVM_SIGNATURE_DOUBLE:
- *kind = HPROF_DOUBLE;
- break;
- case JVM_SIGNATURE_BYTE:
- *kind = HPROF_BYTE;
- break;
- case JVM_SIGNATURE_SHORT:
- *kind = HPROF_SHORT;
- break;
- case JVM_SIGNATURE_INT:
- *kind = HPROF_INT;
- break;
- case JVM_SIGNATURE_LONG:
- *kind = HPROF_LONG;
- break;
- default:
- HPROF_ASSERT(0);
- break;
- }
- *size = type_size[*kind];
-}
-
-static void
-type_array(const char *sig, HprofType *kind, jint *elem_size)
-{
- *kind = 0;
- *elem_size = 0;
- switch ( sig[0] ) {
- case JVM_SIGNATURE_ARRAY:
- type_from_signature(sig+1, kind, elem_size);
- break;
- }
-}
-
-static void
-system_error(const char *system_call, int rc, int errnum)
-{
- char buf[256];
- char details[256];
-
- details[0] = 0;
- if ( errnum != 0 ) {
- md_system_error(details, (int)sizeof(details));
- } else if ( rc >= 0 ) {
- (void)strcpy(details,"Only part of buffer processed");
- }
- if ( details[0] == 0 ) {
- (void)strcpy(details,"Unknown system error condition");
- }
- (void)md_snprintf(buf, sizeof(buf), "System %s failed: %s\n",
- system_call, details);
- HPROF_ERROR(JNI_TRUE, buf);
-}
-
-static void
-system_write(int fd, void *buf, int len, jboolean socket)
-{
- int res;
-
- HPROF_ASSERT(fd>=0);
- if (socket) {
- res = md_send(fd, buf, len, 0);
- if (res < 0 || res!=len) {
- system_error("send", res, errno);
- }
- } else {
- res = md_write(fd, buf, len);
- if (res < 0 || res!=len) {
- system_error("write", res, errno);
- }
- }
-}
-
-static void
-write_flush(void)
-{
- HPROF_ASSERT(gdata->fd >= 0);
- if (gdata->write_buffer_index) {
- system_write(gdata->fd, gdata->write_buffer, gdata->write_buffer_index,
- gdata->socket);
- gdata->write_buffer_index = 0;
- }
-}
-
-static void
-heap_flush(void)
-{
- HPROF_ASSERT(gdata->heap_fd >= 0);
- if (gdata->heap_buffer_index) {
- gdata->heap_write_count += (jlong)gdata->heap_buffer_index;
- system_write(gdata->heap_fd, gdata->heap_buffer, gdata->heap_buffer_index,
- JNI_FALSE);
- gdata->heap_buffer_index = 0;
- }
-}
-
-static void
-write_raw(void *buf, int len)
-{
- HPROF_ASSERT(gdata->fd >= 0);
- if (gdata->write_buffer_index + len > gdata->write_buffer_size) {
- write_flush();
- if (len > gdata->write_buffer_size) {
- system_write(gdata->fd, buf, len, gdata->socket);
- return;
- }
- }
- (void)memcpy(gdata->write_buffer + gdata->write_buffer_index, buf, len);
- gdata->write_buffer_index += len;
-}
-
-static void
-write_u4(unsigned i)
-{
- i = md_htonl(i);
- write_raw(&i, (jint)sizeof(unsigned));
-}
-
-static void
-write_u8(jlong t)
-{
- write_u4((jint)jlong_high(t));
- write_u4((jint)jlong_low(t));
-}
-
-static void
-write_u2(unsigned short i)
-{
- i = md_htons(i);
- write_raw(&i, (jint)sizeof(unsigned short));
-}
-
-static void
-write_u1(unsigned char i)
-{
- write_raw(&i, (jint)sizeof(unsigned char));
-}
-
-static void
-write_id(HprofId i)
-{
- write_u4(i);
-}
-
-static void
-write_current_ticks(void)
-{
- write_u4((jint)(md_get_microsecs() - gdata->micro_sec_ticks));
-}
-
-static void
-write_header(unsigned char type, jint length)
-{
- write_u1(type);
- write_current_ticks();
- write_u4(length);
-}
-
-static void
-write_index_id(HprofId index)
-{
- write_id(index);
-}
-
-static IoNameIndex
-write_name_first(char *name)
-{
- if ( name == NULL ) {
- return 0;
- }
- if (gdata->output_format == 'b') {
- IoNameIndex name_index;
- jboolean new_one;
-
- new_one = JNI_FALSE;
- name_index = ioname_find_or_create(name, &new_one);
- if ( new_one ) {
- int len;
-
- len = (int)strlen(name);
- write_header(HPROF_UTF8, len + (jint)sizeof(HprofId));
- write_index_id(name_index);
- write_raw(name, len);
-
- }
- return name_index;
- }
- return 0;
-}
-
-static void
-write_printf(char *fmt, ...)
-{
- char buf[1024];
- va_list args;
- va_start(args, fmt);
- (void)md_vsnprintf(buf, sizeof(buf), fmt, args);
- buf[sizeof(buf)-1] = 0;
- write_raw(buf, (int)strlen(buf));
- va_end(args);
-}
-
-static void
-write_thread_serial_number(SerialNumber thread_serial_num, int with_comma)
-{
- if ( thread_serial_num != 0 ) {
- CHECK_THREAD_SERIAL_NO(thread_serial_num);
- if ( with_comma ) {
- write_printf(" thread %d,", thread_serial_num);
- } else {
- write_printf(" thread %d", thread_serial_num);
- }
- } else {
- if ( with_comma ) {
- write_printf(" <unknown thread>,");
- } else {
- write_printf(" <unknown thread>");
- }
- }
-}
-
-static void
-heap_raw(void *buf, int len)
-{
- HPROF_ASSERT(gdata->heap_fd >= 0);
- if (gdata->heap_buffer_index + len > gdata->heap_buffer_size) {
- heap_flush();
- if (len > gdata->heap_buffer_size) {
- gdata->heap_write_count += (jlong)len;
- system_write(gdata->heap_fd, buf, len, JNI_FALSE);
- return;
- }
- }
- (void)memcpy(gdata->heap_buffer + gdata->heap_buffer_index, buf, len);
- gdata->heap_buffer_index += len;
-}
-
-static void
-heap_u4(unsigned i)
-{
- i = md_htonl(i);
- heap_raw(&i, (jint)sizeof(unsigned));
-}
-
-static void
-heap_u8(jlong i)
-{
- heap_u4((jint)jlong_high(i));
- heap_u4((jint)jlong_low(i));
-}
-
-static void
-heap_u2(unsigned short i)
-{
- i = md_htons(i);
- heap_raw(&i, (jint)sizeof(unsigned short));
-}
-
-static void
-heap_u1(unsigned char i)
-{
- heap_raw(&i, (jint)sizeof(unsigned char));
-}
-
-/* Write out the first byte of a heap tag */
-static void
-heap_tag(unsigned char tag)
-{
- jlong pos;
-
- /* Current position in virtual heap dump file */
- pos = gdata->heap_write_count + (jlong)gdata->heap_buffer_index;
- if ( gdata->segmented == JNI_TRUE ) { /* 1.0.2 */
- if ( pos >= gdata->maxHeapSegment ) {
- /* Flush all bytes to the heap dump file */
- heap_flush();
-
- /* Send out segment (up to last tag written out) */
- dump_heap_segment_and_reset(gdata->heap_last_tag_position);
-
- /* Get new current position */
- pos = gdata->heap_write_count + (jlong)gdata->heap_buffer_index;
- }
- }
- /* Save position of this tag */
- gdata->heap_last_tag_position = pos;
- /* Write out this tag */
- heap_u1(tag);
-}
-
-static void
-heap_id(HprofId i)
-{
- heap_u4(i);
-}
-
-static void
-heap_index_id(HprofId index)
-{
- heap_id(index);
-}
-
-static void
-heap_name(char *name)
-{
- heap_index_id(get_name_index(name));
-}
-
-static void
-heap_printf(char *fmt, ...)
-{
- char buf[1024];
- va_list args;
- va_start(args, fmt);
- (void)md_vsnprintf(buf, sizeof(buf), fmt, args);
- buf[sizeof(buf)-1] = 0;
- heap_raw(buf, (int)strlen(buf));
- va_end(args);
-}
-
-static void
-heap_element(HprofType kind, jint size, jvalue value)
-{
- if ( !HPROF_TYPE_IS_PRIMITIVE(kind) ) {
- HPROF_ASSERT(size==4);
- heap_id((HprofId)value.i);
- } else {
- switch ( size ) {
- case 8:
- HPROF_ASSERT(size==8);
- HPROF_ASSERT(kind==HPROF_LONG || kind==HPROF_DOUBLE);
- heap_u8(value.j);
- break;
- case 4:
- HPROF_ASSERT(size==4);
- HPROF_ASSERT(kind==HPROF_INT || kind==HPROF_FLOAT);
- heap_u4(value.i);
- break;
- case 2:
- HPROF_ASSERT(size==2);
- HPROF_ASSERT(kind==HPROF_SHORT || kind==HPROF_CHAR);
- heap_u2(value.s);
- break;
- case 1:
- HPROF_ASSERT(size==1);
- HPROF_ASSERT(kind==HPROF_BOOLEAN || kind==HPROF_BYTE);
- HPROF_ASSERT(kind==HPROF_BOOLEAN?(value.b==0 || value.b==1):1);
- heap_u1(value.b);
- break;
- default:
- HPROF_ASSERT(0);
- break;
- }
- }
-}
-
-/* Dump out all elements of an array, objects in jvalues, prims packed */
-static void
-heap_elements(HprofType kind, jint num_elements, jint elem_size, void *elements)
-{
- int i;
- jvalue val;
- static jvalue empty_val;
-
- if ( num_elements == 0 ) {
- return;
- }
-
- switch ( kind ) {
- case 0:
- case HPROF_ARRAY_OBJECT:
- case HPROF_NORMAL_OBJECT:
- for (i = 0; i < num_elements; i++) {
- val = empty_val;
- val.i = ((ObjectIndex*)elements)[i];
- heap_element(kind, elem_size, val);
- }
- break;
- case HPROF_BYTE:
- case HPROF_BOOLEAN:
- HPROF_ASSERT(elem_size==1);
- for (i = 0; i < num_elements; i++) {
- val = empty_val;
- val.b = ((jboolean*)elements)[i];
- heap_element(kind, elem_size, val);
- }
- break;
- case HPROF_CHAR:
- case HPROF_SHORT:
- HPROF_ASSERT(elem_size==2);
- for (i = 0; i < num_elements; i++) {
- val = empty_val;
- val.s = ((jshort*)elements)[i];
- heap_element(kind, elem_size, val);
- }
- break;
- case HPROF_FLOAT:
- case HPROF_INT:
- HPROF_ASSERT(elem_size==4);
- for (i = 0; i < num_elements; i++) {
- val = empty_val;
- val.i = ((jint*)elements)[i];
- heap_element(kind, elem_size, val);
- }
- break;
- case HPROF_DOUBLE:
- case HPROF_LONG:
- HPROF_ASSERT(elem_size==8);
- for (i = 0; i < num_elements; i++) {
- val = empty_val;
- val.j = ((jlong*)elements)[i];
- heap_element(kind, elem_size, val);
- }
- break;
- }
-}
-
-/* ------------------------------------------------------------------ */
-
-void
-io_flush(void)
-{
- HPROF_ASSERT(gdata->header!=NULL);
- write_flush();
-}
-
-void
-io_setup(void)
-{
- gdata->write_buffer_size = FILE_IO_BUFFER_SIZE;
- gdata->write_buffer = HPROF_MALLOC(gdata->write_buffer_size);
- gdata->write_buffer_index = 0;
-
- gdata->heap_write_count = (jlong)0;
- gdata->heap_last_tag_position = (jlong)0;
- gdata->heap_buffer_size = FILE_IO_BUFFER_SIZE;
- gdata->heap_buffer = HPROF_MALLOC(gdata->heap_buffer_size);
- gdata->heap_buffer_index = 0;
-
- if ( gdata->logflags & LOG_CHECK_BINARY ) {
- gdata->check_buffer_size = FILE_IO_BUFFER_SIZE;
- gdata->check_buffer = HPROF_MALLOC(gdata->check_buffer_size);
- gdata->check_buffer_index = 0;
- }
-
- ioname_init();
-}
-
-void
-io_cleanup(void)
-{
- if ( gdata->write_buffer != NULL ) {
- HPROF_FREE(gdata->write_buffer);
- }
- gdata->write_buffer_size = 0;
- gdata->write_buffer = NULL;
- gdata->write_buffer_index = 0;
-
- if ( gdata->heap_buffer != NULL ) {
- HPROF_FREE(gdata->heap_buffer);
- }
- gdata->heap_write_count = (jlong)0;
- gdata->heap_last_tag_position = (jlong)0;
- gdata->heap_buffer_size = 0;
- gdata->heap_buffer = NULL;
- gdata->heap_buffer_index = 0;
-
- if ( gdata->logflags & LOG_CHECK_BINARY ) {
- if ( gdata->check_buffer != NULL ) {
- HPROF_FREE(gdata->check_buffer);
- }
- gdata->check_buffer_size = 0;
- gdata->check_buffer = NULL;
- gdata->check_buffer_index = 0;
- }
-
- ioname_cleanup();
-}
-
-void
-io_write_file_header(void)
-{
- HPROF_ASSERT(gdata->header!=NULL);
- if (gdata->output_format == 'b') {
- jint settings;
- jlong t;
-
- settings = 0;
- if (gdata->heap_dump || gdata->alloc_sites) {
- settings |= 1;
- }
- if (gdata->cpu_sampling) {
- settings |= 2;
- }
- t = md_get_timemillis();
-
- write_raw(gdata->header, (int)strlen(gdata->header) + 1);
- write_u4((jint)sizeof(HprofId));
- write_u8(t);
-
- write_header(HPROF_CONTROL_SETTINGS, 4 + 2);
- write_u4(settings);
- write_u2((unsigned short)gdata->max_trace_depth);
-
- } else if ((!gdata->cpu_timing) || (!gdata->old_timing_format)) {
- /* We don't want the prelude file for the old prof output format */
- time_t t;
- char prelude_file[FILENAME_MAX];
- int prelude_fd;
- int nbytes;
-
- t = time(0);
-
- md_get_prelude_path(prelude_file, sizeof(prelude_file), PRELUDE_FILE);
-
- prelude_fd = md_open(prelude_file);
- if (prelude_fd < 0) {
- char buf[FILENAME_MAX+80];
-
- (void)md_snprintf(buf, sizeof(buf), "Can't open %s", prelude_file);
- buf[sizeof(buf)-1] = 0;
- HPROF_ERROR(JNI_TRUE, buf);
- }
-
- write_printf("%s, created %s\n", gdata->header, ctime(&t));
-
- do {
- char buf[1024]; /* File is small, small buffer ok here */
-
- nbytes = md_read(prelude_fd, buf, sizeof(buf));
- if ( nbytes < 0 ) {
- system_error("read", nbytes, errno);
- break;
- }
- if (nbytes == 0) {
- break;
- }
- write_raw(buf, nbytes);
- } while ( nbytes > 0 );
-
- md_close(prelude_fd);
-
- write_printf("\n--------\n\n");
-
- write_flush();
- }
-}
-
-void
-io_write_file_footer(void)
-{
- HPROF_ASSERT(gdata->header!=NULL);
-}
-
-void
-io_write_class_load(SerialNumber class_serial_num, ObjectIndex index,
- SerialNumber trace_serial_num, char *sig)
-{
- CHECK_CLASS_SERIAL_NO(class_serial_num);
- CHECK_TRACE_SERIAL_NO(trace_serial_num);
- if (gdata->output_format == 'b') {
- IoNameIndex name_index;
- char *class_name;
-
- class_name = signature_to_name(sig);
- name_index = write_name_first(class_name);
- write_header(HPROF_LOAD_CLASS, (2 * (jint)sizeof(HprofId)) + (4 * 2));
- write_u4(class_serial_num);
- write_index_id(index);
- write_u4(trace_serial_num);
- write_index_id(name_index);
- HPROF_FREE(class_name);
- }
-}
-
-void
-io_write_class_unload(SerialNumber class_serial_num, ObjectIndex index)
-{
- CHECK_CLASS_SERIAL_NO(class_serial_num);
- if (gdata->output_format == 'b') {
- write_header(HPROF_UNLOAD_CLASS, 4);
- write_u4(class_serial_num);
- }
-}
-
-void
-io_write_sites_header(const char * comment_str, jint flags, double cutoff,
- jint total_live_bytes, jint total_live_instances,
- jlong total_alloced_bytes, jlong total_alloced_instances,
- jint count)
-{
- if ( gdata->output_format == 'b') {
- write_header(HPROF_ALLOC_SITES, 2 + (8 * 4) + (count * (4 * 6 + 1)));
- write_u2((unsigned short)flags);
- write_u4(*(int *)(&cutoff));
- write_u4(total_live_bytes);
- write_u4(total_live_instances);
- write_u8(total_alloced_bytes);
- write_u8(total_alloced_instances);
- write_u4(count);
- } else {
- time_t t;
-
- t = time(0);
- write_printf("SITES BEGIN (ordered by %s) %s", comment_str, ctime(&t));
- write_printf(
- " percent live alloc'ed stack class\n");
- write_printf(
- " rank self accum bytes objs bytes objs trace name\n");
- }
-}
-
-void
-io_write_sites_elem(jint index, double ratio, double accum_percent,
- char *sig, SerialNumber class_serial_num,
- SerialNumber trace_serial_num, jint n_live_bytes,
- jint n_live_instances, jint n_alloced_bytes,
- jint n_alloced_instances)
-{
- CHECK_CLASS_SERIAL_NO(class_serial_num);
- CHECK_TRACE_SERIAL_NO(trace_serial_num);
- if ( gdata->output_format == 'b') {
- HprofType kind;
- jint size;
-
- type_array(sig, &kind, &size);
- write_u1(kind);
- write_u4(class_serial_num);
- write_u4(trace_serial_num);
- write_u4(n_live_bytes);
- write_u4(n_live_instances);
- write_u4(n_alloced_bytes);
- write_u4(n_alloced_instances);
- } else {
- char *class_name;
-
- class_name = signature_to_name(sig);
- write_printf("%5u %5.2f%% %5.2f%% %9u %4u %9u %5u %5u %s\n",
- index,
- ratio * 100.0,
- accum_percent * 100.0,
- n_live_bytes,
- n_live_instances,
- n_alloced_bytes,
- n_alloced_instances,
- trace_serial_num,
- class_name);
- HPROF_FREE(class_name);
- }
-}
-
-void
-io_write_sites_footer(void)
-{
- if (gdata->output_format == 'b') {
- not_implemented();
- } else {
- write_printf("SITES END\n");
- }
-}
-
-void
-io_write_thread_start(SerialNumber thread_serial_num,
- ObjectIndex thread_obj_id,
- SerialNumber trace_serial_num, char *thread_name,
- char *thread_group_name, char *thread_parent_name)
-{
- CHECK_THREAD_SERIAL_NO(thread_serial_num);
- CHECK_TRACE_SERIAL_NO(trace_serial_num);
- if (gdata->output_format == 'b') {
- IoNameIndex tname_index;
- IoNameIndex gname_index;
- IoNameIndex pname_index;
-
- tname_index = write_name_first(thread_name);
- gname_index = write_name_first(thread_group_name);
- pname_index = write_name_first(thread_parent_name);
- write_header(HPROF_START_THREAD, ((jint)sizeof(HprofId) * 4) + (4 * 2));
- write_u4(thread_serial_num);
- write_index_id(thread_obj_id);
- write_u4(trace_serial_num);
- write_index_id(tname_index);
- write_index_id(gname_index);
- write_index_id(pname_index);
-
- } else if ( (!gdata->cpu_timing) || (!gdata->old_timing_format)) {
- /* We don't want thread info for the old prof output format */
- write_printf("THREAD START "
- "(obj=%x, id = %d, name=\"%s\", group=\"%s\")\n",
- thread_obj_id, thread_serial_num,
- (thread_name==NULL?"":thread_name),
- (thread_group_name==NULL?"":thread_group_name));
- }
-}
-
-void
-io_write_thread_end(SerialNumber thread_serial_num)
-{
- CHECK_THREAD_SERIAL_NO(thread_serial_num);
- if (gdata->output_format == 'b') {
- write_header(HPROF_END_THREAD, 4);
- write_u4(thread_serial_num);
-
- } else if ( (!gdata->cpu_timing) || (!gdata->old_timing_format)) {
- /* we don't want thread info for the old prof output format */
- write_printf("THREAD END (id = %d)\n", thread_serial_num);
- }
-}
-
-void
-io_write_frame(FrameIndex index, SerialNumber frame_serial_num,
- char *mname, char *msig, char *sname,
- SerialNumber class_serial_num, jint lineno)
-{
- CHECK_CLASS_SERIAL_NO(class_serial_num);
- if (gdata->output_format == 'b') {
- IoNameIndex mname_index;
- IoNameIndex msig_index;
- IoNameIndex sname_index;
-
- mname_index = write_name_first(mname);
- msig_index = write_name_first(msig);
- sname_index = write_name_first(sname);
-
- write_header(HPROF_FRAME, ((jint)sizeof(HprofId) * 4) + (4 * 2));
- write_index_id(index);
- write_index_id(mname_index);
- write_index_id(msig_index);
- write_index_id(sname_index);
- write_u4(class_serial_num);
- write_u4(lineno);
- }
-}
-
-void
-io_write_trace_header(SerialNumber trace_serial_num,
- SerialNumber thread_serial_num, jint n_frames, char *phase_str)
-{
- CHECK_TRACE_SERIAL_NO(trace_serial_num);
- if (gdata->output_format == 'b') {
- write_header(HPROF_TRACE, ((jint)sizeof(HprofId) * n_frames) + (4 * 3));
- write_u4(trace_serial_num);
- write_u4(thread_serial_num);
- write_u4(n_frames);
- } else {
- write_printf("TRACE %u:", trace_serial_num);
- if (thread_serial_num) {
- write_printf(" (thread=%d)", thread_serial_num);
- }
- if ( phase_str != NULL ) {
- write_printf(" (from %s phase of JVM)", phase_str);
- }
- write_printf("\n");
- if (n_frames == 0) {
- write_printf("\t<empty>\n");
- }
- }
-}
-
-void
-io_write_trace_elem(SerialNumber trace_serial_num, FrameIndex frame_index,
- SerialNumber frame_serial_num,
- char *csig, char *mname, char *sname, jint lineno)
-{
- if (gdata->output_format == 'b') {
- write_index_id(frame_index);
- } else {
- char *class_name;
- char linebuf[32];
-
- if (lineno == -2) {
- (void)md_snprintf(linebuf, sizeof(linebuf), "Compiled method");
- } else if (lineno == -3) {
- (void)md_snprintf(linebuf, sizeof(linebuf), "Native method");
- } else if (lineno == -1) {
- (void)md_snprintf(linebuf, sizeof(linebuf), "Unknown line");
- } else {
- (void)md_snprintf(linebuf, sizeof(linebuf), "%d", lineno);
- }
- linebuf[sizeof(linebuf)-1] = 0;
- class_name = signature_to_name(csig);
- if ( mname == NULL ) {
- mname = "<Unknown Method>";
- }
- if ( sname == NULL ) {
- sname = "<Unknown Source>";
- }
- write_printf("\t%s.%s(%s:%s)\n", class_name, mname, sname, linebuf);
- HPROF_FREE(class_name);
- }
-}
-
-void
-io_write_trace_footer(SerialNumber trace_serial_num,
- SerialNumber thread_serial_num, jint n_frames)
-{
-}
-
-#define CPU_SAMPLES_RECORD_NAME ("CPU SAMPLES")
-#define CPU_TIMES_RECORD_NAME ("CPU TIME (ms)")
-
-void
-io_write_cpu_samples_header(jlong total_cost, jint n_items)
-{
-
- if (gdata->output_format == 'b') {
- write_header(HPROF_CPU_SAMPLES, (n_items * (4 * 2)) + (4 * 2));
- write_u4((jint)total_cost);
- write_u4(n_items);
- } else {
- time_t t;
- char *record_name;
-
- if ( gdata->cpu_sampling ) {
- record_name = CPU_SAMPLES_RECORD_NAME;
- } else {
- record_name = CPU_TIMES_RECORD_NAME;
- }
- t = time(0);
- write_printf("%s BEGIN (total = %d) %s", record_name,
- /*jlong*/(int)total_cost, ctime(&t));
- if ( n_items > 0 ) {
- write_printf("rank self accum count trace method\n");
- }
- }
-}
-
-void
-io_write_cpu_samples_elem(jint index, double percent, double accum,
- jint num_hits, jlong cost, SerialNumber trace_serial_num,
- jint n_frames, char *csig, char *mname)
-{
- CHECK_TRACE_SERIAL_NO(trace_serial_num);
- if (gdata->output_format == 'b') {
- write_u4((jint)cost);
- write_u4(trace_serial_num);
- } else {
- write_printf("%4u %5.2f%% %5.2f%% %7u %5u",
- index, percent, accum, num_hits,
- trace_serial_num);
- if (n_frames > 0) {
- char * class_name;
-
- class_name = signature_to_name(csig);
- write_printf(" %s.%s\n", class_name, mname);
- HPROF_FREE(class_name);
- } else {
- write_printf(" <empty trace>\n");
- }
- }
-}
-
-void
-io_write_cpu_samples_footer(void)
-{
- if (gdata->output_format == 'b') {
- not_implemented();
- } else {
- char *record_name;
-
- if ( gdata->cpu_sampling ) {
- record_name = CPU_SAMPLES_RECORD_NAME;
- } else {
- record_name = CPU_TIMES_RECORD_NAME;
- }
- write_printf("%s END\n", record_name);
- }
-}
-
-void
-io_write_heap_summary(jlong total_live_bytes, jlong total_live_instances,
- jlong total_alloced_bytes, jlong total_alloced_instances)
-{
- if (gdata->output_format == 'b') {
- write_header(HPROF_HEAP_SUMMARY, 4 * 6);
- write_u4((jint)total_live_bytes);
- write_u4((jint)total_live_instances);
- write_u8(total_alloced_bytes);
- write_u8(total_alloced_instances);
- }
-}
-
-void
-io_write_oldprof_header(void)
-{
- if ( gdata->old_timing_format ) {
- write_printf("count callee caller time\n");
- }
-}
-
-void
-io_write_oldprof_elem(jint num_hits, jint num_frames, char *csig_callee,
- char *mname_callee, char *msig_callee, char *csig_caller,
- char *mname_caller, char *msig_caller, jlong cost)
-{
- if ( gdata->old_timing_format ) {
- char * class_name_callee;
- char * class_name_caller;
-
- class_name_callee = signature_to_name(csig_callee);
- class_name_caller = signature_to_name(csig_caller);
- write_printf("%d ", num_hits);
- if (num_frames >= 1) {
- write_printf("%s.%s%s ", class_name_callee,
- mname_callee, msig_callee);
- } else {
- write_printf("%s ", "<unknown callee>");
- }
- if (num_frames > 1) {
- write_printf("%s.%s%s ", class_name_caller,
- mname_caller, msig_caller);
- } else {
- write_printf("%s ", "<unknown caller>");
- }
- write_printf("%d\n", (int)cost);
- HPROF_FREE(class_name_callee);
- HPROF_FREE(class_name_caller);
- }
-}
-
-void
-io_write_oldprof_footer(void)
-{
-}
-
-void
-io_write_monitor_header(jlong total_time)
-{
- if (gdata->output_format == 'b') {
- not_implemented();
- } else {
- time_t t = time(0);
-
- t = time(0);
- write_printf("MONITOR TIME BEGIN (total = %u ms) %s",
- (int)total_time, ctime(&t));
- if (total_time > 0) {
- write_printf("rank self accum count trace monitor\n");
- }
- }
-}
-
-void
-io_write_monitor_elem(jint index, double percent, double accum,
- jint num_hits, SerialNumber trace_serial_num, char *sig)
-{
- CHECK_TRACE_SERIAL_NO(trace_serial_num);
- if (gdata->output_format == 'b') {
- not_implemented();
- } else {
- char *class_name;
-
- class_name = signature_to_name(sig);
- write_printf("%4u %5.2f%% %5.2f%% %7u %5u %s (Java)\n",
- index, percent, accum, num_hits,
- trace_serial_num, class_name);
- HPROF_FREE(class_name);
- }
-}
-
-void
-io_write_monitor_footer(void)
-{
- if (gdata->output_format == 'b') {
- not_implemented();
- } else {
- write_printf("MONITOR TIME END\n");
- }
-}
-
-void
-io_write_monitor_sleep(jlong timeout, SerialNumber thread_serial_num)
-{
- if (gdata->output_format == 'b') {
- not_implemented();
- } else {
- if ( thread_serial_num == 0 ) {
- write_printf("SLEEP: timeout=%d, <unknown thread>\n",
- (int)timeout);
- } else {
- CHECK_THREAD_SERIAL_NO(thread_serial_num);
- write_printf("SLEEP: timeout=%d, thread %d\n",
- (int)timeout, thread_serial_num);
- }
- }
-}
-
-void
-io_write_monitor_wait(char *sig, jlong timeout,
- SerialNumber thread_serial_num)
-{
- if (gdata->output_format == 'b') {
- not_implemented();
- } else {
- if ( thread_serial_num == 0 ) {
- write_printf("WAIT: MONITOR %s, timeout=%d, <unknown thread>\n",
- sig, (int)timeout);
- } else {
- CHECK_THREAD_SERIAL_NO(thread_serial_num);
- write_printf("WAIT: MONITOR %s, timeout=%d, thread %d\n",
- sig, (int)timeout, thread_serial_num);
- }
- }
-}
-
-void
-io_write_monitor_waited(char *sig, jlong time_waited,
- SerialNumber thread_serial_num)
-{
- if (gdata->output_format == 'b') {
- not_implemented();
- } else {
- if ( thread_serial_num == 0 ) {
- write_printf("WAITED: MONITOR %s, time_waited=%d, <unknown thread>\n",
- sig, (int)time_waited);
- } else {
- CHECK_THREAD_SERIAL_NO(thread_serial_num);
- write_printf("WAITED: MONITOR %s, time_waited=%d, thread %d\n",
- sig, (int)time_waited, thread_serial_num);
- }
- }
-}
-
-void
-io_write_monitor_exit(char *sig, SerialNumber thread_serial_num)
-{
- if (gdata->output_format == 'b') {
- not_implemented();
- } else {
- if ( thread_serial_num == 0 ) {
- write_printf("EXIT: MONITOR %s, <unknown thread>\n", sig);
- } else {
- CHECK_THREAD_SERIAL_NO(thread_serial_num);
- write_printf("EXIT: MONITOR %s, thread %d\n",
- sig, thread_serial_num);
- }
- }
-}
-
-void
-io_write_monitor_dump_header(void)
-{
- if (gdata->output_format == 'b') {
- not_implemented();
- } else {
- write_printf("MONITOR DUMP BEGIN\n");
- }
-}
-
-void
-io_write_monitor_dump_thread_state(SerialNumber thread_serial_num,
- SerialNumber trace_serial_num,
- jint threadState)
-{
- CHECK_THREAD_SERIAL_NO(thread_serial_num);
- CHECK_TRACE_SERIAL_NO(trace_serial_num);
- if (gdata->output_format == 'b') {
- not_implemented();
- } else {
- char tstate[20];
-
- tstate[0] = 0;
-
- if (threadState & JVMTI_THREAD_STATE_SUSPENDED) {
- (void)strcat(tstate,"S|");
- }
- if (threadState & JVMTI_THREAD_STATE_INTERRUPTED) {
- (void)strcat(tstate,"intr|");
- }
- if (threadState & JVMTI_THREAD_STATE_IN_NATIVE) {
- (void)strcat(tstate,"native|");
- }
- if ( ! ( threadState & JVMTI_THREAD_STATE_ALIVE ) ) {
- if ( threadState & JVMTI_THREAD_STATE_TERMINATED ) {
- (void)strcat(tstate,"ZO");
- } else {
- (void)strcat(tstate,"NS");
- }
- } else {
- if ( threadState & JVMTI_THREAD_STATE_SLEEPING ) {
- (void)strcat(tstate,"SL");
- } else if ( threadState & JVMTI_THREAD_STATE_BLOCKED_ON_MONITOR_ENTER ) {
- (void)strcat(tstate,"MW");
- } else if ( threadState & JVMTI_THREAD_STATE_WAITING ) {
- (void)strcat(tstate,"CW");
- } else if ( threadState & JVMTI_THREAD_STATE_RUNNABLE ) {
- (void)strcat(tstate,"R");
- } else {
- (void)strcat(tstate,"UN");
- }
- }
- write_printf(" THREAD %d, trace %d, status: %s\n",
- thread_serial_num, trace_serial_num, tstate);
- }
-}
-
-void
-io_write_monitor_dump_state(char *sig, SerialNumber thread_serial_num,
- jint entry_count,
- SerialNumber *waiters, jint waiter_count,
- SerialNumber *notify_waiters, jint notify_waiter_count)
-{
- if (gdata->output_format == 'b') {
- not_implemented();
- } else {
- int i;
-
- if ( thread_serial_num != 0 ) {
- CHECK_THREAD_SERIAL_NO(thread_serial_num);
- write_printf(" MONITOR %s\n", sig);
- write_printf("\towner: thread %d, entry count: %d\n",
- thread_serial_num, entry_count);
- } else {
- write_printf(" MONITOR %s unowned\n", sig);
- }
- write_printf("\twaiting to enter:");
- for (i = 0; i < waiter_count; i++) {
- write_thread_serial_number(waiters[i],
- (i != (waiter_count-1)));
- }
- write_printf("\n");
- write_printf("\twaiting to be notified:");
- for (i = 0; i < notify_waiter_count; i++) {
- write_thread_serial_number(notify_waiters[i],
- (i != (notify_waiter_count-1)));
- }
- write_printf("\n");
- }
-}
-
-void
-io_write_monitor_dump_footer(void)
-{
- if (gdata->output_format == 'b') {
- not_implemented();
- } else {
- write_printf("MONITOR DUMP END\n");
- }
-}
-
-/* ----------------------------------------------------------------- */
-/* These functions write to a separate file */
-
-void
-io_heap_header(jlong total_live_instances, jlong total_live_bytes)
-{
- if (gdata->output_format != 'b') {
- time_t t;
-
- t = time(0);
- heap_printf("HEAP DUMP BEGIN (%u objects, %u bytes) %s",
- /*jlong*/(int)total_live_instances,
- /*jlong*/(int)total_live_bytes, ctime(&t));
- }
-}
-
-void
-io_heap_root_thread_object(ObjectIndex thread_obj_id,
- SerialNumber thread_serial_num, SerialNumber trace_serial_num)
-{
- CHECK_THREAD_SERIAL_NO(thread_serial_num);
- CHECK_TRACE_SERIAL_NO(trace_serial_num);
- if (gdata->output_format == 'b') {
- heap_tag(HPROF_GC_ROOT_THREAD_OBJ);
- heap_id(thread_obj_id);
- heap_u4(thread_serial_num);
- heap_u4(trace_serial_num);
- } else {
- heap_printf("ROOT %x (kind=<thread>, id=%u, trace=%u)\n",
- thread_obj_id, thread_serial_num, trace_serial_num);
- }
-}
-
-void
-io_heap_root_unknown(ObjectIndex obj_id)
-{
- if (gdata->output_format == 'b') {
- heap_tag(HPROF_GC_ROOT_UNKNOWN);
- heap_id(obj_id);
- } else {
- heap_printf("ROOT %x (kind=<unknown>)\n", obj_id);
- }
-}
-
-void
-io_heap_root_jni_global(ObjectIndex obj_id, SerialNumber gref_serial_num,
- SerialNumber trace_serial_num)
-{
- CHECK_TRACE_SERIAL_NO(trace_serial_num);
- if (gdata->output_format == 'b') {
- heap_tag(HPROF_GC_ROOT_JNI_GLOBAL);
- heap_id(obj_id);
- heap_id(gref_serial_num);
- } else {
- heap_printf("ROOT %x (kind=<JNI global ref>, "
- "id=%x, trace=%u)\n",
- obj_id, gref_serial_num, trace_serial_num);
- }
-}
-
-void
-io_heap_root_jni_local(ObjectIndex obj_id, SerialNumber thread_serial_num,
- jint frame_depth)
-{
- CHECK_THREAD_SERIAL_NO(thread_serial_num);
- if (gdata->output_format == 'b') {
- heap_tag(HPROF_GC_ROOT_JNI_LOCAL);
- heap_id(obj_id);
- heap_u4(thread_serial_num);
- heap_u4(frame_depth);
- } else {
- heap_printf("ROOT %x (kind=<JNI local ref>, "
- "thread=%u, frame=%d)\n",
- obj_id, thread_serial_num, frame_depth);
- }
-}
-
-void
-io_heap_root_system_class(ObjectIndex obj_id, char *sig, SerialNumber class_serial_num)
-{
- if (gdata->output_format == 'b') {
- heap_tag(HPROF_GC_ROOT_STICKY_CLASS);
- heap_id(obj_id);
- } else {
- char *class_name;
-
- class_name = signature_to_name(sig);
- heap_printf("ROOT %x (kind=<system class>, name=%s)\n",
- obj_id, class_name);
- HPROF_FREE(class_name);
- }
-}
-
-void
-io_heap_root_monitor(ObjectIndex obj_id)
-{
- if (gdata->output_format == 'b') {
- heap_tag(HPROF_GC_ROOT_MONITOR_USED);
- heap_id(obj_id);
- } else {
- heap_printf("ROOT %x (kind=<busy monitor>)\n", obj_id);
- }
-}
-
-void
-io_heap_root_thread(ObjectIndex obj_id, SerialNumber thread_serial_num)
-{
- CHECK_THREAD_SERIAL_NO(thread_serial_num);
- if (gdata->output_format == 'b') {
- heap_tag(HPROF_GC_ROOT_THREAD_BLOCK);
- heap_id(obj_id);
- heap_u4(thread_serial_num);
- } else {
- heap_printf("ROOT %x (kind=<thread block>, thread=%u)\n",
- obj_id, thread_serial_num);
- }
-}
-
-void
-io_heap_root_java_frame(ObjectIndex obj_id, SerialNumber thread_serial_num,
- jint frame_depth)
-{
- CHECK_THREAD_SERIAL_NO(thread_serial_num);
- if (gdata->output_format == 'b') {
- heap_tag(HPROF_GC_ROOT_JAVA_FRAME);
- heap_id(obj_id);
- heap_u4(thread_serial_num);
- heap_u4(frame_depth);
- } else {
- heap_printf("ROOT %x (kind=<Java stack>, "
- "thread=%u, frame=%d)\n",
- obj_id, thread_serial_num, frame_depth);
- }
-}
-
-void
-io_heap_root_native_stack(ObjectIndex obj_id, SerialNumber thread_serial_num)
-{
- CHECK_THREAD_SERIAL_NO(thread_serial_num);
- if (gdata->output_format == 'b') {
- heap_tag(HPROF_GC_ROOT_NATIVE_STACK);
- heap_id(obj_id);
- heap_u4(thread_serial_num);
- } else {
- heap_printf("ROOT %x (kind=<native stack>, thread=%u)\n",
- obj_id, thread_serial_num);
- }
-}
-
-static jboolean
-is_static_field(jint modifiers)
-{
- if ( modifiers & JVM_ACC_STATIC ) {
- return JNI_TRUE;
- }
- return JNI_FALSE;
-}
-
-static jboolean
-is_inst_field(jint modifiers)
-{
- if ( modifiers & JVM_ACC_STATIC ) {
- return JNI_FALSE;
- }
- return JNI_TRUE;
-}
-
-void
-io_heap_class_dump(ClassIndex cnum, char *sig, ObjectIndex class_id,
- SerialNumber trace_serial_num,
- ObjectIndex super_id, ObjectIndex loader_id,
- ObjectIndex signers_id, ObjectIndex domain_id,
- jint size,
- jint n_cpool, ConstantPoolValue *cpool,
- jint n_fields, FieldInfo *fields, jvalue *fvalues)
-{
- CHECK_TRACE_SERIAL_NO(trace_serial_num);
- if (gdata->output_format == 'b') {
- int i;
- jint n_static_fields;
- jint n_inst_fields;
- jint inst_size;
- jint saved_inst_size;
-
- n_static_fields = 0;
- n_inst_fields = 0;
- inst_size = 0;
-
- /* These do NOT go into the heap output */
- for ( i = 0 ; i < n_fields ; i++ ) {
- if ( fields[i].cnum == cnum &&
- is_static_field(fields[i].modifiers) ) {
- char *field_name;
-
- field_name = string_get(fields[i].name_index);
- (void)write_name_first(field_name);
- n_static_fields++;
- }
- if ( is_inst_field(fields[i].modifiers) ) {
- inst_size += size_from_field_info(fields[i].primSize);
- if ( fields[i].cnum == cnum ) {
- char *field_name;
-
- field_name = string_get(fields[i].name_index);
- (void)write_name_first(field_name);
- n_inst_fields++;
- }
- }
- }
-
- /* Verify that the instance size we have calculated as we went
- * through the fields, matches what is saved away with this
- * class.
- */
- if ( size >= 0 ) {
- saved_inst_size = class_get_inst_size(cnum);
- if ( saved_inst_size == -1 ) {
- class_set_inst_size(cnum, inst_size);
- } else if ( saved_inst_size != inst_size ) {
- HPROF_ERROR(JNI_TRUE, "Mis-match on instance size in class dump");
- }
- }
-
- heap_tag(HPROF_GC_CLASS_DUMP);
- heap_id(class_id);
- heap_u4(trace_serial_num);
- heap_id(super_id);
- heap_id(loader_id);
- heap_id(signers_id);
- heap_id(domain_id);
- heap_id(0);
- heap_id(0);
- heap_u4(inst_size); /* Must match inst_size in instance dump */
-
- heap_u2((unsigned short)n_cpool);
- for ( i = 0 ; i < n_cpool ; i++ ) {
- HprofType kind;
- jint size;
-
- type_from_signature(string_get(cpool[i].sig_index),
- &kind, &size);
- heap_u2((unsigned short)(cpool[i].constant_pool_index));
- heap_u1(kind);
- HPROF_ASSERT(!HPROF_TYPE_IS_PRIMITIVE(kind));
- heap_element(kind, size, cpool[i].value);
- }
-
- heap_u2((unsigned short)n_static_fields);
- for ( i = 0 ; i < n_fields ; i++ ) {
- if ( fields[i].cnum == cnum &&
- is_static_field(fields[i].modifiers) ) {
- char *field_name;
- HprofType kind;
- jint size;
-
- type_from_signature(string_get(fields[i].sig_index),
- &kind, &size);
- field_name = string_get(fields[i].name_index);
- heap_name(field_name);
- heap_u1(kind);
- heap_element(kind, size, fvalues[i]);
- }
- }
-
- heap_u2((unsigned short)n_inst_fields); /* Does not include super class */
- for ( i = 0 ; i < n_fields ; i++ ) {
- if ( fields[i].cnum == cnum &&
- is_inst_field(fields[i].modifiers) ) {
- HprofType kind;
- jint size;
- char *field_name;
-
- field_name = string_get(fields[i].name_index);
- type_from_signature(string_get(fields[i].sig_index),
- &kind, &size);
- heap_name(field_name);
- heap_u1(kind);
- }
- }
- } else {
- char * class_name;
- int i;
-
- class_name = signature_to_name(sig);
- heap_printf("CLS %x (name=%s, trace=%u)\n",
- class_id, class_name, trace_serial_num);
- HPROF_FREE(class_name);
- if (super_id) {
- heap_printf("\tsuper\t\t%x\n", super_id);
- }
- if (loader_id) {
- heap_printf("\tloader\t\t%x\n", loader_id);
- }
- if (signers_id) {
- heap_printf("\tsigners\t\t%x\n", signers_id);
- }
- if (domain_id) {
- heap_printf("\tdomain\t\t%x\n", domain_id);
- }
- for ( i = 0 ; i < n_fields ; i++ ) {
- if ( fields[i].cnum == cnum &&
- is_static_field(fields[i].modifiers) ) {
- HprofType kind;
- jint size;
-
- type_from_signature(string_get(fields[i].sig_index),
- &kind, &size);
- if ( !HPROF_TYPE_IS_PRIMITIVE(kind) ) {
- if (fvalues[i].i != 0 ) {
- char *field_name;
-
- field_name = string_get(fields[i].name_index);
- heap_printf("\tstatic %s\t%x\n", field_name,
- fvalues[i].i);
- }
- }
- }
- }
- for ( i = 0 ; i < n_cpool ; i++ ) {
- HprofType kind;
- jint size;
-
- type_from_signature(string_get(cpool[i].sig_index), &kind, &size);
- if ( !HPROF_TYPE_IS_PRIMITIVE(kind) ) {
- if (cpool[i].value.i != 0 ) {
- heap_printf("\tconstant pool entry %d\t%x\n",
- cpool[i].constant_pool_index, cpool[i].value.i);
- }
- }
- }
- }
-}
-
-/* Dump the instance fields in the right order. */
-static int
-dump_instance_fields(ClassIndex cnum,
- FieldInfo *fields, jvalue *fvalues, jint n_fields)
-{
- ClassIndex super_cnum;
- int i;
- int nbytes;
-
- HPROF_ASSERT(cnum!=0);
-
- nbytes = 0;
- for (i = 0; i < n_fields; i++) {
- if ( fields[i].cnum == cnum &&
- is_inst_field(fields[i].modifiers) ) {
- HprofType kind;
- int size;
-
- type_from_signature(string_get(fields[i].sig_index),
- &kind, &size);
- heap_element(kind, size, fvalues[i]);
- nbytes += size;
- }
- }
-
- super_cnum = class_get_super(cnum);
- if ( super_cnum != 0 ) {
- nbytes += dump_instance_fields(super_cnum, fields, fvalues, n_fields);
- }
- return nbytes;
-}
-
-void
-io_heap_instance_dump(ClassIndex cnum, ObjectIndex obj_id,
- SerialNumber trace_serial_num,
- ObjectIndex class_id, jint size, char *sig,
- FieldInfo *fields, jvalue *fvalues, jint n_fields)
-{
- CHECK_TRACE_SERIAL_NO(trace_serial_num);
- if (gdata->output_format == 'b') {
- jint inst_size;
- jint saved_inst_size;
- int i;
- int nbytes;
-
- inst_size = 0;
- for (i = 0; i < n_fields; i++) {
- if ( is_inst_field(fields[i].modifiers) ) {
- inst_size += size_from_field_info(fields[i].primSize);
- }
- }
-
- /* Verify that the instance size we have calculated as we went
- * through the fields, matches what is saved away with this
- * class.
- */
- saved_inst_size = class_get_inst_size(cnum);
- if ( saved_inst_size == -1 ) {
- class_set_inst_size(cnum, inst_size);
- } else if ( saved_inst_size != inst_size ) {
- HPROF_ERROR(JNI_TRUE, "Mis-match on instance size in instance dump");
- }
-
- heap_tag(HPROF_GC_INSTANCE_DUMP);
- heap_id(obj_id);
- heap_u4(trace_serial_num);
- heap_id(class_id);
- heap_u4(inst_size); /* Must match inst_size in class dump */
-
- /* Order must be class, super, super's super, ... */
- nbytes = dump_instance_fields(cnum, fields, fvalues, n_fields);
- HPROF_ASSERT(nbytes==inst_size);
- } else {
- char * class_name;
- int i;
-
- class_name = signature_to_name(sig);
- heap_printf("OBJ %x (sz=%u, trace=%u, class=%s@%x)\n",
- obj_id, size, trace_serial_num, class_name, class_id);
- HPROF_FREE(class_name);
-
- for (i = 0; i < n_fields; i++) {
- if ( is_inst_field(fields[i].modifiers) ) {
- HprofType kind;
- int size;
-
- type_from_signature(string_get(fields[i].sig_index),
- &kind, &size);
- if ( !HPROF_TYPE_IS_PRIMITIVE(kind) ) {
- if (fvalues[i].i != 0 ) {
- char *sep;
- ObjectIndex val_id;
- char *field_name;
-
- field_name = string_get(fields[i].name_index);
- val_id = (ObjectIndex)(fvalues[i].i);
- sep = (int)strlen(field_name) < 8 ? "\t" : "";
- heap_printf("\t%s\t%s%x\n", field_name, sep, val_id);
- }
- }
- }
- }
- }
-}
-
-void
-io_heap_object_array(ObjectIndex obj_id, SerialNumber trace_serial_num,
- jint size, jint num_elements, char *sig, ObjectIndex *values,
- ObjectIndex class_id)
-{
- CHECK_TRACE_SERIAL_NO(trace_serial_num);
- if (gdata->output_format == 'b') {
-
- heap_tag(HPROF_GC_OBJ_ARRAY_DUMP);
- heap_id(obj_id);
- heap_u4(trace_serial_num);
- heap_u4(num_elements);
- heap_id(class_id);
- heap_elements(HPROF_NORMAL_OBJECT, num_elements,
- (jint)sizeof(HprofId), (void*)values);
- } else {
- char *name;
- int i;
-
- name = signature_to_name(sig);
- heap_printf("ARR %x (sz=%u, trace=%u, nelems=%u, elem type=%s@%x)\n",
- obj_id, size, trace_serial_num, num_elements,
- name, class_id);
- for (i = 0; i < num_elements; i++) {
- ObjectIndex id;
-
- id = values[i];
- if (id != 0) {
- heap_printf("\t[%u]\t\t%x\n", i, id);
- }
- }
- HPROF_FREE(name);
- }
-}
-
-void
-io_heap_prim_array(ObjectIndex obj_id, SerialNumber trace_serial_num,
- jint size, jint num_elements, char *sig, void *elements)
-{
- CHECK_TRACE_SERIAL_NO(trace_serial_num);
- if (gdata->output_format == 'b') {
- HprofType kind;
- jint esize;
-
- type_array(sig, &kind, &esize);
- HPROF_ASSERT(HPROF_TYPE_IS_PRIMITIVE(kind));
- heap_tag(HPROF_GC_PRIM_ARRAY_DUMP);
- heap_id(obj_id);
- heap_u4(trace_serial_num);
- heap_u4(num_elements);
- heap_u1(kind);
- heap_elements(kind, num_elements, esize, elements);
- } else {
- char *name;
-
- name = signature_to_name(sig);
- heap_printf("ARR %x (sz=%u, trace=%u, nelems=%u, elem type=%s)\n",
- obj_id, size, trace_serial_num, num_elements, name);
- HPROF_FREE(name);
- }
-}
-
-/* Move file bytes into supplied raw interface */
-static void
-write_raw_from_file(int fd, jlong byteCount, void (*raw_interface)(void *,int))
-{
- char *buf;
- int buf_len;
- int left;
- int nbytes;
-
- HPROF_ASSERT(fd >= 0);
-
- /* Move contents of this file into output file. */
- buf_len = FILE_IO_BUFFER_SIZE*2; /* Twice as big! */
- buf = HPROF_MALLOC(buf_len);
- HPROF_ASSERT(buf!=NULL);
-
- /* Keep track of how many we have left */
- left = (int)byteCount;
- do {
- int count;
-
- count = buf_len;
- if ( count > left ) count = left;
- nbytes = md_read(fd, buf, count);
- if (nbytes < 0) {
- system_error("read", nbytes, errno);
- break;
- }
- if (nbytes == 0) {
- break;
- }
- if ( nbytes > 0 ) {
- (*raw_interface)(buf, nbytes);
- left -= nbytes;
- }
- } while ( left > 0 );
-
- if (left > 0 && nbytes == 0) {
- HPROF_ERROR(JNI_TRUE, "File size is smaller than bytes written");
- }
- HPROF_FREE(buf);
-}
-
-/* Write out a heap segment, and copy remainder to top of file. */
-static void
-dump_heap_segment_and_reset(jlong segment_size)
-{
- int fd;
- jlong last_chunk_len;
-
- HPROF_ASSERT(gdata->heap_fd >= 0);
-
- /* Flush all bytes to the heap dump file */
- heap_flush();
-
- /* Last segment? */
- last_chunk_len = gdata->heap_write_count - segment_size;
- HPROF_ASSERT(last_chunk_len>=0);
-
- /* Re-open in proper way, binary vs. ascii is important */
- if (gdata->output_format == 'b') {
- int tag;
-
- if ( gdata->segmented == JNI_TRUE ) { /* 1.0.2 */
- tag = HPROF_HEAP_DUMP_SEGMENT; /* 1.0.2 */
- } else {
- tag = HPROF_HEAP_DUMP; /* Just one segment */
- HPROF_ASSERT(last_chunk_len==0);
- }
-
- /* Write header for binary heap dump (don't know size until now) */
- write_header(tag, (jint)segment_size);
-
- fd = md_open_binary(gdata->heapfilename);
- } else {
- fd = md_open(gdata->heapfilename);
- }
-
- /* Move file bytes into hprof dump file */
- write_raw_from_file(fd, segment_size, &write_raw);
-
- /* Clear the byte count and reset the heap file. */
- if ( md_seek(gdata->heap_fd, (jlong)0) != (jlong)0 ) {
- HPROF_ERROR(JNI_TRUE, "Cannot seek to beginning of heap info file");
- }
- gdata->heap_write_count = (jlong)0;
- gdata->heap_last_tag_position = (jlong)0;
-
- /* Move trailing bytes from heap dump file to beginning of file */
- if ( last_chunk_len > 0 ) {
- write_raw_from_file(fd, last_chunk_len, &heap_raw);
- }
-
- /* Close the temp file handle */
- md_close(fd);
-}
-
-void
-io_heap_footer(void)
-{
- HPROF_ASSERT(gdata->heap_fd >= 0);
-
- /* Flush all bytes to the heap dump file */
- heap_flush();
-
- /* Send out the last (or maybe only) segment */
- dump_heap_segment_and_reset(gdata->heap_write_count);
-
- /* Write out the last tag */
- if (gdata->output_format != 'b') {
- write_printf("HEAP DUMP END\n");
- } else {
- if ( gdata->segmented == JNI_TRUE ) { /* 1.0.2 */
- write_header(HPROF_HEAP_DUMP_END, 0);
- }
- }
-}
--- a/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_io.h Thu Aug 20 12:29:58 2015 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,169 +0,0 @@
-/*
- * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * - Neither the name of Oracle nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
- * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/*
- * This source code is provided to illustrate the usage of a given feature
- * or technique and has been deliberately simplified. Additional steps
- * required for a production-quality application, such as security checks,
- * input validation and proper error handling, might not be present in
- * this sample code.
- */
-
-
-#ifndef HPROF_IO_H
-#define HPROF_IO_H
-
-void io_flush(void);
-void io_setup(void);
-void io_cleanup(void);
-
-void io_write_file_header(void);
-void io_write_file_footer(void);
-
-void io_write_class_load(SerialNumber class_serial_num, ObjectIndex index,
- SerialNumber trace_serial_num, char *csig);
-void io_write_class_unload(SerialNumber class_serial_num, ObjectIndex index);
-
-void io_write_sites_header(const char * comment_str, jint flags,
- double cutoff, jint total_live_bytes,
- jint total_live_instances, jlong total_alloced_bytes,
- jlong total_alloced_instances, jint count);
-void io_write_sites_elem(jint index, double ratio, double accum_percent,
- char *csig, SerialNumber class_serial_num,
- SerialNumber trace_serial_num,
- jint n_live_bytes, jint n_live_instances,
- jint n_alloced_bytes, jint n_alloced_instances);
-void io_write_sites_footer(void);
-
-void io_write_thread_start(SerialNumber thread_serial_num, TlsIndex tls_index,
- SerialNumber trace_serial_num, char *thread_name,
- char *thread_group_name, char *thread_parent_name);
-void io_write_thread_end(SerialNumber thread_serial_num);
-
-void io_write_frame(FrameIndex index, SerialNumber serial_num,
- char *mname, char *msig,
- char *sname, SerialNumber class_serial_num,
- jint lineno);
-
-void io_write_trace_header(SerialNumber trace_serial_num,
- SerialNumber thread_serial_num, jint n_frames,
- char * phase_str);
-void io_write_trace_elem(SerialNumber trace_serial_num,
- FrameIndex frame_index, SerialNumber frame_serial_num,
- char *csig, char *mname,
- char *sname, jint lineno);
-void io_write_trace_footer(SerialNumber trace_serial_num,
- SerialNumber thread_serial_num, jint n_frames);
-
-void io_write_cpu_samples_header(jlong total_cost, jint n_items);
-void io_write_cpu_samples_elem(jint index, double percent, double accum,
- jint num_hits, jlong cost,
- SerialNumber trace_serial_num, jint n_frames,
- char *csig, char *mname);
-void io_write_cpu_samples_footer(void);
-
-void io_write_heap_summary(jlong total_live_bytes, jlong total_live_instances,
- jlong total_alloced_bytes,
- jlong total_alloced_instances);
-
-void io_write_oldprof_header(void);
-void io_write_oldprof_elem(jint num_hits, jint num_frames, char *csig_callee,
- char *mname_callee, char *msig_callee,
- char *csig_caller, char *mname_caller,
- char *msig_caller, jlong cost);
-void io_write_oldprof_footer(void);
-
-void io_write_monitor_header(jlong total_time);
-void io_write_monitor_elem(jint index, double percent, double accum,
- jint num_hits, SerialNumber trace_serial_num,
- char *sig);
-void io_write_monitor_footer(void);
-
-void io_write_monitor_sleep(jlong timeout, SerialNumber thread_serial_num);
-void io_write_monitor_wait(char *sig, jlong timeout,
- SerialNumber thread_serial_num);
-void io_write_monitor_waited(char *sig, jlong time_waited,
- SerialNumber thread_serial_num);
-void io_write_monitor_exit(char *sig, SerialNumber thread_serial_num);
-
-void io_write_monitor_dump_header(void);
-void io_write_monitor_dump_thread_state(SerialNumber thread_serial_num,
- SerialNumber trace_serial_num,
- jint threadState);
-void io_write_monitor_dump_state(char *sig,
- SerialNumber thread_serial_num, jint entry_count,
- SerialNumber *waiters, jint waiter_count,
- SerialNumber *notify_waiters, jint notify_waiter_count);
-void io_write_monitor_dump_footer(void);
-
-void io_heap_header(jlong total_live_instances, jlong total_live_bytes);
-
-void io_heap_root_thread_object(ObjectIndex thread_id,
- SerialNumber thread_serial_num,
- SerialNumber trace_serial_num);
-void io_heap_root_unknown(ObjectIndex obj_id);
-void io_heap_root_jni_global(ObjectIndex obj_id, SerialNumber gref_serial_num,
- SerialNumber trace_serial_num);
-void io_heap_root_jni_local(ObjectIndex obj_id,
- SerialNumber thread_serial_num, jint frame_depth);
-void io_heap_root_system_class(ObjectIndex obj_id, char *sig, SerialNumber class_serial_num);
-void io_heap_root_monitor(ObjectIndex obj_id);
-void io_heap_root_thread(ObjectIndex obj_id,
- SerialNumber thread_serial_num);
-void io_heap_root_java_frame(ObjectIndex obj_id,
- SerialNumber thread_serial_num, jint frame_depth);
-void io_heap_root_native_stack(ObjectIndex obj_id,
- SerialNumber thread_serial_num);
-
-void io_heap_class_dump(ClassIndex cnum, char *sig, ObjectIndex class_id,
- SerialNumber trace_serial_num,
- ObjectIndex super_id, ObjectIndex loader_id,
- ObjectIndex signers_id, ObjectIndex domain_id,
- jint inst_size,
- jint n_cpool, ConstantPoolValue *cpool,
- jint n_fields, FieldInfo *fields, jvalue *fvalues);
-
-void io_heap_instance_dump(ClassIndex cnum, ObjectIndex obj_id,
- SerialNumber trace_serial_num,
- ObjectIndex class_id, jint size,
- char *sig, FieldInfo *fields,
- jvalue *fvalues, jint n_fields);
-
-void io_heap_object_array(ObjectIndex obj_id, SerialNumber trace_serial_num,
- jint size, jint num_elements, char *sig,
- ObjectIndex *values, ObjectIndex class_id);
-void io_heap_prim_array(ObjectIndex obj_id, SerialNumber trace_serial_num,
- jint size, jint num_elements, char *sig,
- void *elements);
-
-void io_heap_footer(void);
-
-#endif
--- a/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_ioname.c Thu Aug 20 12:29:58 2015 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,71 +0,0 @@
-/*
- * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * - Neither the name of Oracle nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
- * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/*
- * This source code is provided to illustrate the usage of a given feature
- * or technique and has been deliberately simplified. Additional steps
- * required for a production-quality application, such as security checks,
- * input validation and proper error handling, might not be present in
- * this sample code.
- */
-
-
-/* Used to store strings written out to the binary format (see hprof_io.c) */
-
-
-/* Probably could have used the basic string table, however, some strings
- * would only be in this table, so it was isolated as a separate table
- * of strings.
- */
-
-#include "hprof.h"
-#include "hprof_ioname.h"
-
-void
-ioname_init(void)
-{
- HPROF_ASSERT(gdata->ioname_table==NULL);
- gdata->ioname_table = table_initialize("IoNames", 512, 512, 511, 0);
-}
-
-IoNameIndex
-ioname_find_or_create(const char *name, jboolean *pnew_entry)
-{
- return table_find_or_create_entry(gdata->ioname_table,
- (void*)name, (int)strlen(name)+1, pnew_entry, NULL);
-}
-
-void
-ioname_cleanup(void)
-{
- table_cleanup(gdata->ioname_table, NULL, NULL);
- gdata->ioname_table = NULL;
-}
--- a/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_ioname.h Thu Aug 20 12:29:58 2015 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,48 +0,0 @@
-/*
- * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * - Neither the name of Oracle nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
- * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/*
- * This source code is provided to illustrate the usage of a given feature
- * or technique and has been deliberately simplified. Additional steps
- * required for a production-quality application, such as security checks,
- * input validation and proper error handling, might not be present in
- * this sample code.
- */
-
-
-#ifndef HPROF_IONAME_H
-#define HPROF_IONAME_H
-
-void ioname_init(void);
-IoNameIndex ioname_find_or_create(const char *name, jboolean *pnew_entry);
-void ioname_cleanup(void);
-
-#endif
--- a/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_listener.c Thu Aug 20 12:29:58 2015 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,436 +0,0 @@
-/*
- * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * - Neither the name of Oracle nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
- * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/*
- * This source code is provided to illustrate the usage of a given feature
- * or technique and has been deliberately simplified. Additional steps
- * required for a production-quality application, such as security checks,
- * input validation and proper error handling, might not be present in
- * this sample code.
- */
-
-
-/* The hprof listener loop thread. net=hostname:port option */
-
-/*
- * The option net=hostname:port causes all hprof output to be sent down
- * a socket connection, and also allows for commands to come in over the
- * socket. The commands are documented below.
- *
- * This thread can cause havoc when started prematurely or not terminated
- * properly, see listener_init() and listener_term(), and their calls
- * in hprof_init.c.
- *
- * The listener loop (hprof_listener.c) can dynamically turn on or off the
- * sampling of all or selected threads.
- *
- * The specification of this command protocol is only here, in the comments
- * below. The HAT tools uses this interface.
- * It is also unknown how well these options work given the limited
- * testing of this interface.
- *
- */
-
-#include "hprof.h"
-
-/* When the hprof Agent in the VM is connected via a socket to the
- * profiling client, the client may send the hprof Agent a set of commands.
- * The commands have the following format:
- *
- * u1 a TAG denoting the type of the record
- * u4 a serial number
- * u4 number of bytes *remaining* in the record. Note that
- * this number excludes the tag and the length field itself.
- * [u1]* BODY of the record (a sequence of bytes)
- */
-
-/* The following commands are presently supported:
- *
- * TAG BODY notes
- * ----------------------------------------------------------
- * HPROF_CMD_GC force a GC.
- *
- * HPROF_CMD_DUMP_HEAP obtain a heap dump
- *
- * HPROF_CMD_ALLOC_SITES obtain allocation sites
- *
- * u2 flags 0x0001: incremental vs. complete
- * 0x0002: sorted by allocation vs. live
- * 0x0004: whether to force a GC
- * u4 cutoff ratio (0.0 ~ 1.0)
- *
- * HPROF_CMD_HEAP_SUMMARY obtain heap summary
- *
- * HPROF_CMD_DUMP_TRACES obtain all newly created traces
- *
- * HPROF_CMD_CPU_SAMPLES obtain a HPROF_CPU_SAMPLES record
- *
- * u2 ignored for now
- * u4 cutoff ratio (0.0 ~ 1.0)
- *
- * HPROF_CMD_CONTROL changing settings
- *
- * u2 0x0001: alloc traces on
- * 0x0002: alloc traces off
- *
- * 0x0003: CPU sampling on
- *
- * id: thread object id (NULL for all)
- *
- * 0x0004: CPU sampling off
- *
- * id: thread object id (NULL for all)
- *
- * 0x0005: CPU sampling clear
- *
- * 0x0006: clear alloc sites info
- *
- * 0x0007: set max stack depth in CPU samples
- * and alloc traces
- *
- * u2: new depth
- */
-
-typedef enum HprofCmd {
- HPROF_CMD_GC = 0x01,
- HPROF_CMD_DUMP_HEAP = 0x02,
- HPROF_CMD_ALLOC_SITES = 0x03,
- HPROF_CMD_HEAP_SUMMARY = 0x04,
- HPROF_CMD_EXIT = 0x05,
- HPROF_CMD_DUMP_TRACES = 0x06,
- HPROF_CMD_CPU_SAMPLES = 0x07,
- HPROF_CMD_CONTROL = 0x08,
- HPROF_CMD_EOF = 0xFF
-} HprofCmd;
-
-static jint
-recv_fully(int f, char *buf, int len)
-{
- jint nbytes;
-
- nbytes = 0;
- if ( f < 0 ) {
- return nbytes;
- }
- while (nbytes < len) {
- int res;
-
- res = md_recv(f, buf + nbytes, (len - nbytes), 0);
- if (res < 0) {
- /*
- * hprof was disabled before we returned from recv() above.
- * This means the command socket is closed so we let that
- * trickle back up the command processing stack.
- */
- LOG("recv() returned < 0");
- break;
- }
- nbytes += res;
- }
- return nbytes;
-}
-
-static unsigned char
-recv_u1(void)
-{
- unsigned char c;
- jint nbytes;
-
- nbytes = recv_fully(gdata->fd, (char *)&c, (int)sizeof(unsigned char));
- if (nbytes == 0) {
- c = HPROF_CMD_EOF;
- }
- return c;
-}
-
-static unsigned short
-recv_u2(void)
-{
- unsigned short s;
- jint nbytes;
-
- nbytes = recv_fully(gdata->fd, (char *)&s, (int)sizeof(unsigned short));
- if (nbytes == 0) {
- s = (unsigned short)-1;
- }
- return md_ntohs(s);
-}
-
-static unsigned
-recv_u4(void)
-{
- unsigned i;
- jint nbytes;
-
- nbytes = recv_fully(gdata->fd, (char *)&i, (int)sizeof(unsigned));
- if (nbytes == 0) {
- i = (unsigned)-1;
- }
- return md_ntohl(i);
-}
-
-static ObjectIndex
-recv_id(void)
-{
- ObjectIndex result;
- jint nbytes;
-
- nbytes = recv_fully(gdata->fd, (char *)&result, (int)sizeof(ObjectIndex));
- if (nbytes == 0) {
- result = (ObjectIndex)0;
- }
- return result;
-}
-
-static void JNICALL
-listener_loop_function(jvmtiEnv *jvmti, JNIEnv *env, void *p)
-{
- jboolean keep_processing;
- unsigned char tag;
- jboolean kill_the_whole_process;
-
- kill_the_whole_process = JNI_FALSE;
- tag = 0;
-
- rawMonitorEnter(gdata->listener_loop_lock); {
- gdata->listener_loop_running = JNI_TRUE;
- keep_processing = gdata->listener_loop_running;
- /* Tell listener_init() that we have started */
- rawMonitorNotifyAll(gdata->listener_loop_lock);
- } rawMonitorExit(gdata->listener_loop_lock);
-
- while ( keep_processing ) {
-
- LOG("listener loop iteration");
-
- tag = recv_u1(); /* This blocks here on the socket read, a close()
- * on this fd will wake this up. And if recv_u1()
- * can't read anything, it returns HPROF_CMD_EOF.
- */
-
- LOG3("listener_loop", "command = ", tag);
-
- if (tag == HPROF_CMD_EOF) {
- /* The cmd socket has closed so the listener thread is done
- * just fall out of loop and let the thread die.
- */
- keep_processing = JNI_FALSE;
- break;
- }
-
- /* seq_num not used */
- (void)recv_u4();
- /* length not used */
- (void)recv_u4();
-
- switch (tag) {
- case HPROF_CMD_GC:
- runGC();
- break;
- case HPROF_CMD_DUMP_HEAP: {
- site_heapdump(env);
- break;
- }
- case HPROF_CMD_ALLOC_SITES: {
- unsigned short flags;
- unsigned i_tmp;
- float ratio;
-
- flags = recv_u2();
- i_tmp = recv_u4();
- ratio = *(float *)(&i_tmp);
- site_write(env, flags, ratio);
- break;
- }
- case HPROF_CMD_HEAP_SUMMARY: {
- rawMonitorEnter(gdata->data_access_lock); {
- io_write_heap_summary( gdata->total_live_bytes,
- gdata->total_live_instances,
- gdata->total_alloced_bytes,
- gdata->total_alloced_instances);
- } rawMonitorExit(gdata->data_access_lock);
- break;
- }
- case HPROF_CMD_EXIT:
- keep_processing = JNI_FALSE;
- kill_the_whole_process = JNI_TRUE;
- verbose_message("HPROF: received exit event, exiting ...\n");
- break;
- case HPROF_CMD_DUMP_TRACES:
- rawMonitorEnter(gdata->data_access_lock); {
- trace_output_unmarked(env);
- } rawMonitorExit(gdata->data_access_lock);
- break;
- case HPROF_CMD_CPU_SAMPLES: {
- unsigned i_tmp;
- float ratio;
-
- /* flags not used */
- (void)recv_u2();
- i_tmp = recv_u4();
- ratio = *(float *)(&i_tmp);
- trace_output_cost(env, ratio);
- break;
- }
- case HPROF_CMD_CONTROL: {
- unsigned short cmd = recv_u2();
- if (cmd == 0x0001) {
- setEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_OBJECT_FREE, NULL);
- tracker_engage(env);
- } else if (cmd == 0x0002) {
- setEventNotificationMode(JVMTI_DISABLE, JVMTI_EVENT_OBJECT_FREE, NULL);
- tracker_disengage(env);
- } else if (cmd == 0x0003) {
- ObjectIndex thread_object_index;
- thread_object_index = recv_id();
- cpu_sample_on(env, thread_object_index);
- } else if (cmd == 0x0004) {
- ObjectIndex thread_object_index;
- thread_object_index = recv_id();
- cpu_sample_off(env, thread_object_index);
- } else if (cmd == 0x0005) {
- rawMonitorEnter(gdata->data_access_lock); {
- trace_clear_cost();
- } rawMonitorExit(gdata->data_access_lock);
- } else if (cmd == 0x0006) {
- rawMonitorEnter(gdata->data_access_lock); {
- site_cleanup();
- site_init();
- } rawMonitorExit(gdata->data_access_lock);
- } else if (cmd == 0x0007) {
- gdata->max_trace_depth = recv_u2();
- }
- break;
- }
- default:{
- char buf[80];
-
- keep_processing = JNI_FALSE;
- kill_the_whole_process = JNI_TRUE;
- (void)md_snprintf(buf, sizeof(buf),
- "failed to recognize cmd %d, exiting..", (int)tag);
- buf[sizeof(buf)-1] = 0;
- HPROF_ERROR(JNI_FALSE, buf);
- break;
- }
- }
-
- rawMonitorEnter(gdata->data_access_lock); {
- io_flush();
- } rawMonitorExit(gdata->data_access_lock);
-
- rawMonitorEnter(gdata->listener_loop_lock); {
- if ( !gdata->listener_loop_running ) {
- keep_processing = JNI_FALSE;
- }
- } rawMonitorExit(gdata->listener_loop_lock);
-
- }
-
- /* If listener_term() is causing this loop to terminate, then
- * you will block here until listener_term wants you to proceed.
- */
- rawMonitorEnter(gdata->listener_loop_lock); {
- if ( gdata->listener_loop_running ) {
- /* We are terminating for our own reasons, maybe because of
- * EOF (socket closed?), or EXIT request, or invalid command.
- * Not from listener_term().
- * We set gdata->listener_loop_running=FALSE so that any
- * future call to listener_term() will do nothing.
- */
- gdata->listener_loop_running = JNI_FALSE;
- } else {
- /* We assume that listener_term() is stopping us,
- * now we need to tell it we understood.
- */
- rawMonitorNotifyAll(gdata->listener_loop_lock);
- }
- } rawMonitorExit(gdata->listener_loop_lock);
-
- LOG3("listener_loop", "finished command = ", tag);
-
- /* If we got an explicit command request to die, die here */
- if ( kill_the_whole_process ) {
- error_exit_process(0);
- }
-
-}
-
-/* External functions */
-
-void
-listener_init(JNIEnv *env)
-{
- /* Create the raw monitor */
- gdata->listener_loop_lock = createRawMonitor("HPROF listener lock");
-
- rawMonitorEnter(gdata->listener_loop_lock); {
- createAgentThread(env, "HPROF listener thread",
- &listener_loop_function);
- /* Wait for listener_loop_function() to tell us it started. */
- rawMonitorWait(gdata->listener_loop_lock, 0);
- } rawMonitorExit(gdata->listener_loop_lock);
-}
-
-void
-listener_term(JNIEnv *env)
-{
- rawMonitorEnter(gdata->listener_loop_lock); {
-
- /* If we are in the middle of sending bytes down the socket, this
- * at least keeps us blocked until that processing is done.
- */
- rawMonitorEnter(gdata->data_access_lock); {
-
- /* Make sure the socket gets everything */
- io_flush();
-
- /*
- * Graceful shutdown of the socket will assure that all data
- * sent is received before the socket close completes.
- */
- (void)md_shutdown(gdata->fd, 2 /* disallow sends and receives */);
-
- /* This close will cause the listener loop to possibly wake up
- * from the recv_u1(), this is critical to get thread running again.
- */
- md_close(gdata->fd);
- } rawMonitorExit(gdata->data_access_lock);
-
- /* It could have shut itself down, so we check the global flag */
- if ( gdata->listener_loop_running ) {
- /* It stopped because of something listener_term() did. */
- gdata->listener_loop_running = JNI_FALSE;
- /* Wait for listener_loop_function() to tell us it finished. */
- rawMonitorWait(gdata->listener_loop_lock, 0);
- }
- } rawMonitorExit(gdata->listener_loop_lock);
-}
--- a/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_listener.h Thu Aug 20 12:29:58 2015 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,47 +0,0 @@
-/*
- * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * - Neither the name of Oracle nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
- * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/*
- * This source code is provided to illustrate the usage of a given feature
- * or technique and has been deliberately simplified. Additional steps
- * required for a production-quality application, such as security checks,
- * input validation and proper error handling, might not be present in
- * this sample code.
- */
-
-
-#ifndef HPROF_LISTENER_H
-#define HPROF_LISTENER_H
-
-void listener_init(JNIEnv *env);
-void listener_term(JNIEnv *env);
-
-#endif
--- a/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_loader.c Thu Aug 20 12:29:58 2015 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,270 +0,0 @@
-/*
- * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * - Neither the name of Oracle nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
- * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/*
- * This source code is provided to illustrate the usage of a given feature
- * or technique and has been deliberately simplified. Additional steps
- * required for a production-quality application, such as security checks,
- * input validation and proper error handling, might not be present in
- * this sample code.
- */
-
-
-/* The Class Loader table. */
-
-/*
- * The Class Loader objects show up so early in the VM process that a
- * separate table was designated for Class Loaders.
- *
- * The Class Loader is unique by way of it's jobject uniqueness, unfortunately
- * use of JNI too early for jobject comparisons is problematic.
- * It is assumed that the number of class loaders will be limited, and
- * a simple linear search will be performed for now.
- * That logic is isolated here and can be changed to use the standard
- * table hash table search once we know JNI can be called safely.
- *
- * A weak global reference is created to keep tabs on loaders, and as
- * each search for a loader happens, NULL weak global references will
- * trigger the freedom of those entries.
- *
- */
-
-#include "hprof.h"
-
-typedef struct {
- jobject globalref; /* Weak Global reference for object */
- ObjectIndex object_index;
-} LoaderInfo;
-
-static LoaderInfo *
-get_info(LoaderIndex index)
-{
- return (LoaderInfo*)table_get_info(gdata->loader_table, index);
-}
-
-static void
-delete_globalref(JNIEnv *env, LoaderInfo *info)
-{
- jobject ref;
-
- HPROF_ASSERT(env!=NULL);
- HPROF_ASSERT(info!=NULL);
- ref = info->globalref;
- info->globalref = NULL;
- if ( ref != NULL ) {
- deleteWeakGlobalReference(env, ref);
- }
- info->object_index = 0;
-}
-
-static void
-cleanup_item(TableIndex index, void *key_ptr, int key_len,
- void *info_ptr, void *arg)
-{
-}
-
-static void
-delete_ref_item(TableIndex index, void *key_ptr, int key_len,
- void *info_ptr, void *arg)
-{
- delete_globalref((JNIEnv*)arg, (LoaderInfo*)info_ptr);
-}
-
-static void
-list_item(TableIndex index, void *key_ptr, int key_len,
- void *info_ptr, void *arg)
-{
- LoaderInfo *info;
-
- HPROF_ASSERT(info_ptr!=NULL);
-
- info = (LoaderInfo*)info_ptr;
- debug_message( "Loader 0x%08x: globalref=%p, object_index=%d\n",
- index, (void*)info->globalref, info->object_index);
-}
-
-static void
-free_entry(JNIEnv *env, LoaderIndex index)
-{
- LoaderInfo *info;
-
- info = get_info(index);
- delete_globalref(env, info);
- table_free_entry(gdata->loader_table, index);
-}
-
-typedef struct SearchData {
- JNIEnv *env;
- jobject loader;
- LoaderIndex found;
-} SearchData;
-
-static void
-search_item(TableIndex index, void *key_ptr, int key_len, void *info_ptr, void *arg)
-{
- LoaderInfo *info;
- SearchData *data;
-
- HPROF_ASSERT(info_ptr!=NULL);
- HPROF_ASSERT(arg!=NULL);
- info = (LoaderInfo*)info_ptr;
- data = (SearchData*)arg;
- if ( data->loader == info->globalref ) {
- /* Covers when looking for NULL too. */
- HPROF_ASSERT(data->found==0); /* Did we find more than one? */
- data->found = index;
- } else if ( data->env != NULL && data->loader != NULL &&
- info->globalref != NULL ) {
- jobject lref;
-
- lref = newLocalReference(data->env, info->globalref);
- if ( lref == NULL ) {
- /* Object went away, free reference and entry */
- free_entry(data->env, index);
- } else if ( isSameObject(data->env, data->loader, lref) ) {
- HPROF_ASSERT(data->found==0); /* Did we find more than one? */
- data->found = index;
- }
- if ( lref != NULL ) {
- deleteLocalReference(data->env, lref);
- }
- }
-
-}
-
-static LoaderIndex
-search(JNIEnv *env, jobject loader)
-{
- SearchData data;
-
- data.env = env;
- data.loader = loader;
- data.found = 0;
- table_walk_items(gdata->loader_table, &search_item, (void*)&data);
- return data.found;
-}
-
-LoaderIndex
-loader_find_or_create(JNIEnv *env, jobject loader)
-{
- LoaderIndex index;
-
- /* See if we remembered the system loader */
- if ( loader==NULL && gdata->system_loader != 0 ) {
- return gdata->system_loader;
- }
- if ( loader==NULL ) {
- env = NULL;
- }
- index = search(env, loader);
- if ( index == 0 ) {
- static LoaderInfo empty_info;
- LoaderInfo info;
-
- info = empty_info;
- if ( loader != NULL ) {
- HPROF_ASSERT(env!=NULL);
- info.globalref = newWeakGlobalReference(env, loader);
- info.object_index = 0;
- }
- index = table_create_entry(gdata->loader_table, NULL, 0, (void*)&info);
- }
- HPROF_ASSERT(search(env,loader)==index);
- /* Remember the system loader */
- if ( loader==NULL && gdata->system_loader == 0 ) {
- gdata->system_loader = index;
- }
- return index;
-}
-
-void
-loader_init(void)
-{
- gdata->loader_table = table_initialize("Loader",
- 16, 16, 0, (int)sizeof(LoaderInfo));
-}
-
-void
-loader_list(void)
-{
- debug_message(
- "--------------------- Loader Table ------------------------\n");
- table_walk_items(gdata->loader_table, &list_item, NULL);
- debug_message(
- "----------------------------------------------------------\n");
-}
-
-void
-loader_cleanup(void)
-{
- table_cleanup(gdata->loader_table, &cleanup_item, NULL);
- gdata->loader_table = NULL;
-}
-
-void
-loader_delete_global_references(JNIEnv *env)
-{
- table_walk_items(gdata->loader_table, &delete_ref_item, (void*)env);
-}
-
-/* Get the object index for a class loader */
-ObjectIndex
-loader_object_index(JNIEnv *env, LoaderIndex index)
-{
- LoaderInfo *info;
- ObjectIndex object_index;
- jobject wref;
-
- /* Assume no object index at first (default class loader) */
- info = get_info(index);
- object_index = info->object_index;
- wref = info->globalref;
- if ( wref != NULL && object_index == 0 ) {
- jobject lref;
-
- object_index = 0;
- lref = newLocalReference(env, wref);
- if ( lref != NULL && !isSameObject(env, lref, NULL) ) {
- jlong tag;
-
- /* Get the tag on the object and extract the object_index */
- tag = getTag(lref);
- if ( tag != (jlong)0 ) {
- object_index = tag_extract(tag);
- }
- }
- if ( lref != NULL ) {
- deleteLocalReference(env, lref);
- }
- info->object_index = object_index;
- }
- return object_index;
-}
--- a/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_loader.h Thu Aug 20 12:29:58 2015 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,51 +0,0 @@
-/*
- * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * - Neither the name of Oracle nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
- * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/*
- * This source code is provided to illustrate the usage of a given feature
- * or technique and has been deliberately simplified. Additional steps
- * required for a production-quality application, such as security checks,
- * input validation and proper error handling, might not be present in
- * this sample code.
- */
-
-
-#ifndef HPROF_LOADER_H
-#define HPROF_LOADER_H
-
-LoaderIndex loader_find_or_create(JNIEnv *env, jobject loader);
-void loader_init(void);
-void loader_list(void);
-void loader_delete_global_references(JNIEnv *env);
-void loader_cleanup(void);
-ObjectIndex loader_object_index(JNIEnv *env, LoaderIndex index);
-
-#endif
--- a/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_md.h Thu Aug 20 12:29:58 2015 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,77 +0,0 @@
-/*
- * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * - Neither the name of Oracle nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
- * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/*
- * This source code is provided to illustrate the usage of a given feature
- * or technique and has been deliberately simplified. Additional steps
- * required for a production-quality application, such as security checks,
- * input validation and proper error handling, might not be present in
- * this sample code.
- */
-
-
-#ifndef HPROF_MD_H
-#define HPROF_MD_H
-
-void md_init(void);
-int md_getpid(void);
-void md_sleep(unsigned seconds);
-int md_connect(char *hostname, unsigned short port);
-int md_recv(int f, char *buf, int len, int option);
-int md_shutdown(int filedes, int option);
-int md_open(const char *filename);
-int md_open_binary(const char *filename);
-int md_creat(const char *filename);
-int md_creat_binary(const char *filename);
-jlong md_seek(int filedes, jlong cur);
-void md_close(int filedes);
-int md_send(int s, const char *msg, int len, int flags);
-int md_write(int filedes, const void *buf, int nbyte);
-int md_read(int filedes, void *buf, int nbyte);
-jlong md_get_microsecs(void);
-jlong md_get_timemillis(void);
-jlong md_get_thread_cpu_timemillis(void);
-void md_get_prelude_path(char *path, int path_len, char *filename);
-int md_snprintf(char *s, int n, const char *format, ...);
-int md_vsnprintf(char *s, int n, const char *format, va_list ap);
-void md_system_error(char *buf, int len);
-
-unsigned md_htons(unsigned short s);
-unsigned md_htonl(unsigned l);
-unsigned md_ntohs(unsigned short s);
-unsigned md_ntohl(unsigned l);
-
-void md_build_library_name(char *holder, int holderlen, const char *pname, const char *fname);
-void * md_load_library(const char *name, char *err_buf, int err_buflen);
-void md_unload_library(void *handle);
-void * md_find_library_entry(void *handle, const char *name);
-
-#endif
--- a/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_monitor.c Thu Aug 20 12:29:58 2015 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,442 +0,0 @@
-/*
- * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * - Neither the name of Oracle nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
- * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/*
- * This source code is provided to illustrate the usage of a given feature
- * or technique and has been deliberately simplified. Additional steps
- * required for a production-quality application, such as security checks,
- * input validation and proper error handling, might not be present in
- * this sample code.
- */
-
-
-/* Monitor contention tracking and monitor wait handling. */
-
-/*
- * Monitor's under contention are unique per trace and signature.
- * Two monitors with the same trace and signature will be treated
- * the same as far as accumulated contention time.
- *
- * The tls table (or thread table) will be used to store the monitor in
- * contention or being waited on.
- *
- * Monitor wait activity is emitted as it happens.
- *
- * Monitor contention is tabulated and summarized at dump time.
- *
- */
-
-#include "hprof.h"
-
-typedef struct MonitorKey {
- TraceIndex trace_index;
- StringIndex sig_index;
-} MonitorKey;
-
-typedef struct MonitorInfo {
- jint num_hits;
- jlong contended_time;
-} MonitorInfo;
-
-typedef struct IterateInfo {
- MonitorIndex *monitors;
- int count;
- jlong total_contended_time;
-} IterateInfo;
-
-/* Private internal functions. */
-
-static MonitorKey*
-get_pkey(MonitorIndex index)
-{
- void * key_ptr;
- int key_len;
-
- table_get_key(gdata->monitor_table, index, &key_ptr, &key_len);
- HPROF_ASSERT(key_len==sizeof(MonitorKey));
- HPROF_ASSERT(key_ptr!=NULL);
- return (MonitorKey*)key_ptr;
-}
-
-static MonitorInfo *
-get_info(MonitorIndex index)
-{
- MonitorInfo * info;
-
- HPROF_ASSERT(index!=0);
- info = (MonitorInfo*)table_get_info(gdata->monitor_table, index);
- HPROF_ASSERT(info!=NULL);
- return info;
-}
-
-static MonitorIndex
-find_or_create_entry(JNIEnv *env, TraceIndex trace_index, jobject object)
-{
- static MonitorKey empty_key;
- MonitorKey key;
- MonitorIndex index;
- char *sig;
-
- HPROF_ASSERT(object!=NULL);
- WITH_LOCAL_REFS(env, 1) {
- jclass clazz;
-
- clazz = getObjectClass(env, object);
- getClassSignature(clazz, &sig, NULL);
- } END_WITH_LOCAL_REFS;
-
- key = empty_key;
- key.trace_index = trace_index;
- key.sig_index = string_find_or_create(sig);
- jvmtiDeallocate(sig);
- index = table_find_or_create_entry(gdata->monitor_table, &key,
- (int)sizeof(key), NULL, NULL);
- return index;
-}
-
-static void
-cleanup_item(MonitorIndex index, void *key_ptr, int key_len, void *info_ptr, void *arg)
-{
-}
-
-static void
-list_item(TableIndex index, void *key_ptr, int key_len, void *info_ptr, void *arg)
-{
- MonitorInfo *info;
- MonitorKey *pkey;
-
- HPROF_ASSERT(key_len==sizeof(MonitorKey));
- HPROF_ASSERT(key_ptr!=NULL);
- HPROF_ASSERT(info_ptr!=NULL);
- pkey = (MonitorKey*)key_ptr;
- info = (MonitorInfo *)info_ptr;
- debug_message(
- "Monitor 0x%08x: trace=0x%08x, sig=0x%08x, "
- "num_hits=%d, contended_time=(%d,%d)\n",
- index,
- pkey->trace_index,
- pkey->sig_index,
- info->num_hits,
- jlong_high(info->contended_time),
- jlong_low(info->contended_time));
-}
-
-static void
-collect_iterator(MonitorIndex index, void *key_ptr, int key_len, void *info_ptr, void *arg)
-{
- MonitorInfo *info;
- IterateInfo *iterate;
-
- HPROF_ASSERT(key_len==sizeof(MonitorKey));
- HPROF_ASSERT(info_ptr!=NULL);
- HPROF_ASSERT(arg!=NULL);
- iterate = (IterateInfo *)arg;
- info = (MonitorInfo *)info_ptr;
- iterate->monitors[iterate->count++] = index;
- iterate->total_contended_time += info->contended_time;
-}
-
-static int
-qsort_compare(const void *p_monitor1, const void *p_monitor2)
-{
- MonitorInfo * info1;
- MonitorInfo * info2;
- MonitorIndex monitor1;
- MonitorIndex monitor2;
- jlong result;
-
- HPROF_ASSERT(p_monitor1!=NULL);
- HPROF_ASSERT(p_monitor2!=NULL);
- monitor1 = *(MonitorIndex *)p_monitor1;
- monitor2 = *(MonitorIndex *)p_monitor2;
- info1 = get_info(monitor1);
- info2 = get_info(monitor2);
-
- result = info2->contended_time - info1->contended_time;
- if (result < (jlong)0) {
- return -1;
- } else if ( result > (jlong)0 ) {
- return 1;
- }
- return info2->num_hits - info1->num_hits;
-}
-
-static void
-clear_item(MonitorIndex index, void *key_ptr, int key_len, void *info_ptr, void *arg)
-{
- MonitorInfo *info;
-
- HPROF_ASSERT(key_len==sizeof(MonitorKey));
- HPROF_ASSERT(info_ptr!=NULL);
- info = (MonitorInfo *)info_ptr;
- info->contended_time = 0;
-}
-
-static TraceIndex
-get_trace(TlsIndex tls_index, JNIEnv *env)
-{
- TraceIndex trace_index;
-
- trace_index = tls_get_trace(tls_index, env, gdata->max_trace_depth, JNI_FALSE);
- return trace_index;
-}
-
-/* External functions (called from hprof_init.c) */
-
-void
-monitor_init(void)
-{
- gdata->monitor_table = table_initialize("Monitor",
- 32, 32, 31, (int)sizeof(MonitorInfo));
-}
-
-void
-monitor_list(void)
-{
- debug_message(
- "------------------- Monitor Table ------------------------\n");
- table_walk_items(gdata->monitor_table, &list_item, NULL);
- debug_message(
- "----------------------------------------------------------\n");
-}
-
-void
-monitor_cleanup(void)
-{
- table_cleanup(gdata->monitor_table, &cleanup_item, (void*)NULL);
- gdata->monitor_table = NULL;
-}
-
-void
-monitor_clear(void)
-{
- table_walk_items(gdata->monitor_table, &clear_item, NULL);
-}
-
-/* Contended monitor output */
-void
-monitor_write_contended_time(JNIEnv *env, double cutoff)
-{
- int n_entries;
-
- n_entries = table_element_count(gdata->monitor_table);
- if ( n_entries == 0 ) {
- return;
- }
-
- rawMonitorEnter(gdata->data_access_lock); {
- IterateInfo iterate;
- int i;
- int n_items;
- jlong total_contended_time;
-
- /* First write all trace we might refer to. */
- trace_output_unmarked(env);
-
- /* Looking for an array of monitor index values of interest */
- iterate.monitors = HPROF_MALLOC(n_entries*(int)sizeof(MonitorIndex));
- (void)memset(iterate.monitors, 0, n_entries*(int)sizeof(MonitorIndex));
-
- /* Get a combined total and an array of monitor index numbers */
- iterate.total_contended_time = 0;
- iterate.count = 0;
- table_walk_items(gdata->monitor_table, &collect_iterator, &iterate);
-
- /* Sort that list */
- n_entries = iterate.count;
- if ( n_entries > 0 ) {
- qsort(iterate.monitors, n_entries, sizeof(MonitorIndex),
- &qsort_compare);
- }
-
- /* Apply the cutoff */
- n_items = 0;
- for (i = 0; i < n_entries; i++) {
- MonitorIndex index;
- MonitorInfo *info;
- double percent;
-
- index = iterate.monitors[i];
- info = get_info(index);
- percent = (double)info->contended_time /
- (double)iterate.total_contended_time;
- if (percent < cutoff) {
- break;
- }
- iterate.monitors[n_items++] = index;
- }
-
- /* Output the items that make sense */
- total_contended_time = iterate.total_contended_time / 1000000;
-
- if ( n_items > 0 && total_contended_time > 0 ) {
- double accum;
-
- /* Output the info on this monitor enter site */
- io_write_monitor_header(total_contended_time);
-
- accum = 0.0;
- for (i = 0; i < n_items; i++) {
- MonitorIndex index;
- MonitorInfo *info;
- MonitorKey *pkey;
- double percent;
- char *sig;
-
- index = iterate.monitors[i];
- pkey = get_pkey(index);
- info = get_info(index);
-
- sig = string_get(pkey->sig_index);
-
- percent = (double)info->contended_time /
- (double)iterate.total_contended_time * 100.0;
- accum += percent;
- io_write_monitor_elem(i + 1, percent, accum,
- info->num_hits,
- trace_get_serial_number(pkey->trace_index),
- sig);
- }
- io_write_monitor_footer();
- }
- HPROF_FREE(iterate.monitors);
- } rawMonitorExit(gdata->data_access_lock);
-}
-
-void
-monitor_contended_enter_event(JNIEnv *env, jthread thread, jobject object)
-{
- TlsIndex tls_index;
- MonitorIndex index;
- TraceIndex trace_index;
-
- HPROF_ASSERT(env!=NULL);
- HPROF_ASSERT(thread!=NULL);
- HPROF_ASSERT(object!=NULL);
-
- tls_index = tls_find_or_create(env, thread);
- HPROF_ASSERT(tls_get_monitor(tls_index)==0);
- trace_index = get_trace(tls_index, env);
- index = find_or_create_entry(env, trace_index, object);
- tls_monitor_start_timer(tls_index);
- tls_set_monitor(tls_index, index);
-}
-
-void
-monitor_contended_entered_event(JNIEnv* env, jthread thread, jobject object)
-{
- TlsIndex tls_index;
- MonitorInfo *info;
- MonitorIndex index;
-
- HPROF_ASSERT(env!=NULL);
- HPROF_ASSERT(object!=NULL);
- HPROF_ASSERT(thread!=NULL);
-
- tls_index = tls_find_or_create(env, thread);
- HPROF_ASSERT(tls_index!=0);
- index = tls_get_monitor(tls_index);
- HPROF_ASSERT(index!=0);
- info = get_info(index);
- info->contended_time += tls_monitor_stop_timer(tls_index);
- info->num_hits++;
- tls_set_monitor(tls_index, 0);
-}
-
-void
-monitor_wait_event(JNIEnv *env, jthread thread, jobject object, jlong timeout)
-{
- TlsIndex tls_index;
- MonitorKey *pkey;
- MonitorIndex index;
- TraceIndex trace_index;
-
- HPROF_ASSERT(env!=NULL);
- HPROF_ASSERT(object!=NULL);
- HPROF_ASSERT(thread!=NULL);
-
- tls_index = tls_find_or_create(env, thread);
- HPROF_ASSERT(tls_index!=0);
- HPROF_ASSERT(tls_get_monitor(tls_index)==0);
- trace_index = get_trace(tls_index, env);
- index = find_or_create_entry(env, trace_index, object);
- pkey = get_pkey(index);
- tls_monitor_start_timer(tls_index);
- tls_set_monitor(tls_index, index);
-
- rawMonitorEnter(gdata->data_access_lock); {
- io_write_monitor_wait(string_get(pkey->sig_index), timeout,
- tls_get_thread_serial_number(tls_index));
- } rawMonitorExit(gdata->data_access_lock);
-}
-
-void
-monitor_waited_event(JNIEnv *env, jthread thread,
- jobject object, jboolean timed_out)
-{
- TlsIndex tls_index;
- MonitorIndex index;
- jlong time_waited;
-
- tls_index = tls_find_or_create(env, thread);
- HPROF_ASSERT(tls_index!=0);
- time_waited = tls_monitor_stop_timer(tls_index);
- index = tls_get_monitor(tls_index);
-
- if ( index ==0 ) {
- /* As best as I can tell, on Solaris X86 (not SPARC) I sometimes
- * get a "waited" event on a thread that I have never seen before
- * at all, so how did I get a WAITED event? Perhaps when I
- * did the VM_INIT handling, a thread I've never seen had already
- * done the WAIT (which I never saw?), and now I see this thread
- * for the first time, and also as it finishes it's WAIT?
- * Only happening on faster processors?
- */
- tls_set_monitor(tls_index, 0);
- return;
- }
- HPROF_ASSERT(index!=0);
- tls_set_monitor(tls_index, 0);
- if (object == NULL) {
- rawMonitorEnter(gdata->data_access_lock); {
- io_write_monitor_sleep(time_waited,
- tls_get_thread_serial_number(tls_index));
- } rawMonitorExit(gdata->data_access_lock);
- } else {
- MonitorKey *pkey;
-
- pkey = get_pkey(index);
- rawMonitorEnter(gdata->data_access_lock); {
- io_write_monitor_waited(string_get(pkey->sig_index), time_waited,
- tls_get_thread_serial_number(tls_index));
- } rawMonitorExit(gdata->data_access_lock);
- }
-}
--- a/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_monitor.h Thu Aug 20 12:29:58 2015 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,60 +0,0 @@
-/*
- * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * - Neither the name of Oracle nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
- * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/*
- * This source code is provided to illustrate the usage of a given feature
- * or technique and has been deliberately simplified. Additional steps
- * required for a production-quality application, such as security checks,
- * input validation and proper error handling, might not be present in
- * this sample code.
- */
-
-
-#ifndef HPROF_MONITOR_H
-#define HPROF_MONITOR_H
-
-void monitor_init(void);
-void monitor_list(void);
-void monitor_cleanup(void);
-
-void monitor_clear(void);
-void monitor_write_contended_time(JNIEnv *env, double cutoff);
-
-void monitor_contended_enter_event(JNIEnv *env_id, jthread thread,
- jobject object);
-void monitor_contended_entered_event(JNIEnv* env_id, jthread thread,
- jobject object);
-void monitor_wait_event(JNIEnv *env_id, jthread thread,
- jobject object, jlong timeout);
-void monitor_waited_event(JNIEnv *env_id, jthread thread,
- jobject object, jboolean timed_out);
-
-#endif
--- a/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_object.c Thu Aug 20 12:29:58 2015 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,324 +0,0 @@
-/*
- * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * - Neither the name of Oracle nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
- * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/*
- * This source code is provided to illustrate the usage of a given feature
- * or technique and has been deliberately simplified. Additional steps
- * required for a production-quality application, such as security checks,
- * input validation and proper error handling, might not be present in
- * this sample code.
- */
-
-
-/* Object table. */
-
-/*
- * An Object is unique by it's allocation site (SiteIndex), it's size,
- * it's kind, and it's serial number. Normally only the serial number
- * would have been necessary for heap=dump, and these other items
- * could have been moved to the ObjectInfo. An optimization left
- * to the reader. Lookups are not normally done on ObjectIndex's
- * anyway because we typically know when to create them.
- * Objects that have been tagged, are tagged with an ObjectIndex,
- * Objects that are not tagged need a ObjectIndex, a lookup when
- * heap=sites, and a new one when heap=dump.
- * Objects that are freed, need the tag converted to an ObjectIndex,
- * so they can be freed, but only when heap=dump.
- * The thread serial number is for the thread associated with this
- * object. If the object is a Thread object, it should be the serial
- * number for that thread. The ThreadStart event is responsible
- * for making sure the thread serial number is correct, but between the
- * initial allocation of a Thread object and it's ThreadStart event
- * the thread serial number could be for the thread that allocated
- * the Thread object.
- *
- * This will likely be the largest table when using heap=dump, when
- * there is one table entry per object.
- *
- * ObjectIndex entries differ between heap=dump and heap=sites.
- * With heap=sites, each ObjectIndex represents a unique site, size,
- * and kind of object, so many jobject's will map to a single ObjectIndex.
- * With heap=dump, every ObjectIndex maps to a unique jobject.
- *
- * During processing of a heap dump, the references for the object
- * this ObjectIndex represents is assigned to the references field
- * of the ObjectInfo as a linked list. (see hprof_references.c).
- * Once all the refernces are attached, they are processed into the
- * appropriate hprof dump information.
- *
- * The references field is set and cleared as many times as the heap
- * is dumped, as is the reference table.
- *
- */
-
-#include "hprof.h"
-
-typedef struct ObjectKey {
- SiteIndex site_index; /* Site of allocation */
- jint size; /* Size of object as reported by VM */
- ObjectKind kind; /* Kind of object, most are OBJECT_NORMAL */
- SerialNumber serial_num; /* For heap=dump, a unique number. */
-} ObjectKey;
-
-typedef struct ObjectInfo {
- RefIndex references; /* Linked list of refs in this object */
- SerialNumber thread_serial_num; /* Thread serial number for allocation */
-} ObjectInfo;
-
-/* Private internal functions. */
-
-static ObjectKey*
-get_pkey(ObjectIndex index)
-{
- void *key_ptr;
- int key_len;
-
- table_get_key(gdata->object_table, index, (void*)&key_ptr, &key_len);
- HPROF_ASSERT(key_len==(int)sizeof(ObjectKey));
- HPROF_ASSERT(key_ptr!=NULL);
- return (ObjectKey*)key_ptr;
-}
-
-static ObjectInfo *
-get_info(ObjectIndex index)
-{
- ObjectInfo *info;
-
- info = (ObjectInfo*)table_get_info(gdata->object_table, index);
- return info;
-}
-
-static void
-list_item(TableIndex i, void *key_ptr, int key_len, void *info_ptr, void *arg)
-{
- ObjectKey *pkey;
- ObjectInfo *info;
-
- HPROF_ASSERT(key_ptr!=NULL);
- HPROF_ASSERT(key_len!=0);
- HPROF_ASSERT(info_ptr!=NULL);
-
- info = (ObjectInfo*)info_ptr;
-
- pkey = (ObjectKey*)key_ptr;
- debug_message( "Object 0x%08x: site=0x%08x, SN=%u, "
- " size=%d, kind=%d, refs=0x%x, threadSN=%u\n",
- i, pkey->site_index, pkey->serial_num, pkey->size, pkey->kind,
- info->references, info->thread_serial_num);
-}
-
-static void
-clear_references(TableIndex i, void *key_ptr, int key_len, void *info_ptr, void *arg)
-{
- ObjectInfo *info;
-
- HPROF_ASSERT(info_ptr!=NULL);
- info = (ObjectInfo *)info_ptr;
- info->references = 0;
-}
-
-static void
-dump_class_references(TableIndex i, void *key_ptr, int key_len, void *info_ptr, void *arg)
-{
- ObjectInfo *info;
-
- HPROF_ASSERT(info_ptr!=NULL);
- info = (ObjectInfo *)info_ptr;
- reference_dump_class((JNIEnv*)arg, i, info->references);
-}
-
-static void
-dump_instance_references(TableIndex i, void *key_ptr, int key_len, void *info_ptr, void *arg)
-{
- ObjectInfo *info;
-
- HPROF_ASSERT(info_ptr!=NULL);
- info = (ObjectInfo *)info_ptr;
- reference_dump_instance((JNIEnv*)arg, i, info->references);
-}
-
-/* External interfaces. */
-
-ObjectIndex
-object_new(SiteIndex site_index, jint size, ObjectKind kind, SerialNumber thread_serial_num)
-{
- ObjectIndex index;
- ObjectKey key;
- static ObjectKey empty_key;
-
- key = empty_key;
- key.site_index = site_index;
- key.size = size;
- key.kind = kind;
- if ( gdata->heap_dump ) {
- static ObjectInfo empty_info;
- ObjectInfo i;
-
- i = empty_info;
- i.thread_serial_num = thread_serial_num;
- key.serial_num = gdata->object_serial_number_counter++;
- index = table_create_entry(gdata->object_table,
- &key, (int)sizeof(ObjectKey), &i);
- } else {
- key.serial_num =
- class_get_serial_number(site_get_class_index(site_index));
- index = table_find_or_create_entry(gdata->object_table,
- &key, (int)sizeof(ObjectKey), NULL, NULL);
- }
- site_update_stats(site_index, size, 1);
- return index;
-}
-
-void
-object_init(void)
-{
- jint bucket_count;
-
- bucket_count = 511;
- if ( gdata->heap_dump ) {
- bucket_count = 0;
- }
- HPROF_ASSERT(gdata->object_table==NULL);
- gdata->object_table = table_initialize("Object", 4096,
- 4096, bucket_count, (int)sizeof(ObjectInfo));
-}
-
-SiteIndex
-object_get_site(ObjectIndex index)
-{
- ObjectKey *pkey;
-
- pkey = get_pkey(index);
- return pkey->site_index;
-}
-
-jint
-object_get_size(ObjectIndex index)
-{
- ObjectKey *pkey;
-
- pkey = get_pkey(index);
- return pkey->size;
-}
-
-ObjectKind
-object_get_kind(ObjectIndex index)
-{
- ObjectKey *pkey;
-
- pkey = get_pkey(index);
- return pkey->kind;
-}
-
-ObjectKind
-object_free(ObjectIndex index)
-{
- ObjectKey *pkey;
- ObjectKind kind;
-
- pkey = get_pkey(index);
- kind = pkey->kind;
-
- /* Decrement allocations at this site. */
- site_update_stats(pkey->site_index, -(pkey->size), -1);
-
- if ( gdata->heap_dump ) {
- table_free_entry(gdata->object_table, index);
- }
- return kind;
-}
-
-void
-object_list(void)
-{
- debug_message(
- "--------------------- Object Table ------------------------\n");
- table_walk_items(gdata->object_table, &list_item, NULL);
- debug_message(
- "----------------------------------------------------------\n");
-}
-
-void
-object_cleanup(void)
-{
- table_cleanup(gdata->object_table, NULL, NULL);
- gdata->object_table = NULL;
-}
-
-void
-object_set_thread_serial_number(ObjectIndex index,
- SerialNumber thread_serial_num)
-{
- ObjectInfo *info;
-
- info = get_info(index);
- info->thread_serial_num = thread_serial_num;
-}
-
-SerialNumber
-object_get_thread_serial_number(ObjectIndex index)
-{
- ObjectInfo *info;
-
- info = get_info(index);
- return info->thread_serial_num;
-}
-
-RefIndex
-object_get_references(ObjectIndex index)
-{
- ObjectInfo *info;
-
- info = get_info(index);
- return info->references;
-}
-
-void
-object_set_references(ObjectIndex index, RefIndex ref_index)
-{
- ObjectInfo *info;
-
- info = get_info(index);
- info->references = ref_index;
-}
-
-void
-object_clear_references(void)
-{
- table_walk_items(gdata->object_table, &clear_references, NULL);
-}
-
-void
-object_reference_dump(JNIEnv *env)
-{
- table_walk_items(gdata->object_table, &dump_instance_references, (void*)env);
- table_walk_items(gdata->object_table, &dump_class_references, (void*)env);
-}
--- a/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_object.h Thu Aug 20 12:29:58 2015 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,62 +0,0 @@
-/*
- * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * - Neither the name of Oracle nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
- * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/*
- * This source code is provided to illustrate the usage of a given feature
- * or technique and has been deliberately simplified. Additional steps
- * required for a production-quality application, such as security checks,
- * input validation and proper error handling, might not be present in
- * this sample code.
- */
-
-
-#ifndef HPROF_OBJECT_H
-#define HPROF_OBJECT_H
-
-void object_init(void);
-ObjectIndex object_new(SiteIndex site_index, jint size, ObjectKind kind,
- SerialNumber thread_serial_num);
-SiteIndex object_get_site(ObjectIndex index);
-jint object_get_size(ObjectIndex index);
-ObjectKind object_get_kind(ObjectIndex index);
-ObjectKind object_free(ObjectIndex index);
-void object_list(void);
-void object_cleanup(void);
-
-void object_set_thread_serial_number(ObjectIndex index,
- SerialNumber thread_serial_num);
-SerialNumber object_get_thread_serial_number(ObjectIndex index);
-RefIndex object_get_references(ObjectIndex index);
-void object_set_references(ObjectIndex index, RefIndex ref_index);
-void object_clear_references(void);
-void object_reference_dump(JNIEnv *env);
-
-#endif
--- a/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_reference.c Thu Aug 20 12:29:58 2015 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,814 +0,0 @@
-/*
- * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * - Neither the name of Oracle nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
- * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/*
- * This source code is provided to illustrate the usage of a given feature
- * or technique and has been deliberately simplified. Additional steps
- * required for a production-quality application, such as security checks,
- * input validation and proper error handling, might not be present in
- * this sample code.
- */
-
-
-/* Object references table (used in hprof_object.c). */
-
-/*
- * This table is used by the object table to store object reference
- * and primitive data information obtained from iterations over the
- * heap (see hprof_site.c).
- *
- * Most of these table entries have no Key, but the key is used to store
- * the primitive array and primitive field jvalue. None of these entries
- * are ever looked up, there will be no hash table, use of the
- * LookupTable was just an easy way to handle a unbounded table of
- * entries. The object table (see hprof_object.c) will completely
- * free this reference table after each heap dump or after processing the
- * references and primitive data.
- *
- * The hprof format required this accumulation of all heap iteration
- * references and primitive data from objects in order to compose an
- * hprof records for it.
- *
- * This file contains detailed understandings of how an hprof CLASS
- * and INSTANCE dump is constructed, most of this is derived from the
- * original hprof code, but some has been derived by reading the HAT
- * code that accepts this format.
- *
- */
-
-#include "hprof.h"
-
-/* The flavor of data being saved in the RefInfo */
-enum {
- INFO_OBJECT_REF_DATA = 1,
- INFO_PRIM_FIELD_DATA = 2,
- INFO_PRIM_ARRAY_DATA = 3
-};
-
-/* Reference information, object reference or primitive data information */
-typedef struct RefInfo {
- ObjectIndex object_index; /* If an object reference, the referree index */
- jint index; /* If array or field, array or field index */
- jint length; /* If array the element count, if not -1 */
- RefIndex next; /* The next table element */
- unsigned flavor : 8; /* INFO_*, flavor of RefInfo */
- unsigned refKind : 8; /* The kind of reference */
- unsigned primType : 8; /* If primitive data involved, it's type */
-} RefInfo;
-
-/* Private internal functions. */
-
-/* Get the RefInfo structure from an entry */
-static RefInfo *
-get_info(RefIndex index)
-{
- RefInfo *info;
-
- info = (RefInfo*)table_get_info(gdata->reference_table, index);
- return info;
-}
-
-/* Get a jvalue that was stored as the key. */
-static jvalue
-get_key_value(RefIndex index)
-{
- void *key;
- int len;
- jvalue value;
- static jvalue empty_value;
-
- key = NULL;
- table_get_key(gdata->reference_table, index, &key, &len);
- HPROF_ASSERT(key!=NULL);
- HPROF_ASSERT(len==(int)sizeof(jvalue));
- if ( key != NULL ) {
- (void)memcpy(&value, key, (int)sizeof(jvalue));
- } else {
- value = empty_value;
- }
- return value;
-}
-
-/* Get size of a primitive type */
-static jint
-get_prim_size(jvmtiPrimitiveType primType)
-{
- jint size;
-
- switch ( primType ) {
- case JVMTI_PRIMITIVE_TYPE_BOOLEAN:
- size = (jint)sizeof(jboolean);
- break;
- case JVMTI_PRIMITIVE_TYPE_BYTE:
- size = (jint)sizeof(jbyte);
- break;
- case JVMTI_PRIMITIVE_TYPE_CHAR:
- size = (jint)sizeof(jchar);
- break;
- case JVMTI_PRIMITIVE_TYPE_SHORT:
- size = (jint)sizeof(jshort);
- break;
- case JVMTI_PRIMITIVE_TYPE_INT:
- size = (jint)sizeof(jint);
- break;
- case JVMTI_PRIMITIVE_TYPE_FLOAT:
- size = (jint)sizeof(jfloat);
- break;
- case JVMTI_PRIMITIVE_TYPE_LONG:
- size = (jint)sizeof(jlong);
- break;
- case JVMTI_PRIMITIVE_TYPE_DOUBLE:
- size = (jint)sizeof(jdouble);
- break;
- default:
- HPROF_ASSERT(0);
- size = 1;
- break;
- }
- return size;
-}
-
-/* Get a void* elements array that was stored as the key. */
-static void *
-get_key_elements(RefIndex index, jvmtiPrimitiveType primType,
- jint *nelements, jint *nbytes)
-{
- void *key;
- jint byteLen;
-
- HPROF_ASSERT(nelements!=NULL);
- HPROF_ASSERT(nbytes!=NULL);
-
- table_get_key(gdata->reference_table, index, &key, &byteLen);
- HPROF_ASSERT(byteLen>=0);
- HPROF_ASSERT(byteLen!=0?key!=NULL:key==NULL);
- *nbytes = byteLen;
- *nelements = byteLen / get_prim_size(primType);
- return key;
-}
-
-/* Dump a RefInfo* structure */
-static void
-dump_ref_info(RefInfo *info)
-{
- debug_message("[%d]: flavor=%d"
- ", refKind=%d"
- ", primType=%d"
- ", object_index=0x%x"
- ", length=%d"
- ", next=0x%x"
- "\n",
- info->index,
- info->flavor,
- info->refKind,
- info->primType,
- info->object_index,
- info->length,
- info->next);
-}
-
-/* Dump a RefIndex list */
-static void
-dump_ref_list(RefIndex list)
-{
- RefInfo *info;
- RefIndex index;
-
- debug_message("\nFOLLOW REFERENCES RETURNED:\n");
- index = list;
- while ( index != 0 ) {
- info = get_info(index);
- dump_ref_info(info);
- index = info->next;
- }
-}
-
-/* Dump information about a field and what ref data we had on it */
-static void
-dump_field(FieldInfo *fields, jvalue *fvalues, int n_fields,
- jint index, jvalue value, jvmtiPrimitiveType primType)
-{
- ClassIndex cnum;
- StringIndex name;
- StringIndex sig;
-
- cnum = fields[index].cnum;
- name = fields[index].name_index;
- sig = fields[index].sig_index;
- debug_message("[%d] %s \"%s\" \"%s\"",
- index,
- cnum!=0?string_get(class_get_signature(cnum)):"?",
- name!=0?string_get(name):"?",
- sig!=0?string_get(sig):"?");
- if ( fields[index].primType!=0 || fields[index].primType!=primType ) {
- debug_message(" (primType=%d(%c)",
- fields[index].primType,
- primTypeToSigChar(fields[index].primType));
- if ( primType != fields[index].primType ) {
- debug_message(", got %d(%c)",
- primType,
- primTypeToSigChar(primType));
- }
- debug_message(")");
- } else {
- debug_message("(ty=OBJ)");
- }
- if ( value.j != (jlong)0 || fvalues[index].j != (jlong)0 ) {
- debug_message(" val=[0x%08x,0x%08x] or [0x%08x,0x%08x]",
- jlong_high(value.j), jlong_low(value.j),
- jlong_high(fvalues[index].j), jlong_low(fvalues[index].j));
- }
- debug_message("\n");
-}
-
-/* Dump all the fields of interest */
-static void
-dump_fields(RefIndex list, FieldInfo *fields, jvalue *fvalues, int n_fields)
-{
- int i;
-
- debug_message("\nHPROF LIST OF ALL FIELDS:\n");
- for ( i = 0 ; i < n_fields ; i++ ) {
- if ( fields[i].name_index != 0 ) {
- dump_field(fields, fvalues, n_fields, i, fvalues[i], fields[i].primType);
- }
- }
- dump_ref_list(list);
-}
-
-/* Verify field data */
-static void
-verify_field(RefIndex list, FieldInfo *fields, jvalue *fvalues, int n_fields,
- jint index, jvalue value, jvmtiPrimitiveType primType)
-{
- HPROF_ASSERT(fvalues != NULL);
- HPROF_ASSERT(n_fields > 0);
- HPROF_ASSERT(index < n_fields);
- HPROF_ASSERT(index >= 0 );
- if ( primType!=fields[index].primType ) {
- dump_fields(list, fields, fvalues, n_fields);
- debug_message("\nPROBLEM WITH:\n");
- dump_field(fields, fvalues, n_fields, index, value, primType);
- debug_message("\n");
- HPROF_ERROR(JNI_FALSE, "Trouble with fields and heap data");
- }
- if ( primType == JVMTI_PRIMITIVE_TYPE_BOOLEAN &&
- ( value.b != 1 && value.b != 0 ) ) {
- dump_fields(list, fields, fvalues, n_fields);
- debug_message("\nPROBLEM WITH:\n");
- dump_field(fields, fvalues, n_fields, index, value, primType);
- debug_message("\n");
- HPROF_ERROR(JNI_FALSE, "Trouble with fields and heap data");
- }
-}
-
-/* Fill in a field value, making sure the index is safe */
-static void
-fill_in_field_value(RefIndex list, FieldInfo *fields, jvalue *fvalues,
- int n_fields, jint index, jvalue value,
- jvmtiPrimitiveType primType)
-{
- HPROF_ASSERT(fvalues != NULL);
- HPROF_ASSERT(n_fields > 0);
- HPROF_ASSERT(index < n_fields);
- HPROF_ASSERT(index >= 0 );
- HPROF_ASSERT(fvalues[index].j==(jlong)0);
- verify_field(list, fields, fvalues, n_fields, index, value, primType);
- if (index >= 0 && index < n_fields) {
- fvalues[index] = value;
- }
-}
-
-/* Walk all references for an ObjectIndex and construct the hprof CLASS dump. */
-static void
-dump_class_and_supers(JNIEnv *env, ObjectIndex object_index, RefIndex list)
-{
- SiteIndex site_index;
- SerialNumber trace_serial_num;
- RefIndex index;
- ClassIndex super_cnum;
- ObjectIndex super_index;
- LoaderIndex loader_index;
- ObjectIndex signers_index;
- ObjectIndex domain_index;
- FieldInfo *fields;
- jvalue *fvalues;
- jint n_fields;
- jboolean skip_fields;
- jint n_fields_set;
- jlong size;
- ClassIndex cnum;
- char *sig;
- ObjectKind kind;
- TraceIndex trace_index;
- Stack *cpool_values;
- ConstantPoolValue *cpool;
- jint cpool_count;
-
- HPROF_ASSERT(object_index!=0);
- kind = object_get_kind(object_index);
- if ( kind != OBJECT_CLASS ) {
- return;
- }
- site_index = object_get_site(object_index);
- HPROF_ASSERT(site_index!=0);
- cnum = site_get_class_index(site_index);
- HPROF_ASSERT(cnum!=0);
- if ( class_get_status(cnum) & CLASS_DUMPED ) {
- return;
- }
- class_add_status(cnum, CLASS_DUMPED);
- size = (jlong)object_get_size(object_index);
-
- super_index = 0;
- super_cnum = class_get_super(cnum);
- if ( super_cnum != 0 ) {
- super_index = class_get_object_index(super_cnum);
- if ( super_index != 0 ) {
- dump_class_and_supers(env, super_index,
- object_get_references(super_index));
- }
- }
-
- trace_index = site_get_trace_index(site_index);
- HPROF_ASSERT(trace_index!=0);
- trace_serial_num = trace_get_serial_number(trace_index);
- sig = string_get(class_get_signature(cnum));
- loader_index = class_get_loader(cnum);
- signers_index = 0;
- domain_index = 0;
-
- /* Get field information */
- n_fields = 0;
- skip_fields = JNI_FALSE;
- n_fields_set = 0;
- fields = NULL;
- fvalues = NULL;
- if ( class_get_all_fields(env, cnum, &n_fields, &fields) == 1 ) {
- /* Problems getting all the fields, can't trust field index values */
- skip_fields = JNI_TRUE;
- /* Class with no references at all? (ok to be unprepared if list==0?) */
- if ( list != 0 ) {
- /* It is assumed that the reason why we didn't get the fields
- * was because the class is not prepared.
- */
- if ( gdata->debugflags & DEBUGFLAG_UNPREPARED_CLASSES ) {
- dump_ref_list(list);
- debug_message("Unprepared class with references: %s\n",
- sig);
- }
- HPROF_ERROR(JNI_FALSE, "Trouble with unprepared classes");
- }
- /* Why would an unprepared class contain references? */
- }
- if ( n_fields > 0 ) {
- fvalues = (jvalue*)HPROF_MALLOC(n_fields*(int)sizeof(jvalue));
- (void)memset(fvalues, 0, n_fields*(int)sizeof(jvalue));
- }
-
- /* We use a Stack just because it will automatically expand as needed */
- cpool_values = stack_init(16, 16, sizeof(ConstantPoolValue));
- cpool = NULL;
- cpool_count = 0;
-
- index = list;
- while ( index != 0 ) {
- RefInfo *info;
- jvalue ovalue;
- static jvalue empty_value;
-
- info = get_info(index);
-
- switch ( info->flavor ) {
- case INFO_OBJECT_REF_DATA:
- switch ( info->refKind ) {
- case JVMTI_HEAP_REFERENCE_FIELD:
- case JVMTI_HEAP_REFERENCE_ARRAY_ELEMENT:
- /* Should never be seen on a class dump */
- HPROF_ASSERT(0);
- break;
- case JVMTI_HEAP_REFERENCE_STATIC_FIELD:
- if ( skip_fields == JNI_TRUE ) {
- break;
- }
- ovalue = empty_value;
- ovalue.i = info->object_index;
- fill_in_field_value(list, fields, fvalues, n_fields,
- info->index, ovalue, 0);
- n_fields_set++;
- HPROF_ASSERT(n_fields_set <= n_fields);
- break;
- case JVMTI_HEAP_REFERENCE_CONSTANT_POOL: {
- ConstantPoolValue cpv;
- ObjectIndex cp_object_index;
- SiteIndex cp_site_index;
- ClassIndex cp_cnum;
-
- cp_object_index = info->object_index;
- HPROF_ASSERT(cp_object_index!=0);
- cp_site_index = object_get_site(cp_object_index);
- HPROF_ASSERT(cp_site_index!=0);
- cp_cnum = site_get_class_index(cp_site_index);
- cpv.constant_pool_index = info->index;
- cpv.sig_index = class_get_signature(cp_cnum);
- cpv.value.i = cp_object_index;
- stack_push(cpool_values, (void*)&cpv);
- cpool_count++;
- break;
- }
- case JVMTI_HEAP_REFERENCE_SIGNERS:
- signers_index = info->object_index;
- break;
- case JVMTI_HEAP_REFERENCE_PROTECTION_DOMAIN:
- domain_index = info->object_index;
- break;
- case JVMTI_HEAP_REFERENCE_CLASS_LOADER:
- case JVMTI_HEAP_REFERENCE_INTERFACE:
- default:
- /* Ignore, not needed */
- break;
- }
- break;
- case INFO_PRIM_FIELD_DATA:
- if ( skip_fields == JNI_TRUE ) {
- break;
- }
- HPROF_ASSERT(info->primType!=0);
- HPROF_ASSERT(info->length==-1);
- HPROF_ASSERT(info->refKind==JVMTI_HEAP_REFERENCE_STATIC_FIELD);
- ovalue = get_key_value(index);
- fill_in_field_value(list, fields, fvalues, n_fields,
- info->index, ovalue, info->primType);
- n_fields_set++;
- HPROF_ASSERT(n_fields_set <= n_fields);
- break;
- case INFO_PRIM_ARRAY_DATA:
- default:
- /* Should never see these */
- HPROF_ASSERT(0);
- break;
- }
-
- index = info->next;
- }
-
- /* Get constant pool data if we have any */
- HPROF_ASSERT(cpool_count==stack_depth(cpool_values));
- if ( cpool_count > 0 ) {
- cpool = (ConstantPoolValue*)stack_element(cpool_values, 0);
- }
- io_heap_class_dump(cnum, sig, object_index, trace_serial_num,
- super_index,
- loader_object_index(env, loader_index),
- signers_index, domain_index,
- (jint)size, cpool_count, cpool, n_fields, fields, fvalues);
-
- stack_term(cpool_values);
- if ( fvalues != NULL ) {
- HPROF_FREE(fvalues);
- }
-}
-
-/* Walk all references for an ObjectIndex and construct the hprof INST dump. */
-static void
-dump_instance(JNIEnv *env, ObjectIndex object_index, RefIndex list)
-{
- jvmtiPrimitiveType primType;
- SiteIndex site_index;
- SerialNumber trace_serial_num;
- RefIndex index;
- ObjectIndex class_index;
- jlong size;
- ClassIndex cnum;
- char *sig;
- void *elements;
- jint num_elements;
- jint num_bytes;
- ObjectIndex *values;
- FieldInfo *fields;
- jvalue *fvalues;
- jint n_fields;
- jboolean skip_fields;
- jint n_fields_set;
- ObjectKind kind;
- TraceIndex trace_index;
- jboolean is_array;
- jboolean is_prim_array;
-
- HPROF_ASSERT(object_index!=0);
- kind = object_get_kind(object_index);
- if ( kind == OBJECT_CLASS ) {
- return;
- }
- site_index = object_get_site(object_index);
- HPROF_ASSERT(site_index!=0);
- cnum = site_get_class_index(site_index);
- HPROF_ASSERT(cnum!=0);
- size = (jlong)object_get_size(object_index);
- trace_index = site_get_trace_index(site_index);
- HPROF_ASSERT(trace_index!=0);
- trace_serial_num = trace_get_serial_number(trace_index);
- sig = string_get(class_get_signature(cnum));
- class_index = class_get_object_index(cnum);
-
- values = NULL;
- elements = NULL;
- num_elements = 0;
- num_bytes = 0;
-
- n_fields = 0;
- skip_fields = JNI_FALSE;
- n_fields_set = 0;
- fields = NULL;
- fvalues = NULL;
-
- index = list;
-
- is_array = JNI_FALSE;
- is_prim_array = JNI_FALSE;
-
- if ( sig[0] != JVM_SIGNATURE_ARRAY ) {
- if ( class_get_all_fields(env, cnum, &n_fields, &fields) == 1 ) {
- /* Trouble getting all the fields, can't trust field index values */
- skip_fields = JNI_TRUE;
- /* It is assumed that the reason why we didn't get the fields
- * was because the class is not prepared.
- */
- if ( gdata->debugflags & DEBUGFLAG_UNPREPARED_CLASSES ) {
- if ( list != 0 ) {
- dump_ref_list(list);
- debug_message("Instance of unprepared class with refs: %s\n",
- sig);
- } else {
- debug_message("Instance of unprepared class without refs: %s\n",
- sig);
- }
- HPROF_ERROR(JNI_FALSE, "Big Trouble with unprepared class instances");
- }
- }
- if ( n_fields > 0 ) {
- fvalues = (jvalue*)HPROF_MALLOC(n_fields*(int)sizeof(jvalue));
- (void)memset(fvalues, 0, n_fields*(int)sizeof(jvalue));
- }
- } else {
- is_array = JNI_TRUE;
- if ( sig[0] != 0 && sigToPrimSize(sig+1) != 0 ) {
- is_prim_array = JNI_TRUE;
- }
- }
-
- while ( index != 0 ) {
- RefInfo *info;
- jvalue ovalue;
- static jvalue empty_value;
-
- info = get_info(index);
-
- /* Process reference objects, many not used right now. */
- switch ( info->flavor ) {
- case INFO_OBJECT_REF_DATA:
- switch ( info->refKind ) {
- case JVMTI_HEAP_REFERENCE_SIGNERS:
- case JVMTI_HEAP_REFERENCE_PROTECTION_DOMAIN:
- case JVMTI_HEAP_REFERENCE_CLASS_LOADER:
- case JVMTI_HEAP_REFERENCE_INTERFACE:
- case JVMTI_HEAP_REFERENCE_STATIC_FIELD:
- case JVMTI_HEAP_REFERENCE_CONSTANT_POOL:
- /* Should never be seen on an instance dump */
- HPROF_ASSERT(0);
- break;
- case JVMTI_HEAP_REFERENCE_FIELD:
- if ( skip_fields == JNI_TRUE ) {
- break;
- }
- HPROF_ASSERT(is_array!=JNI_TRUE);
- ovalue = empty_value;
- ovalue.i = info->object_index;
- fill_in_field_value(list, fields, fvalues, n_fields,
- info->index, ovalue, 0);
- n_fields_set++;
- HPROF_ASSERT(n_fields_set <= n_fields);
- break;
- case JVMTI_HEAP_REFERENCE_ARRAY_ELEMENT:
- /* We get each object element one at a time. */
- HPROF_ASSERT(is_array==JNI_TRUE);
- HPROF_ASSERT(is_prim_array!=JNI_TRUE);
- if ( num_elements <= info->index ) {
- int nbytes;
-
- if ( values == NULL ) {
- num_elements = info->index + 1;
- nbytes = num_elements*(int)sizeof(ObjectIndex);
- values = (ObjectIndex*)HPROF_MALLOC(nbytes);
- (void)memset(values, 0, nbytes);
- } else {
- void *new_values;
- int new_size;
- int obytes;
-
- obytes = num_elements*(int)sizeof(ObjectIndex);
- new_size = info->index + 1;
- nbytes = new_size*(int)sizeof(ObjectIndex);
- new_values = (void*)HPROF_MALLOC(nbytes);
- (void)memcpy(new_values, values, obytes);
- (void)memset(((char*)new_values)+obytes, 0,
- nbytes-obytes);
- HPROF_FREE(values);
- num_elements = new_size;
- values = new_values;
- }
- }
- HPROF_ASSERT(values[info->index]==0);
- values[info->index] = info->object_index;
- break;
- default:
- /* Ignore, not needed */
- break;
- }
- break;
- case INFO_PRIM_FIELD_DATA:
- if ( skip_fields == JNI_TRUE ) {
- break;
- }
- HPROF_ASSERT(info->primType!=0);
- HPROF_ASSERT(info->length==-1);
- HPROF_ASSERT(info->refKind==JVMTI_HEAP_REFERENCE_FIELD);
- HPROF_ASSERT(is_array!=JNI_TRUE);
- ovalue = get_key_value(index);
- fill_in_field_value(list, fields, fvalues, n_fields,
- info->index, ovalue, info->primType);
- n_fields_set++;
- HPROF_ASSERT(n_fields_set <= n_fields);
- break;
- case INFO_PRIM_ARRAY_DATA:
- /* Should only be one, and it's handled below */
- HPROF_ASSERT(info->refKind==0);
- /* We assert that nothing else was saved with this array */
- HPROF_ASSERT(index==list&&info->next==0);
- HPROF_ASSERT(is_array==JNI_TRUE);
- HPROF_ASSERT(is_prim_array==JNI_TRUE);
- primType = info->primType;
- elements = get_key_elements(index, primType,
- &num_elements, &num_bytes);
- HPROF_ASSERT(info->length==num_elements);
- size = num_bytes;
- break;
- default:
- HPROF_ASSERT(0);
- break;
- }
- index = info->next;
- }
-
- if ( is_array == JNI_TRUE ) {
- if ( is_prim_array == JNI_TRUE ) {
- HPROF_ASSERT(values==NULL);
- io_heap_prim_array(object_index, trace_serial_num,
- (jint)size, num_elements, sig, elements);
- } else {
- HPROF_ASSERT(elements==NULL);
- io_heap_object_array(object_index, trace_serial_num,
- (jint)size, num_elements, sig, values, class_index);
- }
- } else {
- io_heap_instance_dump(cnum, object_index, trace_serial_num,
- class_index, (jint)size, sig, fields, fvalues, n_fields);
- }
- if ( values != NULL ) {
- HPROF_FREE(values);
- }
- if ( fvalues != NULL ) {
- HPROF_FREE(fvalues);
- }
- if ( elements != NULL ) {
- /* Do NOT free elements, it's a key in the table, leave it be */
- }
-}
-
-/* External interfaces. */
-
-void
-reference_init(void)
-{
- HPROF_ASSERT(gdata->reference_table==NULL);
- gdata->reference_table = table_initialize("Ref", 2048, 4096, 0,
- (int)sizeof(RefInfo));
-}
-
-/* Save away a reference to an object */
-RefIndex
-reference_obj(RefIndex next, jvmtiHeapReferenceKind refKind,
- ObjectIndex object_index, jint index, jint length)
-{
- static RefInfo empty_info;
- RefIndex entry;
- RefInfo info;
-
- info = empty_info;
- info.flavor = INFO_OBJECT_REF_DATA;
- info.refKind = refKind;
- info.object_index = object_index;
- info.index = index;
- info.length = length;
- info.next = next;
- entry = table_create_entry(gdata->reference_table, NULL, 0, (void*)&info);
- return entry;
-}
-
-/* Save away some primitive field data */
-RefIndex
-reference_prim_field(RefIndex next, jvmtiHeapReferenceKind refKind,
- jvmtiPrimitiveType primType, jvalue field_value, jint field_index)
-{
- static RefInfo empty_info;
- RefIndex entry;
- RefInfo info;
-
- HPROF_ASSERT(primType==JVMTI_PRIMITIVE_TYPE_BOOLEAN?(field_value.b==1||field_value.b==0):1);
-
- info = empty_info;
- info.flavor = INFO_PRIM_FIELD_DATA;
- info.refKind = refKind;
- info.primType = primType;
- info.index = field_index;
- info.length = -1;
- info.next = next;
- entry = table_create_entry(gdata->reference_table,
- (void*)&field_value, (int)sizeof(jvalue), (void*)&info);
- return entry;
-}
-
-/* Save away some primitive array data */
-RefIndex
-reference_prim_array(RefIndex next, jvmtiPrimitiveType primType,
- const void *elements, jint elementCount)
-{
- static RefInfo empty_info;
- RefIndex entry;
- RefInfo info;
-
- HPROF_ASSERT(next == 0);
- HPROF_ASSERT(elementCount >= 0);
- HPROF_ASSERT(elements != NULL);
-
- info = empty_info;
- info.flavor = INFO_PRIM_ARRAY_DATA;
- info.refKind = 0;
- info.primType = primType;
- info.index = 0;
- info.length = elementCount;
- info.next = next;
- entry = table_create_entry(gdata->reference_table, (void*)elements,
- elementCount * get_prim_size(primType), (void*)&info);
- return entry;
-}
-
-void
-reference_cleanup(void)
-{
- if ( gdata->reference_table == NULL ) {
- return;
- }
- table_cleanup(gdata->reference_table, NULL, NULL);
- gdata->reference_table = NULL;
-}
-
-void
-reference_dump_instance(JNIEnv *env, ObjectIndex object_index, RefIndex list)
-{
- dump_instance(env, object_index, list);
-}
-
-void
-reference_dump_class(JNIEnv *env, ObjectIndex object_index, RefIndex list)
-{
- dump_class_and_supers(env, object_index, list);
-}
--- a/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_reference.h Thu Aug 20 12:29:58 2015 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,57 +0,0 @@
-/*
- * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * - Neither the name of Oracle nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
- * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/*
- * This source code is provided to illustrate the usage of a given feature
- * or technique and has been deliberately simplified. Additional steps
- * required for a production-quality application, such as security checks,
- * input validation and proper error handling, might not be present in
- * this sample code.
- */
-
-
-#ifndef HPROF_REFERENCE_H
-#define HPROF_REFERENCE_H
-
-void reference_init(void);
-RefIndex reference_obj(RefIndex next, jvmtiHeapReferenceKind kind,
- ObjectIndex object_index, jint index, jint length);
-RefIndex reference_prim_field(RefIndex next, jvmtiHeapReferenceKind refKind,
- jvmtiPrimitiveType primType, jvalue value, jint field_index);
-RefIndex reference_prim_array(RefIndex next, jvmtiPrimitiveType element_type,
- const void *elements, jint count);
-void reference_cleanup(void);
-void reference_dump_class(JNIEnv *env, ObjectIndex object_index,
- RefIndex list);
-void reference_dump_instance(JNIEnv *env, ObjectIndex object_index,
- RefIndex list);
-
-#endif
--- a/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_site.c Thu Aug 20 12:29:58 2015 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,905 +0,0 @@
-/*
- * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * - Neither the name of Oracle nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
- * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/*
- * This source code is provided to illustrate the usage of a given feature
- * or technique and has been deliberately simplified. Additional steps
- * required for a production-quality application, such as security checks,
- * input validation and proper error handling, might not be present in
- * this sample code.
- */
-
-
-/* Allocation site table. */
-
-/*
- * Every object allocation will have a place where it was allocated,
- * this is the purpose of the SiteIndex.
- *
- * The allocation site or SiteIndex is unique via a (class,trace) pair.
- *
- * The allocation statistics are accumulated in the SiteInfo for each
- * site.
- *
- * This file also contains the heap iterate logic, which is closely
- * associated with the site table, the object table, and the
- * reference table. Each object has an element in the object table
- * and as the heap is traversed, and information contained in each
- * object is saved as a linked list of references.
- *
- */
-
-#include "hprof.h"
-
-typedef struct SiteKey {
- ClassIndex cnum; /* Unique class number */
- TraceIndex trace_index; /* Trace number */
-} SiteKey;
-
-typedef struct SiteInfo {
- int changed; /* Objects at this site changed? */
- unsigned n_alloced_instances; /* Total allocated instances */
- unsigned n_alloced_bytes; /* Total bytes allocated from here */
- unsigned n_live_instances; /* Live instances for this site. */
- unsigned n_live_bytes; /* Live byte count for this site. */
-} SiteInfo;
-
-typedef struct IterateInfo {
- SiteIndex * site_nums;
- int count;
- int changed_only;
-} IterateInfo;
-
-/* Private internal functions. */
-
-static SiteKey*
-get_pkey(SiteIndex index)
-{
- void *key_ptr;
- int key_len;
-
- table_get_key(gdata->site_table, index, &key_ptr, &key_len);
- HPROF_ASSERT(key_len==sizeof(SiteKey));
- HPROF_ASSERT(key_ptr!=NULL);
- return (SiteKey*)key_ptr;
-}
-
-ClassIndex
-site_get_class_index(SiteIndex index)
-{
- SiteKey *pkey;
-
- pkey = get_pkey(index);
- return pkey->cnum;
-}
-
-TraceIndex
-site_get_trace_index(SiteIndex index)
-{
- SiteKey *pkey;
-
- pkey = get_pkey(index);
- return pkey->trace_index;
-}
-
-static SiteInfo *
-get_info(SiteIndex index)
-{
- SiteInfo *info;
-
- info = (SiteInfo*)table_get_info(gdata->site_table, index);
- return info;
-}
-
-static void
-list_item(TableIndex i, void *key_ptr, int key_len, void *info_ptr, void *arg)
-{
- SiteKey *pkey;
- jlong n_alloced_instances;
- jlong n_alloced_bytes;
- jlong n_live_instances;
- jlong n_live_bytes;
-
- HPROF_ASSERT(key_ptr!=NULL);
- HPROF_ASSERT(key_len==sizeof(SiteKey));
- pkey = (SiteKey*)key_ptr;
-
- if ( info_ptr != NULL ) {
- SiteInfo *info;
-
- info = (SiteInfo *)info_ptr;
- n_alloced_instances = info->n_alloced_instances;
- n_alloced_bytes = info->n_alloced_bytes;
- n_live_instances = info->n_live_instances;
- n_live_bytes = info->n_live_bytes;
- } else {
- n_alloced_instances = 0;
- n_alloced_bytes = 0;
- n_live_instances = 0;
- n_live_bytes = 0;
- }
-
- debug_message( "Site 0x%08x: class=0x%08x, trace=0x%08x, "
- "Ninst=(%d,%d), Nbytes=(%d,%d), "
- "Nlive=(%d,%d), NliveBytes=(%d,%d)\n",
- i,
- pkey->cnum,
- pkey->trace_index,
- jlong_high(n_alloced_instances), jlong_low(n_alloced_instances),
- jlong_high(n_alloced_bytes), jlong_low(n_alloced_bytes),
- jlong_high(n_live_instances), jlong_low(n_live_instances),
- jlong_high(n_live_bytes), jlong_low(n_live_bytes));
-}
-
-static void
-collect_iterator(TableIndex i, void *key_ptr, int key_len, void *info_ptr, void *arg)
-{
- IterateInfo *iterate;
-
- HPROF_ASSERT(key_ptr!=NULL);
- HPROF_ASSERT(key_len==sizeof(SiteKey));
- HPROF_ASSERT(arg!=NULL);
- iterate = (IterateInfo *)arg;
-
- if ( iterate->changed_only ) {
- SiteInfo *info;
-
- info = (SiteInfo *)info_ptr;
- if ( info==NULL || !info->changed ) {
- return;
- }
- }
- iterate->site_nums[iterate->count++] = i;
-}
-
-static void
-mark_unchanged_iterator(TableIndex i, void *key_ptr, int key_len, void *info_ptr, void *arg)
-{
- SiteInfo *info;
-
- HPROF_ASSERT(key_ptr!=NULL);
- HPROF_ASSERT(key_len==sizeof(SiteKey));
-
- info = (SiteInfo *)info_ptr;
- if ( info != NULL ) {
- info->changed = 0;
- }
-}
-
-static int
-qsort_compare_allocated_bytes(const void *p_site1, const void *p_site2)
-{
- SiteIndex site1;
- SiteIndex site2;
- SiteInfo *info1;
- SiteInfo *info2;
-
- HPROF_ASSERT(p_site1!=NULL);
- HPROF_ASSERT(p_site2!=NULL);
- site1 = *(SiteIndex *)p_site1;
- site2 = *(SiteIndex *)p_site2;
- info1 = get_info(site1);
- info2 = get_info(site2);
- return info2->n_alloced_bytes - info1->n_alloced_bytes;
-}
-
-static int
-qsort_compare_live_bytes(const void *p_site1, const void *p_site2)
-{
- SiteIndex site1;
- SiteIndex site2;
- SiteInfo *info1;
- SiteInfo *info2;
-
- HPROF_ASSERT(p_site1!=NULL);
- HPROF_ASSERT(p_site2!=NULL);
- site1 = *(SiteIndex *)p_site1;
- site2 = *(SiteIndex *)p_site2;
- info1 = get_info(site1);
- info2 = get_info(site2);
- return info2->n_live_bytes - info1->n_live_bytes;
-}
-
-static ClassIndex
-find_cnum(jlong class_tag)
-{
- ClassIndex cnum;
- ObjectIndex class_object_index;
- SiteIndex class_site_index;
- SiteKey *pkey;
-
- HPROF_ASSERT(class_tag!=(jlong)0);
- class_object_index = tag_extract(class_tag);
- class_site_index = object_get_site(class_object_index);
- pkey = get_pkey(class_site_index);
- cnum = pkey->cnum;
- return cnum;
-}
-
-/* Create tag and object entry for an untagged object (should be rare) */
-static jlong
-make_new_tag(jlong class_tag, jlong size, TraceIndex trace_index,
- SerialNumber thread_serial_num,
- ObjectIndex *pindex, SiteIndex *psite)
-{
- ObjectIndex object_index;
- SiteIndex object_site_index;
-
- HPROF_ASSERT(class_tag!=(jlong)0);
- object_site_index = site_find_or_create(find_cnum(class_tag), trace_index);
- object_index = object_new(object_site_index, (jint)size,
- OBJECT_SYSTEM, thread_serial_num);
- if ( pindex != NULL ) {
- *pindex = object_index;
- }
- if ( psite != NULL ) {
- *psite = object_site_index;
- }
- return tag_create(object_index);
-}
-
-/* Setup tag on root object, if tagged return object index and site index */
-static void
-setup_tag_on_root(jlong *tag_ptr, jlong class_tag, jlong size,
- SerialNumber thread_serial_num,
- ObjectIndex *pindex, SiteIndex *psite)
-{
- HPROF_ASSERT(class_tag!=(jlong)0);
- if ( (*tag_ptr) != (jlong)0 ) {
- if ( pindex != NULL ) {
- *pindex = tag_extract(*tag_ptr);
- }
- if ( psite != NULL ) {
- *psite = object_get_site(tag_extract(*tag_ptr));
- }
- } else {
- /* Create and set the tag. */
- *tag_ptr = make_new_tag(class_tag, size, gdata->system_trace_index,
- thread_serial_num, pindex, psite);
- }
-}
-
-/* External interfaces */
-
-SiteIndex
-site_find_or_create(ClassIndex cnum, TraceIndex trace_index)
-{
- SiteIndex index;
- static SiteKey empty_key;
- SiteKey key;
-
- key = empty_key;
- HPROF_ASSERT(cnum!=0);
- HPROF_ASSERT(trace_index!=0);
- key.cnum = cnum;
- key.trace_index = trace_index;
- index = table_find_or_create_entry(gdata->site_table,
- &key, (int)sizeof(key), NULL, NULL);
- return index;
-}
-
-void
-site_init(void)
-{
- HPROF_ASSERT(gdata->site_table==NULL);
- gdata->site_table = table_initialize("Site",
- 1024, 1024, 511, (int)sizeof(SiteInfo));
-}
-
-void
-site_list(void)
-{
- debug_message(
- "--------------------- Site Table ------------------------\n");
- table_walk_items(gdata->site_table, &list_item, NULL);
- debug_message(
- "----------------------------------------------------------\n");
-}
-
-void
-site_cleanup(void)
-{
- table_cleanup(gdata->site_table, NULL, NULL);
- gdata->site_table = NULL;
-}
-
-void
-site_update_stats(SiteIndex index, jint size, jint hits)
-{
- SiteInfo *info;
-
- table_lock_enter(gdata->site_table); {
- info = get_info(index);
-
- info->n_live_instances += hits;
- info->n_live_bytes += size;
- info->changed = 1;
-
- gdata->total_live_bytes += size;
- gdata->total_live_instances += hits;
-
- if ( size > 0 ) {
- info->n_alloced_instances += hits;
- info->n_alloced_bytes += size;
- gdata->total_alloced_bytes =
- jlong_add(gdata->total_alloced_bytes, jint_to_jlong(size));
- gdata->total_alloced_instances =
- jlong_add(gdata->total_alloced_instances, jint_to_jlong(hits));
- }
- } table_lock_exit(gdata->site_table);
-}
-
-/* Output allocation sites, up to the given cut-off point, and according
- * to the given flags:
- *
- * SITE_DUMP_INCREMENTAL only dump what's changed since last dump.
- * SITE_SORT_BY_ALLOC sort sites by total allocation rather
- * than live data.
- * SITE_FORCE_GC force a GC before the site dump.
- */
-
-void
-site_write(JNIEnv *env, int flags, double cutoff)
-{
- HPROF_ASSERT(gdata->site_table!=NULL);
- LOG3("site_write", "flags", flags);
-
- if (flags & SITE_FORCE_GC) {
- runGC();
- }
-
- HPROF_ASSERT(gdata->total_live_bytes!=0);
-
- rawMonitorEnter(gdata->data_access_lock); {
-
- IterateInfo iterate;
- int site_table_size;
- double accum_percent;
- void * comment_str;
- int i;
- int cutoff_count;
- int nbytes;
-
- accum_percent = 0;
- site_table_size = table_element_count(gdata->site_table);
-
- (void)memset(&iterate, 0, sizeof(iterate));
- nbytes = site_table_size * (int)sizeof(SiteIndex);
- if ( nbytes > 0 ) {
- iterate.site_nums = HPROF_MALLOC(nbytes);
- (void)memset(iterate.site_nums, 0, nbytes);
- }
- iterate.count = 0;
- iterate.changed_only = flags & SITE_DUMP_INCREMENTAL;
- table_walk_items(gdata->site_table, &collect_iterator, &iterate);
-
- site_table_size = iterate.count;
-
- if (flags & SITE_SORT_BY_ALLOC) {
- comment_str = "allocated bytes";
- qsort(iterate.site_nums, site_table_size, sizeof(SiteIndex),
- &qsort_compare_allocated_bytes);
- } else {
- comment_str = "live bytes";
- qsort(iterate.site_nums, site_table_size, sizeof(SiteIndex),
- &qsort_compare_live_bytes);
- }
-
- trace_output_unmarked(env);
-
- cutoff_count = 0;
- for (i = 0; i < site_table_size; i++) {
- SiteInfo *info;
- SiteIndex index;
- double ratio;
-
- index= iterate.site_nums[i];
- HPROF_ASSERT(index!=0);
- info = get_info(index);
- ratio = (double)info->n_live_bytes / (double)gdata->total_live_bytes;
- if (ratio < cutoff) {
- break;
- }
- cutoff_count++;
- }
-
- io_write_sites_header( comment_str,
- flags,
- cutoff,
- gdata->total_live_bytes,
- gdata->total_live_instances,
- gdata->total_alloced_bytes,
- gdata->total_alloced_instances,
- cutoff_count);
-
- for (i = 0; i < cutoff_count; i++) {
- SiteInfo *info;
- SiteKey *pkey;
- SiteIndex index;
- char *class_signature;
- double ratio;
-
- index = iterate.site_nums[i];
- pkey = get_pkey(index);
- info = get_info(index);
-
- ratio = (double)info->n_live_bytes / (double)gdata->total_live_bytes;
- accum_percent += ratio;
-
- class_signature = string_get(class_get_signature(pkey->cnum));
-
- io_write_sites_elem(i + 1,
- ratio,
- accum_percent,
- class_signature,
- class_get_serial_number(pkey->cnum),
- trace_get_serial_number(pkey->trace_index),
- info->n_live_bytes,
- info->n_live_instances,
- info->n_alloced_bytes,
- info->n_alloced_instances);
- }
-
- io_write_sites_footer();
-
- table_walk_items(gdata->site_table, &mark_unchanged_iterator, NULL);
-
- if ( iterate.site_nums != NULL ) {
- HPROF_FREE(iterate.site_nums);
- }
-
- } rawMonitorExit(gdata->data_access_lock);
-}
-
-/* Primitive array data callback for FollowReferences */
-static jint JNICALL
-cbPrimArrayData(jlong class_tag, jlong size, jlong* tag_ptr,
- jint element_count, jvmtiPrimitiveType element_type,
- const void* elements, void* user_data)
-{
- ObjectIndex object_index;
- RefIndex ref_index;
- RefIndex prev_ref_index;
-
- HPROF_ASSERT(tag_ptr!=NULL);
- HPROF_ASSERT(class_tag!=(jlong)0);
- HPROF_ASSERT((*tag_ptr)!=(jlong)0);
- if ( class_tag == (jlong)0 || (*tag_ptr) == (jlong)0 ) {
- /* We can't do anything with a class_tag==0, just skip it */
- return JVMTI_VISIT_OBJECTS;
- }
-
- /* Assume object has been tagged, get object index */
- object_index = tag_extract((*tag_ptr));
-
- /* Save string data */
- prev_ref_index = object_get_references(object_index);
- ref_index = reference_prim_array(prev_ref_index,
- element_type, elements, element_count);
- object_set_references(object_index, ref_index);
-
- return JVMTI_VISIT_OBJECTS;
-}
-
-/* Primitive field data callback for FollowReferences */
-static jint JNICALL
-cbPrimFieldData(jvmtiHeapReferenceKind reference_kind,
- const jvmtiHeapReferenceInfo* reference_info, jlong class_tag,
- jlong* tag_ptr, jvalue value, jvmtiPrimitiveType value_type,
- void* user_data)
-{
- ObjectIndex object_index;
- jint field_index;
- RefIndex ref_index;
- RefIndex prev_ref_index;
-
- HPROF_ASSERT(tag_ptr!=NULL);
- HPROF_ASSERT(class_tag!=(jlong)0);
- HPROF_ASSERT((*tag_ptr)!=(jlong)0);
- if ( class_tag == (jlong)0 || (*tag_ptr) == (jlong)0 ) {
- /* We can't do anything with a class_tag==0, just skip it */
- return JVMTI_VISIT_OBJECTS;
- }
-
- /* If the field is 0, just skip it, we assume 0 */
- if ( value.j == (jlong)0 ) {
- return JVMTI_VISIT_OBJECTS;
- }
-
- /* Get field index */
- field_index = reference_info->field.index;
-
- /* We assume the object was tagged */
- object_index = tag_extract((*tag_ptr));
-
- /* Save primitive field data */
- prev_ref_index = object_get_references(object_index);
- ref_index = reference_prim_field(prev_ref_index, reference_kind,
- value_type, value, field_index);
- object_set_references(object_index, ref_index);
-
- return JVMTI_VISIT_OBJECTS;
-}
-
-static SerialNumber
-checkThreadSerialNumber(SerialNumber thread_serial_num)
-{
- TlsIndex tls_index;
-
- if ( thread_serial_num == gdata->unknown_thread_serial_num ) {
- return thread_serial_num;
- }
- tls_index = tls_find(thread_serial_num);
- if ( tls_index != 0 && tls_get_in_heap_dump(tls_index) != 0 ) {
- return thread_serial_num;
- }
- return gdata->unknown_thread_serial_num;
-}
-
-/* Get the object index and thread serial number for this local object */
-static void
-localReference(jlong *tag_ptr, jlong class_tag, jlong thread_tag,
- jlong size, ObjectIndex *pobject_index, SerialNumber *pthread_serial_num)
-{
- ObjectIndex object_index;
- SerialNumber thread_serial_num;
-
- HPROF_ASSERT(pobject_index!=NULL);
- HPROF_ASSERT(pthread_serial_num!=NULL);
- HPROF_ASSERT(tag_ptr!=NULL);
- HPROF_ASSERT(class_tag!=(jlong)0);
-
- if ( (*tag_ptr) != (jlong)0 ) {
- object_index = tag_extract(*tag_ptr);
- thread_serial_num = object_get_thread_serial_number(object_index);
- thread_serial_num = checkThreadSerialNumber(thread_serial_num);
- } else {
- if ( thread_tag != (jlong)0 ) {
- ObjectIndex thread_object_index;
-
- thread_object_index = tag_extract(thread_tag);
- thread_serial_num =
- object_get_thread_serial_number(thread_object_index);
- thread_serial_num = checkThreadSerialNumber(thread_serial_num);
- } else {
- thread_serial_num = gdata->unknown_thread_serial_num;
- }
- /* Create and set the tag. */
- *tag_ptr = make_new_tag(class_tag, size, gdata->system_trace_index,
- thread_serial_num, &object_index, NULL);
- }
-
- HPROF_ASSERT(thread_serial_num!=0);
- HPROF_ASSERT(object_index!=0);
- *pobject_index = object_index;
- *pthread_serial_num = thread_serial_num;
-}
-
-/* Store away plain object reference information */
-static jint
-objectReference(jvmtiHeapReferenceKind reference_kind,
- const jvmtiHeapReferenceInfo* reference_info,
- jlong class_tag, jlong size, jlong* tag_ptr,
- jlong* referrer_tag_ptr, jint length)
-{
- ObjectIndex object_index;
- jint reference_index;
- RefIndex ref_index;
- RefIndex prev_ref_index;
- ObjectIndex referrer_object_index;
- jlong object_tag;
-
- HPROF_ASSERT(tag_ptr!=NULL);
- HPROF_ASSERT(class_tag!=(jlong)0);
- HPROF_ASSERT(referrer_tag_ptr!=NULL);
- HPROF_ASSERT((*referrer_tag_ptr)!=(jlong)0);
- if ( class_tag == (jlong)0 || (*referrer_tag_ptr) == (jlong)0 ) {
- /* We can't do anything with a class_tag==0, just skip it */
- return JVMTI_VISIT_OBJECTS;
- }
-
- switch ( reference_kind ) {
- case JVMTI_HEAP_REFERENCE_CLASS_LOADER:
- case JVMTI_HEAP_REFERENCE_INTERFACE:
- default:
- /* Currently we don't need these */
- return JVMTI_VISIT_OBJECTS;
- case JVMTI_HEAP_REFERENCE_FIELD:
- case JVMTI_HEAP_REFERENCE_STATIC_FIELD:
- reference_index = reference_info->field.index;
- break;
- case JVMTI_HEAP_REFERENCE_ARRAY_ELEMENT:
- reference_index = reference_info->array.index;
- break;
- case JVMTI_HEAP_REFERENCE_CONSTANT_POOL:
- reference_index = reference_info->constant_pool.index;
- break;
- case JVMTI_HEAP_REFERENCE_SIGNERS:
- case JVMTI_HEAP_REFERENCE_PROTECTION_DOMAIN:
- reference_index = 0;
- break;
- }
-
- /* We assume the referrer is tagged */
- referrer_object_index = tag_extract((*referrer_tag_ptr));
-
- /* Now check the referree */
- object_tag = *tag_ptr;
- if ( object_tag != (jlong)0 ) {
- object_index = tag_extract(object_tag);
- } else {
- /* Create and set the tag. */
- object_tag = make_new_tag(class_tag, size, gdata->system_trace_index,
- gdata->unknown_thread_serial_num,
- &object_index, NULL);
- *tag_ptr = object_tag;
- }
- HPROF_ASSERT(object_index!=0);
-
- /* Save reference information */
- prev_ref_index = object_get_references(referrer_object_index);
- ref_index = reference_obj(prev_ref_index, reference_kind,
- object_index, reference_index, length);
- object_set_references(referrer_object_index, ref_index);
-
- return JVMTI_VISIT_OBJECTS;
-}
-
-/* FollowReferences heap_reference_callback */
-static jint JNICALL
-cbReference(jvmtiHeapReferenceKind reference_kind,
- const jvmtiHeapReferenceInfo* reference_info,
- jlong class_tag, jlong referrer_class_tag,
- jlong size, jlong* tag_ptr,
- jlong* referrer_tag_ptr, jint length, void* user_data)
-{
- ObjectIndex object_index;
-
- /* Only calls to Allocate, Deallocate, RawMonitorEnter & RawMonitorExit
- * are allowed here (see the JVMTI Spec).
- */
-
- HPROF_ASSERT(tag_ptr!=NULL);
- HPROF_ASSERT(class_tag!=(jlong)0);
- if ( class_tag == (jlong)0 ) {
- /* We can't do anything with a class_tag==0, just skip it */
- return JVMTI_VISIT_OBJECTS;
- }
-
- switch ( reference_kind ) {
-
- case JVMTI_HEAP_REFERENCE_FIELD:
- case JVMTI_HEAP_REFERENCE_ARRAY_ELEMENT:
- case JVMTI_HEAP_REFERENCE_CLASS_LOADER:
- case JVMTI_HEAP_REFERENCE_SIGNERS:
- case JVMTI_HEAP_REFERENCE_PROTECTION_DOMAIN:
- case JVMTI_HEAP_REFERENCE_INTERFACE:
- case JVMTI_HEAP_REFERENCE_STATIC_FIELD:
- case JVMTI_HEAP_REFERENCE_CONSTANT_POOL:
- return objectReference(reference_kind, reference_info,
- class_tag, size, tag_ptr, referrer_tag_ptr, length);
-
- case JVMTI_HEAP_REFERENCE_JNI_GLOBAL: {
- SerialNumber trace_serial_num;
- SerialNumber gref_serial_num;
- TraceIndex trace_index;
- SiteIndex object_site_index;
-
- setup_tag_on_root(tag_ptr, class_tag, size,
- gdata->unknown_thread_serial_num,
- &object_index, &object_site_index);
- if ( object_site_index != 0 ) {
- SiteKey *pkey;
-
- pkey = get_pkey(object_site_index);
- trace_index = pkey->trace_index;
- } else {
- trace_index = gdata->system_trace_index;
- }
- trace_serial_num = trace_get_serial_number(trace_index);
- gref_serial_num = gdata->gref_serial_number_counter++;
- io_heap_root_jni_global(object_index, gref_serial_num,
- trace_serial_num);
- }
- break;
-
- case JVMTI_HEAP_REFERENCE_SYSTEM_CLASS: {
- char *sig;
- SerialNumber class_serial_num;
- SiteIndex object_site_index;
-
- setup_tag_on_root(tag_ptr, class_tag, size,
- gdata->unknown_thread_serial_num,
- &object_index, &object_site_index);
- sig = "Unknown";
- class_serial_num = 0;
- if ( object_site_index != 0 ) {
- SiteKey *pkey;
-
- pkey = get_pkey(object_site_index);
- sig = string_get(class_get_signature(pkey->cnum));
- class_serial_num = class_get_serial_number(pkey->cnum);
- }
- io_heap_root_system_class(object_index, sig, class_serial_num);
- }
- break;
-
- case JVMTI_HEAP_REFERENCE_MONITOR:
- setup_tag_on_root(tag_ptr, class_tag, size,
- gdata->unknown_thread_serial_num,
- &object_index, NULL);
- io_heap_root_monitor(object_index);
- break;
-
- case JVMTI_HEAP_REFERENCE_STACK_LOCAL: {
- SerialNumber thread_serial_num;
- jlong thread_tag;
-
- thread_tag = reference_info->stack_local.thread_tag;
- localReference(tag_ptr, class_tag, thread_tag, size,
- &object_index, &thread_serial_num);
- io_heap_root_java_frame(object_index, thread_serial_num,
- reference_info->stack_local.depth);
- }
- break;
-
- case JVMTI_HEAP_REFERENCE_JNI_LOCAL: {
- SerialNumber thread_serial_num;
- jlong thread_tag;
-
- thread_tag = reference_info->jni_local.thread_tag;
- localReference(tag_ptr, class_tag, thread_tag, size,
- &object_index, &thread_serial_num);
- io_heap_root_jni_local(object_index, thread_serial_num,
- reference_info->jni_local.depth);
- }
- break;
-
- case JVMTI_HEAP_REFERENCE_THREAD: {
- SerialNumber thread_serial_num;
- SerialNumber trace_serial_num;
- TraceIndex trace_index;
- SiteIndex object_site_index;
- TlsIndex tls_index;
-
- /* It is assumed that tag_ptr is referring to a
- * java.lang.Thread object here.
- */
- if ( (*tag_ptr) != (jlong)0 ) {
- setup_tag_on_root(tag_ptr, class_tag, size, 0,
- &object_index, &object_site_index);
- trace_index = site_get_trace_index(object_site_index);
- /* Hopefully the ThreadStart event put this thread's
- * correct serial number on it's object.
- */
- thread_serial_num = object_get_thread_serial_number(object_index);
- } else {
- /* Rare situation that a Thread object is not tagged.
- * Create special unique thread serial number in this
- * case, probably means we never saw a thread start
- * or thread end, or even an allocation of the thread
- * object.
- */
- thread_serial_num = gdata->thread_serial_number_counter++;
- setup_tag_on_root(tag_ptr, class_tag, size,
- thread_serial_num,
- &object_index, &object_site_index);
- trace_index = gdata->system_trace_index;
- }
- /* Get tls_index and set in_heap_dump, if we find it. */
- tls_index = tls_find(thread_serial_num);
- if ( tls_index != 0 ) {
- tls_set_in_heap_dump(tls_index, 1);
- }
- trace_serial_num = trace_get_serial_number(trace_index);
- /* Issue thread object (must be before thread root) */
- io_heap_root_thread_object(object_index,
- thread_serial_num, trace_serial_num);
- /* Issue thread root */
- io_heap_root_thread(object_index, thread_serial_num);
- }
- break;
-
- case JVMTI_HEAP_REFERENCE_OTHER:
- setup_tag_on_root(tag_ptr, class_tag, size,
- gdata->unknown_thread_serial_num,
- &object_index, NULL);
- io_heap_root_unknown(object_index);
- break;
-
- default:
- /* Ignore anything else */
- break;
-
- }
-
- return JVMTI_VISIT_OBJECTS;
-}
-
-void
-site_heapdump(JNIEnv *env)
-{
-
- rawMonitorEnter(gdata->data_access_lock); {
-
- jvmtiHeapCallbacks heapCallbacks;
-
- /* Remove class dumped status, all classes must be dumped */
- class_all_status_remove(CLASS_DUMPED);
-
- /* Clear in_heap_dump flag */
- tls_clear_in_heap_dump();
-
- /* Dump the last thread traces and get the lists back we need */
- tls_dump_traces(env);
-
- /* Write header for heap dump */
- io_heap_header(gdata->total_live_instances, gdata->total_live_bytes);
-
- /* Setup a clean reference table */
- reference_init();
-
- /* Walk over all reachable objects and dump out roots */
- gdata->gref_serial_number_counter = gdata->gref_serial_number_start;
-
- /* Issue thread object for fake non-existent unknown thread
- * just in case someone refers to it. Real threads are handled
- * during iterate over reachable objects.
- */
- io_heap_root_thread_object(0, gdata->unknown_thread_serial_num,
- trace_get_serial_number(gdata->system_trace_index));
-
- /* Iterate over heap and get the real stuff */
- (void)memset(&heapCallbacks, 0, sizeof(heapCallbacks));
-
- /* Select callbacks */
- heapCallbacks.heap_reference_callback = &cbReference;
- if ( gdata->primfields == JNI_TRUE ) {
- heapCallbacks.primitive_field_callback = &cbPrimFieldData;
- }
- if ( gdata->primarrays == JNI_TRUE ) {
- heapCallbacks.array_primitive_value_callback = &cbPrimArrayData;
- }
- followReferences(&heapCallbacks, (void*)NULL);
-
- /* Process reference information. */
- object_reference_dump(env);
- object_clear_references();
- reference_cleanup();
-
- /* Dump the last thread traces and get the lists back we need */
- tls_dump_traces(env);
-
- /* Write out footer for heap dump */
- io_heap_footer();
-
- } rawMonitorExit(gdata->data_access_lock);
-}
--- a/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_site.h Thu Aug 20 12:29:58 2015 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,56 +0,0 @@
-/*
- * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * - Neither the name of Oracle nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
- * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/*
- * This source code is provided to illustrate the usage of a given feature
- * or technique and has been deliberately simplified. Additional steps
- * required for a production-quality application, such as security checks,
- * input validation and proper error handling, might not be present in
- * this sample code.
- */
-
-
-#ifndef HPROF_SITE_H
-#define HPROF_SITE_H
-
-void site_init(void);
-SiteIndex site_find_or_create(ClassIndex cnum, TraceIndex trace_index);
-TraceIndex site_get_trace_index(SiteIndex index);
-ClassIndex site_get_class_index(SiteIndex index);
-
-void site_list(void);
-void site_cleanup(void);
-void site_update_stats(SiteIndex index, jint size, jint hits);
-void site_write(JNIEnv *env, int flags, double cutoff);
-
-void site_heapdump(JNIEnv *env);
-
-#endif
--- a/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_stack.c Thu Aug 20 12:29:58 2015 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,170 +0,0 @@
-/*
- * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * - Neither the name of Oracle nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
- * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/*
- * This source code is provided to illustrate the usage of a given feature
- * or technique and has been deliberately simplified. Additional steps
- * required for a production-quality application, such as security checks,
- * input validation and proper error handling, might not be present in
- * this sample code.
- */
-
-
-/* Simple stack storage mechanism (or simple List). */
-
-/*
- * Stack is any depth (grows as it needs to), elements are arbitrary
- * length but known at stack init time.
- *
- * Stack elements can be accessed via pointers (be careful, if stack
- * moved while you point into stack you have problems)
- *
- * Pointers to stack elements passed in are copied.
- *
- * Since the stack can be inspected, it can be used for more than just
- * a simple stack.
- *
- */
-
-#include "hprof.h"
-
-static void
-resize(Stack *stack)
-{
- void *old_elements;
- void *new_elements;
- int old_size;
- int new_size;
-
- HPROF_ASSERT(stack!=NULL);
- HPROF_ASSERT(stack->elements!=NULL);
- HPROF_ASSERT(stack->size>0);
- HPROF_ASSERT(stack->elem_size>0);
- HPROF_ASSERT(stack->incr_size>0);
- old_size = stack->size;
- old_elements = stack->elements;
- if ( (stack->resizes % 10) && stack->incr_size < (old_size >> 2) ) {
- stack->incr_size = old_size >> 2; /* 1/4 the old_size */
- }
- new_size = old_size + stack->incr_size;
- new_elements = HPROF_MALLOC(new_size*stack->elem_size);
- (void)memcpy(new_elements, old_elements, old_size*stack->elem_size);
- stack->size = new_size;
- stack->elements = new_elements;
- HPROF_FREE(old_elements);
- stack->resizes++;
-}
-
-Stack *
-stack_init(int init_size, int incr_size, int elem_size)
-{
- Stack *stack;
- void *elements;
-
- HPROF_ASSERT(init_size>0);
- HPROF_ASSERT(elem_size>0);
- HPROF_ASSERT(incr_size>0);
- stack = (Stack*)HPROF_MALLOC((int)sizeof(Stack));
- elements = HPROF_MALLOC(init_size*elem_size);
- stack->size = init_size;
- stack->incr_size = incr_size;
- stack->elem_size = elem_size;
- stack->count = 0;
- stack->elements = elements;
- stack->resizes = 0;
- return stack;
-}
-
-void *
-stack_element(Stack *stack, int i)
-{
- HPROF_ASSERT(stack!=NULL);
- HPROF_ASSERT(stack->elements!=NULL);
- HPROF_ASSERT(stack->count>i);
- HPROF_ASSERT(i>=0);
- return (void*)(((char*)stack->elements) + i * stack->elem_size);
-}
-
-void *
-stack_top(Stack *stack)
-{
- void *element;
-
- HPROF_ASSERT(stack!=NULL);
- element = NULL;
- if ( stack->count > 0 ) {
- element = stack_element(stack, (stack->count-1));
- }
- return element;
-}
-
-int
-stack_depth(Stack *stack)
-{
- HPROF_ASSERT(stack!=NULL);
- return stack->count;
-}
-
-void *
-stack_pop(Stack *stack)
-{
- void *element;
-
- element = stack_top(stack);
- if ( element != NULL ) {
- stack->count--;
- }
- return element;
-}
-
-void
-stack_push(Stack *stack, void *element)
-{
- void *top_element;
-
- HPROF_ASSERT(stack!=NULL);
- if ( stack->count >= stack->size ) {
- resize(stack);
- }
- stack->count++;
- top_element = stack_top(stack);
- (void)memcpy(top_element, element, stack->elem_size);
-}
-
-void
-stack_term(Stack *stack)
-{
- HPROF_ASSERT(stack!=NULL);
- if ( stack->elements != NULL ) {
- HPROF_FREE(stack->elements);
- }
- HPROF_FREE(stack);
-}
--- a/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_stack.h Thu Aug 20 12:29:58 2015 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,61 +0,0 @@
-/*
- * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * - Neither the name of Oracle nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
- * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/*
- * This source code is provided to illustrate the usage of a given feature
- * or technique and has been deliberately simplified. Additional steps
- * required for a production-quality application, such as security checks,
- * input validation and proper error handling, might not be present in
- * this sample code.
- */
-
-
-#ifndef HPROF_STACK_H
-#define HPROF_STACK_H
-
-typedef struct Stack {
- int elem_size;
- int incr_size;
- int size;
- int count;
- int resizes;
- void *elements;
-} Stack;
-
-Stack *stack_init(int init_size, int incr_size, int elem_size);
-void *stack_element(Stack *stack, int i);
-void *stack_top(Stack *stack);
-int stack_depth(Stack *stack);
-void *stack_pop(Stack *stack);
-void stack_push(Stack *stack, void *element);
-void stack_term(Stack *stack);
-
-#endif
--- a/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_string.c Thu Aug 20 12:29:58 2015 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,115 +0,0 @@
-/*
- * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * - Neither the name of Oracle nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
- * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/*
- * This source code is provided to illustrate the usage of a given feature
- * or technique and has been deliberately simplified. Additional steps
- * required for a production-quality application, such as security checks,
- * input validation and proper error handling, might not be present in
- * this sample code.
- */
-
-
-/* Table of byte arrays (e.g. char* string + NULL byte) */
-
-/*
- * Strings are unique by their own contents, since the string itself
- * is the Key, and the hprof_table.c guarantees that keys don't move,
- * this works out perfect. Any key in this table can be used as
- * an char*.
- *
- * This does mean that this table has dynamically sized keys.
- *
- * Care needs to be taken to make sure the NULL byte is included, not for
- * the sake of hprof_table.c, but so that the key can be used as a char*.
- *
- */
-
-#include "hprof.h"
-
-void
-string_init(void)
-{
- HPROF_ASSERT(gdata->string_table==NULL);
- gdata->string_table = table_initialize("Strings", 4096, 4096, 1024, 0);
-}
-
-StringIndex
-string_find_or_create(const char *str)
-{
- return table_find_or_create_entry(gdata->string_table,
- (void*)str, (int)strlen(str)+1, NULL, NULL);
-}
-
-static void
-list_item(TableIndex index, void *str, int len, void *info_ptr, void *arg)
-{
- debug_message( "0x%08x: String \"%s\"\n", index, (const char *)str);
-}
-
-void
-string_list(void)
-{
- debug_message(
- "-------------------- String Table ------------------------\n");
- table_walk_items(gdata->string_table, &list_item, NULL);
- debug_message(
- "----------------------------------------------------------\n");
-}
-
-void
-string_cleanup(void)
-{
- table_cleanup(gdata->string_table, NULL, NULL);
- gdata->string_table = NULL;
-}
-
-char *
-string_get(StringIndex index)
-{
- void *key;
- int key_len;
-
- table_get_key(gdata->string_table, index, &key, &key_len);
- HPROF_ASSERT(key_len>0);
- return (char*)key;
-}
-
-int
-string_get_len(StringIndex index)
-{
- void *key;
- int key_len;
-
- table_get_key(gdata->string_table, index, &key, &key_len);
- HPROF_ASSERT(key_len>0);
- return key_len-1;
-}
--- a/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_string.h Thu Aug 20 12:29:58 2015 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,51 +0,0 @@
-/*
- * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * - Neither the name of Oracle nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
- * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/*
- * This source code is provided to illustrate the usage of a given feature
- * or technique and has been deliberately simplified. Additional steps
- * required for a production-quality application, such as security checks,
- * input validation and proper error handling, might not be present in
- * this sample code.
- */
-
-
-#ifndef HPROF_STRING_H
-#define HPROF_STRING_H
-
-void string_init(void);
-StringIndex string_find_or_create(const char *name);
-char * string_get(StringIndex index);
-int string_get_len(StringIndex index);
-void string_list(void);
-void string_cleanup(void);
-
-#endif
--- a/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_table.c Thu Aug 20 12:29:58 2015 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,954 +0,0 @@
-/*
- * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * - Neither the name of Oracle nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
- * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/*
- * This source code is provided to illustrate the usage of a given feature
- * or technique and has been deliberately simplified. Additional steps
- * required for a production-quality application, such as security checks,
- * input validation and proper error handling, might not be present in
- * this sample code.
- */
-
-
-/* Lookup Table of generic elements. */
-
-/*
- * Each table has a unique lock, all accesses are protected.
- *
- * Table elements are identified with a 32bit unsigned int.
- * (Also see HARE trick below, which makes the TableIndex unique per table).
- *
- * Each element has a key (N bytes) and possible additional info.
- *
- * Two elements with the same key should be the same element.
- *
- * The storage for the Key and Info cannot move, the table itself can.
- *
- * The hash table will only be allocated if we have keys, and will resize
- * when the table needs to resize. The hash buckets just provide the
- * reference to the first TableIndex in the hash bucket, the next
- * field of the TableElement takes you to the next item in the hash
- * bucket. Lookups will drift the looked up item to the head of the
- * list.
- *
- * The full 32bit hashcode and key length is saved for comparisons, the
- * last thing done is the actual comparison of the Key contents with
- * keys_equal().
- *
- * Freed elements (not many tables actually free items) are managed with
- * a bit vector and a low index where a freed element might be found.
- * Bytes are inspected until a non-zero byte indicates a freed bit is
- * set. A count of freed elements is also kept.
- *
- */
-
-#include "hprof.h"
-
-/* Macros for bit vectors: unsigned char 2^3==8 OR unsigned int 2^5==32 */
-
-#define BV_CHUNK_POWER_2 3 /* 2 to this power == BV_CHUNK_BITSIZE */
-#define BV_CHUNK_TYPE unsigned char
-
-#define BV_CHUNK_BITSIZE (((int)sizeof(BV_CHUNK_TYPE))<<3) /* x8 */
-#define BV_CHUNK_INDEX_MASK ( (1 << BV_CHUNK_POWER_2) - 1 )
-#define BV_ELEMENT_COUNT(nelems) ((((nelems+1)) >> BV_CHUNK_POWER_2) + 1)
-
-#define BV_CHUNK_ROUND(i) ((i) & ~(BV_CHUNK_INDEX_MASK))
-#define BV_CHUNK(ptr, i) \
- (((BV_CHUNK_TYPE*)(ptr))[(i) >> BV_CHUNK_POWER_2])
-#define BV_CHUNK_MASK(i) \
- (1 << ((i) & BV_CHUNK_INDEX_MASK))
-
-/* Hash code value */
-
-typedef unsigned HashCode;
-
-/* Basic key for an element. What makes the element unique. */
-
-typedef struct TableKey {
- void *ptr; /* Pointer to arbitrary data that forms the key. */
- int len; /* Length in bytes of this key. */
-} TableKey;
-
-/* Basic TableElement (but only allocated if keys are used) */
-
-typedef struct TableElement {
- TableKey key; /* The element key. */
- HashCode hcode; /* The full 32bit hashcode for the key. */
- TableIndex next; /* The next TableElement in the hash bucket chain. */
- void *info; /* Info pointer */
-} TableElement;
-
-/* Generic Lookup Table structure */
-
-typedef struct LookupTable {
- char name[48]; /* Name of table. */
- void *table; /* Pointer to array of elements. */
- TableIndex *hash_buckets; /* Pointer to hash bucket chains. */
- Blocks *info_blocks; /* Blocks space for info */
- Blocks *key_blocks; /* Blocks space for keys */
- TableIndex next_index; /* Next element available. */
- TableIndex table_size; /* Current size of table. */
- TableIndex table_incr; /* Suggested increment size. */
- TableIndex hash_bucket_count; /* Number of hash buckets. */
- int elem_size; /* Size of element. */
- int info_size; /* Size of info structure (can be 0). */
- void *freed_bv; /* Freed element bit vector */
- int freed_count; /* Count of freed'd elements */
- TableIndex freed_start; /* First freed in table */
- int resizes; /* Count of table resizes done. */
- unsigned bucket_walks; /* Count of bucket walks. */
- jrawMonitorID lock; /* Lock for table access. */
- SerialNumber serial_num; /* Table serial number. */
- TableIndex hare; /* Rabbit (HARE) trick. */
-} LookupTable;
-
-/* To get a pointer to an element, regardless of element size. */
-
-#define ELEMENT_PTR(ltable, i) \
- ((void*)(((char*)(ltable)->table) + (ltable)->elem_size * (i)))
-
-/* Sanity, check all the time. */
-
-#define SANITY_CHECK(condition) ( (condition) ? (void)0 : \
- HPROF_ERROR(JNI_FALSE, "SANITY IN QUESTION: " #condition))
-
-/* To see if an index is valid. */
-
-#define SANITY_CHECK_INDEX(ltable,i) SANITY_CHECK((i) < ltable->next_index)
-
-/* Small rabbits (hares) can be hidden in the index value returned.
- * Only the right rabbits are allowed in certain pens (LookupTables).
- * When herding rabbits it's important to keep them separate,
- * there are lots of rabbits, all different kinds and sizes,
- * keeping them all separate is important to avoid cross breeding.
- */
-
-#define _SANITY_USE_HARE
-#ifdef _SANITY_USE_HARE
- #define SANITY_ADD_HARE(i,hare) (SANITY_REMOVE_HARE(i) | (hare))
- #define SANITY_REMOVE_HARE(i) ((i) & 0x0FFFFFFF)
- #define SANITY_CHECK_HARE(i,hare) SANITY_CHECK(SANITY_ADD_HARE(i,hare)==(i))
-#else
- #define SANITY_ADD_HARE(i,hare) (i)
- #define SANITY_REMOVE_HARE(i) (i)
- #define SANITY_CHECK_HARE(i,hare)
-#endif
-
-static jrawMonitorID
-lock_create(char *name)
-{
- jrawMonitorID stanley;
-
- stanley = createRawMonitor(name);
- return stanley;
-}
-
-static void
-lock_destroy(jrawMonitorID stanley)
-{
- if ( stanley != NULL ) {
- destroyRawMonitor(stanley);
- }
-}
-
-static void
-lock_enter(jrawMonitorID stanley)
-{
- if ( stanley != NULL ) {
- rawMonitorEnter(stanley);
- }
-}
-
-static void
-lock_exit(jrawMonitorID stanley)
-{
- if ( stanley != NULL ) {
- rawMonitorExit(stanley);
- }
-}
-
-static void
-get_key(LookupTable *ltable, TableIndex index, void **pkey_ptr, int *pkey_len)
-{
- *pkey_ptr = ((TableElement*)ELEMENT_PTR(ltable,index))->key.ptr;
- *pkey_len = ((TableElement*)ELEMENT_PTR(ltable,index))->key.len;
-}
-
-static void *
-get_info(LookupTable *ltable, TableIndex index)
-{
- TableElement *element;
-
- element = (TableElement*)ELEMENT_PTR(ltable,index);
- return element->info;
-}
-
-static void
-hash_out(LookupTable *ltable, TableIndex index)
-{
- if ( ltable->hash_bucket_count > 0 ) {
- TableElement *element;
- TableElement *prev_e;
- TableIndex bucket;
- TableIndex i;
-
- element = (TableElement*)ELEMENT_PTR(ltable,index);
- bucket = (element->hcode % ltable->hash_bucket_count);
- i = ltable->hash_buckets[bucket];
- HPROF_ASSERT(i!=0);
- prev_e = NULL;
- while ( i != 0 && i != index ) {
- prev_e = (TableElement*)ELEMENT_PTR(ltable,i);
- i = prev_e->next;
- }
- HPROF_ASSERT(i==index);
- if ( prev_e == NULL ) {
- ltable->hash_buckets[bucket] = element->next;
- } else {
- prev_e->next = element->next;
- }
- element->next = 0;
- element->hcode = 0;
- }
-}
-
-static jboolean
-is_freed_entry(LookupTable *ltable, TableIndex index)
-{
- if ( ltable->freed_bv == NULL ) {
- return JNI_FALSE;
- }
- if ( ( BV_CHUNK(ltable->freed_bv, index) & BV_CHUNK_MASK(index) ) != 0 ) {
- return JNI_TRUE;
- }
- return JNI_FALSE;
-}
-
-static void
-set_freed_bit(LookupTable *ltable, TableIndex index)
-{
- void *p;
-
- HPROF_ASSERT(!is_freed_entry(ltable, index));
- p = ltable->freed_bv;
- if ( p == NULL ) {
- int size;
-
- /* First time for a free */
- HPROF_ASSERT(ltable->freed_start==0);
- HPROF_ASSERT(ltable->freed_start==0);
- size = BV_ELEMENT_COUNT(ltable->table_size);
- p = HPROF_MALLOC(size*(int)sizeof(BV_CHUNK_TYPE));
- ltable->freed_bv = p;
- (void)memset(p, 0, size*(int)sizeof(BV_CHUNK_TYPE));
- }
- BV_CHUNK(p, index) |= BV_CHUNK_MASK(index);
- ltable->freed_count++;
- if ( ltable->freed_count == 1 ) {
- /* Set freed_start for first time. */
- HPROF_ASSERT(ltable->freed_start==0);
- ltable->freed_start = index;
- } else if ( index < ltable->freed_start ) {
- /* Set freed_start to smaller value so we can be smart about search */
- HPROF_ASSERT(ltable->freed_start!=0);
- ltable->freed_start = index;
- }
- HPROF_ASSERT(ltable->freed_start!=0);
- HPROF_ASSERT(ltable->freed_start < ltable->next_index);
- HPROF_ASSERT(is_freed_entry(ltable, index));
-}
-
-static TableIndex
-find_freed_entry(LookupTable *ltable)
-{
- if ( ltable->freed_count > 0 ) {
- TableIndex i;
- TableIndex istart;
- void *p;
- BV_CHUNK_TYPE chunk;
-
- HPROF_ASSERT(BV_CHUNK_BITSIZE==(1<<BV_CHUNK_POWER_2));
-
- p = ltable->freed_bv;
- HPROF_ASSERT(p!=NULL);
-
- /* Go to beginning of chunk */
- HPROF_ASSERT(ltable->freed_start!=0);
- HPROF_ASSERT(ltable->freed_start < ltable->next_index);
- istart = BV_CHUNK_ROUND(ltable->freed_start);
-
- /* Find chunk with any bit set */
- chunk = 0;
- for( ; istart < ltable->next_index ; istart += BV_CHUNK_BITSIZE ) {
- chunk = BV_CHUNK(p, istart);
- if ( chunk != 0 ) {
- break;
- }
- }
- HPROF_ASSERT(chunk!=0);
- HPROF_ASSERT(chunk==BV_CHUNK(p,istart));
- HPROF_ASSERT(istart < ltable->next_index);
-
- /* Find bit in chunk and return index of freed item */
- for( i = istart ; i < (istart+BV_CHUNK_BITSIZE) ; i++) {
- BV_CHUNK_TYPE mask;
-
- mask = BV_CHUNK_MASK(i);
- if ( (chunk & mask) != 0 ) {
- HPROF_ASSERT(chunk==BV_CHUNK(p,i));
- chunk &= ~mask;
- BV_CHUNK(p, i) = chunk;
- ltable->freed_count--;
- HPROF_ASSERT(i < ltable->next_index);
- if ( ltable->freed_count > 0 ) {
- /* Set freed_start so we can be smart about search */
- HPROF_ASSERT((i+1) < ltable->next_index);
- ltable->freed_start = i+1;
- } else {
- /* Clear freed_start because there are no freed entries */
- ltable->freed_start = 0;
- }
- HPROF_ASSERT(!is_freed_entry(ltable, i));
- return i;
- }
- }
- HPROF_ASSERT(0);
- }
- return 0;
-}
-
-static void
-free_entry(LookupTable *ltable, TableIndex index)
-{
- set_freed_bit(ltable, index);
- hash_out(ltable, index);
-}
-
-/* Fairly generic hash code generator (not a hash table index) */
-static HashCode
-hashcode(void *key_ptr, int key_len)
-{
- unsigned char * p;
- HashCode hcode;
- int i;
-
- hcode = 0;
- if ( key_ptr == NULL || key_len == 0 ) {
- return hcode;
- }
- i = 0;
- p = (unsigned char*)key_ptr;
- for ( ; i < key_len-3 ; i += 4 ) {
- /* Do a little loop unrolling */
- hcode += (
- ( (unsigned)(p[i]) << 24 ) |
- ( (unsigned)(p[i+1]) << 16 ) |
- ( (unsigned)(p[i+2]) << 8 ) |
- ( (unsigned)(p[i+3]) )
- );
- }
- for ( ; i < key_len ; i++ ) {
- hcode += (unsigned)(p[i]);
- }
- return hcode;
-}
-
-static void
-hash_in(LookupTable *ltable, TableIndex index, HashCode hcode)
-{
- if ( ltable->hash_bucket_count > 0 ) {
- TableElement *element;
- TableIndex bucket;
-
- bucket = (hcode % ltable->hash_bucket_count);
- element = (TableElement*)ELEMENT_PTR(ltable, index);
- element->hcode = hcode;
- element->next = ltable->hash_buckets[bucket];
- ltable->hash_buckets[bucket] = index;
- }
-}
-
-static void
-resize_hash_buckets(LookupTable *ltable)
-{
- /* Don't want to do this too often. */
-
- /* Hash table needs resizing when it's smaller than 1/16 the number of
- * elements used in the table. This is just a guess.
- */
- if ( ( ltable->hash_bucket_count < (ltable->next_index >> 4) )
- && ( ltable->hash_bucket_count > 0 )
- && ( ( ltable->resizes % 10 ) == 0 )
- && ( ltable->bucket_walks > 1000*ltable->hash_bucket_count )
- ) {
- int old_size;
- int new_size;
- TableIndex *new_buckets;
- TableIndex *old_buckets;
- int bucket;
-
- /* Increase size of hash_buckets array, and rehash all elements */
-
- LOG3("Table resize", ltable->name, ltable->resizes);
-
- old_size = ltable->hash_bucket_count;
- old_buckets = ltable->hash_buckets;
- new_size = (ltable->next_index >> 3); /* 1/8 current used count */
- SANITY_CHECK(new_size > old_size);
- new_buckets = HPROF_MALLOC(new_size*(int)sizeof(TableIndex));
- (void)memset(new_buckets, 0, new_size*(int)sizeof(TableIndex));
- ltable->hash_bucket_count = new_size;
- ltable->hash_buckets = new_buckets;
-
- for ( bucket = 0 ; bucket < old_size ; bucket++ ) {
- TableIndex index;
-
- index = old_buckets[bucket];
- while ( index != 0 ) {
- TableElement *element;
- TableIndex next;
-
- element = (TableElement*)ELEMENT_PTR(ltable, index);
- next = element->next;
- element->next = 0;
- hash_in(ltable, index, element->hcode);
- index = next;
- }
- }
- HPROF_FREE(old_buckets);
-
- ltable->bucket_walks = 0;
- }
-}
-
-static void
-resize(LookupTable *ltable)
-{
- int old_size;
- int new_size;
- void *old_table;
- void *new_table;
- int nbytes;
- int obytes;
-
- LOG3("Table resize", ltable->name, ltable->resizes);
-
- /* Adjust increment on every resize
- * Minimum is 1/4 the size of the current table or 512.
- */
- old_size = ltable->table_size;
- if ( ltable->table_incr < (unsigned)(old_size >> 2) ) {
- ltable->table_incr = (old_size >> 2);
- }
- if ( ltable->table_incr < 512 ) {
- ltable->table_incr = 512;
- }
- new_size = old_size + ltable->table_incr;
-
- /* Basic table element array */
- obytes = old_size * ltable->elem_size;
- nbytes = new_size * ltable->elem_size;
- old_table = ltable->table;
- new_table = HPROF_MALLOC(nbytes);
- (void)memcpy(new_table, old_table, obytes);
- (void)memset(((char*)new_table)+obytes, 0, nbytes-obytes);
- ltable->table = new_table;
- ltable->table_size = new_size;
- HPROF_FREE(old_table);
-
- /* Then bit vector for freed entries */
- if ( ltable->freed_bv != NULL ) {
- void *old_bv;
- void *new_bv;
-
- obytes = BV_ELEMENT_COUNT(old_size)*(int)sizeof(BV_CHUNK_TYPE);
- nbytes = BV_ELEMENT_COUNT(new_size)*(int)sizeof(BV_CHUNK_TYPE);
- old_bv = ltable->freed_bv;
- new_bv = HPROF_MALLOC(nbytes);
- (void)memcpy(new_bv, old_bv, obytes);
- (void)memset(((char*)new_bv)+obytes, 0, nbytes-obytes);
- ltable->freed_bv = new_bv;
- HPROF_FREE(old_bv);
- }
-
- /* Check to see if the hash table needs resizing */
- resize_hash_buckets(ltable);
-
- ltable->resizes++;
-}
-
-static jboolean
-keys_equal(void *key_ptr1, void *key_ptr2, int key_len)
-{
- unsigned char * p1;
- unsigned char * p2;
- int i;
-
- if ( key_len == 0 ) {
- return JNI_TRUE;
- }
-
- /* We know these are aligned because we malloc'd them. */
-
- /* Compare word by word, then byte by byte */
- p1 = (unsigned char*)key_ptr1;
- p2 = (unsigned char*)key_ptr2;
- for ( i = 0 ; i < key_len-3 ; i += 4 ) {
- /*LINTED*/
- if ( *(unsigned*)(p1+i) != *(unsigned*)(p2+i) ) {
- return JNI_FALSE;
- }
- }
- for ( ; i < key_len ; i++ ) {
- if ( p1[i] != p2[i] ) {
- return JNI_FALSE;
- }
- }
- return JNI_TRUE;
-}
-
-static TableIndex
-find_entry(LookupTable *ltable, void *key_ptr, int key_len, HashCode hcode)
-{
- TableIndex index;
-
- HPROF_ASSERT(ltable!=NULL);
-
- index = 0;
- if ( ltable->hash_bucket_count > 0 ) {
- TableIndex bucket;
- TableIndex prev_index;
-
- HPROF_ASSERT(key_ptr!=NULL);
- HPROF_ASSERT(key_len>0);
- prev_index = 0;
- bucket = (hcode % ltable->hash_bucket_count);
- index = ltable->hash_buckets[bucket];
- while ( index != 0 ) {
- TableElement *element;
- TableElement *prev_element;
-
- element = (TableElement*)ELEMENT_PTR(ltable, index);
- if ( hcode == element->hcode &&
- key_len == element->key.len &&
- keys_equal(key_ptr, element->key.ptr, key_len) ) {
- /* Place this guy at the head of the bucket list */
- if ( prev_index != 0 ) {
- prev_element = (TableElement*)ELEMENT_PTR(ltable, prev_index);
- prev_element->next = element->next;
- element->next = ltable->hash_buckets[bucket];
- ltable->hash_buckets[bucket] = index;
- }
- break;
- }
- prev_index = index;
- index = element->next;
- ltable->bucket_walks++;
- }
- }
- return index;
-}
-
-static TableIndex
-setup_new_entry(LookupTable *ltable, void *key_ptr, int key_len, void *info_ptr)
-{
- TableIndex index;
- TableElement *element;
- void *info;
- void *dup_key;
-
- /* Assume we need new allocations for key and info */
- dup_key = NULL;
- info = NULL;
-
- /* Look for a freed element */
- index = 0;
- if ( ltable->freed_count > 0 ) {
- index = find_freed_entry(ltable);
- }
- if ( index != 0 ) {
- int old_key_len;
-
- /* Found a freed element, re-use what we can but clean it up. */
- element = (TableElement*)ELEMENT_PTR(ltable, index);
- dup_key = element->key.ptr;
- old_key_len = element->key.len;
- info = element->info;
- (void)memset(element, 0, ltable->elem_size);
-
- /* Toss the key space if size is too small to hold new key */
- if ( key_ptr != NULL ) {
- if ( old_key_len < key_len ) {
- /* This could leak space in the Blocks if keys are variable
- * in size AND the table does frees of elements.
- */
- dup_key = NULL;
- }
- }
- } else {
-
- /* Brand new table element */
- if ( ltable->next_index >= ltable->table_size ) {
- resize(ltable);
- }
- index = ltable->next_index++;
- element = (TableElement*)ELEMENT_PTR(ltable, index);
- }
-
- /* Setup info area */
- if ( ltable->info_size > 0 ) {
- if ( info == NULL ) {
- info = blocks_alloc(ltable->info_blocks, ltable->info_size);
- }
- if ( info_ptr==NULL ) {
- (void)memset(info, 0, ltable->info_size);
- } else {
- (void)memcpy(info, info_ptr, ltable->info_size);
- }
- }
-
- /* Setup key area if one was provided */
- if ( key_ptr != NULL ) {
- if ( dup_key == NULL ) {
- dup_key = blocks_alloc(ltable->key_blocks, key_len);
- }
- (void)memcpy(dup_key, key_ptr, key_len);
- }
-
- /* Fill in element */
- element->key.ptr = dup_key;
- element->key.len = key_len;
- element->info = info;
-
- return index;
-}
-
-LookupTable *
-table_initialize(const char *name, int size, int incr, int bucket_count,
- int info_size)
-{
- LookupTable * ltable;
- char lock_name[80];
- int elem_size;
- int key_size;
-
- HPROF_ASSERT(name!=NULL);
- HPROF_ASSERT(size>0);
- HPROF_ASSERT(incr>0);
- HPROF_ASSERT(bucket_count>=0);
- HPROF_ASSERT(info_size>=0);
-
- key_size = 1;
- ltable = (LookupTable *)HPROF_MALLOC((int)sizeof(LookupTable));
- (void)memset(ltable, 0, (int)sizeof(LookupTable));
-
- (void)strncpy(ltable->name, name, sizeof(ltable->name));
-
- elem_size = (int)sizeof(TableElement);
-
- ltable->next_index = 1; /* Never use index 0 */
- ltable->table_size = size;
- ltable->table_incr = incr;
- ltable->hash_bucket_count = bucket_count;
- ltable->elem_size = elem_size;
- ltable->info_size = info_size;
- if ( info_size > 0 ) {
- ltable->info_blocks = blocks_init(8, info_size, incr);
- }
- if ( key_size > 0 ) {
- ltable->key_blocks = blocks_init(8, key_size, incr);
- }
- ltable->table = HPROF_MALLOC(size * elem_size);
- (void)memset(ltable->table, 0, size * elem_size);
- if ( bucket_count > 0 ) {
- int nbytes;
-
- nbytes = (int)(bucket_count*sizeof(TableIndex));
- ltable->hash_buckets = (TableIndex*)HPROF_MALLOC(nbytes);
- (void)memset(ltable->hash_buckets, 0, nbytes);
- }
-
- (void)md_snprintf(lock_name, sizeof(lock_name),
- "HPROF %s table lock", name);
- lock_name[sizeof(lock_name)-1] = 0;
- ltable->lock = lock_create(lock_name);
- ltable->serial_num = gdata->table_serial_number_counter++;
- ltable->hare = (ltable->serial_num << 28);
-
- LOG3("Table initialized", ltable->name, ltable->table_size);
- return ltable;
-}
-
-int
-table_element_count(LookupTable *ltable)
-{
- int nelems;
-
- HPROF_ASSERT(ltable!=NULL);
-
- lock_enter(ltable->lock); {
- nelems = ltable->next_index-1;
- } lock_exit(ltable->lock);
-
- return nelems;
-}
-
-void
-table_free_entry(LookupTable *ltable, TableIndex index)
-{
- HPROF_ASSERT(ltable!=NULL);
- SANITY_CHECK_HARE(index, ltable->hare);
- index = SANITY_REMOVE_HARE(index);
- SANITY_CHECK_INDEX(ltable, index);
-
- lock_enter(ltable->lock); {
- HPROF_ASSERT(!is_freed_entry(ltable, index));
- free_entry(ltable, index);
- } lock_exit(ltable->lock);
-}
-
-void
-table_walk_items(LookupTable *ltable, LookupTableIterator func, void* arg)
-{
- if ( ltable == NULL || ltable->next_index <= 1 ) {
- return;
- }
- HPROF_ASSERT(func!=NULL);
-
- lock_enter(ltable->lock); {
- TableIndex index;
- int fcount;
-
- LOG3("table_walk_items() count+free", ltable->name, ltable->next_index);
- fcount = 0;
- for ( index = 1 ; index < ltable->next_index ; index++ ) {
- if ( ! is_freed_entry(ltable, index) ) {
- void *key_ptr;
- int key_len;
- void *info;
-
- get_key(ltable, index, &key_ptr, &key_len);
- if ( ltable->info_size == 0 ) {
- info = NULL;
- } else {
- info = get_info(ltable, index);
- }
- (*func)(SANITY_ADD_HARE(index, ltable->hare), key_ptr, key_len, info, arg);
- if ( is_freed_entry(ltable, index) ) {
- fcount++;
- }
- } else {
- fcount++;
- }
- }
- LOG3("table_walk_items() count-free", ltable->name, ltable->next_index);
- HPROF_ASSERT(fcount==ltable->freed_count);
- } lock_exit(ltable->lock);
-}
-
-void
-table_cleanup(LookupTable *ltable, LookupTableIterator func, void *arg)
-{
- if ( ltable == NULL ) {
- return;
- }
-
- if ( func != NULL ) {
- table_walk_items(ltable, func, arg);
- }
-
- lock_enter(ltable->lock); {
-
- HPROF_FREE(ltable->table);
- if ( ltable->hash_buckets != NULL ) {
- HPROF_FREE(ltable->hash_buckets);
- }
- if ( ltable->freed_bv != NULL ) {
- HPROF_FREE(ltable->freed_bv);
- }
- if ( ltable->info_blocks != NULL ) {
- blocks_term(ltable->info_blocks);
- ltable->info_blocks = NULL;
- }
- if ( ltable->key_blocks != NULL ) {
- blocks_term(ltable->key_blocks);
- ltable->key_blocks = NULL;
- }
-
- } lock_exit(ltable->lock);
-
- lock_destroy(ltable->lock);
- ltable->lock = NULL;
-
- HPROF_FREE(ltable);
- ltable = NULL;
-}
-
-TableIndex
-table_create_entry(LookupTable *ltable, void *key_ptr, int key_len, void *info_ptr)
-{
- TableIndex index;
- HashCode hcode;
-
- HPROF_ASSERT(ltable!=NULL);
-
- /* Create hash code if needed */
- hcode = 0;
- if ( ltable->hash_bucket_count > 0 ) {
- hcode = hashcode(key_ptr, key_len);
- }
-
- /* Create a new entry */
- lock_enter(ltable->lock); {
-
- /* Need to create a new entry */
- index = setup_new_entry(ltable, key_ptr, key_len, info_ptr);
-
- /* Add to hash table if we have one */
- if ( ltable->hash_bucket_count > 0 ) {
- hash_in(ltable, index, hcode);
- }
-
- } lock_exit(ltable->lock);
- return SANITY_ADD_HARE(index, ltable->hare);
-}
-
-TableIndex
-table_find_entry(LookupTable *ltable, void *key_ptr, int key_len)
-{
- TableIndex index;
- HashCode hcode;
-
- /* Create hash code if needed */
- hcode = 0;
- if ( ltable->hash_bucket_count > 0 ) {
- hcode = hashcode(key_ptr, key_len);
- }
-
- /* Look for element */
- lock_enter(ltable->lock); {
- index = find_entry(ltable, key_ptr, key_len, hcode);
- } lock_exit(ltable->lock);
-
- return index==0 ? index : SANITY_ADD_HARE(index, ltable->hare);
-}
-
-TableIndex
-table_find_or_create_entry(LookupTable *ltable, void *key_ptr, int key_len,
- jboolean *pnew_entry, void *info_ptr)
-{
- TableIndex index;
- HashCode hcode;
-
- /* Assume it is NOT a new entry for now */
- if ( pnew_entry ) {
- *pnew_entry = JNI_FALSE;
- }
-
- /* Create hash code if needed */
- hcode = 0;
- if ( ltable->hash_bucket_count > 0 ) {
- hcode = hashcode(key_ptr, key_len);
- }
-
- /* Look for element */
- index = 0;
- lock_enter(ltable->lock); {
- if ( ltable->hash_bucket_count > 0 ) {
- index = find_entry(ltable, key_ptr, key_len, hcode);
- }
- if ( index == 0 ) {
-
- /* Need to create a new entry */
- index = setup_new_entry(ltable, key_ptr, key_len, info_ptr);
-
- /* Add to hash table if we have one */
- if ( ltable->hash_bucket_count > 0 ) {
- hash_in(ltable, index, hcode);
- }
-
- if ( pnew_entry ) {
- *pnew_entry = JNI_TRUE;
- }
- }
- } lock_exit(ltable->lock);
-
- return SANITY_ADD_HARE(index, ltable->hare);
-}
-
-void *
-table_get_info(LookupTable *ltable, TableIndex index)
-{
- void *info;
-
- HPROF_ASSERT(ltable!=NULL);
- HPROF_ASSERT(ltable->info_size > 0);
- SANITY_CHECK_HARE(index, ltable->hare);
- index = SANITY_REMOVE_HARE(index);
- SANITY_CHECK_INDEX(ltable, index);
-
- lock_enter(ltable->lock); {
- HPROF_ASSERT(!is_freed_entry(ltable, index));
- info = get_info(ltable,index);
- } lock_exit(ltable->lock);
-
- return info;
-}
-
-void
-table_get_key(LookupTable *ltable, TableIndex index, void **pkey_ptr, int *pkey_len)
-{
- HPROF_ASSERT(ltable!=NULL);
- HPROF_ASSERT(pkey_ptr!=NULL);
- HPROF_ASSERT(pkey_len!=NULL);
- SANITY_CHECK_HARE(index, ltable->hare);
- HPROF_ASSERT(ltable->elem_size!=0);
- index = SANITY_REMOVE_HARE(index);
- SANITY_CHECK_INDEX(ltable, index);
-
- lock_enter(ltable->lock); {
- HPROF_ASSERT(!is_freed_entry(ltable, index));
- get_key(ltable, index, pkey_ptr, pkey_len);
- } lock_exit(ltable->lock);
-}
-
-void
-table_lock_enter(LookupTable *ltable)
-{
- lock_enter(ltable->lock);
-}
-
-void
-table_lock_exit(LookupTable *ltable)
-{
- lock_exit(ltable->lock);
-}
--- a/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_table.h Thu Aug 20 12:29:58 2015 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,75 +0,0 @@
-/*
- * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * - Neither the name of Oracle nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
- * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/*
- * This source code is provided to illustrate the usage of a given feature
- * or technique and has been deliberately simplified. Additional steps
- * required for a production-quality application, such as security checks,
- * input validation and proper error handling, might not be present in
- * this sample code.
- */
-
-
-#ifndef HPROF_TABLE_H
-#define HPROF_TABLE_H
-
-/* Key based generic lookup table */
-
-struct LookupTable;
-
-typedef void (*LookupTableIterator)
- (TableIndex, void *key_ptr, int key_len, void*, void*);
-
-struct LookupTable * table_initialize(const char *name, int size,
- int incr, int buckets, int esize);
-int table_element_count(struct LookupTable *ltable);
-TableIndex table_create_entry(struct LookupTable *ltable,
- void *key_ptr, int key_len, void *info_ptr);
-TableIndex table_find_entry(struct LookupTable *ltable,
- void *key_ptr, int key_len);
-TableIndex table_find_or_create_entry(struct LookupTable *ltable,
- void *key_ptr, int key_len,
- jboolean *pnew_entry, void *info_ptr);
-void table_free_entry(struct LookupTable *ltable,
- TableIndex index);
-void table_cleanup(struct LookupTable *ltable,
- LookupTableIterator func, void *arg);
-void table_walk_items(struct LookupTable *ltable,
- LookupTableIterator func, void *arg);
-void * table_get_info(struct LookupTable *ltable,
- TableIndex index);
-void table_get_key(struct LookupTable *ltable,
- TableIndex index, void **pkey_ptr,
- int *pkey_len);
-void table_lock_enter(struct LookupTable *ltable);
-void table_lock_exit(struct LookupTable *ltable);
-
-#endif
--- a/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_tag.c Thu Aug 20 12:29:58 2015 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,134 +0,0 @@
-/*
- * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * - Neither the name of Oracle nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
- * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/*
- * This source code is provided to illustrate the usage of a given feature
- * or technique and has been deliberately simplified. Additional steps
- * required for a production-quality application, such as security checks,
- * input validation and proper error handling, might not be present in
- * this sample code.
- */
-
-
-/* JVMTI tag definitions. */
-
-/*
- * JVMTI tags are jlongs (64 bits) and how the hprof information is
- * turned into a tag and/or extracted from a tag is here.
- *
- * Currently a special TAG_CHECK is placed in the high order 32 bits of
- * the tag as a check.
- *
- */
-
-#include "hprof.h"
-
-#define TAG_CHECK 0xfad4dead
-
-jlong
-tag_create(ObjectIndex object_index)
-{
- jlong tag;
-
- HPROF_ASSERT(object_index != 0);
- tag = TAG_CHECK;
- tag = (tag << 32) | object_index;
- return tag;
-}
-
-ObjectIndex
-tag_extract(jlong tag)
-{
- HPROF_ASSERT(tag != (jlong)0);
- if ( ((tag >> 32) & 0xFFFFFFFF) != TAG_CHECK) {
- HPROF_ERROR(JNI_TRUE, "JVMTI tag value is not 0 and missing TAG_CHECK");
- }
- return (ObjectIndex)(tag & 0xFFFFFFFF);
-}
-
-/* Tag a new jobject */
-void
-tag_new_object(jobject object, ObjectKind kind, SerialNumber thread_serial_num,
- jint size, SiteIndex site_index)
-{
- ObjectIndex object_index;
- jlong tag;
-
- HPROF_ASSERT(site_index!=0);
- /* New object for this site. */
- object_index = object_new(site_index, size, kind, thread_serial_num);
- /* Create and set the tag. */
- tag = tag_create(object_index);
- setTag(object, tag);
- LOG3("tag_new_object", "tag", (int)tag);
-}
-
-/* Tag a jclass jobject if it hasn't been tagged. */
-void
-tag_class(JNIEnv *env, jclass klass, ClassIndex cnum,
- SerialNumber thread_serial_num, SiteIndex site_index)
-{
- ObjectIndex object_index;
-
- /* If the ClassIndex has an ObjectIndex, then we have tagged it. */
- object_index = class_get_object_index(cnum);
-
- if ( object_index == 0 ) {
- jint size;
- jlong tag;
-
- HPROF_ASSERT(site_index!=0);
-
- /* If we don't know the size of a java.lang.Class object, get it */
- size = gdata->system_class_size;
- if ( size == 0 ) {
- size = (jint)getObjectSize(klass);
- gdata->system_class_size = size;
- }
-
- /* Tag this java.lang.Class object if it hasn't been already */
- tag = getTag(klass);
- if ( tag == (jlong)0 ) {
- /* New object for this site. */
- object_index = object_new(site_index, size, OBJECT_CLASS,
- thread_serial_num);
- /* Create and set the tag. */
- tag = tag_create(object_index);
- setTag(klass, tag);
- } else {
- /* Get the ObjectIndex from the tag. */
- object_index = tag_extract(tag);
- }
-
- /* Record this object index in the Class table */
- class_set_object_index(cnum, object_index);
- }
-}
--- a/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_tag.h Thu Aug 20 12:29:58 2015 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,53 +0,0 @@
-/*
- * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * - Neither the name of Oracle nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
- * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/*
- * This source code is provided to illustrate the usage of a given feature
- * or technique and has been deliberately simplified. Additional steps
- * required for a production-quality application, such as security checks,
- * input validation and proper error handling, might not be present in
- * this sample code.
- */
-
-
-#ifndef HPROF_TAG_H
-#define HPROF_TAG_H
-
-jlong tag_create(ObjectIndex object_index);
-ObjectIndex tag_extract(jlong tag);
-
-void tag_new_object(jobject object, ObjectKind kind,
- SerialNumber thread_serial_num,
- jint size, SiteIndex site_index);
-void tag_class(JNIEnv *env, jclass klass, ClassIndex cnum,
- SerialNumber thread_serial_num, SiteIndex site_index);
-
-#endif
--- a/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_tls.c Thu Aug 20 12:29:58 2015 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,1190 +0,0 @@
-/*
- * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * - Neither the name of Oracle nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
- * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/*
- * This source code is provided to illustrate the usage of a given feature
- * or technique and has been deliberately simplified. Additional steps
- * required for a production-quality application, such as security checks,
- * input validation and proper error handling, might not be present in
- * this sample code.
- */
-
-
-#include "hprof.h"
-
-/* Thread Local Storage Table and method entry/exit handling. */
-
-/*
- * The tls table items have a key of it's serial number, but may be
- * searched via a walk of the table looking for a jthread match.
- * This isn't a performance
- * issue because the table index should normally be stored in the
- * Thread Local Storage for the thread. The table is only searched
- * when the jthread is seen before the Thread Local Storage is set
- * (e.g. before VM_INIT or the ThreadStart).
- * The key is only used when we need to lookup a tls table entry by
- * way of it's serial number, which should be unique per thread.
- *
- * Each active thread that we have seen should have a unique TlsIndex
- * which is an index into this table.
- *
- * For cpu=times, each table entry will have a stack to hold the method
- * that have been called, effectively keeping an active stack trace
- * for the thread. As each method exits, the statistics for the trace
- * associated with the current stack contents is updated.
- *
- * For cpu=samples, each thread is checked to see if it's runnable,
- * and not suspended, and has a stack associated with it, and then
- * that stack trace is updated with an additional 'hit'.
- *
- * This file also contains the dump logic for owned monitors, and for
- * threads.
- *
- */
-
-/*
- * Initial number of stack elements to track per thread. This
- * value should be set to a reasonable guess as to the number of
- * methods deep a thread calls. This stack doubles in size for each
- * reallocation and does not shrink.
- */
-
-#define INITIAL_THREAD_STACK_LIMIT 64
-
-typedef struct StackElement {
- FrameIndex frame_index; /* Frame (method/location(-1)) */
- jmethodID method; /* Method ID */
- jlong method_start_time; /* method start time */
- jlong time_in_callees; /* time in callees */
-} StackElement;
-
-typedef struct TlsInfo {
- jint sample_status; /* Thread status for cpu sampling */
- jboolean agent_thread; /* Is thread our own agent thread? */
- jthread globalref; /* Global reference for thread */
- Stack *stack; /* Stack of StackElements entry/exit */
- MonitorIndex monitor_index; /* last contended mon */
- jint tracker_status; /* If we are inside Tracker class */
- FrameIndex *frames_buffer; /* Buffer used to create TraceIndex */
- jvmtiFrameInfo *jframes_buffer; /* Buffer used to create TraceIndex */
- int buffer_depth; /* Frames allowed in buffer */
- TraceIndex last_trace; /* Last trace for this thread */
- ObjectIndex thread_object_index;/* If heap=dump */
- jlong monitor_start_time; /* Start time for monitor */
- jint in_heap_dump; /* If we are an object in the dump */
-} TlsInfo;
-
-typedef struct SearchData {
- JNIEnv *env;
- jthread thread;
- TlsIndex found;
-} SearchData;
-
-typedef struct IterateInfo {
- TlsIndex * ptls_index;
- jthread * pthreads;
- jint count;
-} IterateInfo;
-
-typedef struct ThreadList {
- jthread *threads;
- SerialNumber *serial_nums;
- TlsInfo **infos;
- jint count;
- JNIEnv *env;
-} ThreadList;
-
-typedef struct SampleData {
- ObjectIndex thread_object_index;
- jint sample_status;
-} SampleData;
-
-/* Private internal functions. */
-
-static SerialNumber
-get_key(TlsIndex index)
-{
- SerialNumber *pkey;
- int key_len;
-
- if ( index == 0 ) {
- return 0;
- }
- pkey = NULL;
- key_len = 0;
- table_get_key(gdata->tls_table, index, (void**)&pkey, &key_len);
- HPROF_ASSERT(pkey!=NULL);
- HPROF_ASSERT(key_len==(int)sizeof(SerialNumber));
- return *pkey;
-}
-
-static TlsInfo *
-get_info(TlsIndex index)
-{
- return (TlsInfo*)table_get_info(gdata->tls_table, index);
-}
-
-static void
-delete_globalref(JNIEnv *env, TlsInfo *info)
-{
- jthread ref;
-
- HPROF_ASSERT(env!=NULL);
- HPROF_ASSERT(info!=NULL);
- ref = info->globalref;
- info->globalref = NULL;
- if ( ref != NULL ) {
- deleteWeakGlobalReference(env, ref);
- }
-}
-
-static void
-clean_info(TlsInfo *info)
-{
- /* Free up any allocated space in this TlsInfo structure */
- if ( info->stack != NULL ) {
- stack_term(info->stack);
- info->stack = NULL;
- }
- if ( info->frames_buffer != NULL ) {
- HPROF_FREE(info->frames_buffer);
- info->frames_buffer = NULL;
- }
- if ( info->jframes_buffer != NULL ) {
- HPROF_FREE(info->jframes_buffer);
- info->jframes_buffer = NULL;
- }
-}
-
-static void
-cleanup_item(TableIndex index, void *key_ptr, int key_len,
- void *info_ptr, void *arg)
-{
- TlsInfo * info;
-
- info = (TlsInfo*)info_ptr;
- clean_info(info);
-}
-
-static void
-delete_ref_item(TableIndex index, void *key_ptr, int key_len,
- void *info_ptr, void *arg)
-{
- delete_globalref((JNIEnv*)arg, (TlsInfo*)info_ptr);
-}
-
-static void
-list_item(TableIndex index, void *key_ptr, int key_len,
- void *info_ptr, void *arg)
-{
- TlsInfo *info;
-
- HPROF_ASSERT(info_ptr!=NULL);
-
- info = (TlsInfo*)info_ptr;
- debug_message( "Tls 0x%08x: SN=%u, sample_status=%d, agent=%d, "
- "thread=%p, monitor=0x%08x, "
- "tracker_status=%d\n",
- index,
- *(SerialNumber*)key_ptr,
- info->sample_status,
- info->agent_thread,
- (void*)info->globalref,
- info->monitor_index,
- info->tracker_status);
-}
-
-static void
-search_item(TableIndex index, void *key_ptr, int key_len,
- void *info_ptr, void *arg)
-{
- TlsInfo *info;
- SearchData *data;
- jobject lref;
-
- HPROF_ASSERT(info_ptr!=NULL);
- HPROF_ASSERT(arg!=NULL);
- info = (TlsInfo*)info_ptr;
- data = (SearchData*)arg;
- lref = newLocalReference(data->env, info->globalref);
- if ( lref != NULL ) {
- if ( isSameObject(data->env, data->thread, lref) ) {
- HPROF_ASSERT(data->found==0); /* Did we find more than one? */
- data->found = index;
- }
- deleteLocalReference(data->env, lref);
- }
-}
-
-static TlsIndex
-search(JNIEnv *env, jthread thread)
-{
- SearchData data;
-
- HPROF_ASSERT(env!=NULL);
- HPROF_ASSERT(thread!=NULL);
-
- data.env = env;
- data.thread = thread;
- data.found = 0;
- table_walk_items(gdata->tls_table, &search_item, (void*)&data);
- return data.found;
-}
-
-static void
-garbage_collect_item(TableIndex index, void *key_ptr, int key_len,
- void *info_ptr, void *arg)
-{
- TlsInfo *info;
- JNIEnv *env;
- jobject lref;
-
- HPROF_ASSERT(info_ptr!=NULL);
- HPROF_ASSERT(arg!=NULL);
- info = (TlsInfo*)info_ptr;
- env = (JNIEnv*)arg;
- lref = newLocalReference(env, info->globalref);
- if ( lref == NULL ) {
- delete_globalref(env, info);
- clean_info(info);
- table_free_entry(gdata->tls_table, index);
- } else {
- deleteLocalReference(env, lref);
- }
-}
-
-void
-tls_garbage_collect(JNIEnv *env)
-{
- HPROF_ASSERT(env!=NULL);
- rawMonitorEnter(gdata->data_access_lock); {
- table_walk_items(gdata->tls_table, &garbage_collect_item, (void*)env);
- } rawMonitorExit(gdata->data_access_lock);
-}
-
-static void
-sum_sample_status_item(TableIndex index, void *key_ptr, int key_len, void *info_ptr, void *arg)
-{
- TlsInfo *info;
-
- HPROF_ASSERT(info_ptr!=NULL);
- info = (TlsInfo*)info_ptr;
- if ( !info->agent_thread ) {
- (*(jint*)arg) += info->sample_status;
- }
-}
-
-static void
-setup_trace_buffers(TlsInfo *info, int max_depth)
-{
- int nbytes;
- int max_frames;
-
- if ( info->frames_buffer != NULL && info->buffer_depth >= max_depth ) {
- return;
- }
- if ( info->frames_buffer != NULL ) {
- HPROF_FREE(info->frames_buffer);
- }
- if ( info->jframes_buffer != NULL ) {
- HPROF_FREE(info->jframes_buffer);
- }
- info->buffer_depth = max_depth;
- max_frames = max_depth + 4; /* Allow for BCI & <init> */
- nbytes = (int)sizeof(FrameIndex)*(max_frames+1);
- info->frames_buffer = HPROF_MALLOC(nbytes);
- nbytes = (int)sizeof(jvmtiFrameInfo)*(max_frames+1);
- info->jframes_buffer = HPROF_MALLOC(nbytes);
-}
-
-static TraceIndex
-get_trace(jthread thread, SerialNumber thread_serial_num,
- int depth, jboolean skip_init,
- FrameIndex *frames_buffer, jvmtiFrameInfo *jframes_buffer)
-{
- TraceIndex trace_index;
-
- trace_index = gdata->system_trace_index;
- if ( thread != NULL ) {
- trace_index = trace_get_current(thread,
- thread_serial_num, depth, skip_init,
- frames_buffer, jframes_buffer);
- }
- return trace_index;
-}
-
-/* Find thread with certain object index */
-static void
-sample_setter(TableIndex index, void *key_ptr, int key_len, void *info_ptr, void *arg)
-{
- TlsInfo *info;
-
- HPROF_ASSERT(info_ptr!=NULL);
-
- info = (TlsInfo*)info_ptr;
- if ( info->globalref != NULL && !info->agent_thread ) {
- SampleData *data;
-
- data = (SampleData*)arg;
- if ( data->thread_object_index == info->thread_object_index ) {
- info->sample_status = data->sample_status;
- }
- }
-}
-
-/* Get various lists on known threads */
-static void
-get_thread_list(TableIndex index, void *key_ptr, int key_len, void *info_ptr, void *arg)
-{
- SerialNumber thread_serial_num;
- TlsInfo *info;
- ThreadList *list;
- jthread thread;
-
- HPROF_ASSERT(key_ptr!=NULL);
- HPROF_ASSERT(info_ptr!=NULL);
-
- thread_serial_num = *(SerialNumber*)key_ptr;
- info = (TlsInfo*)info_ptr;
- list = (ThreadList*)arg;
- thread = newLocalReference(list->env, info->globalref);
- if ( thread != NULL && info->sample_status != 0 && !info->agent_thread ) {
- if ( list->infos != NULL ) {
- list->infos[list->count] = info;
- }
- if ( list->serial_nums != NULL ) {
- list->serial_nums[list->count] = thread_serial_num;
- }
- list->threads[list->count] = thread;
- list->count++;
- /* Local reference gets freed by caller */
- } else {
- /* If we don't use the local reference, delete it now */
- if ( thread != NULL ) {
- deleteLocalReference(list->env, thread);
- }
- }
-}
-
-static void
-adjust_stats(jlong total_time, jlong self_time, TraceIndex trace_index,
- StackElement *parent)
-{
- if ( total_time > 0 && parent != NULL ) { /* if a caller exists */
- parent->time_in_callees += total_time;
- }
- trace_increment_cost(trace_index, 1, self_time, total_time);
-}
-
-static void
-push_method(Stack *stack, jlong method_start_time, jmethodID method)
-{
- StackElement new_element;
- FrameIndex frame_index;
-
- HPROF_ASSERT(method!=NULL);
- HPROF_ASSERT(stack!=NULL);
-
- frame_index = frame_find_or_create(method, -1);
- HPROF_ASSERT(frame_index != 0);
- new_element.frame_index = frame_index;
- new_element.method = method;
- new_element.method_start_time= method_start_time;
- new_element.time_in_callees = (jlong)0;
- stack_push(stack, &new_element);
-}
-
-static Stack *
-insure_method_on_stack(jthread thread, TlsInfo *info, jlong current_time,
- FrameIndex frame_index, jmethodID method)
-{
- StackElement element;
- void *p;
- int depth;
- int count;
- int fcount;
- int i;
- Stack *new_stack;
- Stack *stack;
-
- stack = info->stack;
-
- HPROF_ASSERT(method!=NULL);
-
- /* If this method is on the stack, just return */
- depth = stack_depth(stack);
- p = stack_top(stack);
- if ( p != NULL ) {
- element = *(StackElement*)p;
- if ( element.frame_index == frame_index ) {
- return stack;
- }
- }
- for ( i = 0 ; i < depth ; i++ ) {
- p = stack_element(stack, i);
- element = *(StackElement*)p;
- if ( element.frame_index == frame_index ) {
- return stack;
- }
- }
-
- /* It wasn't found, create a new stack */
- getFrameCount(thread, &count);
- if ( count <= 0 ) {
- HPROF_ERROR(JNI_FALSE, "no frames, method can't be on stack");
- }
- setup_trace_buffers(info, count);
- getStackTrace(thread, info->jframes_buffer, count, &fcount);
- HPROF_ASSERT(count==fcount);
-
- /* Create a new stack */
- new_stack = stack_init(INITIAL_THREAD_STACK_LIMIT,
- INITIAL_THREAD_STACK_LIMIT,
- (int)sizeof(StackElement));
- for ( i = count-1; i >= 0 ; i-- ) {
- push_method(new_stack, current_time, info->jframes_buffer[i].method);
- }
- if ( depth > 0 ) {
- for ( i = depth-1 ; i >= 0; i-- ) {
- stack_push(new_stack, stack_element(stack, i));
- }
- }
- stack_term(stack);
- return new_stack;
-}
-
-static void
-pop_method(TlsIndex index, jlong current_time, jmethodID method, FrameIndex frame_index)
-{
- SerialNumber thread_serial_num;
- TlsInfo * info;
- StackElement element;
- void *p;
- int depth;
- int trace_depth;
- jlong total_time;
- jlong self_time;
- int i;
- TraceIndex trace_index;
-
- HPROF_ASSERT(method!=NULL);
- HPROF_ASSERT(frame_index!=0);
-
- thread_serial_num = get_key(index);
- info = get_info(index);
- HPROF_ASSERT(info!=NULL);
- HPROF_ASSERT(info->stack!=NULL);
- depth = stack_depth(info->stack);
- p = stack_pop(info->stack);
- if (p == NULL) {
- HPROF_ERROR(JNI_FALSE, "method return tracked, but stack is empty");
- return;
- }
- element = *(StackElement*)p;
- HPROF_ASSERT(element.frame_index!=0);
-
- /* The depth of frames we should keep track for reporting */
- if (gdata->prof_trace_depth > depth) {
- trace_depth = depth;
- } else {
- trace_depth = gdata->prof_trace_depth;
- }
-
- /* Create a trace entry */
- HPROF_ASSERT(info->frames_buffer!=NULL);
- HPROF_ASSERT(info->jframes_buffer!=NULL);
- setup_trace_buffers(info, trace_depth);
- info->frames_buffer[0] = element.frame_index;
- for (i = 1; i < trace_depth; i++) {
- StackElement e;
-
- e = *(StackElement*)stack_element(info->stack, (depth - i) - 1);
- info->frames_buffer[i] = e.frame_index;
- HPROF_ASSERT(e.frame_index!=0);
- }
- trace_index = trace_find_or_create(thread_serial_num,
- trace_depth, info->frames_buffer, info->jframes_buffer);
-
- /* Calculate time spent */
- total_time = current_time - element.method_start_time;
- if ( total_time < 0 ) {
- total_time = 0;
- self_time = 0;
- } else {
- self_time = total_time - element.time_in_callees;
- }
-
- /* Update stats */
- p = stack_top(info->stack);
- if ( p != NULL ) {
- adjust_stats(total_time, self_time, trace_index, (StackElement*)p);
- } else {
- adjust_stats(total_time, self_time, trace_index, NULL);
- }
-}
-
-static void
-dump_thread_state(TlsIndex index, void *key_ptr, int key_len, void *info_ptr, void *arg)
-{
- SerialNumber thread_serial_num;
- TlsInfo *info;
- jthread thread;
- JNIEnv *env;
-
- HPROF_ASSERT(key_ptr!=NULL);
- HPROF_ASSERT(info_ptr!=NULL);
- env = (JNIEnv*)arg;
- thread_serial_num = *(SerialNumber*)key_ptr;
- info = (TlsInfo*)info_ptr;
- thread = newLocalReference(env, info->globalref);
- if ( thread != NULL ) {
- jint threadState;
- SerialNumber trace_serial_num;
-
- getThreadState(thread, &threadState);
- /* A 0 trace at this time means the thread is in unknown territory.
- * The trace serial number MUST be a valid serial number, so we use
- * the system trace (empty) just so it has a valid trace.
- */
- if ( info->last_trace == 0 ) {
- trace_serial_num = trace_get_serial_number(gdata->system_trace_index);
- } else {
- trace_serial_num = trace_get_serial_number(info->last_trace);
- }
- io_write_monitor_dump_thread_state(thread_serial_num,
- trace_serial_num, threadState);
- deleteLocalReference(env, thread);
- }
-}
-
-static SerialNumber
-get_serial_number(JNIEnv *env, jthread thread)
-{
- TlsIndex index;
-
- if ( thread == NULL ) {
- return gdata->unknown_thread_serial_num;
- }
- HPROF_ASSERT(env!=NULL);
- index = tls_find_or_create(env, thread);
- return get_key(index);
-}
-
-static void
-dump_monitor_state(TlsIndex index, void *key_ptr, int key_len, void *info_ptr, void *arg)
-{
- TlsInfo *info;
- jthread thread;
- JNIEnv *env;
-
- HPROF_ASSERT(info_ptr!=NULL);
- env = (JNIEnv*)arg;
- info = (TlsInfo*)info_ptr;
- thread = newLocalReference(env, info->globalref);
- if ( thread != NULL ) {
- jobject *objects;
- jint ocount;
- int i;
-
- getOwnedMonitorInfo(thread, &objects, &ocount);
- if ( ocount > 0 ) {
- for ( i = 0 ; i < ocount ; i++ ) {
- jvmtiMonitorUsage usage;
- SerialNumber *waiter_nums;
- SerialNumber *notify_waiter_nums;
- int t;
- char * sig;
-
- WITH_LOCAL_REFS(env, 1) {
- jclass clazz;
-
- clazz = getObjectClass(env, objects[i]);
- getClassSignature(clazz, &sig, NULL);
- } END_WITH_LOCAL_REFS;
-
- getObjectMonitorUsage(objects[i], &usage);
- waiter_nums = HPROF_MALLOC(usage.waiter_count*
- (int)sizeof(SerialNumber)+1);
- for ( t = 0 ; t < usage.waiter_count ; t++ ) {
- waiter_nums[t] =
- get_serial_number(env, usage.waiters[t]);
- }
- notify_waiter_nums = HPROF_MALLOC(usage.notify_waiter_count*
- (int)sizeof(SerialNumber)+1);
- for ( t = 0 ; t < usage.notify_waiter_count ; t++ ) {
- notify_waiter_nums[t] =
- get_serial_number(env, usage.notify_waiters[t]);
- }
- io_write_monitor_dump_state(sig,
- get_serial_number(env, usage.owner),
- usage.entry_count,
- waiter_nums, usage.waiter_count,
- notify_waiter_nums, usage.notify_waiter_count);
- jvmtiDeallocate(sig);
- jvmtiDeallocate(usage.waiters);
- jvmtiDeallocate(usage.notify_waiters);
- HPROF_FREE(waiter_nums);
- HPROF_FREE(notify_waiter_nums);
- }
- }
- jvmtiDeallocate(objects);
- deleteLocalReference(env, thread);
- }
-}
-
-static jlong
-monitor_time(void)
-{
- jlong mtime;
-
- mtime = md_get_timemillis(); /* gettimeofday() */
- return mtime;
-}
-
-static jlong
-method_time(void)
-{
- jlong method_time;
-
- method_time = md_get_thread_cpu_timemillis(); /* thread CPU time */
- return method_time;
-}
-
-/* External interfaces */
-
-TlsIndex
-tls_find_or_create(JNIEnv *env, jthread thread)
-{
- SerialNumber thread_serial_num;
- static TlsInfo empty_info;
- TlsInfo info;
- TlsIndex index;
-
- HPROF_ASSERT(env!=NULL);
- HPROF_ASSERT(thread!=NULL);
-
- /*LINTED*/
- index = (TlsIndex)(ptrdiff_t)getThreadLocalStorage(thread);
- if ( index != 0 ) {
- HPROF_ASSERT(isSameObject(env, thread, get_info(index)->globalref));
- return index;
- }
- index = search(env, thread);
- if ( index != 0 ) {
- setThreadLocalStorage(thread, (void*)(ptrdiff_t)index);
- return index;
- }
- thread_serial_num = gdata->thread_serial_number_counter++;
- info = empty_info;
- info.monitor_index = 0;
- info.sample_status = 1;
- info.agent_thread = JNI_FALSE;
- info.stack = stack_init(INITIAL_THREAD_STACK_LIMIT,
- INITIAL_THREAD_STACK_LIMIT,
- (int)sizeof(StackElement));
- setup_trace_buffers(&info, gdata->max_trace_depth);
- info.globalref = newWeakGlobalReference(env, thread);
- index = table_create_entry(gdata->tls_table, &thread_serial_num, (int)sizeof(SerialNumber), (void*)&info);
- setThreadLocalStorage(thread, (void*)(ptrdiff_t)index);
- HPROF_ASSERT(search(env,thread)==index);
- return index;
-}
-
-/* Mark a new or existing entry as being an agent thread */
-void
-tls_agent_thread(JNIEnv *env, jthread thread)
-{
- TlsIndex index;
- TlsInfo *info;
-
- index = tls_find_or_create(env, thread);
- info = get_info(index);
- info->agent_thread = JNI_TRUE;
-}
-
-void
-tls_init(void)
-{
- gdata->tls_table = table_initialize("TLS",
- 16, 16, 16, (int)sizeof(TlsInfo));
-}
-
-void
-tls_list(void)
-{
- debug_message(
- "--------------------- TLS Table ------------------------\n");
- table_walk_items(gdata->tls_table, &list_item, NULL);
- debug_message(
- "----------------------------------------------------------\n");
-}
-
-jint
-tls_sum_sample_status(void)
-{
- jint sample_status_total;
-
- sample_status_total = 0;
- table_walk_items(gdata->tls_table, &sum_sample_status_item, (void*)&sample_status_total);
- return sample_status_total;
-}
-
-void
-tls_set_sample_status(ObjectIndex object_index, jint sample_status)
-{
- SampleData data;
-
- data.thread_object_index = object_index;
- data.sample_status = sample_status;
- table_walk_items(gdata->tls_table, &sample_setter, (void*)&data);
-}
-
-jint
-tls_get_tracker_status(JNIEnv *env, jthread thread, jboolean skip_init,
- jint **ppstatus, TlsIndex* pindex,
- SerialNumber *pthread_serial_num, TraceIndex *ptrace_index)
-{
- TlsInfo *info;
- TlsIndex index;
- SerialNumber thread_serial_num;
- jint status;
-
- index = tls_find_or_create(env, thread);
- info = get_info(index);
- *ppstatus = &(info->tracker_status);
- status = **ppstatus;
- thread_serial_num = get_key(index);
-
- if ( pindex != NULL ) {
- *pindex = index;
- }
- if ( status != 0 ) {
- return status;
- }
- if ( ptrace_index != NULL ) {
- setup_trace_buffers(info, gdata->max_trace_depth);
- *ptrace_index = get_trace(thread, thread_serial_num,
- gdata->max_trace_depth, skip_init,
- info->frames_buffer, info->jframes_buffer);
- }
- if ( pthread_serial_num != NULL ) {
- *pthread_serial_num = thread_serial_num;
- }
- return status;
-}
-
-MonitorIndex
-tls_get_monitor(TlsIndex index)
-{
- TlsInfo *info;
-
- info = get_info(index);
- return info->monitor_index;
-}
-
-void
-tls_set_thread_object_index(TlsIndex index, ObjectIndex thread_object_index)
-{
- TlsInfo *info;
-
- info = get_info(index);
- info->thread_object_index = thread_object_index;
-}
-
-SerialNumber
-tls_get_thread_serial_number(TlsIndex index)
-{
- return get_key(index);
-}
-
-void
-tls_set_monitor(TlsIndex index, MonitorIndex monitor_index)
-{
- TlsInfo *info;
-
- info = get_info(index);
- info->monitor_index = monitor_index;
-}
-
-void
-tls_cleanup(void)
-{
- table_cleanup(gdata->tls_table, &cleanup_item, NULL);
- gdata->tls_table = NULL;
-}
-
-void
-tls_delete_global_references(JNIEnv *env)
-{
- table_walk_items(gdata->tls_table, &delete_ref_item, (void*)env);
-}
-
-void
-tls_thread_ended(JNIEnv *env, TlsIndex index)
-{
- HPROF_ASSERT(env!=NULL);
-
- /* Sample thread stack for last time, do NOT free the entry yet. */
- table_lock_enter(gdata->tls_table); {
- SerialNumber thread_serial_num;
- TlsInfo *info;
- jthread thread;
-
- thread_serial_num = get_key(index);
- info = get_info(index);
- thread = newLocalReference(env, info->globalref);
- if (gdata->heap_dump && thread!=NULL) {
- setup_trace_buffers(info, gdata->max_trace_depth);
- info->last_trace = get_trace(thread, thread_serial_num,
- gdata->max_trace_depth, JNI_FALSE,
- info->frames_buffer, info->jframes_buffer);
- }
- if ( thread != NULL ) {
- deleteLocalReference(env, thread);
- }
- } table_lock_exit(gdata->tls_table);
-
-}
-
-/* Sample ALL threads and update the trace costs */
-void
-tls_sample_all_threads(JNIEnv *env)
-{
- ThreadList list;
- jthread *threads;
- SerialNumber *serial_nums;
-
- table_lock_enter(gdata->tls_table); {
- int max_count;
- int nbytes;
- int i;
-
- /* Get buffers to hold thread list and serial number list */
- max_count = table_element_count(gdata->tls_table);
- nbytes = (int)sizeof(jthread)*max_count;
- threads = (jthread*)HPROF_MALLOC(nbytes);
- nbytes = (int)sizeof(SerialNumber)*max_count;
- serial_nums = (SerialNumber*)HPROF_MALLOC(nbytes);
-
- /* Get list of threads and serial numbers */
- list.threads = threads;
- list.infos = NULL;
- list.serial_nums = serial_nums;
- list.count = 0;
- list.env = env;
- table_walk_items(gdata->tls_table, &get_thread_list, (void*)&list);
-
- /* Increment the cost on the traces for these threads */
- trace_increment_all_sample_costs(list.count, threads, serial_nums,
- gdata->max_trace_depth, JNI_FALSE);
-
- /* Loop over local refs and free them */
- for ( i = 0 ; i < list.count ; i++ ) {
- if ( threads[i] != NULL ) {
- deleteLocalReference(env, threads[i]);
- }
- }
-
- } table_lock_exit(gdata->tls_table);
-
- /* Free up allocated space */
- HPROF_FREE(threads);
- HPROF_FREE(serial_nums);
-
-}
-
-void
-tls_push_method(TlsIndex index, jmethodID method)
-{
- jlong method_start_time;
- TlsInfo *info;
-
- HPROF_ASSERT(method!=NULL);
- info = get_info(index);
- HPROF_ASSERT(info!=NULL);
- method_start_time = method_time();
- HPROF_ASSERT(info->stack!=NULL);
- push_method(info->stack, method_start_time, method);
-}
-
-void
-tls_pop_exception_catch(TlsIndex index, jthread thread, jmethodID method)
-{
- TlsInfo *info;
- StackElement element;
- void *p;
- FrameIndex frame_index;
- jlong current_time;
-
- HPROF_ASSERT(method!=NULL);
- frame_index = frame_find_or_create(method, -1);
- HPROF_ASSERT(frame_index != 0);
-
- info = get_info(index);
-
- HPROF_ASSERT(info!=NULL);
- HPROF_ASSERT(info->stack!=NULL);
- HPROF_ASSERT(frame_index!=0);
- current_time = method_time();
- info->stack = insure_method_on_stack(thread, info, current_time,
- frame_index, method);
- p = stack_top(info->stack);
- if (p == NULL) {
- HPROF_ERROR(JNI_FALSE, "expection pop, nothing on stack");
- return;
- }
- element = *(StackElement*)p;
- HPROF_ASSERT(element.frame_index!=0);
- while ( element.frame_index != frame_index ) {
- pop_method(index, current_time, element.method, frame_index);
- p = stack_top(info->stack);
- if ( p == NULL ) {
- break;
- }
- element = *(StackElement*)p;
- }
- if (p == NULL) {
- HPROF_ERROR(JNI_FALSE, "exception pop stack empty");
- }
-}
-
-void
-tls_pop_method(TlsIndex index, jthread thread, jmethodID method)
-{
- TlsInfo *info;
- StackElement element;
- void *p;
- FrameIndex frame_index;
- jlong current_time;
-
- HPROF_ASSERT(method!=NULL);
- frame_index = frame_find_or_create(method, -1);
- HPROF_ASSERT(frame_index != 0);
-
- info = get_info(index);
- HPROF_ASSERT(info!=NULL);
- HPROF_ASSERT(info->stack!=NULL);
- current_time = method_time();
- HPROF_ASSERT(frame_index!=0);
- info->stack = insure_method_on_stack(thread, info, current_time,
- frame_index, method);
- p = stack_top(info->stack);
- HPROF_ASSERT(p!=NULL);
- element = *(StackElement*)p;
- while ( element.frame_index != frame_index ) {
- pop_method(index, current_time, element.method, frame_index);
- p = stack_top(info->stack);
- if ( p == NULL ) {
- break;
- }
- element = *(StackElement*)p;
- }
- pop_method(index, current_time, method, frame_index);
-}
-
-/* For all TLS entries, update the last_trace on all threads */
-static void
-update_all_last_traces(JNIEnv *env)
-{
- jthread *threads;
- TlsInfo **infos;
- SerialNumber *serial_nums;
- TraceIndex *traces;
-
- if ( gdata->max_trace_depth == 0 ) {
- return;
- }
-
- table_lock_enter(gdata->tls_table); {
-
- ThreadList list;
- int max_count;
- int nbytes;
- int i;
-
- /* Get buffers to hold thread list and serial number list */
- max_count = table_element_count(gdata->tls_table);
- nbytes = (int)sizeof(jthread)*max_count;
- threads = (jthread*)HPROF_MALLOC(nbytes);
- nbytes = (int)sizeof(SerialNumber)*max_count;
- serial_nums = (SerialNumber*)HPROF_MALLOC(nbytes);
- nbytes = (int)sizeof(TlsInfo*)*max_count;
- infos = (TlsInfo**)HPROF_MALLOC(nbytes);
-
- /* Get list of threads, serial numbers, and info pointers */
- list.threads = threads;
- list.serial_nums = serial_nums;
- list.infos = infos;
- list.count = 0;
- list.env = env;
- table_walk_items(gdata->tls_table, &get_thread_list, (void*)&list);
-
- /* Get all stack trace index's for all these threadss */
- nbytes = (int)sizeof(TraceIndex)*max_count;
- traces = (TraceIndex*)HPROF_MALLOC(nbytes);
- trace_get_all_current(list.count, threads, serial_nums,
- gdata->max_trace_depth, JNI_FALSE,
- traces, JNI_TRUE);
-
- /* Loop over traces and update last_trace's */
- for ( i = 0 ; i < list.count ; i++ ) {
- if ( threads[i] != NULL ) {
- deleteLocalReference(env, threads[i]);
- }
- infos[i]->last_trace = traces[i];
- }
-
- } table_lock_exit(gdata->tls_table);
-
- /* Free up all allocated space */
- HPROF_FREE(threads);
- HPROF_FREE(serial_nums);
- HPROF_FREE(infos);
- HPROF_FREE(traces);
-
-}
-
-void
-tls_dump_traces(JNIEnv *env)
-{
- rawMonitorEnter(gdata->data_access_lock); {
- update_all_last_traces(env);
- trace_output_unmarked(env);
- } rawMonitorExit(gdata->data_access_lock);
-}
-
-void
-tls_dump_monitor_state(JNIEnv *env)
-{
- HPROF_ASSERT(env!=NULL);
-
- rawMonitorEnter(gdata->data_access_lock); {
- tls_dump_traces(env);
- io_write_monitor_dump_header();
- table_walk_items(gdata->tls_table, &dump_thread_state, (void*)env);
- table_walk_items(gdata->tls_table, &dump_monitor_state, (void*)env);
- io_write_monitor_dump_footer();
- } rawMonitorExit(gdata->data_access_lock);
-}
-
-void
-tls_monitor_start_timer(TlsIndex index)
-{
- TlsInfo *info;
-
- info = get_info(index);
- HPROF_ASSERT(info!=NULL);
- HPROF_ASSERT(info->globalref!=NULL);
- info->monitor_start_time = monitor_time();
-}
-
-jlong
-tls_monitor_stop_timer(TlsIndex index)
-{
- TlsInfo *info;
- jlong t;
-
- info = get_info(index);
- HPROF_ASSERT(info!=NULL);
- t = monitor_time() - info->monitor_start_time;
- info->monitor_start_time = 0;
- return t;
-}
-
-TraceIndex
-tls_get_trace(TlsIndex index, JNIEnv *env, int depth, jboolean skip_init)
-{
- SerialNumber thread_serial_num;
- TraceIndex trace_index;
- TlsInfo *info;
- jthread thread;
-
- thread_serial_num = get_key(index);
- info = get_info(index);
- HPROF_ASSERT(info!=NULL);
- setup_trace_buffers(info, depth);
- thread = newLocalReference(env, info->globalref);
- if ( thread != NULL ) {
- trace_index = get_trace(thread, thread_serial_num, depth, skip_init,
- info->frames_buffer, info->jframes_buffer);
- deleteLocalReference(env, thread);
- } else {
- trace_index = gdata->system_trace_index;
- }
- return trace_index;
-}
-
-void
-tls_set_in_heap_dump(TlsIndex index, jint in_heap_dump)
-{
- TlsInfo *info;
-
- info = get_info(index);
- info->in_heap_dump = in_heap_dump;
-}
-
-jint
-tls_get_in_heap_dump(TlsIndex index)
-{
- TlsInfo *info;
-
- info = get_info(index);
- return info->in_heap_dump;
-}
-
-static void
-clean_in_heap_dump(TableIndex index, void *key_ptr, int key_len, void *info_ptr, void *arg)
-{
- TlsInfo *info;
-
- HPROF_ASSERT(info_ptr!=NULL);
- info = (TlsInfo*)info_ptr;
- info->in_heap_dump = 0;
-}
-
-void
-tls_clear_in_heap_dump(void)
-{
- table_walk_items(gdata->tls_table, &clean_in_heap_dump, NULL);
-}
-
-TlsIndex
-tls_find(SerialNumber thread_serial_num)
-{
- TlsIndex index;
-
- if ( thread_serial_num == 0 ) {
- return 0;
- }
- index = table_find_entry(gdata->tls_table,
- (void*)&thread_serial_num, (int)sizeof(SerialNumber));
- return index;
-}
--- a/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_tls.h Thu Aug 20 12:29:58 2015 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,89 +0,0 @@
-/*
- * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * - Neither the name of Oracle nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
- * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/*
- * This source code is provided to illustrate the usage of a given feature
- * or technique and has been deliberately simplified. Additional steps
- * required for a production-quality application, such as security checks,
- * input validation and proper error handling, might not be present in
- * this sample code.
- */
-
-
-#ifndef HPROF_TLS_H
-#define HPROF_TLS_H
-
-void tls_init(void);
-TlsIndex tls_find_or_create(JNIEnv *env, jthread thread);
-void tls_agent_thread(JNIEnv *env, jthread thread);
-SerialNumber tls_get_thread_serial_number(TlsIndex index);
-void tls_list(void);
-void tls_delete_global_references(JNIEnv *env);
-void tls_garbage_collect(JNIEnv *env);
-void tls_cleanup(void);
-void tls_thread_ended(JNIEnv *env, TlsIndex index);
-void tls_sample_all_threads(JNIEnv *env);
-
-MonitorIndex tls_get_monitor(TlsIndex index);
-void tls_set_monitor(TlsIndex index, MonitorIndex monitor_index);
-
-void tls_set_thread_object_index(TlsIndex index,
- ObjectIndex thread_object_index);
-
-jint tls_get_tracker_status(JNIEnv *env, jthread thread,
- jboolean skip_init, jint **ppstatus, TlsIndex* pindex,
- SerialNumber *pthread_serial_num,
- TraceIndex *ptrace_index);
-
-void tls_set_sample_status(ObjectIndex object_index, jint sample_status);
-jint tls_sum_sample_status(void);
-
-void tls_dump_traces(JNIEnv *env);
-
-void tls_monitor_start_timer(TlsIndex index);
-jlong tls_monitor_stop_timer(TlsIndex index);
-
-void tls_dump_monitor_state(JNIEnv *env);
-
-void tls_push_method(TlsIndex index, jmethodID method);
-void tls_pop_method(TlsIndex index, jthread thread, jmethodID method);
-void tls_pop_exception_catch(TlsIndex index, jthread thread, jmethodID method);
-
-TraceIndex tls_get_trace(TlsIndex index, JNIEnv *env,
- int depth, jboolean skip_init);
-
-void tls_set_in_heap_dump(TlsIndex index, jint in_heap_dump);
-jint tls_get_in_heap_dump(TlsIndex index);
-void tls_clear_in_heap_dump(void);
-
-TlsIndex tls_find(SerialNumber thread_serial_num);
-
-#endif
--- a/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_trace.c Thu Aug 20 12:29:58 2015 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,869 +0,0 @@
-/*
- * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * - Neither the name of Oracle nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
- * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/*
- * This source code is provided to illustrate the usage of a given feature
- * or technique and has been deliberately simplified. Additional steps
- * required for a production-quality application, such as security checks,
- * input validation and proper error handling, might not be present in
- * this sample code.
- */
-
-
-/* Trace table. */
-
-/*
- * A trace is an optional thread serial number plus N frames.
- *
- * The thread serial number is added to the key only if the user asks for
- * threads in traces, which will cause many more traces to be created.
- * Without it all threads share the traces.
- *
- * This is a variable length Key, depending on the number of frames.
- * The frames are FrameIndex values into the frame table.
- *
- * It is important that the thread serial number is used and not the
- * TlsIndex, threads come and go, and TlsIndex values are re-used
- * but the thread serial number is unique per thread.
- *
- * The cpu=times and cpu=samples dumps rely heavily on traces, the trace
- * dump preceeds the cpu information and uses the trace information.
- * Depending on the cpu= request, different sorts are applied to the
- * traces that are dumped.
- *
- */
-
-#include "hprof.h"
-
-typedef struct TraceKey {
- SerialNumber thread_serial_num; /* Thread serial number */
- short n_frames; /* Number of frames that follow. */
- jvmtiPhase phase : 8; /* Makes some traces unique */
- FrameIndex frames[1]; /* Variable length */
-} TraceKey;
-
-typedef struct TraceInfo {
- SerialNumber serial_num; /* Trace serial number */
- jint num_hits; /* Number of hits this trace has */
- jlong total_cost; /* Total cost associated with trace */
- jlong self_cost; /* Total cost without children cost */
- jint status; /* Status of dump of trace */
-} TraceInfo;
-
-typedef struct IterateInfo {
- TraceIndex* traces;
- int count;
- jlong grand_total_cost;
-} IterateInfo;
-
-/* Private internal functions. */
-
-static TraceKey*
-get_pkey(TraceIndex index)
-{
- void * pkey;
- int key_len;
-
- table_get_key(gdata->trace_table, index, &pkey, &key_len);
- HPROF_ASSERT(pkey!=NULL);
- HPROF_ASSERT(key_len>=(int)sizeof(TraceKey));
- HPROF_ASSERT(((TraceKey*)pkey)->n_frames<=1?key_len==(int)sizeof(TraceKey) :
- key_len==(int)sizeof(TraceKey)+
- (int)sizeof(FrameIndex)*(((TraceKey*)pkey)->n_frames-1));
- return (TraceKey*)pkey;
-}
-
-static TraceInfo *
-get_info(TraceIndex index)
-{
- TraceInfo * info;
-
- info = (TraceInfo*)table_get_info(gdata->trace_table, index);
- return info;
-}
-
-static TraceIndex
-find_or_create(SerialNumber thread_serial_num, jint n_frames,
- FrameIndex *frames, jvmtiPhase phase, TraceKey *trace_key_buffer)
-{
- TraceInfo * info;
- TraceKey * pkey;
- int key_len;
- TraceIndex index;
- jboolean new_one;
- static TraceKey empty_key;
-
- HPROF_ASSERT(frames!=NULL);
- HPROF_ASSERT(trace_key_buffer!=NULL);
- key_len = (int)sizeof(TraceKey);
- if ( n_frames > 1 ) {
- key_len += (int)((n_frames-1)*(int)sizeof(FrameIndex));
- }
- pkey = trace_key_buffer;
- *pkey = empty_key;
- pkey->thread_serial_num = (gdata->thread_in_traces ? thread_serial_num : 0);
- pkey->n_frames = (short)n_frames;
- pkey->phase = phase;
- if ( n_frames > 0 ) {
- (void)memcpy(pkey->frames, frames, (n_frames*(int)sizeof(FrameIndex)));
- }
-
- new_one = JNI_FALSE;
- index = table_find_or_create_entry(gdata->trace_table,
- pkey, key_len, &new_one, NULL);
- if ( new_one ) {
- info = get_info(index);
- info->serial_num = gdata->trace_serial_number_counter++;
- }
- return index;
-}
-
-static void
-list_item(TableIndex index, void *key_ptr, int key_len, void *info_ptr, void *arg)
-{
- TraceInfo *info;
- TraceKey *key;
- int i;
-
- HPROF_ASSERT(key_ptr!=NULL);
- HPROF_ASSERT(key_len>0);
- HPROF_ASSERT(info_ptr!=NULL);
- key = (TraceKey*)key_ptr;
- info = (TraceInfo *)info_ptr;
-
- debug_message( "Trace 0x%08x: SN=%u, threadSN=%u, n_frames=%d, frames=(",
- index,
- info->serial_num,
- key->thread_serial_num,
- key->n_frames);
- for ( i = 0 ; i < key->n_frames ; i++ ) {
- debug_message( "0x%08x, ", key->frames[i]);
- }
- debug_message( "), traceSN=%u, num_hits=%d, self_cost=(%d,%d), "
- "total_cost=(%d,%d), status=0x%08x\n",
- info->serial_num,
- info->num_hits,
- jlong_high(info->self_cost),
- jlong_low(info->self_cost),
- jlong_high(info->total_cost),
- jlong_low(info->total_cost),
- info->status);
-}
-
-static void
-clear_cost(TableIndex i, void *key_ptr, int key_len, void *info_ptr, void *arg)
-{
- TraceInfo *info;
-
- HPROF_ASSERT(key_ptr!=NULL);
- HPROF_ASSERT(key_len>0);
- HPROF_ASSERT(info_ptr!=NULL);
- info = (TraceInfo *)info_ptr;
- info->num_hits = 0;
- info->total_cost = 0;
- info->self_cost = 0;
-}
-
-/* Get the names for a frame in order to dump it. */
-static void
-get_frame_details(JNIEnv *env, FrameIndex frame_index,
- SerialNumber *frame_serial_num, char **pcsig, ClassIndex *pcnum,
- char **pmname, char **pmsig, char **psname, jint *plineno)
-{
- jmethodID method;
- jlocation location;
- jint lineno;
-
- HPROF_ASSERT(frame_index!=0);
- *pmname = NULL;
- *pmsig = NULL;
- *pcsig = NULL;
- if ( psname != NULL ) {
- *psname = NULL;
- }
- if ( plineno != NULL ) {
- *plineno = -1;
- }
- if ( pcnum != NULL ) {
- *pcnum = 0;
- }
- frame_get_location(frame_index, frame_serial_num, &method, &location, &lineno);
- if ( plineno != NULL ) {
- *plineno = lineno;
- }
- WITH_LOCAL_REFS(env, 1) {
- jclass klass;
-
- getMethodClass(method, &klass);
- getClassSignature(klass, pcsig, NULL);
- if ( pcnum != NULL ) {
- LoaderIndex loader_index;
- jobject loader;
-
- loader = getClassLoader(klass);
- loader_index = loader_find_or_create(env, loader);
- *pcnum = class_find_or_create(*pcsig, loader_index);
- (void)class_new_classref(env, *pcnum, klass);
- }
- if ( psname != NULL ) {
- getSourceFileName(klass, psname);
- }
- } END_WITH_LOCAL_REFS;
- getMethodName(method, pmname, pmsig);
-}
-
-/* Write out a stack trace. */
-static void
-output_trace(TableIndex index, void *key_ptr, int key_len, void *info_ptr, void *arg)
-{
- TraceKey *key;
- TraceInfo *info;
- SerialNumber serial_num;
- SerialNumber thread_serial_num;
- jint n_frames;
- JNIEnv *env;
- int i;
- char *phase_str;
- struct FrameNames {
- SerialNumber serial_num;
- char * sname;
- char * csig;
- char * mname;
- int lineno;
- } *finfo;
-
- info = (TraceInfo*)info_ptr;
- if ( info->status != 0 ) {
- return;
- }
-
- env = (JNIEnv*)arg;
-
- key = (TraceKey*)key_ptr;
- thread_serial_num = key->thread_serial_num;
- serial_num = info->serial_num;
- info->status = 1;
- finfo = NULL;
-
- n_frames = (jint)key->n_frames;
- if ( n_frames > 0 ) {
- finfo = (struct FrameNames *)HPROF_MALLOC(n_frames*(int)sizeof(struct FrameNames));
-
- /* Write frames, but save information for trace later */
- for (i = 0; i < n_frames; i++) {
- FrameIndex frame_index;
- char *msig;
- ClassIndex cnum;
-
- frame_index = key->frames[i];
- get_frame_details(env, frame_index, &finfo[i].serial_num,
- &finfo[i].csig, &cnum,
- &finfo[i].mname, &msig, &finfo[i].sname, &finfo[i].lineno);
-
- if (frame_get_status(frame_index) == 0) {
- io_write_frame(frame_index, finfo[i].serial_num,
- finfo[i].mname, msig,
- finfo[i].sname, class_get_serial_number(cnum),
- finfo[i].lineno);
- frame_set_status(frame_index, 1);
- }
- jvmtiDeallocate(msig);
- }
- }
-
- /* Find phase string */
- if ( key->phase == JVMTI_PHASE_LIVE ) {
- phase_str = NULL; /* Normal trace, no phase annotation */
- } else {
- phase_str = phaseString(key->phase);
- }
-
- io_write_trace_header(serial_num, thread_serial_num, n_frames, phase_str);
-
- for (i = 0; i < n_frames; i++) {
- io_write_trace_elem(serial_num, key->frames[i], finfo[i].serial_num,
- finfo[i].csig,
- finfo[i].mname, finfo[i].sname, finfo[i].lineno);
- jvmtiDeallocate(finfo[i].csig);
- jvmtiDeallocate(finfo[i].mname);
- jvmtiDeallocate(finfo[i].sname);
- }
-
- io_write_trace_footer(serial_num, thread_serial_num, n_frames);
-
- if ( finfo != NULL ) {
- HPROF_FREE(finfo);
- }
-}
-
-/* Output a specific list of traces. */
-static void
-output_list(JNIEnv *env, TraceIndex *list, jint count)
-{
- rawMonitorEnter(gdata->data_access_lock); {
- int i;
-
- for ( i = 0; i < count ; i++ ) {
- TraceIndex index;
- TraceInfo *info;
- void * pkey;
- int key_len;
-
- index = list[i];
- table_get_key(gdata->trace_table, index, &pkey, &key_len);
- info = get_info(index);
- output_trace(index, pkey, key_len, info, (void*)env);
- }
- } rawMonitorExit(gdata->data_access_lock);
-}
-
-static void
-collect_iterator(TableIndex index, void *key_ptr, int key_len, void *info_ptr, void *arg)
-{
- TraceInfo *info;
- IterateInfo *iterate;
-
- HPROF_ASSERT(key_ptr!=NULL);
- HPROF_ASSERT(key_len>0);
- HPROF_ASSERT(arg!=NULL);
- HPROF_ASSERT(info_ptr!=NULL);
- iterate = (IterateInfo *)arg;
- info = (TraceInfo *)info_ptr;
- iterate->traces[iterate->count++] = index;
- iterate->grand_total_cost += info->self_cost;
-}
-
-static int
-qsort_compare_cost(const void *p_trace1, const void *p_trace2)
-{
- TraceIndex trace1;
- TraceIndex trace2;
- TraceInfo * info1;
- TraceInfo * info2;
-
- HPROF_ASSERT(p_trace1!=NULL);
- HPROF_ASSERT(p_trace2!=NULL);
- trace1 = *(TraceIndex *)p_trace1;
- trace2 = *(TraceIndex *)p_trace2;
- info1 = get_info(trace1);
- info2 = get_info(trace2);
- /*LINTED*/
- return (int)(info2->self_cost - info1->self_cost);
-}
-
-static int
-qsort_compare_num_hits(const void *p_trace1, const void *p_trace2)
-{
- TraceIndex trace1;
- TraceIndex trace2;
- TraceInfo * info1;
- TraceInfo * info2;
-
- HPROF_ASSERT(p_trace1!=NULL);
- HPROF_ASSERT(p_trace2!=NULL);
- trace1 = *(TraceIndex *)p_trace1;
- trace2 = *(TraceIndex *)p_trace2;
- info1 = get_info(trace1);
- info2 = get_info(trace2);
- return info2->num_hits - info1->num_hits;
-}
-
-/* External interfaces. */
-
-void
-trace_init(void)
-{
- gdata->trace_table = table_initialize("Trace",
- 256, 256, 511, (int)sizeof(TraceInfo));
-}
-
-void
-trace_list(void)
-{
- debug_message(
- "--------------------- Trace Table ------------------------\n");
- table_walk_items(gdata->trace_table, &list_item, NULL);
- debug_message(
- "----------------------------------------------------------\n");
-}
-
-void
-trace_cleanup(void)
-{
- table_cleanup(gdata->trace_table, NULL, NULL);
- gdata->trace_table = NULL;
-}
-
-SerialNumber
-trace_get_serial_number(TraceIndex index)
-{
- TraceInfo *info;
-
- if ( index == 0 ) {
- return 0;
- }
- info = get_info(index);
- return info->serial_num;
-}
-
-void
-trace_increment_cost(TraceIndex index, jint num_hits, jlong self_cost, jlong total_cost)
-{
- TraceInfo *info;
-
- table_lock_enter(gdata->trace_table); {
- info = get_info(index);
- info->num_hits += num_hits;
- info->self_cost += self_cost;
- info->total_cost += total_cost;
- } table_lock_exit(gdata->trace_table);
-}
-
-TraceIndex
-trace_find_or_create(SerialNumber thread_serial_num, jint n_frames, FrameIndex *frames, jvmtiFrameInfo *jframes_buffer)
-{
- return find_or_create(thread_serial_num, n_frames, frames, getPhase(),
- (TraceKey*)jframes_buffer);
-}
-
-/* We may need to ask for more frames than the user asked for */
-static int
-get_real_depth(int depth, jboolean skip_init)
-{
- int extra_frames;
-
- extra_frames = 0;
- /* This is only needed if we are doing BCI */
- if ( gdata->bci && depth > 0 ) {
- /* Account for Java and native Tracker methods */
- extra_frames = 2;
- if ( skip_init ) {
- /* Also allow for ignoring the java.lang.Object.<init> method */
- extra_frames += 1;
- }
- }
- return depth + extra_frames;
-}
-
-/* Fill in FrameIndex array from jvmtiFrameInfo array, return n_frames */
-static int
-fill_frame_buffer(int depth, int real_depth,
- int frame_count, jboolean skip_init,
- jvmtiFrameInfo *jframes_buffer, FrameIndex *frames_buffer)
-{
- int n_frames;
- jint topframe;
-
- /* If real_depth is 0, just return 0 */
- if ( real_depth == 0 ) {
- return 0;
- }
-
- /* Assume top frame index is 0 for now */
- topframe = 0;
-
- /* Possible top frames belong to the hprof Tracker class, remove them */
- if ( gdata->bci ) {
- while ( ( ( frame_count - topframe ) > 0 ) &&
- ( topframe < (real_depth-depth) ) &&
- ( tracker_method(jframes_buffer[topframe].method) ||
- ( skip_init
- && jframes_buffer[topframe].method==gdata->object_init_method ) )
- ) {
- topframe++;
- }
- }
-
- /* Adjust count to match depth request */
- if ( ( frame_count - topframe ) > depth ) {
- frame_count = depth + topframe;
- }
-
- /* The actual frame count we will process */
- n_frames = frame_count - topframe;
- if ( n_frames > 0 ) {
- int i;
-
- for (i = 0; i < n_frames; i++) {
- jmethodID method;
- jlocation location;
-
- method = jframes_buffer[i+topframe].method;
- location = jframes_buffer[i+topframe].location;
- frames_buffer[i] = frame_find_or_create(method, location);
- }
- }
- return n_frames;
-}
-
-/* Get the trace for the supplied thread */
-TraceIndex
-trace_get_current(jthread thread, SerialNumber thread_serial_num,
- int depth, jboolean skip_init,
- FrameIndex *frames_buffer,
- jvmtiFrameInfo *jframes_buffer)
-{
- TraceIndex index;
- jint frame_count;
- int real_depth;
- int n_frames;
-
- HPROF_ASSERT(thread!=NULL);
- HPROF_ASSERT(frames_buffer!=NULL);
- HPROF_ASSERT(jframes_buffer!=NULL);
-
- /* We may need to ask for more frames than the user asked for */
- real_depth = get_real_depth(depth, skip_init);
-
- /* Get the stack trace for this one thread */
- frame_count = 0;
- if ( real_depth > 0 ) {
- getStackTrace(thread, jframes_buffer, real_depth, &frame_count);
- }
-
- /* Create FrameIndex's */
- n_frames = fill_frame_buffer(depth, real_depth, frame_count, skip_init,
- jframes_buffer, frames_buffer);
-
- /* Lookup or create new TraceIndex */
- index = find_or_create(thread_serial_num, n_frames, frames_buffer,
- getPhase(), (TraceKey*)jframes_buffer);
- return index;
-}
-
-/* Get traces for all threads in list (traces[i]==0 if thread not running) */
-void
-trace_get_all_current(jint thread_count, jthread *threads,
- SerialNumber *thread_serial_nums,
- int depth, jboolean skip_init,
- TraceIndex *traces, jboolean always_care)
-{
- jvmtiStackInfo *stack_info;
- int nbytes;
- int real_depth;
- int i;
- FrameIndex *frames_buffer;
- TraceKey *trace_key_buffer;
- jvmtiPhase phase;
-
- HPROF_ASSERT(threads!=NULL);
- HPROF_ASSERT(thread_serial_nums!=NULL);
- HPROF_ASSERT(traces!=NULL);
- HPROF_ASSERT(thread_count > 0);
-
- /* Find out what the phase is for all these traces */
- phase = getPhase();
-
- /* We may need to ask for more frames than the user asked for */
- real_depth = get_real_depth(depth, skip_init);
-
- /* Get the stack traces for all the threads */
- getThreadListStackTraces(thread_count, threads, real_depth, &stack_info);
-
- /* Allocate a frames_buffer and trace key buffer */
- nbytes = (int)sizeof(FrameIndex)*real_depth;
- frames_buffer = (FrameIndex*)HPROF_MALLOC(nbytes);
- nbytes += (int)sizeof(TraceKey);
- trace_key_buffer = (TraceKey*)HPROF_MALLOC(nbytes);
-
- /* Loop over the stack traces we have for these 'thread_count' threads */
- for ( i = 0 ; i < thread_count ; i++ ) {
- int n_frames;
-
- /* Assume 0 at first (no trace) */
- traces[i] = 0;
-
- /* If thread has frames, is runnable, and isn't suspended, we care */
- if ( always_care ||
- ( stack_info[i].frame_count > 0
- && (stack_info[i].state & JVMTI_THREAD_STATE_RUNNABLE)!=0
- && (stack_info[i].state & JVMTI_THREAD_STATE_SUSPENDED)==0
- && (stack_info[i].state & JVMTI_THREAD_STATE_INTERRUPTED)==0 )
- ) {
-
- /* Create FrameIndex's */
- n_frames = fill_frame_buffer(depth, real_depth,
- stack_info[i].frame_count,
- skip_init,
- stack_info[i].frame_buffer,
- frames_buffer);
-
- /* Lookup or create new TraceIndex */
- traces[i] = find_or_create(thread_serial_nums[i],
- n_frames, frames_buffer, phase, trace_key_buffer);
- }
- }
-
- /* Make sure we free the space */
- HPROF_FREE(frames_buffer);
- HPROF_FREE(trace_key_buffer);
- jvmtiDeallocate(stack_info);
-}
-
-/* Increment the trace costs for all the threads (for cpu=samples) */
-void
-trace_increment_all_sample_costs(jint thread_count, jthread *threads,
- SerialNumber *thread_serial_nums,
- int depth, jboolean skip_init)
-{
- TraceIndex *traces;
- int nbytes;
-
- HPROF_ASSERT(threads!=NULL);
- HPROF_ASSERT(thread_serial_nums!=NULL);
- HPROF_ASSERT(thread_count > 0);
- HPROF_ASSERT(depth >= 0);
-
- if ( depth == 0 ) {
- return;
- }
-
- /* Allocate a traces array */
- nbytes = (int)sizeof(TraceIndex)*thread_count;
- traces = (TraceIndex*)HPROF_MALLOC(nbytes);
-
- /* Get all the current traces for these threads */
- trace_get_all_current(thread_count, threads, thread_serial_nums,
- depth, skip_init, traces, JNI_FALSE);
-
- /* Increment the cpu=samples cost on these traces */
- table_lock_enter(gdata->trace_table); {
- int i;
-
- for ( i = 0 ; i < thread_count ; i++ ) {
- /* Each trace gets a hit and an increment of it's total cost */
- if ( traces[i] != 0 ) {
- TraceInfo *info;
-
- info = get_info(traces[i]);
- info->num_hits += 1;
- info->self_cost += (jlong)1;
- info->total_cost += (jlong)1;
- }
- }
- } table_lock_exit(gdata->trace_table);
-
- /* Free up the memory allocated */
- HPROF_FREE(traces);
-}
-
-void
-trace_output_unmarked(JNIEnv *env)
-{
- rawMonitorEnter(gdata->data_access_lock); {
- table_walk_items(gdata->trace_table, &output_trace, (void*)env);
- } rawMonitorExit(gdata->data_access_lock);
-}
-
-/* output info on the cost associated with traces */
-void
-trace_output_cost(JNIEnv *env, double cutoff)
-{
- IterateInfo iterate;
- int i, trace_table_size, n_items;
- double accum;
- int n_entries;
-
- rawMonitorEnter(gdata->data_access_lock); {
-
- n_entries = table_element_count(gdata->trace_table);
- iterate.traces = HPROF_MALLOC(n_entries*(int)sizeof(TraceIndex)+1);
- iterate.count = 0;
- iterate.grand_total_cost = 0;
- table_walk_items(gdata->trace_table, &collect_iterator, &iterate);
-
- trace_table_size = iterate.count;
-
- /* sort all the traces according to the cost */
- qsort(iterate.traces, trace_table_size, sizeof(TraceIndex),
- &qsort_compare_cost);
-
- n_items = 0;
- for (i = 0; i < trace_table_size; i++) {
- TraceInfo *info;
- TraceIndex trace_index;
- double percent;
-
- trace_index = iterate.traces[i];
- info = get_info(trace_index);
- /* As soon as a trace with zero hits is seen, we need no others */
- if (info->num_hits == 0 ) {
- break;
- }
- percent = (double)info->self_cost / (double)iterate.grand_total_cost;
- if (percent < cutoff) {
- break;
- }
- n_items++;
- }
-
- /* Now write all trace we might refer to. */
- output_list(env, iterate.traces, n_items);
-
- io_write_cpu_samples_header(iterate.grand_total_cost, n_items);
-
- accum = 0;
-
- for (i = 0; i < n_items; i++) {
- SerialNumber frame_serial_num;
- TraceInfo *info;
- TraceKey *key;
- TraceIndex trace_index;
- double percent;
- char *csig;
- char *mname;
- char *msig;
-
- trace_index = iterate.traces[i];
- info = get_info(trace_index);
- key = get_pkey(trace_index);
- percent = ((double)info->self_cost / (double)iterate.grand_total_cost) * 100.0;
- accum += percent;
-
- csig = NULL;
- mname = NULL;
- msig = NULL;
-
- if (key->n_frames > 0) {
- get_frame_details(env, key->frames[0], &frame_serial_num,
- &csig, NULL, &mname, &msig, NULL, NULL);
- }
-
- io_write_cpu_samples_elem(i+1, percent, accum, info->num_hits,
- (jint)info->self_cost, info->serial_num,
- key->n_frames, csig, mname);
-
- jvmtiDeallocate(csig);
- jvmtiDeallocate(mname);
- jvmtiDeallocate(msig);
- }
-
- io_write_cpu_samples_footer();
-
- HPROF_FREE(iterate.traces);
-
- } rawMonitorExit(gdata->data_access_lock);
-
-}
-
-/* output the trace cost in old prof format */
-void
-trace_output_cost_in_prof_format(JNIEnv *env)
-{
- IterateInfo iterate;
- int i, trace_table_size;
- int n_entries;
-
- rawMonitorEnter(gdata->data_access_lock); {
-
- n_entries = table_element_count(gdata->trace_table);
- iterate.traces = HPROF_MALLOC(n_entries*(int)sizeof(TraceIndex)+1);
- iterate.count = 0;
- iterate.grand_total_cost = 0;
- table_walk_items(gdata->trace_table, &collect_iterator, &iterate);
-
- trace_table_size = iterate.count;
-
- /* sort all the traces according to the number of hits */
- qsort(iterate.traces, trace_table_size, sizeof(TraceIndex),
- &qsort_compare_num_hits);
-
- io_write_oldprof_header();
-
- for (i = 0; i < trace_table_size; i++) {
- SerialNumber frame_serial_num;
- TraceInfo *info;
- TraceKey *key;
- TraceIndex trace_index;
- int num_frames;
- int num_hits;
- char *csig_callee;
- char *mname_callee;
- char *msig_callee;
- char *csig_caller;
- char *mname_caller;
- char *msig_caller;
-
- trace_index = iterate.traces[i];
- key = get_pkey(trace_index);
- info = get_info(trace_index);
- num_hits = info->num_hits;
-
- if (num_hits == 0) {
- break;
- }
-
- csig_callee = NULL;
- mname_callee = NULL;
- msig_callee = NULL;
- csig_caller = NULL;
- mname_caller = NULL;
- msig_caller = NULL;
-
- num_frames = (int)key->n_frames;
-
- if (num_frames >= 1) {
- get_frame_details(env, key->frames[0], &frame_serial_num,
- &csig_callee, NULL,
- &mname_callee, &msig_callee, NULL, NULL);
- }
-
- if (num_frames > 1) {
- get_frame_details(env, key->frames[1], &frame_serial_num,
- &csig_caller, NULL,
- &mname_caller, &msig_caller, NULL, NULL);
- }
-
- io_write_oldprof_elem(info->num_hits, num_frames,
- csig_callee, mname_callee, msig_callee,
- csig_caller, mname_caller, msig_caller,
- (int)info->total_cost);
-
- jvmtiDeallocate(csig_callee);
- jvmtiDeallocate(mname_callee);
- jvmtiDeallocate(msig_callee);
- jvmtiDeallocate(csig_caller);
- jvmtiDeallocate(mname_caller);
- jvmtiDeallocate(msig_caller);
- }
-
- io_write_oldprof_footer();
-
- HPROF_FREE(iterate.traces);
-
- } rawMonitorExit(gdata->data_access_lock);
-}
-
-void
-trace_clear_cost(void)
-{
- table_walk_items(gdata->trace_table, &clear_cost, NULL);
-}
--- a/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_trace.h Thu Aug 20 12:29:58 2015 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,74 +0,0 @@
-/*
- * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * - Neither the name of Oracle nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
- * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/*
- * This source code is provided to illustrate the usage of a given feature
- * or technique and has been deliberately simplified. Additional steps
- * required for a production-quality application, such as security checks,
- * input validation and proper error handling, might not be present in
- * this sample code.
- */
-
-
-#ifndef HPROF_TRACE_H
-#define HPROF_TRACE_H
-
-void trace_increment_all_sample_costs(jint count, jthread *threads,
- SerialNumber *thread_serial_nums, int depth,
- jboolean skip_init);
-
-void trace_get_all_current(jint count, jthread *threads,
- SerialNumber *thread_serial_nums, int depth,
- jboolean skip_init, TraceIndex *traces,
- jboolean always_care);
-
-TraceIndex trace_get_current(jthread thread,
- SerialNumber thread_serial_num, int depth,
- jboolean skip_init,
- FrameIndex *frames_buffer,
- jvmtiFrameInfo *jframes_buffer);
-
-void trace_init(void);
-TraceIndex trace_find_or_create(SerialNumber thread_serial_num,
- jint n_frames, FrameIndex *frames,
- jvmtiFrameInfo *jframes_buffer);
-SerialNumber trace_get_serial_number(TraceIndex index);
-void trace_increment_cost(TraceIndex index,
- jint num_hits, jlong self_cost, jlong total_cost);
-void trace_list(void);
-void trace_cleanup(void);
-
-void trace_clear_cost(void);
-void trace_output_unmarked(JNIEnv *env);
-void trace_output_cost(JNIEnv *env, double cutoff);
-void trace_output_cost_in_prof_format(JNIEnv *env);
-
-#endif
--- a/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_tracker.c Thu Aug 20 12:29:58 2015 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,320 +0,0 @@
-/*
- * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * - Neither the name of Oracle nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
- * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/*
- * This source code is provided to illustrate the usage of a given feature
- * or technique and has been deliberately simplified. Additional steps
- * required for a production-quality application, such as security checks,
- * input validation and proper error handling, might not be present in
- * this sample code.
- */
-
-
-/* Tracker class support functions. */
-
-/*
- * This file contains the native support calls for the Tracker
- * class. These native methods are registered and not made extern.
- * Tracking is engaged by using JNI to assign to a static field in the
- * Tracker class.
- *
- * Just like JVMTI callbacks, it's best that we keep track of these so that
- * when the VM_DEATH happens we know to wait for them to complete.
- *
- * This file also contains the functions that will initialize the Tracker
- * interface for BCI and identify the Tracker methods to make sure
- * they are not included in any stack traces obtained from JVMTI.
- *
- * RFE: The performance of the java injected code calling native methods
- * could be an issue here, cpu=times seems to be the worst where
- * a native call is made for entry and exit, even on the smallest
- * Java method. The alternative would be to cache the data on
- * the Java side, and either push it out to the native side, or
- * use some kind of pull from the native side, or even using
- * shared memory or a socket. However having said that, the
- * current performance issues are more around sheer memory needed,
- * and repeated calls to GetThreadCpuTime(), which is being investigated.
- *
- */
-
-#include "hprof.h"
-
-/* Macros to surround tracker based callback code.
- * Also see BEGIN_CALLBACK and END_CALLBACK in hprof_init.c.
- * If the VM_DEATH callback is active in the begining, then this callback
- * just blocks (it is assumed we don't want to return to the VM).
- * If the VM_DEATH callback is active at the end, then this callback
- * will notify the VM_DEATH callback if it's the last one.
- *
- * WARNING: No not 'return' or 'goto' out of the BEGIN_TRACKER_CALLBACK/END_TRACKER_CALLBACK
- * block, this will mess up the count.
- */
-
-#define BEGIN_TRACKER_CALLBACK() \
-{ /* BEGIN OF TRACKER_CALLBACK */ \
- jboolean bypass = JNI_TRUE; \
- rawMonitorEnter(gdata->callbackLock); { \
- if ( gdata->tracking_engaged != 0 ) { \
- if (!gdata->vm_death_callback_active) { \
- gdata->active_callbacks++; \
- bypass = JNI_FALSE; \
- } \
- } \
- } rawMonitorExit(gdata->callbackLock); \
- if ( !bypass ) { \
- /* BODY OF TRACKER_CALLBACK CODE */
-
-#define END_TRACKER_CALLBACK() /* Part of bypass if body */ \
- rawMonitorEnter(gdata->callbackLock); { \
- gdata->active_callbacks--; \
- if (gdata->active_callbacks < 0) { \
- HPROF_ERROR(JNI_TRUE, "Problems tracking callbacks"); \
- } \
- if (gdata->vm_death_callback_active) { \
- if (gdata->active_callbacks == 0) { \
- rawMonitorNotifyAll(gdata->callbackLock); \
- } \
- } \
- } rawMonitorExit(gdata->callbackLock); \
- } \
-} /* END OF TRACKER_CALLBACK */
-
-
-/*
- * Class: Tracker
- * Method: nativeNewArray
- * Signature: (Ljava/lang/Object;Ljava/lang/Object;)V
- */
-static void JNICALL
-Tracker_nativeNewArray
- (JNIEnv *env, jclass clazz, jobject thread, jobject obj)
-{
- BEGIN_TRACKER_CALLBACK() {
- event_newarray(env, thread, obj);
- } END_TRACKER_CALLBACK();
-}
-
-/*
- * Class: Tracker
- * Method: nativeObjectInit
- * Signature: (Ljava/lang/Object;Ljava/lang/Object;)V
- */
-static void JNICALL
-Tracker_nativeObjectInit
- (JNIEnv *env, jclass clazz, jobject thread, jobject obj)
-{
- BEGIN_TRACKER_CALLBACK() {
- event_object_init(env, thread, obj);
- } END_TRACKER_CALLBACK();
-}
-
-/*
- * Class: Tracker
- * Method: nativeCallSite
- * Signature: (Ljava/lang/Object;II)V
- */
-static void JNICALL
-Tracker_nativeCallSite
- (JNIEnv *env, jclass clazz, jobject thread, jint cnum, jint mnum)
-{
- BEGIN_TRACKER_CALLBACK() {
- event_call(env, thread, cnum, mnum);
- } END_TRACKER_CALLBACK();
-}
-
-/*
- * Class: Tracker
- * Method: nativeReturnSite
- * Signature: (Ljava/lang/Object;II)V
- */
-static void JNICALL
-Tracker_nativeReturnSite
- (JNIEnv *env, jclass clazz, jobject thread, jint cnum, jint mnum)
-{
- BEGIN_TRACKER_CALLBACK() {
- event_return(env, thread, cnum, mnum);
- } END_TRACKER_CALLBACK();
-}
-
-
-/* ------------------------------------------------------------------- */
-/* Set Java static field to turn on native code calls in Tracker. */
-
-static void
-set_engaged(JNIEnv *env, jint engaged)
-{
- LOG3("set_engaged()", "engaging tracking", engaged);
-
- if ( ! gdata->bci ) {
- return;
- }
- rawMonitorEnter(gdata->callbackLock); {
- if ( gdata->tracking_engaged != engaged ) {
- jfieldID field;
- jclass tracker_class;
-
- tracker_class = class_get_class(env, gdata->tracker_cnum);
- gdata->tracking_engaged = 0;
- /* Activate or deactivate the injection code on the Java side */
- HPROF_ASSERT(tracker_class!=NULL);
- exceptionClear(env);
- field = getStaticFieldID(env, tracker_class,
- TRACKER_ENGAGED_NAME, TRACKER_ENGAGED_SIG);
- setStaticIntField(env, tracker_class, field, engaged);
- exceptionClear(env);
-
- LOG3("set_engaged()", "tracking engaged", engaged);
-
- gdata->tracking_engaged = engaged;
- }
- } rawMonitorExit(gdata->callbackLock);
-}
-
-void
-tracker_engage(JNIEnv *env)
-{
- set_engaged(env, 0xFFFF);
-}
-
-void
-tracker_disengage(JNIEnv *env)
-{
- set_engaged(env, 0);
-}
-
-jboolean
-tracker_method(jmethodID method)
-{
- int i;
-
- if ( ! gdata->bci ) {
- return JNI_FALSE;
- }
-
- HPROF_ASSERT(method!=NULL);
- HPROF_ASSERT(gdata->tracker_method_count > 0);
- for ( i = 0 ; i < gdata->tracker_method_count ; i++ ) {
- HPROF_ASSERT(gdata->tracker_methods[i].method!=NULL);
- if ( method == gdata->tracker_methods[i].method ) {
- return JNI_TRUE;
- }
- }
- return JNI_FALSE;
-}
-
-static JNINativeMethod registry[4] =
-{
- { TRACKER_NEWARRAY_NATIVE_NAME, TRACKER_NEWARRAY_NATIVE_SIG,
- (void*)&Tracker_nativeNewArray },
- { TRACKER_OBJECT_INIT_NATIVE_NAME, TRACKER_OBJECT_INIT_NATIVE_SIG,
- (void*)&Tracker_nativeObjectInit },
- { TRACKER_CALL_NATIVE_NAME, TRACKER_CALL_NATIVE_SIG,
- (void*)&Tracker_nativeCallSite },
- { TRACKER_RETURN_NATIVE_NAME, TRACKER_RETURN_NATIVE_SIG,
- (void*)&Tracker_nativeReturnSite }
-};
-
-static struct {
- char *name;
- char *sig;
-} tracker_methods[] =
- {
- { TRACKER_NEWARRAY_NAME, TRACKER_NEWARRAY_SIG },
- { TRACKER_OBJECT_INIT_NAME, TRACKER_OBJECT_INIT_SIG },
- { TRACKER_CALL_NAME, TRACKER_CALL_SIG },
- { TRACKER_RETURN_NAME, TRACKER_RETURN_SIG },
- { TRACKER_NEWARRAY_NATIVE_NAME, TRACKER_NEWARRAY_NATIVE_SIG },
- { TRACKER_OBJECT_INIT_NATIVE_NAME, TRACKER_OBJECT_INIT_NATIVE_SIG },
- { TRACKER_CALL_NATIVE_NAME, TRACKER_CALL_NATIVE_SIG },
- { TRACKER_RETURN_NATIVE_NAME, TRACKER_RETURN_NATIVE_SIG }
- };
-
-void
-tracker_setup_class(void)
-{
- ClassIndex cnum;
- LoaderIndex loader_index;
-
- HPROF_ASSERT(gdata->tracker_cnum==0);
- loader_index = loader_find_or_create(NULL,NULL);
- cnum = class_find_or_create(TRACKER_CLASS_SIG, loader_index);
- gdata->tracker_cnum = cnum;
- HPROF_ASSERT(cnum!=0);
- class_add_status(cnum, CLASS_SPECIAL);
-}
-
-void
-tracker_setup_methods(JNIEnv *env)
-{
- ClassIndex cnum;
- LoaderIndex loader_index;
- int i;
- jclass object_class;
- jclass tracker_class;
-
- if ( ! gdata->bci ) {
- return;
- }
-
- loader_index = loader_find_or_create(NULL,NULL);
- cnum = class_find_or_create(OBJECT_CLASS_SIG, loader_index);
- object_class = class_get_class(env, cnum);
- tracker_class = class_get_class(env, gdata->tracker_cnum);
-
- CHECK_EXCEPTIONS(env) {
- registerNatives(env, tracker_class, registry,
- (int)sizeof(registry)/(int)sizeof(registry[0]));
- } END_CHECK_EXCEPTIONS;
-
- HPROF_ASSERT(tracker_class!=NULL);
-
- gdata->tracker_method_count =
- (int)sizeof(tracker_methods)/(int)sizeof(tracker_methods[0]);
-
- HPROF_ASSERT(gdata->tracker_method_count <=
- (int)(sizeof(gdata->tracker_methods)/sizeof(gdata->tracker_methods[0])));
-
- CHECK_EXCEPTIONS(env) {
- gdata->object_init_method = getMethodID(env, object_class,
- OBJECT_INIT_NAME, OBJECT_INIT_SIG);
- for ( i=0 ; i < gdata->tracker_method_count ; i++ ) {
- gdata->tracker_methods[i].name =
- string_find_or_create(tracker_methods[i].name);
- gdata->tracker_methods[i].sig =
- string_find_or_create(tracker_methods[i].sig);
- gdata->tracker_methods[i].method =
- getStaticMethodID(env, tracker_class,
- tracker_methods[i].name, tracker_methods[i].sig);
- HPROF_ASSERT(gdata->tracker_methods[i].method!=NULL);
- LOG2("tracker_setup_methods(): Found", tracker_methods[i].name);
- }
- } END_CHECK_EXCEPTIONS;
-}
--- a/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_tracker.h Thu Aug 20 12:29:58 2015 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,84 +0,0 @@
-/*
- * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * - Neither the name of Oracle nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
- * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/*
- * This source code is provided to illustrate the usage of a given feature
- * or technique and has been deliberately simplified. Additional steps
- * required for a production-quality application, such as security checks,
- * input validation and proper error handling, might not be present in
- * this sample code.
- */
-
-
-#ifndef HPROF_TRACKER_H
-#define HPROF_TRACKER_H
-
-/* The internal qualified classname */
-
-#define OBJECT_CLASS_SIG "Ljava/lang/Object;"
-#define OBJECT_INIT_NAME "<init>"
-#define OBJECT_INIT_SIG "()V"
-
-#define TRACKER_PACKAGE "com/sun/demo/jvmti/hprof"
-#define TRACKER_CLASS_NAME TRACKER_PACKAGE "/Tracker"
-#define TRACKER_CLASS_SIG "L" TRACKER_CLASS_NAME ";"
-
-#define TRACKER_NEWARRAY_NAME "NewArray"
-#define TRACKER_NEWARRAY_SIG "(Ljava/lang/Object;)V"
-#define TRACKER_NEWARRAY_NATIVE_NAME "nativeNewArray"
-#define TRACKER_NEWARRAY_NATIVE_SIG "(Ljava/lang/Object;Ljava/lang/Object;)V"
-
-#define TRACKER_OBJECT_INIT_NAME "ObjectInit"
-#define TRACKER_OBJECT_INIT_SIG "(Ljava/lang/Object;)V"
-#define TRACKER_OBJECT_INIT_NATIVE_NAME "nativeObjectInit"
-#define TRACKER_OBJECT_INIT_NATIVE_SIG "(Ljava/lang/Object;Ljava/lang/Object;)V"
-
-#define TRACKER_CALL_NAME "CallSite"
-#define TRACKER_CALL_SIG "(II)V"
-#define TRACKER_CALL_NATIVE_NAME "nativeCallSite"
-#define TRACKER_CALL_NATIVE_SIG "(Ljava/lang/Object;II)V"
-
-
-#define TRACKER_RETURN_NAME "ReturnSite"
-#define TRACKER_RETURN_SIG "(II)V"
-#define TRACKER_RETURN_NATIVE_NAME "nativeReturnSite"
-#define TRACKER_RETURN_NATIVE_SIG "(Ljava/lang/Object;II)V"
-
-#define TRACKER_ENGAGED_NAME "engaged"
-#define TRACKER_ENGAGED_SIG "I"
-
-void tracker_setup_class(void);
-void tracker_setup_methods(JNIEnv *env);
-void tracker_engage(JNIEnv *env);
-void tracker_disengage(JNIEnv *env);
-jboolean tracker_method(jmethodID method);
-
-#endif
--- a/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_util.c Thu Aug 20 12:29:58 2015 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,1738 +0,0 @@
-/*
- * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * - Neither the name of Oracle nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
- * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/*
- * This source code is provided to illustrate the usage of a given feature
- * or technique and has been deliberately simplified. Additional steps
- * required for a production-quality application, such as security checks,
- * input validation and proper error handling, might not be present in
- * this sample code.
- */
-
-
-/* General utility functions. */
-
-/*
- * Wrappers over JVM, JNI, and JVMTI functions are placed here.
- *
- * All memory allocation and deallocation goes through jvmtiAllocate()
- * and jvmtiDeallocate().
- *
- */
-
-
-#include "hprof.h"
-
-/* Macro to get JNI function pointer. */
-#define JNI_FUNC_PTR(env,f) (*((*(env))->f))
-
-/* Macro to get JVM function pointer. */
-#define JVM_FUNC_PTR(env,f) (*((*(env))->f))
-
-/* Macro to get JVMTI function pointer. */
-#define JVMTI_FUNC_PTR(env,f) (*((*(env))->f))
-
-/* ------------------------------------------------------------------- */
-/* JVM functions */
-
-JNIEnv *
-getEnv(void)
-{
- JNIEnv *env;
- jint res;
-
- res = JVM_FUNC_PTR(gdata->jvm,GetEnv)
- (gdata->jvm, (void **)&env, JNI_VERSION_1_2);
- if (res != JNI_OK) {
- char buf[256];
-
- (void)md_snprintf(buf, sizeof(buf),
- "Unable to access JNI Version 1.2 (0x%x),"
- " is your JDK a 5.0 or newer version?"
- " JNIEnv's GetEnv() returned %d",
- JNI_VERSION_1_2, res);
- buf[sizeof(buf)-1] = 0;
- HPROF_ERROR(JNI_FALSE, buf);
- error_exit_process(1); /* Kill entire process, no core dump */
- }
- return env;
-}
-
-/* ------------------------------------------------------------------- */
-/* Memory Allocation */
-
-void *
-jvmtiAllocate(int size)
-{
- jvmtiError error;
- unsigned char *ptr;
-
- HPROF_ASSERT(size>=0);
- ptr = NULL;
- if ( size == 0 ) {
- return ptr;
- }
- error = JVMTI_FUNC_PTR(gdata->jvmti,Allocate)
- (gdata->jvmti, (jlong)size, &ptr);
- if ( error != JVMTI_ERROR_NONE || ptr == NULL ) {
- HPROF_JVMTI_ERROR(error, "Cannot allocate jvmti memory");
- }
- return (void*)ptr;
-}
-
-void
-jvmtiDeallocate(void *ptr)
-{
- if ( ptr != NULL ) {
- jvmtiError error;
-
- error = JVMTI_FUNC_PTR(gdata->jvmti,Deallocate)
- (gdata->jvmti, (unsigned char*)ptr);
- if ( error != JVMTI_ERROR_NONE ) {
- HPROF_JVMTI_ERROR(error, "Cannot deallocate jvmti memory");
- }
- }
-}
-
-#ifdef DEBUG
-
-void *
-hprof_debug_malloc(int size, char *file, int line)
-{
- void *ptr;
-
- HPROF_ASSERT(size>0);
-
- rawMonitorEnter(gdata->debug_malloc_lock); {
- ptr = debug_malloc(size, file, line);
- } rawMonitorExit(gdata->debug_malloc_lock);
-
- if ( ptr == NULL ) {
- HPROF_ERROR(JNI_TRUE, "Cannot allocate malloc memory");
- }
- return ptr;
-}
-
-void
-hprof_debug_free(void *ptr, char *file, int line)
-{
- HPROF_ASSERT(ptr!=NULL);
-
- rawMonitorEnter(gdata->debug_malloc_lock); {
- (void)debug_free(ptr, file, line);
- } rawMonitorExit(gdata->debug_malloc_lock);
-}
-
-#endif
-
-void *
-hprof_malloc(int size)
-{
- void *ptr;
-
- HPROF_ASSERT(size>0);
- ptr = malloc(size);
- if ( ptr == NULL ) {
- HPROF_ERROR(JNI_TRUE, "Cannot allocate malloc memory");
- }
- return ptr;
-}
-
-void
-hprof_free(void *ptr)
-{
- HPROF_ASSERT(ptr!=NULL);
- (void)free(ptr);
-}
-
-/* ------------------------------------------------------------------- */
-/* JVMTI Version functions */
-
-jint
-jvmtiVersion(void)
-{
- if (gdata->cachedJvmtiVersion == 0) {
- jvmtiError error;
-
- error = JVMTI_FUNC_PTR(gdata->jvmti,GetVersionNumber)
- (gdata->jvmti, &(gdata->cachedJvmtiVersion));
- if (error != JVMTI_ERROR_NONE) {
- HPROF_JVMTI_ERROR(error, "Cannot get jvmti version number");
- }
- }
- return gdata->cachedJvmtiVersion;
-}
-
-static jint
-jvmtiMajorVersion(void)
-{
- return (jvmtiVersion() & JVMTI_VERSION_MASK_MAJOR)
- >> JVMTI_VERSION_SHIFT_MAJOR;
-}
-
-static jint
-jvmtiMinorVersion(void)
-{
- return (jvmtiVersion() & JVMTI_VERSION_MASK_MINOR)
- >> JVMTI_VERSION_SHIFT_MINOR;
-}
-
-static jint
-jvmtiMicroVersion(void)
-{
- return (jvmtiVersion() & JVMTI_VERSION_MASK_MICRO)
- >> JVMTI_VERSION_SHIFT_MICRO;
-}
-
-/* Logic to determine JVMTI version compatibility */
-static jboolean
-compatible_versions(jint major_runtime, jint minor_runtime,
- jint major_compiletime, jint minor_compiletime)
-{
- /* Runtime major version must match. */
- if ( major_runtime != major_compiletime ) {
- return JNI_FALSE;
- }
- /* Runtime minor version must be >= the version compiled with. */
- if ( minor_runtime < minor_compiletime ) {
- return JNI_FALSE;
- }
- /* Assumed compatible */
- return JNI_TRUE;
-}
-
-/* ------------------------------------------------------------------- */
-/* JVMTI Raw Monitor support functions */
-
-jrawMonitorID
-createRawMonitor(const char *str)
-{
- jvmtiError error;
- jrawMonitorID m;
-
- m = NULL;
- error = JVMTI_FUNC_PTR(gdata->jvmti,CreateRawMonitor)
- (gdata->jvmti, str, &m);
- if ( error != JVMTI_ERROR_NONE ) {
- HPROF_JVMTI_ERROR(error, "Cannot create raw monitor");
- }
- return m;
-}
-
-void
-rawMonitorEnter(jrawMonitorID m)
-{
- jvmtiError error;
-
- error = JVMTI_FUNC_PTR(gdata->jvmti,RawMonitorEnter)
- (gdata->jvmti, m);
- if ( error == JVMTI_ERROR_WRONG_PHASE ) {
- /* Treat this as ok, after agent shutdown CALLBACK code may call this */
- error = JVMTI_ERROR_NONE;
- }
- if ( error != JVMTI_ERROR_NONE ) {
- HPROF_JVMTI_ERROR(error, "Cannot enter with raw monitor");
- }
-}
-
-void
-rawMonitorWait(jrawMonitorID m, jlong pause_time)
-{
- jvmtiError error;
-
- error = JVMTI_FUNC_PTR(gdata->jvmti,RawMonitorWait)
- (gdata->jvmti, m, pause_time);
- if ( error != JVMTI_ERROR_NONE ) {
- HPROF_JVMTI_ERROR(error, "Cannot wait with raw monitor");
- }
-}
-
-void
-rawMonitorNotifyAll(jrawMonitorID m)
-{
- jvmtiError error;
-
- error = JVMTI_FUNC_PTR(gdata->jvmti,RawMonitorNotifyAll)
- (gdata->jvmti, m);
- if ( error != JVMTI_ERROR_NONE ) {
- HPROF_JVMTI_ERROR(error, "Cannot notify all with raw monitor");
- }
-}
-
-void
-rawMonitorExit(jrawMonitorID m)
-{
- jvmtiError error;
-
- error = JVMTI_FUNC_PTR(gdata->jvmti,RawMonitorExit)
- (gdata->jvmti, m);
- if ( error == JVMTI_ERROR_WRONG_PHASE ) {
- /* Treat this as ok, after agent shutdown CALLBACK code may call this */
- error = JVMTI_ERROR_NONE;
- }
- if ( error != JVMTI_ERROR_NONE ) {
- HPROF_JVMTI_ERROR(error, "Cannot exit with raw monitor");
- }
-}
-
-void
-destroyRawMonitor(jrawMonitorID m)
-{
- jvmtiError error;
-
- error = JVMTI_FUNC_PTR(gdata->jvmti,DestroyRawMonitor)
- (gdata->jvmti, m);
- if ( error == JVMTI_ERROR_WRONG_PHASE ) {
- /* Treat this as ok */
- error = JVMTI_ERROR_NONE;
- }
- if ( error != JVMTI_ERROR_NONE ) {
- HPROF_JVMTI_ERROR(error, "Cannot destroy raw monitor");
- }
-}
-
-/* ------------------------------------------------------------------- */
-/* JVMTI Event enabling/disabilin */
-
-void
-setEventNotificationMode(jvmtiEventMode mode, jvmtiEvent event, jthread thread)
-{
- jvmtiError error;
-
- error = JVMTI_FUNC_PTR(gdata->jvmti,SetEventNotificationMode)
- (gdata->jvmti, mode, event, thread);
- if ( error != JVMTI_ERROR_NONE ) {
- HPROF_JVMTI_ERROR(error, "Cannot set event notification");
- }
-}
-
-/* ---------------------------------------------------------------------- */
-/* JNI Support Functions */
-
-jobject
-exceptionOccurred(JNIEnv *env)
-{
- return JNI_FUNC_PTR(env,ExceptionOccurred)(env);
-}
-
-void
-exceptionDescribe(JNIEnv *env)
-{
- JNI_FUNC_PTR(env,ExceptionDescribe)(env);
-}
-
-void
-exceptionClear(JNIEnv *env)
-{
- JNI_FUNC_PTR(env,ExceptionClear)(env);
-}
-
-jobject
-newGlobalReference(JNIEnv *env, jobject object)
-{
- jobject gref;
-
- HPROF_ASSERT(env!=NULL);
- HPROF_ASSERT(object!=NULL);
- gref = JNI_FUNC_PTR(env,NewGlobalRef)(env, object);
- HPROF_ASSERT(gref!=NULL);
- return gref;
-}
-
-jobject
-newWeakGlobalReference(JNIEnv *env, jobject object)
-{
- jobject gref;
-
- HPROF_ASSERT(env!=NULL);
- HPROF_ASSERT(object!=NULL);
- gref = JNI_FUNC_PTR(env,NewWeakGlobalRef)(env, object);
- HPROF_ASSERT(gref!=NULL);
- return gref;
-}
-
-void
-deleteGlobalReference(JNIEnv *env, jobject object)
-{
- HPROF_ASSERT(env!=NULL);
- HPROF_ASSERT(object!=NULL);
- JNI_FUNC_PTR(env,DeleteGlobalRef)(env, object);
-}
-
-jobject
-newLocalReference(JNIEnv *env, jobject object)
-{
- jobject lref;
-
- HPROF_ASSERT(env!=NULL);
- HPROF_ASSERT(object!=NULL);
- lref = JNI_FUNC_PTR(env,NewLocalRef)(env, object);
- /* Possible for a non-null weak reference to return a NULL localref */
- return lref;
-}
-
-void
-deleteLocalReference(JNIEnv *env, jobject object)
-{
- HPROF_ASSERT(env!=NULL);
- HPROF_ASSERT(object!=NULL);
- JNI_FUNC_PTR(env,DeleteLocalRef)(env, object);
-}
-
-void
-deleteWeakGlobalReference(JNIEnv *env, jobject object)
-{
- HPROF_ASSERT(env!=NULL);
- HPROF_ASSERT(object!=NULL);
- JNI_FUNC_PTR(env,DeleteWeakGlobalRef)(env, object);
-}
-
-jclass
-getObjectClass(JNIEnv *env, jobject object)
-/* WARNING: Must be called inside WITH_LOCAL_REFS */
-{
- jclass clazz;
-
- HPROF_ASSERT(env!=NULL);
- HPROF_ASSERT(object!=NULL);
- clazz = JNI_FUNC_PTR(env,GetObjectClass)(env, object);
- HPROF_ASSERT(clazz!=NULL);
- return clazz;
-}
-
-jclass
-getSuperclass(JNIEnv *env, jclass klass)
-/* WARNING: Must be called inside WITH_LOCAL_REFS */
-{
- jclass super_klass;
-
- HPROF_ASSERT(env!=NULL);
- HPROF_ASSERT(klass!=NULL);
- super_klass = JNI_FUNC_PTR(env,GetSuperclass)(env, klass);
- return super_klass;
-}
-
-jmethodID
-getStaticMethodID(JNIEnv *env, jclass clazz, const char *name, const char *sig)
-{
- jmethodID method;
-
- HPROF_ASSERT(env!=NULL);
- HPROF_ASSERT(clazz!=NULL);
- HPROF_ASSERT(name!=NULL);
- HPROF_ASSERT(sig!=NULL);
- CHECK_EXCEPTIONS(env) {
- method = JNI_FUNC_PTR(env,GetStaticMethodID)(env, clazz, name, sig);
- } END_CHECK_EXCEPTIONS;
- HPROF_ASSERT(method!=NULL);
- return method;
-}
-
-jmethodID
-getMethodID(JNIEnv *env, jclass clazz, const char *name, const char *sig)
-{
- jmethodID method;
- jobject exception;
-
- HPROF_ASSERT(env!=NULL);
- HPROF_ASSERT(clazz!=NULL);
- HPROF_ASSERT(name!=NULL);
- HPROF_ASSERT(sig!=NULL);
- method = JNI_FUNC_PTR(env,GetMethodID)(env, clazz, name, sig);
- /* Might be a static method */
- exception = JNI_FUNC_PTR(env,ExceptionOccurred)(env);
- if ( exception != NULL ) {
- JNI_FUNC_PTR(env,ExceptionClear)(env);
- method = getStaticMethodID(env, clazz, name, sig);
- }
- HPROF_ASSERT(method!=NULL);
- return method;
-}
-
-jclass
-findClass(JNIEnv *env, const char *name)
-/* WARNING: Must be called inside WITH_LOCAL_REFS */
-{
- jclass clazz;
-
- HPROF_ASSERT(env!=NULL);
- HPROF_ASSERT(name!=NULL);
- LOG2("FindClass", name);
- CHECK_EXCEPTIONS(env) {
- clazz = JNI_FUNC_PTR(env,FindClass)(env, name);
- } END_CHECK_EXCEPTIONS;
- HPROF_ASSERT(clazz!=NULL);
- return clazz;
-}
-
-jfieldID
-getStaticFieldID(JNIEnv *env, jclass clazz, const char *name, const char *sig)
-{
- jfieldID field;
-
- HPROF_ASSERT(env!=NULL);
- HPROF_ASSERT(clazz!=NULL);
- HPROF_ASSERT(name!=NULL);
- HPROF_ASSERT(sig!=NULL);
- CHECK_EXCEPTIONS(env) {
- field = JNI_FUNC_PTR(env,GetStaticFieldID)(env, clazz, name, sig);
- } END_CHECK_EXCEPTIONS;
- return field;
-}
-
-void
-setStaticIntField(JNIEnv *env, jclass clazz, jfieldID field, jint value)
-{
- HPROF_ASSERT(env!=NULL);
- HPROF_ASSERT(clazz!=NULL);
- HPROF_ASSERT(field!=NULL);
- CHECK_EXCEPTIONS(env) {
- JNI_FUNC_PTR(env,SetStaticIntField)(env, clazz, field, value);
- } END_CHECK_EXCEPTIONS;
-}
-
-static jobject
-callStaticObjectMethod(JNIEnv *env, jclass klass, jmethodID method)
-{
- jobject x;
-
- HPROF_ASSERT(env!=NULL);
- HPROF_ASSERT(klass!=NULL);
- HPROF_ASSERT(method!=NULL);
- CHECK_EXCEPTIONS(env) {
- x = JNI_FUNC_PTR(env,CallStaticObjectMethod)(env, klass, method);
- } END_CHECK_EXCEPTIONS;
- return x;
-}
-
-static jlong
-callLongMethod(JNIEnv *env, jobject object, jmethodID method)
-{
- jlong x;
-
- HPROF_ASSERT(env!=NULL);
- HPROF_ASSERT(object!=NULL);
- HPROF_ASSERT(method!=NULL);
- CHECK_EXCEPTIONS(env) {
- x = JNI_FUNC_PTR(env,CallLongMethod)(env, object, method);
- } END_CHECK_EXCEPTIONS;
- return x;
-}
-
-static void
-callVoidMethod(JNIEnv *env, jobject object, jmethodID method, jboolean arg)
-{
- HPROF_ASSERT(env!=NULL);
- HPROF_ASSERT(object!=NULL);
- HPROF_ASSERT(method!=NULL);
- CHECK_EXCEPTIONS(env) {
- JNI_FUNC_PTR(env,CallVoidMethod)(env, object, method, arg);
- } END_CHECK_EXCEPTIONS;
-}
-
-static jstring
-newStringUTF(JNIEnv *env, const char *name)
-/* WARNING: Must be called inside WITH_LOCAL_REFS */
-{
- jstring string;
-
- HPROF_ASSERT(env!=NULL);
- HPROF_ASSERT(name!=NULL);
- CHECK_EXCEPTIONS(env) {
- string = JNI_FUNC_PTR(env,NewStringUTF)(env, name);
- } END_CHECK_EXCEPTIONS;
- HPROF_ASSERT(string!=NULL);
- return string;
-}
-
-static jobject
-newThreadObject(JNIEnv *env, jclass clazz, jmethodID method,
- jthreadGroup group, jstring name)
-/* WARNING: Must be called inside WITH_LOCAL_REFS */
-{
- jthread thread;
-
- HPROF_ASSERT(env!=NULL);
- HPROF_ASSERT(clazz!=NULL);
- HPROF_ASSERT(method!=NULL);
- CHECK_EXCEPTIONS(env) {
- thread = JNI_FUNC_PTR(env,NewObject)(env, clazz, method, group, name);
- } END_CHECK_EXCEPTIONS;
- HPROF_ASSERT(thread!=NULL);
- return thread;
-}
-
-jboolean
-isSameObject(JNIEnv *env, jobject o1, jobject o2)
-{
- HPROF_ASSERT(env!=NULL);
- if ( o1 == o2 || JNI_FUNC_PTR(env,IsSameObject)(env, o1, o2) ) {
- return JNI_TRUE;
- }
- return JNI_FALSE;
-}
-
-void
-pushLocalFrame(JNIEnv *env, jint capacity)
-{
- HPROF_ASSERT(env!=NULL);
- CHECK_EXCEPTIONS(env) {
- jint ret;
-
- ret = JNI_FUNC_PTR(env,PushLocalFrame)(env, capacity);
- if ( ret != 0 ) {
- HPROF_ERROR(JNI_TRUE, "JNI PushLocalFrame returned non-zero");
- }
- } END_CHECK_EXCEPTIONS;
-}
-
-void
-popLocalFrame(JNIEnv *env, jobject result)
-{
- jobject ret;
-
- HPROF_ASSERT(env!=NULL);
- ret = JNI_FUNC_PTR(env,PopLocalFrame)(env, result);
- if ( (result != NULL && ret == NULL) || (result == NULL && ret != NULL) ) {
- HPROF_ERROR(JNI_TRUE, "JNI PopLocalFrame returned wrong object");
- }
-}
-
-void
-registerNatives(JNIEnv *env, jclass clazz,
- JNINativeMethod *methods, jint count)
-{
- jint ret;
-
- HPROF_ASSERT(env!=NULL);
- HPROF_ASSERT(clazz!=NULL);
- HPROF_ASSERT(methods!=NULL);
- HPROF_ASSERT(count>0);
- ret = JNI_FUNC_PTR(env,RegisterNatives)(env, clazz, methods, count);
- if ( ret != 0 ) {
- HPROF_ERROR(JNI_TRUE, "JNI RegisterNatives returned non-zero");
- }
-}
-
-/* ---------------------------------------------------------------------- */
-/* JVMTI Support Functions */
-
-char *
-getErrorName(jvmtiError error_number)
-{
- char *error_name;
-
- error_name = NULL;
- (void)JVMTI_FUNC_PTR(gdata->jvmti,GetErrorName)
- (gdata->jvmti, error_number, &error_name);
- return error_name;
-}
-
-jvmtiPhase
-getPhase(void)
-{
- jvmtiPhase phase;
-
- phase = 0;
- (void)JVMTI_FUNC_PTR(gdata->jvmti,GetPhase)(gdata->jvmti, &phase);
- return phase;
-}
-
-char *
-phaseString(jvmtiPhase phase)
-{
- switch ( phase ) {
- case JVMTI_PHASE_ONLOAD:
- return "onload";
- case JVMTI_PHASE_PRIMORDIAL:
- return "primordial";
- case JVMTI_PHASE_START:
- return "start";
- case JVMTI_PHASE_LIVE:
- return "live";
- case JVMTI_PHASE_DEAD:
- return "dead";
- }
- return "unknown";
-}
-
-void
-disposeEnvironment(void)
-{
- (void)JVMTI_FUNC_PTR(gdata->jvmti,DisposeEnvironment)
- (gdata->jvmti);
-}
-
-jlong
-getObjectSize(jobject object)
-{
- jlong size;
- jvmtiError error;
-
- HPROF_ASSERT(object!=NULL);
- size = 0;
- error = JVMTI_FUNC_PTR(gdata->jvmti,GetObjectSize)
- (gdata->jvmti, object, &size);
- if ( error != JVMTI_ERROR_NONE ) {
- HPROF_JVMTI_ERROR(error, "Cannot get object size");
- }
- return size;
-}
-
-static jboolean
-isInterface(jclass klass)
-{
- jvmtiError error;
- jboolean answer;
-
- HPROF_ASSERT(klass!=NULL);
- answer = JNI_FALSE;
- error = JVMTI_FUNC_PTR(gdata->jvmti,IsInterface)
- (gdata->jvmti, klass, &answer);
- if ( error != JVMTI_ERROR_NONE ) {
- HPROF_JVMTI_ERROR(error, "Cannot call IsInterface");
- }
- return answer;
-}
-
-jint
-getClassStatus(jclass klass)
-{
- jvmtiError error;
- jint status;
-
- HPROF_ASSERT(klass!=NULL);
- status = 0;
- error = JVMTI_FUNC_PTR(gdata->jvmti,GetClassStatus)
- (gdata->jvmti, klass, &status);
- if ( error == JVMTI_ERROR_WRONG_PHASE ) {
- /* Treat this as ok */
- error = JVMTI_ERROR_NONE;
- status = 0;
- }
- if ( error != JVMTI_ERROR_NONE ) {
- HPROF_JVMTI_ERROR(error, "Cannot get class status");
- }
- return status;
-}
-
-jobject
-getClassLoader(jclass klass)
-/* WARNING: Must be called inside WITH_LOCAL_REFS */
-{
- jvmtiError error;
- jobject loader;
-
- HPROF_ASSERT(klass!=NULL);
- loader = NULL;
- error = JVMTI_FUNC_PTR(gdata->jvmti,GetClassLoader)
- (gdata->jvmti, klass, &loader);
- if ( error != JVMTI_ERROR_NONE ) {
- HPROF_JVMTI_ERROR(error, "Cannot get class loader");
- }
- return loader;
-}
-
-jlong
-getTag(jobject object)
-{
- jlong tag;
- jvmtiError error;
-
- HPROF_ASSERT(object!=NULL);
- tag = 0;
- error = JVMTI_FUNC_PTR(gdata->jvmti,GetTag)
- (gdata->jvmti, object, &tag);
- if ( error != JVMTI_ERROR_NONE ) {
- HPROF_JVMTI_ERROR(error, "Cannot get object tag");
- }
- return tag;
-}
-
-void
-setTag(jobject object, jlong tag)
-{
- jvmtiError error;
-
- HPROF_ASSERT(object!=NULL);
- error = JVMTI_FUNC_PTR(gdata->jvmti,SetTag)
- (gdata->jvmti, object, tag);
- if ( error != JVMTI_ERROR_NONE ) {
- HPROF_JVMTI_ERROR(error, "Cannot set object tag");
- }
-}
-
-void
-getObjectMonitorUsage(jobject object, jvmtiMonitorUsage *uinfo)
-{
- jvmtiError error;
-
- HPROF_ASSERT(object!=NULL);
- error = JVMTI_FUNC_PTR(gdata->jvmti,GetObjectMonitorUsage)
- (gdata->jvmti, object, uinfo);
- if ( error != JVMTI_ERROR_NONE ) {
- HPROF_JVMTI_ERROR(error, "Cannot get monitor usage info");
- }
-}
-
-void
-getOwnedMonitorInfo(jthread thread, jobject **ppobjects, jint *pcount)
-/* WARNING: Must be called inside WITH_LOCAL_REFS */
-{
- jvmtiError error;
-
- HPROF_ASSERT(thread!=NULL);
- HPROF_ASSERT(ppobjects!=NULL);
- HPROF_ASSERT(pcount!=NULL);
- *pcount = 0;
- *ppobjects = NULL;
- error = JVMTI_FUNC_PTR(gdata->jvmti,GetOwnedMonitorInfo)
- (gdata->jvmti, thread, pcount, ppobjects);
- if ( error == JVMTI_ERROR_THREAD_NOT_ALIVE ) {
- *pcount = 0;
- error = JVMTI_ERROR_NONE;
- }
- if ( error != JVMTI_ERROR_NONE ) {
- HPROF_JVMTI_ERROR(error, "Cannot get thread owned monitor info");
- }
-}
-
-void
-getSystemProperty(const char *name, char **value)
-{
- jvmtiError error;
-
- HPROF_ASSERT(name!=NULL);
- *value = NULL;
- error = JVMTI_FUNC_PTR(gdata->jvmti,GetSystemProperty)
- (gdata->jvmti, name, value);
- if ( error != JVMTI_ERROR_NONE ) {
- HPROF_JVMTI_ERROR(error, "Cannot get system property");
- }
-}
-
-void
-getClassSignature(jclass klass, char** psignature, char **pgeneric_signature)
-{
- jvmtiError error;
- char *generic_signature;
-
- HPROF_ASSERT(klass!=NULL);
- *psignature = NULL;
- error = JVMTI_FUNC_PTR(gdata->jvmti,GetClassSignature)
- (gdata->jvmti, klass, psignature, &generic_signature);
- if ( error != JVMTI_ERROR_NONE ) {
- HPROF_JVMTI_ERROR(error, "Cannot get class signature");
- }
- if ( pgeneric_signature != NULL ) {
- *pgeneric_signature = generic_signature;
- } else {
- jvmtiDeallocate(generic_signature);
- }
-}
-
-void
-getSourceFileName(jclass klass, char** pname)
-{
- jvmtiError error;
-
- HPROF_ASSERT(klass!=NULL);
- *pname = NULL;
- error = JVMTI_FUNC_PTR(gdata->jvmti,GetSourceFileName)
- (gdata->jvmti, klass, pname);
- if ( error == JVMTI_ERROR_ABSENT_INFORMATION ) {
- error = JVMTI_ERROR_NONE;
- *pname = NULL;
- }
- if ( error != JVMTI_ERROR_NONE ) {
- HPROF_JVMTI_ERROR(error, "Cannot get source file name");
- }
-}
-
-static void
-getClassFields(jclass klass, jint* pn_fields, jfieldID** pfields)
-{
- jvmtiError error;
- jint status;
-
- HPROF_ASSERT(klass!=NULL);
- *pn_fields = 0;
- *pfields = NULL;
-
- /* Get class status */
- status = getClassStatus(klass);
-
- /* Arrays have no fields */
- if ( status & JVMTI_CLASS_STATUS_ARRAY ) {
- return;
- }
-
- /* Primitives have no fields */
- if ( status & JVMTI_CLASS_STATUS_PRIMITIVE ) {
- return;
- }
-
- /* If the class is not prepared, we have a problem? */
- if ( !(status & JVMTI_CLASS_STATUS_PREPARED) ) {
- HPROF_ERROR(JNI_FALSE, "Class not prepared when needing fields");
- return;
- }
-
- /* Now try and get all the fields */
- error = JVMTI_FUNC_PTR(gdata->jvmti,GetClassFields)
- (gdata->jvmti, klass, pn_fields, pfields);
- if ( error != JVMTI_ERROR_NONE ) {
- HPROF_JVMTI_ERROR(error, "Cannot get class field list");
- }
-}
-
-static jint
-getFieldModifiers(jclass klass, jfieldID field)
-{
- jvmtiError error;
- jint modifiers;
-
- HPROF_ASSERT(klass!=NULL);
- HPROF_ASSERT(field!=NULL);
- modifiers = 0;
- error = JVMTI_FUNC_PTR(gdata->jvmti,GetFieldModifiers)
- (gdata->jvmti, klass, field, &modifiers);
- if ( error != JVMTI_ERROR_NONE ) {
- HPROF_JVMTI_ERROR(error, "Cannot get field modifiers");
- }
- return modifiers;
-}
-
-static void
-getFieldName(jclass klass, jfieldID field, char** pname, char** psignature,
- char **pgeneric_signature)
-{
- jvmtiError error;
- char *generic_signature;
-
- generic_signature = NULL;
- *pname = NULL;
- *psignature = NULL;
- error = JVMTI_FUNC_PTR(gdata->jvmti,GetFieldName)
- (gdata->jvmti, klass, field, pname, psignature, &generic_signature);
- if ( error != JVMTI_ERROR_NONE ) {
- HPROF_JVMTI_ERROR(error, "Cannot get field name");
- }
- if ( pgeneric_signature != NULL ) {
- *pgeneric_signature = generic_signature;
- } else {
- jvmtiDeallocate(generic_signature);
- }
-}
-
-static void
-getImplementedInterfaces(jclass klass, jint* pn_interfaces,
- jclass** pinterfaces)
-/* WARNING: Must be called inside WITH_LOCAL_REFS */
-{
- jvmtiError error;
-
- *pn_interfaces = 0;
- *pinterfaces = NULL;
- error = JVMTI_FUNC_PTR(gdata->jvmti,GetImplementedInterfaces)
- (gdata->jvmti, klass, pn_interfaces, pinterfaces);
- if ( error != JVMTI_ERROR_NONE ) {
- HPROF_JVMTI_ERROR(error, "Cannot get class interface list");
- }
-}
-
-static ClassIndex
-get_cnum(JNIEnv *env, jclass klass)
-/* WARNING: Must be called inside WITH_LOCAL_REFS */
-{
- ClassIndex cnum;
- LoaderIndex loader_index;
- char *sig;
- jobject loader;
-
- loader = getClassLoader(klass);
- loader_index = loader_find_or_create(env, loader);
- getClassSignature(klass, &sig, NULL);
- cnum = class_find_or_create(sig, loader_index);
- jvmtiDeallocate(sig);
- (void)class_new_classref(env, cnum, klass);
- return cnum;
-}
-
-/* From primitive type, get signature letter */
-char
-primTypeToSigChar(jvmtiPrimitiveType primType)
-{
- char sig_ch;
-
- sig_ch = 0;
- switch ( primType ) {
- case JVMTI_PRIMITIVE_TYPE_BYTE:
- sig_ch = JVM_SIGNATURE_BYTE;
- break;
- case JVMTI_PRIMITIVE_TYPE_CHAR:
- sig_ch = JVM_SIGNATURE_CHAR;
- break;
- case JVMTI_PRIMITIVE_TYPE_FLOAT:
- sig_ch = JVM_SIGNATURE_FLOAT;
- break;
- case JVMTI_PRIMITIVE_TYPE_DOUBLE:
- sig_ch = JVM_SIGNATURE_DOUBLE;
- break;
- case JVMTI_PRIMITIVE_TYPE_INT:
- sig_ch = JVM_SIGNATURE_INT;
- break;
- case JVMTI_PRIMITIVE_TYPE_LONG:
- sig_ch = JVM_SIGNATURE_LONG;
- break;
- case JVMTI_PRIMITIVE_TYPE_SHORT:
- sig_ch = JVM_SIGNATURE_SHORT;
- break;
- case JVMTI_PRIMITIVE_TYPE_BOOLEAN:
- sig_ch = JVM_SIGNATURE_BOOLEAN;
- break;
- default:
- sig_ch = 0;
- break;
- }
- return sig_ch;
-}
-
-/* From signature, get primitive type */
-jvmtiPrimitiveType
-sigToPrimType(char *sig)
-{
- jvmtiPrimitiveType primType;
-
- primType = 0;
- if ( sig == NULL || sig[0] == 0 ) {
- return primType;
- }
- switch ( sig[0] ) {
- case JVM_SIGNATURE_BYTE:
- primType = JVMTI_PRIMITIVE_TYPE_BYTE;
- break;
- case JVM_SIGNATURE_CHAR:
- primType = JVMTI_PRIMITIVE_TYPE_CHAR;
- break;
- case JVM_SIGNATURE_FLOAT:
- primType = JVMTI_PRIMITIVE_TYPE_FLOAT;
- break;
- case JVM_SIGNATURE_DOUBLE:
- primType = JVMTI_PRIMITIVE_TYPE_DOUBLE;
- break;
- case JVM_SIGNATURE_INT:
- primType = JVMTI_PRIMITIVE_TYPE_INT;
- break;
- case JVM_SIGNATURE_LONG:
- primType = JVMTI_PRIMITIVE_TYPE_LONG;
- break;
- case JVM_SIGNATURE_SHORT:
- primType = JVMTI_PRIMITIVE_TYPE_SHORT;
- break;
- case JVM_SIGNATURE_BOOLEAN:
- primType = JVMTI_PRIMITIVE_TYPE_BOOLEAN;
- break;
- }
- return primType;
-}
-
-/* From signature, get primitive size */
-int
-sigToPrimSize(char *sig)
-{
- unsigned size;
-
- size = 0;
- if ( sig == NULL || sig[0] == 0 ) {
- return size;
- }
- switch ( sig[0] ) {
- case JVM_SIGNATURE_BYTE:
- case JVM_SIGNATURE_BOOLEAN:
- size = 1;
- break;
- case JVM_SIGNATURE_CHAR:
- case JVM_SIGNATURE_SHORT:
- size = 2;
- break;
- case JVM_SIGNATURE_FLOAT:
- case JVM_SIGNATURE_INT:
- size = 4;
- break;
- case JVM_SIGNATURE_DOUBLE:
- case JVM_SIGNATURE_LONG:
- size = 8;
- break;
- }
- return size;
-}
-
-static void
-add_class_fields(JNIEnv *env, ClassIndex top_cnum, ClassIndex cnum,
- jclass klass, Stack *field_list, Stack *class_list)
-/* WARNING: Must be called inside WITH_LOCAL_REFS */
-{
- jclass *interfaces;
- jint n_interfaces;
- jfieldID *idlist;
- jint n_fields;
- int i;
- int depth;
- int skip_static_field_names;
- jint status;
-
- HPROF_ASSERT(env!=NULL);
- HPROF_ASSERT(klass!=NULL);
- HPROF_ASSERT(field_list!=NULL);
- HPROF_ASSERT(class_list!=NULL);
-
- /* If not the initial class, we can skip the static fields (perf issue) */
- skip_static_field_names = (cnum != top_cnum);
-
- /* Get class status */
- status = getClassStatus(klass);
-
- /* Arrays have no fields */
- if ( status & JVMTI_CLASS_STATUS_ARRAY ) {
- return;
- }
-
- /* Primitives have no fields */
- if ( status & JVMTI_CLASS_STATUS_PRIMITIVE ) {
- return;
- }
-
- /* If the class is not prepared, we have a problem? */
- if ( !(status & JVMTI_CLASS_STATUS_PREPARED) ) {
- char *sig;
-
- getClassSignature(klass, &sig, NULL);
- debug_message("Class signature is: %s\n", sig);
- HPROF_ERROR(JNI_FALSE, "Class not prepared when needing all fields");
- jvmtiDeallocate(sig);
- return;
- }
-
- /* See if class already processed */
- depth = stack_depth(class_list);
- for ( i = depth-1 ; i >= 0 ; i-- ) {
- if ( isSameObject(env, klass, *(jclass*)stack_element(class_list, i)) ) {
- return;
- }
- }
-
- /* Class or Interface, do implemented interfaces recursively */
- getImplementedInterfaces(klass, &n_interfaces, &interfaces);
- for ( i = 0 ; i < n_interfaces ; i++ ) {
- add_class_fields(env, top_cnum,
- get_cnum(env, interfaces[i]), interfaces[i],
- field_list, class_list);
- }
- jvmtiDeallocate(interfaces);
-
- /* Begin graph traversal, go up super chain recursively */
- if ( !isInterface(klass) ) {
- jclass super_klass;
-
- super_klass = getSuperclass(env, klass);
- if ( super_klass != NULL ) {
- add_class_fields(env, top_cnum,
- get_cnum(env, super_klass), super_klass,
- field_list, class_list);
- }
- }
-
-
- /* Only now we add klass to list so we don't repeat it later */
- stack_push(class_list, &klass);
-
- /* Now actually add the fields for this klass */
- getClassFields(klass, &n_fields, &idlist);
- for ( i = 0 ; i < n_fields ; i++ ) {
- FieldInfo finfo;
- static FieldInfo empty_finfo;
-
- finfo = empty_finfo;
- finfo.cnum = cnum;
- finfo.modifiers = (unsigned short)getFieldModifiers(klass, idlist[i]);
- if ( ( finfo.modifiers & JVM_ACC_STATIC ) == 0 ||
- !skip_static_field_names ) {
- char *field_name;
- char *field_sig;
-
- getFieldName(klass, idlist[i], &field_name, &field_sig, NULL);
- finfo.name_index = string_find_or_create(field_name);
- finfo.sig_index = string_find_or_create(field_sig);
- finfo.primType = sigToPrimType(field_sig);
- finfo.primSize = sigToPrimSize(field_sig);
- jvmtiDeallocate(field_name);
- jvmtiDeallocate(field_sig);
- }
- stack_push(field_list, &finfo);
- }
- jvmtiDeallocate(idlist);
-}
-
-void
-getAllClassFieldInfo(JNIEnv *env, jclass klass,
- jint* pn_fields, FieldInfo** pfields)
-{
- ClassIndex cnum;
-
- *pfields = NULL;
- *pn_fields = 0;
-
- WITH_LOCAL_REFS(env, 1) {
- Stack *class_list;
- Stack *field_list;
- int nbytes;
-
- cnum = get_cnum(env, klass);
- class_list = stack_init( 16, 16, (int)sizeof(jclass));
- field_list = stack_init(128, 128, (int)sizeof(FieldInfo));
- add_class_fields(env, cnum, cnum, klass, field_list, class_list);
- *pn_fields = stack_depth(field_list);
- if ( (*pn_fields) > 0 ) {
- nbytes = (*pn_fields) * (int)sizeof(FieldInfo);
- *pfields = (FieldInfo*)HPROF_MALLOC(nbytes);
- (void)memcpy(*pfields, stack_element(field_list, 0), nbytes);
- }
- stack_term(field_list);
- stack_term(class_list);
- } END_WITH_LOCAL_REFS;
-}
-
-void
-getMethodClass(jmethodID method, jclass *pclazz)
-/* WARNING: Must be called inside WITH_LOCAL_REFS */
-{
- jvmtiError error;
-
- HPROF_ASSERT(method!=NULL);
- *pclazz = NULL;
- error = JVMTI_FUNC_PTR(gdata->jvmti,GetMethodDeclaringClass)
- (gdata->jvmti, method, pclazz);
- if ( error != JVMTI_ERROR_NONE ) {
- HPROF_JVMTI_ERROR(error, "Cannot get method class");
- }
-}
-
-jboolean
-isMethodNative(jmethodID method)
-{
- jvmtiError error;
- jboolean isNative;
-
- HPROF_ASSERT(method!=NULL);
- error = JVMTI_FUNC_PTR(gdata->jvmti,IsMethodNative)
- (gdata->jvmti, method, &isNative);
- if ( error != JVMTI_ERROR_NONE ) {
- HPROF_JVMTI_ERROR(error, "Cannot check is method native");
- }
- return isNative;
-}
-
-void
-getMethodName(jmethodID method, char** pname, char** psignature)
-{
- jvmtiError error;
- char *generic_signature;
-
- HPROF_ASSERT(method!=NULL);
- generic_signature = NULL;
- *pname = NULL;
- *psignature = NULL;
- error = JVMTI_FUNC_PTR(gdata->jvmti,GetMethodName)
- (gdata->jvmti, method, pname, psignature, &generic_signature);
- if ( error != JVMTI_ERROR_NONE ) {
- HPROF_JVMTI_ERROR(error, "Cannot get method name");
- }
- jvmtiDeallocate(generic_signature);
-}
-
-void
-getPotentialCapabilities(jvmtiCapabilities *pcapabilities)
-{
- jvmtiError error;
-
- (void)memset(pcapabilities,0,sizeof(jvmtiCapabilities));
- error = JVMTI_FUNC_PTR(gdata->jvmti,GetPotentialCapabilities)
- (gdata->jvmti, pcapabilities);
- if (error != JVMTI_ERROR_NONE) {
- HPROF_ERROR(JNI_FALSE, "Unable to get potential JVMTI capabilities.");
- error_exit_process(1); /* Kill entire process, no core dump wanted */
- }
-}
-
-void
-addCapabilities(jvmtiCapabilities *pcapabilities)
-{
- jvmtiError error;
-
- error = JVMTI_FUNC_PTR(gdata->jvmti,AddCapabilities)
- (gdata->jvmti, pcapabilities);
- if (error != JVMTI_ERROR_NONE) {
- HPROF_ERROR(JNI_FALSE, "Unable to get necessary JVMTI capabilities.");
- error_exit_process(1); /* Kill entire process, no core dump wanted */
- }
-}
-
-void
-setEventCallbacks(jvmtiEventCallbacks *pcallbacks)
-{
- jvmtiError error;
-
- error = JVMTI_FUNC_PTR(gdata->jvmti,SetEventCallbacks)
- (gdata->jvmti, pcallbacks, (int)sizeof(jvmtiEventCallbacks));
- if (error != JVMTI_ERROR_NONE) {
- HPROF_JVMTI_ERROR(error, "Cannot set jvmti callbacks");
- }
-
-}
-
-void *
-getThreadLocalStorage(jthread thread)
-{
- jvmtiError error;
- void *ptr;
-
- HPROF_ASSERT(thread!=NULL);
- ptr = NULL;
- error = JVMTI_FUNC_PTR(gdata->jvmti,GetThreadLocalStorage)
- (gdata->jvmti, thread, &ptr);
- if ( error == JVMTI_ERROR_WRONG_PHASE ) {
- /* Treat this as ok */
- error = JVMTI_ERROR_NONE;
- ptr = NULL;
- }
- if ( error != JVMTI_ERROR_NONE ) {
- HPROF_JVMTI_ERROR(error, "Cannot get thread local storage");
- }
- return ptr;
-}
-
-void
-setThreadLocalStorage(jthread thread, void *ptr)
-{
- jvmtiError error;
-
- HPROF_ASSERT(thread!=NULL);
- error = JVMTI_FUNC_PTR(gdata->jvmti,SetThreadLocalStorage)
- (gdata->jvmti, thread, (const void *)ptr);
- if ( error == JVMTI_ERROR_WRONG_PHASE ) {
- /* Treat this as ok */
- error = JVMTI_ERROR_NONE;
- }
- if ( error != JVMTI_ERROR_NONE ) {
- HPROF_JVMTI_ERROR(error, "Cannot set thread local storage");
- }
-}
-
-void
-getThreadState(jthread thread, jint *threadState)
-{
- jvmtiError error;
-
- HPROF_ASSERT(thread!=NULL);
- HPROF_ASSERT(threadState!=NULL);
- *threadState = 0;
- error = JVMTI_FUNC_PTR(gdata->jvmti,GetThreadState)
- (gdata->jvmti, thread, threadState);
- if ( error != JVMTI_ERROR_NONE ) {
- HPROF_JVMTI_ERROR(error, "Cannot get thread state");
- }
-}
-
-void
-getThreadInfo(jthread thread, jvmtiThreadInfo *info)
-/* WARNING: Must be called inside WITH_LOCAL_REFS */
-{
- jvmtiError error;
-
- HPROF_ASSERT(thread!=NULL);
- HPROF_ASSERT(info!=NULL);
- (void)memset((void*)info, 0, sizeof(jvmtiThreadInfo));
- error = JVMTI_FUNC_PTR(gdata->jvmti,GetThreadInfo)
- (gdata->jvmti, thread, info);
- if ( error != JVMTI_ERROR_NONE ) {
- HPROF_JVMTI_ERROR(error, "Cannot get thread info");
- }
-}
-
-void
-getThreadGroupInfo(jthreadGroup thread_group, jvmtiThreadGroupInfo *info)
-/* WARNING: Must be called inside WITH_LOCAL_REFS */
-{
- jvmtiError error;
-
- HPROF_ASSERT(info!=NULL);
- (void)memset((void*)info, 0, sizeof(jvmtiThreadGroupInfo));
- error = JVMTI_FUNC_PTR(gdata->jvmti,GetThreadGroupInfo)
- (gdata->jvmti, thread_group, info);
- if ( error != JVMTI_ERROR_NONE ) {
- HPROF_JVMTI_ERROR(error, "Cannot get thread group info");
- }
-}
-
-void
-getLoadedClasses(jclass **ppclasses, jint *pcount)
-/* WARNING: Must be called inside WITH_LOCAL_REFS */
-{
- jvmtiError error;
-
- *ppclasses = NULL;
- *pcount = 0;
- error = JVMTI_FUNC_PTR(gdata->jvmti,GetLoadedClasses)
- (gdata->jvmti, pcount, ppclasses);
- if ( error != JVMTI_ERROR_NONE ) {
- HPROF_JVMTI_ERROR(error, "Cannot get all loaded class list");
- }
-}
-
-static void
-getLineNumberTable(jmethodID method, jvmtiLineNumberEntry **ppentries,
- jint *pcount)
-{
- jvmtiError error;
-
- HPROF_ASSERT(method!=NULL);
- *ppentries = NULL;
- *pcount = 0;
- error = JVMTI_FUNC_PTR(gdata->jvmti,GetLineNumberTable)
- (gdata->jvmti, method, pcount, ppentries);
- if ( error == JVMTI_ERROR_ABSENT_INFORMATION ) {
- error = JVMTI_ERROR_NONE;
- *ppentries = NULL;
- *pcount = 0;
- }
- if ( error != JVMTI_ERROR_NONE ) {
- HPROF_JVMTI_ERROR(error, "Cannot get source line numbers");
- }
-}
-
-static jint
-map_loc2line(jlocation location, jvmtiLineNumberEntry *table, jint count)
-{
- jint line_number;
- int i;
- int start;
- int half;
-
- HPROF_ASSERT(location>=0);
- HPROF_ASSERT(count>=0);
-
- line_number = -1;
- if ( count == 0 ) {
- return line_number;
- }
-
- /* Do a binary search */
- half = count >> 1;
- start = 0;
- while ( half > 0 ) {
- jlocation start_location;
-
- start_location = table[start + half].start_location;
- if ( location > start_location ) {
- start = start + half;
- } else if ( location == start_location ) {
- start = start + half;
- break;
- }
- half = half >> 1;
- }
-
- HPROF_ASSERT(start < count);
-
- /* Now start the table search */
- for ( i = start ; i < count ; i++ ) {
- if ( location < table[i].start_location ) {
- HPROF_ASSERT( ((int)location) < ((int)table[i].start_location) );
- break;
- }
- line_number = table[i].line_number;
- }
- HPROF_ASSERT(line_number > 0);
- return line_number;
-}
-
-jint
-getLineNumber(jmethodID method, jlocation location)
-{
- jvmtiLineNumberEntry *line_table;
- jint line_count;
- jint lineno;
-
- HPROF_ASSERT(method!=NULL);
- if ( location < 0 ) {
- HPROF_ASSERT(location > -4);
- return (jint)location;
- }
- lineno = -1;
-
- getLineNumberTable(method, &line_table, &line_count);
- lineno = map_loc2line(location, line_table, line_count);
- jvmtiDeallocate(line_table);
-
- return lineno;
-}
-
-jlong
-getMaxMemory(JNIEnv *env)
-{
- jlong max;
-
- HPROF_ASSERT(env!=NULL);
-
- max = (jlong)0;
- WITH_LOCAL_REFS(env, 1) {
- jclass clazz;
- jmethodID getRuntime;
- jobject runtime;
- jmethodID maxMemory;
-
- clazz = findClass(env, "java/lang/Runtime");
- getRuntime = getStaticMethodID(env, clazz, "getRuntime",
- "()Ljava/lang/Runtime;");
- runtime = callStaticObjectMethod(env, clazz, getRuntime);
- maxMemory = getMethodID(env, clazz, "maxMemory", "()J");
- max = callLongMethod(env, runtime, maxMemory);
- } END_WITH_LOCAL_REFS;
- return max;
-}
-
-void
-createAgentThread(JNIEnv *env, const char *name, jvmtiStartFunction func)
-{
- jvmtiError error;
-
- HPROF_ASSERT(name!=NULL);
- HPROF_ASSERT(func!=NULL);
-
- WITH_LOCAL_REFS(env, 1) {
- jclass clazz;
- jmethodID threadConstructor;
- jmethodID threadSetDaemon;
- jthread thread;
- jstring nameString;
- jthreadGroup systemThreadGroup;
- jthreadGroup * groups;
- jint groupCount;
-
- thread = NULL;
- systemThreadGroup = NULL;
- groups = NULL;
- clazz = class_get_class(env, gdata->thread_cnum);
- HPROF_ASSERT(clazz!=NULL);
- threadConstructor = getMethodID(env, clazz, "<init>",
- "(Ljava/lang/ThreadGroup;Ljava/lang/String;)V");
- threadSetDaemon = getMethodID(env, clazz, "setDaemon",
- "(Z)V");
-
- error = JVMTI_FUNC_PTR(gdata->jvmti,GetTopThreadGroups)
- (gdata->jvmti, &groupCount, &groups);
- if ( error == JVMTI_ERROR_NONE ) {
- if ( groupCount > 0 ) {
- systemThreadGroup = groups[0];
- }
- jvmtiDeallocate(groups);
-
- nameString = newStringUTF(env, name);
- HPROF_ASSERT(nameString!=NULL);
- thread = newThreadObject(env, clazz, threadConstructor,
- systemThreadGroup, nameString);
- HPROF_ASSERT(thread!=NULL);
- callVoidMethod(env, thread, threadSetDaemon, JNI_TRUE);
-
- error = JVMTI_FUNC_PTR(gdata->jvmti,RunAgentThread)
- (gdata->jvmti, thread, func, NULL, JVMTI_THREAD_MAX_PRIORITY);
-
- /* After the thread is running... */
-
- /* Make sure the TLS table has this thread as an agent thread */
- tls_agent_thread(env, thread);
- }
- } END_WITH_LOCAL_REFS;
-
- if ( error != JVMTI_ERROR_NONE ) {
- HPROF_JVMTI_ERROR(error, "Cannot create agent thread");
- }
-}
-
-jlong
-getThreadCpuTime(jthread thread)
-{
- jvmtiError error;
- jlong cpuTime;
-
- HPROF_ASSERT(thread!=NULL);
- cpuTime = -1;
- error = JVMTI_FUNC_PTR(gdata->jvmti,GetThreadCpuTime)
- (gdata->jvmti, thread, &cpuTime);
- if ( error != JVMTI_ERROR_NONE ) {
- HPROF_JVMTI_ERROR(error, "Cannot get cpu time");
- }
- return cpuTime;
-}
-
-/* Get frame count */
-void
-getFrameCount(jthread thread, jint *pcount)
-{
- jvmtiError error;
-
- HPROF_ASSERT(thread!=NULL);
- HPROF_ASSERT(pcount!=NULL);
- *pcount = 0;
- error = JVMTI_FUNC_PTR(gdata->jvmti,GetFrameCount)
- (gdata->jvmti, thread, pcount);
- if ( error != JVMTI_ERROR_NONE ) {
- *pcount = 0;
- }
-}
-
-/* Get call trace */
-void
-getStackTrace(jthread thread, jvmtiFrameInfo *pframes, jint depth, jint *pcount)
-{
- jvmtiError error;
-
- HPROF_ASSERT(thread!=NULL);
- HPROF_ASSERT(pframes!=NULL);
- HPROF_ASSERT(depth >= 0);
- HPROF_ASSERT(pcount!=NULL);
- *pcount = 0;
- error = JVMTI_FUNC_PTR(gdata->jvmti,GetStackTrace)
- (gdata->jvmti, thread, 0, depth, pframes, pcount);
- if ( error != JVMTI_ERROR_NONE ) {
- *pcount = 0;
- }
-}
-
-void
-getThreadListStackTraces(jint count, jthread *threads,
- jint depth, jvmtiStackInfo **stack_info)
-{
- jvmtiError error;
-
- HPROF_ASSERT(threads!=NULL);
- HPROF_ASSERT(stack_info!=NULL);
- HPROF_ASSERT(depth >= 0);
- HPROF_ASSERT(count > 0);
- *stack_info = NULL;
- error = JVMTI_FUNC_PTR(gdata->jvmti,GetThreadListStackTraces)
- (gdata->jvmti, count, threads, depth, stack_info);
- if ( error != JVMTI_ERROR_NONE ) {
- HPROF_JVMTI_ERROR(error, "Cannot get thread list stack info");
- }
-}
-
-void
-followReferences(jvmtiHeapCallbacks *pHeapCallbacks, void *user_data)
-{
- jvmtiError error;
-
- error = JVMTI_FUNC_PTR(gdata->jvmti,FollowReferences)
- (gdata->jvmti, 0, NULL, NULL, pHeapCallbacks, user_data);
- if ( error != JVMTI_ERROR_NONE ) {
- HPROF_JVMTI_ERROR(error, "Cannot follow references");
- }
-}
-
-/* GC control */
-void
-runGC(void)
-{
- jvmtiError error;
- error = JVMTI_FUNC_PTR(gdata->jvmti,ForceGarbageCollection)
- (gdata->jvmti);
- if ( error != JVMTI_ERROR_NONE ) {
- HPROF_JVMTI_ERROR(error, "Cannot force garbage collection");
- }
-}
-
-/* ------------------------------------------------------------------- */
-/* Getting the initial JVMTI environment */
-
-void
-getJvmti(void)
-{
- jvmtiEnv *jvmti = NULL;
- jint res;
- jint jvmtiCompileTimeMajorVersion;
- jint jvmtiCompileTimeMinorVersion;
- jint jvmtiCompileTimeMicroVersion;
-
- res = JVM_FUNC_PTR(gdata->jvm,GetEnv)
- (gdata->jvm, (void **)&jvmti, JVMTI_VERSION_1);
- if (res != JNI_OK) {
- char buf[256];
-
- (void)md_snprintf(buf, sizeof(buf),
- "Unable to access JVMTI Version 1 (0x%x),"
- " is your JDK a 5.0 or newer version?"
- " JNIEnv's GetEnv() returned %d",
- JVMTI_VERSION_1, res);
- buf[sizeof(buf)-1] = 0;
- HPROF_ERROR(JNI_FALSE, buf);
- error_exit_process(1); /* Kill entire process, no core dump */
- }
- gdata->jvmti = jvmti;
-
- /* Check to make sure the version of jvmti.h we compiled with
- * matches the runtime version we are using.
- */
- jvmtiCompileTimeMajorVersion = ( JVMTI_VERSION & JVMTI_VERSION_MASK_MAJOR )
- >> JVMTI_VERSION_SHIFT_MAJOR;
- jvmtiCompileTimeMinorVersion = ( JVMTI_VERSION & JVMTI_VERSION_MASK_MINOR )
- >> JVMTI_VERSION_SHIFT_MINOR;
- jvmtiCompileTimeMicroVersion = ( JVMTI_VERSION & JVMTI_VERSION_MASK_MICRO )
- >> JVMTI_VERSION_SHIFT_MICRO;
- if ( !compatible_versions(jvmtiMajorVersion(), jvmtiMinorVersion(),
- jvmtiCompileTimeMajorVersion, jvmtiCompileTimeMinorVersion) ) {
- char buf[256];
-
- (void)md_snprintf(buf, sizeof(buf),
- "This " AGENTNAME " native library will not work with this VM's "
- "version of JVMTI (%d.%d.%d), it needs JVMTI %d.%d[.%d]."
- ,
- jvmtiMajorVersion(),
- jvmtiMinorVersion(),
- jvmtiMicroVersion(),
- jvmtiCompileTimeMajorVersion,
- jvmtiCompileTimeMinorVersion,
- jvmtiCompileTimeMicroVersion);
- buf[sizeof(buf)-1] = 0;
- HPROF_ERROR(JNI_FALSE, buf);
- error_exit_process(1); /* Kill entire process, no core dump wanted */
- }
-}
--- a/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_util.h Thu Aug 20 12:29:58 2015 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,199 +0,0 @@
-/*
- * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * - Neither the name of Oracle nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
- * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/*
- * This source code is provided to illustrate the usage of a given feature
- * or technique and has been deliberately simplified. Additional steps
- * required for a production-quality application, such as security checks,
- * input validation and proper error handling, might not be present in
- * this sample code.
- */
-
-
-#ifndef HPROF_UTIL_H
-#define HPROF_UTIL_H
-
-/* Use THIS_FILE when it is available. */
-#ifndef THIS_FILE
- #define THIS_FILE __FILE__
-#endif
-
-/* Macros that protect code from accidently using a local ref improperly */
-#define WITH_LOCAL_REFS(env, number) \
- { \
- JNIEnv *_env = (env); \
- pushLocalFrame(_env, number); \
- { /* BEGINNING OF WITH SCOPE */
-
-#define END_WITH_LOCAL_REFS \
- } /* END OF WITH SCOPE */ \
- popLocalFrame(_env, NULL); \
- }
-
-/* Macro to check for exceptions after JNI calls. */
-#define CHECK_EXCEPTIONS(env) \
- { \
- JNIEnv *_env = (env); \
- jobject _exception; \
- _exception = exceptionOccurred(_env); \
- if ( _exception != NULL ) { \
- exceptionDescribe(_env); \
- HPROF_ERROR(JNI_TRUE, "Unexpected Exception found beforehand");\
- } \
- {
-
-#define END_CHECK_EXCEPTIONS \
- } \
- _exception = exceptionOccurred(_env); \
- if ( _exception != NULL ) { \
- exceptionDescribe(_env); \
- HPROF_ERROR(JNI_TRUE, "Unexpected Exception found afterward");\
- } \
- }
-
-JNIEnv * getEnv(void);
-
-/* JNI support functions */
-jobject newGlobalReference(JNIEnv *env, jobject object);
-jobject newWeakGlobalReference(JNIEnv *env, jobject object);
-void deleteGlobalReference(JNIEnv *env, jobject object);
-jobject newLocalReference(JNIEnv *env, jobject object);
-void deleteLocalReference(JNIEnv *env, jobject object);
-void deleteWeakGlobalReference(JNIEnv *env, jobject object);
-jclass getObjectClass(JNIEnv *env, jobject object);
-jmethodID getMethodID(JNIEnv *env, jclass clazz, const char* name,
- const char *sig);
-jclass getSuperclass(JNIEnv *env, jclass klass);
-jmethodID getStaticMethodID(JNIEnv *env, jclass clazz, const char* name,
- const char *sig);
-jfieldID getStaticFieldID(JNIEnv *env, jclass clazz, const char* name,
- const char *sig);
-jclass findClass(JNIEnv *env, const char *name);
-void setStaticIntField(JNIEnv *env, jclass clazz, jfieldID field,
- jint value);
-jboolean isSameObject(JNIEnv *env, jobject o1, jobject o2);
-void pushLocalFrame(JNIEnv *env, jint capacity);
-void popLocalFrame(JNIEnv *env, jobject ret);
-jobject exceptionOccurred(JNIEnv *env);
-void exceptionDescribe(JNIEnv *env);
-void exceptionClear(JNIEnv *env);
-void registerNatives(JNIEnv *env, jclass clazz,
- JNINativeMethod *methods, jint count);
-
-/* More JVMTI support functions */
-char * getErrorName(jvmtiError error_number);
-jvmtiPhase getPhase(void);
-char * phaseString(jvmtiPhase phase);
-void disposeEnvironment(void);
-jlong getObjectSize(jobject object);
-jobject getClassLoader(jclass klass);
-jint getClassStatus(jclass klass);
-jlong getTag(jobject object);
-void setTag(jobject object, jlong tag);
-void getObjectMonitorUsage(jobject object, jvmtiMonitorUsage *uinfo);
-void getOwnedMonitorInfo(jthread thread, jobject **ppobjects,
- jint *pcount);
-void getSystemProperty(const char *name, char **value);
-void getClassSignature(jclass klass, char**psignature,
- char **pgeneric_signature);
-void getSourceFileName(jclass klass, char** src_name_ptr);
-
-jvmtiPrimitiveType sigToPrimType(char *sig);
-int sigToPrimSize(char *sig);
-char primTypeToSigChar(jvmtiPrimitiveType primType);
-
-void getAllClassFieldInfo(JNIEnv *env, jclass klass,
- jint* field_count_ptr, FieldInfo** fields_ptr);
-void getMethodName(jmethodID method, char** name_ptr,
- char** signature_ptr);
-void getMethodClass(jmethodID method, jclass *pclazz);
-jboolean isMethodNative(jmethodID method);
-void getPotentialCapabilities(jvmtiCapabilities *capabilities);
-void addCapabilities(jvmtiCapabilities *capabilities);
-void setEventCallbacks(jvmtiEventCallbacks *pcallbacks);
-void setEventNotificationMode(jvmtiEventMode mode, jvmtiEvent event,
- jthread thread);
-void * getThreadLocalStorage(jthread thread);
-void setThreadLocalStorage(jthread thread, void *ptr);
-void getThreadState(jthread thread, jint *threadState);
-void getThreadInfo(jthread thread, jvmtiThreadInfo *info);
-void getThreadGroupInfo(jthreadGroup thread_group, jvmtiThreadGroupInfo *info);
-void getLoadedClasses(jclass **ppclasses, jint *pcount);
-jint getLineNumber(jmethodID method, jlocation location);
-jlong getMaxMemory(JNIEnv *env);
-void createAgentThread(JNIEnv *env, const char *name,
- jvmtiStartFunction func);
-jlong getThreadCpuTime(jthread thread);
-void getStackTrace(jthread thread, jvmtiFrameInfo *pframes, jint depth,
- jint *pcount);
-void getThreadListStackTraces(jint count, jthread *threads,
- jint depth, jvmtiStackInfo **stack_info);
-void getFrameCount(jthread thread, jint *pcount);
-void followReferences(jvmtiHeapCallbacks *pHeapCallbacks, void *user_data);
-
-/* GC control */
-void runGC(void);
-
-/* Get initial JVMTI environment */
-void getJvmti(void);
-
-/* Get current runtime JVMTI version */
-jint jvmtiVersion(void);
-
-/* Raw monitor functions */
-jrawMonitorID createRawMonitor(const char *str);
-void rawMonitorEnter(jrawMonitorID m);
-void rawMonitorWait(jrawMonitorID m, jlong pause_time);
-void rawMonitorNotifyAll(jrawMonitorID m);
-void rawMonitorExit(jrawMonitorID m);
-void destroyRawMonitor(jrawMonitorID m);
-
-/* JVMTI alloc/dealloc */
-void * jvmtiAllocate(int size);
-void jvmtiDeallocate(void *ptr);
-
-/* System malloc/free */
-void * hprof_malloc(int size);
-void hprof_free(void *ptr);
-
-#include "debug_malloc.h"
-
-#ifdef DEBUG
- void * hprof_debug_malloc(int size, char *file, int line);
- void hprof_debug_free(void *ptr, char *file, int line);
- #define HPROF_MALLOC(size) hprof_debug_malloc(size, THIS_FILE, __LINE__)
- #define HPROF_FREE(ptr) hprof_debug_free(ptr, THIS_FILE, __LINE__)
-#else
- #define HPROF_MALLOC(size) hprof_malloc(size)
- #define HPROF_FREE(ptr) hprof_free(ptr)
-#endif
-
-#endif
--- a/jdk/src/jdk.hprof.agent/share/native/libhprof/jvm.hprof.txt Thu Aug 20 12:29:58 2015 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,86 +0,0 @@
-Copyright (c) 2003, 2005, Oracle and/or its affiliates. All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-
- - Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
-
- - Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
-
- - Neither the name of Oracle nor the names of its
- contributors may be used to endorse or promote products derived
- from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
-IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
-THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
-CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
-EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
-PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
-LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
-NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-
-Header for -agentlib:hprof (or -Xrunhprof) ASCII Output (JDK 5.0 JVMTI based)
-
-WARNING! This file format is under development, and is subject to
-change without notice.
-
-This file contains the following types of records:
-
-THREAD START
-THREAD END mark the lifetime of Java threads
-
-TRACE represents a Java stack trace. Each trace consists
- of a series of stack frames. Other records refer to
- TRACEs to identify (1) where object allocations have
- taken place, (2) the frames in which GC roots were
- found, and (3) frequently executed methods.
-
-HEAP DUMP is a complete snapshot of all live objects in the Java
- heap. Following distinctions are made:
-
- ROOT root set as determined by GC
- CLS classes
- OBJ instances
- ARR arrays
-
-SITES is a sorted list of allocation sites. This identifies
- the most heavily allocated object types, and the TRACE
- at which those allocations occurred.
-
-CPU SAMPLES is a statistical profile of program execution. The VM
- periodically samples all running threads, and assigns
- a quantum to active TRACEs in those threads. Entries
- in this record are TRACEs ranked by the percentage of
- total quanta they consumed; top-ranked TRACEs are
- typically hot spots in the program.
-
-CPU TIME is a profile of program execution obtained by measuring
- the time spent in individual methods (excluding the time
- spent in callees), as well as by counting the number of
- times each method is called. Entries in this record are
- TRACEs ranked by the percentage of total CPU time. The
- "count" field indicates the number of times each TRACE
- is invoked.
-
-MONITOR TIME is a profile of monitor contention obtained by measuring
- the time spent by a thread waiting to enter a monitor.
- Entries in this record are TRACEs ranked by the percentage
- of total monitor contention time and a brief description
- of the monitor. The "count" field indicates the number of
- times the monitor was contended at that TRACE.
-
-MONITOR DUMP is a complete snapshot of all the monitors and threads in
- the System.
-
-HEAP DUMP, SITES, CPU SAMPLES|TIME and MONITOR DUMP|TIME records are generated
-at program exit. They can also be obtained during program execution by typing
-Ctrl-\ (on Solaris) or by typing Ctrl-Break (on Win32).
--- a/jdk/src/jdk.hprof.agent/share/native/libhprof/manual.html Thu Aug 20 12:29:58 2015 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,1737 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
-<html>
-<head>
- <meta content="deepa viswanathan" name="Author">
- <meta content="Mozilla/4.04 [en] (WinNT; U) [Netscape]"
- name="GENERATOR">
- <title>HPROF Agent</title>
- <meta name="author" content="Kelly O'Hair">
-</head>
-<body alink="#ff0000" bgcolor="#ffffff" link="#0000ee" text="#000000"
- vlink="#551a8b">
-<h1 style="text-align: center;"><a name="mozTocId137594"
- class="mozTocH1"></a><span style="font-weight: bold;"></span>HPROF
-Agent<br>
-</h1>
-<h2><a name="mozTocId558923" class="mozTocH2"></a>Contents</h2>
-<span style="text-decoration: underline;"></span>
-<ol id="mozToc">
-<!--mozToc h1 1 h2 2 h3 3 h4 4 h5 5 h6 6--><li><a href="#mozTocId137594">HPROF
-Agent</a>
- <ol>
- <li><a href="#mozTocId558923">Contents</a></li>
- <li><a href="#mozTocId550204">Overview</a></li>
- <li><a href="#mozTocId634758">Start-up</a></li>
- <li><a href="#mozTocId708821">Heap Allocation
-Profiles (heap=sites) </a></li>
- <li><a href="#mozTocId634725">Heap Dump (heap=dump)</a></li>
- <li><a href="#mozTocId546448">CPU Usage Sampling
-Profiles (cpu=samples) </a></li>
- <li><a href="#mozTocId116568">CPU Usage Times Profile (cpu=times)
- </a></li>
- <li><a href="#mozTocId848088">Binary Dump Format
-(format=b)</a>
- <ol>
- <li><a href="#mozTocId348369">Socket Connection and
-Communication</a></li>
- </ol>
- <ol>
- <li><a href="#mozTocId348360">Handling of Arrays</a></li>
- </ol>
- </li>
- <li><a href="#mozTocId589424">Source Code </a></li>
- </ol>
- </li>
-</ol>
-<span style="text-decoration: underline;"></span>
-<h2><a name="mozTocId550204" class="mozTocH2"></a>Overview</h2>
-<p>This document describes the JVM TI Agent HPROF delivered in
-the Java Development Kit (JDK). It is intended as demonstration code
-for JVM TI, and as a functional
-replacement for the older HPROF JVMPI Agent delivered in past releases.<br>
-</p>
-Previous 1.4 and earlier releases of the JDK contained an HPROF
-agent built on the experimental JVMPI.
-The newer JVM TI replaces both JVMDI and JVMPI.
-<p><span style="font-weight: bold;">Note</span>: Differences between
-this HPROF implementation and the older JVMPI based HPROF are marked in
-<span style="font-style: italic; color: rgb(255, 0, 0);">RED ITALICS</span>
-throughout this document.<br>
-</p>
-<br>
-<h2><a name="mozTocId634758" class="mozTocH3"></a>Start-up</h2>
-<p>HPROF is a simple profiler agent shipped with the JDK. It is
-a dynamically-linked
-library that interacts with the JVM TI and
-writes out profiling
-information either to a file or to a socket in ascii or binary format.
-This information can
-be further processed by a profiler front-end tool.</p>
-<p>It is capable of presenting CPU usage, heap allocation statistics
-and monitor contention
-profiles. In addition it can also report complete heap dumps and states
-of all the monitors and threads in the Java virtual machine.
-</p>
-<p>HPROF can be invoked by:
-</p>
-<pre>java -<span style="font-weight: bold;">agentlib:</span><b>hprof</b> ToBeProfiledClass</pre>
-Depending on the type of profiling requested, HPROF instructs the
-virtual machine to send it the relevant JVM TI events and processes
-the event data into profiling information. For example, the following
-command obtains the heap allocation profile:
-<pre>java -agentlib:hprof=heap=sites ToBeProfiledClass</pre>
-Following is the complete list of options that can passed to hprof :
-<blockquote>
- <pre>java -agentlib:hprof=help<br><br> HPROF: Heap and CPU Profiling Agent (JVMTI Demonstration Code)<br><br>hprof usage: java -agentlib:hprof=[help]|[<option>=<value>, ...]<br><br>Option Name and Value Description Default<br>--------------------- ----------- -------<br>heap=dump|sites|all heap profiling all<br>cpu=samples|times|old CPU usage off<br>monitor=y|n monitor contention n<br>format=a|b text(txt) or binary output a<br>file=<file> write data to file java.hprof[{.txt}]<br>net=<host>:<port> send data over a socket off<br>depth=<size> stack trace depth 4<br>interval=<ms> sample interval in ms 10<br>cutoff=<value> output cutoff point 0.0001<br>lineno=y|n line number in traces? y<br>thread=y|n thread in traces? n<br>doe=y|n dump on exit? y<br>msa=y|n Solaris micro state accounting n<br>force=y|n force output to <file> y<br>verbose=y|n print messages about dumps y<br><br>Obsolete Options<br>----------------<br>gc_okay=y|n<br><br>Examples<br>--------<br> - Get sample cpu information every 20 millisec, with a stack depth of 3:<br> java -agentlib:hprof=cpu=samples,interval=20,depth=3 classname<br> - Get heap usage information based on the allocation sites:<br> java -agentlib:hprof=heap=sites classname<br><br>Notes<br>-----<br> - The option format=b cannot be used with monitor=y.<br> - The option format=b cannot be used with cpu=old|times.<br> - Use of the -Xrunhprof interface can still be used, e.g.<br> java -Xrunhprof:[help]|[<option>=<value>, ...]<br> will behave exactly the same as:<br> java -agentlib:hprof=[help]|[<option>=<value>, ...]<br><br>Warnings<br>--------<br> - This is demonstration code for the JVMTI interface and use of BCI,<br> it is not an official product or formal part of the JDK.<br> - The -Xrunhprof interface will be removed in a future release.<br> - The option format=b is considered experimental, this format may change<br> in a future release.<br></pre>
-</blockquote>
-<p>By default, heap profiling information (sites and dump) is written
-out
-to java.hprof.txt (ascii).
-The monitor=y|n option has proven to be problematic and may be replaced
-with something more useful.<br>
-</p>
-<p>The output in most cases will contain ID's for traces, threads,
-objects, etc. Each type of ID will typically start with a
-different number than the other ID's, e.g. traces might start with
-300000.<br>
-</p>
-<p><span style="font-weight: bold;">Note</span>: <span
- style="font-style: italic; color: rgb(255, 0, 0);">The gc_okay option
-is no longer supported.</span><br>
-</p>
-<h2><a name="mozTocId708821" class="mozTocH4"></a>Heap Allocation
-Profiles (heap=sites)<br>
-</h2>
-Following is the heap allocation profile generated by running the Java
-compiler
-(<code>javac</code>) on a set of input files. Only parts of the
-profiler output are shown here.
-<p></p>
-<pre>Command used: javac -J-agentlib:hprof=heap=sites Hello.java<br><br>SITES BEGIN (ordered by live bytes) Fri Feb 6 13:13:42 2004<br> percent live alloc'ed stack class<br> rank self accum bytes objs bytes objs trace name<br> 1 44.13% 44.13% 1117360 13967 1117360 13967 301926 java.util.zip.ZipEntry<br> 2 8.83% 52.95% 223472 13967 223472 13967 301927 com.sun.tools.javac.util.List<br> 3 5.18% 58.13% 131088 1 131088 1 300996 byte[]<br> 4 5.18% 63.31% 131088 1 131088 1 300995 com.sun.tools.javac.util.Name[]<br> <br></pre>
-A crucial piece of information in heap profile is the amount of
-allocation that occurs
-in various parts of the program. The <code>SITES</code> record above
-tells us that 44.13% of the total space was allocated for
-java.util.zip.ZipEntry objects. Note that the amount of live data is
-only a fraction
-of the total allocation that has occurred at a given site; the rest has
-been garbage collected.
-<p>A good way to relate allocation sites to the source code is to
-record
-the dynamic stack traces that led to the heap allocation. Following is
-another part of the profiler output that illustrates the stack traces
-referred to by the four allocation sites in output shown above.
-<span style="font-family: monospace;"><br>
-</span></p>
-<pre><span style="font-family: monospace;"></span>TRACE 301926:<br> java.util.zip.ZipEntry.<init>(ZipEntry.java:101)<br> java.util.zip.ZipFile+3.nextElement(ZipFile.java:417)<br> com.sun.tools.javac.jvm.ClassReader.openArchive(ClassReader.java:1374)<br> com.sun.tools.javac.jvm.ClassReader.list(ClassReader.java:1631)<br><br>TRACE 301927:<br> com.sun.tools.javac.util.List.<init>(List.java:42)<br> com.sun.tools.javac.util.List.<init>(List.java:50)<br> com.sun.tools.javac.util.ListBuffer.append(ListBuffer.java:94)<br> com.sun.tools.javac.jvm.ClassReader.openArchive(ClassReader.java:1374)<br><br>TRACE 300996:<br> com.sun.tools.javac.util.Name$Table.<init>(Name.java:379)<br> com.sun.tools.javac.util.Name$Table.<init>(Name.java:481)<br> com.sun.tools.javac.util.Name$Table.make(Name.java:332)<br> com.sun.tools.javac.util.Name$Table.instance(Name.java:349)<br><br>TRACE 300995:<br> com.sun.tools.javac.util.Name$Table.<init>(Name.java:378)<br> com.sun.tools.javac.util.Name$Table.<init>(Name.java:481)<br> com.sun.tools.javac.util.Name$Table.make(Name.java:332)<br> com.sun.tools.javac.util.Name$Table.instance(Name.java:349)<init><init><init><br></init></init></init></pre>
-<blockquote></blockquote>
-<p>
-Each frame in the stack trace contains class name, method name, source
-file name, and the line number. The user can set the maximum number
-of frames collected by the HPROF agent. The default limit is 4. Stack
-traces reveal not only which methods performed heap allocation, but
-also which methods were ultimately responsible for making calls that
-resulted in memory allocation. <br>
-</p>
-<h2><a name="mozTocId634725" class="mozTocH2"></a>Heap Dump (heap=dump)</h2>
-A complete dump of the current live objects in the heap can be obtained
-with:<br>
-<pre>Command used: javac -J-agentlib:hprof=heap=dump Hello.java<br></pre>
-This is a very large output file, but can be viewed and searched in any
-editor.<br>
-<br>
-<h2><a name="mozTocId546448" class="mozTocH4"></a>CPU Usage Sampling
-Profiles (cpu=samples)<br>
-</h2>
-HPROF can collect CPU usage information by sampling threads. Following
-is part of the output collected from a run
-of the <code>javac</code> compiler.
-<p></p>
-<pre>Command used: javac -J-agentlib:hprof=cpu=samples Hello.java<br><br>CPU SAMPLES BEGIN (total = 462) Fri Feb 6 13:33:07 2004<br>rank self accum count trace method<br> 1 49.57% 49.57% 229 300187 java.util.zip.ZipFile.getNextEntry<br> 2 6.93% 56.49% 32 300190 java.util.zip.ZipEntry.initFields<br> 3 4.76% 61.26% 22 300122 java.lang.ClassLoader.defineClass2<br> 4 2.81% 64.07% 13 300188 java.util.zip.ZipFile.freeEntry<br> 5 1.95% 66.02% 9 300129 java.util.Vector.addElement<br> 6 1.73% 67.75% 8 300124 java.util.zip.ZipFile.getEntry<br> 7 1.52% 69.26% 7 300125 java.lang.ClassLoader.findBootstrapClass<br> 8 0.87% 70.13% 4 300172 com.sun.tools.javac.main.JavaCompiler.<init><br> 9 0.65% 70.78% 3 300030 java.util.zip.ZipFile.open<br> 10 0.65% 71.43% 3 300175 com.sun.tools.javac.main.JavaCompiler.<init><br><init>
-...
-CPU SAMPLES END
-</init></pre>
-<blockquote>
-</blockquote>
-<p>
-The HPROF agent periodically samples the stack of all running threads
-to record the most frequently active stack traces. The <code>count</code>
-field above indicates how many times a particular stack trace was found
-to be active. These stack traces correspond to the CPU usage hot spots
-in the application.<br>
-</p>
-<h2><a name="mozTocId116568" class="mozTocH2"></a>CPU Usage Times
-Profile (cpu=times)<br>
-</h2>
-HPROF can collect CPU usage information by injecting code into every
-method entry and exit, keeping track of exact method call counts and
-the time spent in each method. This uses Byte Code Injection (BCI) and
-runs considerably slower than cpu=samples. Following is part of the
-output collected from a run
-of the <code>javac</code> compiler.
-<p></p>
-<pre>Command used: javac -J-agentlib:hprof=cpu=times Hello.java<br><br>CPU TIME (ms) BEGIN (total = 2082665289) Fri Feb 6 13:43:42 2004<br>rank self accum count trace method<br> 1 3.70% 3.70% 1 311243 com.sun.tools.javac.Main.compile<br> 2 3.64% 7.34% 1 311242 com.sun.tools.javac.main.Main.compile<br> 3 3.64% 10.97% 1 311241 com.sun.tools.javac.main.Main.compile<br> 4 3.11% 14.08% 1 311173 com.sun.tools.javac.main.JavaCompiler.compile<br> 5 2.54% 16.62% 8 306183 com.sun.tools.javac.jvm.ClassReader.listAll<br> 6 2.53% 19.15% 36 306182 com.sun.tools.javac.jvm.ClassReader.list<br> 7 2.03% 21.18% 1 307195 com.sun.tools.javac.comp.Enter.main<br> 8 2.03% 23.21% 1 307194 com.sun.tools.javac.comp.Enter.complete<br> 9 1.68% 24.90% 1 306392 com.sun.tools.javac.comp.Enter.classEnter<br> 10 1.68% 26.58% 1 306388 com.sun.tools.javac.comp.Enter.classEnter<br><br>...<br>CPU TIME (ms) END</pre>
-Here the count represents the true count of the times this method was
-entered, and the percentages represent a measure of thread CPU time
-spent in those methods.<br>
-<br>
-<h2><a class="mozTocH3" name="mozTocId848088"></a>Binary Dump Format
-(format=b)</h2>
-The basic fields in the binary output are u1 (1 byte), u2 (2 byte), u4
-(4 byte), and u8 (8 byte). An ID in this implementation is a u4,
-however the size of an ID is really determined by the "size of
-identifiers" field in the header.<br>
-<br>
-<span style="font-weight: bold;">WARNING</span>: This format is still
-considered highly experimental, however, all attempts were made to
-match the format of past HPROF implementations.<br>
-<br>
-The binary output begins with the information:<br>
-<br>
-<table style="text-align: left; width: 100%; height: 124px;" border="1"
- cellpadding="2" cellspacing="2">
- <tbody>
- <tr>
- <td style="vertical-align: top;">[u1]*<br>
- </td>
- <td style="vertical-align: top;">An initial NULL terminated
-series of bytes representing the format name and version, in this
-implementation and historically, the string "JAVA PROFILE 1.0.1" (18
-u1 bytes) followed by a NULL byte. If the TAG "HEAP DUMP SEGMENT" is
-used this string will be "JAVA PROFILE 1.0.2". </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">u4<br>
- </td>
- <td style="vertical-align: top;">size of identifiers. Identifiers
-are used to represent UTF8 strings, objects, stack traces, etc. They
-can have the same size as host pointers or sizeof(void*), but are not
-required to be.<span style="color: rgb(0, 0, 0);"></span></td>
- </tr>
- <tr>
- <td style="vertical-align: top;">u4<br>
- </td>
- <td style="vertical-align: top;">high word of number of
-milliseconds since 0:00 GMT, 1/1/70</td>
- </tr>
- <tr>
- <td style="vertical-align: top;">u4<br>
- </td>
- <td style="vertical-align: top;">low word of number of
-milliseconds since 0:00 GMT, 1/1/70</td>
- </tr>
- </tbody>
-</table>
-<br>
-Followed by a se<span style="font-family: monospace;"></span>quence of
-records that look like:<br>
-<br>
-<table style="text-align: left; width: 100%;" border="1" cellpadding="2"
- cellspacing="2">
- <tbody>
- <tr>
- <td style="vertical-align: top;">u1<br>
- </td>
- <td style="vertical-align: top;">TAG: denoting the type of the
-record</td>
- </tr>
- <tr>
- <td style="vertical-align: top;">u4<br>
- </td>
- <td style="vertical-align: top;">TIME: number of microseconds
-since the
-time stamp in the header<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">u4<br>
- </td>
- <td style="vertical-align: top;">LENGTH: number of bytes that
-follow this
-u4 field and belong to this record<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">[u1]*<br>
- </td>
- <td style="vertical-align: top;">BODY: as many bytes as specified
-in
-the above u4 field<br>
- </td>
- </tr>
- </tbody>
-</table>
-<br>
-<br>
-The following TAGs are supported:<br>
-<br>
-<table style="text-align: left; width: 100%;" border="1" cellpadding="2"
- cellspacing="2">
- <tbody>
- <tr>
- <td style="vertical-align: top;">STRING IN UTF8<br>
- </td>
- <td style="vertical-align: top;">0x01<br>
- </td>
- <td style="vertical-align: top;">
- <table style="text-align: left; width: 100%;" border="1"
- cellpadding="2" cellspacing="2">
- <tbody>
- <tr>
- <td style="vertical-align: top;">ID<br>
- </td>
- <td style="vertical-align: top;">ID for this string<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">[u1]*<br>
- </td>
- <td style="vertical-align: top;">UTF8 characters for string
-(NOT NULL terminated)<br>
- </td>
- </tr>
- </tbody>
- </table>
- <br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">LOAD CLASS<br>
- </td>
- <td style="vertical-align: top;">0x02<br>
- </td>
- <td style="vertical-align: top;">
- <table style="text-align: left; width: 100%;" border="1"
- cellpadding="2" cellspacing="2">
- <tbody>
- <tr>
- <td style="vertical-align: top;">u4<br>
- </td>
- <td style="vertical-align: top;">class serial number
-(always > 0)<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">ID<br>
- </td>
- <td style="vertical-align: top;">class object ID<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">u4<br>
- </td>
- <td style="vertical-align: top;">stack trace serial number<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">ID<br>
- </td>
- <td style="vertical-align: top;">class name string ID<br>
- </td>
- </tr>
- </tbody>
- </table>
- <br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">UNLOAD CLASS<br>
- </td>
- <td style="vertical-align: top;">0x03<br>
- </td>
- <td style="vertical-align: top;">
- <table style="text-align: left; width: 100%;" border="1"
- cellpadding="2" cellspacing="2">
- <tbody>
- <tr>
- <td style="vertical-align: top;">u4<br>
- </td>
- <td style="vertical-align: top;">class serial number<br>
- </td>
- </tr>
- </tbody>
- </table>
- <br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">STACK FRAME<br>
- </td>
- <td style="vertical-align: top;">0x04<br>
- </td>
- <td style="vertical-align: top;">
- <table style="text-align: left; width: 100%;" border="1"
- cellpadding="2" cellspacing="2">
- <tbody>
- <tr>
- <td style="vertical-align: top;">ID<br>
- </td>
- <td style="vertical-align: top;">stack frame ID<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">ID<br>
- </td>
- <td style="vertical-align: top;">method name string ID<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">ID<br>
- </td>
- <td style="vertical-align: top;">method signature string ID<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">ID<br>
- </td>
- <td style="vertical-align: top;">source file name string ID<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">u4<br>
- </td>
- <td style="vertical-align: top;">class serial number<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">u4<br>
- </td>
- <td style="vertical-align: top;">
- <table style="text-align: left; width: 100%;" border="1"
- cellpadding="2" cellspacing="2">
- <tbody>
- <tr>
- <td style="vertical-align: top;">> 0<br>
- </td>
- <td style="vertical-align: top;">line number<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">0<br>
- </td>
- <td style="vertical-align: top;">no line information
-available<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">-1<br>
- </td>
- <td style="vertical-align: top;">unknown location<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">-2<br>
- </td>
- <td style="vertical-align: top;">compiled method (<span
- style="font-style: italic; color: rgb(255, 0, 0);">Not implemented</span>)<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">-3<br>
- </td>
- <td style="vertical-align: top;">native method (<span
- style="color: rgb(255, 0, 0); font-style: italic;">Not implemented</span>)<br>
- </td>
- </tr>
- </tbody>
- </table>
- <br>
- </td>
- </tr>
- </tbody>
- </table>
- <br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">STACK TRACE<br>
- </td>
- <td style="vertical-align: top;">0x05<br>
- </td>
- <td style="vertical-align: top;">
- <table style="text-align: left; width: 100%;" border="1"
- cellpadding="2" cellspacing="2">
- <tbody>
- <tr>
- <td style="vertical-align: top;">u4<br>
- </td>
- <td style="vertical-align: top;">stack trace serial number<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">u4<br>
- </td>
- <td style="vertical-align: top;">thread serial number<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">u4<br>
- </td>
- <td style="vertical-align: top;">number of frames<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">[ID]*<br>
- </td>
- <td style="vertical-align: top;">series of stack frame ID's<br>
- </td>
- </tr>
- </tbody>
- </table>
- <br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">ALLOC SITES<br>
- </td>
- <td style="vertical-align: top;">0x06<br>
- </td>
- <td style="vertical-align: top;">
- <table style="text-align: left; width: 100%;" border="1"
- cellpadding="2" cellspacing="2">
- <tbody>
- <tr>
- <td style="vertical-align: top;">u2<br>
- </td>
- <td style="vertical-align: top;">Bit mask flags:<br>
- <table style="text-align: left; width: 441px; height: 74px;"
- border="1" cellpadding="2" cellspacing="2">
- <tbody>
- <tr>
- <td style="vertical-align: top;">0x1<br>
- </td>
- <td style="vertical-align: top;">incremental vs.
-complete<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">0x2<br>
- </td>
- <td style="vertical-align: top; text-align: left;">sorted
-by allocation vs. line<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">0x4<br>
- </td>
- <td style="vertical-align: top;">whether to force GC
-(<span style="font-style: italic; color: rgb(255, 0, 0);">Not
-Implemented</span>)<br>
- </td>
- </tr>
- </tbody>
- </table>
- <br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">u4<br>
- </td>
- <td style="vertical-align: top;">cutoff ratio (floating
-point)<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">u4<br>
- </td>
- <td style="vertical-align: top;">total live bytes<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">u4<br>
- </td>
- <td style="vertical-align: top;">total live instances<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">u8<br>
- </td>
- <td style="vertical-align: top;">total bytes allocated<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">u8<br>
- </td>
- <td style="vertical-align: top;">total instances allocated<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">u4<br>
- </td>
- <td style="vertical-align: top;">number of sites that
-follow:<br>
- <table style="text-align: left; width: 100%;" border="1"
- cellpadding="2" cellspacing="2">
- <tbody>
- <tr>
- <td style="vertical-align: top;">u1<br>
- </td>
- <td style="vertical-align: top;">array indicator: 0
-means not an array, non-zero means an array of this type (See <a
- href="#Basic_Type">Basic Type</a>)<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">u4<br>
- </td>
- <td style="vertical-align: top;">class serial number<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">u4<br>
- </td>
- <td style="vertical-align: top;">stack trace serial
-number<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">u4<br>
- </td>
- <td style="vertical-align: top;">number of live bytes<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">u4<br>
- </td>
- <td style="vertical-align: top;">number of live
-instances<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">u4<br>
- </td>
- <td style="vertical-align: top;">number of bytes
-allocated<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">u4<br>
- </td>
- <td style="vertical-align: top;">number of instances
-allocated<br>
- </td>
- </tr>
- </tbody>
- </table>
- <br>
- </td>
- </tr>
- </tbody>
- </table>
- <br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">HEAP SUMMARY<br>
- </td>
- <td style="vertical-align: top;">0x07<br>
- </td>
- <td style="vertical-align: top;">
- <table style="text-align: left; width: 100%;" border="1"
- cellpadding="2" cellspacing="2">
- <tbody>
- <tr>
- <td style="vertical-align: top;">u4<br>
- </td>
- <td style="vertical-align: top;">total live bytes<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">u4<br>
- </td>
- <td style="vertical-align: top;">total live instances<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">u8<br>
- </td>
- <td style="vertical-align: top;">total bytes allocated<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">u8<br>
- </td>
- <td style="vertical-align: top;">total instances allocated<br>
- </td>
- </tr>
- </tbody>
- </table>
- <br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">START THREAD<br>
- </td>
- <td style="vertical-align: top;">0x0A<br>
- </td>
- <td style="vertical-align: top;">
- <table style="text-align: left; width: 100%;" border="1"
- cellpadding="2" cellspacing="2">
- <tbody>
- <tr>
- <td style="vertical-align: top;">u4<br>
- </td>
- <td style="vertical-align: top;">thread serial number<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">ID<br>
- </td>
- <td style="vertical-align: top;">thread object ID<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">u4<br>
- </td>
- <td style="vertical-align: top;">stack trace serial number<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">ID<br>
- </td>
- <td style="vertical-align: top;">thread name string ID<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">ID<br>
- </td>
- <td style="vertical-align: top;">thread group name ID<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">ID<br>
- </td>
- <td style="vertical-align: top;">thread parent group name ID<br>
- </td>
- </tr>
- </tbody>
- </table>
- <br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">END THREAD<br>
- </td>
- <td style="vertical-align: top;">0x0B<br>
- </td>
- <td style="vertical-align: top;">
- <table style="text-align: left; width: 100%;" border="1"
- cellpadding="2" cellspacing="2">
- <tbody>
- <tr>
- <td style="vertical-align: top;">u4<br>
- </td>
- <td style="vertical-align: top;">thread serial number<br>
- </td>
- </tr>
- </tbody>
- </table>
- <br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">HEAP DUMP<br>
- <span style="font-style: italic;">or</span><br>
-HEAP DUMP SEGMENT<br>
- </td>
- <td style="vertical-align: top;">0x0C<br>
- <span style="font-style: italic;">or</span><br>
-0x1C<br>
- </td>
- <td style="vertical-align: top;">Contains any number of sub-tags,
-each begins a u1 field (no order implied here):<br>
- <table style="text-align: left; width: 100%;" border="1"
- cellpadding="2" cellspacing="2">
- <tbody>
- <tr>
- <td style="vertical-align: top;">ROOT UNKNOWN<br>
- </td>
- <td style="vertical-align: top;">0xFF<br>
- </td>
- <td style="vertical-align: top;">
- <table style="text-align: left; width: 100%;" border="1"
- cellpadding="2" cellspacing="2">
- <tbody>
- <tr>
- <td style="vertical-align: top;">ID<br>
- </td>
- <td style="vertical-align: top;">object ID<br>
- </td>
- </tr>
- </tbody>
- </table>
- <br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">ROOT JNI GLOBAL<br>
- </td>
- <td style="vertical-align: top;">0x01<br>
- </td>
- <td style="vertical-align: top;">
- <table style="text-align: left; width: 100%;" border="1"
- cellpadding="2" cellspacing="2">
- <tbody>
- <tr>
- <td style="vertical-align: top;">ID<br>
- </td>
- <td style="vertical-align: top;">object ID<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">ID<br>
- </td>
- <td style="vertical-align: top;">JNI global ref ID<br>
- </td>
- </tr>
- </tbody>
- </table>
- <br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">ROOT JNI LOCAL<br>
- </td>
- <td style="vertical-align: top;">0x02<br>
- </td>
- <td style="vertical-align: top;">
- <table style="text-align: left; width: 100%;" border="1"
- cellpadding="2" cellspacing="2">
- <tbody>
- <tr>
- <td style="vertical-align: top;">ID<br>
- </td>
- <td style="vertical-align: top;">object ID<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">u4<br>
- </td>
- <td style="vertical-align: top;">thread serial number<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">u4<br>
- </td>
- <td style="vertical-align: top;">frame number in
-stack trace (-1 for empty)<br>
- </td>
- </tr>
- </tbody>
- </table>
- <br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">ROOT JAVA FRAME<br>
- </td>
- <td style="vertical-align: top;">0x03<br>
- </td>
- <td style="vertical-align: top;">
- <table style="text-align: left; width: 100%;" border="1"
- cellpadding="2" cellspacing="2">
- <tbody>
- <tr>
- <td style="vertical-align: top;">ID<br>
- </td>
- <td style="vertical-align: top;">object ID<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">u4<br>
- </td>
- <td style="vertical-align: top;">thread serial number<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">u4<br>
- </td>
- <td style="vertical-align: top;">frame number in
-stack trace (-1 for empty)</td>
- </tr>
- </tbody>
- </table>
- <br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">ROOT NATIVE STACK<br>
- </td>
- <td style="vertical-align: top;">0x04<br>
- </td>
- <td style="vertical-align: top;">
- <table style="text-align: left; width: 100%;" border="1"
- cellpadding="2" cellspacing="2">
- <tbody>
- <tr>
- <td style="vertical-align: top;">ID<br>
- </td>
- <td style="vertical-align: top;">object ID<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">u4<br>
- </td>
- <td style="vertical-align: top;">thread serial number<br>
- </td>
- </tr>
- </tbody>
- </table>
- <br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">ROOT STICKY CLASS<br>
- </td>
- <td style="vertical-align: top;">0x05<br>
- </td>
- <td style="vertical-align: top;">
- <table style="text-align: left; width: 100%;" border="1"
- cellpadding="2" cellspacing="2">
- <tbody>
- <tr>
- <td style="vertical-align: top;">ID<br>
- </td>
- <td style="vertical-align: top;">object ID<br>
- </td>
- </tr>
- </tbody>
- </table>
- <br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">ROOT THREAD BLOCK<br>
- </td>
- <td style="vertical-align: top;">0x06<br>
- </td>
- <td style="vertical-align: top;">
- <table style="text-align: left; width: 100%;" border="1"
- cellpadding="2" cellspacing="2">
- <tbody>
- <tr>
- <td style="vertical-align: top;">ID<br>
- </td>
- <td style="vertical-align: top;">object ID<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">u4<br>
- </td>
- <td style="vertical-align: top;">thread serial number<br>
- </td>
- </tr>
- </tbody>
- </table>
- <br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">ROOT MONITOR USED<br>
- </td>
- <td style="vertical-align: top;">0x07<br>
- </td>
- <td style="vertical-align: top;">
- <table style="text-align: left; width: 100%;" border="1"
- cellpadding="2" cellspacing="2">
- <tbody>
- <tr>
- <td style="vertical-align: top;">ID<br>
- </td>
- <td style="vertical-align: top;">object ID<br>
- </td>
- </tr>
- </tbody>
- </table>
- <br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">ROOT THREAD OBJECT<br>
- </td>
- <td style="vertical-align: top;">0x08<br>
- </td>
- <td style="vertical-align: top;">
- <table style="text-align: left; width: 100%;" border="1"
- cellpadding="2" cellspacing="2">
- <tbody>
- <tr>
- <td style="vertical-align: top;">ID<br>
- </td>
- <td style="vertical-align: top;">thread object ID<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">u4<br>
- </td>
- <td style="vertical-align: top;">thread serial number<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">u4<br>
- </td>
- <td style="vertical-align: top;">stack trace serial
-number<br>
- </td>
- </tr>
- </tbody>
- </table>
- <br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">CLASS DUMP<br>
- </td>
- <td style="vertical-align: top;">0x20<br>
- </td>
- <td style="vertical-align: top;">
- <table style="text-align: left; width: 100%;" border="1"
- cellpadding="2" cellspacing="2">
- <tbody>
- <tr>
- <td style="vertical-align: top;">ID<br>
- </td>
- <td style="vertical-align: top;">class object ID<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">u4<br>
- </td>
- <td style="vertical-align: top;">stack trace serial
-number<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">ID<br>
- </td>
- <td style="vertical-align: top;">super class object ID<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">ID<br>
- </td>
- <td style="vertical-align: top;">class loader object
-ID<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">ID<br>
- </td>
- <td style="vertical-align: top;">signers object ID<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">ID<br>
- </td>
- <td style="vertical-align: top;">protection domain
-object ID<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">ID<br>
- </td>
- <td style="vertical-align: top;">reserved<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">ID<br>
- </td>
- <td style="vertical-align: top;">reserved<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">u4<br>
- </td>
- <td style="vertical-align: top;">instance size (in
-bytes)<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">u2<br>
- </td>
- <td style="vertical-align: top;">size of constant
-pool and number of records that follow:<br>
- <table style="text-align: left; width: 100%;"
- border="1" cellpadding="2" cellspacing="2">
- <tbody>
- <tr>
- <td style="vertical-align: top;">u2<br>
- </td>
- <td style="vertical-align: top;">constant pool
-index<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">u1<br>
- </td>
- <td style="vertical-align: top;">type of entry:
-(See <a href="#Basic_Type">Basic Type</a>)<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">value<br>
- </td>
- <td style="vertical-align: top;">value of entry
-(u1, u2, u4, or u8 based on type of entry)<span
- style="font-style: italic; color: rgb(255, 0, 0);"></span><br>
- </td>
- </tr>
- </tbody>
- </table>
- <br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">u2<br>
- </td>
- <td style="vertical-align: top;">Number of static
-fields:<br>
- <table style="text-align: left; width: 100%;"
- border="1" cellpadding="2" cellspacing="2">
- <tbody>
- <tr>
- <td style="vertical-align: top;">ID<br>
- </td>
- <td style="vertical-align: top;">static field
-name string ID<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">u1<br>
- </td>
- <td style="vertical-align: top;">type of field:
-(See <a href="#Basic_Type">Basic Type</a>)<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">value<br>
- </td>
- <td style="vertical-align: top;">value of entry
-(u1, u2, u4, or u8 based on type of field) <span
- style="font-style: italic; color: rgb(255, 0, 0);"></span><br>
- </td>
- </tr>
- </tbody>
- </table>
- <br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">u2<br>
- </td>
- <td style="vertical-align: top;">Number of instance
-fields (not including super class's)<br>
- <table style="text-align: left; width: 100%;"
- border="1" cellpadding="2" cellspacing="2">
- <tbody>
- <tr>
- <td style="vertical-align: top;">ID<br>
- </td>
- <td style="vertical-align: top;">field name
-string ID<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">u1<br>
- </td>
- <td style="vertical-align: top;">type of field:
-(See <a href="#Basic_Type">Basic Type</a>)<br>
- </td>
- </tr>
- </tbody>
- </table>
- <br>
- </td>
- </tr>
- </tbody>
- </table>
- <br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">INSTANCE DUMP<br>
- </td>
- <td style="vertical-align: top;">0x21<br>
- </td>
- <td style="vertical-align: top;"><br>
- <table style="text-align: left; width: 100%;" border="1"
- cellpadding="2" cellspacing="2">
- <tbody>
- <tr>
- <td style="vertical-align: top;">ID<br>
- </td>
- <td style="vertical-align: top;">object ID<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">u4<br>
- </td>
- <td style="vertical-align: top;">stack trace serial
-number<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">ID<br>
- </td>
- <td style="vertical-align: top;">class object ID<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">u4<br>
- </td>
- <td style="vertical-align: top;">number of bytes that
-follow<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">[value]*<br>
- </td>
- <td style="vertical-align: top;">instance field
-values (this class, followed by super class, etc)<span
- style="font-style: italic; color: rgb(255, 0, 0);"></span><br>
- </td>
- </tr>
- </tbody>
- </table>
- <br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">OBJECT ARRAY DUMP<br>
- </td>
- <td style="vertical-align: top;">0x22<br>
- </td>
- <td style="vertical-align: top;"><br>
- <table style="text-align: left; width: 100%;" border="1"
- cellpadding="2" cellspacing="2">
- <tbody>
- <tr>
- <td style="vertical-align: top;">ID<br>
- </td>
- <td style="vertical-align: top;">array object ID<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">u4<br>
- </td>
- <td style="vertical-align: top;">stack trace serial
-number<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">u4<br>
- </td>
- <td style="vertical-align: top;">number of elements<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">ID<br>
- </td>
- <td style="vertical-align: top;">array class object
-ID<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">[ID]*<br>
- </td>
- <td style="vertical-align: top;">elements<br>
- </td>
- </tr>
- </tbody>
- </table>
- <br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">PRIMITIVE ARRAY DUMP<br>
- </td>
- <td style="vertical-align: top;">0x23<br>
- </td>
- <td style="vertical-align: top;">
- <table style="text-align: left; width: 100%;" border="1"
- cellpadding="2" cellspacing="2">
- <tbody>
- <tr>
- <td style="vertical-align: top;">ID<br>
- </td>
- <td style="vertical-align: top;">array object ID<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">u4<br>
- </td>
- <td style="vertical-align: top;">stack trace serial
-number<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">u4<br>
- </td>
- <td style="vertical-align: top;">number of elements<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">u1<br>
- </td>
- <td style="vertical-align: top;">element type (See <a
- href="#Basic_Type">Basic Type</a>)<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">[u1]*<br>
- </td>
- <td style="vertical-align: top;">elements (packed
-array) </td>
- </tr>
- </tbody>
- </table>
- <br>
- </td>
- </tr>
- </tbody>
- </table>
- <br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">HEAP DUMP END<br>
- </td>
- <td style="vertical-align: top;">0x2C<br>
- </td>
- <td style="vertical-align: top;">Terminates a series of HEAP DUMP
-SEGMENTS. Concatenation of HEAP DUMP SEGMENTS equals a HEAP DUMP.<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">CPU SAMPLES<br>
- </td>
- <td style="vertical-align: top;">0x0D<br>
- </td>
- <td style="vertical-align: top;">
- <table style="text-align: left; width: 100%;" border="1"
- cellpadding="2" cellspacing="2">
- <tbody>
- <tr>
- <td style="vertical-align: top;">u4<br>
- </td>
- <td style="vertical-align: top;">total number of samples<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">u4<br>
- </td>
- <td style="vertical-align: top;">number of traces that
-follow:<br>
- <table style="text-align: left; width: 100%;" border="1"
- cellpadding="2" cellspacing="2">
- <tbody>
- <tr>
- <td style="vertical-align: top;">u4<br>
- </td>
- <td style="vertical-align: top;">number of samples<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">u4<br>
- </td>
- <td style="vertical-align: top;">stack trace serial
-number<br>
- </td>
- </tr>
- </tbody>
- </table>
- <br>
- </td>
- </tr>
- </tbody>
- </table>
- <br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">CONTROL SETTINGS<br>
- </td>
- <td style="vertical-align: top;">0x0E<br>
- </td>
- <td style="vertical-align: top;">
- <table style="text-align: left; width: 100%;" border="1"
- cellpadding="2" cellspacing="2">
- <tbody>
- <tr>
- <td style="vertical-align: top;">u4<br>
- </td>
- <td style="vertical-align: top;">Bit mask flags:<br>
- <table style="text-align: left; width: 100%;" border="1"
- cellpadding="2" cellspacing="2">
- <tbody>
- <tr>
- <td style="vertical-align: top;">0x1<br>
- </td>
- <td style="vertical-align: top;">alloc traces on/off<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">0x2<br>
- </td>
- <td style="vertical-align: top;">cpu sampling on/off<br>
- </td>
- </tr>
- </tbody>
- </table>
- <br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">u2<br>
- </td>
- <td style="vertical-align: top;">stack trace depth<br>
- </td>
- </tr>
- </tbody>
- </table>
- <br>
- </td>
- </tr>
- </tbody>
-</table>
-<span style="font-weight: bold;"><br>
-</span><a name="Basic_Type"></a>Basic Type
-<table style="text-align: left; width: 296px; height: 221px;" border="1"
- cellpadding="2" cellspacing="2">
- <tbody>
- <tr>
- <td style="vertical-align: top;">2<br>
- </td>
- <td style="vertical-align: top;">object<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">4<br>
- </td>
- <td style="vertical-align: top;">boolean<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">5<br>
- </td>
- <td style="vertical-align: top;">char<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">6<br>
- </td>
- <td style="vertical-align: top;">float<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">7<br>
- </td>
- <td style="vertical-align: top;">double<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">8<br>
- </td>
- <td style="vertical-align: top;">byte<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">9<br>
- </td>
- <td style="vertical-align: top;">short<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">10<br>
- </td>
- <td style="vertical-align: top;">int<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">11<br>
- </td>
- <td style="vertical-align: top;">long<br>
- </td>
- </tr>
- </tbody>
-</table>
-<h3><a name="mozTocId348360" class="mozTocH3"></a>Handling of Arrays</h3>
-<br>
-There will be a "LOAD CLASS" tag for type type of each array
-in the dump. In the LOAD CLASS record, the class name string ID
-will refer to a string with a human-readable name of the array
-type that is formatted as the type name would be in Java source
-code. Thus, the LOAD CLASS record for the type char[] will
-be "char[]", for short[][][] will be "short[][][]" and for
-MyType[] will be "MyType[]".
-<br>
-<h3><a name="mozTocId348369" class="mozTocH3"></a>Socket Connection and
-Communication</h3>
-<br>
-<span style="font-weight: bold;">WARNING</span>: This command format is
-still
-considered highly experimental, however, all attempts were made to
-match the format of past HPROF implementations.<br>
-<br>
-<br>
-Commands can be sent to HPROF via the socket connection, the accepted
-COMMAND TAGS are:<br>
-<br>
-<table style="text-align: left; width: 100%;" border="1" cellpadding="2"
- cellspacing="2">
- <tbody>
- <tr>
- <td style="vertical-align: top;">FORCE GC (<span
- style="font-style: italic; color: rgb(255, 0, 0);">Not implemented</span>)<br>
- </td>
- <td style="vertical-align: top;">0x01<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">DUMP HEAP<br>
- </td>
- <td style="vertical-align: top;">0x02<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">ALLOC SITES<br>
- </td>
- <td style="vertical-align: top;">0x03<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">HEAP SUMMARY<br>
- </td>
- <td style="vertical-align: top;">0x04<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">EXIT THE VM<br>
- </td>
- <td style="vertical-align: top;">0x05<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">DUMP TRACES<br>
- </td>
- <td style="vertical-align: top;">0x06<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">CPU SAMPLES<br>
- </td>
- <td style="vertical-align: top;">0x07<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">CONTROL<br>
- </td>
- <td style="vertical-align: top;">0x08<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">EOF (used to terminate socket
-connection)<br>
- </td>
- <td style="vertical-align: top;">0xFF<br>
- </td>
- </tr>
- </tbody>
-</table>
-<br>
-The commands take the form:<br>
-<br>
-<table style="text-align: left; width: 100%;" border="1" cellpadding="2"
- cellspacing="2">
- <tbody>
- <tr>
- <td style="vertical-align: top;">u1<br>
- </td>
- <td style="vertical-align: top;">COMMAND TAG<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">u4<br>
- </td>
- <td style="vertical-align: top;">serial number<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">u4<br>
- </td>
- <td style="vertical-align: top;">number of bytes that follow<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">[u1]*<br>
- </td>
- <td style="vertical-align: top;">
- <table style="text-align: left; width: 100%;" border="1"
- cellpadding="2" cellspacing="2">
- <tbody>
- <tr>
- <td style="vertical-align: top;">ALLOC SITES<br>
- </td>
- <td style="vertical-align: top;">
- <table style="text-align: left; width: 100%;" border="1"
- cellpadding="2" cellspacing="2">
- <tbody>
- <tr>
- <td style="vertical-align: top;">u2<br>
- </td>
- <td style="vertical-align: top;">Flags:<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">u4<br>
- </td>
- <td style="vertical-align: top;">cutoff ratio
-(floating point between 0.0 and 1.0)<br>
- </td>
- </tr>
- </tbody>
- </table>
- <br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">CPU SAMPLES<br>
- </td>
- <td style="vertical-align: top;">
- <table style="text-align: left; width: 100%;" border="1"
- cellpadding="2" cellspacing="2">
- <tbody>
- <tr>
- <td style="vertical-align: top;">u2<br>
- </td>
- <td style="vertical-align: top;">ignored<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">u4<br>
- </td>
- <td style="vertical-align: top;">cutoff ratio
-(floating point between 0.0 and 1.0)<br>
- </td>
- </tr>
- </tbody>
- </table>
- <br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">CONTROL<br>
- </td>
- <td style="vertical-align: top;">
- <table style="text-align: left; width: 100%;" border="1"
- cellpadding="2" cellspacing="2">
- <tbody>
- <tr>
- <td style="vertical-align: top;">u2<br>
- </td>
- <td style="vertical-align: top;">Sub option:<br>
- <table style="text-align: left; width: 100%;"
- border="1" cellpadding="2" cellspacing="2">
- <tbody>
- <tr>
- <td style="vertical-align: top;">0x1<br>
- </td>
- <td style="vertical-align: top;">Turn alloc
-traces on<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">0x2<br>
- </td>
- <td style="vertical-align: top;">Turn alloc
-traces off<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">0x3<br>
- </td>
- <td style="vertical-align: top;">Turn CPU
-sampling on:<br>
- <table style="text-align: left; width: 100%;"
- border="1" cellpadding="2" cellspacing="2">
- <tbody>
- <tr>
- <td style="vertical-align: top;">ID<br>
- </td>
- <td style="vertical-align: top;">thread
-object ID (0 for all threads)<br>
- </td>
- </tr>
- </tbody>
- </table>
- <br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">0x4<br>
- </td>
- <td style="vertical-align: top;">Turn CPU
-sampling off:<br>
- <table style="text-align: left; width: 100%;"
- border="1" cellpadding="2" cellspacing="2">
- <tbody>
- <tr>
- <td style="vertical-align: top;">ID<br>
- </td>
- <td style="vertical-align: top;">thread
-object ID (0 for all threads)</td>
- </tr>
- </tbody>
- </table>
- <br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">0x5<br>
- </td>
- <td style="vertical-align: top;">Clear CPU
-sampling<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">0x6<br>
- </td>
- <td style="vertical-align: top;">Set max stack
-depth:<br>
- <table style="text-align: left; width: 100%;"
- border="1" cellpadding="2" cellspacing="2">
- <tbody>
- <tr>
- <td style="vertical-align: top;">u2<br>
- </td>
- <td style="vertical-align: top;">New max
-stack depth<br>
- </td>
- </tr>
- </tbody>
- </table>
- <br>
- </td>
- </tr>
- </tbody>
- </table>
- <br>
- </td>
- </tr>
- </tbody>
- </table>
- <br>
- </td>
- </tr>
- </tbody>
- </table>
- </td>
- </tr>
- </tbody>
-</table>
-<br>
-<p></p>
-<hr><!-- hhmts start -->
-Last modified: 2005<!-- hhmts end -->
-</body>
-</html>
--- a/jdk/src/jdk.hprof.agent/unix/native/libhprof/hprof_md.c Thu Aug 20 12:29:58 2015 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,453 +0,0 @@
-/*
- * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * - Neither the name of Oracle nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
- * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/*
- * This source code is provided to illustrate the usage of a given feature
- * or technique and has been deliberately simplified. Additional steps
- * required for a production-quality application, such as security checks,
- * input validation and proper error handling, might not be present in
- * this sample code.
- */
-
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-
-#if !defined(LINUX) && !defined(_ALLBSD_SOURCE) && !defined(AIX)
-#include <procfs.h>
-#endif
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/socket.h>
-#include <sys/errno.h>
-#include <unistd.h>
-#include <errno.h>
-#include <dlfcn.h>
-#include <sys/time.h>
-
-#include <netdb.h>
-#include <netinet/in.h>
-#include <sys/param.h>
-#include <time.h>
-
-#include "jni.h"
-#include "jvm_md.h"
-#include "hprof.h"
-
-#ifdef AIX
-#include "porting_aix.h" /* For the 'dladdr' function. */
-#endif
-
-int
-md_getpid(void)
-{
- static int pid = -1;
-
- if ( pid >= 0 ) {
- return pid;
- }
- pid = getpid();
- return pid;
-}
-
-void
-md_sleep(unsigned seconds)
-{
- sleep(seconds);
-}
-
-void
-md_init(void)
-{
-#if defined(LINUX) || defined(_ALLBSD_SOURCE) || defined(AIX)
- /* No Hi-Res timer option? */
-#else
- if ( gdata->micro_state_accounting ) {
- char proc_ctl_fn[48];
- int procfd;
-
- /* Turn on micro state accounting, once per process */
- (void)md_snprintf(proc_ctl_fn, sizeof(proc_ctl_fn),
- "/proc/%d/ctl", md_getpid());
-
- procfd = open(proc_ctl_fn, O_WRONLY);
- if (procfd >= 0) {
- long ctl_op[2];
-
- ctl_op[0] = PCSET;
- ctl_op[1] = PR_MSACCT;
- (void)write(procfd, ctl_op, sizeof(ctl_op));
- (void)close(procfd);
- }
- }
-#endif
-}
-
-int
-md_connect(char *hostname, unsigned short port)
-{
- struct hostent *hentry;
- struct sockaddr_in s;
- int fd;
-
- /* create a socket */
- fd = socket(AF_INET, SOCK_STREAM, 0);
- if ( fd < 0 ) {
- return -1;
- }
-
- /* find remote host's addr from name */
- if ((hentry = gethostbyname(hostname)) == NULL) {
- (void)close(fd);
- return -1;
- }
- (void)memset((char *)&s, 0, sizeof(s));
- /* set remote host's addr; its already in network byte order */
- (void)memcpy(&s.sin_addr.s_addr, *(hentry->h_addr_list),
- (int)sizeof(s.sin_addr.s_addr));
- /* set remote host's port */
- s.sin_port = htons(port);
- s.sin_family = AF_INET;
-
- /* now try connecting */
- if (-1 == connect(fd, (struct sockaddr*)&s, sizeof(s))) {
- (void)close(fd);
- return 0;
- }
- return fd;
-}
-
-int
-md_recv(int f, char *buf, int len, int option)
-{
- return recv(f, buf, len, option);
-}
-
-int
-md_shutdown(int filedes, int option)
-{
- return shutdown(filedes, option);
-}
-
-int
-md_open(const char *filename)
-{
- return open(filename, O_RDONLY);
-}
-
-int
-md_open_binary(const char *filename)
-{
- return md_open(filename);
-}
-
-int
-md_creat(const char *filename)
-{
- return open(filename, O_WRONLY | O_CREAT | O_TRUNC,
- S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
-}
-
-int
-md_creat_binary(const char *filename)
-{
- return md_creat(filename);
-}
-
-jlong
-md_seek(int filedes, jlong cur)
-{
- jlong new_pos;
-
- if ( cur == (jlong)-1 ) {
- new_pos = lseek(filedes, 0, SEEK_END);
- } else {
- new_pos = lseek(filedes, cur, SEEK_SET);
- }
- return new_pos;
-}
-
-void
-md_close(int filedes)
-{
- (void)close(filedes);
-}
-
-int
-md_send(int s, const char *msg, int len, int flags)
-{
- int res;
-
- do {
- res = send(s, msg, len, flags);
- } while ((res < 0) && (errno == EINTR));
-
- return res;
-}
-
-int
-md_write(int filedes, const void *buf, int nbyte)
-{
- int res;
-
- do {
- res = write(filedes, buf, nbyte);
- } while ((res < 0) && (errno == EINTR));
-
- return res;
-}
-
-int
-md_read(int filedes, void *buf, int nbyte)
-{
- int res;
-
- do {
- res = read(filedes, buf, nbyte);
- } while ((res < 0) && (errno == EINTR));
-
- return res;
-}
-
-/* Time of day in milli-seconds */
-static jlong
-md_timeofday(void)
-{
- struct timeval tv;
-
- if ( gettimeofday(&tv, (void *)0) != 0 ) {
- return (jlong)0; /* EOVERFLOW ? */
- }
- /*LINTED*/
- return ((jlong)tv.tv_sec * (jlong)1000) + (jlong)(tv.tv_usec / 1000);
-}
-
-/* Hi-res timer in micro-seconds */
-jlong
-md_get_microsecs(void)
-{
-#if defined(LINUX) || defined(_ALLBSD_SOURCE) || defined(AIX)
- return (jlong)(md_timeofday() * (jlong)1000); /* Milli to micro */
-#else
- return (jlong)(gethrtime()/(hrtime_t)1000); /* Nano seconds to micro seconds */
-#endif
-}
-
-/* Time of day in milli-seconds */
-jlong
-md_get_timemillis(void)
-{
- return md_timeofday();
-}
-
-/* Current CPU hi-res CPU time used */
-jlong
-md_get_thread_cpu_timemillis(void)
-{
-#if defined(LINUX) || defined(_ALLBSD_SOURCE) || defined(AIX)
- return md_timeofday();
-#else
- return (jlong)(gethrvtime()/1000); /* Nano seconds to milli seconds */
-#endif
-}
-
-void
-md_get_prelude_path(char *path, int path_len, char *filename)
-{
- void *addr;
- char libdir[FILENAME_MAX+1];
- Dl_info dlinfo;
-
- libdir[0] = 0;
- addr = (void*)&md_get_prelude_path;
-
- /* Use dladdr() to get the full path to libhprof.so, which we use to find
- * the prelude file.
- */
- dlinfo.dli_fname = NULL;
- (void)dladdr(addr, &dlinfo);
- if ( dlinfo.dli_fname != NULL ) {
- char * lastSlash;
-
- /* Full path to library name, need to move up one directory to 'lib' */
- (void)strcpy(libdir, (char *)dlinfo.dli_fname);
- lastSlash = strrchr(libdir, '/');
- if ( lastSlash != NULL ) {
- *lastSlash = '\0';
- }
-#ifndef __APPLE__
- // not sure why other platforms have to go up two levels, but on macos we only need up one
- lastSlash = strrchr(libdir, '/');
- if ( lastSlash != NULL ) {
- *lastSlash = '\0';
- }
-#endif /* __APPLE__ */
- }
- (void)snprintf(path, path_len, "%s/%s", libdir, filename);
-}
-
-
-int
-md_vsnprintf(char *s, int n, const char *format, va_list ap)
-{
- return vsnprintf(s, n, format, ap);
-}
-
-int
-md_snprintf(char *s, int n, const char *format, ...)
-{
- int ret;
- va_list ap;
-
- va_start(ap, format);
- ret = md_vsnprintf(s, n, format, ap);
- va_end(ap);
- return ret;
-}
-
-void
-md_system_error(char *buf, int len)
-{
- char *p;
-
- buf[0] = 0;
- p = strerror(errno);
- if ( p != NULL ) {
- (void)strcpy(buf, p);
- }
-}
-
-unsigned
-md_htons(unsigned short s)
-{
- return htons(s);
-}
-
-unsigned
-md_htonl(unsigned l)
-{
- return htonl(l);
-}
-
-unsigned
-md_ntohs(unsigned short s)
-{
- return ntohs(s);
-}
-
-unsigned
-md_ntohl(unsigned l)
-{
- return ntohl(l);
-}
-
-static void dll_build_name(char* buffer, size_t buflen,
- const char* paths, const char* fname) {
- char *path, *paths_copy, *next_token;
-
- paths_copy = strdup(paths);
- if (paths_copy == NULL) {
- return;
- }
-
- next_token = NULL;
- path = strtok_r(paths_copy, ":", &next_token);
-
- while (path != NULL) {
- snprintf(buffer, buflen, "%s/lib%s" JNI_LIB_SUFFIX, path, fname);
- if (access(buffer, F_OK) == 0) {
- break;
- }
- *buffer = '\0';
- path = strtok_r(NULL, ":", &next_token);
- }
-
- free(paths_copy);
-}
-
-/* Create the actual fill filename for a dynamic library. */
-void
-md_build_library_name(char *holder, int holderlen, const char *pname, const char *fname)
-{
- int pnamelen;
-
- /* Length of options directory location. */
- pnamelen = pname ? strlen(pname) : 0;
-
- *holder = '\0';
- /* Quietly truncate on buffer overflow. Should be an error. */
- if (pnamelen + (int)strlen(fname) + 10 > holderlen) {
- return;
- }
-
- /* Construct path to library */
- if (pnamelen == 0) {
- (void)snprintf(holder, holderlen, "lib%s" JNI_LIB_SUFFIX, fname);
- } else {
- dll_build_name(holder, holderlen, pname, fname);
- }
-}
-
-/* Load this library (return NULL on error, and error message in err_buf) */
-void *
-md_load_library(const char *name, char *err_buf, int err_buflen)
-{
- void * result;
-
- result = dlopen(name, RTLD_LAZY);
- if (result == NULL) {
- (void)strncpy(err_buf, dlerror(), err_buflen-2);
- err_buf[err_buflen-1] = '\0';
- }
- return result;
-}
-
-/* Unload this library */
-void
-md_unload_library(void *handle)
-{
- (void)dlclose(handle);
-}
-
-/* Find an entry point inside this library (return NULL if not found) */
-void *
-md_find_library_entry(void *handle, const char *name)
-{
- void * sym;
-
- sym = dlsym(handle, name);
- return sym;
-}
-
-
--- a/jdk/src/jdk.hprof.agent/windows/native/libhprof/hprof_md.c Thu Aug 20 12:29:58 2015 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,450 +0,0 @@
-/*
- * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * - Neither the name of Oracle nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
- * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/*
- * This source code is provided to illustrate the usage of a given feature
- * or technique and has been deliberately simplified. Additional steps
- * required for a production-quality application, such as security checks,
- * input validation and proper error handling, might not be present in
- * this sample code.
- */
-
-
-// To ensure winsock2.h is used, it has to be included ahead of
-// windows.h, which includes winsock.h by default.
-#include <winsock2.h>
-#include <windows.h>
-#include <io.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <mmsystem.h>
-#include <fcntl.h>
-#include <process.h>
-
-#include "jni.h"
-#include "hprof.h"
-
-int
-md_getpid(void)
-{
- static int pid = -1;
-
- if ( pid >= 0 ) {
- return pid;
- }
- pid = getpid();
- return pid;
-}
-
-void
-md_sleep(unsigned seconds)
-{
- Sleep((DWORD)seconds*1000);
-}
-
-void
-md_init(void)
-{
-}
-
-int
-md_connect(char *hostname, unsigned short port)
-{
- struct hostent *hentry;
- struct sockaddr_in s;
- int fd;
-
- /* find remote host's addr from name */
- if ((hentry = gethostbyname(hostname)) == NULL) {
- return -1;
- }
- (void)memset((char *)&s, 0, sizeof(s));
- /* set remote host's addr; its already in network byte order */
- (void)memcpy(&s.sin_addr.s_addr, *(hentry->h_addr_list),
- (int)sizeof(s.sin_addr.s_addr));
- /* set remote host's port */
- s.sin_port = htons(port);
- s.sin_family = AF_INET;
-
- /* create a socket */
- fd = (int)socket(AF_INET, SOCK_STREAM, 0);
- if (INVALID_SOCKET == fd) {
- return 0;
- }
-
- /* now try connecting */
- if (SOCKET_ERROR == connect(fd, (struct sockaddr*)&s, sizeof(s))) {
- closesocket(fd);
- return 0;
- }
- return fd;
-}
-
-int
-md_recv(int f, char *buf, int len, int option)
-{
- return recv(f, buf, len, option);
-}
-
-int
-md_shutdown(int filedes, int option)
-{
- return shutdown(filedes, option);
-}
-
-int
-md_open(const char *filename)
-{
- return open(filename, O_RDONLY);
-}
-
-int
-md_open_binary(const char *filename)
-{
- return open(filename, O_RDONLY|O_BINARY);
-}
-
-int
-md_creat(const char *filename)
-{
- return open(filename, O_CREAT | O_WRONLY | O_TRUNC,
- _S_IREAD | _S_IWRITE);
-}
-
-int
-md_creat_binary(const char *filename)
-{
- return open(filename, O_CREAT | O_WRONLY | O_TRUNC | O_BINARY,
- _S_IREAD | _S_IWRITE);
-}
-
-jlong
-md_seek(int filedes, jlong pos)
-{
- jlong new_pos;
-
- if ( pos == (jlong)-1 ) {
- new_pos = _lseeki64(filedes, 0L, SEEK_END);
- } else {
- new_pos = _lseeki64(filedes, pos, SEEK_SET);
- }
- return new_pos;
-}
-
-void
-md_close(int filedes)
-{
- (void)closesocket(filedes);
-}
-
-int
-md_send(int s, const char *msg, int len, int flags)
-{
- return send(s, msg, len, flags);
-}
-
-int
-md_read(int filedes, void *buf, int nbyte)
-{
- return read(filedes, buf, nbyte);
-}
-
-int
-md_write(int filedes, const void *buf, int nbyte)
-{
- return write(filedes, buf, nbyte);
-}
-
-jlong
-md_get_microsecs(void)
-{
- return (jlong)(timeGetTime())*(jlong)1000;
-}
-
-#define FT2JLONG(ft) \
- ((jlong)(ft).dwHighDateTime << 32 | (jlong)(ft).dwLowDateTime)
-
-jlong
-md_get_timemillis(void)
-{
- static jlong fileTime_1_1_70 = 0;
- SYSTEMTIME st0;
- FILETIME ft0;
-
- if (fileTime_1_1_70 == 0) {
- /* Initialize fileTime_1_1_70 -- the Win32 file time of midnight
- * 1/1/70.
- */
-
- memset(&st0, 0, sizeof(st0));
- st0.wYear = 1970;
- st0.wMonth = 1;
- st0.wDay = 1;
- SystemTimeToFileTime(&st0, &ft0);
- fileTime_1_1_70 = FT2JLONG(ft0);
- }
-
- GetSystemTime(&st0);
- SystemTimeToFileTime(&st0, &ft0);
-
- return (FT2JLONG(ft0) - fileTime_1_1_70) / 10000;
-}
-
-jlong
-md_get_thread_cpu_timemillis(void)
-{
- return md_get_timemillis();
-}
-
-HINSTANCE hJavaInst;
-static int nError = 0;
-
-BOOL WINAPI
-DllMain(HINSTANCE hinst, DWORD reason, LPVOID reserved)
-{
- WSADATA wsaData;
- switch (reason) {
- case DLL_PROCESS_ATTACH:
- hJavaInst = hinst;
- nError = WSAStartup(MAKEWORD(2,0), &wsaData);
- break;
- case DLL_PROCESS_DETACH:
- WSACleanup();
- hJavaInst = NULL;
- default:
- break;
- }
- return TRUE;
-}
-
-void
-md_get_prelude_path(char *path, int path_len, char *filename)
-{
- char libdir[FILENAME_MAX+1];
- char *lastSlash;
-
- GetModuleFileName(hJavaInst, libdir, FILENAME_MAX);
-
- /* This is actually in the bin directory, so move above bin for lib */
- lastSlash = strrchr(libdir, '\\');
- if ( lastSlash != NULL ) {
- *lastSlash = '\0';
- }
- lastSlash = strrchr(libdir, '\\');
- if ( lastSlash != NULL ) {
- *lastSlash = '\0';
- }
- (void)md_snprintf(path, path_len, "%s\\lib\\%s", libdir, filename);
-}
-
-int
-md_vsnprintf(char *s, int n, const char *format, va_list ap)
-{
- return _vsnprintf(s, n, format, ap);
-}
-
-int
-md_snprintf(char *s, int n, const char *format, ...)
-{
- int ret;
- va_list ap;
-
- va_start(ap, format);
- ret = md_vsnprintf(s, n, format, ap);
- va_end(ap);
- return ret;
-}
-
-void
-md_system_error(char *buf, int len)
-{
- long errval;
-
- errval = GetLastError();
- buf[0] = '\0';
- if (errval != 0) {
- int n;
-
- n = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS,
- NULL, errval,
- 0, buf, len, NULL);
- if (n > 3) {
- /* Drop final '.', CR, LF */
- if (buf[n - 1] == '\n') n--;
- if (buf[n - 1] == '\r') n--;
- if (buf[n - 1] == '.') n--;
- buf[n] = '\0';
- }
- }
-}
-
-unsigned
-md_htons(unsigned short s)
-{
- return htons(s);
-}
-
-unsigned
-md_htonl(unsigned l)
-{
- return htonl(l);
-}
-
-unsigned
-md_ntohs(unsigned short s)
-{
- return ntohs(s);
-}
-
-unsigned
-md_ntohl(unsigned l)
-{
- return ntohl(l);
-}
-
-static int
-get_last_error_string(char *buf, int len)
-{
- long errval;
-
- errval = GetLastError();
- if (errval != 0) {
- /* DOS error */
- int n;
-
- n = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS,
- NULL, errval,
- 0, buf, len, NULL);
- if (n > 3) {
- /* Drop final '.', CR, LF */
- if (buf[n - 1] == '\n') n--;
- if (buf[n - 1] == '\r') n--;
- if (buf[n - 1] == '.') n--;
- buf[n] = '\0';
- }
- return n;
- }
-
- if (errno != 0) {
- /* C runtime error that has no corresponding DOS error code */
- const char *s;
- int n;
-
- s = strerror(errno);
- n = (int)strlen(s);
- if (n >= len) {
- n = len - 1;
- }
- (void)strncpy(buf, s, n);
- buf[n] = '\0';
- return n;
- }
-
- return 0;
-}
-
-static void dll_build_name(char* buffer, size_t buflen,
- const char* paths, const char* fname) {
- char *path, *paths_copy, *next_token;
-
- paths_copy = strdup(paths);
- if (paths_copy == NULL) {
- return;
- }
-
- next_token = NULL;
- path = strtok_s(paths_copy, ";", &next_token);
-
- while (path != NULL) {
- _snprintf(buffer, buflen, "%s\\%s.dll", path, fname);
- if (_access(buffer, 0) == 0) {
- break;
- }
- *buffer = '\0';
- path = strtok_s(NULL, ";", &next_token);
- }
-
- free(paths_copy);
-}
-
-/* Build a machine dependent library name out of a path and file name. */
-void
-md_build_library_name(char *holder, int holderlen, const char *pname, const char *fname)
-{
- int pnamelen;
-
- pnamelen = pname ? (int)strlen(pname) : 0;
-
- *holder = '\0';
- /* Quietly truncates on buffer overflow. Should be an error. */
- if (pnamelen + strlen(fname) + 10 > (unsigned int)holderlen) {
- return;
- }
-
- if (pnamelen == 0) {
- sprintf(holder, "%s.dll", fname);
- } else {
- dll_build_name(holder, holderlen, pname, fname);
- }
-}
-
-void *
-md_load_library(const char * name, char *err_buf, int err_buflen)
-{
- void *result;
-
- result = LoadLibrary(name);
- if (result == NULL) {
- /* Error message is pretty lame, try to make a better guess. */
- long errcode;
-
- errcode = GetLastError();
- if (errcode == ERROR_MOD_NOT_FOUND) {
- strncpy(err_buf, "Can't find dependent libraries", err_buflen-2);
- err_buf[err_buflen-1] = '\0';
- } else {
- get_last_error_string(err_buf, err_buflen);
- }
- }
- return result;
-}
-
-void
-md_unload_library(void *handle)
-{
- FreeLibrary(handle);
-}
-
-void *
-md_find_library_entry(void *handle, const char *name)
-{
- return GetProcAddress(handle, name);
-}
--- a/jdk/src/jdk.httpserver/share/classes/com/sun/net/httpserver/spi/HttpServerProvider.java Thu Aug 20 12:29:58 2015 -0700
+++ b/jdk/src/jdk.httpserver/share/classes/com/sun/net/httpserver/spi/HttpServerProvider.java Wed Jul 05 20:46:25 2017 +0200
@@ -142,7 +142,7 @@
* visible to the system class loader, and that jar file contains a
* provider-configuration file named
* {@code com.sun.net.httpserver.HttpServerProvider} in the resource
- * directory <tt>META-INF/services</tt>, then the first class name
+ * directory {@code META-INF/services}, then the first class name
* specified in that file is taken. The class is loaded and
* instantiated; if this process fails then an unspecified unchecked error
* or exception is thrown. </p></li>
--- a/jdk/src/jdk.jdi/share/classes/com/sun/jdi/VirtualMachineManager.java Thu Aug 20 12:29:58 2015 -0700
+++ b/jdk/src/jdk.jdi/share/classes/com/sun/jdi/VirtualMachineManager.java Wed Jul 05 20:46:25 2017 +0200
@@ -197,8 +197,8 @@
* in a jar file that is visible to the defining class loader of
* the {@link com.sun.jdi.connect.Connector} type,
* and that jar file contains a provider configuration file named
- * <tt>com.sun.jdi.connect.Connector</tt> in the resource directory
- * <tt>META-INF/services</tt>, and the provider configuration file
+ * {@code com.sun.jdi.connect.Connector} in the resource directory
+ * {@code META-INF/services}, and the provider configuration file
* lists the full-qualified class name of the Connector
* implementation. A Connector is a class that implements the
* {@link com.sun.jdi.connect.Connector Connector} interface. More
@@ -209,7 +209,7 @@
* LaunchingConnector}. The format of the provider configuration file
* is one fully-qualified class name per line. Space and tab characters
* surrounding each class, as well as blank lines are ignored. The
- * comment character is <tt>'#'</tt> (<tt>0x23</tt>), and on each
+ * comment character is {@code '#'} ({@code 0x23}), and on each
* line all characters following the first comment character are
* ignored. The file must be encoded in UTF-8.
*
@@ -227,8 +227,8 @@
* visible to the defining class loader for the
* {@link com.sun.jdi.connect.spi.TransportService} type, and that jar
* file contains a provider configuration file named
- * <tt>com.sun.jdi.connect.spi.TransportService</tt> in the resource
- * directory <tt>META-INF/services</tt>, and the provider
+ * {@code com.sun.jdi.connect.spi.TransportService} in the resource
+ * directory {@code META-INF/services}, and the provider
* configuration file lists the full-qualified class name of the
* TransportService implementation. A TransportService is a concrete
* sub-class of {@link com.sun.jdi.connect.spi.TransportService
@@ -245,12 +245,12 @@
* com.sun.jdi.connect.Transport Transport} that in turn
* encapsulates the TransportService.
* The AttachingConnector will be named based on the name of the
- * transport service concatenated with the string <tt>Attach</tt>.
+ * transport service concatenated with the string {@code Attach}.
* For example, if the transport service {@link
* com.sun.jdi.connect.spi.TransportService#name() name()} method
- * returns <tt>telepathic</tt> then the AttachingConnector will
- * be named <tt>telepathicAttach</tt>. Similiarly the ListeningConnector
- * will be named with the string <tt>Listen</tt> tagged onto the
+ * returns {@code telepathic} then the AttachingConnector will
+ * be named {@code telepathicAttach}. Similiarly the ListeningConnector
+ * will be named with the string {@code Listen} tagged onto the
* name of the transport service. The {@link
* com.sun.jdi.connect.Connector#description() description()} method
* of both the AttachingConnector, and the ListeningConnector, will
@@ -259,10 +259,10 @@
* the AttachingConnector and the ListeningConnector will have two
* Connector {@link com.sun.jdi.connect.Connector$Argument Arguments}.
* A {@link com.sun.jdi.connect.Connector$StringArgument StringArgument}
- * named <tt>address</tt> is the connector argument to specify the
+ * named {@code address} is the connector argument to specify the
* address to attach too, or to listen on. A
* {@link com.sun.jdi.connect.Connector$IntegerArgument IntegerArgument}
- * named <tt>timeout</tt> is the connector argument to specify the
+ * named {@code timeout} is the connector argument to specify the
* timeout when attaching, or accepting. The timeout connector may be
* ignored depending on if the transport service supports an attach
* timeout or accept timeout.
@@ -372,13 +372,13 @@
* A Connector can then use this method to create a virtual machine
* mirror to represent the composite state of the target VM.
*
- * <p> The <tt>process</tt> argument specifies the
+ * <p> The {@code process} argument specifies the
* {@link java.lang.Process} object for the taget VM. It may be
- * specified as <tt>null</tt>. If the target VM is launched
+ * specified as {@code null}. If the target VM is launched
* by a {@link com.sun.jdi.connect.LaunchingConnector
- * LaunchingConnector} the <tt>process</tt> argument should be
+ * LaunchingConnector} the {@code process} argument should be
* specified, otherwise calling {@link com.sun.jdi.VirtualMachine#process()}
- * on the created virtual machine will return <tt>null</tt>.
+ * on the created virtual machine will return {@code null}.
*
* <p> This method exists so that Connectors may create
* a virtual machine mirror when a connection is established
@@ -391,7 +391,7 @@
*
* @param process
* If launched, the {@link java.lang.Process} object for
- * the target VM. <tt>null</tt> if not launched.
+ * the target VM. {@code null} if not launched.
*
* @return new virtual machine representing the target VM.
*
@@ -413,7 +413,7 @@
*
* <p> This convenience method works as if by invoking {@link
* #createVirtualMachine(Connection, Process)} method and
- * specifying <tt>null</tt> as the <tt>process</tt> argument.
+ * specifying {@code null} as the {@code process} argument.
*
* <p> This method exists so that Connectors may create
* a virtual machine mirror when a connection is established
--- a/jdk/src/jdk.jdi/share/classes/com/sun/jdi/connect/TransportTimeoutException.java Thu Aug 20 12:29:58 2015 -0700
+++ b/jdk/src/jdk.jdi/share/classes/com/sun/jdi/connect/TransportTimeoutException.java Wed Jul 05 20:46:25 2017 +0200
@@ -58,7 +58,7 @@
public class TransportTimeoutException extends java.io.IOException {
private static final long serialVersionUID = 4107035242623365074L;
/**
- * Constructs a <tt>TransportTimeoutException</tt> with no detail
+ * Constructs a {@code TransportTimeoutException} with no detail
* message.
*/
public TransportTimeoutException() {
@@ -66,7 +66,7 @@
/**
- * Constructs a <tt>TransportTimeoutException</tt> with the
+ * Constructs a {@code TransportTimeoutException} with the
* specified detail message.
*
* @param message the detail message pertaining to this exception.
--- a/jdk/src/jdk.jdi/share/classes/com/sun/jdi/connect/spi/ClosedConnectionException.java Thu Aug 20 12:29:58 2015 -0700
+++ b/jdk/src/jdk.jdi/share/classes/com/sun/jdi/connect/spi/ClosedConnectionException.java Wed Jul 05 20:46:25 2017 +0200
@@ -49,14 +49,14 @@
public class ClosedConnectionException extends java.io.IOException {
private static final long serialVersionUID = 3877032124297204774L;
/**
- * Constructs a <tt>ClosedConnectionException</tt> with no detail
+ * Constructs a {@code ClosedConnectionException} with no detail
* message.
*/
public ClosedConnectionException() {
}
/**
- * Constructs a <tt>ClosedConnectionException</tt> with the
+ * Constructs a {@code ClosedConnectionException} with the
* specified detail message.
*
* @param message the detail message pertaining to this exception.
--- a/jdk/src/jdk.jdi/share/classes/com/sun/jdi/connect/spi/TransportService.java Thu Aug 20 12:29:58 2015 -0700
+++ b/jdk/src/jdk.jdi/share/classes/com/sun/jdi/connect/spi/TransportService.java Wed Jul 05 20:46:25 2017 +0200
@@ -105,7 +105,7 @@
* multiple concurrent connections to a single address that
* it is listening on.
*
- * @return <tt>true</tt> if, and only if, this transport
+ * @return {@code true} if, and only if, this transport
* service supports multiple connections.
*/
public abstract boolean supportsMultipleConnections();
@@ -115,7 +115,7 @@
* Tell whether or not this transport service supports a timeout
* when attaching to a target VM.
*
- * @return <tt>true</tt> if, and only if, this transport
+ * @return {@code true} if, and only if, this transport
* service supports attaching with a timeout.
*
* @see #attach(String,long,long)
@@ -126,7 +126,7 @@
* Tell whether or not this transport service supports a
* timeout while waiting for a target VM to connect.
*
- * @return <tt>true</tt> if, and only if, this transport
+ * @return {@code true} if, and only if, this transport
* service supports timeout while waiting for
* a target VM to connect.
*
@@ -138,7 +138,7 @@
* Tells whether or not this transport service supports a
* timeout when handshaking with the target VM.
*
- * @return <tt>true</tt> if, and only if, this transport
+ * @return {@code true} if, and only if, this transport
* service supports a timeout while handshaking
* with the target VM.
*
@@ -176,15 +176,15 @@
*
* @param attachTimeout
* If this transport service supports an attach timeout,
- * and if <tt>attachTimeout</tt> is positive, then it specifies
+ * and if {@code attachTimeout} is positive, then it specifies
* the timeout, in milliseconds (more or less), to use
* when attaching to the target VM. If the transport service
- * does not support an attach timeout, or if <tt>attachTimeout</tt>
+ * does not support an attach timeout, or if {@code attachTimeout}
* is specified as zero then attach without any timeout.
*
* @param handshakeTimeout
* If this transport service supports a handshake timeout,
- * and if <tt>handshakeTimeout</tt> is positive, then it
+ * and if {@code handshakeTimeout} is positive, then it
* specifies the timeout, in milliseconds (more or less), to
* use when handshaking with the target VM. The exact
* usage of the timeout are specific to the transport service.
@@ -195,7 +195,7 @@
* use the handshakeTimeout as a timeout for the duration of the
* handshake exchange.
* If the transport service does not support a handshake
- * timeout, or if <tt>handshakeTimeout</tt> is specified
+ * timeout, or if {@code handshakeTimeout} is specified
* as zero then the handshake does not timeout if there
* isn't a response from the target VM.
*
@@ -221,9 +221,9 @@
/**
* A <i>listen key</i>.
*
- * <p> A <tt>TransportService</tt> may listen on multiple, yet
+ * <p> A {@code TransportService} may listen on multiple, yet
* different, addresses at the same time. To uniquely identify
- * each <tt>listener</tt> a listen key is created each time that
+ * each {@code listener} a listen key is created each time that
* {@link #startListening startListening} is called. The listen
* key is used in calls to the {@link #accept accept} method
* to accept inbound connections to that listener. A listen
@@ -250,7 +250,7 @@
*
* @param address
* The address to start listening for connections,
- * or <tt>null</tt> to listen on an address chosen
+ * or {@code null} to listen on an address chosen
* by the transport service.
*
* @return a listen key to be used in subsequent calls to be
@@ -268,8 +268,8 @@
/**
* Listens on an address chosen by the transport service.
*
- * <p> This convenience method works as if by invoking {@link
- * #startListening(String) startListening(<tt>null</tt>)}. </p>
+ * <p> This convenience method works as if by invoking
+ * {@link #startListening(String) startListening(null)}.
*
* @return a listen key to be used in subsequent calls to be
* {@link #accept accept} or {@link #stopListening
@@ -327,16 +327,16 @@
*
* @param acceptTimeout
* if this transport service supports an accept timeout, and
- * if <tt>acceptTimeout</tt> is positive then block for up to
- * <tt>acceptTimeout</tt> milliseconds, more or less, while waiting
+ * if {@code acceptTimeout} is positive then block for up to
+ * {@code acceptTimeout} milliseconds, more or less, while waiting
* for the target VM to connect.
* If the transport service does not support an accept timeout
- * or if <tt>acceptTimeout</tt> is zero then block indefinitely
+ * or if {@code acceptTimeout} is zero then block indefinitely
* for a target VM to connect.
*
* @param handshakeTimeout
* If this transport service supports a handshake timeout,
- * and if <tt>handshakeTimeout</tt> is positive, then it
+ * and if {@code handshakeTimeout} is positive, then it
* specifies the timeout, in milliseconds (more or less), to
* use when handshaking with the target VM. The exact
* usage of the timeout is specific to the transport service.
@@ -347,7 +347,7 @@
* use the timeout as a timeout for the duration of the
* handshake exchange.
* If the transport service does not support a handshake
- * timeout, of if <tt>handshakeTimeout</tt> is specified
+ * timeout, of if {@code handshakeTimeout} is specified
* as zero then the handshake does not timeout if there
* isn't a response from the target VM.
*
--- a/jdk/src/jdk.jvmstat/share/classes/sun/jvmstat/monitor/HostIdentifier.java Thu Aug 20 12:29:58 2015 -0700
+++ b/jdk/src/jdk.jvmstat/share/classes/sun/jvmstat/monitor/HostIdentifier.java Wed Jul 05 20:46:25 2017 +0200
@@ -42,26 +42,26 @@
* to the string <em>local://localhost</em>. The components of the
* HostIdentifier are:
* <ul>
- * <li><p><tt>protocol</tt> - The communications protocol. If omitted,
+ * <li><p>{@code protocol} - The communications protocol. If omitted,
* and a hostname is not specified, then default local protocol,
* <em>local:</em>, is assumed. If the protocol is omitted and a
* hostname is specified then the default remote protocol,
* <em>rmi:</em> is assumed.
* </p></li>
- * <li><p><tt>hostname</tt> - The hostname. If omitted, then
+ * <li><p>{@code hostname} - The hostname. If omitted, then
* <em>localhost</em> is assumed. If the protocol is also omitted,
* then default local protocol <em>local:</em> is also assumed.
* If the hostname is not omitted but the protocol is omitted,
* then the default remote protocol, <em>rmi:</em> is assumed.
* </p></li>
- * <li><p><tt>port</tt> - The port for the communications protocol.
- * Treatment of the <tt>port</tt> parameter is implementation
+ * <li><p>{@code port} - The port for the communications protocol.
+ * Treatment of the {@code port} parameter is implementation
* (protocol) specific. It is unused by the default local protocol,
* <em>local:</em>. For the default remote protocol, <em>rmi:</em>,
- * <tt>port</tt> indicates the port number of the <em>rmiregistry</em>
+ * {@code port} indicates the port number of the <em>rmiregistry</em>
* on the target host and defaults to port 1099.
* </p></li>
- * <li><p><tt>servername</tt> - The treatment of the Path, Query, and
+ * <li><p>{@code servername} - The treatment of the Path, Query, and
* Fragment components of the HostIdentifier are implementation
* (protocol) dependent. These components are ignored by the
* default local protocol, <em>local:</em>. For the default remote
--- a/jdk/src/jdk.jvmstat/share/classes/sun/jvmstat/monitor/MonitoredHost.java Thu Aug 20 12:29:58 2015 -0700
+++ b/jdk/src/jdk.jvmstat/share/classes/sun/jvmstat/monitor/MonitoredHost.java Wed Jul 05 20:46:25 2017 +0200
@@ -94,7 +94,7 @@
/**
* Factory method to construct MonitoredHost instances to manage
- * connections to the host indicated by <tt>hostIdString</tt>
+ * connections to the host indicated by {@code hostIdString}
*
* @param hostIdString a String representation of a {@link HostIdentifier}
* @return MonitoredHost - the MonitoredHost instance for communicating
@@ -113,7 +113,7 @@
/**
* Factory method to construct a MonitoredHost instance to manage the
- * connection to the Java Virtual Machine indicated by <tt>vmid</tt>.
+ * connection to the Java Virtual Machine indicated by {@code vmid}.
*
* This method provide a convenient short cut for attaching to a specific
* instrumented Java Virtual Machine. The information in the VmIdentifier
@@ -142,7 +142,7 @@
/**
* Factory method to construct a MonitoredHost instance to manage the
- * connection to the host indicated by <tt>hostId</tt>.
+ * connection to the host indicated by {@code hostId}.
*
* @param hostId the identifier for the target host.
* @return MonitoredHost - The MonitoredHost object needed to attach to
@@ -269,7 +269,7 @@
* Get the last exception encountered while polling this MonitoredHost.
*
* @return Exception - the last exception occurred while polling this
- * MonitoredHost, or <tt>null</tt> if no exception
+ * MonitoredHost, or {@code null} if no exception
* has occurred or the exception has been cleared,
*/
public Exception getLastException() {
--- a/jdk/src/jdk.jvmstat/share/classes/sun/jvmstat/monitor/MonitoredHostService.java Thu Aug 20 12:29:58 2015 -0700
+++ b/jdk/src/jdk.jvmstat/share/classes/sun/jvmstat/monitor/MonitoredHostService.java Wed Jul 05 20:46:25 2017 +0200
@@ -29,7 +29,7 @@
/**
* Construct a MonitoredHost instance to manage the
- * connection to the host indicated by <tt>hostId</tt>.
+ * connection to the host indicated by {@code hostId}.
*
* @param hostId the identifier for the target host.
* @return MonitoredHost - The MonitoredHost object needed to attach to
--- a/jdk/src/jdk.jvmstat/share/classes/sun/jvmstat/monitor/MonitoredVm.java Thu Aug 20 12:29:58 2015 -0700
+++ b/jdk/src/jdk.jvmstat/share/classes/sun/jvmstat/monitor/MonitoredVm.java Wed Jul 05 20:46:25 2017 +0200
@@ -55,12 +55,12 @@
* instrumentation exported by this Java Virtual Machine. If an
* instrumentation object with the given name exists, a Monitor interface
* to that object will be return. Otherwise, the method returns
- * <tt>null</tt>.
+ * {@code null}.
*
* @param name the name of the Instrumentation object to find.
* @return Monitor - the {@link Monitor} object that can be used to
* monitor the named instrumentation object, or
- * <tt>null</tt> if the named object doesn't exist.
+ * {@code null} if the named object doesn't exist.
* @throws MonitorException Thrown if an error occurs while communicating
* with the target Java Virtual Machine.
*/
@@ -99,7 +99,7 @@
/* ---- Methods to support polled MonitoredVm Implementations ---- */
/**
- * Set the polling interval to <code>interval</code> milliseconds.
+ * Set the polling interval to {@code interval} milliseconds.
*
* Polling based monitoring implementations need to refresh the
* instrumentation data on a periodic basis. This interface allows
@@ -136,10 +136,10 @@
* Get the last exception encountered while polling this MonitoredVm.
*
* Returns the last exception observed by the implementation dependent
- * polling task or <tt>null</tt> if no such error has occurred.
+ * polling task or {@code null} if no such error has occurred.
*
* @return Exception - the last exception that occurred during polling
- * or <tt>null</tt> if no error condition exists.
+ * or {@code null} if no error condition exists.
* @see #isErrored
* @see #setLastException
*/
--- a/jdk/src/jdk.jvmstat/share/classes/sun/jvmstat/perfdata/monitor/AbstractPerfDataBuffer.java Thu Aug 20 12:29:58 2015 -0700
+++ b/jdk/src/jdk.jvmstat/share/classes/sun/jvmstat/perfdata/monitor/AbstractPerfDataBuffer.java Wed Jul 05 20:46:25 2017 +0200
@@ -87,12 +87,12 @@
* instrumentation exported by this Java Virtual Machine. If an
* instrumentation object with the given name exists, a Monitor interface
* to that object will be return. Otherwise, the method returns
- * <tt>null</tt>.
+ * {@code null}.
*
* @param name the name of the Instrumentation object to find.
* @return Monitor - the {@link Monitor} object that can be used to
* monitor the named instrumentation object, or
- * <tt>null</tt> if the named object doesn't exist.
+ * {@code null} if the named object doesn't exist.
* @throws MonitorException Thrown if an error occurs while communicating
* with the target Java Virtual Machine.
*/
--- a/jdk/src/jdk.jvmstat/share/classes/sun/jvmstat/perfdata/monitor/PerfByteArrayMonitor.java Thu Aug 20 12:29:58 2015 -0700
+++ b/jdk/src/jdk.jvmstat/share/classes/sun/jvmstat/perfdata/monitor/PerfByteArrayMonitor.java Wed Jul 05 20:46:25 2017 +0200
@@ -98,7 +98,7 @@
* Get the current value of an element of the byte array instrument.
*
* @return byte - a copy of the current value of the element at index
- * <tt>index</tt> of the byte array instrument.
+ * {@code index} of the byte array instrument.
*/
public byte byteAt(int index) {
bb.position(index);
--- a/jdk/src/jdk.jvmstat/share/classes/sun/jvmstat/perfdata/monitor/PerfDataBufferImpl.java Thu Aug 20 12:29:58 2015 -0700
+++ b/jdk/src/jdk.jvmstat/share/classes/sun/jvmstat/perfdata/monitor/PerfDataBufferImpl.java Wed Jul 05 20:46:25 2017 +0200
@@ -222,7 +222,7 @@
* instrumentation exported by this Java Virtual Machine. If an
* instrumentation object with the given name exists, a Monitor interface
* to that object will be return. Otherwise, the method returns
- * <tt>null</tt>. The method will map requests for instrumention objects
+ * {@code null}. The method will map requests for instrumention objects
* using old names to their current names, if applicable.
*
*
@@ -230,7 +230,7 @@
* @param name the name of the Instrumentation object to find.
* @return Monitor - the {@link Monitor} object that can be used to
* monitor the named instrumentation object, or
- * <tt>null</tt> if the named object doesn't exist.
+ * {@code null} if the named object doesn't exist.
* @throws MonitorException Thrown if an error occurs while communicating
* with the target Java Virtual Machine.
*/
--- a/jdk/src/jdk.jvmstat/share/classes/sun/jvmstat/perfdata/monitor/protocol/file/MonitoredHostProvider.java Thu Aug 20 12:29:58 2015 -0700
+++ b/jdk/src/jdk.jvmstat/share/classes/sun/jvmstat/perfdata/monitor/protocol/file/MonitoredHostProvider.java Wed Jul 05 20:46:25 2017 +0200
@@ -66,7 +66,7 @@
* {@inheritDoc}.
* <p>
* Note - the <em>file:</em> protocol silently ignores the
- * <tt>interval</tt> parameter.
+ * {@code interval} parameter.
*/
public MonitoredVm getMonitoredVm(VmIdentifier vmid, int interval)
throws MonitorException {
--- a/jdk/src/jdk.jvmstat/share/classes/sun/jvmstat/perfdata/monitor/protocol/local/PerfDataFile.java Thu Aug 20 12:29:58 2015 -0700
+++ b/jdk/src/jdk.jvmstat/share/classes/sun/jvmstat/perfdata/monitor/protocol/local/PerfDataFile.java Wed Jul 05 20:46:25 2017 +0200
@@ -84,7 +84,7 @@
* for the JVM identified by the given local Vm Identifier.
* <p>
* This method looks for the most up to date backing store file for
- * the given <tt>lvmid</tt>. It will search all the user specific
+ * the given {@code lvmid}. It will search all the user specific
* directories in the temporary directory for the host operating
* system, which may be influenced by platform specific environment
* variables.
--- a/jdk/src/jdk.jvmstat/share/classes/sun/jvmstat/perfdata/monitor/protocol/local/package.html Thu Aug 20 12:29:58 2015 -0700
+++ b/jdk/src/jdk.jvmstat/share/classes/sun/jvmstat/perfdata/monitor/protocol/local/package.html Wed Jul 05 20:46:25 2017 +0200
@@ -40,7 +40,7 @@
implementation. It utilizes a name shared memory mechanism, identified
by a backing store file in the file system name space. The location of
the backing store file is platform specific and is dictated primarily by
-the JVM implementation. However, the <tt>java.io.tmpdir</em> system
+the JVM implementation. However, the <code>java.io.tmpdir</code> system
property generally contains the location of the files, with the exception
of the Solaris implementation, as the SDK and HotSpot JVM use different
locations for their temporary file storage. The HotSpot JVM uses the
--- a/jdk/src/jdk.management/share/classes/com/sun/management/GarbageCollectorMXBean.java Thu Aug 20 12:29:58 2015 -0700
+++ b/jdk/src/jdk.management/share/classes/com/sun/management/GarbageCollectorMXBean.java Wed Jul 05 20:46:25 2017 +0200
@@ -44,16 +44,16 @@
/**
* Returns the GC information about the most recent GC.
* This method returns a {@link GcInfo}.
- * If no GC information is available, <tt>null</tt> is returned.
+ * If no GC information is available, {@code null} is returned.
* The collector-specific attributes, if any, can be obtained
* via the {@link CompositeData CompositeData} interface.
* <p>
* <b>MBeanServer access:</b>
- * The mapped type of <tt>GcInfo</tt> is <tt>CompositeData</tt>
+ * The mapped type of {@code GcInfo} is {@code CompositeData}
* with attributes specified in {@link GcInfo#from GcInfo}.
*
- * @return a <tt>GcInfo</tt> object representing
- * the most GC information; or <tt>null</tt> if no GC
+ * @return a {@code GcInfo} object representing
+ * the most GC information; or {@code null} if no GC
* information available.
*/
public GcInfo getLastGcInfo();
--- a/jdk/src/jdk.management/share/classes/com/sun/management/HotSpotDiagnosticMXBean.java Thu Aug 20 12:29:58 2015 -0700
+++ b/jdk/src/jdk.management/share/classes/com/sun/management/HotSpotDiagnosticMXBean.java Wed Jul 05 20:46:25 2017 +0200
@@ -33,10 +33,10 @@
* <p>The diagnostic MBean is registered to the platform MBeanServer
* as are other platform MBeans.
*
- * <p>The <tt>ObjectName</tt> for uniquely identifying the diagnostic
+ * <p>The {@code ObjectName} for uniquely identifying the diagnostic
* MXBean within an MBeanServer is:
* <blockquote>
- * <tt>com.sun.management:type=HotSpotDiagnostic</tt>
+ * {@code com.sun.management:type=HotSpotDiagnostic}
* </blockquote>
.*
* It can be obtained by calling the
@@ -50,22 +50,22 @@
@jdk.Exported
public interface HotSpotDiagnosticMXBean extends PlatformManagedObject {
/**
- * Dumps the heap to the <tt>outputFile</tt> file in the same
+ * Dumps the heap to the {@code outputFile} file in the same
* format as the hprof heap dump.
* <p>
* If this method is called remotely from another process,
- * the heap dump output is written to a file named <tt>outputFile</tt>
+ * the heap dump output is written to a file named {@code outputFile}
* on the machine where the target VM is running. If outputFile is
* a relative path, it is relative to the working directory where
* the target VM was started.
*
* @param outputFile the system-dependent filename
- * @param live if <tt>true</tt> dump only <i>live</i> objects
+ * @param live if {@code true} dump only <i>live</i> objects
* i.e. objects that are reachable from others
- * @throws IOException if the <tt>outputFile</tt>
+ * @throws IOException if the {@code outputFile}
* cannot be created, opened, or written to.
* @throws UnsupportedOperationException if this operation is not supported.
- * @throws NullPointerException if <tt>outputFile</tt> is <tt>null</tt>.
+ * @throws NullPointerException if {@code outputFile} is {@code null}.
* @throws SecurityException
* If a security manager exists and its {@link
* java.lang.SecurityManager#checkWrite(java.lang.String)}
@@ -75,21 +75,21 @@
public void dumpHeap(String outputFile, boolean live) throws java.io.IOException;
/**
- * Returns a list of <tt>VMOption</tt> objects for all diagnostic options.
+ * Returns a list of {@code VMOption} objects for all diagnostic options.
* A diagnostic option is a {@link VMOption#isWriteable writeable}
* VM option that can be set dynamically mainly for troubleshooting
* and diagnosis.
*
- * @return a list of <tt>VMOption</tt> objects for all diagnostic options.
+ * @return a list of {@code VMOption} objects for all diagnostic options.
*/
public java.util.List<VMOption> getDiagnosticOptions();
/**
- * Returns a <tt>VMOption</tt> object for a VM option of the given
+ * Returns a {@code VMOption} object for a VM option of the given
* name.
*
- * @return a <tt>VMOption</tt> object for a VM option of the given name.
- * @throws NullPointerException if name is <tt>null</tt>.
+ * @return a {@code VMOption} object for a VM option of the given name.
+ * @throws NullPointerException if name is {@code null}.
* @throws IllegalArgumentException if a VM option of the given name
* does not exist.
*/
@@ -97,10 +97,10 @@
/**
* Sets a VM option of the given name to the specified value.
- * The new value will be reflected in a new <tt>VMOption</tt>
+ * The new value will be reflected in a new {@code VMOption}
* object returned by the {@link #getVMOption} method or
* the {@link #getDiagnosticOptions} method. This method does
- * not change the value of this <tt>VMOption</tt> object.
+ * not change the value of this {@code VMOption} object.
*
* @param name Name of a VM option
* @param value New value of the VM option to be set
@@ -109,7 +109,7 @@
* does not exist.
* @throws IllegalArgumentException if the new value is invalid.
* @throws IllegalArgumentException if the VM option is not writable.
- * @throws NullPointerException if name or value is <tt>null</tt>.
+ * @throws NullPointerException if name or value is {@code null}.
*
* @throws java.lang.SecurityException
* if a security manager exists and the caller does not have
--- a/jdk/src/jdk.management/share/classes/com/sun/management/OperatingSystemMXBean.java Thu Aug 20 12:29:58 2015 -0700
+++ b/jdk/src/jdk.management/share/classes/com/sun/management/OperatingSystemMXBean.java Wed Jul 05 20:46:25 2017 +0200
@@ -30,7 +30,7 @@
* on which the Java virtual machine is running.
*
* <p>
- * The <tt>OperatingSystemMXBean</tt> object returned by
+ * The {@code OperatingSystemMXBean} object returned by
* {@link java.lang.management.ManagementFactory#getOperatingSystemMXBean()}
* is an instance of the implementation class of this interface
* or {@link UnixOperatingSystemMXBean} interface depending on
@@ -46,11 +46,11 @@
/**
* Returns the amount of virtual memory that is guaranteed to
* be available to the running process in bytes,
- * or <tt>-1</tt> if this operation is not supported.
+ * or {@code -1} if this operation is not supported.
*
* @return the amount of virtual memory that is guaranteed to
* be available to the running process in bytes,
- * or <tt>-1</tt> if this operation is not supported.
+ * or {@code -1} if this operation is not supported.
*/
public long getCommittedVirtualMemorySize();
@@ -72,11 +72,11 @@
* Returns the CPU time used by the process on which the Java
* virtual machine is running in nanoseconds. The returned value
* is of nanoseconds precision but not necessarily nanoseconds
- * accuracy. This method returns <tt>-1</tt> if the
+ * accuracy. This method returns {@code -1} if the
* the platform does not support this operation.
*
* @return the CPU time used by the process in nanoseconds,
- * or <tt>-1</tt> if this operation is not supported.
+ * or {@code -1} if this operation is not supported.
*/
public long getProcessCpuTime();
--- a/jdk/src/jdk.naming.dns/share/classes/com/sun/jndi/dns/DnsContext.java Thu Aug 20 12:29:58 2015 -0700
+++ b/jdk/src/jdk.naming.dns/share/classes/com/sun/jndi/dns/DnsContext.java Wed Jul 05 20:46:25 2017 +0200
@@ -125,7 +125,7 @@
* Returns a clone of a DNS context. The context's modifiable
* private state is independent of the original's (so closing one
* context, for example, won't close the other). The two contexts
- * share <tt>environment</tt>, but it's copy-on-write so there's
+ * share {@code environment}, but it's copy-on-write so there's
* no conflict.
*/
private DnsContext(DnsContext ctx) {
--- a/jdk/src/jdk.naming.dns/share/classes/com/sun/jndi/dns/DnsName.java Thu Aug 20 12:29:58 2015 -0700
+++ b/jdk/src/jdk.naming.dns/share/classes/com/sun/jndi/dns/DnsName.java Wed Jul 05 20:46:25 2017 +0200
@@ -34,7 +34,7 @@
/**
- * <tt>DnsName</tt> implements compound names for DNS as specified by
+ * {@code DnsName} implements compound names for DNS as specified by
* RFCs 1034 and 1035, and as updated and clarified by RFCs 1123 and 2181.
*
* <p> The labels in a domain name correspond to JNDI atomic names.
@@ -57,45 +57,45 @@
* <p> DNS does not specify an encoding (such as UTF-8) to use for
* octets with non-ASCII values. As of this writing there is some
* work going on in this area, but it is not yet finalized.
- * <tt>DnsName</tt> currently converts any non-ASCII octets into
+ * {@code DnsName} currently converts any non-ASCII octets into
* characters using ISO-LATIN-1 encoding, in effect taking the
* value of each octet and storing it directly into the low-order byte
* of a Java character and <i>vice versa</i>. As a consequence, no
* character in a DNS name will ever have a non-zero high-order byte.
* When the work on internationalizing domain names has stabilized
- * (see for example <i>draft-ietf-idn-idna-10.txt</i>), <tt>DnsName</tt>
+ * (see for example <i>draft-ietf-idn-idna-10.txt</i>), {@code DnsName}
* may be updated to conform to that work.
*
- * <p> Backslash (<tt>\</tt>) is used as the escape character in the
+ * <p> Backslash ({@code \}) is used as the escape character in the
* textual representation of a domain name. The character sequence
- * `<tt>\DDD</tt>', where <tt>DDD</tt> is a 3-digit decimal number
+ * `{@code \DDD}', where {@code DDD} is a 3-digit decimal number
* (with leading zeros if needed), represents the octet whose value
- * is <tt>DDD</tt>. The character sequence `<tt>\C</tt>', where
- * <tt>C</tt> is a character other than <tt>'0'</tt> through
- * <tt>'9'</tt>, represents the octet whose value is that of
- * <tt>C</tt> (again using ISO-LATIN-1 encoding); this is particularly
- * useful for escaping <tt>'.'</tt> or backslash itself. Backslash is
+ * is {@code DDD}. The character sequence `{@code \C}', where
+ * {@code C} is a character other than {@code '0'} through
+ * {@code '9'}, represents the octet whose value is that of
+ * {@code C} (again using ISO-LATIN-1 encoding); this is particularly
+ * useful for escaping {@code '.'} or backslash itself. Backslash is
* otherwise not allowed in a domain name. Note that escape characters
* are interpreted when a name is parsed. So, for example, the character
- * sequences `<tt>S</tt>', `<tt>\S</tt>', and `<tt>\083</tt>' each
- * represent the same one-octet name. The <tt>toString()</tt> method
+ * sequences `{@code S}', `{@code \S}', and `{@code \083}' each
+ * represent the same one-octet name. The {@code toString()} method
* does not generally insert escape sequences except where necessary.
- * If, however, the <tt>DnsName</tt> was constructed using unneeded
- * escapes, those escapes may appear in the <tt>toString</tt> result.
+ * If, however, the {@code DnsName} was constructed using unneeded
+ * escapes, those escapes may appear in the {@code toString} result.
*
* <p> Atomic names passed as parameters to methods of
- * <tt>DnsName</tt>, and those returned by them, are unescaped. So,
- * for example, <tt>(new DnsName()).add("a.b")</tt> creates an
- * object representing the one-label domain name <tt>a\.b</tt>, and
- * calling <tt>get(0)</tt> on this object returns <tt>"a.b"</tt>.
+ * {@code DnsName}, and those returned by them, are unescaped. So,
+ * for example, <code>(new DnsName()).add("a.b")</code> creates an
+ * object representing the one-label domain name {@code a\.b}, and
+ * calling {@code get(0)} on this object returns {@code "a.b"}.
*
* <p> While DNS names are case-preserving, comparisons between them
* are case-insensitive. When comparing names containing non-ASCII
- * octets, <tt>DnsName</tt> uses case-insensitive comparison
+ * octets, {@code DnsName} uses case-insensitive comparison
* between pairs of ASCII values, and exact binary comparison
* otherwise.
- * <p> A <tt>DnsName</tt> instance is not synchronized against
+ * <p> A {@code DnsName} instance is not synchronized against
* concurrent access by multiple threads.
*
* @author Scott Seligman
@@ -119,16 +119,16 @@
/**
- * Constructs a <tt>DnsName</tt> representing the empty domain name.
+ * Constructs a {@code DnsName} representing the empty domain name.
*/
public DnsName() {
}
/**
- * Constructs a <tt>DnsName</tt> representing a given domain name.
+ * Constructs a {@code DnsName} representing a given domain name.
*
* @param name the domain name to parse
- * @throws InvalidNameException if <tt>name</tt> does not conform
+ * @throws InvalidNameException if {@code name} does not conform
* to DNS syntax.
*/
public DnsName(String name) throws InvalidNameException {
--- a/jdk/src/jdk.naming.dns/share/classes/com/sun/jndi/dns/NameNode.java Thu Aug 20 12:29:58 2015 -0700
+++ b/jdk/src/jdk.naming.dns/share/classes/com/sun/jndi/dns/NameNode.java Wed Jul 05 20:46:25 2017 +0200
@@ -38,7 +38,7 @@
* <p> A node may be addressed from another by giving a DnsName
* consisting of the sequence of labels from one node to the other.
*
- * <p> Each node also has an <tt>isZoneCut</tt> flag, used to indicate
+ * <p> Each node also has an {@code isZoneCut} flag, used to indicate
* if the node is a zone cut. A zone cut is a node with an NS record
* that is contained in one zone, but that actually belongs to a child zone.
*
@@ -115,7 +115,7 @@
/*
* Returns the node at the end of a path, or null if the
* node does not exist.
- * The path is specified by the labels of <tt>name</tt>, beginning
+ * The path is specified by the labels of {@code name}, beginning
* at index idx.
*/
NameNode get(DnsName name, int idx) {
@@ -129,7 +129,7 @@
/*
* Returns the node at the end of a path, creating it and any
* intermediate nodes as needed.
- * The path is specified by the labels of <tt>name</tt>, beginning
+ * The path is specified by the labels of {@code name}, beginning
* at index idx.
*/
NameNode add(DnsName name, int idx) {
--- a/jdk/src/jdk.naming.dns/share/classes/com/sun/jndi/dns/Resolver.java Thu Aug 20 12:29:58 2015 -0700
+++ b/jdk/src/jdk.naming.dns/share/classes/com/sun/jndi/dns/Resolver.java Wed Jul 05 20:46:25 2017 +0200
@@ -160,7 +160,7 @@
}
/*
- * Finds the name servers of a zone. <tt>zone</tt> is a fully-qualified
+ * Finds the name servers of a zone. {@code zone} is a fully-qualified
* domain name at the top of a zone.
* If recursion is true, recursion is requested on the query.
*/
--- a/jdk/src/jdk.naming.dns/share/classes/com/sun/jndi/dns/ZoneNode.java Thu Aug 20 12:29:58 2015 -0700
+++ b/jdk/src/jdk.naming.dns/share/classes/com/sun/jndi/dns/ZoneNode.java Wed Jul 05 20:46:25 2017 +0200
@@ -154,7 +154,7 @@
}
/*
- * Set this zone's data to expire in <tt>secsToExpiration</tt> seconds.
+ * Set this zone's data to expire in {@code secsToExpiration} seconds.
*/
private void setExpiration(long secsToExpiration) {
expiration = new Date(System.currentTimeMillis() +
--- a/jdk/test/ProblemList.txt Thu Aug 20 12:29:58 2015 -0700
+++ b/jdk/test/ProblemList.txt Wed Jul 05 20:46:25 2017 +0200
@@ -129,6 +129,9 @@
# 8029891
java/lang/ClassLoader/deadlock/GetResource.java generic-all
+# 8133552
+java/lang/ProcessHandle/InfoTest.java generic-all
+
############################################################################
# jdk_instrument
--- a/jdk/test/com/sun/management/OperatingSystemMXBean/TestTotalSwap.java Thu Aug 20 12:29:58 2015 -0700
+++ b/jdk/test/com/sun/management/OperatingSystemMXBean/TestTotalSwap.java Wed Jul 05 20:46:25 2017 +0200
@@ -73,6 +73,8 @@
private static final long MAX_SIZE_FOR_PASS = Long.MAX_VALUE;
public static void main(String args[]) throws Throwable {
+ // yocto might ignore the request to report swap size in bytes
+ boolean swapInKB = mbean.getVersion().contains("yocto");
long expected_swap_size = getSwapSizeFromOs();
@@ -87,10 +89,13 @@
if (expected_swap_size > -1) {
if (size != expected_swap_size) {
- throw new RuntimeException("Expected total swap size : " +
- expected_swap_size +
- " but getTotalSwapSpaceSize returned: " +
- size);
+ // try the expected size in kiloBytes
+ if (!(swapInKB && expected_swap_size * 1024 == size)) {
+ throw new RuntimeException("Expected total swap size : " +
+ expected_swap_size +
+ " but getTotalSwapSpaceSize returned: " +
+ size);
+ }
}
}
--- a/jdk/test/java/lang/ClassLoader/GetSystemPackage.java Thu Aug 20 12:29:58 2015 -0700
+++ b/jdk/test/java/lang/ClassLoader/GetSystemPackage.java Wed Jul 05 20:46:25 2017 +0200
@@ -181,7 +181,6 @@
private static Package findPackage(String name) {
Package[] packages = Package.getPackages();
for (Package p : packages) {
- System.out.println(p);
if (p.getName().equals(name)) {
return p;
}
--- a/jdk/test/java/lang/ProcessHandle/InfoTest.java Thu Aug 20 12:29:58 2015 -0700
+++ b/jdk/test/java/lang/ProcessHandle/InfoTest.java Wed Jul 05 20:46:25 2017 +0200
@@ -49,10 +49,12 @@
/*
* @test
+ * @bug 8077350 8081566 8081567 8098852
* @build jdk.testlibrary.*
* @library /lib/testlibrary
* @summary Functions of ProcessHandle.Info
* @author Roger Riggs
+ * @key intermittent
*/
public class InfoTest {
@@ -136,7 +138,17 @@
}
}
-
+ if (Platform.isAix()) {
+ // Unfortunately, on AIX the usr/sys times reported through
+ // /proc/<pid>/psinfo which are used by ProcessHandle.Info
+ // are running slow compared to the corresponding times reported
+ // by the times()/getrusage() system calls which are used by
+ // OperatingSystemMXBean.getProcessCpuTime() and returned by
+ // the JavaChild for the "cputime" command.
+ // This is because /proc/<pid>/status is only updated once a second.
+ // So we better wait a little bit to get plausible values here.
+ Thread.sleep(1000);
+ }
ProcessHandle.Info info = p1.info();
System.out.printf(" info: %s%n", info);
@@ -160,19 +172,10 @@
if (info.arguments().isPresent()) {
String[] args = info.arguments().get();
- if (Platform.isLinux() || Platform.isOSX()) {
- int offset = args.length - extraArgs.length;
- for (int i = 0; i < extraArgs.length; i++) {
- Assert.assertEquals(args[offset + i], extraArgs[i],
- "Actual argument mismatch, index: " + i);
- }
- } else if (Platform.isSolaris()) {
- Assert.assertEquals(args.length, 1,
- "Expected argument list length: 1");
- Assert.assertNotNull(args[0],
- "Expected an argument");
- } else {
- System.out.printf("No argument test for OS: %s%n", Platform.getOsName());
+ int offset = args.length - extraArgs.length;
+ for (int i = 0; i < extraArgs.length; i++) {
+ Assert.assertEquals(args[offset + i], extraArgs[i],
+ "Actual argument mismatch, index: " + i);
}
// Now check that the first argument is not the same as the executed command
@@ -183,6 +186,46 @@
}
}
+ if (command.isPresent() && info.arguments().isPresent()) {
+ // If both, 'command' and 'arguments' are present,
+ // 'commandLine' is just the concatenation of the two.
+ Assert.assertTrue(info.commandLine().isPresent(),
+ "commandLine() must be available");
+
+ String javaExe = System.getProperty("test.jdk") +
+ File.separator + "bin" + File.separator + "java";
+ String expected = Platform.isWindows() ? javaExe + ".exe" : javaExe;
+ Path expectedPath = Paths.get(expected);
+ String commandLine = info.commandLine().get();
+ String commandLineCmd = commandLine.split(" ")[0];
+ Path commandLineCmdPath = Paths.get(commandLineCmd);
+ Assert.assertTrue(Files.isSameFile(commandLineCmdPath, expectedPath),
+ "commandLine() should start with: " + expectedPath +
+ " but starts with " + commandLineCmdPath);
+
+ List<String> allArgs = p1.getArgs();
+ for (int i = 0; i < allArgs.size(); i++) {
+ Assert.assertTrue(commandLine.contains(allArgs.get(i)),
+ "commandLine() must contain argument: " + allArgs.get(i));
+ }
+ } else if (info.commandLine().isPresent()) {
+ // If we only have the commandLine() we can only do some basic checks...
+ String commandLine = info.commandLine().get();
+ String javaExe = "java" + (Platform.isWindows() ? ".exe": "");
+ int pos = commandLine.indexOf(javaExe);
+ Assert.assertTrue(pos > 0, "commandLine() should at least contain 'java'");
+
+ pos += javaExe.length() + 1; // +1 for the space after the command
+ List<String> allArgs = p1.getArgs();
+ // First argument is the command - skip it here as we've already checked that.
+ for (int i = 1; (i < allArgs.size()) &&
+ (pos + allArgs.get(i).length() < commandLine.length()); i++) {
+ Assert.assertTrue(commandLine.contains(allArgs.get(i)),
+ "commandLine() must contain argument: " + allArgs.get(i));
+ pos += allArgs.get(i).length() + 1;
+ }
+ }
+
if (info.totalCpuDuration().isPresent()) {
Duration totalCPU = info.totalCpuDuration().get();
Duration epsilon = Duration.ofMillis(200L);
@@ -269,10 +312,27 @@
public static void test4() {
Duration myCputime1 = ProcessUtil.MXBeanCpuTime();
+ if (Platform.isAix()) {
+ // Unfortunately, on AIX the usr/sys times reported through
+ // /proc/<pid>/psinfo which are used by ProcessHandle.Info
+ // are running slow compared to the corresponding times reported
+ // by the times()/getrusage() system calls which are used by
+ // OperatingSystemMXBean.getProcessCpuTime() and returned by
+ // the JavaChild for the "cputime" command.
+ // So we better wait a little bit to get plausible values here.
+ try {
+ Thread.sleep(1000);
+ } catch (InterruptedException ex) {}
+ }
Optional<Duration> dur1 = ProcessHandle.current().info().totalCpuDuration();
Duration myCputime2 = ProcessUtil.MXBeanCpuTime();
+ if (Platform.isAix()) {
+ try {
+ Thread.sleep(1000);
+ } catch (InterruptedException ex) {}
+ }
Optional<Duration> dur2 = ProcessHandle.current().info().totalCpuDuration();
if (dur1.isPresent() && dur2.isPresent()) {
--- a/jdk/test/java/lang/ProcessHandle/JavaChild.java Thu Aug 20 12:29:58 2015 -0700
+++ b/jdk/test/java/lang/ProcessHandle/JavaChild.java Wed Jul 05 20:46:25 2017 +0200
@@ -68,8 +68,9 @@
* {@link #forEachOutputLine} can be used to process output from the child
* @param delegate the process to delegate and send commands to and get responses from
*/
- private JavaChild(Process delegate) {
- this.delegate = delegate;
+ private JavaChild(ProcessBuilder pb) throws IOException {
+ allArgs = pb.command();
+ delegate = pb.start();
// Initialize PrintWriter with autoflush (on println)
inputWriter = new PrintWriter(delegate.getOutputStream(), true);
outputReader = new BufferedReader(new InputStreamReader(delegate.getInputStream()));
@@ -119,6 +120,10 @@
return "delegate: " + delegate.toString();
}
+ public List<String> getArgs() {
+ return allArgs;
+ }
+
public CompletableFuture<JavaChild> onJavaChildExit() {
return onExit().thenApply(ph -> this);
}
@@ -187,7 +192,7 @@
}
ProcessBuilder pb = build(stringArgs);
pb.redirectError(ProcessBuilder.Redirect.INHERIT);
- return new JavaChild(pb.start());
+ return new JavaChild(pb);
}
/**
@@ -236,6 +241,9 @@
"-classpath", absolutifyPath(classpath),
"JavaChild");
+ // Will hold the complete list of arguments which was given to Processbuilder.command()
+ private List<String> allArgs;
+
private static String absolutifyPath(String path) {
StringBuilder sb = new StringBuilder();
for (String file : path.split(File.pathSeparator)) {
--- a/jdk/test/java/lang/ProcessHandle/OnExitTest.java Thu Aug 20 12:29:58 2015 -0700
+++ b/jdk/test/java/lang/ProcessHandle/OnExitTest.java Wed Jul 05 20:46:25 2017 +0200
@@ -126,6 +126,11 @@
} while (processes.size() < expected &&
Instant.now().isBefore(endTimeout));
+ if (processes.size() < expected) {
+ printf("WARNING: not all children have been started. Can't complete test.%n");
+ printf(" You can try to increase the timeout or%n");
+ printf(" you can try to use a faster VM (i.e. not a debug version).%n");
+ }
children = getAllChildren(procHandle);
ConcurrentHashMap<ProcessHandle, CompletableFuture<ProcessHandle>> completions =
--- a/jdk/test/java/lang/invoke/ExplicitCastArgumentsTest.java Thu Aug 20 12:29:58 2015 -0700
+++ b/jdk/test/java/lang/invoke/ExplicitCastArgumentsTest.java Wed Jul 05 20:46:25 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -21,79 +21,583 @@
* questions.
*/
-package java.lang.invoke;
-
+import com.oracle.testlibrary.jsr292.Helper;
+import java.io.File;
+import java.io.Serializable;
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+import java.lang.invoke.WrongMethodTypeException;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Random;
import sun.invoke.util.Wrapper;
-/* @test
+/*
+ * @test
+ * @bug 8060483 8066746
+ * @key randomness
+ * @library /lib/testlibrary /lib/testlibrary/jsr292
* @summary unit tests for MethodHandles.explicitCastArguments()
- *
- * @run main/bootclasspath java.lang.invoke.ExplicitCastArgumentsTest
+ * @run main ExplicitCastArgumentsTest
+ */
+
+/**
+ * Tests for MethodHandles.explicitCastArguments().
*/
public class ExplicitCastArgumentsTest {
- private static final boolean VERBOSE = Boolean.getBoolean("verbose");
+
+ private static final boolean VERBOSE = Helper.IS_VERBOSE;
private static final Class<?> THIS_CLASS = ExplicitCastArgumentsTest.class;
+ private static final Random RNG = Helper.RNG;
+ private static final Map<Wrapper, Object> RANDOM_VALUES = new HashMap<>(9);
+
+ static {
+ RANDOM_VALUES.put(Wrapper.BOOLEAN, RNG.nextBoolean());
+ RANDOM_VALUES.put(Wrapper.BYTE, (byte) RNG.nextInt());
+ RANDOM_VALUES.put(Wrapper.SHORT, (short) RNG.nextInt());
+ RANDOM_VALUES.put(Wrapper.CHAR, (char) RNG.nextInt());
+ RANDOM_VALUES.put(Wrapper.INT, RNG.nextInt());
+ RANDOM_VALUES.put(Wrapper.LONG, RNG.nextLong());
+ RANDOM_VALUES.put(Wrapper.FLOAT, RNG.nextFloat());
+ RANDOM_VALUES.put(Wrapper.DOUBLE, RNG.nextDouble());
+ RANDOM_VALUES.put(Wrapper.OBJECT, new Object());
+ }
public static void main(String[] args) throws Throwable {
testVarargsCollector();
+ testNullRef2Prim();
testRef2Prim();
+ testPrim2Ref();
+ testPrim2Prim();
+ testNonBCPRef2NonBCPRef();
+ testBCPRef2BCPRef();
+ testNonBCPRef2BCPRef();
+ testReturnAny2Void();
+ testReturnVoid2Any();
+ testMultipleArgs();
System.out.println("TEST PASSED");
}
- public static String[] f(String... args) { return args; }
+ /**
+ * Dummy method used in {@link #testVarargsCollector} test to form a method
+ * handle.
+ *
+ * @param args - any args
+ * @return - returns args
+ */
+ public static String[] f(String... args) {
+ return args;
+ }
+ /**
+ * Tests that MHs.explicitCastArguments does incorrect type checks for
+ * VarargsCollector. Bug 8066746.
+ *
+ * @throws java.lang.Throwable
+ */
public static void testVarargsCollector() throws Throwable {
MethodType mt = MethodType.methodType(String[].class, String[].class);
- MethodHandle mh = MethodHandles.publicLookup().findStatic(THIS_CLASS, "f", mt);
- mh = MethodHandles.explicitCastArguments(mh, MethodType.methodType(Object.class, Object.class));
- mh.invokeWithArguments((Object)(new String[] {"str1", "str2"}));
+ MethodHandle mh = MethodHandles.publicLookup()
+ .findStatic(THIS_CLASS, "f", mt);
+ mh = MethodHandles.explicitCastArguments(mh,
+ MethodType.methodType(Object.class, Object.class));
+ mh.invokeWithArguments((Object) (new String[]{"str1", "str2"}));
+ }
+
+ /**
+ * Tests that null wrapper reference is successfully converted to primitive
+ * types. Converted result should be zero for a primitive. Bug 8060483.
+ */
+ public static void testNullRef2Prim() {
+ for (Wrapper from : Wrapper.values()) {
+ for (Wrapper to : Wrapper.values()) {
+ if (from == Wrapper.VOID || to == Wrapper.VOID) {
+ continue;
+ }
+ // MHs.eCA javadoc:
+ // If T0 is a reference and T1 a primitive, and if the reference
+ // is null at runtime, a zero value is introduced.
+ for (TestConversionMode mode : TestConversionMode.values()) {
+ testConversion(mode, from.wrapperType(),
+ to.primitiveType(), null, to.zero(), false, null);
+ }
+ }
+ }
}
- public static void testRef2Prim() throws Throwable {
+ /**
+ * Tests that non-null wrapper reference is successfully converted to
+ * primitive types.
+ */
+ public static void testRef2Prim() {
+ for (Wrapper from : Wrapper.values()) {
+ for (Wrapper to : Wrapper.values()) {
+ if (from == Wrapper.VOID || to == Wrapper.VOID
+ || to == Wrapper.OBJECT) {
+ continue;
+ }
+ Object value = RANDOM_VALUES.get(from);
+ for (TestConversionMode mode : TestConversionMode.values()) {
+ if (from != Wrapper.OBJECT) {
+ Object convValue = to.wrap(value);
+ testConversion(mode, from.wrapperType(),
+ to.primitiveType(), value, convValue, false, null);
+ } else {
+ testConversion(mode, from.wrapperType(),
+ to.primitiveType(), value, null,
+ true, ClassCastException.class);
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Tests that primitive is successfully converted to wrapper reference
+ * types, to the Number type (if possible) and to the Object type.
+ */
+ public static void testPrim2Ref() {
for (Wrapper from : Wrapper.values()) {
for (Wrapper to : Wrapper.values()) {
- if (from == Wrapper.VOID || to == Wrapper.VOID) continue;
- testRef2Prim(from, to);
+ if (from == Wrapper.VOID || from == Wrapper.OBJECT
+ || to == Wrapper.VOID || to == Wrapper.OBJECT) {
+ continue;
+ }
+ Object value = RANDOM_VALUES.get(from);
+ for (TestConversionMode mode : TestConversionMode.values()) {
+ if (from == to) {
+ testConversion(mode, from.primitiveType(),
+ to.wrapperType(), value, value, false, null);
+ } else {
+ testConversion(mode, from.primitiveType(),
+ to.wrapperType(), value, null, true, ClassCastException.class);
+ }
+ if (from != Wrapper.BOOLEAN && from != Wrapper.CHAR) {
+ testConversion(mode, from.primitiveType(),
+ Number.class, value, value, false, null);
+ } else {
+ testConversion(mode, from.primitiveType(),
+ Number.class, value, null,
+ true, ClassCastException.class);
+ }
+ testConversion(mode, from.primitiveType(),
+ Object.class, value, value, false, null);
+ }
+ }
+ }
+ }
+
+ /**
+ * Tests that primitive is successfully converted to other primitive type.
+ */
+ public static void testPrim2Prim() {
+ for (Wrapper from : Wrapper.values()) {
+ for (Wrapper to : Wrapper.values()) {
+ if (from == Wrapper.VOID || to == Wrapper.VOID
+ || from == Wrapper.OBJECT || to == Wrapper.OBJECT) {
+ continue;
+ }
+ Object value = RANDOM_VALUES.get(from);
+ Object convValue = to.wrap(value);
+ for (TestConversionMode mode : TestConversionMode.values()) {
+ testConversion(mode, from.primitiveType(),
+ to.primitiveType(), value, convValue, false, null);
+ }
}
}
}
- public static void testRef2Prim(Wrapper from, Wrapper to) throws Throwable {
- // MHs.eCA javadoc:
- // If T0 is a reference and T1 a primitive, and if the reference is null at runtime, a zero value is introduced.
- test(from.wrapperType(), to.primitiveType(), null, false);
+ /**
+ * Dummy interface for {@link #testNonBCPRef2Ref} test.
+ */
+ public static interface TestInterface {}
+
+ /**
+ * Dummy class for {@link #testNonBCPRef2Ref} test.
+ */
+ public static class TestSuperClass implements TestInterface {}
+
+ /**
+ * Dummy class for {@link #testNonBCPRef2Ref} test.
+ */
+ public static class TestSubClass1 extends TestSuperClass {}
+
+ /**
+ * Dummy class for {@link #testNonBCPRef2Ref} test.
+ */
+ public static class TestSubClass2 extends TestSuperClass {}
+
+ /**
+ * Tests non-bootclasspath reference to reference conversions.
+ *
+ * @throws java.lang.Throwable
+ */
+ public static void testNonBCPRef2NonBCPRef() throws Throwable {
+ Class testInterface = TestInterface.class;
+ Class testSuperClass = TestSuperClass.class;
+ Class testSubClass1 = TestSubClass1.class;
+ Class testSubClass2 = TestSubClass2.class;
+ Object testSuperObj = new TestSuperClass();
+ Object testObj01 = new TestSubClass1();
+ Object testObj02 = new TestSubClass2();
+ Class[] parents = {testInterface, testSuperClass};
+ Class[] children = {testSubClass1, testSubClass2};
+ Object[] childInst = {testObj01, testObj02};
+ for (TestConversionMode mode : TestConversionMode.values()) {
+ for (Class parent : parents) {
+ for (int j = 0; j < children.length; j++) {
+ // Child type to parent type non-null conversion, shoud succeed
+ testConversion(mode, children[j], parent, childInst[j], childInst[j], false, null);
+ // Child type to parent type null conversion, shoud succeed
+ testConversion(mode, children[j], parent, null, null, false, null);
+ // Parent type to child type non-null conversion with parent
+ // type instance, should fail
+ testConversion(mode, parent, children[j], testSuperObj, null, true, ClassCastException.class);
+ // Parent type to child type non-null conversion with child
+ // type instance, should succeed
+ testConversion(mode, parent, children[j], childInst[j], childInst[j], false, null);
+ // Parent type to child type null conversion, should succeed
+ testConversion(mode, parent, children[j], null, null, false, null);
+ }
+ // Parent type to child type non-null conversion with sibling
+ // type instance, should fail
+ testConversion(mode, parent, testSubClass1, testObj02, null, true, ClassCastException.class);
+ }
+ // Sibling type non-null conversion, should fail
+ testConversion(mode, testSubClass1,
+ testSubClass2, testObj01, null, true,
+ ClassCastException.class);
+ // Sibling type null conversion, should succeed
+ testConversion(mode, testSubClass1,
+ testSubClass2, null, null, false, null);
+ }
+ }
+
+ /**
+ * Dummy interface for {@link #testNonBCPRef2BCPRef} test.
+ */
+ public static interface TestSerializableInterface extends Serializable {}
+
+ /**
+ * Dummy class for {@link #testNonBCPRef2BCPRef} test.
+ */
+ public static class TestSerializableClass
+ implements TestSerializableInterface {}
+
+ /**
+ * Dummy class for {@link #testNonBCPRef2BCPRef} test.
+ */
+ public static class TestFileChildClass extends File
+ implements TestSerializableInterface {
+ public TestFileChildClass(String pathname) {
+ super(pathname);
+ }
+ }
+
+ /**
+ * Tests non-bootclasspath reference to bootclasspath reference conversions
+ * and vice-versa.
+ *
+ * @throws java.lang.Throwable
+ */
+ public static void testNonBCPRef2BCPRef() throws Throwable {
+ Class bcpInterface = Serializable.class;
+ Class bcpSuperClass = File.class;
+ Class nonBcpInterface = TestSerializableInterface.class;
+ Class nonBcpSuperSiblingClass = TestSerializableClass.class;
+ Class nonBcpSubClass = TestFileChildClass.class;
+ Object bcpSuperObj = new File(".");
+ Object testSuperSiblingObj = new TestSerializableClass();
+ Object testSubObj = new TestFileChildClass(".");
+ Class[] parents = {bcpInterface, bcpSuperClass};
+ for (TestConversionMode mode : TestConversionMode.values()) {
+ for (Class parent : parents) {
+ // Child type to parent type non-null conversion, shoud succeed
+ testConversion(mode, nonBcpSubClass, parent, testSubObj,
+ testSubObj, false, null);
+ // Child type to parent type null conversion, shoud succeed
+ testConversion(mode, nonBcpSubClass, parent, null, null,
+ false, null);
+ // Parent type to child type non-null conversion with parent
+ // type instance, should fail
+ testConversion(mode, parent, nonBcpSubClass, bcpSuperObj, null,
+ true, ClassCastException.class);
+ // Parent type to child type non-null conversion with child
+ // type instance, should succeed
+ testConversion(mode, parent, nonBcpSubClass, testSubObj,
+ testSubObj, false, null);
+ // Parent type to child type null conversion, should succeed
+ testConversion(mode, parent, nonBcpSubClass, null, null,
+ false, null);
+ }
+ // Parent type to child type non-null conversion with
+ // super sibling type instance, should fail
+ testConversion(mode, bcpInterface, nonBcpSubClass,
+ testSuperSiblingObj, null, true, ClassCastException.class);
+ Class[] siblings = {nonBcpSubClass, bcpSuperClass};
+ for (Class sibling : siblings) {
+ // Non-bcp class to bcp/non-bcp sibling class non-null
+ // conversion with nonBcpSuperSiblingClass instance, should fail
+ testConversion(mode, nonBcpSuperSiblingClass, sibling,
+ testSuperSiblingObj, null, true, ClassCastException.class);
+ // Non-bcp class to bcp/non-bcp sibling class null conversion,
+ // should succeed
+ testConversion(mode, nonBcpSuperSiblingClass, sibling,
+ null, null, false, null);
+ // Non-bcp interface to bcp/non-bcp sibling class non-null
+ // conversion with nonBcpSubClass instance, should succeed
+ testConversion(mode, nonBcpInterface, sibling, testSubObj,
+ testSubObj, false, null);
+ // Non-bcp interface to bcp/non-bcp sibling class
+ // null conversion, should succeed
+ testConversion(mode, nonBcpInterface, sibling, null, null,
+ false, null);
+ // Non-bcp interface to bcp/non-bcp sibling class non-null
+ // conversion with nonBcpSuperSiblingClass instance, should fail
+ testConversion(mode, nonBcpInterface, sibling,
+ testSuperSiblingObj, testSubObj,
+ true, ClassCastException.class);
+ }
+ }
}
- public static void test(Class<?> from, Class<?> to, Object param, boolean failureExpected) throws Throwable {
- if (VERBOSE) System.out.printf("%-10s => %-10s: %5s: ", from.getSimpleName(), to.getSimpleName(), param);
+ /**
+ * Tests bootclasspath reference to reference conversions.
+ */
+ public static void testBCPRef2BCPRef() {
+ Class bcpInterface = CharSequence.class;
+ Class bcpSubClass1 = String.class;
+ Class bcpSubClass2 = StringBuffer.class;
+ Object testObj01 = new String("test");
+ Object testObj02 = new StringBuffer("test");
+ Class[] children = {bcpSubClass1, bcpSubClass2};
+ Object[] childInst = {testObj01, testObj02};
+ for (TestConversionMode mode : TestConversionMode.values()) {
+ for (int i = 0; i < children.length; i++) {
+ // Child type to parent type non-null conversion, shoud succeed
+ testConversion(mode, children[i], bcpInterface, childInst[i],
+ childInst[i], false, null);
+ // Child type to parent type null conversion, shoud succeed
+ testConversion(mode, children[i], bcpInterface, null,
+ null, false, null);
+ // Parent type to child type non-null conversion with child
+ // type instance, should succeed
+ testConversion(mode, bcpInterface,
+ children[i], childInst[i], childInst[i], false, null);
+ // Parent type to child type null conversion, should succeed
+ testConversion(mode, bcpInterface,
+ children[i], null, null, false, null);
+ }
+ // Sibling type non-null conversion, should fail
+ testConversion(mode, bcpSubClass1,
+ bcpSubClass2, testObj01, null, true,
+ ClassCastException.class);
+ // Sibling type null conversion, should succeed
+ testConversion(mode, bcpSubClass1,
+ bcpSubClass2, null, null, false, null);
+ // Parent type to child type non-null conversion with sibling
+ // type instance, should fail
+ testConversion(mode, bcpInterface, bcpSubClass1, testObj02,
+ null, true, ClassCastException.class);
+ }
+ }
+
+ /**
+ * Dummy method used in {@link #testReturnAny2Void} and
+ * {@link #testReturnVoid2Any} tests to form a method handle.
+ */
+ public static void retVoid() {}
+
+ /**
+ * Tests that non-null any return is successfully converted to non-type
+ * void.
+ */
+ public static void testReturnAny2Void() {
+ for (Wrapper from : Wrapper.values()) {
+ testConversion(TestConversionMode.RETURN_VALUE, from.wrapperType(),
+ void.class, RANDOM_VALUES.get(from),
+ null, false, null);
+ testConversion(TestConversionMode.RETURN_VALUE, from.primitiveType(),
+ void.class, RANDOM_VALUES.get(from),
+ null, false, null);
+ }
+ }
+
+ /**
+ * Tests that void return is successfully converted to primitive and
+ * reference. Result should be zero for primitives and null for references.
+ */
+ public static void testReturnVoid2Any() {
+ for (Wrapper to : Wrapper.values()) {
+ testConversion(TestConversionMode.RETURN_VALUE, void.class,
+ to.primitiveType(), null,
+ to.zero(), false, null);
+ testConversion(TestConversionMode.RETURN_VALUE, void.class,
+ to.wrapperType(), null,
+ null, false, null);
+ }
+ }
+
+ private static void checkForWrongMethodTypeException(MethodHandle mh, MethodType mt) {
+ try {
+ MethodHandles.explicitCastArguments(mh, mt);
+ throw new AssertionError("Expected WrongMethodTypeException is not thrown");
+ } catch (WrongMethodTypeException wmte) {
+ if (VERBOSE) {
+ System.out.printf("Expected exception %s: %s\n",
+ wmte.getClass(), wmte.getMessage());
+ }
+ }
+ }
- MethodHandle original = MethodHandles.identity(from);
- MethodType newType = original.type().changeReturnType(to);
+ /**
+ * Tests that MHs.eCA method works correctly with MHs with multiple arguments.
+ * @throws Throwable
+ */
+ public static void testMultipleArgs() throws Throwable {
+ int arity = 1 + RNG.nextInt(Helper.MAX_ARITY / 2 - 2);
+ int arityMinus = RNG.nextInt(arity);
+ int arityPlus = arity + RNG.nextInt(Helper.MAX_ARITY / 2 - arity) + 1;
+ MethodType mType = Helper.randomMethodTypeGenerator(arity);
+ MethodType mTypeNew = Helper.randomMethodTypeGenerator(arity);
+ MethodType mTypeNewMinus = Helper.randomMethodTypeGenerator(arityMinus);
+ MethodType mTypeNewPlus = Helper.randomMethodTypeGenerator(arityPlus);
+ Class<?> rType = mType.returnType();
+ MethodHandle original;
+ if (rType.equals(void.class)) {
+ MethodType mt = MethodType.methodType(void.class);
+ original = MethodHandles.publicLookup()
+ .findStatic(THIS_CLASS, "retVoid", mt);
+ } else {
+ Object rValue = Helper.castToWrapper(1, rType);
+ original = MethodHandles.constant(rType, rValue);
+ }
+ original = Helper.addTrailingArgs(original, arity, mType.parameterList());
+ MethodHandle target = MethodHandles
+ .explicitCastArguments(original, mTypeNew);
+ Object[] parList = Helper.randomArgs(mTypeNew.parameterList());
+ for (int i = 0; i < parList.length; i++) {
+ if (parList[i] instanceof String) {
+ parList[i] = null; //getting rid of Stings produced by randomArgs
+ }
+ }
+ target.invokeWithArguments(parList);
+ checkForWrongMethodTypeException(original, mTypeNewMinus);
+ checkForWrongMethodTypeException(original, mTypeNewPlus);
+ }
+
+ /**
+ * Enumeration of test conversion modes.
+ */
+ public enum TestConversionMode {
+ RETURN_VALUE,
+ ARGUMENT;
+ }
+ /**
+ * Tests type and value conversion. Comparing with the given expected result.
+ *
+ * @param mode - test conversion mode. See {@link #TestConversionMode}.
+ * @param from - source type.
+ * @param to - destination type.
+ * @param param - value to be converted.
+ * @param expectedResult - expected value after conversion.
+ * @param failureExpected - true if conversion failure expected.
+ * @param expectedException - expected exception class if
+ * {@code failureExpected} is true.
+ */
+ public static void testConversion(TestConversionMode mode,
+ Class<?> from, Class<?> to, Object param,
+ Object expectedResult, boolean failureExpected,
+ Class<? extends Throwable> expectedException) {
+ if (VERBOSE) {
+ System.out.printf("Testing return value conversion: "
+ + "%-10s => %-10s: %5s: ", from.getSimpleName(),
+ to.getSimpleName(), param);
+ }
+ MethodHandle original = null;
+ MethodType newType = null;
+ switch (mode) {
+ case RETURN_VALUE:
+ if (from.equals(void.class)) {
+ MethodType mt = MethodType.methodType(void.class);
+ try {
+ original = MethodHandles.publicLookup()
+ .findStatic(THIS_CLASS, "retVoid", mt);
+ } catch (NoSuchMethodException | IllegalAccessException ex) {
+ throw new Error("Unexpected issue", ex);
+ }
+ } else {
+ original = MethodHandles.constant(from, param);
+ }
+ newType = original.type().changeReturnType(to);
+ break;
+ case ARGUMENT:
+ if (from.equals(void.class) || to.equals(void.class)) {
+ throw new Error("Test issue: argument conversion does not"
+ + " work with non-type void");
+ }
+ original = MethodHandles.identity(to);
+ newType = original.type().changeParameterType(0, from);
+ break;
+ default:
+ String msg = String.format("Test issue: unknown test"
+ + " convertion mode %s.", mode.name());
+ throw new Error(msg);
+ }
try {
- MethodHandle target = MethodHandles.explicitCastArguments(original, newType);
- Object result = target.invokeWithArguments(param);
-
+ MethodHandle target = MethodHandles
+ .explicitCastArguments(original, newType);
+ Object result;
+ switch (mode) {
+ case RETURN_VALUE:
+ result = target.invokeWithArguments();
+ break;
+ case ARGUMENT:
+ result = target.invokeWithArguments(param);
+ break;
+ default:
+ String msg = String.format("Test issue: unknown test"
+ + " convertion mode %s.", mode.name());
+ throw new Error(msg);
+ }
+ if (!failureExpected
+ && (expectedResult != null && !expectedResult.equals(result)
+ || expectedResult == null && result != null)) {
+ String msg = String.format("Conversion result %s is not equal"
+ + " to the expected result %10s",
+ result, expectedResult);
+ throw new AssertionError(msg);
+ }
if (VERBOSE) {
String resultStr;
if (result != null) {
- resultStr = String.format("%10s (%10s)", "'"+result+"'", result.getClass().getSimpleName());
+ resultStr = String.format("Converted value and type are"
+ + " %10s (%10s)", "'" + result + "'",
+ result.getClass().getSimpleName());
} else {
- resultStr = String.format("%10s", result);
+ resultStr = String.format("Converted value is %10s", result);
}
System.out.println(resultStr);
}
-
if (failureExpected) {
- String msg = String.format("No exception thrown: %s => %s; parameter: %s", from, to, param);
+ String msg = String.format("No exception thrown while testing"
+ + " return value conversion: %10s => %10s;"
+ + " parameter: %10s",
+ from, to, param);
throw new AssertionError(msg);
}
} catch (AssertionError e) {
throw e; // report test failure
} catch (Throwable e) {
- if (VERBOSE) System.out.printf("%s: %s\n", e.getClass(), e.getMessage());
- if (!failureExpected) {
- String msg = String.format("Unexpected exception was thrown: %s => %s; parameter: %s", from, to, param);
+ if (VERBOSE) {
+ System.out.printf("%s: %s\n", e.getClass(), e.getMessage());
+ }
+ if (!failureExpected || !e.getClass().equals(expectedException)) {
+ String msg = String.format("Unexpected exception was thrown"
+ + " while testing return value conversion:"
+ + " %s => %s; parameter: %s", from, to, param);
throw new AssertionError(msg, e);
}
}
--- a/jdk/test/java/lang/invoke/LFCaching/TestMethods.java Thu Aug 20 12:29:58 2015 -0700
+++ b/jdk/test/java/lang/invoke/LFCaching/TestMethods.java Wed Jul 05 20:46:25 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -207,7 +207,7 @@
return MethodHandles.filterReturnValue(target, filter);
}
},
- INSERT_ARGUMENTS("insertArguments") {
+ INSERT_ARGUMENTS("insertArguments", Helper.MAX_ARITY - 3) {
@Override
public Map<String, Object> getTestCaseData() {
Map<String, Object> data = new HashMap<>();
@@ -610,26 +610,7 @@
* @return MethodType generated randomly.
*/
private static MethodType randomMethodTypeGenerator(int arity) {
- final Class<?>[] CLASSES = {
- Object.class,
- int.class,
- boolean.class,
- byte.class,
- short.class,
- char.class,
- long.class,
- float.class,
- double.class
- };
- if (arity > Helper.MAX_ARITY) {
- throw new IllegalArgumentException(
- String.format("Arity should not exceed %d!", Helper.MAX_ARITY));
- }
- List<Class<?>> list = Helper.randomClasses(CLASSES, arity);
- list = Helper.getParams(list, false, arity);
- int i = Helper.RNG.nextInt(CLASSES.length + 1);
- Class<?> rtype = i == CLASSES.length ? void.class : CLASSES[i];
- return MethodType.methodType(rtype, list);
+ return Helper.randomMethodTypeGenerator(arity);
}
/**
--- a/jdk/test/java/lang/ref/ReferenceEnqueue.java Thu Aug 20 12:29:58 2015 -0700
+++ b/jdk/test/java/lang/ref/ReferenceEnqueue.java Wed Jul 05 20:46:25 2017 +0200
@@ -22,7 +22,7 @@
*/
/* @test
- * @bug 4268317
+ * @bug 4268317 8132306
* @summary Test if Reference.enqueue() works properly with GC
*/
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/Formatter/NullArg.java Wed Jul 05 20:46:25 2017 +0200
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @bug 8039390
+ * @summary Basic test for null argument
+ */
+
+import java.util.Formatter;
+import java.util.Locale;
+
+public class NullArg {
+
+ public static void main(String [] args) {
+ char[] cs = new char[] {
+ 'b', 'B', 'h', 'H', 's', 'S', 'c', 'C', 'd', 'o', 'x', 'X',
+ 'e', 'E', 'f', 'g', 'G', 'a', 'A', 't', 'T',
+ };
+ char[] tcs = new char[] {
+ 'H', 'I', 'k', 'l', 'l', 'M', 'S', 'L', 'N', 'p', 'z', 'Z', 's',
+ 'Q', 'B', 'b', 'h', 'A', 'a', 'C', 'Y', 'y', 'j', 'm', 'd', 'e',
+ 'R', 'T', 'r', 'D', 'F', 'c'
+ };
+ for (char c : cs) {
+ String expected = (c == 'b' || c == 'B') ? "false" : "null";
+ if (Character.isUpperCase(c)) {
+ expected = expected.toUpperCase(Locale.ROOT);
+ }
+ if (c == 't' || c == 'T') {
+ for (char ct : tcs) {
+ if (!String.format("%" + c + ct, null).equals(expected)) {
+ throw new RuntimeException("%t" + ct + "null check failed.");
+ }
+ }
+ } else {
+ if (!String.format("%" + c , null).equals(expected)) {
+ throw new RuntimeException("%" + c + "null check failed.");
+ }
+ }
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/security/auth/login/LoginContext/LCTest.jaas.config Wed Jul 05 20:46:25 2017 +0200
@@ -0,0 +1,57 @@
+
+"AbortRequired" {
+ LCTest$LoginModuleAllPass required;
+ LCTest$LoginModuleWithLoginException required;
+ LCTest$LoginModuleAllPass required;
+};
+
+"AbortRequisite" {
+ LCTest$LoginModuleWithLoginException required;
+ LCTest$LoginModuleWithAbortException requisite;
+ LCTest$LoginModuleAllPass required;
+};
+
+"AbortSufficient" {
+ LCTest$LoginModuleWithLoginException required;
+ LCTest$LoginModuleWithLoginException sufficient;
+ LCTest$LoginModuleAllPass required;
+};
+
+"LogoutRequisite" {
+ LCTest$LoginModuleAllPass required;
+ LCTest$LoginModuleWithLogoutException requisite;
+ LCTest$LoginModuleAllPass required;
+};
+
+"LogoutSufficient" {
+ LCTest$LoginModuleAllPass required;
+ LCTest$LoginModuleWithLoginException sufficient;
+ LCTest$LoginModuleAllPass required;
+};
+
+"LogoutRequired" {
+ LCTest$LoginModuleWithLogoutException required;
+ LCTest$LoginModuleWithAbortException required;
+ LCTest$LoginModuleAllPass required;
+};
+
+"LoginRequired" {
+ LCTest$LoginModuleWithLoginException required;
+ LCTest$LoginModuleWithAbortException required;
+ LCTest$LoginModuleAllPass required;
+};
+
+"LoginSufficient" {
+ LCTest$LoginModuleAllPass required;
+ LCTest$LoginModuleWithLoginException sufficient;
+ LCTest$LoginModuleAllPass required;
+};
+
+"LoginRequisite" {
+ LCTest$LoginModuleWithLoginException required;
+ LCTest$LoginModuleWithAbortException requisite;
+ LCTest$LoginModuleAllPass required;
+};
+
+"EmptyModuleConfig" {
+};
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/security/auth/login/LoginContext/LCTest.java Wed Jul 05 20:46:25 2017 +0200
@@ -0,0 +1,337 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import com.sun.security.auth.UnixPrincipal;
+
+import javax.security.auth.Subject;
+import javax.security.auth.callback.*;
+import javax.security.auth.login.FailedLoginException;
+import javax.security.auth.login.LoginContext;
+import javax.security.auth.login.LoginException;
+import javax.security.auth.spi.LoginModule;
+import java.io.IOException;
+import java.security.Principal;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+/*
+ * @test
+ * @bug 8050460
+ * @summary Test checks that proper methods associated with login/logout process
+ * of LoginContext are called for different configurations and circumstances.
+ * @modules jdk.security.auth
+ *
+ * @run main/othervm LCTest EmptyModuleConfig false
+ * @run main/othervm LCTest IncorrectName false
+ * @run main/othervm LCTest AbortRequisite false abort
+ * @run main/othervm LCTest AbortSufficient false abort
+ * @run main/othervm LCTest AbortRequired false abort
+ * @run main/othervm LCTest LogoutRequisite false logout
+ * @run main/othervm LCTest LogoutSufficient true logout
+ * @run main/othervm LCTest LogoutRequired false logout
+ * @run main/othervm LCTest LoginRequisite false login
+ * @run main/othervm LCTest LoginSufficient true login
+ * @run main/othervm LCTest LoginRequired false login
+ */
+
+public class LCTest {
+
+ private static final String USER_NAME = "testUser";
+ private static final String PASSWORD = "testPassword";
+ private static final List<String> loggedActions = new ArrayList<>();
+
+ static {
+ System.setProperty("java.security.auth.login.config",
+ System.getProperty("test.src")
+ + System.getProperty("file.separator")
+ + "LCTest.jaas.config");
+ }
+
+ public static void main(String[] args) {
+ if (args.length < 2) {
+ throw new RuntimeException("Incorrect test params");
+ }
+ String nameOfContext = args[0];
+ boolean isPositive = Boolean.parseBoolean(args[1]);
+ String actionName = null;
+ if (args.length == 3) {
+ actionName = args[2];
+ }
+ try {
+ LoginContext lc = new LoginContext(nameOfContext,
+ new MyCallbackHandler());
+ lc.login();
+ checkPrincipal(lc, true);
+ lc.logout();
+ checkPrincipal(lc, false);
+ if (!isPositive) {
+ throw new RuntimeException("Test failed. Exception expected.");
+ }
+ } catch (LoginException le) {
+ if (isPositive) {
+ throw new RuntimeException("Test failed. Unexpected " +
+ "exception", le);
+ }
+ System.out.println("Expected exception: "
+ + le.getMessage());
+ }
+ checkActions(actionName);
+ System.out.println("Test passed.");
+ }
+
+ /*
+ * Log action from login modules
+ */
+ private static void logAction(String actionName) {
+ loggedActions.add(actionName);
+ }
+
+ /*
+ * Check if logged actions are as expected. We always expected 3 actions
+ * if any.
+ */
+ private static void checkActions(String actionName) {
+ if (actionName == null) {
+ if (loggedActions.size() != 0) {
+ throw new RuntimeException("No logged actions expected");
+ }
+ } else {
+ int loggedActionsFound = 0;
+ System.out.println("Logged actions : " + loggedActions);
+ for (String s : loggedActions) {
+ if (s.equals(actionName)) {
+ loggedActionsFound++;
+ }
+ }
+ if (loggedActionsFound != 3) {
+ throw new RuntimeException("Incorrect number of actions " +
+ actionName + " : " + loggedActionsFound);
+ }
+ }
+ }
+
+ /*
+ * Check context for principal of the test user.
+ */
+ private static void checkPrincipal(LoginContext loginContext, boolean
+ principalShouldExist) {
+ if (!principalShouldExist) {
+ if (loginContext.getSubject().getPrincipals().size() != 0) {
+ throw new RuntimeException("Test failed. Principal was not " +
+ "cleared.");
+ }
+ } else {
+ for (Principal p : loginContext.getSubject().getPrincipals()) {
+ if (p instanceof UnixPrincipal &&
+ USER_NAME.equals(p.getName())) {
+ //Proper principal was found, return.
+ return;
+ }
+ }
+ throw new RuntimeException("Test failed. UnixPrincipal "
+ + USER_NAME + " expected.");
+ }
+ }
+
+ private static class MyCallbackHandler implements CallbackHandler {
+
+ @Override
+ public void handle(Callback[] callbacks) throws IOException,
+ UnsupportedCallbackException {
+ for (Callback callback : callbacks) {
+ if (callback instanceof NameCallback) {
+ ((NameCallback) callback).setName(USER_NAME);
+ } else if (callback instanceof PasswordCallback) {
+ ((PasswordCallback) callback).setPassword(
+ PASSWORD.toCharArray());
+ } else {
+ throw new UnsupportedCallbackException(callback);
+ }
+ }
+ }
+ }
+
+ /* -------------------------------------------------------------------------
+ * Test login modules
+ * -------------------------------------------------------------------------
+ */
+
+ /*
+ * Login module that should pass through all phases.
+ */
+ public static class LoginModuleAllPass extends LoginModuleBase {
+
+ }
+
+ /*
+ * Login module that throws Exception in abort method.
+ */
+ public static class LoginModuleWithAbortException extends LoginModuleBase {
+
+ @Override
+ public boolean abort() throws LoginException {
+ super.abort();
+ throw new LoginException("Abort failed!");
+ }
+ }
+
+ /*
+ * Login module that throws Exception in login method.
+ */
+ public static class LoginModuleWithLoginException extends LoginModuleBase {
+
+ @Override
+ public boolean login() throws LoginException {
+ super.login();
+ throw new FailedLoginException("Login failed!");
+ }
+ }
+
+ /*
+ * Login module that throws Exception in logout method.
+ */
+ public static class LoginModuleWithLogoutException extends LoginModuleBase {
+
+ @Override
+ public boolean logout() throws LoginException {
+ super.logout();
+ throw new FailedLoginException("Logout failed!");
+ }
+ }
+
+ /*
+ * Base class for login modules
+ */
+ public static abstract class LoginModuleBase implements LoginModule {
+ // initial state
+ private Subject subject;
+ private CallbackHandler callbackHandler;
+ private Map sharedState;
+ private Map options;
+ private UnixPrincipal userPrincipal;
+
+ // username and password
+ private String username;
+ private String password;
+
+ // the authentication status
+ private boolean succeeded = false;
+ private boolean commitSucceeded = false;
+
+ @Override
+ public void initialize(Subject subject, CallbackHandler callbackHandler,
+ Map<String, ?> sharedState, Map<String, ?> options) {
+
+ this.subject = subject;
+ this.callbackHandler = callbackHandler;
+ this.sharedState = sharedState;
+ this.options = options;
+ System.out.println("Login module initialized.");
+ }
+
+ /*
+ * Authenticate the user by prompting for a username and password.
+ */
+ @Override
+ public boolean login() throws LoginException {
+ LCTest.logAction("login");
+ if (callbackHandler == null) {
+ throw new LoginException("No CallbackHandler available");
+ }
+
+ Callback[] callbacks = new Callback[2];
+ callbacks[0] = new NameCallback("Username: ");
+ callbacks[1] = new PasswordCallback("Password: ", false);
+
+ try {
+ callbackHandler.handle(callbacks);
+ username = ((NameCallback) callbacks[0]).getName();
+ password = new String(((PasswordCallback) callbacks[1])
+ .getPassword());
+ if (username.equals(LCTest.USER_NAME) &&
+ password.equals(LCTest.PASSWORD)) {
+ succeeded = true;
+ return true;
+ }
+ throw new FailedLoginException("Incorrect username/password!");
+ } catch (IOException | UnsupportedCallbackException e) {
+ throw new LoginException("Login failed: " + e.getMessage());
+ }
+ }
+
+ @Override
+ public boolean commit() throws LoginException {
+ LCTest.logAction("commit");
+ if (succeeded == false) {
+ return false;
+ }
+ userPrincipal = new UnixPrincipal(username);
+ final Subject s = subject;
+ final UnixPrincipal up = userPrincipal;
+ java.security.AccessController.doPrivileged
+ ((java.security.PrivilegedAction) () -> {
+ if (!s.getPrincipals().contains(up)) {
+ s.getPrincipals().add(up);
+ }
+ return null;
+ });
+ password = null;
+ commitSucceeded = true;
+ return true;
+ }
+
+ @Override
+ public boolean abort() throws LoginException {
+ LCTest.logAction("abort");
+ if (succeeded == false) {
+ return false;
+ }
+ clearState();
+ return true;
+ }
+
+ @Override
+ public boolean logout() throws LoginException {
+ LCTest.logAction("logout");
+ clearState();
+ return true;
+ }
+
+ private void clearState() {
+ if (commitSucceeded) {
+ final Subject s = subject;
+ final UnixPrincipal up = userPrincipal;
+ java.security.AccessController.doPrivileged
+ ((java.security.PrivilegedAction) () -> {
+ s.getPrincipals().remove(up);
+ return null;
+ });
+ }
+ username = null;
+ password = null;
+ userPrincipal = null;
+ }
+ }
+
+}
--- a/jdk/test/jdk/internal/jimage/JImageTest.java Thu Aug 20 12:29:58 2015 -0700
+++ b/jdk/test/jdk/internal/jimage/JImageTest.java Wed Jul 05 20:46:25 2017 +0200
@@ -66,9 +66,10 @@
String bootimage = bootimagePath.toAbsolutePath().toString();
String extractDir = Paths.get(".", "extract").toAbsolutePath().toString();
String recreateImage = Paths.get(".", "recreate.jimage").toAbsolutePath().toString();
-
+ String relativeRecreateImage = Paths.get(".", "recreate2.jimage").toString();
jimage("extract", "--dir", extractDir, bootimage);
jimage("recreate", "--dir", extractDir, recreateImage);
+ jimage("recreate", "--dir", extractDir, relativeRecreateImage);
System.out.println("Test successful");
} else {
--- a/jdk/test/lib/testlibrary/jsr292/com/oracle/testlibrary/jsr292/Helper.java Thu Aug 20 12:29:58 2015 -0700
+++ b/jdk/test/lib/testlibrary/jsr292/com/oracle/testlibrary/jsr292/Helper.java Wed Jul 05 20:46:25 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -315,4 +315,33 @@
}
return null;
}
+
+ /**
+ * Routine used to obtain a randomly generated method type.
+ *
+ * @param arity Arity of returned method type.
+ * @return MethodType generated randomly.
+ */
+ public static MethodType randomMethodTypeGenerator(int arity) {
+ final Class<?>[] CLASSES = {
+ Object.class,
+ int.class,
+ boolean.class,
+ byte.class,
+ short.class,
+ char.class,
+ long.class,
+ float.class,
+ double.class
+ };
+ if (arity > MAX_ARITY) {
+ throw new IllegalArgumentException(
+ String.format("Arity should not exceed %d!", MAX_ARITY));
+ }
+ List<Class<?>> list = randomClasses(CLASSES, arity);
+ list = getParams(list, false, arity);
+ int i = RNG.nextInt(CLASSES.length + 1);
+ Class<?> rtype = i == CLASSES.length ? void.class : CLASSES[i];
+ return MethodType.methodType(rtype, list);
+ }
}
--- a/jdk/test/sun/tools/jhsdb/BasicLauncherTest.java Thu Aug 20 12:29:58 2015 -0700
+++ b/jdk/test/sun/tools/jhsdb/BasicLauncherTest.java Wed Jul 05 20:46:25 2017 +0200
@@ -42,6 +42,7 @@
import jdk.testlibrary.OutputAnalyzer;
import jdk.testlibrary.ProcessTools;
import jdk.test.lib.apps.LingeredApp;
+import jdk.testlibrary.Platform;
public class BasicLauncherTest {
@@ -131,10 +132,16 @@
public static void main(String[] args)
throws IOException {
+ if (!Platform.shouldSAAttach()) {
+ // Silently skip the test if we don't have enough permissions to attach
+ System.err.println("Error! Insufficient permissions to attach.");
+ return;
+ }
+
launchCLHSDB();
launch("No deadlocks found", "jstack");
- launch("Server compiler detected", "jmap");
+ launch("compiler detected", "jmap");
launch("Java System Properties", "jinfo");
// The test throws RuntimeException on error.
--- a/jdk/test/sun/util/calendar/zi/tzdata/VERSION Thu Aug 20 12:29:58 2015 -0700
+++ b/jdk/test/sun/util/calendar/zi/tzdata/VERSION Wed Jul 05 20:46:25 2017 +0200
@@ -21,4 +21,4 @@
# or visit www.oracle.com if you need additional information or have any
# questions.
#
-tzdata2015e
+tzdata2015f
--- a/jdk/test/sun/util/calendar/zi/tzdata/africa Thu Aug 20 12:29:58 2015 -0700
+++ b/jdk/test/sun/util/calendar/zi/tzdata/africa Wed Jul 05 20:46:25 2017 +0200
@@ -561,7 +561,7 @@
# From Alex Krivenyshev (2008-07-11):
# Seems that English language article "The revival of daylight saving
-# time: Energy conservation?"-# No. 16578 (07/11/2008) was originally
+# time: Energy conservation?"- No. 16578 (07/11/2008) was originally
# published on Monday, June 30, 2008...
#
# I guess that article in French "Le gouvernement avance l'introduction
@@ -693,7 +693,7 @@
# Here is a link to official document from Royaume du Maroc Premier Ministre,
# Ministère de la Modernisation des Secteurs Publics
#
-# Under Article 1 of Royal Decree No. 455-67 of Act 23 safar 1387 (2 june 1967)
+# Under Article 1 of Royal Decree No. 455-67 of Act 23 safar 1387 (2 June 1967)
# concerning the amendment of the legal time, the Ministry of Modernization of
# Public Sectors announced that the official time in the Kingdom will be
# advanced 60 minutes from Sunday 31 May 2009 at midnight.
--- a/jdk/test/sun/util/calendar/zi/tzdata/asia Thu Aug 20 12:29:58 2015 -0700
+++ b/jdk/test/sun/util/calendar/zi/tzdata/asia Wed Jul 05 20:46:25 2017 +0200
@@ -29,7 +29,7 @@
# tz@iana.org for general use in the future). For more, please see
# the file CONTRIBUTING in the tz distribution.
-# From Paul Eggert (2014-10-31):
+# From Paul Eggert (2015-08-08):
#
# Unless otherwise specified, the source for data through 1990 is:
# Thomas G. Shanks and Rique Pottenger, The International Atlas (6th edition),
@@ -66,7 +66,7 @@
# 2:00 EET EEST Eastern European Time
# 2:00 IST IDT Israel
# 3:00 AST ADT Arabia*
-# 3:30 IRST IRDT Iran
+# 3:30 IRST IRDT Iran*
# 4:00 GST Gulf*
# 5:30 IST India
# 7:00 ICT Indochina, most times and locations*
@@ -75,10 +75,11 @@
# 8:00 CST China
# 8:00 IDT Indochina, 1943-45, 1947-55, 1960-75 (some locations)*
# 8:00 JWST Western Standard Time (Japan, 1896/1937)*
+# 8:30 KST KDT Korea when at +0830*
# 9:00 JCST Central Standard Time (Japan, 1896/1937)
# 9:00 WIT east Indonesia (Waktu Indonesia Timur)
# 9:00 JST JDT Japan
-# 9:00 KST KDT Korea
+# 9:00 KST KDT Korea when at +09
# 9:30 ACST Australian Central Standard Time
#
# See the 'europe' file for Russia and Turkey in Asia.
@@ -1050,7 +1051,7 @@
#
# From Roozbeh Pournader (2007-11-05):
# This is quoted from Official Gazette of the Islamic Republic of
-# Iran, Volume 63, Number 18242, dated Tuesday 1386/6/24
+# Iran, Volume 63, No. 18242, dated Tuesday 1386/6/24
# [2007-10-16]. I am doing the best translation I can:...
# The official time of the country will be moved forward for one hour
# on the 24 hours of the first day of the month of Farvardin and will
@@ -1580,7 +1581,7 @@
# - Qyzylorda switched from +5:00 to +6:00 on 1992-01-19 02:00.
# - Oral switched from +5:00 to +4:00 in spring 1989.
-# From Kazakhstan Embassy's News Bulletin #11
+# From Kazakhstan Embassy's News Bulletin No. 11
# <http://www.kazsociety.org.uk/news/2005/03/30.htm> (2005-03-21):
# The Government of Kazakhstan passed a resolution March 15 abolishing
# daylight saving time citing lack of economic benefits and health
@@ -1734,6 +1735,17 @@
#
# For Pyongyang we have no information; guess no changes since World War II.
+# From Steffen Thorsen (2015-08-07):
+# According to many news sources, North Korea is going to change to
+# the 8:30 time zone on August 15, one example:
+# http://www.bbc.com/news/world-asia-33815049
+#
+# From Paul Eggert (2015-08-07):
+# No transition time is specified; assume 00:00.
+# There is no common English-language abbreviation for this time zone.
+# Use %z rather than invent one. We can't assume %z works everywhere yet,
+# so for now substitute its output manually.
+
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
Zone Asia/Seoul 8:27:52 - LMT 1908 Apr 1
8:30 - KST 1912 Jan 1
@@ -1746,7 +1758,8 @@
8:30 - KST 1912 Jan 1
9:00 - JCST 1937 Oct 1
9:00 - JST 1945 Aug 24
- 9:00 - KST
+ 9:00 - KST 2015 Aug 15
+ 8:30 - KST
###############################################################################
--- a/jdk/test/sun/util/calendar/zi/tzdata/europe Thu Aug 20 12:29:58 2015 -0700
+++ b/jdk/test/sun/util/calendar/zi/tzdata/europe Wed Jul 05 20:46:25 2017 +0200
@@ -216,11 +216,14 @@
# republished in Finest Hour (Spring 2002) 1(114):26
# http://www.winstonchurchill.org/images/finesthour/Vol.01%20No.114.pdf
-# From Paul Eggert (1996-09-03):
+# From Paul Eggert (2015-08-08):
# The OED Supplement says that the English originally said "Daylight Saving"
# when they were debating the adoption of DST in 1908; but by 1916 this
# term appears only in quotes taken from DST's opponents, whereas the
# proponents (who eventually won the argument) are quoted as using "Summer".
+# The term "Summer Time" was introduced by Herbert Samuel, Home Secretary; see:
+# Viscount Samuel. Leisure in a Democracy. Cambridge University Press
+# ISBN 978-1-107-49471-8 (1949, reissued 2015), p 8.
# From Arthur David Olson (1989-01-19):
# A source at the British Information Office in New York avers that it's
@@ -366,7 +369,7 @@
# From an anonymous contributor (1996-06-02):
# The law governing time in Ireland is under Statutory Instrument SI 395/94,
-# which gives force to European Union 7th Council Directive # 94/21/EC.
+# which gives force to European Union 7th Council Directive No. 94/21/EC.
# Under this directive, the Minister for Justice in Ireland makes appropriate
# regulations. I spoke this morning with the Secretary of the Department of
# Justice (tel +353 1 678 9711) who confirmed to me that the correct name is
@@ -615,11 +618,11 @@
Rule Russia 1921 only - Mar 20 23:00 2:00 MSM # Midsummer
Rule Russia 1921 only - Sep 1 0:00 1:00 MSD
Rule Russia 1921 only - Oct 1 0:00 0 -
-# Act No.925 of the Council of Ministers of the USSR (1980-10-24):
+# Act No. 925 of the Council of Ministers of the USSR (1980-10-24):
Rule Russia 1981 1984 - Apr 1 0:00 1:00 S
Rule Russia 1981 1983 - Oct 1 0:00 0 -
-# Act No.967 of the Council of Ministers of the USSR (1984-09-13), repeated in
-# Act No.227 of the Council of Ministers of the USSR (1989-03-14):
+# Act No. 967 of the Council of Ministers of the USSR (1984-09-13), repeated in
+# Act No. 227 of the Council of Ministers of the USSR (1989-03-14):
Rule Russia 1984 1991 - Sep lastSun 2:00s 0 -
Rule Russia 1985 1991 - Mar lastSun 2:00s 1:00 S
#
@@ -851,7 +854,7 @@
# Bulgaria
#
# From Plamen Simenov via Steffen Thorsen (1999-09-09):
-# A document of Government of Bulgaria (No.94/1997) says:
+# A document of Government of Bulgaria (No. 94/1997) says:
# EET -> EETDST is in 03:00 Local time in last Sunday of March ...
# EETDST -> EET is in 04:00 Local time in last Sunday of October
#
@@ -868,7 +871,7 @@
1:00 C-Eur CE%sT 1945
1:00 - CET 1945 Apr 2 3:00
2:00 - EET 1979 Mar 31 23:00
- 2:00 Bulg EE%sT 1982 Sep 26 2:00
+ 2:00 Bulg EE%sT 1982 Sep 26 3:00
2:00 C-Eur EE%sT 1991
2:00 E-Eur EE%sT 1997
2:00 EU EE%sT
@@ -1085,8 +1088,8 @@
# after that.
# From Mart Oruaas (2000-01-29):
-# Regulation no. 301 (1999-10-12) obsoletes previous regulation
-# no. 206 (1998-09-22) and thus sticks Estonia to +02:00 GMT for all
+# Regulation No. 301 (1999-10-12) obsoletes previous regulation
+# No. 206 (1998-09-22) and thus sticks Estonia to +02:00 GMT for all
# the year round. The regulation is effective 1999-11-01.
# From Toomas Soome (2002-02-21):
@@ -1107,7 +1110,7 @@
3:00 Russia MSK/MSD 1989 Mar 26 2:00s
2:00 1:00 EEST 1989 Sep 24 2:00s
2:00 C-Eur EE%sT 1998 Sep 22
- 2:00 EU EE%sT 1999 Nov 1
+ 2:00 EU EE%sT 1999 Oct 31 4:00
2:00 - EET 2002 Feb 21
2:00 EU EE%sT
@@ -1550,21 +1553,21 @@
# correct data in juridical acts and I found some juridical documents about
# changes in the counting of time in Latvia from 1981....
#
-# Act No.35 of the Council of Ministers of Latvian SSR of 1981-01-22 ...
-# according to the Act No.925 of the Council of Ministers of USSR of 1980-10-24
+# Act No. 35 of the Council of Ministers of Latvian SSR of 1981-01-22 ...
+# according to the Act No. 925 of the Council of Ministers of USSR of 1980-10-24
# ...: all year round the time of 2nd time zone + 1 hour, in addition turning
# the hands of the clock 1 hour forward on 1 April at 00:00 (GMT 31 March 21:00)
# and 1 hour backward on the 1 October at 00:00 (GMT 30 September 20:00).
#
-# Act No.592 of the Council of Ministers of Latvian SSR of 1984-09-24 ...
-# according to the Act No.967 of the Council of Ministers of USSR of 1984-09-13
+# Act No. 592 of the Council of Ministers of Latvian SSR of 1984-09-24 ...
+# according to the Act No. 967 of the Council of Ministers of USSR of 1984-09-13
# ...: all year round the time of 2nd time zone + 1 hour, in addition turning
# the hands of the clock 1 hour forward on the last Sunday of March at 02:00
# (GMT 23:00 on the previous day) and 1 hour backward on the last Sunday of
# September at 03:00 (GMT 23:00 on the previous day).
#
-# Act No.81 of the Council of Ministers of Latvian SSR of 1989-03-22 ...
-# according to the Act No.227 of the Council of Ministers of USSR of 1989-03-14
+# Act No. 81 of the Council of Ministers of Latvian SSR of 1989-03-22 ...
+# according to the Act No. 227 of the Council of Ministers of USSR of 1989-03-14
# ...: since the last Sunday of March 1989 in Lithuanian SSR, Latvian SSR,
# Estonian SSR and Kaliningrad region of Russian Federation all year round the
# time of 2nd time zone (Moscow time minus one hour). On the territory of Latvia
@@ -1581,7 +1584,7 @@
# From Andrei Ivanov (2000-03-06):
# This year Latvia will not switch to Daylight Savings Time (as specified in
# The Regulations of the Cabinet of Ministers of the Rep. of Latvia of
-# 29-Feb-2000 (#79) <http://www.lv-laiks.lv/wwwraksti/2000/071072/vd4.htm>,
+# 29-Feb-2000 (No. 79) <http://www.lv-laiks.lv/wwwraksti/2000/071072/vd4.htm>,
# in Latvian for subscribers only).
# From RFE/RL Newsline
@@ -1786,6 +1789,18 @@
# News from Moldova (in russian):
# http://ru.publika.md/link_317061.html
+# From Roman Tudos (2015-07-02):
+# http://lex.justice.md/index.php?action=view&view=doc&lang=1&id=355077
+# From Paul Eggert (2015-07-01):
+# The abovementioned official link to IGO1445-868/2014 states that
+# 2014-10-26's fallback transition occurred at 03:00 local time. Also,
+# http://www.trm.md/en/social/la-30-martie-vom-trece-la-ora-de-vara
+# says the 2014-03-30 spring-forward transition was at 02:00 local time.
+# Guess that since 1997 Moldova has switched one hour before the EU.
+
+# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
+Rule Moldova 1997 max - Mar lastSun 2:00 1:00 S
+Rule Moldova 1997 max - Oct lastSun 3:00 0 -
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
Zone Europe/Chisinau 1:55:20 - LMT 1880
@@ -1800,7 +1815,7 @@
2:00 Russia EE%sT 1992
2:00 E-Eur EE%sT 1997
# See Romania commentary for the guessed 1997 transition to EU rules.
- 2:00 EU EE%sT
+ 2:00 Moldova EE%sT
# Monaco
# Shanks & Pottenger give 0:09:20 for Paris Mean Time; go with Howse's
@@ -2146,7 +2161,7 @@
# Russia
# From Alexander Krivenyshev (2011-09-15):
-# Based on last Russian Government Decree # 725 on August 31, 2011
+# Based on last Russian Government Decree No. 725 on August 31, 2011
# (Government document
# http://www.government.ru/gov/results/16355/print/
# in Russian)
@@ -2156,7 +2171,7 @@
# http://www.worldtimezone.com/dst_news/dst_news_russia36.htm
# From Sanjeev Gupta (2011-09-27):
-# Scans of [Decree #23 of January 8, 1992] are available at:
+# Scans of [Decree No. 23 of January 8, 1992] are available at:
# http://government.consultant.ru/page.aspx?1223966
# They are in Cyrillic letters (presumably Russian).
@@ -2167,19 +2182,19 @@
# One source is
# http://government.ru/gov/results/16355/
# which, according to translate.google.com, begins "Decree of August 31,
-# 2011 No 725" and contains no other dates or "effective date" information.
+# 2011 No. 725" and contains no other dates or "effective date" information.
#
# Another source is
# http://www.rg.ru/2011/09/06/chas-zona-dok.html
# which, according to translate.google.com, begins "Resolution of the
# Government of the Russian Federation on August 31, 2011 N 725" and also
# contains "Date first official publication: September 6, 2011 Posted on:
-# in the 'RG' - Federal Issue number 5573 September 6, 2011" but which
+# in the 'RG' - Federal Issue No. 5573 September 6, 2011" but which
# does not contain any "effective date" information.
#
# Another source is
# http://en.wikipedia.org/wiki/Oymyakonsky_District#cite_note-RuTime-7
-# which, in note 8, contains "Resolution #725 of August 31, 2011...
+# which, in note 8, contains "Resolution No. 725 of August 31, 2011...
# Effective as of after 7 days following the day of the official publication"
# but which does not contain any reference to September 6, 2011.
#
@@ -2387,7 +2402,7 @@
# changed in May.
2:00 E-Eur EE%sT 1994 May
# From IATA SSIM (1994/1997), which also says that Kerch is still like Kiev.
- 3:00 E-Eur MSK/MSD 1996 Mar 31 3:00s
+ 3:00 E-Eur MSK/MSD 1996 Mar 31 0:00s
3:00 1:00 MSD 1996 Oct 27 3:00s
# IATA SSIM (1997-09) says Crimea switched to EET/EEST.
# Assume it happened in March by not changing the clocks.
@@ -2522,7 +2537,7 @@
# from current Russia Zone 6 - Krasnoyarsk Time Zone (KRA) UTC +0700
# to Russia Zone 5 - Novosibirsk Time Zone (NOV) UTC +0600
#
-# This is according to Government of Russia decree # 740, on September
+# This is according to Government of Russia decree No. 740, on September
# 14, 2009 "Application in the territory of the Kemerovo region the Fifth
# time zone." ("Russia Zone 5" or old "USSR Zone 5" is GMT +0600)
#
@@ -2945,7 +2960,7 @@
Zone Atlantic/Canary -1:01:36 - LMT 1922 Mar # Las Palmas de Gran C.
-1:00 - CANT 1946 Sep 30 1:00 # Canaries T
0:00 - WET 1980 Apr 6 0:00s
- 0:00 1:00 WEST 1980 Sep 28 0:00s
+ 0:00 1:00 WEST 1980 Sep 28 1:00u
0:00 EU WE%sT
# IATA SSIM (1996-09) says the Canaries switch at 2:00u, not 1:00u.
# Ignore this for now, as the Canaries are part of the EU.
@@ -3235,7 +3250,7 @@
# From Igor Karpov, who works for the Ukrainian Ministry of Justice,
# via Garrett Wollman (2003-01-27):
# BTW, I've found the official document on this matter. It's government
-# regulations number 509, May 13, 1996. In my poor translation it says:
+# regulations No. 509, May 13, 1996. In my poor translation it says:
# "Time in Ukraine is set to second timezone (Kiev time). Each last Sunday
# of March at 3am the time is changing to 4am and each last Sunday of
# October the time at 4am is changing to 3am"
@@ -3244,7 +3259,7 @@
# On September 20, 2011 the deputies of the Verkhovna Rada agreed to
# abolish the transfer clock to winter time.
#
-# Bill number 8330 of MP from the Party of Regions Oleg Nadoshi got
+# Bill No. 8330 of MP from the Party of Regions Oleg Nadoshi got
# approval from 266 deputies.
#
# Ukraine abolishes transfer back to the winter time (in Russian)
--- a/jdk/test/sun/util/calendar/zi/tzdata/leapseconds Thu Aug 20 12:29:58 2015 -0700
+++ b/jdk/test/sun/util/calendar/zi/tzdata/leapseconds Wed Jul 05 20:46:25 2017 +0200
@@ -79,5 +79,5 @@
Leap 2012 Jun 30 23:59:60 + S
Leap 2015 Jun 30 23:59:60 + S
-# Updated through IERS Bulletin C49
-# File expires on: 28 December 2015
+# Updated through IERS Bulletin C50
+# File expires on: 28 June 2016
--- a/jdk/test/sun/util/calendar/zi/tzdata/northamerica Thu Aug 20 12:29:58 2015 -0700
+++ b/jdk/test/sun/util/calendar/zi/tzdata/northamerica Wed Jul 05 20:46:25 2017 +0200
@@ -1258,10 +1258,19 @@
# west Labrador, Nova Scotia, Prince Edward I
-# From Paul Eggert (2006-03-22):
+# From Brian Inglis (2015-07-20):
+# From the historical weather station records available at:
+# https://weatherspark.com/history/28351/1971/Sydney-Nova-Scotia-Canada
+# Sydney shares the same time history as Glace Bay, so was
+# likely to be the same across the island....
+# Sydney, as the capital and most populous location, or Cape Breton, would
+# have been better names for the zone had we known this in 1996.
+
+# From Paul Eggert (2015-07-20):
# Shanks & Pottenger write that since 1970 most of this region has been like
# Halifax. Many locales did not observe peacetime DST until 1972;
-# Glace Bay, NS is the largest that we know of.
+# the Cape Breton area, represented by Glace Bay, is the largest we know of
+# (Glace Bay was perhaps not the best name choice but no point changing now).
# Shanks & Pottenger also write that Liverpool, NS was the only town
# in Canada to observe DST in 1971 but not 1970; for now we'll assume
# this is a typo.
@@ -1819,13 +1828,13 @@
# Exact date in October unknown; Sunday October 1 is a reasonable guess.
# 3. June 1918: switch to Pacific Daylight Time (GMT-7)
# Exact date in June unknown; Sunday June 2 is a reasonable guess.
-# note#1:
+# note 1:
# On Oct 27/1918 when daylight saving ended in the rest of Canada,
# Creston did not change its clocks.
-# note#2:
+# note 2:
# During WWII when the Federal Government legislated a mandatory clock change,
# Creston did not oblige.
-# note#3:
+# note 3:
# There is no guarantee that Creston will remain on Mountain Standard Time
# (UTC-7) forever.
# The subject was debated at least once this year by the town Council.
--- a/jdk/test/sun/util/calendar/zi/tzdata/southamerica Thu Aug 20 12:29:58 2015 -0700
+++ b/jdk/test/sun/util/calendar/zi/tzdata/southamerica Wed Jul 05 20:46:25 2017 +0200
@@ -154,7 +154,7 @@
# Timezone Law (which never was effectively applied) will (would?) be
# in effect.... The article is at
# http://ar.clarin.com/diario/2001-06-06/e-01701.htm
-# ... The Law itself is "Ley No 25155", sanctioned on 1999-08-25, enacted
+# ... The Law itself is "Ley No. 25155", sanctioned on 1999-08-25, enacted
# 1999-09-17, and published 1999-09-21. The official publication is at:
# http://www.boletin.jus.gov.ar/BON/Primera/1999/09-Septiembre/21/PDF/BO21-09-99LEG.PDF
# Regretfully, you have to subscribe (and pay) for the on-line version....
@@ -198,15 +198,11 @@
# http://www.worldtimezone.com/dst_news/dst_news_argentina03.html
# http://www.impulsobaires.com.ar/nota.php?id=57832 (in spanish)
-# From Rodrigo Severo (2008-10-06):
-# Here is some info available at a Gentoo bug related to TZ on Argentina's DST:
-# ...
-# ------- Comment #1 from [jmdocile] 2008-10-06 16:28 0000 -------
-# Hi, there is a problem with timezone-data-2008e and maybe with
-# timezone-data-2008f
-# Argentinian law [Number] 25.155 is no longer valid.
+# From Juan Manuel Docile in https://bugs.gentoo.org/240339 (2008-10-07)
+# via Rodrigo Severo:
+# Argentinian law No. 25.155 is no longer valid.
# http://www.infoleg.gov.ar/infolegInternet/anexos/60000-64999/60036/norma.htm
-# The new one is law [Number] 26.350
+# The new one is law No. 26.350
# http://www.infoleg.gov.ar/infolegInternet/anexos/135000-139999/136191/norma.htm
# So there is no summer time in Argentina for now.
@@ -794,7 +790,7 @@
# [ and in a second message (same day): ]
# I found the decree.
#
-# DECRETO No- 7.584, DE 13 DE OUTUBRO DE 2011
+# DECRETO No. 7.584, DE 13 DE OUTUBRO DE 2011
# Link :
# http://www.in.gov.br/visualiza/index.jsp?data=13/10/2011&jornal=1000&pagina=6&totalArquivos=6
@@ -1148,7 +1144,7 @@
# Conflicts between [1] and [2] were resolved as follows:
#
# - [1] says the 1910 transition was Jan 1, [2] says Jan 10 and cites
-# Boletín Nº 1, Aviso Nº 1 (1910). Go with [2].
+# Boletín No. 1, Aviso No. 1 (1910). Go with [2].
#
# - [1] says SMT was -4:42:45, [2] says Chile's official time from
# 1916 to 1919 was -4:42:46.3, the meridian of Chile's National
@@ -1156,7 +1152,7 @@
# Quinta Normal in Santiago. Go with [2], rounding it to -4:42:46.
#
# - [1] says the 1918 transition was Sep 1, [2] says Sep 10 and cites
-# Boletín Nº 22, Aviso Nº 129/1918 (1918-08-23). Go with [2].
+# Boletín No. 22, Aviso No. 129/1918 (1918-08-23). Go with [2].
#
# - [1] does not give times for transitions; assume they occur
# at midnight mainland time, the current common practice. However,
@@ -1556,7 +1552,7 @@
# (1999-09) reports no date; go with above sources and Gerd Knops (2001-02-27).
Rule Para 1998 2001 - Mar Sun>=1 0:00 0 -
# From Rives McDow (2002-02-28):
-# A decree was issued in Paraguay (no. 16350) on 2002-02-26 that changed the
+# A decree was issued in Paraguay (No. 16350) on 2002-02-26 that changed the
# dst method to be from the first Sunday in September to the first Sunday in
# April.
Rule Para 2002 2004 - Apr Sun>=1 0:00 0 -
@@ -1736,8 +1732,19 @@
Rule Uruguay 2006 only - Mar 12 2:00 0 -
# From Jesper Nørgaard Welen (2006-09-06):
# http://www.presidencia.gub.uy/_web/decretos/2006/09/CM%20210_08%2006%202006_00001.PDF
-Rule Uruguay 2006 max - Oct Sun>=1 2:00 1:00 S
-Rule Uruguay 2007 max - Mar Sun>=8 2:00 0 -
+#
+# From Steffen Thorsen (2015-06-30):
+# ... it looks like they will not be using DST the coming summer:
+# http://www.elobservador.com.uy/gobierno-resolvio-que-no-habra-cambio-horario-verano-n656787
+# http://www.republica.com.uy/este-ano-no-se-modificara-el-huso-horario-en-uruguay/523760/
+# From Paul Eggert (2015-06-30):
+# Apparently restaurateurs complained that DST caused people to go to the beach
+# instead of out to dinner.
+# From Pablo Camargo (2015-07-13):
+# http://archivo.presidencia.gub.uy/sci/decretos/2015/06/cons_min_201.pdf
+# [dated 2015-06-29; repeals Decree 311/006 dated 2006-09-04]
+Rule Uruguay 2006 2014 - Oct Sun>=1 2:00 1:00 S
+Rule Uruguay 2007 2015 - Mar Sun>=8 2:00 0 -
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
Zone America/Montevideo -3:44:44 - LMT 1898 Jun 28
-3:44:44 - MMT 1920 May 1 # Montevideo MT
@@ -1746,6 +1753,10 @@
# Venezuela
#
+# From Paul Eggert (2015-07-28):
+# For the 1965 transition see Gaceta Oficial No. 27.619 (1964-12-15), p 205.533
+# http://www.pgr.gob.ve/dmdocuments/1964/27619.pdf
+#
# From John Stainforth (2007-11-28):
# ... the change for Venezuela originally expected for 2007-12-31 has
# been brought forward to 2007-12-09. The official announcement was
@@ -1757,6 +1768,6 @@
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
Zone America/Caracas -4:27:44 - LMT 1890
-4:27:40 - CMT 1912 Feb 12 # Caracas Mean Time?
- -4:30 - VET 1965 # Venezuela Time
+ -4:30 - VET 1965 Jan 1 0:00 # Venezuela T.
-4:00 - VET 2007 Dec 9 3:00
-4:30 - VET
--- a/jdk/test/sun/util/calendar/zi/tzdata/zone.tab Thu Aug 20 12:29:58 2015 -0700
+++ b/jdk/test/sun/util/calendar/zi/tzdata/zone.tab Wed Jul 05 20:46:25 2017 +0200
@@ -129,8 +129,8 @@
BY +5354+02734 Europe/Minsk
BZ +1730-08812 America/Belize
CA +4734-05243 America/St_Johns Newfoundland Time, including SE Labrador
-CA +4439-06336 America/Halifax Atlantic Time - Nova Scotia (most places), PEI
-CA +4612-05957 America/Glace_Bay Atlantic Time - Nova Scotia - places that did not observe DST 1966-1971
+CA +4439-06336 America/Halifax Atlantic Time - Nova Scotia (peninsula), PEI
+CA +4612-05957 America/Glace_Bay Atlantic Time - Nova Scotia (Cape Breton)
CA +4606-06447 America/Moncton Atlantic Time - New Brunswick
CA +5320-06025 America/Goose_Bay Atlantic Time - Labrador - most locations
CA +5125-05707 America/Blanc-Sablon Atlantic Standard Time - Quebec - Lower North Shore
--- a/jdk/test/tools/pack200/CommandLineTests.java Thu Aug 20 12:29:58 2015 -0700
+++ b/jdk/test/tools/pack200/CommandLineTests.java Wed Jul 05 20:46:25 2017 +0200
@@ -110,7 +110,6 @@
ps.println("pack.pass.file.2=java/lang/Object.class");
ps.println("pack.pass.file.3=java/lang/Throwable.class");
ps.println("pack.pass.file.4=java/lang/VerifyError.class");
- ps.println("pack.pass.file.5=com/sun/demo/jvmti/hprof/Tracker.class");
} finally {
Utils.close(ps);
Utils.close(fos);
--- a/make/Images.gmk Thu Aug 20 12:29:58 2015 -0700
+++ b/make/Images.gmk Wed Jul 05 20:46:25 2017 +0200
@@ -47,7 +47,7 @@
# tools
TOOLS_MODULES += jdk.attach jdk.compiler jdk.dev jdk.internal.le jdk.scripting.nashorn.shell \
- jdk.javadoc jdk.jcmd jdk.jconsole jdk.hotspot.agent jdk.hprof.agent jdk.jartool \
+ jdk.javadoc jdk.jcmd jdk.jconsole jdk.hotspot.agent jdk.jartool \
jdk.jdeps jdk.jdi jdk.jdwp.agent jdk.policytool jdk.rmic jdk.xml.bind jdk.xml.ws
ifeq ($(OPENJDK_TARGET_OS), windows)
--- a/modules.xml Thu Aug 20 12:29:58 2015 -0700
+++ b/modules.xml Wed Jul 05 20:46:25 2017 +0200
@@ -1623,10 +1623,6 @@
<depend>jdk.jdi</depend>
</module>
<module>
- <name>jdk.hprof.agent</name>
- <depend>java.base</depend>
- </module>
- <module>
<name>jdk.httpserver</name>
<depend>java.base</depend>
<depend>java.logging</depend>
@@ -1798,7 +1794,7 @@
<name>jdk.scripting.nashorn</name>
<depend>java.base</depend>
<depend>java.logging</depend>
- <depend>java.scripting</depend>
+ <depend re-exports="true">java.scripting</depend>
<export>
<name>jdk.nashorn.internal.runtime</name>
<to>jdk.scripting.nashorn.shell</to>
@@ -1811,11 +1807,16 @@
<name>jdk.nashorn.tools</name>
<to>jdk.scripting.nashorn.shell</to>
</export>
+ <export>
+ <name>jdk.nashorn.api.scripting</name>
+ </export>
+ <export>
+ <name>jdk.nashorn.api.tree</name>
+ </export>
</module>
<module>
<name>jdk.scripting.nashorn.shell</name>
<depend>java.base</depend>
- <depend>java.prefs</depend>
<depend>jdk.scripting.nashorn</depend>
<depend>jdk.internal.le</depend>
</module>