Repository: pinpoint-apm/pinpoint
Issue: Fails to inject array-typed fields, or getters/setters for array-typed fields
Labels: bug

https://groups.google.com/forum/#!topic/pinpoint_user/-PutLtVn5rc

When injecting array-typed fields:
The agent currently invokes `Class.getName()` on the field's type to generate the field signature when injecting a field into a class. The `getName()` method on an array class returns a form not suitable for generating signatures (ie int[] -> [I).

When adding getter/setter for array-typed fields
Type checking is done by comparing Javassist's `CtClass.getName()` and `Class.getName()`. This comparison fails for array classes due to reason similar to above.
For an array of int, `CtClass.getName()` returns int[] whereas `Class.getName()` again returns [I, failing the check.


Issue comments:

Pull request review comments:

Patch that resolved the issue:
diff --git a/profiler/src/main/java/com/navercorp/pinpoint/profiler/instrument/JavassistClass.java b/profiler/src/main/java/com/navercorp/pinpoint/profiler/instrument/JavassistClass.java
index a4b3846419ad..b8988f55a108 100644
--- a/profiler/src/main/java/com/navercorp/pinpoint/profiler/instrument/JavassistClass.java
+++ b/profiler/src/main/java/com/navercorp/pinpoint/profiler/instrument/JavassistClass.java
@@ -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);
@@ -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());
             }
 
@@ -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());
             }
 
diff --git a/profiler/src/main/java/com/navercorp/pinpoint/profiler/util/JavaAssistUtils.java b/profiler/src/main/java/com/navercorp/pinpoint/profiler/util/JavaAssistUtils.java
index d0435d269ea6..7b90d8947d52 100644
--- a/profiler/src/main/java/com/navercorp/pinpoint/profiler/util/JavaAssistUtils.java
+++ b/profiler/src/main/java/com/navercorp/pinpoint/profiler/util/JavaAssistUtils.java
@@ -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) {


Test patch:
diff --git a/profiler/src/test/java/com/navercorp/pinpoint/profiler/interceptor/bci/IntArrayGetter.java b/profiler/src/test/java/com/navercorp/pinpoint/profiler/interceptor/bci/IntArrayGetter.java
new file mode 100644
index 000000000000..b02e42053623
--- /dev/null
+++ b/profiler/src/test/java/com/navercorp/pinpoint/profiler/interceptor/bci/IntArrayGetter.java
@@ -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();
+}
diff --git a/profiler/src/test/java/com/navercorp/pinpoint/profiler/interceptor/bci/IntArraySetter.java b/profiler/src/test/java/com/navercorp/pinpoint/profiler/interceptor/bci/IntArraySetter.java
new file mode 100644
index 000000000000..a8ab44f32daa
--- /dev/null
+++ b/profiler/src/test/java/com/navercorp/pinpoint/profiler/interceptor/bci/IntArraySetter.java
@@ -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);
+}
diff --git a/profiler/src/test/java/com/navercorp/pinpoint/profiler/interceptor/bci/IntArrayTraceValue.java b/profiler/src/test/java/com/navercorp/pinpoint/profiler/interceptor/bci/IntArrayTraceValue.java
new file mode 100644
index 000000000000..0f58ed20ec09
--- /dev/null
+++ b/profiler/src/test/java/com/navercorp/pinpoint/profiler/interceptor/bci/IntArrayTraceValue.java
@@ -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();
+}
diff --git a/profiler/src/test/java/com/navercorp/pinpoint/profiler/interceptor/bci/IntSetter.java b/profiler/src/test/java/com/navercorp/pinpoint/profiler/interceptor/bci/IntSetter.java
new file mode 100644
index 000000000000..96cc1ea10c04
--- /dev/null
+++ b/profiler/src/test/java/com/navercorp/pinpoint/profiler/interceptor/bci/IntSetter.java
@@ -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);
+}
diff --git a/profiler/src/test/java/com/navercorp/pinpoint/profiler/interceptor/bci/IntegerArrayGetter.java b/profiler/src/test/java/com/navercorp/pinpoint/profiler/interceptor/bci/IntegerArrayGetter.java
new file mode 100644
index 000000000000..5984febcfa54
--- /dev/null
+++ b/profiler/src/test/java/com/navercorp/pinpoint/profiler/interceptor/bci/IntegerArrayGetter.java
@@ -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();
+}
diff --git a/profiler/src/test/java/com/navercorp/pinpoint/profiler/interceptor/bci/IntegerArraySetter.java b/profiler/src/test/java/com/navercorp/pinpoint/profiler/interceptor/bci/IntegerArraySetter.java
new file mode 100644
index 000000000000..b49308fcd687
--- /dev/null
+++ b/profiler/src/test/java/com/navercorp/pinpoint/profiler/interceptor/bci/IntegerArraySetter.java
@@ -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);
+}
diff --git a/profiler/src/test/java/com/navercorp/pinpoint/profiler/interceptor/bci/IntegerArrayTraceValue.java b/profiler/src/test/java/com/navercorp/pinpoint/profiler/interceptor/bci/IntegerArrayTraceValue.java
new file mode 100644
index 000000000000..0b69a32c4104
--- /dev/null
+++ b/profiler/src/test/java/com/navercorp/pinpoint/profiler/interceptor/bci/IntegerArrayTraceValue.java
@@ -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();
+}
diff --git a/profiler/src/test/java/com/navercorp/pinpoint/profiler/interceptor/bci/JavassistClassTest.java b/profiler/src/test/java/com/navercorp/pinpoint/profiler/interceptor/bci/JavassistClassTest.java
index 905a2c7f480c..0d817815e4b3 100644
--- a/profiler/src/test/java/com/navercorp/pinpoint/profiler/interceptor/bci/JavassistClassTest.java
+++ b/profiler/src/test/java/com/navercorp/pinpoint/profiler/interceptor/bci/JavassistClassTest.java
@@ -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());
 
@@ -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));
@@ -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
@@ -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) {
@@ -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);
@@ -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));
     }
 
 
diff --git a/profiler/src/test/java/com/navercorp/pinpoint/profiler/interceptor/bci/TestObject3.java b/profiler/src/test/java/com/navercorp/pinpoint/profiler/interceptor/bci/TestObject3.java
index 8ee9b70e3b15..fb6549fe6706 100644
--- a/profiler/src/test/java/com/navercorp/pinpoint/profiler/interceptor/bci/TestObject3.java
+++ b/profiler/src/test/java/com/navercorp/pinpoint/profiler/interceptor/bci/TestObject3.java
@@ -21,6 +21,8 @@
 public class TestObject3 {
     private String value;
     private int intValue;
+    private int[] intValues;
+    private Integer[] integerValues;
 
     public void setValue(String value) {
         this.value = value;
@@ -30,6 +32,14 @@ public void setIntValue(int value) {
         this.intValue = value;
     }
 
+    public void setIntValues(int[] values) {
+        this.intValues = values;
+    }
+
+    public void setIntegerValues(Integer[] values) {
+        this.integerValues = values;
+    }
+
     @Override
     public String toString() {
         return value;
diff --git a/profiler/src/test/java/com/navercorp/pinpoint/profiler/interceptor/bci/TestObject4.java b/profiler/src/test/java/com/navercorp/pinpoint/profiler/interceptor/bci/TestObject4.java
new file mode 100644
index 000000000000..ffd244e45fff
--- /dev/null
+++ b/profiler/src/test/java/com/navercorp/pinpoint/profiler/interceptor/bci/TestObject4.java
@@ -0,0 +1,38 @@
+/*
+ * 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 class TestObject4 {
+    private int intValue;
+    private int[] intValues;
+    private Integer[] integerValues;
+
+    public int getIntValue() {
+        return this.intValue;
+    }
+
+    public int[] getIntValues() {
+        return this.intValues;
+    }
+
+    public Integer[] getIntegerValues() {
+        return this.integerValues;
+    }
+}
diff --git a/profiler/src/test/java/com/navercorp/pinpoint/profiler/util/JavaAssistUtilsTest.java b/profiler/src/test/java/com/navercorp/pinpoint/profiler/util/JavaAssistUtilsTest.java
index e9d97df81828..62f404196836 100644
--- a/profiler/src/test/java/com/navercorp/pinpoint/profiler/util/JavaAssistUtilsTest.java
+++ b/profiler/src/test/java/com/navercorp/pinpoint/profiler/util/JavaAssistUtilsTest.java
@@ -24,10 +24,10 @@
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import com.navercorp.pinpoint.profiler.util.ApiUtils;
-import com.navercorp.pinpoint.profiler.util.JavaAssistUtils;
-
+import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
 
 /**
  * @author emeroad
@@ -71,6 +71,56 @@ public void javaArraySize() {
         Assert.assertEquals(JavaAssistUtils.getJavaObjectArraySize("java.lang.String[][]"), 2);
     }
 
+    @Test
+    public void javaClassNameToObjectName() {
+        // primitives
+        Assert.assertEquals("boolean", JavaAssistUtils.javaClassNameToObjectName(boolean.class.getName()));
+        Assert.assertEquals("byte", JavaAssistUtils.javaClassNameToObjectName(byte.class.getName()));
+        Assert.assertEquals("char", JavaAssistUtils.javaClassNameToObjectName(char.class.getName()));
+        Assert.assertEquals("double", JavaAssistUtils.javaClassNameToObjectName(double.class.getName()));
+        Assert.assertEquals("float", JavaAssistUtils.javaClassNameToObjectName(float.class.getName()));
+        Assert.assertEquals("int", JavaAssistUtils.javaClassNameToObjectName(int.class.getName()));
+        Assert.assertEquals("short", JavaAssistUtils.javaClassNameToObjectName(short.class.getName()));
+
+        // wrappers
+        Assert.assertEquals("java.lang.Integer", JavaAssistUtils.javaClassNameToObjectName(Integer.class.getName()));
+        Assert.assertEquals("java.lang.String", JavaAssistUtils.javaClassNameToObjectName(String.class.getName()));
+
+        // classes
+        Assert.assertEquals("java.util.List", JavaAssistUtils.javaClassNameToObjectName(List.class.getName()));
+        Assert.assertEquals("java.util.ArrayList", JavaAssistUtils.javaClassNameToObjectName(new ArrayList<Integer>().getClass().getName()));
+
+        // arrays
+        Assert.assertEquals("boolean[]", JavaAssistUtils.javaClassNameToObjectName(boolean[].class.getName()));
+        Assert.assertEquals("byte[]", JavaAssistUtils.javaClassNameToObjectName(byte[].class.getName()));
+        Assert.assertEquals("java.lang.String[]", JavaAssistUtils.javaClassNameToObjectName(String[].class.getName()));
+
+        // inner/nested classes
+        Assert.assertEquals(
+                this.getClass().getName() + "$1",
+                JavaAssistUtils.javaClassNameToObjectName(new Comparable<Long>() {
+                    @Override
+                    public int compareTo(Long o) {
+                        return 0;
+                    }
+                }.getClass().getName()));
+        class SomeComparable implements Comparable<Long> {
+            @Override
+            public int compareTo(Long o) {
+                return 0;
+            }
+        }
+        SomeComparable inner = new SomeComparable();
+        Assert.assertEquals(
+                this.getClass().getName() + "$1SomeComparable",
+                JavaAssistUtils.javaClassNameToObjectName(inner.getClass().getName())); // assume nothing else is defined in this class
+        Assert.assertEquals(
+                this.getClass().getName() + "$1SomeComparable[]",
+                JavaAssistUtils.javaClassNameToObjectName(new SomeComparable[] {inner}.getClass().getName()));
+        Assert.assertEquals("java.util.Map$Entry", JavaAssistUtils.javaClassNameToObjectName(Map.Entry.class.getName()));
+        Assert.assertEquals("java.util.Map$Entry[]", JavaAssistUtils.javaClassNameToObjectName(Map.Entry[].class.getName()));
+    }
+
 
     @Test
     public void toJvmSignature() {