|
1 | 1 | /*
|
2 |
| - * Copyright (c) 2018, 2021, Oracle and/or its affiliates. All rights reserved. |
| 2 | + * Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved. |
3 | 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
4 | 4 | *
|
5 | 5 | * This code is free software; you can redistribute it and/or modify it
|
|
28 | 28 | import java.io.FileNotFoundException;
|
29 | 29 | import java.io.IOException;
|
30 | 30 | import java.io.PrintWriter;
|
| 31 | +import java.math.BigInteger; |
31 | 32 | import java.nio.file.Path;
|
32 | 33 | import java.util.ArrayList;
|
33 | 34 | import java.util.HashMap;
|
|
38 | 39 | import jdk.jfr.EventType;
|
39 | 40 | import jdk.jfr.Timespan;
|
40 | 41 | import jdk.jfr.Timestamp;
|
| 42 | +import jdk.jfr.Unsigned; |
41 | 43 | import jdk.jfr.ValueDescriptor;
|
42 | 44 | import jdk.jfr.consumer.RecordedEvent;
|
43 | 45 | import jdk.jfr.consumer.RecordedObject;
|
|
47 | 49 | abstract class EventPrintWriter extends StructuredWriter {
|
48 | 50 |
|
49 | 51 | enum ValueType {
|
50 |
| - TIMESPAN, TIMESTAMP, OTHER |
| 52 | + TIMESPAN, TIMESTAMP, UNSIGNED, OTHER |
51 | 53 | }
|
52 | 54 |
|
53 | 55 | protected static final String STACK_TRACE_FIELD = "stackTrace";
|
@@ -118,23 +120,44 @@ protected Object getValue(RecordedObject object, ValueDescriptor v) {
|
118 | 120 | valueType = determineValueType(v);
|
119 | 121 | typeOfValues.put(v, valueType);
|
120 | 122 | }
|
121 |
| - switch (valueType) { |
122 |
| - case TIMESPAN: |
123 |
| - return object.getDuration(v.getName()); |
124 |
| - case TIMESTAMP: |
125 |
| - return PRIVATE_ACCESS.getOffsetDataTime(object, v.getName()); |
126 |
| - default: |
127 |
| - return object.getValue(v.getName()); |
| 123 | + String name = v.getName(); |
| 124 | + return switch (valueType) { |
| 125 | + case TIMESPAN -> object.getDuration(name); |
| 126 | + case TIMESTAMP -> PRIVATE_ACCESS.getOffsetDataTime(object, name); |
| 127 | + case UNSIGNED -> getUnsigned(object, name); |
| 128 | + case OTHER -> object.getValue(name); |
| 129 | + }; |
| 130 | + } |
| 131 | + |
| 132 | + private Object getUnsigned(RecordedObject object, String name) { |
| 133 | + // RecordedObject::getLong handles unsigned byte, short, int |
| 134 | + long value = object.getLong(name); |
| 135 | + // If unsigned long value exceeds 2^63, return (upper << 32) + lower |
| 136 | + if (value < 0) { |
| 137 | + int upper = (int) (value >>> 32); |
| 138 | + int lower = (int) value; |
| 139 | + BigInteger u = BigInteger.valueOf(Integer.toUnsignedLong(upper)); |
| 140 | + u = u.shiftLeft(32); |
| 141 | + BigInteger l = BigInteger.valueOf(Integer.toUnsignedLong(lower)); |
| 142 | + return u.add(l); |
128 | 143 | }
|
| 144 | + return Long.valueOf(value); |
129 | 145 | }
|
130 |
| - // It's expensive t check |
| 146 | + |
| 147 | + // Somewhat expensive operation |
131 | 148 | private ValueType determineValueType(ValueDescriptor v) {
|
132 | 149 | if (v.getAnnotation(Timespan.class) != null) {
|
133 | 150 | return ValueType.TIMESPAN;
|
134 | 151 | }
|
135 | 152 | if (v.getAnnotation(Timestamp.class) != null) {
|
136 | 153 | return ValueType.TIMESTAMP;
|
137 | 154 | }
|
| 155 | + if (v.getAnnotation(Unsigned.class) != null) { |
| 156 | + return switch(v.getTypeName()) { |
| 157 | + case "byte", "short", "int", "long" -> ValueType.UNSIGNED; |
| 158 | + default -> ValueType.OTHER; |
| 159 | + }; |
| 160 | + } |
138 | 161 | return ValueType.OTHER;
|
139 | 162 | }
|
140 | 163 | }
|
0 commit comments