diff --git a/src/share/vm/jfr/jni/jfrJniMethod.cpp b/src/share/vm/jfr/jni/jfrJniMethod.cpp index 30e5f5d590bce9af461ba9cb47fd935dfe222489..51447b7d0869368ba58029a13e0e79bb13d3e72f 100644 --- a/src/share/vm/jfr/jni/jfrJniMethod.cpp +++ b/src/share/vm/jfr/jni/jfrJniMethod.cpp @@ -229,6 +229,10 @@ JVM_ENTRY_NO_ENV(void, jfr_begin_recording(JNIEnv* env, jobject jvm)) JfrRecorder::start_recording(); JVM_END +JVM_ENTRY_NO_ENV(jboolean, jfr_is_recording(JNIEnv * env, jobject jvm)) + return JfrRecorder::is_recording() ? JNI_TRUE : JNI_FALSE; +JVM_END + JVM_ENTRY_NO_ENV(void, jfr_end_recording(JNIEnv* env, jobject jvm)) if (!JfrRecorder::is_recording()) { return; @@ -236,6 +240,9 @@ JVM_ENTRY_NO_ENV(void, jfr_end_recording(JNIEnv* env, jobject jvm)) JfrRecorder::stop_recording(); JVM_END +JVM_ENTRY_NO_ENV(void, jfr_mark_chunk_final(JNIEnv * env, jobject jvm)) + JfrRepository::mark_chunk_final(); +JVM_END JVM_ENTRY_NO_ENV(jboolean, jfr_emit_event(JNIEnv* env, jobject jvm, jlong eventTypeId, jlong timeStamp, jlong when)) JfrPeriodicEventSet::requestEvent((JfrEventId)eventTypeId); diff --git a/src/share/vm/jfr/jni/jfrJniMethod.hpp b/src/share/vm/jfr/jni/jfrJniMethod.hpp index a9a56ee2c8cff2854dff6ad1ab6dc923e220efc0..b987a4a1270ff3f7e8ad5edca231c1634d44ca93 100644 --- a/src/share/vm/jfr/jni/jfrJniMethod.hpp +++ b/src/share/vm/jfr/jni/jfrJniMethod.hpp @@ -49,8 +49,12 @@ jboolean JNICALL jfr_destroy_jfr(JNIEnv* env, jobject jvm); void JNICALL jfr_begin_recording(JNIEnv* env, jobject jvm); +jboolean JNICALL jfr_is_recording(JNIEnv* env, jobject jvm); + void JNICALL jfr_end_recording(JNIEnv* env, jobject jvm); +void JNICALL jfr_mark_chunk_final(JNIEnv* env, jobject jvm); + jboolean JNICALL jfr_emit_event(JNIEnv* env, jobject jvm, jlong eventTypeId, jlong timeStamp, jlong when); jobject JNICALL jfr_get_all_event_classes(JNIEnv* env, jobject jvm); diff --git a/src/share/vm/jfr/jni/jfrJniMethodRegistration.cpp b/src/share/vm/jfr/jni/jfrJniMethodRegistration.cpp index e8ce2480c0b42c6dc75319db20a08329d40b5954..2fb0a98b8d18aaf8fa1e77bccc8175137cfce6c0 100644 --- a/src/share/vm/jfr/jni/jfrJniMethodRegistration.cpp +++ b/src/share/vm/jfr/jni/jfrJniMethodRegistration.cpp @@ -36,7 +36,9 @@ JfrJniMethodRegistration::JfrJniMethodRegistration(JNIEnv* env) { if (jfr_clz != NULL) { JNINativeMethod method[] = { (char*)"beginRecording", (char*)"()V", (void*)jfr_begin_recording, + (char*)"isRecording", (char*)"()Z", (void*)jfr_is_recording, (char*)"endRecording", (char*)"()V", (void*)jfr_end_recording, + (char*)"markChunkFinal", (char*)"()V", (void*)jfr_mark_chunk_final, (char*)"counterTime", (char*)"()J", (void*)jfr_elapsed_counter, (char*)"createJFR", (char*)"(Z)Z", (void*)jfr_create_jfr, (char*)"destroyJFR", (char*)"()Z", (void*)jfr_destroy_jfr, diff --git a/src/share/vm/jfr/recorder/repository/jfrChunk.cpp b/src/share/vm/jfr/recorder/repository/jfrChunk.cpp index fddeaf9047149381a3dc322dc23873f868b9daa9..77594fa0a50fb7f079551f2cdf46fb55119f137a 100644 --- a/src/share/vm/jfr/recorder/repository/jfrChunk.cpp +++ b/src/share/vm/jfr/recorder/repository/jfrChunk.cpp @@ -59,7 +59,8 @@ JfrChunk::JfrChunk() : _last_update_nanos(0), _last_checkpoint_offset(0), _last_metadata_offset(0), - _generation(1) {} + _generation(1), + _final(false) {} JfrChunk::~JfrChunk() { reset(); @@ -86,10 +87,20 @@ u2 JfrChunk::minor_version() const { return JFR_VERSION_MINOR; } -u2 JfrChunk::capabilities() const { +void JfrChunk::mark_final() { + _final = true; +} + +u2 JfrChunk::flags() const { // chunk capabilities, CompressedIntegers etc - static bool compressed_integers = JfrOptionSet::compressed_integers(); - return compressed_integers; + u2 flags = 0; + if (JfrOptionSet::compressed_integers()) { + flags |= 1 << 0; + } + if (_final) { + flags |= 1 << 1; + } + return flags; } int64_t JfrChunk::cpu_frequency() const { diff --git a/src/share/vm/jfr/recorder/repository/jfrChunk.hpp b/src/share/vm/jfr/recorder/repository/jfrChunk.hpp index 26073b9aa3bdb1e4f2eaa50039372e6d25f9e47d..d7bd3411160d758ea6f20f7647f197c09ee650a2 100644 --- a/src/share/vm/jfr/recorder/repository/jfrChunk.hpp +++ b/src/share/vm/jfr/recorder/repository/jfrChunk.hpp @@ -44,6 +44,7 @@ class JfrChunk : public JfrCHeapObj { int64_t _last_checkpoint_offset; int64_t _last_metadata_offset; mutable u1 _generation; + bool _final; JfrChunk(); ~JfrChunk(); @@ -53,7 +54,9 @@ class JfrChunk : public JfrCHeapObj { u2 major_version() const; u2 minor_version() const; int64_t cpu_frequency() const; - u2 capabilities() const; + u2 flags() const; + + void mark_final(); void update_start_ticks(); void update_start_nanos(); diff --git a/src/share/vm/jfr/recorder/repository/jfrChunkWriter.cpp b/src/share/vm/jfr/recorder/repository/jfrChunkWriter.cpp index 9f10a7211e9e124d114a8177fef02cef5f06493d..c8eee97579d0acf57efe3d505cac51f1a57b97f3 100644 --- a/src/share/vm/jfr/recorder/repository/jfrChunkWriter.cpp +++ b/src/share/vm/jfr/recorder/repository/jfrChunkWriter.cpp @@ -41,8 +41,8 @@ static const int64_t DURATION_NANOS_OFFSET = START_NANOS_OFFSET + SLOT_SIZE; static const int64_t START_TICKS_OFFSET = DURATION_NANOS_OFFSET + SLOT_SIZE; static const int64_t CPU_FREQUENCY_OFFSET = START_TICKS_OFFSET + SLOT_SIZE; static const int64_t GENERATION_OFFSET = CPU_FREQUENCY_OFFSET + SLOT_SIZE; -static const int64_t CAPABILITY_OFFSET = GENERATION_OFFSET + 2; -static const int64_t HEADER_SIZE = CAPABILITY_OFFSET + 2; +static const int64_t FLAG_OFFSET = GENERATION_OFFSET + 2; +static const int64_t HEADER_SIZE = FLAG_OFFSET + 2; static fio_fd open_chunk(const char* path) { assert(JfrStream_lock->owned_by_self(), "invariant"); @@ -118,8 +118,8 @@ class JfrChunkHeadWriter : public StackObj { _writer->flush(); } - void write_capabilities() { - _writer->be_write(_chunk->capabilities()); + void write_flags() { + _writer->be_write(_chunk->flags()); } void write_size_to_generation(int64_t size, bool finalize) { @@ -136,7 +136,7 @@ class JfrChunkHeadWriter : public StackObj { assert(_chunk != NULL, "invariant"); DEBUG_ONLY(assert_writer_position(_writer, SIZE_OFFSET);) write_size_to_generation(size, finalize); - // no need to write capabilities + write_flags(); _writer->seek(size); // implicit flush } @@ -147,7 +147,7 @@ class JfrChunkHeadWriter : public StackObj { write_magic(); write_version(); write_size_to_generation(HEADER_SIZE, false); - write_capabilities(); + write_flags(); DEBUG_ONLY(assert_writer_position(_writer, HEADER_SIZE);) _writer->flush(); } @@ -202,7 +202,7 @@ int64_t JfrChunkWriter::write_chunk_header_checkpoint(bool flushpoint) { head.write_time(false); head.write_cpu_frequency(); head.write_next_generation(); - head.write_capabilities(); + head.write_flags(); assert(current_offset() - header_content_pos == HEADER_SIZE, "invariant"); const u4 checkpoint_size = current_offset() - event_size_offset; write_padded_at_offset(checkpoint_size, event_size_offset); @@ -212,6 +212,11 @@ int64_t JfrChunkWriter::write_chunk_header_checkpoint(bool flushpoint) { return sz_written; } +void JfrChunkWriter::mark_chunk_final() { + assert(_chunk != NULL, "invariant"); + _chunk->mark_final(); +} + int64_t JfrChunkWriter::flush_chunk(bool flushpoint) { assert(_chunk != NULL, "invariant"); const int64_t sz_written = write_chunk_header_checkpoint(flushpoint); diff --git a/src/share/vm/jfr/recorder/repository/jfrChunkWriter.hpp b/src/share/vm/jfr/recorder/repository/jfrChunkWriter.hpp index 707f995b7afcebde33f1ddef7ff1a56690b250a9..f5739629a67753f2110a7404479ecd11b34e3dcf 100644 --- a/src/share/vm/jfr/recorder/repository/jfrChunkWriter.hpp +++ b/src/share/vm/jfr/recorder/repository/jfrChunkWriter.hpp @@ -59,6 +59,7 @@ class JfrChunkWriter : public JfrChunkWriterBase { bool has_metadata() const; void set_time_stamp(); + void mark_chunk_final(); }; #endif // SHARE_VM_JFR_RECORDER_REPOSITORY_JFRCHUNKWRITER_HPP diff --git a/src/share/vm/jfr/recorder/repository/jfrRepository.cpp b/src/share/vm/jfr/recorder/repository/jfrRepository.cpp index ebb1486b426991cfec90764e2be8893da5f968dc..4c3c72d17be24c3fc5123b58e8dc6184436601a1 100644 --- a/src/share/vm/jfr/recorder/repository/jfrRepository.cpp +++ b/src/share/vm/jfr/recorder/repository/jfrRepository.cpp @@ -114,6 +114,10 @@ void JfrRepository::set_chunk_path(const char* path) { chunkwriter().set_path(path); } +void JfrRepository::mark_chunk_final() { + chunkwriter().mark_chunk_final(); +} + jlong JfrRepository::current_chunk_start_nanos() { return chunkwriter().current_chunk_start_nanos(); } diff --git a/src/share/vm/jfr/recorder/repository/jfrRepository.hpp b/src/share/vm/jfr/recorder/repository/jfrRepository.hpp index 8c1b0edb23062d0dc457b9648c1a8b10abb411f9..db26cc11cd41767d20f7bf00089611e8f49ebb5c 100644 --- a/src/share/vm/jfr/recorder/repository/jfrRepository.hpp +++ b/src/share/vm/jfr/recorder/repository/jfrRepository.hpp @@ -70,6 +70,7 @@ class JfrRepository : public JfrCHeapObj { public: static void set_path(jstring location, JavaThread* jt); static void set_chunk_path(jstring path, JavaThread* jt); + static void mark_chunk_final(); static void flush(JavaThread* jt); static jlong current_chunk_start_nanos(); }; diff --git a/src/share/vm/jfr/recorder/service/jfrRecorderService.cpp b/src/share/vm/jfr/recorder/service/jfrRecorderService.cpp index 63189a5267c43ccceda5b5beda82b1d1f900d92c..2c983a318620ab0ccac2f854bf1f70d0be32eab5 100644 --- a/src/share/vm/jfr/recorder/service/jfrRecorderService.cpp +++ b/src/share/vm/jfr/recorder/service/jfrRecorderService.cpp @@ -432,6 +432,7 @@ void JfrRecorderService::vm_error_rotation() { if (_chunkwriter.is_valid()) { Thread* const t = Thread::current(); _storage.flush_regular_buffer(t->jfr_thread_local()->native_buffer(), t); + _chunkwriter.mark_chunk_final(); invoke_flush(); _chunkwriter.set_time_stamp(); _repository.close_chunk();