spring-loaded QuickVisitor 代码
文件路径:/springloaded/src/main/java/org/springsource/loaded/QuickVisitor.java
/*
* Copyright 2010-2012 VMware and contributors
*
* 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
*
* https://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 org.springsource.loaded;
import org.objectweb.asm.ClassReader;
/**
* Can be used to take a quick look in the bytecode for something. The various static get* methods are the things that
* the quick visitor can discover.
*
* @author Andy Clement
* @since 0.7.3
*/
public class QuickVisitor {
public static String[] getImplementedInterfaces(byte[] bytes) {
ClassReader fileReader = new ClassReader(bytes);
QuickVisitor1 qv = new QuickVisitor1();
try {
fileReader.accept(qv, ClassReader.SKIP_FRAMES);/ TODO more flags to skip other things?
}
catch (EarlyExitException eee) {
}
return qv.interfaces;
}
static class QuickVisitor1 extends EmptyClassVisitor {
String[] interfaces;
@Override
public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
this.interfaces = interfaces;
/ TODO is it truly easier to exit via exception than to visit the rest of it?
throw new EarlyExitException();
}
}
@SuppressWarnings("serial")
private static class EarlyExitException extends RuntimeException {
}
/ public static int investigate(String slashedClassName, byte[] bytes) {
/ ClassReader fileReader = new ClassReader(bytes);
/ RewriteClassAdaptor classAdaptor = new RewriteClassAdaptor();
/ fileReader.accept(classAdaptor, ClassReader.SKIP_FRAMES);
/ return classAdaptor.hitCount;
/ }
/
/ static class RewriteClassAdaptor extends ClassAdapter implements Constants {
/
/ int hitCount = 0;
/ private ClassWriter cw;
/ int bits = 0x0000;
/ private String classname;
/
/ private static boolean isInterceptable(String owner, String methodName) {
/ return MethodInvokerRewriter.RewriteClassAdaptor.intercepted.contains(owner + "." + methodName);
/ }
/
/ public RewriteClassAdaptor() {
/ / TODO should it also compute frames?
/ super(new ClassWriter(ClassWriter.COMPUTE_MAXS));
/ cw = (ClassWriter) cv;
/ }
/
/ public byte[] getBytes() {
/ byte[] bytes = cw.toByteArray();
/ return bytes;
/ }
/
/ public int getBits() {
/ return bits;
/ }
/
/ @Override
/ public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
/ super.visit(version, access, name, signature, superName, interfaces);
/ this.classname = name;
/ }
/
/ @Override
/ public MethodVisitor visitMethod(int flags, String name, String descriptor, String signature, String[] exceptions) {
/ MethodVisitor mv = super.visitMethod(flags, name, descriptor, signature, exceptions);
/ return new RewritingMethodAdapter(mv);
/ }
/
/ class RewritingMethodAdapter extends MethodAdapter implements Opcodes, Constants {
/
/ public RewritingMethodAdapter(MethodVisitor mv) {
/ super(mv);
/ }
/
/ private boolean interceptReflection(String owner, String name, String desc) {
/ if (isInterceptable(owner, name)) {
/ hitCount++;
/ System.out.println("SystemClassReflectionInvestigator: " + classname + " uses " + owner + "." + name + desc);
/ }
/ return false;
/ }
/
/ int unitializedObjectsCount = 0;
/
/ @Override
/ public void visitTypeInsn(final int opcode, final String type) {
/ if (opcode == NEW) {
/ unitializedObjectsCount++;
/ }
/ super.visitTypeInsn(opcode, type);
/ }
/
/ @Override
/ public void visitMethodInsn(final int opcode, final String owner, final String name, final String desc) {
/ if (!GlobalConfiguration.interceptReflection || rewriteReflectiveCall(opcode, owner, name, desc)) {
/ return;
/ }
/ if (opcode == INVOKESPECIAL) {
/ unitializedObjectsCount--;
/ }
/ super.visitMethodInsn(opcode, owner, name, desc);
/ }
/
/ /**
/ * Determine if a method call is a reflective call and an attempt should be made to rewrite it.
/ *
/ * @return true if the call was rewritten
/ */
/ private boolean rewriteReflectiveCall(int opcode, String owner, String name, String desc) {
/ if (owner.length() > 10 && owner.charAt(8) == 'g'
/ && (owner.startsWith("java/lang/reflect/") || owner.equals("java/lang/Class"))) {
/ boolean rewritten = interceptReflection(owner, name, desc);
/ if (rewritten) {
/ return true;
/ }
/ }
/ return false;
/ }
/
/ }
/ }
}
相关信息
相关文章
spring-loaded AbstractMember 源码
spring-loaded AnyTypePattern 源码
spring-loaded ChildClassLoader 源码
spring-loaded ConstantPoolChecker 源码
spring-loaded ConstantPoolChecker2 源码