Skip to content
Permalink
Browse files
6656: Allow capturing field values with path syntax
Reviewed-by: hirt
  • Loading branch information
tabjy authored and thegreystone committed Feb 13, 2020
1 parent 7731ae9 commit 689812b07b3ee5e260dd1b84a6ef9c082bc330c9
Showing with 2,414 additions and 117 deletions.
  1. +47 −0 core/org.openjdk.jmc.agent/src/main/java/org/openjdk/jmc/agent/Attribute.java
  2. +106 −0 core/org.openjdk.jmc.agent/src/main/java/org/openjdk/jmc/agent/Field.java
  3. +2 −2 core/org.openjdk.jmc.agent/src/main/java/org/openjdk/jmc/agent/Parameter.java
  4. +17 −3 core/org.openjdk.jmc.agent/src/main/java/org/openjdk/jmc/agent/ReturnValue.java
  5. +3 −3 core/org.openjdk.jmc.agent/src/main/java/org/openjdk/jmc/agent/TransformDescriptor.java
  6. +22 −12 core/org.openjdk.jmc.agent/src/main/java/org/openjdk/jmc/agent/Transformer.java
  7. +60 −8 core/org.openjdk.jmc.agent/src/main/java/org/openjdk/jmc/agent/impl/DefaultTransformRegistry.java
  8. +9 −2 core/org.openjdk.jmc.agent/src/main/java/org/openjdk/jmc/agent/jfr/JFRTransformDescriptor.java
  9. +16 −4 core/org.openjdk.jmc.agent/src/main/java/org/openjdk/jmc/agent/jfr/impl/JFRClassVisitor.java
  10. +22 −15 core/org.openjdk.jmc.agent/src/main/java/org/openjdk/jmc/agent/jfr/impl/JFREventClassGenerator.java
  11. +105 −14 core/org.openjdk.jmc.agent/src/main/java/org/openjdk/jmc/agent/jfr/impl/JFRMethodAdvisor.java
  12. +17 −5 core/org.openjdk.jmc.agent/src/main/java/org/openjdk/jmc/agent/jfrnext/impl/JFRNextClassVisitor.java
  13. +17 −10 ...penjdk.jmc.agent/src/main/java/org/openjdk/jmc/agent/jfrnext/impl/JFRNextEventClassGenerator.java
  14. +106 −15 .../org.openjdk.jmc.agent/src/main/java/org/openjdk/jmc/agent/jfrnext/impl/JFRNextMethodAdvisor.java
  15. +342 −0 core/org.openjdk.jmc.agent/src/main/java/org/openjdk/jmc/agent/util/AccessUtils.java
  16. +99 −0 core/org.openjdk.jmc.agent/src/main/java/org/openjdk/jmc/agent/util/InspectionClassLoader.java
  17. +96 −8 core/org.openjdk.jmc.agent/src/main/java/org/openjdk/jmc/agent/util/TypeUtils.java
  18. +720 −0 ...org.openjdk.jmc.agent/src/main/java/org/openjdk/jmc/agent/util/expression/ExpressionResolver.java
  19. +51 −0 ...openjdk.jmc.agent/src/main/java/org/openjdk/jmc/agent/util/expression/IllegalSyntaxException.java
  20. +135 −0 core/org.openjdk.jmc.agent/src/main/java/org/openjdk/jmc/agent/util/expression/ReferenceChain.java
  21. +214 −0 ....openjdk.jmc.agent/src/main/java/org/openjdk/jmc/agent/util/expression/ReferenceChainElement.java
  22. +57 −8 core/org.openjdk.jmc.agent/src/test/java/org/openjdk/jmc/agent/test/InstrumentMe.java
  23. +8 −7 core/org.openjdk.jmc.agent/src/test/java/org/openjdk/jmc/agent/test/TestDefineEventProbes.java
  24. +143 −1 core/org.openjdk.jmc.agent/src/test/resources/org/openjdk/jmc/agent/test/jfrprobes_template.xml
@@ -0,0 +1,47 @@
/*
* Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved.
*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* The contents of this file are subject to the terms of either the Universal Permissive License
* v 1.0 as shown at http://oss.oracle.com/licenses/upl
*
* or the following license:
*
* Redistribution and use in source and binary forms, with or without modification, are permitted
* provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions
* and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of
* conditions and the following disclaimer in the documentation and/or other materials provided with
* the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors may be used to
* endorse or promote products derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
* WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.openjdk.jmc.agent;

public interface Attribute {
String getName();

String getFieldName();

String getDescription();

String getContentType();

String getRelationKey();

String getConverterClassName();
}
@@ -0,0 +1,106 @@
/*
* Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved.
*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* The contents of this file are subject to the terms of either the Universal Permissive License
* v 1.0 as shown at http://oss.oracle.com/licenses/upl
*
* or the following license:
*
* Redistribution and use in source and binary forms, with or without modification, are permitted
* provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions
* and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of
* conditions and the following disclaimer in the documentation and/or other materials provided with
* the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors may be used to
* endorse or promote products derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
* WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.openjdk.jmc.agent;

import org.openjdk.jmc.agent.util.expression.ExpressionResolver;
import org.openjdk.jmc.agent.util.expression.IllegalSyntaxException;
import org.openjdk.jmc.agent.util.expression.ReferenceChain;
import org.openjdk.jmc.agent.util.TypeUtils;

public class Field implements Attribute {

private final String name;
private final String expression;
private final String fieldName;
private final String description;
private final String contentType;
private final String relationKey;
private final String converterClassName;

private Class<?> resolvingCaller;
private ReferenceChain referenceChain;

public Field(String name, String expression, String description, String contentType, String relationKey,
String converterClassName) {
this.name = name;
this.expression = expression;
this.description = description;
this.contentType = contentType;
this.relationKey = relationKey;
this.converterClassName = converterClassName;
this.fieldName = "field" + TypeUtils.deriveIdentifierPart(name);
}

@Override
public String getName() {
return this.name;
}

public String getExpression() {
return expression;
}

@Override
public String getFieldName() {
return this.fieldName;
}

@Override
public String getDescription() {
return this.description;
}

@Override
public String getContentType() {
return this.contentType;
}

@Override
public String getRelationKey() {
return this.relationKey;
}

@Override
public String getConverterClassName() {
return this.converterClassName;
}

public ReferenceChain resolveReferenceChain(Class<?> callerClass) throws IllegalSyntaxException {
if (!callerClass.equals(resolvingCaller)) {
resolvingCaller = callerClass;
referenceChain = ExpressionResolver.solve(callerClass, expression);
}

return referenceChain;
}
}
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved.
*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@@ -37,7 +37,7 @@
/**
* Metadata for a parameter to be logged by the agent.
*/
public final class Parameter {
public final class Parameter implements Attribute {
public static final int INDEX_INVALID = -1;

private final int index;
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved.
*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@@ -37,16 +37,20 @@
/**
* Metadata for a return value to be logged by the agent.
*/
public final class ReturnValue {
public final class ReturnValue implements Attribute {
private final String name;
private final String fieldName;
private final String description;
private final String contentType;
private final String relationKey;
private final String converterClassName;

public ReturnValue(String name, String description, String contentType) {
public ReturnValue(String name, String description, String contentType, String relationKey, String converterClassName) {
this.name = name == null ? "Return Value" : name;
this.description = description;
this.contentType = contentType;
this.relationKey = relationKey;
this.converterClassName = converterClassName;
this.fieldName = "field" + TypeUtils.deriveIdentifierPart(this.name); //$NON-NLS-1$
}

@@ -62,6 +66,16 @@ public String getContentType() {
return contentType;
}

@Override
public String getRelationKey() {
return relationKey;
}

@Override
public String getConverterClassName() {
return converterClassName;
}

public String getFieldName() {
return fieldName;
}
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved.
*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@@ -105,8 +105,8 @@ protected String getTransformationAttribute(String attribute) {
* @return the instantiated {@link TransformDescriptor}.
*/
public static TransformDescriptor create(
String id, String internalName, Method method, Map<String, String> values, List<Parameter> parameters, ReturnValue returnValue) {
return new JFRTransformDescriptor(id, internalName, method, values, parameters, returnValue);
String id, String internalName, Method method, Map<String, String> values, List<Parameter> parameters, ReturnValue returnValue, List<Field> fields) {
return new JFRTransformDescriptor(id, internalName, method, values, parameters, returnValue, fields);
}

@Override
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved.
*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@@ -47,6 +47,7 @@
import org.openjdk.jmc.agent.jfr.VersionResolver.JFRVersion;
import org.openjdk.jmc.agent.jfr.impl.JFRClassVisitor;
import org.openjdk.jmc.agent.jfrnext.impl.JFRNextClassVisitor;
import org.openjdk.jmc.agent.util.InspectionClassLoader;

public class Transformer implements ClassFileTransformer {
private TransformRegistry registry;
@@ -62,41 +63,50 @@ public byte[] transform(
if (!registry.hasPendingTransforms(className)) {
return registry.isRevertIntrumentation() ? classfileBuffer : null;
}
return doTransforms(registry.getTransformData(className), classfileBuffer, loader, protectionDomain);

// We need a class instance for reflective inspection, so create a InspectionClassLoader if the class if not yet
// loaded.
return doTransforms(registry.getTransformData(className), classfileBuffer, loader, classBeingRedefined,
protectionDomain, classBeingRedefined != null ? null : new InspectionClassLoader(loader));
}

private byte[] doTransforms(
List<TransformDescriptor> transformDataList, byte[] classfileBuffer, ClassLoader definingClassLoader,
ProtectionDomain protectionDomain) {
Class<?> classBeingRedefined, ProtectionDomain protectionDomain,
InspectionClassLoader inspectionClassLoader) {
for (TransformDescriptor td : transformDataList) {
if (td.isPendingTransforms()) {
// FIXME: Optimization, should do all transforms to one class in one go, instead of creating one class writer per transform.
classfileBuffer = doTransform(td, classfileBuffer, definingClassLoader, protectionDomain);
classfileBuffer = doTransform(td, classfileBuffer, definingClassLoader, classBeingRedefined,
protectionDomain, inspectionClassLoader);
td.setPendingTransforms(false);
}
}
return classfileBuffer;
}

private byte[] doTransform(
TransformDescriptor td, byte[] classfileBuffer, ClassLoader definingClassLoader,
ProtectionDomain protectionDomain) {
return doJFRLogging((JFRTransformDescriptor) td, classfileBuffer, definingClassLoader, protectionDomain);
TransformDescriptor td, byte[] classfileBuffer, ClassLoader definingClassLoader, Class<?> classBeingRedefined,
ProtectionDomain protectionDomain, InspectionClassLoader inspectionClassLoader) {
return doJFRLogging((JFRTransformDescriptor) td, classfileBuffer, definingClassLoader, classBeingRedefined,
protectionDomain, inspectionClassLoader);
}

private byte[] doJFRLogging(
JFRTransformDescriptor td, byte[] classfileBuffer, ClassLoader definingClassLoader,
ProtectionDomain protectionDomain) {
JFRTransformDescriptor td, byte[] classfileBuffer, ClassLoader definingClassLoader, Class<?> classBeingRedefined,
ProtectionDomain protectionDomain, InspectionClassLoader inspectionClassLoader) {
if (VersionResolver.getAvailableJFRVersion() == JFRVersion.NONE) {
Logger.getLogger(getClass().getName()).log(Level.SEVERE,
"Could not find JFR classes. Failed to instrument " + td.getMethod().toString()); //$NON-NLS-1$
return classfileBuffer;
}
try {
ClassWriter classWriter = new ClassWriter(ClassWriter.COMPUTE_MAXS);
ClassVisitor visitor = VersionResolver.getAvailableJFRVersion() == JFRVersion.JFRNEXT
? new JFRNextClassVisitor(classWriter, td, definingClassLoader, protectionDomain)
: new JFRClassVisitor(classWriter, td, definingClassLoader, protectionDomain);
ClassVisitor visitor = VersionResolver.getAvailableJFRVersion() == JFRVersion.JFRNEXT ?
new JFRNextClassVisitor(classWriter, td, definingClassLoader, classBeingRedefined, protectionDomain,
inspectionClassLoader) :
new JFRClassVisitor(classWriter, td, definingClassLoader, classBeingRedefined, protectionDomain,
inspectionClassLoader);
ClassReader reader = new ClassReader(classfileBuffer);
reader.accept(visitor, 0);
return classWriter.toByteArray();

0 comments on commit 689812b

Please sign in to comment.