diff -r 2c3cc4b01880 -r c16ac7a2eba4 src/jdk.jfr/share/classes/jdk/jfr/consumer/RecordedObject.java --- a/src/jdk.jfr/share/classes/jdk/jfr/consumer/RecordedObject.java Wed Oct 30 16:14:56 2019 +0100 +++ b/src/jdk.jfr/share/classes/jdk/jfr/consumer/RecordedObject.java Wed Oct 30 19:43:52 2019 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,18 +25,24 @@ package jdk.jfr.consumer; +import java.io.IOException; import java.io.PrintWriter; import java.io.StringWriter; import java.time.Duration; import java.time.Instant; import java.time.OffsetDateTime; +import java.util.Comparator; import java.util.List; import java.util.Objects; import jdk.jfr.Timespan; import jdk.jfr.Timestamp; import jdk.jfr.ValueDescriptor; +import jdk.jfr.internal.consumer.JdkJfrConsumer; +import jdk.jfr.internal.consumer.ObjectFactory; import jdk.jfr.internal.PrivateAccess; +import jdk.jfr.internal.Type; +import jdk.jfr.internal.consumer.ObjectContext; import jdk.jfr.internal.tool.PrettyWriter; /** @@ -51,6 +57,89 @@ */ public class RecordedObject { + static{ + JdkJfrConsumer access = new JdkJfrConsumer() { + public List readTypes(RecordingFile file) throws IOException { + return file.readTypes(); + } + + public boolean isLastEventInChunk(RecordingFile file) { + return file.isLastEventInChunk(); + } + + @Override + public Object getOffsetDataTime(RecordedObject event, String name) { + return event.getOffsetDateTime(name); + } + + @Override + public RecordedClass newRecordedClass(ObjectContext objectContext, long id, Object[] values) { + return new RecordedClass(objectContext, id, values); + } + + @Override + public RecordedClassLoader newRecordedClassLoader(ObjectContext objectContext, long id, Object[] values) { + return new RecordedClassLoader(objectContext, id, values); + } + + @Override + public Comparator eventComparator() { + return new Comparator() { + @Override + public int compare(RecordedEvent e1, RecordedEvent e2) { + return Long.compare(e1.endTimeTicks, e2.endTimeTicks); + } + }; + } + + @Override + public RecordedStackTrace newRecordedStackTrace(ObjectContext objectContext, Object[] values) { + return new RecordedStackTrace(objectContext, values); + } + + @Override + public RecordedThreadGroup newRecordedThreadGroup(ObjectContext objectContext, Object[] values) { + return new RecordedThreadGroup(objectContext, values); + } + + @Override + public RecordedFrame newRecordedFrame(ObjectContext objectContext, Object[] values) { + return new RecordedFrame(objectContext, values); + } + + @Override + public RecordedThread newRecordedThread(ObjectContext objectContext, long id, Object[] values) { + return new RecordedThread(objectContext, id, values); + } + + @Override + public RecordedMethod newRecordedMethod(ObjectContext objectContext, Object[] values) { + return new RecordedMethod(objectContext, values); + } + + @Override + public RecordedEvent newRecordedEvent(ObjectContext objectContext, Object[] values, long startTimeTicks, long endTimeTicks) { + return new RecordedEvent(objectContext, values, startTimeTicks, endTimeTicks); + } + + @Override + public void setStartTicks(RecordedEvent event, long startTicks) { + event.startTimeTicks = startTicks; + } + + @Override + public void setEndTicks(RecordedEvent event, long endTicks) { + event.endTimeTicks = endTicks; + } + + @Override + public Object[] eventValues(RecordedEvent event) { + return event.objects; + } + }; + JdkJfrConsumer.setAccess(access); + } + private final static class UnsignedValue { private final Object o; @@ -63,15 +152,13 @@ } } - private final Object[] objects; - private final List descriptors; - private final TimeConverter timeConverter; + final Object[] objects; + final ObjectContext objectContext; // package private, not to be subclassed outside this package - RecordedObject(List descriptors, Object[] objects, TimeConverter timeConverter) { - this.descriptors = descriptors; + RecordedObject(ObjectContext objectContext, Object[] objects) { + this.objectContext = objectContext; this.objects = objects; - this.timeConverter = timeConverter; } // package private @@ -101,7 +188,7 @@ */ public boolean hasField(String name) { Objects.requireNonNull(name); - for (ValueDescriptor v : descriptors) { + for (ValueDescriptor v : objectContext.fields) { if (v.getName().equals(name)) { return true; } @@ -109,7 +196,7 @@ int dotIndex = name.indexOf("."); if (dotIndex > 0) { String structName = name.substring(0, dotIndex); - for (ValueDescriptor v : descriptors) { + for (ValueDescriptor v : objectContext.fields) { if (!v.getFields().isEmpty() && v.getName().equals(structName)) { RecordedObject child = getValue(structName); if (child != null) { @@ -169,12 +256,16 @@ return t; } + protected Object objectAt(int index) { + return objects[index]; + } + private Object getValue(String name, boolean allowUnsigned) { Objects.requireNonNull(name); int index = 0; - for (ValueDescriptor v : descriptors) { + for (ValueDescriptor v : objectContext.fields) { if (name.equals(v.getName())) { - Object object = objects[index]; + Object object = objectAt(index); if (object == null) { // error or missing return null; @@ -200,7 +291,7 @@ return structifyArray(v, array, 0); } // struct - return new RecordedObject(v.getFields(), (Object[]) object, timeConverter); + return new RecordedObject(objectContext.getInstance(v), (Object[]) object); } } index++; @@ -209,7 +300,7 @@ int dotIndex = name.indexOf("."); if (dotIndex > 0) { String structName = name.substring(0, dotIndex); - for (ValueDescriptor v : descriptors) { + for (ValueDescriptor v : objectContext.fields) { if (!v.getFields().isEmpty() && v.getName().equals(structName)) { RecordedObject child = getValue(structName); String subName = name.substring(dotIndex + 1); @@ -261,7 +352,7 @@ private T getTypedValue(String name, String typeName) { Objects.requireNonNull(name); // Validate name and type first - getValueDescriptor(descriptors, name, typeName); + getValueDescriptor(objectContext.fields, name, typeName); return getValue(name); } @@ -270,15 +361,16 @@ return null; } Object[] structArray = new Object[array.length]; + ObjectContext objContext = objectContext.getInstance(v); for (int i = 0; i < structArray.length; i++) { Object arrayElement = array[i]; if (dimension == 0) { // No general way to handle structarrays // without invoking ObjectFactory for every instance (which may require id) if (isStackFrameType(v.getTypeName())) { - structArray[i] = new RecordedFrame(v.getFields(), (Object[]) arrayElement, timeConverter); + structArray[i] = new RecordedFrame(objContext, (Object[]) arrayElement); } else { - structArray[i] = new RecordedObject(v.getFields(), (Object[]) arrayElement, timeConverter); + structArray[i] = new RecordedObject(objContext, (Object[]) arrayElement); } } else { structArray[i] = structifyArray(v, (Object[]) arrayElement, dimension - 1); @@ -303,7 +395,7 @@ * @return the fields, not {@code null} */ public List getFields() { - return descriptors; + return objectContext.fields; } /** @@ -725,7 +817,7 @@ } private Duration getDuration(long timespan, String name) throws InternalError { - ValueDescriptor v = getValueDescriptor(descriptors, name, null); + ValueDescriptor v = getValueDescriptor(objectContext.fields, name, null); if (timespan == Long.MIN_VALUE) { return Duration.ofSeconds(Long.MIN_VALUE, 0); } @@ -741,7 +833,7 @@ case Timespan.NANOSECONDS: return Duration.ofNanos(timespan); case Timespan.TICKS: - return Duration.ofNanos(timeConverter.convertTimespan(timespan)); + return Duration.ofNanos(objectContext.convertTimespan(timespan)); } throw new IllegalArgumentException("Attempt to get " + v.getTypeName() + " field \"" + name + "\" with illegal timespan unit " + ts.value()); } @@ -804,7 +896,7 @@ } private Instant getInstant(long timestamp, String name) { - ValueDescriptor v = getValueDescriptor(descriptors, name, null); + ValueDescriptor v = getValueDescriptor(objectContext.fields, name, null); Timestamp ts = v.getAnnotation(Timestamp.class); if (ts != null) { if (timestamp == Long.MIN_VALUE) { @@ -814,7 +906,7 @@ case Timestamp.MILLISECONDS_SINCE_EPOCH: return Instant.ofEpochMilli(timestamp); case Timestamp.TICKS: - return Instant.ofEpochSecond(0, timeConverter.convertTimestamp(timestamp)); + return Instant.ofEpochSecond(0, objectContext.convertTimestamp(timestamp)); } throw new IllegalArgumentException("Attempt to get " + v.getTypeName() + " field \"" + name + "\" with illegal timestamp unit " + ts.value()); } @@ -889,12 +981,12 @@ } // package private for now. Used by EventWriter - OffsetDateTime getOffsetDateTime(String name) { + private OffsetDateTime getOffsetDateTime(String name) { Instant instant = getInstant(name); if (instant.equals(Instant.MIN)) { return OffsetDateTime.MIN; } - return OffsetDateTime.ofInstant(getInstant(name), timeConverter.getZoneOffset()); + return OffsetDateTime.ofInstant(getInstant(name), objectContext.getZoneOffset()); } private static IllegalArgumentException newIllegalArgumentException(String name, String typeName) {