天天看点

java.lang.InstantiationError: sun.net.ftp.FtpClient

今天排查老系统上传文件报错问题时发现线上环境控制台报错java.lang.InstantiationError: sun.net.ftp.FtpClient

随手复制粘贴百度,很容易找到了原因,在jdk1.6中FtpClient是有空的构造函数的,但是到了jdk1.7之后FtpClient的空构造函数就被私有化了

带着这个答案我阅读了项目的代码,发现在报错信息所指代码行处有一个ftpClient = new FtpClient();,这样更进一步的验证了答案

首先将对应的错误class文件从线上服务器下载下来,然后使用EditPlus打开,打开后会有一个弹框让我们选择以什么字符编码打开class文件,这里我们选择Hex viewer(16进制字符编码)

java.lang.InstantiationError: sun.net.ftp.FtpClient

然后查看第一行的前8个组合:CA FE BA BE 00 00 00 32,这里我们的class文件是被jdk1.6编译的

1:前面8个字节CA FE BA BE是固定的。

2:随后4个字节00 00是次版本号

3:再后面的4个字节00 34是JDK的版本号。

 JDK版本号对应关系如下:

      34(对应十进制的50):JDK1.8

      33(对应十进制的50):JDK1.7

      32(对应十进制的50):JDK1.6

      31(对应十进制的49):JDK1.5

  30(对应十进制的48):JDK1.4

  2F(对应十进制的47):JDK1.3

  2E(对应十进制的46):JDK1.2

java.lang.InstantiationError: sun.net.ftp.FtpClient

到线上服务器tomcat的bin下执行./version.sh,发现用的是jdk1.7,也就是我jdk1.6编译的class文件现在运行在jdk1.7环境下,然后FtpClient的空构造函数在jdk1.7下是私有的,所以运行的时候代码会报错

java.lang.InstantiationError: sun.net.ftp.FtpClient

rpm -qa|grep java 查看当前服务器有哪些jdk,我们需要jdk1.6,发现服务器上已经有了jdk1.6

java.lang.InstantiationError: sun.net.ftp.FtpClient

这时候我们需要找到jdk1.6的路径,使用find -name rt.jar,这里为什么找rt.jar呢,因为我尝试了很多关键词,发现找不到,然后想到每个jdk中都自带rt.jar,所以直接找这个文件,可以迅速找到jdk的文件路径

找到路径后进入tomcat的bin目录下,vim操作catalina.sh文件,在文件的头部添加一段代码(这里注意不要放到文件第一行,要放到被注释的命令的后面)

java.lang.InstantiationError: sun.net.ftp.FtpClient

export JAVA_HOME=/usr/lib/jvm/java-1.6.0-openjdk-1.6.0.0.x86_64/jre

这里加这段代码的含义是tomcat启动时将JAVA_HOME替换成jdk1.6,这样tomcat的jdk就变成了1.6,再到tomcat的bin下执行./version.sh,发现这时候tomcat的jdk版本是1.6

然后启动服务,上传文件,问题解决!

继续阅读