ASM 5.0.3字节代码抛出NoClassDefFoundError oracle / security / pki / OraclePKIProvider

时间:2017-10-04 12:41:58

标签: java bytecode java-bytecode-asm

我正在使用ASM 5.0.3和Websphere 8.5.x以及IDM JDK 1.7来使用 org.objectweb.asm.commons.AdviceAdapter

分析方法执行时间

Oracle JDBC驱动程序 ojdbc7.jar 用于创建JDBC。我的应用程序工作正常,没有添加-javaagent参数。

当修改字节码时(通过-javaagent),Websphere启动正常但在访问应用程序时会抛出 java.lang.NoClassDefFoundError:oracle / security / pki / OraclePKIProvider

我找到了一个链接,详细解释了这个问题。显示某些JVM /驱动程序版本组合发生NoClassDefFoundError

https://plumbr.eu/blog/java/troubleshooting-verifiers-the-rabbit-hole-goes-deep

An exception occurred while invoking method setDataSourceProperties on com.ibm.ws.rsadapter.spi.WSManagedConnectionFactoryImpl used by resource jdbc/appDatasource : java.lang.NoClassDefFoundError: oracle/security/pki/OraclePKIProvider
 at oracle.jdbc.pool.OracleDataSource.<clinit>(OracleDataSource.java:103)
 at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
 at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
 at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
 at java.lang.reflect.Constructor.newInstance(Constructor.java:526)
 at java.lang.Class.newInstance(Class.java:383)
 at com.ibm.ws.rsadapter.DSConfigHelper.createDataSource(DSConfigHelper.java:747)
 at com.ibm.ws.rsadapter.spi.WSRdbDataSource.createNewDataSource(WSRdbDataSource.java:3029)
 at com.ibm.ws.rsadapter.spi.WSRdbDataSource.<init>(WSRdbDataSource.java:1358)
 at com.ibm.ws.rsadapter.spi.WSManagedConnectionFactoryImpl.setDataSourceProperties(WSManagedConnectionFactoryImpl.java:2653)
 at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
 at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
 at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
 at java.lang.reflect.Method.invoke(Method.java:606)
 ......

来自链接的建议解决方案是

确保如果标签访问最初是框架访问,我们会在框架访问后插入我们的说明,而不是框架和标签之间。

有人可以解释&#34;如何使用ASM字节码实现这一点?&#34;

Update1 - 附加AdviceAdapter代码

package com.abc.agent.adapter;

import com.abc.jm.TMConstants;
import com.abc.jm.TMLog;
import com.abc.org.objectweb.asm.Label;
import com.abc.org.objectweb.asm.MethodVisitor;
import com.abc.org.objectweb.asm.Opcodes;
import com.abc.org.objectweb.asm.Type;
import com.abc.org.objectweb.asm.commons.AdviceAdapter;

public class DriverMethodAdviceAdapter extends AdviceAdapter  {

    private String methodName;
    private String className;
    private String description;
    private boolean isConnectMethod;

    private static final String INTERFACE_DRIVER_CONNECT_METHOD_DESC = "(Ljava/lang/String;Ljava/util/Properties;)Ljava/sql/Connection;";

    private int okFlag =  newLocal(Type.BOOLEAN_TYPE); 
    Label startFinally = new Label();

    public DriverMethodAdviceAdapter(int access , MethodVisitor mv , String methodName, String description, String className, int classFileVersion){
        super(Opcodes.ASM5, mv, access, methodName, description);
        this.className = className;
        this.methodName = methodName;
        this.description = description;
        this.isConnectMethod = false;

        if(methodName.equals("connect") && description.equals(INTERFACE_DRIVER_CONNECT_METHOD_DESC)){
            isConnectMethod = true;
        }
    }

    public void visitCode() {
        super.visitCode(); 
        mv.visitLabel(startFinally);
    }

    protected void onMethodEnter(){
         if(isConnectMethod){
            mv.visitInsn(Opcodes.ICONST_0);
            mv.visitVarInsn(ISTORE, okFlag);

            mv.visitLdcInsn(className);
            mv.visitLdcInsn(methodName);
            mv.visitLdcInsn(description);
            mv.visitMethodInsn(Opcodes.INVOKESTATIC, "com/abc/agent/trace/Tracer", "jdbcConnectionMethodBegin", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Z", false);
            mv.visitVarInsn(ISTORE, okFlag);
         }
    }

    protected void onMethodExit(int opcode){
        if(opcode!=ATHROW) {
            onFinally(opcode);
        }
    }

    public void visitMaxs(int maxStack, int maxLocals){
        Label endFinally = new Label();
        mv.visitTryCatchBlock(startFinally, endFinally, endFinally, null);
        mv.visitLabel(endFinally);
        onFinally(ATHROW);
        mv.visitInsn(ATHROW);
        mv.visitMaxs(maxStack+4, maxLocals);
    }

    private void onFinally(int opcode){
         if(isConnectMethod){
            mv.visitInsn(Opcodes.DUP); // This is return object 
            mv.visitLdcInsn(className);
            mv.visitLdcInsn(methodName);
            mv.visitLdcInsn(description);
            mv.visitVarInsn(ILOAD, okFlag);
            mv.visitLdcInsn(opcode);
            mv.visitMethodInsn(Opcodes.INVOKESTATIC, "com/abc/agent/trace/Tracer", "jdbcConnectionMethodEnd", "(Ljava/lang/Object;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ZI)V", false);
        }
    }
}

我正在使用标志 ClassWriter.COMPUTE_FRAMES 用于ClassWriter和 ClassReader.EXPAND_FRAMES | ClasseReader.accept()的ClassReader.SKIP_FRAMES

0 个答案:

没有答案