Fri, 23 Nov 2018 16:36:07 +0900
8213015: Inconsistent settings between JFR.configure and -XX:FlightRecorderOptions
Reviewed-by: mgronlun, egahlin
apetushkov@9858 | 1 | /* |
apetushkov@9858 | 2 | * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved. |
apetushkov@9858 | 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
apetushkov@9858 | 4 | * |
apetushkov@9858 | 5 | * This code is free software; you can redistribute it and/or modify it |
apetushkov@9858 | 6 | * under the terms of the GNU General Public License version 2 only, as |
apetushkov@9858 | 7 | * published by the Free Software Foundation. |
apetushkov@9858 | 8 | * |
apetushkov@9858 | 9 | * This code is distributed in the hope that it will be useful, but WITHOUT |
apetushkov@9858 | 10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
apetushkov@9858 | 11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
apetushkov@9858 | 12 | * version 2 for more details (a copy is included in the LICENSE file that |
apetushkov@9858 | 13 | * accompanied this code). |
apetushkov@9858 | 14 | * |
apetushkov@9858 | 15 | * You should have received a copy of the GNU General Public License version |
apetushkov@9858 | 16 | * 2 along with this work; if not, write to the Free Software Foundation, |
apetushkov@9858 | 17 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
apetushkov@9858 | 18 | * |
apetushkov@9858 | 19 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
apetushkov@9858 | 20 | * or visit www.oracle.com if you need additional information or have any |
apetushkov@9858 | 21 | * questions. |
apetushkov@9858 | 22 | * |
apetushkov@9858 | 23 | */ |
apetushkov@9858 | 24 | |
apetushkov@9858 | 25 | #include "precompiled.hpp" |
apetushkov@9858 | 26 | #include "jfr/dcmd/jfrDcmds.hpp" |
apetushkov@9858 | 27 | #include "jfr/recorder/service/jfrMemorySizer.hpp" |
apetushkov@9858 | 28 | #include "jfr/recorder/service/jfrOptionSet.hpp" |
apetushkov@9858 | 29 | #include "jfr/utilities/jfrAllocation.hpp" |
apetushkov@9858 | 30 | #include "memory/allocation.inline.hpp" |
apetushkov@9858 | 31 | #include "memory/resourceArea.hpp" |
apetushkov@9858 | 32 | #include "runtime/java.hpp" |
apetushkov@9858 | 33 | #include "runtime/thread.inline.hpp" |
apetushkov@9858 | 34 | #include "services/diagnosticArgument.hpp" |
apetushkov@9858 | 35 | #include "services/diagnosticFramework.hpp" |
apetushkov@9858 | 36 | #include "utilities/growableArray.hpp" |
apetushkov@9858 | 37 | #include "utilities/ostream.hpp" |
apetushkov@9858 | 38 | |
apetushkov@9858 | 39 | struct ObsoleteOption { |
apetushkov@9858 | 40 | const char* name; |
apetushkov@9858 | 41 | const char* message; |
apetushkov@9858 | 42 | }; |
apetushkov@9858 | 43 | |
apetushkov@9858 | 44 | static const ObsoleteOption OBSOLETE_OPTIONS[] = { |
apetushkov@9858 | 45 | {"checkpointbuffersize", ""}, |
apetushkov@9858 | 46 | {"maxsize", "Use -XX:StartFlightRecording=maxsize=... instead."}, |
apetushkov@9858 | 47 | {"maxage", "Use -XX:StartFlightRecording=maxage=... instead."}, |
apetushkov@9858 | 48 | {"settings", "Use -XX:StartFlightRecording=settings=... instead."}, |
apetushkov@9858 | 49 | {"defaultrecording", "Use -XX:StartFlightRecording=disk=false to create an in-memory recording."}, |
apetushkov@9858 | 50 | {"disk", "Use -XX:StartFlightRecording=disk=... instead."}, |
apetushkov@9858 | 51 | {"dumponexit", "Use -XX:StartFlightRecording=dumponexit=... instead."}, |
apetushkov@9858 | 52 | {"dumponexitpath", "Use -XX:StartFlightRecording=filename=... instead."}, |
apetushkov@9858 | 53 | {"loglevel", "Use -Xlog:jfr=... instead."} |
apetushkov@9858 | 54 | }; |
apetushkov@9858 | 55 | |
apetushkov@9858 | 56 | jlong JfrOptionSet::max_chunk_size() { |
apetushkov@9858 | 57 | return _max_chunk_size; |
apetushkov@9858 | 58 | } |
apetushkov@9858 | 59 | |
apetushkov@9858 | 60 | void JfrOptionSet::set_max_chunk_size(jlong value) { |
apetushkov@9858 | 61 | _max_chunk_size = value; |
apetushkov@9858 | 62 | } |
apetushkov@9858 | 63 | |
apetushkov@9858 | 64 | jlong JfrOptionSet::global_buffer_size() { |
apetushkov@9858 | 65 | return _global_buffer_size; |
apetushkov@9858 | 66 | } |
apetushkov@9858 | 67 | |
apetushkov@9858 | 68 | void JfrOptionSet::set_global_buffer_size(jlong value) { |
apetushkov@9858 | 69 | _global_buffer_size = value; |
apetushkov@9858 | 70 | } |
apetushkov@9858 | 71 | |
apetushkov@9858 | 72 | jlong JfrOptionSet::thread_buffer_size() { |
apetushkov@9858 | 73 | return _thread_buffer_size; |
apetushkov@9858 | 74 | } |
apetushkov@9858 | 75 | |
apetushkov@9858 | 76 | void JfrOptionSet::set_thread_buffer_size(jlong value) { |
apetushkov@9858 | 77 | _thread_buffer_size = value; |
apetushkov@9858 | 78 | } |
apetushkov@9858 | 79 | |
apetushkov@9858 | 80 | jlong JfrOptionSet::memory_size() { |
apetushkov@9858 | 81 | return _memory_size; |
apetushkov@9858 | 82 | } |
apetushkov@9858 | 83 | |
apetushkov@9858 | 84 | void JfrOptionSet::set_memory_size(jlong value) { |
apetushkov@9858 | 85 | _memory_size = value; |
apetushkov@9858 | 86 | } |
apetushkov@9858 | 87 | |
apetushkov@9858 | 88 | jlong JfrOptionSet::num_global_buffers() { |
apetushkov@9858 | 89 | return _num_global_buffers; |
apetushkov@9858 | 90 | } |
apetushkov@9858 | 91 | |
apetushkov@9858 | 92 | void JfrOptionSet::set_num_global_buffers(jlong value) { |
apetushkov@9858 | 93 | _num_global_buffers = value; |
apetushkov@9858 | 94 | } |
apetushkov@9858 | 95 | |
apetushkov@9858 | 96 | jint JfrOptionSet::old_object_queue_size() { |
apetushkov@9858 | 97 | return (jint)_old_object_queue_size; |
apetushkov@9858 | 98 | } |
apetushkov@9858 | 99 | |
apetushkov@9858 | 100 | void JfrOptionSet::set_old_object_queue_size(jlong value) { |
apetushkov@9858 | 101 | _old_object_queue_size = value; |
apetushkov@9858 | 102 | } |
apetushkov@9858 | 103 | |
apetushkov@9858 | 104 | u4 JfrOptionSet::stackdepth() { |
apetushkov@9858 | 105 | return _stack_depth; |
apetushkov@9858 | 106 | } |
apetushkov@9858 | 107 | |
apetushkov@9858 | 108 | static const u4 STACK_DEPTH_DEFAULT = 64; |
apetushkov@9858 | 109 | static const u4 MIN_STACK_DEPTH = 1; |
apetushkov@9858 | 110 | static const u4 MAX_STACK_DEPTH = 2048; |
apetushkov@9858 | 111 | |
apetushkov@9858 | 112 | void JfrOptionSet::set_stackdepth(u4 depth) { |
apetushkov@9858 | 113 | if (depth < MIN_STACK_DEPTH) { |
apetushkov@9858 | 114 | _stack_depth = MIN_STACK_DEPTH; |
apetushkov@9858 | 115 | } else if (depth > MAX_STACK_DEPTH) { |
apetushkov@9858 | 116 | _stack_depth = MAX_STACK_DEPTH; |
apetushkov@9858 | 117 | } else { |
apetushkov@9858 | 118 | _stack_depth = depth; |
apetushkov@9858 | 119 | } |
apetushkov@9858 | 120 | } |
apetushkov@9858 | 121 | |
apetushkov@9858 | 122 | bool JfrOptionSet::sample_threads() { |
apetushkov@9858 | 123 | return _sample_threads == JNI_TRUE; |
apetushkov@9858 | 124 | } |
apetushkov@9858 | 125 | |
apetushkov@9858 | 126 | void JfrOptionSet::set_sample_threads(jboolean sample) { |
apetushkov@9858 | 127 | _sample_threads = sample; |
apetushkov@9858 | 128 | } |
apetushkov@9858 | 129 | |
apetushkov@9858 | 130 | bool JfrOptionSet::can_retransform() { |
apetushkov@9858 | 131 | return _retransform == JNI_TRUE; |
apetushkov@9858 | 132 | } |
apetushkov@9858 | 133 | |
apetushkov@9858 | 134 | void JfrOptionSet::set_retransform(jboolean value) { |
apetushkov@9858 | 135 | _retransform = value; |
apetushkov@9858 | 136 | } |
apetushkov@9858 | 137 | |
apetushkov@9858 | 138 | bool JfrOptionSet::sample_protection() { |
apetushkov@9858 | 139 | return _sample_protection == JNI_TRUE; |
apetushkov@9858 | 140 | } |
apetushkov@9858 | 141 | |
apetushkov@9858 | 142 | #ifdef ASSERT |
apetushkov@9858 | 143 | void JfrOptionSet::set_sample_protection(jboolean protection) { |
apetushkov@9858 | 144 | _sample_protection = protection; |
apetushkov@9858 | 145 | } |
apetushkov@9858 | 146 | #endif |
apetushkov@9858 | 147 | |
apetushkov@9858 | 148 | bool JfrOptionSet::compressed_integers() { |
apetushkov@9858 | 149 | // Set this to false for debugging purposes. |
apetushkov@9858 | 150 | return true; |
apetushkov@9858 | 151 | } |
apetushkov@9858 | 152 | |
apetushkov@9858 | 153 | bool JfrOptionSet::allow_retransforms() { |
apetushkov@9858 | 154 | #if INCLUDE_JVMTI |
apetushkov@9858 | 155 | return true; |
apetushkov@9858 | 156 | #else |
apetushkov@9858 | 157 | return false; |
apetushkov@9858 | 158 | #endif |
apetushkov@9858 | 159 | } |
apetushkov@9858 | 160 | |
apetushkov@9858 | 161 | bool JfrOptionSet::allow_event_retransforms() { |
apetushkov@9858 | 162 | return allow_retransforms() && (DumpSharedSpaces || can_retransform()); |
apetushkov@9858 | 163 | } |
apetushkov@9858 | 164 | |
apetushkov@9858 | 165 | // default options for the dcmd parser |
apetushkov@9858 | 166 | const char* const default_repository = NULL; |
apetushkov@9858 | 167 | const char* const default_global_buffer_size = "512k"; |
apetushkov@9858 | 168 | const char* const default_num_global_buffers = "20"; |
apetushkov@9858 | 169 | const char* const default_memory_size = "10m"; |
apetushkov@9858 | 170 | const char* const default_thread_buffer_size = "8k"; |
apetushkov@9858 | 171 | const char* const default_max_chunk_size = "12m"; |
apetushkov@9858 | 172 | const char* const default_sample_threads = "true"; |
apetushkov@9858 | 173 | const char* const default_stack_depth = "64"; |
apetushkov@9858 | 174 | const char* const default_retransform = "true"; |
apetushkov@9858 | 175 | const char* const default_old_object_queue_size = "256"; |
apetushkov@9858 | 176 | DEBUG_ONLY(const char* const default_sample_protection = "false";) |
apetushkov@9858 | 177 | |
apetushkov@9858 | 178 | // statics |
apetushkov@9858 | 179 | static DCmdArgument<char*> _dcmd_repository( |
apetushkov@9858 | 180 | "repository", |
apetushkov@9858 | 181 | "Flight recorder disk repository location", |
apetushkov@9858 | 182 | "STRING", |
apetushkov@9858 | 183 | false, |
apetushkov@9858 | 184 | default_repository); |
apetushkov@9858 | 185 | |
apetushkov@9858 | 186 | static DCmdArgument<MemorySizeArgument> _dcmd_threadbuffersize( |
apetushkov@9858 | 187 | "threadbuffersize", |
apetushkov@9858 | 188 | "Thread buffer size", |
apetushkov@9858 | 189 | "MEMORY SIZE", |
apetushkov@9858 | 190 | false, |
apetushkov@9858 | 191 | default_thread_buffer_size); |
apetushkov@9858 | 192 | |
apetushkov@9858 | 193 | static DCmdArgument<MemorySizeArgument> _dcmd_memorysize( |
apetushkov@9858 | 194 | "memorysize", |
apetushkov@9858 | 195 | "Size of memory to be used by Flight Recorder", |
apetushkov@9858 | 196 | "MEMORY SIZE", |
apetushkov@9858 | 197 | false, |
apetushkov@9858 | 198 | default_memory_size); |
apetushkov@9858 | 199 | |
apetushkov@9858 | 200 | static DCmdArgument<MemorySizeArgument> _dcmd_globalbuffersize( |
apetushkov@9858 | 201 | "globalbuffersize", |
apetushkov@9858 | 202 | "Global buffer size", |
apetushkov@9858 | 203 | "MEMORY SIZE", |
apetushkov@9858 | 204 | false, |
apetushkov@9858 | 205 | default_global_buffer_size); |
apetushkov@9858 | 206 | |
apetushkov@9858 | 207 | static DCmdArgument<jlong> _dcmd_numglobalbuffers( |
apetushkov@9858 | 208 | "numglobalbuffers", |
apetushkov@9858 | 209 | "Number of global buffers", |
apetushkov@9858 | 210 | "JULONG", |
apetushkov@9858 | 211 | false, |
apetushkov@9858 | 212 | default_num_global_buffers); |
apetushkov@9858 | 213 | |
apetushkov@9858 | 214 | static DCmdArgument<MemorySizeArgument> _dcmd_maxchunksize( |
apetushkov@9858 | 215 | "maxchunksize", |
apetushkov@9858 | 216 | "Maximum size of a single repository disk chunk", |
apetushkov@9858 | 217 | "MEMORY SIZE", |
apetushkov@9858 | 218 | false, |
apetushkov@9858 | 219 | default_max_chunk_size); |
apetushkov@9858 | 220 | |
apetushkov@9858 | 221 | static DCmdArgument<jlong> _dcmd_old_object_queue_size ( |
apetushkov@9858 | 222 | "old-object-queue-size", |
apetushkov@9858 | 223 | "Maximum number of old objects to track", |
apetushkov@9858 | 224 | "JINT", |
apetushkov@9858 | 225 | false, |
apetushkov@9858 | 226 | default_old_object_queue_size); |
apetushkov@9858 | 227 | |
apetushkov@9858 | 228 | static DCmdArgument<bool> _dcmd_sample_threads( |
apetushkov@9858 | 229 | "samplethreads", |
apetushkov@9858 | 230 | "Thread sampling enable / disable (only sampling when event enabled and sampling enabled)", |
apetushkov@9858 | 231 | "BOOLEAN", |
apetushkov@9858 | 232 | false, |
apetushkov@9858 | 233 | default_sample_threads); |
apetushkov@9858 | 234 | |
apetushkov@9858 | 235 | #ifdef ASSERT |
apetushkov@9858 | 236 | static DCmdArgument<bool> _dcmd_sample_protection( |
apetushkov@9858 | 237 | "sampleprotection", |
apetushkov@9858 | 238 | "Safeguard for stackwalking while sampling threads (false by default)", |
apetushkov@9858 | 239 | "BOOLEAN", |
apetushkov@9858 | 240 | false, |
apetushkov@9858 | 241 | default_sample_protection); |
apetushkov@9858 | 242 | #endif |
apetushkov@9858 | 243 | |
apetushkov@9858 | 244 | static DCmdArgument<jlong> _dcmd_stackdepth( |
apetushkov@9858 | 245 | "stackdepth", |
apetushkov@9858 | 246 | "Stack depth for stacktraces (minimum 1, maximum 2048)", |
apetushkov@9858 | 247 | "JULONG", |
apetushkov@9858 | 248 | false, |
apetushkov@9858 | 249 | default_stack_depth); |
apetushkov@9858 | 250 | |
apetushkov@9858 | 251 | static DCmdArgument<bool> _dcmd_retransform( |
apetushkov@9858 | 252 | "retransform", |
apetushkov@9858 | 253 | "If event classes should be instrumented using JVMTI (by default true)", |
apetushkov@9858 | 254 | "BOOLEAN", |
apetushkov@9858 | 255 | true, |
apetushkov@9858 | 256 | default_retransform); |
apetushkov@9858 | 257 | |
apetushkov@9858 | 258 | static DCmdParser _parser; |
apetushkov@9858 | 259 | |
apetushkov@9858 | 260 | static void register_parser_options() { |
apetushkov@9858 | 261 | _parser.add_dcmd_option(&_dcmd_repository); |
apetushkov@9858 | 262 | _parser.add_dcmd_option(&_dcmd_threadbuffersize); |
apetushkov@9858 | 263 | _parser.add_dcmd_option(&_dcmd_memorysize); |
apetushkov@9858 | 264 | _parser.add_dcmd_option(&_dcmd_globalbuffersize); |
apetushkov@9858 | 265 | _parser.add_dcmd_option(&_dcmd_numglobalbuffers); |
apetushkov@9858 | 266 | _parser.add_dcmd_option(&_dcmd_maxchunksize); |
apetushkov@9858 | 267 | _parser.add_dcmd_option(&_dcmd_stackdepth); |
apetushkov@9858 | 268 | _parser.add_dcmd_option(&_dcmd_sample_threads); |
apetushkov@9858 | 269 | _parser.add_dcmd_option(&_dcmd_retransform); |
apetushkov@9858 | 270 | _parser.add_dcmd_option(&_dcmd_old_object_queue_size); |
apetushkov@9858 | 271 | DEBUG_ONLY(_parser.add_dcmd_option(&_dcmd_sample_protection);) |
apetushkov@9858 | 272 | } |
apetushkov@9858 | 273 | |
apetushkov@9858 | 274 | static bool parse_flight_recorder_options_internal(TRAPS) { |
apetushkov@9858 | 275 | if (FlightRecorderOptions == NULL) { |
apetushkov@9858 | 276 | return true; |
apetushkov@9858 | 277 | } |
apetushkov@9858 | 278 | const size_t length = strlen((const char*)FlightRecorderOptions); |
apetushkov@9858 | 279 | CmdLine cmdline((const char*)FlightRecorderOptions, length, true); |
apetushkov@9858 | 280 | _parser.parse(&cmdline, ',', THREAD); |
apetushkov@9858 | 281 | if (HAS_PENDING_EXCEPTION) { |
apetushkov@9858 | 282 | for (int index = 0; index < 9; index++) { |
apetushkov@9858 | 283 | ObsoleteOption option = OBSOLETE_OPTIONS[index]; |
apetushkov@9858 | 284 | const char* p = strstr((const char*)FlightRecorderOptions, option.name); |
apetushkov@9858 | 285 | const size_t option_length = strlen(option.name); |
apetushkov@9858 | 286 | if (p != NULL && p[option_length] == '=') { |
apetushkov@9858 | 287 | tty->print_cr("-XX:FlightRecorderOptions=%s=... has been removed. %s", option.name, option.message); |
apetushkov@9858 | 288 | return false; |
apetushkov@9858 | 289 | } |
apetushkov@9858 | 290 | } |
apetushkov@9858 | 291 | ResourceMark rm(THREAD); |
apetushkov@9858 | 292 | oop message = java_lang_Throwable::message(PENDING_EXCEPTION); |
apetushkov@9858 | 293 | if (message != NULL) { |
apetushkov@9858 | 294 | const char* msg = java_lang_String::as_utf8_string(message); |
apetushkov@9858 | 295 | tty->print_cr("%s", msg); |
apetushkov@9858 | 296 | } |
apetushkov@9858 | 297 | CLEAR_PENDING_EXCEPTION; |
apetushkov@9858 | 298 | return false; |
apetushkov@9858 | 299 | } |
apetushkov@9858 | 300 | return true; |
apetushkov@9858 | 301 | } |
apetushkov@9858 | 302 | |
apetushkov@9858 | 303 | jlong JfrOptionSet::_max_chunk_size = 0; |
apetushkov@9858 | 304 | jlong JfrOptionSet::_global_buffer_size = 0; |
apetushkov@9858 | 305 | jlong JfrOptionSet::_thread_buffer_size = 0; |
apetushkov@9858 | 306 | jlong JfrOptionSet::_memory_size = 0; |
apetushkov@9858 | 307 | jlong JfrOptionSet::_num_global_buffers = 0; |
apetushkov@9858 | 308 | jlong JfrOptionSet::_old_object_queue_size = 0; |
apetushkov@9858 | 309 | u4 JfrOptionSet::_stack_depth = STACK_DEPTH_DEFAULT; |
apetushkov@9858 | 310 | jboolean JfrOptionSet::_sample_threads = JNI_TRUE; |
apetushkov@9858 | 311 | jboolean JfrOptionSet::_retransform = JNI_TRUE; |
apetushkov@9858 | 312 | #ifdef ASSERT |
apetushkov@9858 | 313 | jboolean JfrOptionSet::_sample_protection = JNI_FALSE; |
apetushkov@9858 | 314 | #else |
apetushkov@9858 | 315 | jboolean JfrOptionSet::_sample_protection = JNI_TRUE; |
apetushkov@9858 | 316 | #endif |
apetushkov@9858 | 317 | |
apetushkov@9858 | 318 | bool JfrOptionSet::initialize(Thread* thread) { |
apetushkov@9858 | 319 | register_parser_options(); |
apetushkov@9858 | 320 | if (!parse_flight_recorder_options_internal(thread)) { |
apetushkov@9858 | 321 | return false; |
apetushkov@9858 | 322 | } |
apetushkov@9858 | 323 | if (_dcmd_retransform.is_set()) { |
apetushkov@9858 | 324 | set_retransform(_dcmd_retransform.value()); |
apetushkov@9858 | 325 | } |
apetushkov@9858 | 326 | set_old_object_queue_size(_dcmd_old_object_queue_size.value()); |
apetushkov@9858 | 327 | return adjust_memory_options(); |
apetushkov@9858 | 328 | } |
apetushkov@9858 | 329 | |
apetushkov@9858 | 330 | bool JfrOptionSet::configure(TRAPS) { |
apetushkov@9858 | 331 | if (FlightRecorderOptions == NULL) { |
apetushkov@9858 | 332 | return true; |
apetushkov@9858 | 333 | } |
apetushkov@9858 | 334 | ResourceMark rm(THREAD); |
apetushkov@9858 | 335 | bufferedStream st; |
apetushkov@9858 | 336 | // delegate to DCmd execution |
apetushkov@9858 | 337 | JfrConfigureFlightRecorderDCmd configure(&st, false); |
apetushkov@9858 | 338 | configure._repository_path.set_is_set(_dcmd_repository.is_set()); |
apetushkov@9858 | 339 | char* repo = _dcmd_repository.value(); |
apetushkov@9858 | 340 | if (repo != NULL) { |
apetushkov@9858 | 341 | const size_t len = strlen(repo); |
apetushkov@9858 | 342 | char* repo_copy = JfrCHeapObj::new_array<char>(len + 1); |
apetushkov@9858 | 343 | if (NULL == repo_copy) { |
apetushkov@9858 | 344 | return false; |
apetushkov@9858 | 345 | } |
apetushkov@9858 | 346 | strncpy(repo_copy, repo, len + 1); |
apetushkov@9858 | 347 | configure._repository_path.set_value(repo_copy); |
apetushkov@9858 | 348 | } |
apetushkov@9858 | 349 | |
apetushkov@9858 | 350 | configure._stack_depth.set_is_set(_dcmd_stackdepth.is_set()); |
apetushkov@9858 | 351 | configure._stack_depth.set_value(_dcmd_stackdepth.value()); |
apetushkov@9858 | 352 | |
apetushkov@9858 | 353 | configure._thread_buffer_size.set_is_set(_dcmd_threadbuffersize.is_set()); |
ysuenaga@9870 | 354 | configure._thread_buffer_size.set_value(_dcmd_threadbuffersize.value()); |
apetushkov@9858 | 355 | |
apetushkov@9858 | 356 | configure._global_buffer_count.set_is_set(_dcmd_numglobalbuffers.is_set()); |
apetushkov@9858 | 357 | configure._global_buffer_count.set_value(_dcmd_numglobalbuffers.value()); |
apetushkov@9858 | 358 | |
apetushkov@9858 | 359 | configure._global_buffer_size.set_is_set(_dcmd_globalbuffersize.is_set()); |
ysuenaga@9870 | 360 | configure._global_buffer_size.set_value(_dcmd_globalbuffersize.value()); |
apetushkov@9858 | 361 | |
apetushkov@9858 | 362 | configure._max_chunk_size.set_is_set(_dcmd_maxchunksize.is_set()); |
ysuenaga@9870 | 363 | configure._max_chunk_size.set_value(_dcmd_maxchunksize.value()); |
apetushkov@9858 | 364 | |
apetushkov@9858 | 365 | configure._memory_size.set_is_set(_dcmd_memorysize.is_set()); |
ysuenaga@9870 | 366 | configure._memory_size.set_value(_dcmd_memorysize.value()); |
apetushkov@9858 | 367 | |
apetushkov@9858 | 368 | configure._sample_threads.set_is_set(_dcmd_sample_threads.is_set()); |
apetushkov@9858 | 369 | configure._sample_threads.set_value(_dcmd_sample_threads.value()); |
apetushkov@9858 | 370 | |
apetushkov@9858 | 371 | configure.execute(DCmd_Source_Internal, THREAD); |
apetushkov@9858 | 372 | |
apetushkov@9858 | 373 | if (HAS_PENDING_EXCEPTION) { |
apetushkov@9858 | 374 | java_lang_Throwable::print(PENDING_EXCEPTION, tty); |
apetushkov@9858 | 375 | CLEAR_PENDING_EXCEPTION; |
apetushkov@9858 | 376 | return false; |
apetushkov@9858 | 377 | } |
apetushkov@9858 | 378 | return true; |
apetushkov@9858 | 379 | } |
apetushkov@9858 | 380 | |
apetushkov@9858 | 381 | template <typename Argument> |
apetushkov@9858 | 382 | static julong divide_with_user_unit(Argument& memory_argument, julong value) { |
apetushkov@9858 | 383 | if (memory_argument.value()._size != memory_argument.value()._val) { |
apetushkov@9858 | 384 | switch (memory_argument.value()._multiplier) { |
apetushkov@9858 | 385 | case 'k': case 'K': |
apetushkov@9858 | 386 | return value / K; |
apetushkov@9858 | 387 | case 'm': case 'M': |
apetushkov@9858 | 388 | return value / M; |
apetushkov@9858 | 389 | case 'g': case 'G': |
apetushkov@9858 | 390 | return value / G; |
apetushkov@9858 | 391 | } |
apetushkov@9858 | 392 | } |
apetushkov@9858 | 393 | return value; |
apetushkov@9858 | 394 | } |
apetushkov@9858 | 395 | |
apetushkov@9858 | 396 | template <typename Argument> |
apetushkov@9858 | 397 | static void log_lower_than_min_value(Argument& memory_argument, julong min_value) { |
apetushkov@9858 | 398 | if (memory_argument.value()._size != memory_argument.value()._val) { |
apetushkov@9858 | 399 | // has multiplier |
apetushkov@9858 | 400 | tty->print_cr( |
apetushkov@9858 | 401 | "This value is lower than the minimum size required " JULONG_FORMAT "%c", |
apetushkov@9858 | 402 | divide_with_user_unit(memory_argument, min_value), |
apetushkov@9858 | 403 | memory_argument.value()._multiplier); |
apetushkov@9858 | 404 | return; |
apetushkov@9858 | 405 | } |
apetushkov@9858 | 406 | tty->print_cr( |
apetushkov@9858 | 407 | "This value is lower than the minimum size required " JULONG_FORMAT, |
apetushkov@9858 | 408 | divide_with_user_unit(memory_argument, min_value)); |
apetushkov@9858 | 409 | } |
apetushkov@9858 | 410 | |
apetushkov@9858 | 411 | template <typename Argument> |
apetushkov@9858 | 412 | static void log_set_value(Argument& memory_argument) { |
apetushkov@9858 | 413 | if (memory_argument.value()._size != memory_argument.value()._val) { |
apetushkov@9858 | 414 | // has multiplier |
apetushkov@9858 | 415 | tty->print_cr( |
apetushkov@9858 | 416 | "Value specified for option \"%s\" is " JULONG_FORMAT "%c", |
apetushkov@9858 | 417 | memory_argument.name(), |
apetushkov@9858 | 418 | memory_argument.value()._val, |
apetushkov@9858 | 419 | memory_argument.value()._multiplier); |
apetushkov@9858 | 420 | return; |
apetushkov@9858 | 421 | } |
apetushkov@9858 | 422 | tty->print_cr( |
apetushkov@9858 | 423 | "Value specified for option \"%s\" is " JULONG_FORMAT, |
apetushkov@9858 | 424 | memory_argument.name(), memory_argument.value()._val); |
apetushkov@9858 | 425 | } |
apetushkov@9858 | 426 | |
apetushkov@9858 | 427 | template <typename MemoryArg> |
apetushkov@9858 | 428 | static void log_adjustments(MemoryArg& original_memory_size, julong new_memory_size, const char* msg) { |
apetushkov@9858 | 429 | if (LogJFR && Verbose) tty->print_cr( |
apetushkov@9858 | 430 | "%s size (original) " JULONG_FORMAT " B (user defined: %s)", |
apetushkov@9858 | 431 | msg, |
apetushkov@9858 | 432 | original_memory_size.value()._size, |
apetushkov@9858 | 433 | original_memory_size.is_set() ? "true" : "false"); |
apetushkov@9858 | 434 | if (LogJFR && Verbose) tty->print_cr( |
apetushkov@9858 | 435 | "%s size (adjusted) " JULONG_FORMAT " B (modified: %s)", |
apetushkov@9858 | 436 | msg, |
apetushkov@9858 | 437 | new_memory_size, |
apetushkov@9858 | 438 | original_memory_size.value()._size != new_memory_size ? "true" : "false"); |
apetushkov@9858 | 439 | if (LogJFR && Verbose) tty->print_cr( |
apetushkov@9858 | 440 | "%s size (adjustment) %s" JULONG_FORMAT " B", |
apetushkov@9858 | 441 | msg, |
apetushkov@9858 | 442 | new_memory_size < original_memory_size.value()._size ? "-" : "+", |
apetushkov@9858 | 443 | new_memory_size < original_memory_size.value()._size ? |
apetushkov@9858 | 444 | original_memory_size.value()._size - new_memory_size : |
apetushkov@9858 | 445 | new_memory_size - original_memory_size.value()._size); |
apetushkov@9858 | 446 | } |
apetushkov@9858 | 447 | |
apetushkov@9858 | 448 | // All "triangular" options are explicitly set |
apetushkov@9858 | 449 | // check that they are congruent and not causing |
apetushkov@9858 | 450 | // an ambiguous situtation |
apetushkov@9858 | 451 | template <typename MemoryArg, typename NumberArg> |
apetushkov@9858 | 452 | static bool check_for_ambiguity(MemoryArg& memory_size, MemoryArg& global_buffer_size, NumberArg& num_global_buffers) { |
apetushkov@9858 | 453 | assert(memory_size.is_set(), "invariant"); |
apetushkov@9858 | 454 | assert(global_buffer_size.is_set(), "invariant"); |
apetushkov@9858 | 455 | assert(num_global_buffers.is_set(), "invariant"); |
apetushkov@9858 | 456 | const julong calc_size = global_buffer_size.value()._size * (julong)num_global_buffers.value(); |
apetushkov@9858 | 457 | if (calc_size != memory_size.value()._size) { |
apetushkov@9858 | 458 | // ambiguous |
apetushkov@9858 | 459 | log_set_value(global_buffer_size); |
apetushkov@9858 | 460 | tty->print_cr( |
apetushkov@9858 | 461 | "Value specified for option \"%s\" is " JLONG_FORMAT, |
apetushkov@9858 | 462 | num_global_buffers.name(), num_global_buffers.value()); |
apetushkov@9858 | 463 | log_set_value(memory_size); |
apetushkov@9858 | 464 | tty->print_cr( |
apetushkov@9858 | 465 | "These values are causing an ambiguity when trying to determine how much memory to use"); |
apetushkov@9858 | 466 | tty->print_cr("\"%s\" * \"%s\" do not equal \"%s\"", |
apetushkov@9858 | 467 | global_buffer_size.name(), |
apetushkov@9858 | 468 | num_global_buffers.name(), |
apetushkov@9858 | 469 | memory_size.name()); |
apetushkov@9858 | 470 | tty->print_cr( |
apetushkov@9858 | 471 | "Try to remove one of the involved options or make sure they are unambigous"); |
apetushkov@9858 | 472 | return false; |
apetushkov@9858 | 473 | } |
apetushkov@9858 | 474 | return true; |
apetushkov@9858 | 475 | } |
apetushkov@9858 | 476 | |
apetushkov@9858 | 477 | template <typename Argument> |
apetushkov@9858 | 478 | static bool ensure_minimum_count(Argument& buffer_count_argument, jlong min_count) { |
apetushkov@9858 | 479 | if (buffer_count_argument.value() < min_count) { |
apetushkov@9858 | 480 | tty->print_cr( |
apetushkov@9858 | 481 | "Value specified for option \"%s\" is " JLONG_FORMAT, |
apetushkov@9858 | 482 | buffer_count_argument.name(), buffer_count_argument.value()); |
apetushkov@9858 | 483 | tty->print_cr( |
apetushkov@9858 | 484 | "This value is lower than the minimum required number " JLONG_FORMAT, |
apetushkov@9858 | 485 | min_count); |
apetushkov@9858 | 486 | return false; |
apetushkov@9858 | 487 | } |
apetushkov@9858 | 488 | return true; |
apetushkov@9858 | 489 | } |
apetushkov@9858 | 490 | |
apetushkov@9858 | 491 | // global buffer size and num global buffers specified |
apetushkov@9858 | 492 | // ensure that particular combination to be ihigher than minimum memory size |
apetushkov@9858 | 493 | template <typename MemoryArg, typename NumberArg> |
apetushkov@9858 | 494 | static bool ensure_calculated_gteq(MemoryArg& global_buffer_size, NumberArg& num_global_buffers, julong min_value) { |
apetushkov@9858 | 495 | assert(global_buffer_size.is_set(), "invariant"); |
apetushkov@9858 | 496 | assert(num_global_buffers.is_set(), "invariant"); |
apetushkov@9858 | 497 | const julong calc_size = global_buffer_size.value()._size * (julong)num_global_buffers.value(); |
apetushkov@9858 | 498 | if (calc_size < min_value) { |
apetushkov@9858 | 499 | log_set_value(global_buffer_size); |
apetushkov@9858 | 500 | tty->print_cr( |
apetushkov@9858 | 501 | "Value specified for option \"%s\" is " JLONG_FORMAT, |
apetushkov@9858 | 502 | num_global_buffers.name(), num_global_buffers.value()); |
apetushkov@9858 | 503 | tty->print_cr("\"%s\" * \"%s\" (" JULONG_FORMAT |
apetushkov@9858 | 504 | ") is lower than minimum memory size required " JULONG_FORMAT, |
apetushkov@9858 | 505 | global_buffer_size.name(), |
apetushkov@9858 | 506 | num_global_buffers.name(), |
apetushkov@9858 | 507 | calc_size, |
apetushkov@9858 | 508 | min_value); |
apetushkov@9858 | 509 | return false; |
apetushkov@9858 | 510 | } |
apetushkov@9858 | 511 | return true; |
apetushkov@9858 | 512 | } |
apetushkov@9858 | 513 | |
apetushkov@9858 | 514 | template <typename Argument> |
apetushkov@9858 | 515 | static bool ensure_first_gteq_second(Argument& first_argument, Argument& second_argument) { |
apetushkov@9858 | 516 | if (second_argument.value()._size > first_argument.value()._size) { |
apetushkov@9858 | 517 | log_set_value(first_argument); |
apetushkov@9858 | 518 | log_set_value(second_argument); |
apetushkov@9858 | 519 | tty->print_cr( |
apetushkov@9858 | 520 | "The value for option \"%s\" should not be larger than the value specified for option \"%s\"", |
apetushkov@9858 | 521 | second_argument.name(), first_argument.name()); |
apetushkov@9858 | 522 | return false; |
apetushkov@9858 | 523 | } |
apetushkov@9858 | 524 | return true; |
apetushkov@9858 | 525 | } |
apetushkov@9858 | 526 | |
apetushkov@9858 | 527 | static bool valid_memory_relations(const JfrMemoryOptions& options) { |
apetushkov@9858 | 528 | if (options.global_buffer_size_configured) { |
apetushkov@9858 | 529 | if (options.memory_size_configured) { |
apetushkov@9858 | 530 | if (!ensure_first_gteq_second(_dcmd_memorysize, _dcmd_globalbuffersize)) { |
apetushkov@9858 | 531 | return false; |
apetushkov@9858 | 532 | } |
apetushkov@9858 | 533 | } |
apetushkov@9858 | 534 | if (options.thread_buffer_size_configured) { |
apetushkov@9858 | 535 | if (!ensure_first_gteq_second(_dcmd_globalbuffersize, _dcmd_threadbuffersize)) { |
apetushkov@9858 | 536 | return false; |
apetushkov@9858 | 537 | } |
apetushkov@9858 | 538 | } |
apetushkov@9858 | 539 | if (options.buffer_count_configured) { |
apetushkov@9858 | 540 | if (!ensure_calculated_gteq(_dcmd_globalbuffersize, _dcmd_numglobalbuffers, MIN_MEMORY_SIZE)) { |
apetushkov@9858 | 541 | return false; |
apetushkov@9858 | 542 | } |
apetushkov@9858 | 543 | } |
apetushkov@9858 | 544 | } |
apetushkov@9858 | 545 | return true; |
apetushkov@9858 | 546 | } |
apetushkov@9858 | 547 | |
apetushkov@9858 | 548 | static void post_process_adjusted_memory_options(const JfrMemoryOptions& options) { |
apetushkov@9858 | 549 | assert(options.memory_size >= MIN_MEMORY_SIZE, "invariant"); |
apetushkov@9858 | 550 | assert(options.global_buffer_size >= MIN_GLOBAL_BUFFER_SIZE, "invariant"); |
apetushkov@9858 | 551 | assert(options.buffer_count >= MIN_BUFFER_COUNT, "invariant"); |
apetushkov@9858 | 552 | assert(options.thread_buffer_size >= MIN_THREAD_BUFFER_SIZE, "invariant"); |
apetushkov@9858 | 553 | log_adjustments(_dcmd_memorysize, options.memory_size, "Memory"); |
apetushkov@9858 | 554 | log_adjustments(_dcmd_globalbuffersize, options.global_buffer_size, "Global buffer"); |
apetushkov@9858 | 555 | log_adjustments(_dcmd_threadbuffersize, options.thread_buffer_size, "Thread local buffer"); |
apetushkov@9858 | 556 | if (LogJFR && Verbose) tty->print_cr("Number of global buffers (original) " JLONG_FORMAT " (user defined: %s)", |
apetushkov@9858 | 557 | _dcmd_numglobalbuffers.value(), |
apetushkov@9858 | 558 | _dcmd_numglobalbuffers.is_set() ? "true" : "false"); |
apetushkov@9858 | 559 | if (LogJFR && Verbose) tty->print_cr( "Number of global buffers (adjusted) " JULONG_FORMAT " (modified: %s)", |
apetushkov@9858 | 560 | options.buffer_count, |
apetushkov@9858 | 561 | _dcmd_numglobalbuffers.value() != (jlong)options.buffer_count ? "true" : "false"); |
apetushkov@9858 | 562 | if (LogJFR && Verbose) tty->print_cr("Number of global buffers (adjustment) %s" JLONG_FORMAT, |
apetushkov@9858 | 563 | (jlong)options.buffer_count < _dcmd_numglobalbuffers.value() ? "" : "+", |
apetushkov@9858 | 564 | (jlong)options.buffer_count - _dcmd_numglobalbuffers.value()); |
apetushkov@9858 | 565 | |
apetushkov@9858 | 566 | MemorySizeArgument adjusted_memory_size; |
apetushkov@9858 | 567 | adjusted_memory_size._val = divide_with_user_unit(_dcmd_memorysize, options.memory_size); |
apetushkov@9858 | 568 | adjusted_memory_size._multiplier = _dcmd_memorysize.value()._multiplier; |
apetushkov@9858 | 569 | adjusted_memory_size._size = options.memory_size; |
apetushkov@9858 | 570 | |
apetushkov@9858 | 571 | MemorySizeArgument adjusted_global_buffer_size; |
apetushkov@9858 | 572 | adjusted_global_buffer_size._val = divide_with_user_unit(_dcmd_globalbuffersize, options.global_buffer_size); |
apetushkov@9858 | 573 | adjusted_global_buffer_size._multiplier = _dcmd_globalbuffersize.value()._multiplier; |
apetushkov@9858 | 574 | adjusted_global_buffer_size._size = options.global_buffer_size; |
apetushkov@9858 | 575 | |
apetushkov@9858 | 576 | MemorySizeArgument adjusted_thread_buffer_size; |
apetushkov@9858 | 577 | adjusted_thread_buffer_size._val = divide_with_user_unit(_dcmd_threadbuffersize, options.thread_buffer_size); |
apetushkov@9858 | 578 | adjusted_thread_buffer_size._multiplier = _dcmd_threadbuffersize.value()._multiplier; |
apetushkov@9858 | 579 | adjusted_thread_buffer_size._size = options.thread_buffer_size; |
apetushkov@9858 | 580 | |
apetushkov@9858 | 581 | // store back to dcmd |
apetushkov@9858 | 582 | _dcmd_memorysize.set_value(adjusted_memory_size); |
apetushkov@9858 | 583 | _dcmd_memorysize.set_is_set(true); |
apetushkov@9858 | 584 | _dcmd_globalbuffersize.set_value(adjusted_global_buffer_size); |
apetushkov@9858 | 585 | _dcmd_globalbuffersize.set_is_set(true); |
apetushkov@9858 | 586 | _dcmd_numglobalbuffers.set_value((jlong)options.buffer_count); |
apetushkov@9858 | 587 | _dcmd_numglobalbuffers.set_is_set(true); |
apetushkov@9858 | 588 | _dcmd_threadbuffersize.set_value(adjusted_thread_buffer_size); |
apetushkov@9858 | 589 | _dcmd_threadbuffersize.set_is_set(true); |
apetushkov@9858 | 590 | } |
apetushkov@9858 | 591 | |
apetushkov@9858 | 592 | static void initialize_memory_options_from_dcmd(JfrMemoryOptions& options) { |
apetushkov@9858 | 593 | options.memory_size = _dcmd_memorysize.value()._size; |
apetushkov@9858 | 594 | options.global_buffer_size = MAX2<julong>(_dcmd_globalbuffersize.value()._size, (julong)os::vm_page_size()); |
apetushkov@9858 | 595 | options.buffer_count = (julong)_dcmd_numglobalbuffers.value(); |
apetushkov@9858 | 596 | options.thread_buffer_size = MAX2<julong>(_dcmd_threadbuffersize.value()._size, (julong)os::vm_page_size()); |
apetushkov@9858 | 597 | // determine which options have been explicitly set |
apetushkov@9858 | 598 | options.memory_size_configured = _dcmd_memorysize.is_set(); |
apetushkov@9858 | 599 | options.global_buffer_size_configured = _dcmd_globalbuffersize.is_set(); |
apetushkov@9858 | 600 | options.buffer_count_configured = _dcmd_numglobalbuffers.is_set(); |
apetushkov@9858 | 601 | options.thread_buffer_size_configured = _dcmd_threadbuffersize.is_set(); |
apetushkov@9858 | 602 | assert(options.memory_size >= MIN_MEMORY_SIZE, "invariant"); |
apetushkov@9858 | 603 | assert(options.global_buffer_size >= MIN_GLOBAL_BUFFER_SIZE, "invariant"); |
apetushkov@9858 | 604 | assert(options.buffer_count >= MIN_BUFFER_COUNT, "invariant"); |
apetushkov@9858 | 605 | assert(options.thread_buffer_size >= MIN_THREAD_BUFFER_SIZE, "invariant"); |
apetushkov@9858 | 606 | } |
apetushkov@9858 | 607 | |
apetushkov@9858 | 608 | template <typename Argument> |
apetushkov@9858 | 609 | static bool ensure_gteq(Argument& memory_argument, const jlong value) { |
apetushkov@9858 | 610 | if ((jlong)memory_argument.value()._size < value) { |
apetushkov@9858 | 611 | log_set_value(memory_argument); |
apetushkov@9858 | 612 | log_lower_than_min_value(memory_argument, value); |
apetushkov@9858 | 613 | return false; |
apetushkov@9858 | 614 | } |
apetushkov@9858 | 615 | return true; |
apetushkov@9858 | 616 | } |
apetushkov@9858 | 617 | |
apetushkov@9858 | 618 | static bool ensure_valid_minimum_sizes() { |
apetushkov@9858 | 619 | // ensure valid minimum memory sizes |
apetushkov@9858 | 620 | if (_dcmd_memorysize.is_set()) { |
apetushkov@9858 | 621 | if (!ensure_gteq(_dcmd_memorysize, MIN_MEMORY_SIZE)) { |
apetushkov@9858 | 622 | return false; |
apetushkov@9858 | 623 | } |
apetushkov@9858 | 624 | } |
apetushkov@9858 | 625 | if (_dcmd_globalbuffersize.is_set()) { |
apetushkov@9858 | 626 | if (!ensure_gteq(_dcmd_globalbuffersize, MIN_GLOBAL_BUFFER_SIZE)) { |
apetushkov@9858 | 627 | return false; |
apetushkov@9858 | 628 | } |
apetushkov@9858 | 629 | } |
apetushkov@9858 | 630 | if (_dcmd_numglobalbuffers.is_set()) { |
apetushkov@9858 | 631 | if (!ensure_minimum_count(_dcmd_numglobalbuffers, MIN_BUFFER_COUNT)) { |
apetushkov@9858 | 632 | return false; |
apetushkov@9858 | 633 | } |
apetushkov@9858 | 634 | } |
apetushkov@9858 | 635 | if (_dcmd_threadbuffersize.is_set()) { |
apetushkov@9858 | 636 | if (!ensure_gteq(_dcmd_threadbuffersize, MIN_THREAD_BUFFER_SIZE)) { |
apetushkov@9858 | 637 | return false; |
apetushkov@9858 | 638 | } |
apetushkov@9858 | 639 | } |
apetushkov@9858 | 640 | return true; |
apetushkov@9858 | 641 | } |
apetushkov@9858 | 642 | |
apetushkov@9858 | 643 | /** |
apetushkov@9858 | 644 | * Starting with the initial set of memory values from the user, |
apetushkov@9858 | 645 | * sanitize, enforce min/max rules and adjust to a set of consistent options. |
apetushkov@9858 | 646 | * |
apetushkov@9858 | 647 | * Adjusted memory sizes will be page aligned. |
apetushkov@9858 | 648 | */ |
apetushkov@9858 | 649 | bool JfrOptionSet::adjust_memory_options() { |
apetushkov@9858 | 650 | if (!ensure_valid_minimum_sizes()) { |
apetushkov@9858 | 651 | return false; |
apetushkov@9858 | 652 | } |
apetushkov@9858 | 653 | JfrMemoryOptions options; |
apetushkov@9858 | 654 | initialize_memory_options_from_dcmd(options); |
apetushkov@9858 | 655 | if (!valid_memory_relations(options)) { |
apetushkov@9858 | 656 | return false; |
apetushkov@9858 | 657 | } |
apetushkov@9858 | 658 | if (!JfrMemorySizer::adjust_options(&options)) { |
apetushkov@9858 | 659 | if (!check_for_ambiguity(_dcmd_memorysize, _dcmd_globalbuffersize, _dcmd_numglobalbuffers)) { |
apetushkov@9858 | 660 | return false; |
apetushkov@9858 | 661 | } |
apetushkov@9858 | 662 | } |
apetushkov@9858 | 663 | post_process_adjusted_memory_options(options); |
apetushkov@9858 | 664 | return true; |
apetushkov@9858 | 665 | } |
apetushkov@9858 | 666 | |
apetushkov@9858 | 667 | bool JfrOptionSet::parse_flight_recorder_option(const JavaVMOption** option, char* delimiter) { |
apetushkov@9858 | 668 | assert(option != NULL, "invariant"); |
apetushkov@9858 | 669 | assert(delimiter != NULL, "invariant"); |
apetushkov@9858 | 670 | assert((*option)->optionString != NULL, "invariant"); |
apetushkov@9858 | 671 | assert(strncmp((*option)->optionString, "-XX:FlightRecorderOptions", 25) == 0, "invariant"); |
apetushkov@9858 | 672 | if (*delimiter == '\0') { |
apetushkov@9858 | 673 | // -XX:FlightRecorderOptions without any delimiter and values |
apetushkov@9858 | 674 | } else { |
apetushkov@9858 | 675 | // -XX:FlightRecorderOptions[=|:] |
apetushkov@9858 | 676 | // set delimiter to '=' |
apetushkov@9858 | 677 | *delimiter = '='; |
apetushkov@9858 | 678 | } |
apetushkov@9858 | 679 | return false; |
apetushkov@9858 | 680 | } |
apetushkov@9858 | 681 | |
apetushkov@9858 | 682 | static GrowableArray<const char*>* startup_recording_options_array = NULL; |
apetushkov@9858 | 683 | |
apetushkov@9858 | 684 | bool JfrOptionSet::parse_start_flight_recording_option(const JavaVMOption** option, char* delimiter) { |
apetushkov@9858 | 685 | assert(option != NULL, "invariant"); |
apetushkov@9858 | 686 | assert(delimiter != NULL, "invariant"); |
apetushkov@9858 | 687 | assert((*option)->optionString != NULL, "invariant"); |
apetushkov@9858 | 688 | assert(strncmp((*option)->optionString, "-XX:StartFlightRecording", 24) == 0, "invariant"); |
apetushkov@9858 | 689 | const char* value = NULL; |
apetushkov@9858 | 690 | if (*delimiter == '\0') { |
apetushkov@9858 | 691 | // -XX:StartFlightRecording without any delimiter and values |
apetushkov@9858 | 692 | // Add dummy value "dumponexit=false" so -XX:StartFlightRecording can be used without explicit values. |
apetushkov@9858 | 693 | // The existing option->optionString points to stack memory so no need to deallocate. |
apetushkov@9858 | 694 | const_cast<JavaVMOption*>(*option)->optionString = (char*)"-XX:StartFlightRecording=dumponexit=false"; |
apetushkov@9858 | 695 | value = (*option)->optionString + 25; |
apetushkov@9858 | 696 | } else { |
apetushkov@9858 | 697 | // -XX:StartFlightRecording[=|:] |
apetushkov@9858 | 698 | // set delimiter to '=' |
apetushkov@9858 | 699 | *delimiter = '='; |
apetushkov@9858 | 700 | value = delimiter + 1; |
apetushkov@9858 | 701 | } |
apetushkov@9858 | 702 | assert(value != NULL, "invariant"); |
apetushkov@9858 | 703 | const size_t value_length = strlen(value); |
apetushkov@9858 | 704 | |
apetushkov@9858 | 705 | if (startup_recording_options_array == NULL) { |
apetushkov@9858 | 706 | startup_recording_options_array = new (ResourceObj::C_HEAP, mtTracing) GrowableArray<const char*>(8, true, mtTracing); |
apetushkov@9858 | 707 | } |
apetushkov@9858 | 708 | assert(startup_recording_options_array != NULL, "invariant"); |
apetushkov@9858 | 709 | char* const startup_value = NEW_C_HEAP_ARRAY(char, value_length + 1, mtTracing); |
apetushkov@9858 | 710 | strncpy(startup_value, value, value_length + 1); |
apetushkov@9858 | 711 | assert(strncmp(startup_value, value, value_length) == 0, "invariant"); |
apetushkov@9858 | 712 | startup_recording_options_array->append(startup_value); |
apetushkov@9858 | 713 | return false; |
apetushkov@9858 | 714 | } |
apetushkov@9858 | 715 | |
apetushkov@9858 | 716 | const GrowableArray<const char*>* JfrOptionSet::startup_recording_options() { |
apetushkov@9858 | 717 | return startup_recording_options_array; |
apetushkov@9858 | 718 | } |
apetushkov@9858 | 719 | |
apetushkov@9858 | 720 | void JfrOptionSet::release_startup_recording_options() { |
apetushkov@9858 | 721 | if (startup_recording_options_array != NULL) { |
apetushkov@9858 | 722 | const int length = startup_recording_options_array->length(); |
apetushkov@9858 | 723 | for (int i = 0; i < length; ++i) { |
apetushkov@9858 | 724 | FREE_C_HEAP_ARRAY(char, startup_recording_options_array->at(i), mtTracing); |
apetushkov@9858 | 725 | } |
apetushkov@9858 | 726 | delete startup_recording_options_array; |
apetushkov@9858 | 727 | startup_recording_options_array = NULL; |
apetushkov@9858 | 728 | } |
apetushkov@9858 | 729 | } |