1 /*
2 * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
178 // - klass: 'java/lang/String' 0x0000000800010290
179 static Pattern instanceObjKlassPattern = Pattern.compile("^ - klass: '([^']+)' 0x([0-9a-f]+)");
180
181 // - klass: {type array byte} 0x00000008000024c8
182 static Pattern typeArrayKlassPattern = Pattern.compile("^ - klass: [{]type array ([a-z]+)[}] 0x([0-9a-f]+)");
183
184 // - klass: 'java/lang/Object'[] 0x00000008000013e0
185 static Pattern objArrayKlassPattern = Pattern.compile("^ - klass: ('[^']+'(\\[\\])+) 0x([0-9a-f]+)");
186
187 // - fields (3 words):
188 static Pattern fieldsWordsPattern = Pattern.compile("^ - fields [(]([0-9]+) words[)]:$");
189
190 // (one address)
191 // - final 'key' 'Ljava/lang/Object;' @16 0x00000007ffc68260 java.lang.String
192 static Pattern oopFieldPattern1 = Pattern.compile(" - [^']* '([^']+)'.*@([0-9]+) 0x([0-9a-f]+) (.*)");
193
194 // (two addresses)
195 // - final 'key' 'Ljava/lang/Object;' @16 0x00000007ffc68260 (0xfff8d04c) java.lang.String
196 static Pattern oopFieldPattern2 = Pattern.compile(" - [^']* '([^']+)'.*@([0-9]+) 0x([0-9a-f]+) [(]0x([0-9a-f]+)[)] (.*)");
197
198 // (injected module_entry)
199 // - injected 'module_entry' 'J' @16 0 (0x0000000000000000)
200 static Pattern moduleEntryPattern = Pattern.compile("- injected 'module_entry' 'J' @[0-9]+[ ]+([0-9]+)");
201
202 // -------------------------------------------------------------------------------
203 // Patterns for metaspace objects
204 // -------------------------------------------------------------------------------
205
206 // 0x00000008000d1698: @@ Class 512 [Ljdk.internal.vm.FillerElement;
207 // 0x00000008000d18a0: @@ Class 520 java.lang.Cloneable
208 static Pattern classPattern = Pattern.compile("^0x([0-9a-f]+): @@ Class [ ]*([0-9]+) (.*)");
209
210
211 private static Matcher match(String line, Pattern pattern) {
212 Matcher m = pattern.matcher(line);
213 if (m.find()) {
214 return m;
215 } else {
216 return null;
217 }
218 }
219
220 private static void parseHeapObject(String className, String oop, String narrowOop) throws IOException {
221 HeapObject heapObject = parseHeapObjectImpl(className, oop, narrowOop);
222 mapFile.add(heapObject);
223 }
224
225 private static HeapObject parseHeapObjectImpl(String className, String oop, String narrowOop) throws IOException {
226 HeapObject heapObject = new HeapObject(className, oop, narrowOop);
227 Matcher m;
228
229 nextLine();
230 while (line != null && match(line, rawDataPattern) != null) { // skip raw data
231 nextLine();
232 }
233
234 if (line == null || !line.startsWith(" - ")) {
235 return heapObject;
236 }
237
238 if ((m = match(line, instanceObjKlassPattern)) != null) {
239 heapObject.setKlass(m.group(1), m.group(2));
240 nextLine();
241 if ((m = match(line, fieldsWordsPattern)) == null) {
242 throw new RuntimeException("Expected field size info");
243 }
244 while (true) {
245 nextLine();
246 if (line == null || !line.startsWith(" - ")) {
247 return heapObject;
248 }
249 if (!line.contains("marked metadata pointer")) {
250 if ((m = match(line, oopFieldPattern2)) != null) {
251 heapObject.addOopField(m.group(1), m.group(2), m.group(3), m.group(4));
252 } else if ((m = match(line, oopFieldPattern1)) != null) {
253 heapObject.addOopField(m.group(1), m.group(2), m.group(3), null);
254 } else if ((m = match(line, moduleEntryPattern)) != null) {
255 String value = m.group(1);
256 if (!value.equals("0")) {
257 throw new RuntimeException("module_entry should be 0 but found: " + line);
258 }
259 }
260 }
261 }
262 } else if ((m = match(line, typeArrayKlassPattern)) != null) {
263 heapObject.setKlass(m.group(1), m.group(2));
264 // TODO: read all the array elements
265 while (true) {
266 nextLine();
267 if (line == null || !line.startsWith(" - ")) {
268 return heapObject;
269 }
270 }
271 } else if ((m = match(line, objArrayKlassPattern)) != null) {
272 heapObject.setKlass(m.group(1), m.group(3));
273 // TODO: read all the array elements
274 while (true) {
275 nextLine();
276 if (line == null || !line.startsWith(" - ")) {
277 return heapObject;
278 }
279 }
280 } else {
281 throw new RuntimeException("Expected klass info");
282 }
283 }
284
285 private static void parseClassObject(String className, String addr, String size) throws IOException {
286 mapFile.addClass(className);
287 nextLine();
288 }
289
290 static MapFile mapFile;
291 static BufferedReader reader;
292 static String line = null; // current line being parsed
293 static int lineCount = 0;
294 static String nextLine() throws IOException {
295 line = reader.readLine();
296 ++ lineCount;
297 return line;
298 }
|
1 /*
2 * Copyright (c) 2023, 2026, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
178 // - klass: 'java/lang/String' 0x0000000800010290
179 static Pattern instanceObjKlassPattern = Pattern.compile("^ - klass: '([^']+)' 0x([0-9a-f]+)");
180
181 // - klass: {type array byte} 0x00000008000024c8
182 static Pattern typeArrayKlassPattern = Pattern.compile("^ - klass: [{]type array ([a-z]+)[}] 0x([0-9a-f]+)");
183
184 // - klass: 'java/lang/Object'[] 0x00000008000013e0
185 static Pattern objArrayKlassPattern = Pattern.compile("^ - klass: ('[^']+'(\\[\\])+) 0x([0-9a-f]+)");
186
187 // - fields (3 words):
188 static Pattern fieldsWordsPattern = Pattern.compile("^ - fields [(]([0-9]+) words[)]:$");
189
190 // (one address)
191 // - final 'key' 'Ljava/lang/Object;' @16 0x00000007ffc68260 java.lang.String
192 static Pattern oopFieldPattern1 = Pattern.compile(" - [^']* '([^']+)'.*@([0-9]+) 0x([0-9a-f]+) (.*)");
193
194 // (two addresses)
195 // - final 'key' 'Ljava/lang/Object;' @16 0x00000007ffc68260 (0xfff8d04c) java.lang.String
196 static Pattern oopFieldPattern2 = Pattern.compile(" - [^']* '([^']+)'.*@([0-9]+) 0x([0-9a-f]+) [(]0x([0-9a-f]+)[)] (.*)");
197
198 // - Flat inline type element 'java/lang/Integer': - Index 1 offset 24:
199 // or
200 // - Flat inline type field 'java/lang/Integer':
201 static Pattern flatFieldPattern = Pattern.compile(" - Flat inline type field '([^']+)':\\s*(null)?\\s*$");
202 static Pattern flatElementPattern = Pattern.compile(" - Flat inline type element '([^']+)':\\s*- Index\\s+(\\d+)\\s+offset\\s+(\\d+):\\s*(null)?\\s*$");
203
204 static Pattern flatNullFreeFieldPattern = Pattern.compile(" - Flat inline null-free type field '([^']+)':\\s*$");
205 static Pattern flatNullFreeElementPattern = Pattern.compile(" - Flat inline null-free type element '([^']+)':\\s*- Index\\s+(\\d+)\\s+offset\\s+(\\d+):\\s*$");
206
207 static Pattern nullMarkerPattern = Pattern.compile(" - \\[null_marker\\] @[0-9]+ Field marked as (.*)");
208
209 // (injected module_entry)
210 // - injected 'module_entry' 'J' @16 0 (0x0000000000000000)
211 static Pattern moduleEntryPattern = Pattern.compile("- injected 'module_entry' 'J' @[0-9]+[ ]+([0-9]+)");
212
213 // -------------------------------------------------------------------------------
214 // Patterns for metaspace objects
215 // -------------------------------------------------------------------------------
216
217 // 0x00000008000d1698: @@ Class 512 [Ljdk.internal.vm.FillerElement;
218 // 0x00000008000d18a0: @@ Class 520 java.lang.Cloneable
219 static Pattern classPattern = Pattern.compile("^0x([0-9a-f]+): @@ Class [ ]*([0-9]+) (.*)");
220
221
222 private static Matcher match(String line, Pattern pattern) {
223 Matcher m = pattern.matcher(line);
224 if (m.find()) {
225 return m;
226 } else {
227 return null;
228 }
229 }
230
231 private static void parseHeapObject(String className, String oop, String narrowOop) throws IOException {
232 HeapObject heapObject = parseHeapObjectImpl(className, oop, narrowOop);
233 mapFile.add(heapObject);
234 }
235
236 private static void parseFlatNullFree(Matcher m) throws IOException {
237 if (line == null || !line.matches("^\s*-.*")) {
238 throw new RuntimeException("Malformed logging of flat field: " + line);
239 } else if ((m = match(line, flatFieldPattern)) != null) {
240 parseFlatField(m);
241 } else if ((m = match(line, flatElementPattern)) != null) {
242 parseFlatElement(m);
243 } else {
244 // Nested field
245 }
246 }
247
248 private static void parseFlatFieldOrElementHelper(Matcher m, String value) throws IOException {
249 nextLine();
250 while (line == null || (m = match(line, nullMarkerPattern)) == null) {
251 parseFlatNullFree(m);
252 nextLine();
253 }
254
255 String nullMarker = m.group(1);
256 if (nullMarker == null) {
257 throw new RuntimeException("missing null_marker: " + line);
258 } else {
259 nullMarker = nullMarker.replace(" ", "");
260 if (value.equals("null") != nullMarker.equals("null")) {
261 throw new RuntimeException("Incorrect null_marker value: " + value + " vs " + nullMarker);
262 }
263 }
264 }
265
266 private static void parseFlatElement(Matcher m) throws IOException {
267 String value = m.group(4);
268 if (value != null) {
269 value = value.replace(" ", ""); // Remove spaces
270 } else {
271 value = "";
272 }
273 parseFlatFieldOrElementHelper(m, value);
274 }
275
276 private static void parseFlatField(Matcher m) throws IOException {
277 String value = m.group(2);
278 if (value != null) {
279 value = value.replace(" ", ""); // Remove spaces
280 } else {
281 value = "";
282 }
283 parseFlatFieldOrElementHelper(m, value);
284 }
285
286 private static HeapObject parseHeapObjectImpl(String className, String oop, String narrowOop) throws IOException {
287 HeapObject heapObject = new HeapObject(className, oop, narrowOop);
288 Matcher m;
289
290 nextLine();
291 while (line != null && match(line, rawDataPattern) != null) { // skip raw data
292 nextLine();
293 }
294
295 if (line == null || !line.startsWith(" - ")) {
296 return heapObject;
297 }
298
299 if ((m = match(line, instanceObjKlassPattern)) != null) {
300 heapObject.setKlass(m.group(1), m.group(2));
301 nextLine();
302 if ((m = match(line, fieldsWordsPattern)) == null) {
303 throw new RuntimeException("Expected field size info");
304 }
305 while (true) {
306 nextLine();
307 if (line == null || !line.matches("^\s*-.*")) {
308 return heapObject;
309 }
310 if (!line.contains("marked metadata pointer")) {
311 if ((m = match(line, oopFieldPattern2)) != null) {
312 heapObject.addOopField(m.group(1), m.group(2), m.group(3), m.group(4));
313 } else if ((m = match(line, oopFieldPattern1)) != null) {
314 heapObject.addOopField(m.group(1), m.group(2), m.group(3), null);
315 } else if ((m = match(line, flatFieldPattern)) != null) {
316 parseFlatField(m);
317 } else if ((m = match(line, flatElementPattern)) != null) {
318 parseFlatElement(m);
319 } else if ((m = match(line, flatNullFreeFieldPattern)) != null ||
320 (m = match(line, flatNullFreeElementPattern)) != null) {
321 parseFlatNullFree(m);
322 } else if ((m = match(line, moduleEntryPattern)) != null) {
323 String value = m.group(1);
324 if (!value.equals("0")) {
325 throw new RuntimeException("module_entry should be 0 but found: " + line);
326 }
327 }
328 }
329 }
330 } else if ((m = match(line, typeArrayKlassPattern)) != null) {
331 heapObject.setKlass(m.group(1), m.group(2));
332 // TODO: read all the array elements
333 while (true) {
334 nextLine();
335 if (line == null || !line.startsWith(" - ")) {
336 return heapObject;
337 }
338 }
339 } else if ((m = match(line, objArrayKlassPattern)) != null) {
340 heapObject.setKlass(m.group(1), m.group(3));
341 // TODO: read all the array elements
342 while (true) {
343 nextLine();
344 if (line == null || !line.matches("^\s*-.*")) { // Check for "-" with leading spaces
345 return heapObject;
346 }
347
348 if ((m = match(line, flatElementPattern)) != null) {
349 parseFlatElement(m);
350 } else if ((m = match(line, flatNullFreeElementPattern)) != null) {
351 parseFlatNullFree(m);
352 }
353 }
354 } else {
355 throw new RuntimeException("Expected klass info");
356 }
357 }
358
359 private static void parseClassObject(String className, String addr, String size) throws IOException {
360 mapFile.addClass(className);
361 nextLine();
362 }
363
364 static MapFile mapFile;
365 static BufferedReader reader;
366 static String line = null; // current line being parsed
367 static int lineCount = 0;
368 static String nextLine() throws IOException {
369 line = reader.readLine();
370 ++ lineCount;
371 return line;
372 }
|