【原创】分析JDK17加载Sybase驱动出现递归调用的原因并解决其加载问题

news2024/9/22 21:18:59

前言

最近好久没发文章了,原因是AI太强了,随便问一句答案就有了,节约了很多折腾的时间,也就没法作为原创文章发布了,还有就是很多涉及公司内部的代码,没法公开发布。

这次遇到了一个项目,用的数据库是Sybase,需要使用jdbc进行连接然后查询其中的数据。这个项目以前在jdk8的环境运行是正常的,但是到了jdk17,加载驱动就出现问题了,这篇文章就来分析并解决这个问题。

问题现象

在jdk17中,加载Sybase驱动会出现递归调用,如图所示:

而jdk8就没有这个问题。

问题原因

原因出在jdk源码里,也就是jdk发生了变化,导致以前的Sybase驱动无法兼容新版本的jdk了(这不是废话吗)

jdk改动

具体代码是这样的:

jdk8的java.sql.DriverManager中的getDrivers方法长这样:

而jdk17长这样:

区别在于jdk17的getDrivers方法多了一行

ensureDriversInitialized();

这个方法是做什么的呢?答案是调用所有jdbc的驱动类的构造方法去初始化所有的驱动类,确保所有的驱动都被加载成功了。

上图代码是来自ensureDriversInitialized();方法中,注意看其中的注释,意思是加在这些驱动,让它们能够顺利的被实例化。

在driversIterator.next();中,会调用驱动自己的构造方法,来实例化它们。而在jdk8中则不会有这个操作。

Sybase驱动包

再看一下Sybase的驱动包,其中的com.sybase.jdbc4.jdbc.SybDriver这个类

其中会调用自己的registerWithDriverManager();这个方法,当我看到这个方法中终于知道了递归初始化的来源:

这个方法首先通过

DriverManager.registerDriver(this);

这个方法将驱动注册到内存中也就是registeredDrivers这个列表中。然后调用

DriverManager.getDrivers();

这个方法获取所有已注册的所有驱动,再通过循环判断Sybase驱动是否已经注册过了,如果注册过了则取消注册之前的Sybase驱动。这个代码原来(jdk8)看着是没有问题的。

但是到了jdk17中DriverManager.getDrivers();这个方法会去调用驱动类的构造方法去初始化驱动,然后构造方法中又会调用registerWithDriverManager(),其中的DriverManager.getDrivers();会调用构造方法,构造方法调用registerWithDriverManager()…………然后就发生递归了。然后这里的try里的catch中什么代码都没有,也不打印报错日志,导致什么错误都不显示了。这个驱动包写的确实让人一言难尽……

问题解决

既然问题找到了,那就得想办法解决这个问题,解决的方案有很多。

1、将jdk17换回jdk8

2、找其他版本兼容jdk17的驱动包

3、更换数据库

4、修改驱动包的字节码

解决方案1,这个想都没别想,目前项目的主题就是将jdk8换成jdk17。

解决方案3,这个也想都别想

更换Sybase其他版本的驱动包

官网

这是我第一个想到的解决方案,然后我在这个解决方案上面栽了一个大坑。Sybase目前被SAP收购了,变成了SAP ASE这个数据库,原来是www.sybase.com这个官网都打不开了,然后更坑的来了,我不好容易注册了SAP的账号,想要去下载东西了,结果一行不起眼的小字提醒了前来下载驱动的我

在SAP官网注册的用户都是P-user,而不是S-user,只有SAP的客户才能拥有S-user,拥有SAP官网的完整功能,难怪我折腾了半天,看了官网一堆的文档,就是下载不到任何东西!!!!

看看SAP官网这一行话吧,意思是只有S-user这个权限的用户才能使用下载功能,如果大家不信,可以去SAP官网试试,我是试了几个小时都没能够下载到任何东西。而老的sybase的官网已经打不开了,我看SAP的论坛里给的驱动链接都是老的Sybase官网的。

DBeaver

如此天才的我想到了DBeaver,这玩意每次要连数据库前不都会去下载驱动,说不定会有什么新的发现。然后我就试了一下,发现DBeaver不仅有Sybase还有SAP ASE

我悬着的心一下子就放下来了,结果等DBeaver下载完驱动,我就傻眼了。

怎么名称和我目前项目里用的一模一样,然后解压后打开其中的MANIDEST.MF,不能说是完全不同的,只能说是一模一样

还是那个2017年用jdk1.6编译出来的Sybase驱动包,完全不带任何更新的!!反编译后代码也是一模一样。当时把我给气得,这个DBeaver怎么连个驱动包都不更新一下,都2024年8月了,还在用2017年的驱动包。

修改字节码

只剩最后一条路了,修改字节码

javaassist

首先想到的是javaassist,说真的,这玩意我也是第一次用,java字节码的组成虽然以前自学过,但是过了太久已经忘了,使用javaassist需要将

Enumeration var2 = DriverManager.getDrivers();

连同后面的while循环全部删掉,这工作量就不小了,何况里面还有synchronized和try、catch块,不是字节码转换出错,就是字节码整完后无法加载,搞得我心累,压根就搞不定,问了AI,给我的答案也是错的,修改后的字节码根本无法使用。

然后同事给我支了一招,用idea中的jarEditor这个插件

jarEditor

在idea中搜索并安装这个插件,找到并加载Sybase的驱动包

上图通过maven加载项目本地的jar包

找到包中的SybDriver.class,点击下方的Jar Editor

将不需要的代码直接删掉

出现报错就解决报错,像我这里是实现com.sybase.jdbcx.SybDriver少了一个方法,直接补上去就行了,按F2就能定位报错的地方

Save后点击Build Jar就行了,Build成功后,这个Jar包就被彻底改变了,其中的字节码就是你刚改的。

然后使用这个新的驱动包后问题就解决了,Sybase驱动包加载的时候就不再递归了,连接一切正常。

小结

没想到一个Sybase加载驱动的问题解决了这么久,大概花了要4~5个小时,要不是同事给我推荐了Jar Editor,我恐怕要在javaassist的泥潭里继续挣扎,不过这javaassist应该是可以用的,只是我目前还不会,后面要好好研究一下这东西,目前Sybase驱动的问题算是解决了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1966916.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Java后端初开-->架构师学习路线!无偿分享!让你少走弯路

由于平台篇幅原因,很多java面试资料内容展示不了,需要的java面试宝典的伙伴们转发文章关注后,扫描下方二维码免费获取:

FFplay:FFmpeg中的多媒体播放器

😎 作者介绍:欢迎来到我的主页👈,我是程序员行者孙,一个热爱分享技术的制能工人。计算机本硕,人工制能研究生。公众号:AI Sun(领取大厂面经等资料),欢迎加我的…

【FANUC】发那科机器人ROBOGUIDE安装教程(含安装包)

👉博__主👈:米码收割机 👉技__能👈:C/Python语言 👉公众号👈:测试开发自动化【获取源码商业合作】 👉荣__誉👈:阿里云博客专家博主、5…

基于Debian用户安装星火商店

星火商店下载地址:https://www.spark-app.store/ 本文章我以kali linux来做示范 注:基本debian的linux包括ubuntu,mint linux,kali linux,Pop!_OS,deepin等等 1.点击下载最新版本 2.点击下载 3.点击开始下载(它会自动跳转网页) 4.选择要下载…

告别啃书难,4款pdf翻译成中文神器在手,阅读起来so easy

在这个快节奏的时代,当我们遇到外文的PDF文档时,能不能快速翻译成中文变得非常重要。为了帮大家解决这个问题,我找来了四款专门用于把pdf翻译成中文的工具。这些工具操作起来很简单,翻译的质量也很高,能帮我们大大提高…

MybatisPlus(二)

目录 扩展功能 代码生成 静态工具 逻辑删除 枚举处理器 JSON处理器 配置加密 插件功能 插件功能 分页插件(通用分页实体) 扩展功能 代码生成 静态工具 逻辑删除 逻辑删除就是基于代码逻辑模拟删除效果,但并不会真正删除数据。思路如下: • 在…

转录组数据去批次方法整理(combat,combat-seq,removeBatchEffect)

为什么需要去除批次效应? 批次效应是指样本在不同批次处理及测量的情况下引入与生物学情况不相关的技术误差,比如不同试剂耗材,不同操作者,不同的实验时间等。 正是因为这些非生物学的因素存在就有可能会导致我们的结果偏离真实…

如何模拟真实的负载情况进行测试?

模拟真实的负载情况是进行性能测试的关键步骤,它可以帮助我们了解系统在高负载下的表现,以及可能出现的问题。以下是一些模拟真实负载的方法: 1. 确定目标:首先,我们需要明确测试的目标,例如,我…

探索Python FastAPI的Annotated参数设计:提升代码的灵活性与可读性

在现代软件开发中,代码的可读性和灵活性是至关重要的。Python的FastAPI框架以其高性能和易用性而受到开发者的喜爱。FastAPI提供了一种名为Annotated的参数设计方式,它允许开发者以类型注解的形式增强函数参数的定义,从而提升代码的表达力和灵…

深度学习(RNN+VAE):高质量的音乐作品让音符飞舞起来

深度学习在音乐生成领域有着广泛的应用,其中循环神经网络(RNN)和变分自编码器(VAE)是两种重要的模型。下面是这两种模型在音乐生成中的应用概述: 1. 循环神经网络(RNN)在音乐生成中…

内存管理【C++】

C/C内存分布 栈又叫堆栈,主要存放非静态局部变量、函数参数、函数返回值,栈一般是向下增长的堆用于程序运行时动态内存分配数据段用于存储全局数据和静态数据代码段用于存储可执行代码和制度常量 C内存管理方式 C语言的内存管理方式在C中可以继续使用&…

RabbitMQ 入门篇

接上一篇《RabbitMQ-安装篇(阿里云主机)-CSDN博客》 安装好RabbitMQ后,我们将开始RabbitMQ的使用,根据官网文档RabbitMQ Tutorials | RabbitMQ,我们一步一步的学习。 1. "Hello World!" 这里先说明几个概…

电影票竞价系统:开发难度与代码规范全解析

电影票竞价系统成为了一种新兴的购票方式,它不仅提升了用户的购票体验,也为电影院带来了新的盈利模式。但是,这样一个系统的开发难度如何?代码又该如何规范?本文将一探究竟。 电影票竞价系统的开发难度 技术复杂性 …

【Android Studio】项目目录结构

文章目录 常用视图Android视图project视图 gradlebuild.gradleSDK 路径主题 常用视图 Android视图 project视图 gradle build.gradle SDK 路径 主题

怎么在电脑中创建虚拟的加密磁盘?

在电脑中创建虚拟的加密磁盘可以有效保护电脑数据,避免电脑数据泄露。那么,我们该怎么在电脑中创建虚拟的加密磁盘呢?下面我们就一起来了解一下吧。 BitLocker 在使用BitLocker加密虚拟磁盘前,我们需要使用虚拟磁盘工具创建一个虚…

Navicat最新版安装及免费使用教程(全网最靠谱,最简单~)

一、官网下载Navicat: Navicat | 下载 Navicat Premium 14 天免费 Windows、macOS 和 Linux 的试用版 二、百度网盘下载 链接: https://pan.baidu.com/s/1J-2ukx3NDTqvNoQsxnE1Jw 提取码: 5120 解压Navicat16和17补丁工具,然后双击执行压缩包文件中的&a…

分布式训练:大规模AI模型的实践与挑战

简介: 随着人工智能的发展,深度学习模型变得越来越复杂,数据集也越来越大。为了应对这种规模的增长,分布式训练成为了训练大规模AI模型的关键技术。本文将介绍分布式训练的基本概念、常用框架(如TensorFlow和PyTorch&a…

企业源代码加密软件推荐,10款超好用的源代码加密软件排行榜

在现代软件开发中,源代码是企业的核心资产之一。保护源代码免受未经授权的访问和盗窃至关重要。源代码加密软件可以为企业提供额外的安全层,确保知识产权和商业秘密得到妥善保护。 1. 安秉源码加密软件 通过驱动层透明加密,确保开发人员在使…

ollama修改模型问答的上下文长度(num_ctx)

文章目录 一劳永逸版:修改模型参数临时抱佛脚之命令行生效临时抱佛脚之API生效没啥卵用之OpenAI API传参没啥卵用之OpenAI 问答传参 在使用ollama做大模型问答的过程中,发现存在着当输入问题过长之后,模型无法回答的问题。经过查询资料&#…