annotate src/share/vm/services/diagnosticArgument.cpp @ 3465:d2a62e0f25eb

6995781: Native Memory Tracking (Phase 1) 7151532: DCmd for hotspot native memory tracking Summary: Implementation of native memory tracking phase 1, which tracks VM native memory usage, and related DCmd Reviewed-by: acorn, coleenp, fparain
author zgu
date Thu, 28 Jun 2012 17:03:16 -0400
parents 51612f0c0a79
children 79f492f184d0 203f64878aab
rev   line source
fparain@2894 1 /*
fparain@3041 2 * Copyright (c) 2011, 2012 Oracle and/or its affiliates. All rights reserved.
fparain@2894 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
fparain@2894 4 *
fparain@2894 5 * This code is free software; you can redistribute it and/or modify it
fparain@2894 6 * under the terms of the GNU General Public License version 2 only, as
fparain@2894 7 * published by the Free Software Foundation.
fparain@2894 8 *
fparain@2894 9 * This code is distributed in the hope that it will be useful, but WITHOUT
fparain@2894 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
fparain@2894 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
fparain@2894 12 * version 2 for more details (a copy is included in the LICENSE file that
fparain@2894 13 * accompanied this code).
fparain@2894 14 *
fparain@2894 15 * You should have received a copy of the GNU General Public License version
fparain@2894 16 * 2 along with this work; if not, write to the Free Software Foundation,
fparain@2894 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
fparain@2894 18 *
fparain@2894 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
fparain@2894 20 * or visit www.oracle.com if you need additional information or have any
fparain@2894 21 * questions.
fparain@2894 22 *
fparain@2894 23 */
fparain@2894 24
fparain@2894 25 #include "precompiled.hpp"
fparain@2894 26 #include "memory/allocation.inline.hpp"
fparain@2894 27 #include "runtime/thread.hpp"
fparain@2894 28 #include "services/diagnosticArgument.hpp"
fparain@2894 29
fparain@2894 30 void GenDCmdArgument::read_value(const char* str, size_t len, TRAPS) {
fparain@3124 31 /* NOTE:Some argument types doesn't require a value,
fparain@3124 32 * for instance boolean arguments: "enableFeatureX". is
fparain@3124 33 * equivalent to "enableFeatureX=true". In these cases,
fparain@3124 34 * str will be null. This is perfectly valid.
fparain@3124 35 * All argument types must perform null checks on str.
fparain@3124 36 */
fparain@3124 37
fparain@3124 38 if (is_set() && !allow_multiple()) {
fparain@2894 39 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
fparain@3124 40 "Duplicates in diagnostic command arguments\n");
fparain@2894 41 }
fparain@2894 42 parse_value(str, len, CHECK);
fparain@2894 43 set_is_set(true);
fparain@2894 44 }
fparain@2894 45
nloodin@3246 46 void GenDCmdArgument::to_string(jlong l, char* buf, size_t len) {
nloodin@3246 47 jio_snprintf(buf, len, INT64_FORMAT, l);
nloodin@3246 48 }
nloodin@3246 49
nloodin@3246 50 void GenDCmdArgument::to_string(bool b, char* buf, size_t len) {
nloodin@3246 51 jio_snprintf(buf, len, b ? "true" : "false");
nloodin@3246 52 }
nloodin@3246 53
nloodin@3246 54 void GenDCmdArgument::to_string(NanoTimeArgument n, char* buf, size_t len) {
nloodin@3246 55 jio_snprintf(buf, len, INT64_FORMAT, n._nanotime);
nloodin@3246 56 }
nloodin@3246 57
nloodin@3246 58 void GenDCmdArgument::to_string(MemorySizeArgument m, char* buf, size_t len) {
nloodin@3246 59 jio_snprintf(buf, len, INT64_FORMAT, m._size);
nloodin@3246 60 }
nloodin@3246 61
nloodin@3246 62 void GenDCmdArgument::to_string(char* c, char* buf, size_t len) {
nloodin@3246 63 jio_snprintf(buf, len, "%s", c);
nloodin@3246 64 }
nloodin@3246 65
nloodin@3246 66 void GenDCmdArgument::to_string(StringArrayArgument* f, char* buf, size_t len) {
nloodin@3246 67 int length = f->array()->length();
nloodin@3246 68 size_t written = 0;
nloodin@3246 69 buf[0] = 0;
nloodin@3246 70 for (int i = 0; i < length; i++) {
nloodin@3246 71 char* next_str = f->array()->at(i);
nloodin@3246 72 size_t next_size = strlen(next_str);
nloodin@3246 73 //Check if there's room left to write next element
nloodin@3246 74 if (written + next_size > len) {
nloodin@3246 75 return;
nloodin@3246 76 }
nloodin@3246 77 //Actually write element
nloodin@3246 78 strcat(buf, next_str);
nloodin@3246 79 written += next_size;
nloodin@3246 80 //Check if there's room left for the comma
nloodin@3246 81 if (i < length-1 && len - written > 0) {
nloodin@3246 82 strcat(buf, ",");
nloodin@3246 83 }
nloodin@3246 84 }
nloodin@3246 85 }
nloodin@3246 86
fparain@2894 87 template <> void DCmdArgument<jlong>::parse_value(const char* str,
fparain@2894 88 size_t len, TRAPS) {
fparain@3124 89 if (str == NULL || sscanf(str, INT64_FORMAT, &_value) != 1) {
fparain@2894 90 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
fparain@3124 91 "Integer parsing error in diagnostic command arguments\n");
fparain@2894 92 }
fparain@2894 93 }
fparain@2894 94
fparain@2894 95 template <> void DCmdArgument<jlong>::init_value(TRAPS) {
fparain@2894 96 if (has_default()) {
fparain@2894 97 this->parse_value(_default_string, strlen(_default_string), THREAD);
fparain@2894 98 if (HAS_PENDING_EXCEPTION) {
fparain@2894 99 fatal("Default string must be parsable");
fparain@2894 100 }
fparain@2894 101 } else {
fparain@2894 102 set_value(0);
fparain@2894 103 }
fparain@2894 104 }
fparain@2894 105
fparain@2894 106 template <> void DCmdArgument<jlong>::destroy_value() { }
fparain@2894 107
fparain@2894 108 template <> void DCmdArgument<bool>::parse_value(const char* str,
fparain@2894 109 size_t len, TRAPS) {
fparain@3041 110 // len is the length of the current token starting at str
fparain@2894 111 if (len == 0) {
fparain@2894 112 set_value(true);
fparain@2894 113 } else {
fparain@3041 114 if (len == strlen("true") && strncasecmp(str, "true", len) == 0) {
fparain@2894 115 set_value(true);
fparain@3041 116 } else if (len == strlen("false") && strncasecmp(str, "false", len) == 0) {
fparain@2894 117 set_value(false);
fparain@2894 118 } else {
fparain@2894 119 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
fparain@2894 120 "Boolean parsing error in diagnostic command arguments");
fparain@2894 121 }
fparain@2894 122 }
fparain@2894 123 }
fparain@2894 124
fparain@2894 125 template <> void DCmdArgument<bool>::init_value(TRAPS) {
fparain@2894 126 if (has_default()) {
fparain@2894 127 this->parse_value(_default_string, strlen(_default_string), THREAD);
fparain@2894 128 if (HAS_PENDING_EXCEPTION) {
fparain@2894 129 fatal("Default string must be parsable");
fparain@2894 130 }
fparain@2894 131 } else {
fparain@2894 132 set_value(false);
fparain@2894 133 }
fparain@2894 134 }
fparain@2894 135
fparain@2894 136 template <> void DCmdArgument<bool>::destroy_value() { }
fparain@2894 137
fparain@2894 138 template <> void DCmdArgument<char*>::parse_value(const char* str,
fparain@2894 139 size_t len, TRAPS) {
fparain@3124 140 if (str == NULL) {
fparain@3124 141 _value = NULL;
fparain@3124 142 } else {
zgu@3465 143 _value = NEW_C_HEAP_ARRAY(char, len+1, mtInternal);
fparain@3124 144 strncpy(_value, str, len);
fparain@3124 145 _value[len] = 0;
fparain@3124 146 }
fparain@2894 147 }
fparain@2894 148
fparain@2894 149 template <> void DCmdArgument<char*>::init_value(TRAPS) {
fparain@3124 150 if (has_default() && _default_string != NULL) {
fparain@2894 151 this->parse_value(_default_string, strlen(_default_string), THREAD);
fparain@2894 152 if (HAS_PENDING_EXCEPTION) {
fparain@3124 153 fatal("Default string must be parsable");
fparain@2894 154 }
fparain@2894 155 } else {
fparain@2894 156 set_value(NULL);
fparain@2894 157 }
fparain@2894 158 }
fparain@2894 159
fparain@2894 160 template <> void DCmdArgument<char*>::destroy_value() {
fparain@2894 161 if (_value != NULL) {
zgu@3465 162 FREE_C_HEAP_ARRAY(char, _value, mtInternal);
fparain@2894 163 set_value(NULL);
fparain@2894 164 }
fparain@2894 165 }
fparain@3124 166
fparain@3124 167 template <> void DCmdArgument<NanoTimeArgument>::parse_value(const char* str,
fparain@3124 168 size_t len, TRAPS) {
fparain@3124 169 if (str == NULL) {
fparain@3124 170 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
fparain@3124 171 "Integer parsing error nanotime value: syntax error");
fparain@3124 172 }
fparain@3124 173
fparain@3124 174 int argc = sscanf(str, INT64_FORMAT , &_value._time);
fparain@3124 175 if (argc != 1) {
fparain@3124 176 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
fparain@3124 177 "Integer parsing error nanotime value: syntax error");
fparain@3124 178 }
fparain@3124 179 size_t idx = 0;
fparain@3124 180 while(idx < len && isdigit(str[idx])) {
fparain@3124 181 idx++;
fparain@3124 182 }
fparain@3124 183 if (idx == len) {
fparain@3124 184 // only accept missing unit if the value is 0
fparain@3124 185 if (_value._time != 0) {
fparain@3124 186 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
fparain@3124 187 "Integer parsing error nanotime value: unit required");
fparain@3124 188 } else {
fparain@3124 189 _value._nanotime = 0;
fparain@3124 190 strcpy(_value._unit, "ns");
fparain@3124 191 return;
fparain@3124 192 }
fparain@3124 193 } else if(len - idx > 2) {
fparain@3124 194 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
fparain@3124 195 "Integer parsing error nanotime value: illegal unit");
fparain@3124 196 } else {
fparain@3124 197 strncpy(_value._unit, &str[idx], len - idx);
fparain@3124 198 /*Write an extra null termination. This is safe because _value._unit
fparain@3124 199 * is declared as char[3], and length is checked to be not larger than
fparain@3124 200 * two above. Also, this is necessary, since length might be 1, and the
fparain@3124 201 * default value already in the string is ns, which is two chars.
fparain@3124 202 */
fparain@3124 203 _value._unit[len-idx] = '\0';
fparain@3124 204 }
fparain@3124 205
fparain@3124 206 if (strcmp(_value._unit, "ns") == 0) {
fparain@3124 207 _value._nanotime = _value._time;
fparain@3124 208 } else if (strcmp(_value._unit, "us") == 0) {
fparain@3124 209 _value._nanotime = _value._time * 1000;
fparain@3124 210 } else if (strcmp(_value._unit, "ms") == 0) {
fparain@3124 211 _value._nanotime = _value._time * 1000 * 1000;
fparain@3124 212 } else if (strcmp(_value._unit, "s") == 0) {
fparain@3124 213 _value._nanotime = _value._time * 1000 * 1000 * 1000;
fparain@3124 214 } else if (strcmp(_value._unit, "m") == 0) {
fparain@3124 215 _value._nanotime = _value._time * 60 * 1000 * 1000 * 1000;
fparain@3124 216 } else if (strcmp(_value._unit, "h") == 0) {
fparain@3124 217 _value._nanotime = _value._time * 60 * 60 * 1000 * 1000 * 1000;
fparain@3124 218 } else if (strcmp(_value._unit, "d") == 0) {
fparain@3124 219 _value._nanotime = _value._time * 24 * 60 * 60 * 1000 * 1000 * 1000;
fparain@3124 220 } else {
fparain@3124 221 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
fparain@3124 222 "Integer parsing error nanotime value: illegal unit");
fparain@3124 223 }
fparain@3124 224 }
fparain@3124 225
fparain@3124 226 template <> void DCmdArgument<NanoTimeArgument>::init_value(TRAPS) {
fparain@3124 227 if (has_default()) {
fparain@3124 228 this->parse_value(_default_string, strlen(_default_string), THREAD);
fparain@3124 229 if (HAS_PENDING_EXCEPTION) {
fparain@3124 230 fatal("Default string must be parsable");
fparain@3124 231 }
fparain@3124 232 } else {
fparain@3124 233 _value._time = 0;
fparain@3124 234 _value._nanotime = 0;
fparain@3124 235 strcmp(_value._unit, "ns");
fparain@3124 236 }
fparain@3124 237 }
fparain@3124 238
fparain@3124 239 template <> void DCmdArgument<NanoTimeArgument>::destroy_value() { }
fparain@3124 240
fparain@3124 241 // WARNING StringArrayArgument can only be used as an option, it cannot be
fparain@3124 242 // used as an argument with the DCmdParser
fparain@3124 243
fparain@3124 244 template <> void DCmdArgument<StringArrayArgument*>::parse_value(const char* str,
fparain@3124 245 size_t len, TRAPS) {
fparain@3124 246 _value->add(str,len);
fparain@3124 247 }
fparain@3124 248
fparain@3124 249 template <> void DCmdArgument<StringArrayArgument*>::init_value(TRAPS) {
fparain@3124 250 _value = new StringArrayArgument();
fparain@3124 251 _allow_multiple = true;
fparain@3124 252 if (has_default()) {
fparain@3124 253 fatal("StringArrayArgument cannot have default value");
fparain@3124 254 }
fparain@3124 255 }
fparain@3124 256
fparain@3124 257 template <> void DCmdArgument<StringArrayArgument*>::destroy_value() {
fparain@3124 258 if (_value != NULL) {
fparain@3124 259 delete _value;
fparain@3124 260 set_value(NULL);
fparain@3124 261 }
fparain@3124 262 }
fparain@3124 263
fparain@3124 264 template <> void DCmdArgument<MemorySizeArgument>::parse_value(const char* str,
fparain@3124 265 size_t len, TRAPS) {
fparain@3124 266 if (str == NULL) {
fparain@3124 267 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
fparain@3124 268 "Integer parsing error nanotime value: syntax error");
fparain@3124 269 }
fparain@3124 270
fparain@3124 271 if (*str == '-') {
fparain@3124 272 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
fparain@3124 273 "Parsing error memory size value: negative values not allowed");
fparain@3124 274 }
fparain@3124 275 int res = sscanf(str, UINT64_FORMAT "%c", &_value._val, &_value._multiplier);
fparain@3124 276 if (res == 2) {
fparain@3124 277 switch (_value._multiplier) {
fparain@3124 278 case 'k': case 'K':
fparain@3124 279 _value._size = _value._val * 1024;
fparain@3124 280 break;
fparain@3124 281 case 'm': case 'M':
fparain@3124 282 _value._size = _value._val * 1024 * 1024;
fparain@3124 283 break;
fparain@3124 284 case 'g': case 'G':
fparain@3124 285 _value._size = _value._val * 1024 * 1024 * 1024;
fparain@3124 286 break;
fparain@3124 287 default:
fparain@3124 288 _value._size = _value._val;
fparain@3124 289 _value._multiplier = ' ';
fparain@3124 290 //default case should be to break with no error, since user
fparain@3124 291 //can write size in bytes, or might have a delimiter and next arg
fparain@3124 292 break;
fparain@3124 293 }
fparain@3124 294 } else if (res == 1) {
fparain@3124 295 _value._size = _value._val;
fparain@3124 296 } else {
fparain@3124 297 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
fparain@3124 298 "Parsing error memory size value: invalid value");
fparain@3124 299 }
fparain@3124 300 }
fparain@3124 301
fparain@3124 302 template <> void DCmdArgument<MemorySizeArgument>::init_value(TRAPS) {
fparain@3124 303 if (has_default()) {
fparain@3124 304 this->parse_value(_default_string, strlen(_default_string), THREAD);
fparain@3124 305 if (HAS_PENDING_EXCEPTION) {
fparain@3124 306 fatal("Default string must be parsable");
fparain@3124 307 }
fparain@3124 308 } else {
fparain@3124 309 _value._size = 0;
fparain@3124 310 _value._val = 0;
fparain@3124 311 _value._multiplier = ' ';
fparain@3124 312 }
fparain@3124 313 }
fparain@3124 314
fparain@3124 315 template <> void DCmdArgument<MemorySizeArgument>::destroy_value() { }