src/share/vm/jfr/recorder/service/jfrOptionSet.cpp

Fri, 23 Nov 2018 16:36:07 +0900

author
ysuenaga
date
Fri, 23 Nov 2018 16:36:07 +0900
changeset 9870
830105382dbd
parent 9858
b985cbb00e68
child 9925
30fb8c8cceb9
permissions
-rw-r--r--

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 }

mercurial