Skip to content
Permalink
Browse files
6887: Agent instrumentation fails silently if method descriptors don'…
…t match

Reviewed-by: hirt
  • Loading branch information
Joshua Matsuoka committed Aug 20, 2020
1 parent f157e54 commit 76d656cdda142fa0b75d7918595f14c788e9fcf5
@@ -67,6 +67,7 @@
private final boolean allowToString;
private final boolean allowConverter;
private final boolean emitOnException;
private boolean matchFound;
private final List<Parameter> parameters;
private final ReturnValue returnValue;
private final List<Field> fields;
@@ -233,4 +234,13 @@ public boolean isAllowedFieldType(Type type) {
}
return type.getSort() != Type.OBJECT && type.getSort() != Type.ARRAY;
}

public void matchFound(boolean matched) {
this.matchFound = matched;
}

public boolean isMatchFound() {
return matchFound;
}

}
@@ -73,6 +73,7 @@ public MethodVisitor visitMethod(int access, String name, String desc, String si
MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions);
if (name.equals(transformDescriptor.getMethod().getName())
&& desc.equals(transformDescriptor.getMethod().getSignature())) {
transformDescriptor.matchFound(true);
return new JFRMethodAdvisor(transformDescriptor, inspectionClass, Opcodes.ASM8, mv, access, name, desc);
}
return mv;
@@ -87,6 +88,11 @@ public void visitEnd() {
Agent.getLogger().log(Level.SEVERE, "Failed to generate event class for " + transformDescriptor.toString(), //$NON-NLS-1$
t);
}
if (!transformDescriptor.isMatchFound()) {
Agent.getLogger().warning("Method " + transformDescriptor.getMethod().getName() + " "
+ transformDescriptor.getMethod().getSignature() + " not found."); // $NON-NLS-1$
}

super.visitEnd();
}

@@ -44,6 +44,8 @@
import org.openjdk.jmc.agent.jfr.JFRTransformDescriptor;
import org.openjdk.jmc.agent.util.InspectionClassLoader;
import org.openjdk.jmc.agent.util.TypeUtils;
import org.openjdk.jmc.agent.Agent;


public class JFRNextClassVisitor extends ClassVisitor {
private final JFRTransformDescriptor transformDescriptor;
@@ -74,6 +76,7 @@ public MethodVisitor visitMethod(int access, String name, String desc, String si
MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions);
if (name.equals(transformDescriptor.getMethod().getName())
&& desc.equals(transformDescriptor.getMethod().getSignature())) {
transformDescriptor.matchFound(true);
return new JFRNextMethodAdvisor(transformDescriptor, inspectionClass, Opcodes.ASM8, mv, access, name, desc);
}
return mv;
@@ -84,9 +87,13 @@ public void visitEnd() {
try {
reflectiveRegister(generateEventClass());
} catch (Exception e) {
Logger.getLogger(JFRNextClassVisitor.class.getName()).log(Level.SEVERE,
Agent.getLogger().log(Level.SEVERE,
"Failed to generate event class for " + transformDescriptor.toString(), e); //$NON-NLS-1$
}
if (!transformDescriptor.isMatchFound()) {
Agent.getLogger().warning("Method " + transformDescriptor.getMethod().getName() + " "
+ transformDescriptor.getMethod().getSignature() + " not found."); // $NON-NLS-1$
}
super.visitEnd();
}

@@ -0,0 +1,118 @@
/*
* Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2020 Red Hat Inc. 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.test;

import static org.junit.Assert.assertTrue;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;

import java.io.ByteArrayInputStream;
import java.util.List;

import org.junit.Test;
import org.objectweb.asm.Type;
import org.openjdk.jmc.agent.TransformDescriptor;
import org.openjdk.jmc.agent.TransformRegistry;
import org.openjdk.jmc.agent.Transformer;
import org.openjdk.jmc.agent.impl.DefaultTransformRegistry;
import org.openjdk.jmc.agent.jfr.JFRTransformDescriptor;
import org.openjdk.jmc.agent.test.util.TestToolkit;

public class TestIncorrectMethodDescriptor {

private static final String AGENT_OBJECT_NAME = "org.openjdk.jmc.jfr.agent:type=AgentController"; //$NON-NLS-1$
private static final String EVENT_ID = "demo.jfr.test6";
private static final String EVENT_NAME = "JFR Hello World Event 6 %TEST_NAME%";
private static final String EVENT_DESCRIPTION = "JFR Hello World Event 6 %TEST_NAME%";
private static final String EVENT_PATH = "demo/jfrhelloworldevent6";
private static final String EVENT_CLASS_NAME = "org.openjdk.jmc.agent.test.InstrumentMe";
private static final String METHOD_NAME = "printHelloWorldJFR6";
private static final String CORRECT_METHOD_DESCRIPTOR = "()D";
private static final String INCORRECT_METHOD_DESCRIPTOR = "()Z";

private static final String XML_DESCRIPTION = "<jfragent>"
+ "<events>"
+ "<event id=\"" + EVENT_ID + "\">"
+ "<name>" + EVENT_NAME + "</name>"
+ "<description>" + EVENT_DESCRIPTION + "</description>"
+ "<path>" + EVENT_PATH + "</path>"
+ "<stacktrace>true</stacktrace>"
+ "<class>" + EVENT_CLASS_NAME + "</class>"
+ "<method>"
+ "<name>" + METHOD_NAME + "</name>"
+ "<descriptor>" + CORRECT_METHOD_DESCRIPTOR + "</descriptor>"
+ "</method>"
+ "<location>WRAP</location>"
+ "</event>"
+ "</events>"
+ "</jfragent>";

@Test
public void testCorrectMethodDescriptor() throws Exception {
TransformRegistry registry = DefaultTransformRegistry.from(new ByteArrayInputStream(XML_DESCRIPTION.getBytes()));
assertTrue(registry.hasPendingTransforms(Type.getInternalName(InstrumentMe.class)));

Transformer jfrTransformer = new Transformer(registry);
byte[] transformedClass = jfrTransformer.transform(InstrumentMe.class.getClassLoader(),
Type.getInternalName(InstrumentMe.class), InstrumentMe.class, null,
TestToolkit.getByteCode(InstrumentMe.class));

List<TransformDescriptor> descriptors = registry.getTransformData(Type.getInternalName(InstrumentMe.class));
assertEquals(descriptors.size(), 1);

JFRTransformDescriptor descriptor = (JFRTransformDescriptor)descriptors.get(0);
assertTrue(descriptor.isMatchFound());
}

@Test
public void testIncorrectMethodDescriptor() throws Exception {
TransformRegistry registry = DefaultTransformRegistry.from(
new ByteArrayInputStream(XML_DESCRIPTION.replace(CORRECT_METHOD_DESCRIPTOR, INCORRECT_METHOD_DESCRIPTOR)
.getBytes()));
assertTrue(registry.hasPendingTransforms(Type.getInternalName(InstrumentMe.class)));

Transformer jfrTransformer = new Transformer(registry);
byte[] transformedClass = jfrTransformer.transform(InstrumentMe.class.getClassLoader(),
Type.getInternalName(InstrumentMe.class), InstrumentMe.class, null,
TestToolkit.getByteCode(InstrumentMe.class));

List<TransformDescriptor> descriptors = registry.getTransformData(Type.getInternalName(InstrumentMe.class));
assertEquals(descriptors.size(), 1);
JFRTransformDescriptor descriptor = (JFRTransformDescriptor)descriptors.get(0);

assertFalse(descriptor.isMatchFound());
}

}

0 comments on commit 76d656c

Please sign in to comment.