src/jdk.jfr/share/classes/jdk/jfr/consumer/RecordedObject.java
branchJEP-349-branch
changeset 57460 bcbc53560c77
parent 57452 6fabe73e5d9a
child 58145 bc54ed8d908a
equal deleted inserted replaced
57459:df39f8d8f4d6 57460:bcbc53560c77
    94             return o;
    94             return o;
    95         }
    95         }
    96     }
    96     }
    97 
    97 
    98     final Object[] objects;
    98     final Object[] objects;
    99     protected final List<ValueDescriptor> descriptors;
    99     final ObjectContext objectContext;
   100     protected final TimeConverter timeConverter;
       
   101 
   100 
   102     // package private, not to be subclassed outside this package
   101     // package private, not to be subclassed outside this package
   103     RecordedObject(List<ValueDescriptor> descriptors, Object[] objects, TimeConverter timeConverter) {
   102     RecordedObject(ObjectContext objectContext, Object[] objects) {
   104         this.descriptors = descriptors;
   103         this.objectContext = objectContext;
   105         this.objects = objects;
   104         this.objects = objects;
   106         this.timeConverter = timeConverter;
       
   107     }
   105     }
   108 
   106 
   109     // package private
   107     // package private
   110     final <T> T getTyped(String name, Class<T> clazz, T defaultValue) {
   108     final <T> T getTyped(String name, Class<T> clazz, T defaultValue) {
   111         // Unnecessary to check field presence twice, but this
   109         // Unnecessary to check field presence twice, but this
   131      *
   129      *
   132      * @see #getFields()
   130      * @see #getFields()
   133      */
   131      */
   134     public boolean hasField(String name) {
   132     public boolean hasField(String name) {
   135         Objects.requireNonNull(name);
   133         Objects.requireNonNull(name);
   136         for (ValueDescriptor v : descriptors) {
   134         for (ValueDescriptor v : objectContext.fields) {
   137             if (v.getName().equals(name)) {
   135             if (v.getName().equals(name)) {
   138                 return true;
   136                 return true;
   139             }
   137             }
   140         }
   138         }
   141         int dotIndex = name.indexOf(".");
   139         int dotIndex = name.indexOf(".");
   142         if (dotIndex > 0) {
   140         if (dotIndex > 0) {
   143             String structName = name.substring(0, dotIndex);
   141             String structName = name.substring(0, dotIndex);
   144             for (ValueDescriptor v : descriptors) {
   142             for (ValueDescriptor v : objectContext.fields) {
   145                 if (!v.getFields().isEmpty() && v.getName().equals(structName)) {
   143                 if (!v.getFields().isEmpty() && v.getName().equals(structName)) {
   146                     RecordedObject child = getValue(structName);
   144                     RecordedObject child = getValue(structName);
   147                     if (child != null) {
   145                     if (child != null) {
   148                         return child.hasField(name.substring(dotIndex + 1));
   146                         return child.hasField(name.substring(dotIndex + 1));
   149                     }
   147                     }
   206     }
   204     }
   207 
   205 
   208     private Object getValue(String name, boolean allowUnsigned) {
   206     private Object getValue(String name, boolean allowUnsigned) {
   209         Objects.requireNonNull(name);
   207         Objects.requireNonNull(name);
   210         int index = 0;
   208         int index = 0;
   211         for (ValueDescriptor v : descriptors) {
   209         for (ValueDescriptor v : objectContext.fields) {
   212             if (name.equals(v.getName())) {
   210             if (name.equals(v.getName())) {
   213                 Object object = objectAt(index);
   211                 Object object = objectAt(index);
   214                 if (object == null) {
   212                 if (object == null) {
   215                     // error or missing
   213                     // error or missing
   216                     return null;
   214                     return null;
   234                     if (v.isArray()) {
   232                     if (v.isArray()) {
   235                         // struct array
   233                         // struct array
   236                         return structifyArray(v, array, 0);
   234                         return structifyArray(v, array, 0);
   237                     }
   235                     }
   238                     // struct
   236                     // struct
   239                     return new RecordedObject(v.getFields(), (Object[]) object, timeConverter);
   237                     return new RecordedObject(objectContext.getInstance(v), (Object[]) object);
   240                 }
   238                 }
   241             }
   239             }
   242             index++;
   240             index++;
   243         }
   241         }
   244 
   242 
   245         int dotIndex = name.indexOf(".");
   243         int dotIndex = name.indexOf(".");
   246         if (dotIndex > 0) {
   244         if (dotIndex > 0) {
   247             String structName = name.substring(0, dotIndex);
   245             String structName = name.substring(0, dotIndex);
   248             for (ValueDescriptor v : descriptors) {
   246             for (ValueDescriptor v : objectContext.fields) {
   249                 if (!v.getFields().isEmpty() && v.getName().equals(structName)) {
   247                 if (!v.getFields().isEmpty() && v.getName().equals(structName)) {
   250                     RecordedObject child = getValue(structName);
   248                     RecordedObject child = getValue(structName);
   251                     String subName = name.substring(dotIndex + 1);
   249                     String subName = name.substring(dotIndex + 1);
   252                     if (child != null) {
   250                     if (child != null) {
   253                         return child.getValue(subName, allowUnsigned);
   251                         return child.getValue(subName, allowUnsigned);
   295     // This is to prevent a call to getString on a thread field, that is
   293     // This is to prevent a call to getString on a thread field, that is
   296     // null to succeed.
   294     // null to succeed.
   297     private <T> T getTypedValue(String name, String typeName) {
   295     private <T> T getTypedValue(String name, String typeName) {
   298         Objects.requireNonNull(name);
   296         Objects.requireNonNull(name);
   299         // Validate name and type first
   297         // Validate name and type first
   300         getValueDescriptor(descriptors, name, typeName);
   298         getValueDescriptor(objectContext.fields, name, typeName);
   301         return getValue(name);
   299         return getValue(name);
   302     }
   300     }
   303 
   301 
   304     private Object[] structifyArray(ValueDescriptor v, Object[] array, int dimension) {
   302     private Object[] structifyArray(ValueDescriptor v, Object[] array, int dimension) {
   305         if (array == null) {
   303         if (array == null) {
   306             return null;
   304             return null;
   307         }
   305         }
   308         Object[] structArray = new Object[array.length];
   306         Object[] structArray = new Object[array.length];
       
   307         ObjectContext objContext = objectContext.getInstance(v);
   309         for (int i = 0; i < structArray.length; i++) {
   308         for (int i = 0; i < structArray.length; i++) {
   310             Object arrayElement = array[i];
   309             Object arrayElement = array[i];
   311             if (dimension == 0) {
   310             if (dimension == 0) {
   312                 // No general way to handle structarrays
   311                 // No general way to handle structarrays
   313                 // without invoking ObjectFactory for every instance (which may require id)
   312                 // without invoking ObjectFactory for every instance (which may require id)
   314                 if (isStackFrameType(v.getTypeName())) {
   313                 if (isStackFrameType(v.getTypeName())) {
   315                     structArray[i] = new RecordedFrame(v.getFields(), (Object[]) arrayElement, timeConverter);
   314                     structArray[i] = new RecordedFrame(objContext, (Object[]) arrayElement);
   316                 } else {
   315                 } else {
   317                     structArray[i] = new RecordedObject(v.getFields(), (Object[]) arrayElement, timeConverter);
   316                     structArray[i] = new RecordedObject(objContext, (Object[]) arrayElement);
   318                 }
   317                 }
   319             } else {
   318             } else {
   320                 structArray[i] = structifyArray(v, (Object[]) arrayElement, dimension - 1);
   319                 structArray[i] = structifyArray(v, (Object[]) arrayElement, dimension - 1);
   321             }
   320             }
   322         }
   321         }
   337      * Returns an immutable list of the fields for this object.
   336      * Returns an immutable list of the fields for this object.
   338      *
   337      *
   339      * @return the fields, not {@code null}
   338      * @return the fields, not {@code null}
   340      */
   339      */
   341     public List<ValueDescriptor> getFields() {
   340     public List<ValueDescriptor> getFields() {
   342         return descriptors;
   341         return objectContext.fields;
   343     }
   342     }
   344 
   343 
   345     /**
   344     /**
   346      * Returns the value of a field of type {@code boolean}.
   345      * Returns the value of a field of type {@code boolean}.
   347      * <p>
   346      * <p>
   759         }
   758         }
   760         throw newIllegalArgumentException(name, "java,time.Duration");
   759         throw newIllegalArgumentException(name, "java,time.Duration");
   761     }
   760     }
   762 
   761 
   763     private Duration getDuration(long timespan, String name) throws InternalError {
   762     private Duration getDuration(long timespan, String name) throws InternalError {
   764         ValueDescriptor v = getValueDescriptor(descriptors, name, null);
   763         ValueDescriptor v = getValueDescriptor(objectContext.fields, name, null);
   765         if (timespan == Long.MIN_VALUE) {
   764         if (timespan == Long.MIN_VALUE) {
   766             return Duration.ofSeconds(Long.MIN_VALUE, 0);
   765             return Duration.ofSeconds(Long.MIN_VALUE, 0);
   767         }
   766         }
   768         Timespan ts = v.getAnnotation(Timespan.class);
   767         Timespan ts = v.getAnnotation(Timespan.class);
   769         if (ts != null) {
   768         if (ts != null) {
   775             case Timespan.MILLISECONDS:
   774             case Timespan.MILLISECONDS:
   776                 return Duration.ofMillis(timespan);
   775                 return Duration.ofMillis(timespan);
   777             case Timespan.NANOSECONDS:
   776             case Timespan.NANOSECONDS:
   778                 return Duration.ofNanos(timespan);
   777                 return Duration.ofNanos(timespan);
   779             case Timespan.TICKS:
   778             case Timespan.TICKS:
   780                 return Duration.ofNanos(timeConverter.convertTimespan(timespan));
   779                 return Duration.ofNanos(objectContext.timeConverter.convertTimespan(timespan));
   781             }
   780             }
   782             throw new IllegalArgumentException("Attempt to get " + v.getTypeName() + " field \"" + name + "\" with illegal timespan unit " + ts.value());
   781             throw new IllegalArgumentException("Attempt to get " + v.getTypeName() + " field \"" + name + "\" with illegal timespan unit " + ts.value());
   783         }
   782         }
   784         throw new IllegalArgumentException("Attempt to get " + v.getTypeName() + " field \"" + name + "\" with missing @Timespan");
   783         throw new IllegalArgumentException("Attempt to get " + v.getTypeName() + " field \"" + name + "\" with missing @Timespan");
   785     }
   784     }
   838         }
   837         }
   839         throw newIllegalArgumentException(name, "java.time.Instant");
   838         throw newIllegalArgumentException(name, "java.time.Instant");
   840     }
   839     }
   841 
   840 
   842     private Instant getInstant(long timestamp, String name) {
   841     private Instant getInstant(long timestamp, String name) {
   843         ValueDescriptor v = getValueDescriptor(descriptors, name, null);
   842         ValueDescriptor v = getValueDescriptor(objectContext.fields, name, null);
   844         Timestamp ts = v.getAnnotation(Timestamp.class);
   843         Timestamp ts = v.getAnnotation(Timestamp.class);
   845         if (ts != null) {
   844         if (ts != null) {
   846             if (timestamp == Long.MIN_VALUE) {
   845             if (timestamp == Long.MIN_VALUE) {
   847                 return Instant.MIN;
   846                 return Instant.MIN;
   848             }
   847             }
   849             switch (ts.value()) {
   848             switch (ts.value()) {
   850             case Timestamp.MILLISECONDS_SINCE_EPOCH:
   849             case Timestamp.MILLISECONDS_SINCE_EPOCH:
   851                 return Instant.ofEpochMilli(timestamp);
   850                 return Instant.ofEpochMilli(timestamp);
   852             case Timestamp.TICKS:
   851             case Timestamp.TICKS:
   853                 return Instant.ofEpochSecond(0, timeConverter.convertTimestamp(timestamp));
   852                 return Instant.ofEpochSecond(0, objectContext.timeConverter.convertTimestamp(timestamp));
   854             }
   853             }
   855             throw new IllegalArgumentException("Attempt to get " + v.getTypeName() + " field \"" + name + "\" with illegal timestamp unit " + ts.value());
   854             throw new IllegalArgumentException("Attempt to get " + v.getTypeName() + " field \"" + name + "\" with illegal timestamp unit " + ts.value());
   856         }
   855         }
   857         throw new IllegalArgumentException("Attempt to get " + v.getTypeName() + " field \"" + name + "\" with missing @Timestamp");
   856         throw new IllegalArgumentException("Attempt to get " + v.getTypeName() + " field \"" + name + "\" with missing @Timestamp");
   858     }
   857     }
   928     OffsetDateTime getOffsetDateTime(String name) {
   927     OffsetDateTime getOffsetDateTime(String name) {
   929         Instant instant = getInstant(name);
   928         Instant instant = getInstant(name);
   930         if (instant.equals(Instant.MIN)) {
   929         if (instant.equals(Instant.MIN)) {
   931             return OffsetDateTime.MIN;
   930             return OffsetDateTime.MIN;
   932         }
   931         }
   933         return OffsetDateTime.ofInstant(getInstant(name), timeConverter.getZoneOffset());
   932         return OffsetDateTime.ofInstant(getInstant(name), objectContext.timeConverter.getZoneOffset());
   934     }
   933     }
   935 
   934 
   936     private static IllegalArgumentException newIllegalArgumentException(String name, String typeName) {
   935     private static IllegalArgumentException newIllegalArgumentException(String name, String typeName) {
   937         return new IllegalArgumentException("Attempt to get field \"" + name + "\" with illegal data type conversion " + typeName);
   936         return new IllegalArgumentException("Attempt to get field \"" + name + "\" with illegal data type conversion " + typeName);
   938     }
   937     }