24
24
import java .io .BufferedReader ;
25
25
import java .io .FileReader ;
26
26
import java .io .IOException ;
27
- import java .io .RandomAccessFile ;
28
27
import java .util .ArrayList ;
29
28
import java .util .HashMap ;
30
29
import java .util .regex .Matcher ;
31
30
import java .util .regex .Pattern ;
32
31
33
- // This is a simple parser for parsing the output of
34
- //
35
- // java -Xshare:dump -Xlog:cds+map=debug,cds+map+oops=trace:file=cds.map:none:filesize=0
36
- //
37
- // Currently it just check the output related to JDK-8308903.
38
- // I.e., each oop fields in the HeapObjects must point to a valid HeapObject.
39
- //
40
- // It can be extended to check for the other parts of the map file, or perform
41
- // more analysis on the HeapObjects.
32
+ /*
33
+
34
+ This is a simple parser for parsing the output of
35
+
36
+ java -Xshare:dump -Xlog:cds+map=debug,cds+map+oops=trace:file=cds.map:none:filesize=0
37
+
38
+ The map file contains patterns like this for the heap objects:
39
+
40
+ ======================================================================
41
+ 0x00000000ffe00000: @@ Object (0xffe00000) java.lang.String
42
+ - klass: 'java/lang/String' 0x0000000800010220
43
+ - fields (3 words):
44
+ - private 'hash' 'I' @12 0 (0x00000000)
45
+ - private final 'coder' 'B' @16 0 (0x00)
46
+ - private 'hashIsZero' 'Z' @17 true (0x01)
47
+ - injected 'flags' 'B' @18 1 (0x01)
48
+ - private final 'value' '[B' @20 0x00000000ffe00018 (0xffe00018) [B length: 0
49
+ 0x00000000ffe00018: @@ Object (0xffe00018) [B length: 0
50
+ - klass: {type array byte} 0x00000008000024d8
51
+ ======================================================================
52
+
53
+ Currently this parser just check the output related to JDK-8308903.
54
+ I.e., each oop field must point to a valid HeapObject. For example, the 'value' field
55
+ in the String must point to a valid byte array.
56
+
57
+ This parser can be extended to check for the other parts of the map file, or perform
58
+ more analysis on the HeapObjects.
59
+
60
+ */
61
+
42
62
public class CDSMapReader {
43
63
public static class MapFile {
44
64
ArrayList <HeapObject > heapObjects = new ArrayList <>();
45
65
HashMap <Long , HeapObject > oopToObject = new HashMap <>();
46
66
HashMap <Long , HeapObject > narrowOopToObject = new HashMap <>();
67
+ public int stringCount = 0 ;
47
68
48
69
void add (HeapObject heapObject ) {
49
70
heapObjects .add (heapObject );
50
71
oopToObject .put (heapObject .address .oop , heapObject );
51
72
if (heapObject .address .narrowOop != 0 ) {
52
73
narrowOopToObject .put (heapObject .address .narrowOop , heapObject );
53
74
}
75
+ if (heapObject .className .equals ("java.lang.String" )) {
76
+ stringCount ++;
77
+ }
54
78
}
55
79
56
80
public int heapObjectCount () {
@@ -184,7 +208,6 @@ private static HeapObject parseHeapObjectImpl(String className, String oop, Stri
184
208
if ((m = match (line , fieldsWordsPattern )) == null ) {
185
209
throw new RuntimeException ("Expected field size info" );
186
210
}
187
- // TODO: read all the array elements
188
211
while (true ) {
189
212
nextLine ();
190
213
if (line == null || !line .startsWith (" - " )) {
@@ -233,6 +256,7 @@ static String nextLine() throws IOException {
233
256
234
257
public static MapFile read (String fileName ) {
235
258
mapFile = new MapFile ();
259
+ lineCount = 0 ;
236
260
237
261
try (BufferedReader r = new BufferedReader (new FileReader (fileName ))) {
238
262
reader = r ;
@@ -254,7 +278,8 @@ public static MapFile read(String fileName) {
254
278
throw new RuntimeException (t );
255
279
} finally {
256
280
System .out .println ("Parsed " + lineCount + " lines in " + fileName );
257
- System .out .println ("Found " + mapFile .heapObjectCount () + " heap objects" );
281
+ System .out .println ("Found " + mapFile .heapObjectCount () + " heap objects ("
282
+ + mapFile .stringCount + " strings)" );
258
283
mapFile = null ;
259
284
reader = null ;
260
285
line = null ;
@@ -270,8 +295,9 @@ private static void mustContain(HashMap<Long, HeapObject> allObjects, Field fiel
270
295
}
271
296
272
297
// Check that each oop fields in the HeapObjects must point to a valid HeapObject.
273
- public static int validate (MapFile mapFile ) {
274
- int count = 0 ;
298
+ public static void validate (MapFile mapFile ) {
299
+ int count1 = 0 ;
300
+ int count2 = 0 ;
275
301
for (HeapObject heapObject : mapFile .heapObjects ) {
276
302
if (heapObject .fields != null ) {
277
303
for (Field field : heapObject .fields ) {
@@ -281,17 +307,32 @@ public static int validate(MapFile mapFile) {
281
307
// Is this test actually doing something?
282
308
// To see how an invalidate pointer may be found, change oop in the
283
309
// following line to oop+1
284
- mustContain (mapFile .oopToObject , field , oop , false );
285
- count ++;
310
+ if (oop != 0 ) {
311
+ mustContain (mapFile .oopToObject , field , oop , false );
312
+ count1 ++;
313
+ }
286
314
if (narrowOop != 0 ) {
287
315
mustContain (mapFile .narrowOopToObject , field , narrowOop , true );
288
- count ++;
316
+ count2 ++;
289
317
}
290
318
}
291
319
}
292
320
}
293
- System .out .println ("Checked " + count + " oop field references" );
294
- return count ;
321
+ System .out .println ("Found " + count1 + " non-null oop field references (normal)" );
322
+ System .out .println ("Found " + count2 + " non-null oop field references (narrow)" );
323
+
324
+ if (mapFile .heapObjectCount () > 0 ) {
325
+ // heapObjectCount() may be zero if the selected GC doesn't support heap object archiving.
326
+ if (mapFile .stringCount <= 0 ) {
327
+ throw new RuntimeException ("CDS map file should contain at least one string" );
328
+ }
329
+ if (count1 < mapFile .stringCount ) {
330
+ throw new RuntimeException ("CDS map file seems incorrect: " + mapFile .heapObjectCount () +
331
+ " objects (" + mapFile .stringCount + " strings). Each string should" +
332
+ " have one non-null oop field but we found only " + count1 +
333
+ " non-null oop field references" );
334
+ }
335
+ }
295
336
}
296
337
297
338
public static void main (String args []) {
0 commit comments