mirror of
https://github.com/wahyd4/pinpoint.git
synced 2026-08-09 04:46:06 +10:00
[#2812] improves the PlainClassLoaderHandler from storing class bytecode & add internal class metadata.
This commit is contained in:
+17
-27
@@ -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 {
|
||||
|
||||
+52
@@ -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;
|
||||
}
|
||||
}
|
||||
+98
@@ -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();
|
||||
}
|
||||
}
|
||||
+66
@@ -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;
|
||||
}
|
||||
}
|
||||
+18
-18
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
+36
@@ -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();
|
||||
}
|
||||
+49
@@ -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;
|
||||
}
|
||||
}
|
||||
+1
-5
@@ -35,8 +35,4 @@ public interface SimpleClassMetadata {
|
||||
List<String> getInterfaceNames();
|
||||
|
||||
byte[] getClassBinary();
|
||||
|
||||
void setDefinedClass(Class<?> definedClass);
|
||||
|
||||
Class<?> getDefinedClass();
|
||||
}
|
||||
}
|
||||
+5
-25
@@ -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));
|
||||
}
|
||||
|
||||
+109
@@ -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 {
|
||||
}
|
||||
}
|
||||
+66
@@ -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 {
|
||||
}
|
||||
}
|
||||
+55
@@ -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());
|
||||
}
|
||||
}
|
||||
+48
@@ -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());
|
||||
}
|
||||
}
|
||||
+71
@@ -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());
|
||||
}
|
||||
|
||||
}
|
||||
+8
-4
@@ -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"));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user