Skip to content

Commit

Permalink
pinpoint-apm#1879 Fix type checking for arrays
Browse files Browse the repository at this point in the history
  • Loading branch information
Xylus committed Jun 29, 2016
1 parent 5d06efb commit 152ab88
Show file tree
Hide file tree
Showing 13 changed files with 387 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -342,7 +342,10 @@ private void addField0(String accessorTypeName, String initValExp) throws Instru
final AccessorAnalyzer accessorAnalyzer = new AccessorAnalyzer();
final AccessorDetails accessorDetails = accessorAnalyzer.analyze(accessorType);

final CtField newField = CtField.make("private " + accessorDetails.getFieldType().getName() + " " + FIELD_PREFIX + accessorTypeName.replace('.', '_').replace('$', '_') + ";", ctClass);
Class<?> fieldType = accessorDetails.getFieldType();
String fieldTypeName = JavaAssistUtils.javaClassNameToObjectName(fieldType.getName());

final CtField newField = CtField.make("private " + fieldTypeName + " " + FIELD_PREFIX + accessorTypeName.replace('.', '_').replace('$', '_') + ";", ctClass);

if (initValExp == null) {
ctClass.addField(newField);
Expand Down Expand Up @@ -371,8 +374,9 @@ public void addGetter(String getterTypeName, String fieldName) throws Instrument
GetterDetails getterDetails = new GetterAnalyzer().analyze(getterType);

CtField field = ctClass.getField(fieldName);
String fieldTypeName = JavaAssistUtils.javaClassNameToObjectName(getterDetails.getFieldType().getName());

if (!field.getType().getName().equals(getterDetails.getFieldType().getName())) {
if (!field.getType().getName().equals(fieldTypeName)) {
throw new IllegalArgumentException("Return type of the getter is different with the field type. getterMethod: " + getterDetails.getGetter() + ", fieldType: " + field.getType().getName());
}

Expand Down Expand Up @@ -404,8 +408,9 @@ public void addSetter(String setterTypeName, String fieldName, boolean removeFin
SetterDetails setterDetails = new SetterAnalyzer().analyze(setterType);

CtField field = ctClass.getField(fieldName);
String fieldTypeName = JavaAssistUtils.javaClassNameToObjectName(setterDetails.getFieldType().getName());

if (!field.getType().getName().equals(setterDetails.getFieldType().getName())) {
if (!field.getType().getName().equals(fieldTypeName)) {
throw new IllegalArgumentException("Argument type of the setter is different with the field type. setterMethod: " + setterDetails.getSetter() + ", fieldType: " + field.getType().getName());
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,16 @@ public static String[] parseParameterSignature(String signature) {
return objectType;
}

public static String javaClassNameToObjectName(String javaClassName) {
final char scheme = javaClassName.charAt(0);
switch (scheme) {
case '[':
return toArrayType(javaClassName);
default:
return javaClassName;
}
}

private static String byteCodeSignatureToObjectType(String signature, int startIndex) {
final char scheme = signature.charAt(startIndex);
switch (scheme) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/*
* Copyright 2016 Naver Corp.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.navercorp.pinpoint.profiler.interceptor.bci;

/**
* @author HyunGil Jeong
*/
public interface IntArrayGetter {
int[] _$PINPOINT$_getIntArray();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/*
* Copyright 2016 Naver Corp.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.navercorp.pinpoint.profiler.interceptor.bci;

/**
* @author HyunGil Jeong
*/
public interface IntArraySetter {
void _$PINPOINT$_setIntArray(int[] integers);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/*
* Copyright 2016 Naver Corp.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.navercorp.pinpoint.profiler.interceptor.bci;

/**
* @author HyunGil Jeong
*/
public interface IntArrayTraceValue {
void _$PINPOINT$_setTraceIntArray(int[] values);
int[] _$PINPOINT$_getTraceIntArray();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/*
* Copyright 2016 Naver Corp.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.navercorp.pinpoint.profiler.interceptor.bci;

/**
* @author HyunGil Jeong
*/
public interface IntSetter {
void _$PINPOINT$_setInt(int integer);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/*
* Copyright 2016 Naver Corp.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.navercorp.pinpoint.profiler.interceptor.bci;

/**
* @author HyunGil Jeong
*/
public interface IntegerArrayGetter {
Integer[] _$PINPOINT$_getIntegerArray();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/*
* Copyright 2016 Naver Corp.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.navercorp.pinpoint.profiler.interceptor.bci;

/**
* @author HyunGil Jeong
*/
public interface IntegerArraySetter {
void _$PINPOINT$_setIntegerArray(Integer[] integers);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/*
* Copyright 2016 Naver Corp.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.navercorp.pinpoint.profiler.interceptor.bci;

/**
* @author HyunGil Jeong
*/
public interface IntegerArrayTraceValue {
void _$PINPOINT$_setTraceIntegerArray(Integer[] values);
Integer[] _$PINPOINT$_getTraceIntegerArray();
}
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,8 @@ public byte[] doInTransform(Instrumentor instrumentor, ClassLoader loader, Strin

aClass.addField(ObjectTraceValue.class.getName());
aClass.addField(IntTraceValue.class.getName());
aClass.addField(IntArrayTraceValue.class.getName());
aClass.addField(IntegerArrayTraceValue.class.getName());
aClass.addField(DatabaseInfoTraceValue.class.getName());
aClass.addField(BindValueTraceValue.class.getName());

Expand Down Expand Up @@ -180,13 +182,27 @@ public byte[] doInTransform(Instrumentor instrumentor, ClassLoader loader, Strin
Object get = objectTraceValue.getMethod("_$PINPOINT$_getTraceObject").invoke(testObject);
Assert.assertEquals("a", get);


Class<?> intTraceValue = loader.loadClass(IntTraceValue.class.getName());
Assert.assertTrue("IntTraceValue implements fail", intTraceValue.isInstance(testObject));
intTraceValue.getMethod("_$PINPOINT$_setTraceInt", int.class).invoke(testObject, 1);
int a = (Integer)intTraceValue.getMethod("_$PINPOINT$_getTraceInt").invoke(testObject);
Assert.assertEquals(1, a);

Class<?> intArrayTraceValue = loader.loadClass(IntArrayTraceValue.class.getName());
Assert.assertTrue("IntArrayTraceValue implements fail", intArrayTraceValue.isInstance(testObject));
int[] expectedInts = {1, 2, 3};
intArrayTraceValue.getMethod("_$PINPOINT$_setTraceIntArray", int[].class).invoke(testObject, expectedInts);
int[] ints = (int[]) intArrayTraceValue.getMethod("_$PINPOINT$_getTraceIntArray").invoke(testObject);
Assert.assertEquals(expectedInts, ints);

Class<?> integerArrayTraceValue = loader.loadClass(IntegerArrayTraceValue.class.getName());
Assert.assertTrue("IntegerArrayTraceValue implements fail", integerArrayTraceValue.isInstance(testObject));
Integer[] expectedIntegers = {1, 2};
// wrap due to vararg expansion
Object[] wrappedExpectedIntegers = new Object[]{expectedIntegers};
integerArrayTraceValue.getMethod("_$PINPOINT$_setTraceIntegerArray", Integer[].class).invoke(testObject, wrappedExpectedIntegers);
Integer[] integers = (Integer[]) integerArrayTraceValue.getMethod("_$PINPOINT$_getTraceIntegerArray").invoke(testObject);
Assert.assertArrayEquals(expectedIntegers, integers);

Class<?> databaseTraceValue = loader.loadClass(DatabaseInfoTraceValue.class.getName());
Assert.assertTrue("DatabaseInfoTraceValue implements fail", databaseTraceValue.isInstance(testObject));
Expand Down Expand Up @@ -335,7 +351,8 @@ public void nullDescriptor() {
public void testAddGetter() throws Exception {
final TestClassLoader loader = getTestClassLoader();
final String targetClassName = "com.navercorp.pinpoint.profiler.interceptor.bci.TestObject3";



loader.addTransformer(targetClassName, new TransformCallback() {

@Override
Expand All @@ -346,6 +363,8 @@ public byte[] doInTransform(Instrumentor instrumentor, ClassLoader classLoader,

aClass.addGetter(StringGetter.class.getName(), "value");
aClass.addGetter(IntGetter.class.getName(), "intValue");
aClass.addGetter(IntArrayGetter.class.getName(), "intValues");
aClass.addGetter(IntegerArrayGetter.class.getName(), "integerValues");

return aClass.toBytecode();
} catch (InstrumentException e) {
Expand All @@ -360,12 +379,18 @@ public byte[] doInTransform(Instrumentor instrumentor, ClassLoader classLoader,

Class<?> stringGetter = loader.loadClass(StringGetter.class.getName());
Class<?> intGetter = loader.loadClass(IntGetter.class.getName());
Class<?> intsGetter = loader.loadClass(IntArrayGetter.class.getName());
Class<?> integersGetter = loader.loadClass(IntegerArrayGetter.class.getName());

Assert.assertTrue(stringGetter.isInstance(testObject));
Assert.assertTrue(intGetter.isInstance(testObject));
Assert.assertTrue(intsGetter.isInstance(testObject));
Assert.assertTrue(integersGetter.isInstance(testObject));

String value = "hehe";
int intValue = 99;
int[] intValues = {99, 100};
Integer[] integerValues = {99, 100};

Method method = testObject.getClass().getMethod("setValue", String.class);
method.invoke(testObject, value);
Expand All @@ -379,6 +404,77 @@ public byte[] doInTransform(Instrumentor instrumentor, ClassLoader classLoader,
Method getInt = intGetter.getMethod("_$PINPOINT$_getInt");
Assert.assertEquals(intValue, getInt.invoke(testObject));

Method setIntValues = testObject.getClass().getMethod("setIntValues", int[].class);
setIntValues.invoke(testObject, intValues);

Method getIntValues = intsGetter.getMethod("_$PINPOINT$_getIntArray");
Assert.assertEquals(intValues, getIntValues.invoke(testObject));

Method setIntegerValues = testObject.getClass().getMethod("setIntegerValues", Integer[].class);
// wrap due to vararg expansion
Object[] wrappedIntegerValues = new Object[]{integerValues};
setIntegerValues.invoke(testObject, wrappedIntegerValues);

Method getIntegerValues = integersGetter.getMethod("_$PINPOINT$_getIntegerArray");
Assert.assertEquals(integerValues, getIntegerValues.invoke(testObject));

}

@Test
public void testAddSetter() throws Exception {
final TestClassLoader loader = getTestClassLoader();
final String targetClassName = "com.navercorp.pinpoint.profiler.interceptor.bci.TestObject4";

loader.addTransformer(targetClassName, new TransformCallback() {
@Override
public byte[] doInTransform(Instrumentor instrumentor, ClassLoader classLoader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws InstrumentException {
try {
logger.info("modify cl:{}", classLoader);
InstrumentClass testClass = instrumentor.getInstrumentClass(classLoader, className, classfileBuffer);

testClass.addSetter(IntSetter.class.getName(), "intValue");
testClass.addSetter(IntArraySetter.class.getName(), "intValues");
testClass.addSetter(IntegerArraySetter.class.getName(), "integerValues");

return testClass.toBytecode();
} catch (InstrumentException e) {
throw new RuntimeException(e.getMessage(), e);
}
}
});

loader.initialize();

Object testObject = loader.loadClass(targetClassName).newInstance();

Class<?> intSetter = loader.loadClass(IntSetter.class.getName());
Class<?> intsSetter = loader.loadClass(IntArraySetter.class.getName());
Class<?> integersSetter = loader.loadClass(IntegerArraySetter.class.getName());

Assert.assertTrue(intSetter.isInstance(testObject));
Assert.assertTrue(intsSetter.isInstance(testObject));
Assert.assertTrue(integersSetter.isInstance(testObject));

int intValue = 99;
int[] intValues = {99, 100};
Integer[] integerValues = {99, 100};

Method setInt = intSetter.getMethod("_$PINPOINT$_setInt", int.class);
setInt.invoke(testObject, intValue);
Method getInt = testObject.getClass().getMethod("getIntValue");
Assert.assertEquals(intValue, getInt.invoke(testObject));

Method setInts = intsSetter.getMethod("_$PINPOINT$_setIntArray", int[].class);
setInts.invoke(testObject, intValues);
Method getInts = testObject.getClass().getMethod("getIntValues");
Assert.assertEquals(intValues, getInts.invoke(testObject));

Method setIntegers = integersSetter.getMethod("_$PINPOINT$_setIntegerArray", Integer[].class);
// wrap due to vararg expansion
Object[] wrappedIntegerValues = new Object[]{integerValues};
setIntegers.invoke(testObject, wrappedIntegerValues);
Method getIntegers = testObject.getClass().getMethod("getIntegerValues");
Assert.assertEquals(integerValues, getIntegers.invoke(testObject));
}


Expand Down
Loading

0 comments on commit 152ab88

Please # to comment.