如何在Java中打印ojdbc8.jar内DNVerifier方法的传入参数?
解决ojdbc8 DN验证不匹配问题:打印verifyConfiguredDN方法参数
可以通过System.out.println实现目标,但由于DNVerifier是ojdbc8.jar中的第三方类,无法直接修改源码,需要借助字节码增强技术注入打印逻辑。以下是两种可行方案:
方案一:使用AspectJ拦截方法调用
AspectJ可以在不修改原类源码的前提下,拦截目标方法并插入自定义逻辑。
- 添加AspectJ依赖(Maven示例)
<dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjrt</artifactId> <version>1.9.20.1</version> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.9.20.1</version> </dependency>
- 编写切面类,拦截
verifyConfiguredDN方法并打印参数
import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; @Aspect public class DNVerifierLogger { @Before("execution(* oracle.net.ssl.DNVerifier.verifyConfiguredDN(..))") public void logDNParameters(JoinPoint joinPoint) { Object[] args = joinPoint.getArgs(); if (args == null || args.length == 0) { System.out.println("verifyConfiguredDN 无传入参数"); return; } System.out.println("=== verifyConfiguredDN 传入参数 ==="); for (int i = 0; i < args.length; i++) { Object arg = args[i]; System.out.printf("参数[%d]: %s%n", i, arg); // 处理字符串数组类型的参数(DN可能以数组形式传入) if (arg instanceof String[]) { String[] strArr = (String[]) arg; for (int j = 0; j < strArr.length; j++) { System.out.printf("子参数[%d][%d]: %s%n", i, j, strArr[j]); } } } } }
- 配置运行时织入
如果是Maven项目,添加aspectj-maven-plugin插件实现编译时织入;或者在启动Java程序时添加VM参数:
-javaagent:path/to/aspectjweaver-1.9.20.1.jar
方案二:使用Javassist动态修改字节码
Javassist允许在程序运行时动态修改类的字节码,直接向目标方法插入打印逻辑。
- 添加Javassist依赖(Maven示例)
<dependency> <groupId>org.javassist</groupId> <artifactId>javassist</artifactId> <version>3.29.2-GA</version> </dependency>
- 编写字节码修改类,在程序启动时注入打印代码
import javassist.ClassPool; import javassist.CtClass; import javassist.CtMethod; public class DNVerifierModifier { public static void injectLogging() throws Exception { // 获取DNVerifier类的字节码对象 ClassPool classPool = ClassPool.getDefault(); CtClass dnVerifierClass = classPool.get("oracle.net.ssl.DNVerifier"); // 获取目标方法 CtMethod verifyMethod = dnVerifierClass.getDeclaredMethod("verifyConfiguredDN"); // 在方法开头插入打印参数的代码 verifyMethod.insertBefore("{" + "System.out.println(\"=== verifyConfiguredDN 调用开始 ===\");" + "for (int i = 0; i < $args.length; i++) {" + " Object arg = $args[i];" + " System.out.println(\"参数[\" + i + \"]: \" + arg);" + " if (arg instanceof String[]) {" + " String[] arr = (String[])arg;" + " for (int j = 0; j < arr.length; j++) {" + " System.out.println(\"子参数[\" + i + \"][\" + j + \"]: \" + arr[j]);" + " }" + " }" + "}" + "}"); // 加载修改后的类到JVM dnVerifierClass.toClass(); } }
- 在程序入口处调用修改逻辑
确保在数据库连接代码执行前,先调用injectLogging():
public class Main { public static void main(String[] args) { try { DNVerifierModifier.injectLogging(); } catch (Exception e) { e.printStackTrace(); } // 后续执行数据库连接代码 // ... } }
注意事项
- 打印的DN参数需重点检查大小写、空格、属性顺序:例如服务器返回的
CN=Test, OU=Dev和客户端配置的OU=Dev, CN=Test逻辑等价,但字符串匹配会失败;部分证书DN的属性名大小写不统一(如cnvsCN)也会导致不匹配。 - Java 9+模块化环境下,需在
module-info.java中添加对org.javassist或org.aspectj模块的依赖声明。 - 确保使用的ojdbc8.jar版本与字节码增强工具版本兼容。
内容的提问来源于stack exchange,提问作者user1929905
相关产品推荐
相关产品推荐

