[#2812] improves the PlainClassLoaderHandler from storing class bytecode & add internal class metadata.

This commit is contained in:
jaehong-kim
2017-04-20 16:16:06 +09:00
committed by Jaehong Kim
parent 2ed0f72fd7
commit 815b602085
18 changed files with 721 additions and 83 deletions
@@ -30,7 +30,6 @@ import com.navercorp.pinpoint.profiler.util.JavaAssistUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
@@ -153,15 +152,23 @@ public class PlainClassLoaderHandler implements ClassInjector {
}
private InputStream getInputStream(ClassLoader classLoader, String className) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException {
private InputStream getInputStream(ClassLoader classLoader, String classPath) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException {
if (isDebug) {
logger.debug("Get input stream className:{} cl:{}", className, classLoader);
logger.debug("Get input stream className:{} cl:{}", classPath, classLoader);
}
final String pluginJarPath = pluginConfig.getPluginJarURLExternalForm();
final ClassLoaderAttachment attachment = getClassLoaderAttachment(classLoader, pluginJarPath);
final InputStream inputStream = attachment.getInputStream(className);
return inputStream;
try {
return pluginJarReader.getInputStream(classPath);
} catch(Exception ex) {
if (isDebug) {
logger.debug("Failed to read plugin jar: {}", pluginConfig.getPluginJarURLExternalForm(), ex);
}
}
// not found.
return null;
}
private ClassLoaderAttachment getClassLoaderAttachment(ClassLoader classLoader, final String pluginJarPath) {
@@ -291,9 +298,7 @@ public class PlainClassLoaderHandler implements ClassInjector {
}
final Class<?> clazz = defineClass(classLoader, currentClass);
currentClass.setDefinedClass(clazz);
attachment.putClass(currentClass.getClassName(), currentClass);
attachment.putClass(currentClass.getClassName(), clazz);
}
private Class<?> defineClass(ClassLoader classLoader, SimpleClassMetadata classMetadata) {
@@ -343,7 +348,7 @@ public class PlainClassLoaderHandler implements ClassInjector {
private final ConcurrentMap<String, PluginLock> pluginLock = new ConcurrentHashMap<String, PluginLock>();
private final ConcurrentMap<String, SimpleClassMetadata> classCache = new ConcurrentHashMap<String, SimpleClassMetadata>();
private final ConcurrentMap<String, Class<?>> classCache = new ConcurrentHashMap<String, Class<?>>();
public PluginLock getPluginLock(String jarFile) {
final PluginLock exist = this.pluginLock.get(jarFile);
@@ -359,8 +364,8 @@ public class PlainClassLoaderHandler implements ClassInjector {
return newPluginLock;
}
public void putClass(String className, SimpleClassMetadata classMetadata) {
final SimpleClassMetadata duplicatedClass = this.classCache.putIfAbsent(className, classMetadata);
public void putClass(String className, Class<?> clazz) {
final Class<?> duplicatedClass = this.classCache.putIfAbsent(className, clazz);
if (duplicatedClass != null) {
if (logger.isWarnEnabled()) {
logger.warn("duplicated pluginClass {}", className);
@@ -369,27 +374,12 @@ public class PlainClassLoaderHandler implements ClassInjector {
}
public Class<?> getClass(String className) {
final SimpleClassMetadata classMetadata = this.classCache.get(className);
if(classMetadata == null) {
return null;
}
return classMetadata.getDefinedClass();
return this.classCache.get(className);
}
public boolean containsClass(String className) {
return this.classCache.containsKey(className);
}
public InputStream getInputStream(String className) {
final SimpleClassMetadata classMetadata = this.classCache.get(className);
if (classMetadata == null) {
return null;
}
return new ByteArrayInputStream(classMetadata.getClassBinary());
}
}
private static class PluginLock {
@@ -0,0 +1,52 @@
/*
* Copyright 2017 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.instrument.classreading;
import org.objectweb.asm.AnnotationVisitor;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
import java.util.ArrayList;
import java.util.List;
/**
* @author jaehong.kim
*/
public class AnnotationMetadataVisitor extends ClassVisitor {
private final List<String> annotationInternalNames = new ArrayList<String>();
public AnnotationMetadataVisitor() {
super(Opcodes.ASM5);
}
@Override
public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
final Type type = Type.getType(desc);
if (type.getSort() == Type.OBJECT) {
final String internalName = type.getInternalName();
if (internalName != null) {
this.annotationInternalNames.add(internalName);
}
}
return null;
}
public List<String> getAnnotationInternalNames() {
return this.annotationInternalNames;
}
}
@@ -0,0 +1,98 @@
/*
* Copyright 2017 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.instrument.classreading;
import com.navercorp.pinpoint.common.util.Asserts;
import org.objectweb.asm.ClassReader;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import java.util.List;
/**
* @author jaehong.kim
*/
public class ClassReaderWrapper {
// wrapped ASM ClassReader.
private final ClassReader classReader;
// bytecodes of the class.
public ClassReaderWrapper(final byte[] classBinary) {
Asserts.notNull(classBinary, "classBinary");
this.classReader = new ClassReader(classBinary);
}
// classloader and class internal name.
public ClassReaderWrapper(final ClassLoader classLoader, final String classInternalName) throws IOException {
Asserts.notNull(classInternalName, "classInternalName");
ClassLoader cl = classLoader;
if (cl == null) {
cl = ClassLoader.getSystemClassLoader();
if (cl == null) {
// system fail.
throw new IOException("system classloader is null.");
}
}
final InputStream in = cl.getResourceAsStream(classInternalName + ".class");
if (in == null) {
throw new IOException("not found class. classLoader=" + cl + ", classInternalName=" + classInternalName);
}
try {
this.classReader = new ClassReader(in);
} finally {
try {
in.close();
} catch (IOException ignored) {
}
}
}
// class's access flags.
public int getAccess() {
return this.classReader.getAccess();
}
// class version.
public int getVersion() {
return this.classReader.readShort(6);
}
public String getSuperClassInternalName() {
return this.classReader.getSuperName();
}
public String getClassInternalName() {
return this.classReader.getClassName();
}
public List<String> getInterfaceInternalNames() {
return Arrays.asList(this.classReader.getInterfaces());
}
public byte[] getClassBinary() {
return this.classReader.b;
}
public List<String> getAnnotationInternalNames() {
// annotation visitor.
final AnnotationMetadataVisitor annotationMetadataVisitor = new AnnotationMetadataVisitor();
this.classReader.accept(annotationMetadataVisitor, 0);
return annotationMetadataVisitor.getAnnotationInternalNames();
}
}
@@ -0,0 +1,66 @@
/*
* Copyright 2017 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.instrument.classreading;
import java.util.Collections;
import java.util.List;
/**
* @author jaehong.kim
*/
public class DefaultInternalClassMetadata implements InternalClassMetadata {
private final String classInternalName;
private final String superClassInternalName;
private final List<String> interfaceInternalNames;
private final List<String> annotationInternalNames;
public DefaultInternalClassMetadata(final String classInternalName, final String superClassInternalName, final List<String> interfaceInternalNames, final List<String> annotationInternalNames) {
this.classInternalName = classInternalName;
this.superClassInternalName = superClassInternalName;
if (interfaceInternalNames == null) {
this.interfaceInternalNames = Collections.EMPTY_LIST;
} else {
this.interfaceInternalNames = Collections.unmodifiableList(interfaceInternalNames);
}
if (annotationInternalNames == null) {
this.annotationInternalNames = Collections.EMPTY_LIST;
} else {
this.annotationInternalNames = Collections.unmodifiableList(annotationInternalNames);
}
}
@Override
public String getClassInternalName() {
return this.classInternalName;
}
@Override
public String getSuperClassInternalName() {
return this.superClassInternalName;
}
@Override
public List<String> getInterfaceInternalNames() {
return this.interfaceInternalNames;
}
@Override
public List<String> getAnnotationInternalNames() {
return this.annotationInternalNames;
}
}
@@ -17,9 +17,9 @@
package com.navercorp.pinpoint.profiler.instrument.classreading;
import com.navercorp.pinpoint.profiler.util.JavaAssistUtils;
import java.util.Collections;
import java.util.List;
/**
@@ -36,18 +36,27 @@ public class DefaultSimpleClassMetadata implements SimpleClassMetadata {
private final String superClassName;
private final List<String> interfaceNameList;
private final List<String> interfaceNames;
private final byte[] classBinary;
private Class<?> definedClass;
public DefaultSimpleClassMetadata(int version, int accessFlag, String className, String superClassName, String[] interfaceNameList, byte[] classBinary) {
public DefaultSimpleClassMetadata(final int version, final int accessFlag, final String classInternalName, final String superClassInternalName, final List<String> interfaceInternalNames, final byte[] classBinary) {
this.version = version;
this.accessFlag = accessFlag;
this.className = JavaAssistUtils.jvmNameToJavaName(className);
this.superClassName = JavaAssistUtils.jvmNameToJavaName(superClassName);
this.interfaceNameList = JavaAssistUtils.jvmNameToJavaName(interfaceNameList);
this.className = JavaAssistUtils.jvmNameToJavaName(classInternalName);
if (superClassInternalName == null) {
this.superClassName = null;
} else {
this.superClassName = JavaAssistUtils.jvmNameToJavaName(superClassInternalName);
}
if (interfaceInternalNames == null) {
this.interfaceNames = Collections.EMPTY_LIST;
} else {
this.interfaceNames = Collections.unmodifiableList(JavaAssistUtils.jvmNameToJavaName(interfaceInternalNames));
}
this.classBinary = classBinary;
}
@@ -72,20 +81,11 @@ public class DefaultSimpleClassMetadata implements SimpleClassMetadata {
@Override
public List<String> getInterfaceNames() {
return interfaceNameList;
return interfaceNames;
}
@Override
public byte[] getClassBinary() {
return classBinary;
}
public void setDefinedClass(final Class<?> definedClass) {
this.definedClass = definedClass;
}
@Override
public Class<?> getDefinedClass() {
return this.definedClass;
}
}
@@ -0,0 +1,36 @@
/*
* Copyright 2017 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.instrument.classreading;
import java.util.List;
/**
* @author jaehong.kim
*/
public interface InternalClassMetadata {
// internal name of the class.
String getClassInternalName();
// internal name of the super class.
String getSuperClassInternalName();
// internal names of the class's interfaces.
List<String> getInterfaceInternalNames();
// internal names of the class's annotations.
List<String> getAnnotationInternalNames();
}
@@ -0,0 +1,49 @@
/*
* Copyright 2017 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.instrument.classreading;
import org.objectweb.asm.ClassReader;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
/**
* @author jaehong.kim
*/
public class InternalClassMetadataReader {
private final InternalClassMetadata classMetadata;
public static InternalClassMetadata readInternalClassMetadata(final byte[] classBinary) {
final InternalClassMetadataReader internalClassMetadataReader = new InternalClassMetadataReader(new ClassReaderWrapper(classBinary));
return internalClassMetadataReader.getInternalClassMetadata();
}
public static InternalClassMetadata readInternalClassMetadata(final ClassLoader classLoader, final String classInternalName) throws IOException {
final InternalClassMetadataReader internalClassMetadataReader = new InternalClassMetadataReader(new ClassReaderWrapper(classLoader, classInternalName));
return internalClassMetadataReader.getInternalClassMetadata();
}
InternalClassMetadataReader(final ClassReaderWrapper classReader) {
this.classMetadata = new DefaultInternalClassMetadata(classReader.getClassInternalName(), classReader.getSuperClassInternalName(), classReader.getInterfaceInternalNames(), classReader.getAnnotationInternalNames());
}
public InternalClassMetadata getInternalClassMetadata() {
return classMetadata;
}
}
@@ -35,8 +35,4 @@ public interface SimpleClassMetadata {
List<String> getInterfaceNames();
byte[] getClassBinary();
void setDefinedClass(Class<?> definedClass);
Class<?> getDefinedClass();
}
}
@@ -17,8 +17,6 @@
package com.navercorp.pinpoint.profiler.instrument.classreading;
import org.objectweb.asm.ClassReader;
/**
* @author Woonduk Kang(emeroad)
*/
@@ -26,34 +24,16 @@ public class SimpleClassMetadataReader {
private final SimpleClassMetadata simpleClassMetadata;
public static SimpleClassMetadata readSimpleClassMetadata(byte[] classBinary) {
SimpleClassMetadataReader simpleClassMetadataReader = new SimpleClassMetadataReader(classBinary);
public static SimpleClassMetadata readSimpleClassMetadata(final byte[] classBinary) {
final SimpleClassMetadataReader simpleClassMetadataReader = new SimpleClassMetadataReader(new ClassReaderWrapper(classBinary));
return simpleClassMetadataReader.getSimpleClassMetadata();
}
SimpleClassMetadataReader(byte[] classBinary) {
if (classBinary == null) {
throw new NullPointerException("classBinary must not be null");
}
final ClassReader classReader = new ClassReader(classBinary);
int accessFlag = classReader.getAccess();
String className = classReader.getClassName();
String superClassName = classReader.getSuperName();
String[] interfaceNameList = classReader.getInterfaces();
// int offset = 0;
// int version = classReader.readShort(offset + 6);
// offset is zero
int version = classReader.readShort(6);
this.simpleClassMetadata = new DefaultSimpleClassMetadata(version, accessFlag, className, superClassName, interfaceNameList, classBinary);
SimpleClassMetadataReader(final ClassReaderWrapper classReader) {
this.simpleClassMetadata = new DefaultSimpleClassMetadata(classReader.getVersion(), classReader.getAccess(), classReader.getClassInternalName(), classReader.getSuperClassInternalName(), classReader.getInterfaceInternalNames(), classReader.getClassBinary());
}
public SimpleClassMetadata getSimpleClassMetadata() {
return simpleClassMetadata;
}
}
}
@@ -49,6 +49,15 @@ public class JarReader {
this.jarFile = jarFile;
}
public InputStream getInputStream(String name) throws IOException {
final JarEntry jarEntry = this.jarFile.getJarEntry(name);
if (jarEntry != null) {
return this.jarFile.getInputStream(jarEntry);
}
return null;
}
public List<FileBinary> read(JarEntryFilter jarEntryFilter) throws IOException{
if (jarEntryFilter == null) {
throw new NullPointerException("jarEntryFilter must not be null");
@@ -125,6 +134,4 @@ public class JarReader {
}
}
}
}
@@ -183,11 +183,12 @@ public final class JavaAssistUtils {
* @param jvmNameArray
* @return
*/
public static List<String> jvmNameToJavaName(String[] jvmNameArray) {
public static List<String> jvmNameToJavaName(List<String> jvmNameArray) {
if (jvmNameArray == null) {
return Collections.emptyList();
}
List<String> list = new ArrayList<String>(jvmNameArray.length);
List<String> list = new ArrayList<String>(jvmNameArray.size());
for (String jvmName : jvmNameArray) {
list.add(jvmNameToJavaName(jvmName));
}
@@ -0,0 +1,109 @@
/*
* Copyright 2017 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.instrument.classreading;
import com.navercorp.pinpoint.profiler.util.JavaAssistUtils;
import org.junit.Test;
import org.objectweb.asm.ClassReader;
import java.io.InputStream;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
/**
* @author jaehong.kim
*/
public class AnnotationMetadataVisitorTest {
@Test
public void visitAnnotation() throws Exception {
final ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
InputStream in = classLoader.getResourceAsStream(JavaAssistUtils.javaNameToJvmName(HasAnnotation.class.getName()) + ".class");
AnnotationMetadataVisitor visitor = new AnnotationMetadataVisitor();
ClassReader reader = new ClassReader(in);
in.close();
reader.accept(visitor, 0);
assertTrue(visitor.getAnnotationInternalNames().contains(JavaAssistUtils.javaNameToJvmName(SimpleClassAnnotation.class.getName())));
assertTrue(visitor.getAnnotationInternalNames().contains(JavaAssistUtils.javaNameToJvmName(RetentionPolicyClassAnnotation.class.getName())));
assertTrue(visitor.getAnnotationInternalNames().contains(JavaAssistUtils.javaNameToJvmName(RetentionPolicyRuntimeAnnotation.class.getName())));
// skip source
assertFalse(visitor.getAnnotationInternalNames().contains(JavaAssistUtils.javaNameToJvmName(RetentionPolicySourceAnnotation.class.getName())));
}
@Test
public void visitMetaAnnotation() throws Exception {
final ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
InputStream in = classLoader.getResourceAsStream(JavaAssistUtils.javaNameToJvmName(HasMetaAnnotation.class.getName()) + ".class");
AnnotationMetadataVisitor visitor = new AnnotationMetadataVisitor();
ClassReader reader = new ClassReader(in);
in.close();
reader.accept(visitor, 0);
assertTrue(visitor.getAnnotationInternalNames().contains(JavaAssistUtils.javaNameToJvmName(NestedMetaAnnotation.class.getName())));
// no consider hierarchy.
assertFalse(visitor.getAnnotationInternalNames().contains(JavaAssistUtils.javaNameToJvmName(RetentionPolicyClassAnnotation.class.getName())));
}
@Documented
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.CLASS)
@interface SimpleClassAnnotation {
}
@Documented
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.CLASS)
@interface RetentionPolicyClassAnnotation {
}
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface RetentionPolicyRuntimeAnnotation {
}
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.SOURCE)
@interface RetentionPolicySourceAnnotation {
}
@RetentionPolicyClassAnnotation
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.CLASS)
@interface NestedMetaAnnotation {
}
@SimpleClassAnnotation
@RetentionPolicyClassAnnotation
@RetentionPolicyRuntimeAnnotation
@RetentionPolicySourceAnnotation
class HasAnnotation {
}
@NestedMetaAnnotation
class HasMetaAnnotation {
}
}
@@ -0,0 +1,66 @@
/*
* Copyright 2017 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.instrument.classreading;
import com.navercorp.pinpoint.common.util.ClassLoaderUtils;
import com.navercorp.pinpoint.profiler.util.BytecodeUtils;
import com.navercorp.pinpoint.profiler.util.JavaAssistUtils;
import org.junit.Test;
import javax.annotation.Resource;
import java.io.ByteArrayInputStream;
import java.lang.annotation.Target;
import static org.junit.Assert.*;
/**
* @author jaehong.kim
*/
public class ClassReaderWrapperTest {
@Test
public void base() throws Exception {
final Class<?> clazz = String.class;
final byte[] classBinary = BytecodeUtils.getClassFile(ClassLoaderUtils.getDefaultClassLoader(), clazz.getName());
assertClassReader(new ClassReaderWrapper(classBinary));
assertClassReader(new ClassReaderWrapper(ClassLoaderUtils.getDefaultClassLoader(), JavaAssistUtils.javaNameToJvmName(clazz.getName())));
}
@Test
public void annotation() throws Exception {
ClassReaderWrapper classReader = new ClassReaderWrapper(ClassLoaderUtils.getDefaultClassLoader(), JavaAssistUtils.javaNameToJvmName(AnnotationMock.class.getName()));
classReader.getAnnotationInternalNames().contains("java/lang/Deprecated");
classReader.getAnnotationInternalNames().contains("javax/annotation/Resource");
}
private void assertClassReader(ClassReaderWrapper classReader) {
assertEquals("java/lang/String", classReader.getClassInternalName());
assertEquals("java/lang/Object", classReader.getSuperClassInternalName());
System.out.println(classReader.getInterfaceInternalNames());
assertTrue(classReader.getInterfaceInternalNames().contains("java/lang/Comparable"));
assertTrue(classReader.getInterfaceInternalNames().contains("java/io/Serializable"));
classReader.getVersion();
classReader.getAccess();
assertNotNull(classReader.getClassBinary());
}
@Deprecated
@Resource
class AnnotationMock {
}
}
@@ -0,0 +1,55 @@
/*
* Copyright 2017 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.instrument.classreading;
import org.junit.Test;
import java.util.Arrays;
import java.util.Collections;
import static org.junit.Assert.*;
/**
* @author jaehong.kim
*/
public class DefaultInternalClassMetadataTest {
@Test
public void base() throws Exception {
DefaultInternalClassMetadata classMetadata = new DefaultInternalClassMetadata("java/lang/String", "java/lang/Object", Arrays.asList("java/lang/Comparable", "java/lang/Serializable"), Collections.EMPTY_LIST);
// name
assertEquals("java/lang/String", classMetadata.getClassInternalName());
// super
assertEquals("java/lang/Object", classMetadata.getSuperClassInternalName());
// interfaces
assertTrue(classMetadata.getInterfaceInternalNames().contains("java/lang/Comparable"));
assertTrue(classMetadata.getInterfaceInternalNames().contains("java/lang/Serializable"));
// annotation
assertEquals(0, classMetadata.getAnnotationInternalNames().size());
}
@Test
public void interfaceNamesNull() throws Exception {
DefaultInternalClassMetadata classMetadata = new DefaultInternalClassMetadata("java/lang/String", "java/lang/Object", null, Collections.EMPTY_LIST);
assertEquals(0, classMetadata.getInterfaceInternalNames().size());
}
@Test
public void annotationNamesNull() throws Exception {
DefaultInternalClassMetadata classMetadata = new DefaultInternalClassMetadata("java/lang/String", "java/lang/Object", Arrays.asList("java/lang/Comparable", "java/lang/Serializable"), null);
assertEquals(0, classMetadata.getAnnotationInternalNames().size());
}
}
@@ -0,0 +1,48 @@
/*
* Copyright 2017 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.instrument.classreading;
import org.junit.Test;
import java.util.Arrays;
import static org.junit.Assert.*;
/**
* @author jaehong.kim
*/
public class DefaultSimpleClassMetadataTest {
@Test
public void base() throws Exception {
final byte[] classBinary = new byte[1];
DefaultSimpleClassMetadata classMetadata = new DefaultSimpleClassMetadata(1, 1, "java/lang/String", "java/lang/Object", Arrays.asList("java/lang/Comparable", "java/lang/Serializable"), classBinary);
assertEquals("java.lang.String", classMetadata.getClassName());
assertEquals("java.lang.Object", classMetadata.getSuperClassName());
assertTrue(classMetadata.getInterfaceNames().contains("java.lang.Comparable"));
assertTrue(classMetadata.getInterfaceNames().contains("java.lang.Serializable"));
assertEquals(1, classMetadata.getAccessFlag());
assertEquals(1, classMetadata.getVersion());
assertEquals(classBinary, classMetadata.getClassBinary());
}
@Test
public void interfaceNameNull() throws Exception {
final byte[] classBinary = new byte[1];
DefaultSimpleClassMetadata classMetadata = new DefaultSimpleClassMetadata(1, 1, "java/lang/String", "java/lang/Object", null, classBinary);
assertEquals(0, classMetadata.getInterfaceNames().size());
}
}
@@ -0,0 +1,71 @@
/*
* Copyright 2017 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.instrument.classreading;
import com.google.common.base.Function;
import com.google.common.collect.Lists;
import com.navercorp.pinpoint.common.util.ClassLoaderUtils;
import com.navercorp.pinpoint.profiler.util.BytecodeUtils;
import com.navercorp.pinpoint.profiler.util.JavaAssistUtils;
import org.junit.Test;
import java.lang.annotation.Annotation;
import java.util.List;
import static org.junit.Assert.*;
/**
* @author jaehong.kim
*/
public class InternalClassMetadataReaderTest {
@Test
public void getInternalClassMetadata() throws Exception {
final Class<?> clazz = String.class;
final byte[] classBinary = BytecodeUtils.getClassFile(ClassLoaderUtils.getDefaultClassLoader(), clazz.getName());
InternalClassMetadata classMetadata = InternalClassMetadataReader.readInternalClassMetadata(classBinary);
// name
assertEquals(JavaAssistUtils.javaNameToJvmName(clazz.getName()), classMetadata.getClassInternalName());
// interfaces
for(Class interfacez : clazz.getInterfaces()) {
final String interfaceInternalName = JavaAssistUtils.javaNameToJvmName(interfacez.getName());
classMetadata.getInterfaceInternalNames().contains(interfaceInternalName);
}
// super
assertEquals("java/lang/Object", classMetadata.getSuperClassInternalName());
// annotations
for (Annotation annotation : clazz.getAnnotations()) {
final String annotationInternalName = JavaAssistUtils.javaNameToJvmName(annotation.annotationType().getName());
classMetadata.getAnnotationInternalNames().contains(annotationInternalName);
}
}
@Test
public void SuperIsNull() throws Exception {
final Class<?> clazz = Object.class;
final byte[] classBinary = BytecodeUtils.getClassFile(ClassLoaderUtils.getDefaultClassLoader(), clazz.getName());
InternalClassMetadata classMetadata = InternalClassMetadataReader.readInternalClassMetadata(classBinary);
// name
assertEquals(JavaAssistUtils.javaNameToJvmName(clazz.getName()), classMetadata.getClassInternalName());
// super
assertNull(classMetadata.getSuperClassInternalName());
}
}
@@ -42,19 +42,24 @@ public class SimpleClassMetadataReaderTest {
byte[] classFile = BytecodeUtils.getClassFile(ClassLoaderUtils.getDefaultClassLoader(), clazz.getName());
SimpleClassMetadata simpleClassMetadata = SimpleClassMetadataReader.readSimpleClassMetadata(classFile);
// name.
Assert.assertEquals(simpleClassMetadata.getClassName(), clazz.getName());
// interfaces
List<String> interfaceList = getInterfaceList(clazz.getInterfaces());
List<String> interfaceNames = simpleClassMetadata.getInterfaceNames();
Assert.assertThat(interfaceNames, containsInAnyOrder(interfaceList.toArray()));
// super
Assert.assertEquals(simpleClassMetadata.getSuperClassName(), "java.lang.Object");
// access
simpleClassMetadata.getAccessFlag();
// version
simpleClassMetadata.getVersion();
}
private List<String> getInterfaceList(Class<?>[] interfaces) {
List<Class<?>> collection = Lists.newArrayList(interfaces);
return Lists.transform(collection, new Function<Class<?>, String>() {
@Override
@@ -63,5 +68,4 @@ public class SimpleClassMetadataReaderTest {
}
});
}
}
@@ -23,6 +23,7 @@ import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.InputStream;
import java.net.URL;
import java.util.List;
import java.util.jar.JarFile;
@@ -48,4 +49,13 @@ public class JarReaderTest {
Assert.assertThat(fileBinary.getFileName(), Matchers.endsWith(".class"));
}
}
@Test
public void getInputStream() throws Exception {
URL location = Logger.class.getProtectionDomain().getCodeSource().getLocation();
JarFile jarFile = new JarFile(location.getPath());
JarReader jarReader = new JarReader(jarFile);
Assert.assertNotNull(jarReader.getInputStream("org/slf4j/Logger.class"));
Assert.assertNull(jarReader.getInputStream("org/slf4j/NotFound.class"));
}
}