本文介绍使用OSS Java SDK的常见问题及解决方法。

包冲突

  • 错误原因

    使用OSS Java SDK时,报类似如下错误,说明您的工程里可能有包冲突。

    Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/http/ssl/TrustStrategy
        at com.aliyun.oss.OSSClient.<init>(OSSClient.java:268)
        at com.aliyun.oss.OSSClient.<init>(OSSClient.java:193)
        at com.aliyun.oss.demo.HelloOSS.main(HelloOSS.java:77)
    Caused by: java.lang.ClassNotFoundException: org.apache.http.ssl.TrustStrategy
        at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
        at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:425)
        at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:358)
        ... 3 more
    					

    Exception in thread "main" java.lang.NoSuchFieldError: INSTANCE
     at org.apache.http.impl.io.DefaultHttpRequestWriterFactory.<init>(DefaultHttpRequestWriterFactory.java:52)
     at org.apache.http.impl.io.DefaultHttpRequestWriterFactory.<init>(DefaultHttpRequestWriterFactory.java:56)
     at org.apache.http.impl.io.DefaultHttpRequestWriterFactory.<clinit>(DefaultHttpRequestWriterFactory.java:46)
     at org.apache.http.impl.conn.ManagedHttpClientConnectionFactory.<init>(ManagedHttpClientConnectionFactory.java:82)
     at org.apache.http.impl.conn.ManagedHttpClientConnectionFactory.<init>(ManagedHttpClientConnectionFactory.java:95)
     at org.apache.http.impl.conn.ManagedHttpClientConnectionFactory.<init>(ManagedHttpClientConnectionFactory.java:104)
     at org.apache.http.impl.conn.ManagedHttpClientConnectionFactory.<clinit>(ManagedHttpClientConnectionFactory.java:62)
     at org.apache.http.impl.conn.PoolingHttpClientConnectionManager$InternalConnectionFactory.<init>(PoolingHttpClientConnectionManager.java:572)
     at org.apache.http.impl.conn.PoolingHttpClientConnectionManager.<init>(PoolingHttpClientConnectionManager.java:174)
     at org.apache.http.impl.conn.PoolingHttpClientConnectionManager.<init>(PoolingHttpClientConnectionManager.java:158)
     at org.apache.http.impl.conn.PoolingHttpClientConnectionManager.<init>(PoolingHttpClientConnectionManager.java:149)
     at org.apache.http.impl.conn.PoolingHttpClientConnectionManager.<init>(PoolingHttpClientConnectionManager.java:125)
     at com.aliyun.oss.common.comm.DefaultServiceClient.createHttpClientConnectionManager(DefaultServiceClient.java:237)
     at com.aliyun.oss.common.comm.DefaultServiceClient.<init>(DefaultServiceClient.java:78)
     at com.aliyun.oss.OSSClient.<init>(OSSClient.java:268)
     at com.aliyun.oss.OSSClient.<init>(OSSClient.java:193)
     at OSSManagerImpl.upload(OSSManagerImpl.java:42)
     at OSSManagerImpl.main(OSSManagerImpl.java:63)
    					

    错误原因是OSS Java SDK使用了Apache httpclient 4.4.1,而您的工程使用了与Apache httpclient 4.4.1冲突的Apache httpclient或commons-httpclient jar包。要查看工程使用的jar包及版本,请在您的工程目录下执行mvn dependency:tree。如下图所示,您的工程里使用了Apache httpclient 4.3:

    常见问题_Java_SDK 参考_对象存储 OSS 阿里云技术文档 第1张
  • 包冲突有以下两种解决方法:

    • 使用统一版本。如果您的工程使用与Apache httpclient 4.4.1冲突的版本,请您使用4.4.1版本,并在pom.xml删除其它版本的Apache httpclient依赖。如果您的工程使用了commons-httpclient,也可能存在冲突,请删除commons-httpclient。
    • 解除依赖冲突。如果您的工程依赖多个第三方包,而第三方包又依赖不同版本的Apache httpclient,您的工程里会有依赖冲突,请使用exclusion解除。详细请参见Maven Guides

    OSS Java SDK依赖以下版本的包,冲突解决办法与httpclient类似。

    常见问题_Java_SDK 参考_对象存储 OSS 阿里云技术文档 第2张

缺少包

  • 错误原因

    使用OSS Java SDK时,报类似如下错误,说明您的工程中可能缺少编译或运行OSS Java SDK所必需的包。

    Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/http/auth/Credentials
            at com.aliyun.oss.OSSClient.<init>(OSSClient.java:268)
            at com.aliyun.oss.OSSClient.<init>(OSSClient.java:193)
            at com.aliyun.oss.demo.HelloOSS.main(HelloOSS.java:76)
    Caused by: java.lang.ClassNotFoundException: org.apache.http.auth.Credentials
            at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
            at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
            at java.security.AccessController.doPrivileged(Native Method)
            at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
            at java.lang.ClassLoader.loadClass(ClassLoader.java:425)
            at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
            at java.lang.ClassLoader.loadClass(ClassLoader.java:358)
            ... 3 more
    					

    Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/http/protocol/HttpContext
            at com.aliyun.oss.OSSClient.<init>(OSSClient.java:268)
            at com.aliyun.oss.OSSClient.<init>(OSSClient.java:193)
            at com.aliyun.oss.demo.HelloOSS.main(HelloOSS.java:76)
    Caused by: java.lang.ClassNotFoundException: org.apache.http.protocol.HttpContext
            at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
            at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
            at java.security.AccessController.doPrivileged(Native Method)
            at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
            at java.lang.ClassLoader.loadClass(ClassLoader.java:425)
            at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
            at java.lang.ClassLoader.loadClass(ClassLoader.java:358)
            ... 3 more
    					

    Exception in thread "main" java.lang.NoClassDefFoundError: org/jdom/input/SAXBuilder
            at com.aliyun.oss.internal.ResponseParsers.getXmlRootElement(ResponseParsers.java:645)
            at … … 
            at com.aliyun.oss.OSSClient.doesBucketExist(OSSClient.java:471)
            at com.aliyun.oss.OSSClient.doesBucketExist(OSSClient.java:465)
            at com.aliyun.oss.demo.HelloOSS.main(HelloOSS.java:82)
    Caused by: java.lang.ClassNotFoundException: org.jdom.input.SAXBuilder
            at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
            at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
            at java.security.AccessController.doPrivileged(Native Method)
            at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
            at java.lang.ClassLoader.loadClass(ClassLoader.java:425)
            at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
            at java.lang.ClassLoader.loadClass(ClassLoader.java:358)
            ... 11 more
    					

    OSS Java SDK依赖下列包:

    • aliyun-sdk-oss-2.2.1.jar
    • hamcrest-core-1.1.jar
    • jdom-1.1.jar
    • commons-codec-1.9.jar
    • httpclient-4.4.1.jar
    • commons-logging-1.2.jar
    • httpcore-4.4.1.jar
    • log4j-1.2.15.jar

    其中log4j-1.2.15.jar是可选的,需要日志功能的时候加入该包,其它包都是必需的。

  • 解决方法

    在您的工程中加入OSS Java SDK依赖的包。加入方法如下:

    • 如果您的工程在Eclipse中,请参见Java SDK使用手册中的安装方式二:在Eclipse项目中导入工程依赖的包。
    • 如果您的工程在Ant中,请把OSS Java SDK依赖的包放入工程的lib目录中。
    • 如果您直接使用.javac或.java文件,请使用-classpath-cp命令指定OSS Java SDK依赖的包路径,或把OSS Java SDK依赖的包放入classpath路经下。

连接超时

  • 错误原因

    运行OSS Java SDK程序时,报类似如下错误,可能的原因是Endpoint错误或者网络不通。

    com.aliyun.oss.ClientException: SocketException
        at com.aliyun.oss.common.utils.ExceptionFactory.createNetworkException(ExceptionFactory.java:71)
        at com.aliyun.oss.common.comm.DefaultServiceClient.sendRequestCore(DefaultServiceClient.java:116)
        at com.aliyun.oss.common.comm.ServiceClient.sendRequestImpl(ServiceClient.java:121)
        at com.aliyun.oss.common.comm.ServiceClient.sendRequest(ServiceClient.java:67)
        at com.aliyun.oss.internal.OSSOperation.send(OSSOperation.java:92)
        at com.aliyun.oss.internal.OSSOperation.doOperation(OSSOperation.java:140)
        at com.aliyun.oss.internal.OSSOperation.doOperation(OSSOperation.java:111)
        at com.aliyun.oss.internal.OSSBucketOperation.getBucketInfo(OSSBucketOperation.java:1152)
        at com.aliyun.oss.OSSClient.getBucketInfo(OSSClient.java:1220)
        at com.aliyun.oss.OSSClient.getBucketInfo(OSSClient.java:1214)
        at com.aliyun.oss.demo.HelloOSS.main(HelloOSS.java:94)
    Caused by: org.apache.http.conn.HttpHostConnectException: Connect to oss-test.oss-cn-hangzhou-internal.aliyuncs.com:80 [oss-test.oss-cn-hangzhou-internal.aliyuncs.com/10.84.135.99] failed: Connection timed out: connect
        at org.apache.http.impl.conn.DefaultHttpClientConnectionOperator.connect(DefaultHttpClientConnectionOperator.java:151)
        at org.apache.http.impl.conn.PoolingHttpClientConnectionManager.connect(PoolingHttpClientConnectionManager.java:353)
        at org.apache.http.impl.execchain.MainClientExec.establishRoute(MainClientExec.java:380)
        at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:236)
        at org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:184)
        at org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:110)
        at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:184)
        at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:82)
        at com.aliyun.oss.common.comm.DefaultServiceClient.sendRequestCore(DefaultServiceClient.java:113)
        ... 9 more
    					
  • 解决方法

    您可以使用ossutil工具快速定位错误原因,从而解决问题。

org.apache.http.NoHttpResponseException: The target server failed to respond

  • 错误原因

    运行OSS Java SDK程序时,报类似如下错误:

    常见问题_Java_SDK 参考_对象存储 OSS 阿里云技术文档 第3张

    使用过期的连接会导致上述错误。该错误仅在Java SDK 2.1.2前的版本出现。

  • 解决方法

    请升级OSS Java SDK到2.1.2及以后版本。

调用OSS Java SDK夯住

  • 错误原因

    调用OSS Java SDK夯住(hang)。通过jstack -l pid命令查看堆栈,夯在如下的位置:

    "main" prio=6 tid=0x000000000291e000 nid=0xc40 waiting on condition [0x0000000002dae000]
    java.lang.Thread.State: WAITING (parking)
        at sun.misc.Unsafe.park(Native Method)
        - parking to wait for  <0x00000007d85697f8> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
        at java.util.concurrent.locks.LockSupport.park(LockSupport.java:186)
        at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2043)
        at org.apache.http.pool.PoolEntryFuture.await(PoolEntryFuture.java:138)
        at org.apache.http.pool.AbstractConnPool.getPoolEntryBlocking(AbstractConnPool.java:306)
        at org.apache.http.pool.AbstractConnPool.access$000(AbstractConnPool.java:64)
        at org.apache.http.pool.AbstractConnPool$2.getPoolEntry(AbstractConnPool.java:192)
        at org.apache.http.pool.AbstractConnPool$2.getPoolEntry(AbstractConnPool.java:185)
        at org.apache.http.pool.PoolEntryFuture.get(PoolEntryFuture.java:107)
        at org.apache.http.impl.conn.PoolingHttpClientConnectionManager.leaseConnection(PoolingHttpClientConnectionManager.java:276)
        at org.apache.http.impl.conn.PoolingHttpClientConnectionManager$1.get(PoolingHttpClientConnectionManager.java:263)
        at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:190)
        at org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:184)
        at org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:110)
        at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:184)
        at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:82)
        at com.aliyun.oss.common.comm.DefaultServiceClient.sendRequestCore(DefaultServiceClient.java:113)
        at com.aliyun.oss.common.comm.ServiceClient.sendRequestImpl(ServiceClient.java:123)
        at com.aliyun.oss.common.comm.ServiceClient.sendRequest(ServiceClient.java:68)
        at com.aliyun.oss.internal.OSSOperation.send(OSSOperation.java:94)
        at com.aliyun.oss.internal.OSSOperation.doOperation(OSSOperation.java:146)
        at com.aliyun.oss.internal.OSSOperation.doOperation(OSSOperation.java:113)
        at com.aliyun.oss.internal.OSSObjectOperation.getObject(OSSObjectOperation.java:229)
        at com.aliyun.oss.OSSClient.getObject(OSSClient.java:629)
        at com.aliyun.oss.OSSClient.getObject(OSSClient.java:617)
        at samples.HelloOSS.main(HelloOSS.java:49)
    					

    原因是连接池中连接泄漏,可能是使用ossObject后没有关闭。

  • 解决方法

    请检查您的程序,确保没有连接泄漏。关闭方法如下:

    // 读取文件
    OSSObject ossObject = ossClient.getObject(bucketName, objectName);
    // OSS操作
    // 关闭ossObject
    ossObject.close();
    					

    问题排查的详细步骤,请参见OSS Java SDK夯住问题排查

连接关闭

  • 错误原因

    如果您在使用ossClient.getObject时,报类似如下错误:

    Exception in thread "main" org.apache.http.ConnectionClosedException: Premature end of Content-Length delimited message body (expected: 11990526; received: 202880)
        at org.apache.http.impl.io.ContentLengthInputStream.read(ContentLengthInputStream.java:180)
        at org.apache.http.impl.io.ContentLengthInputStream.read(ContentLengthInputStream.java:200)
        at org.apache.http.impl.io.ContentLengthInputStream.close(ContentLengthInputStream.java:103)
        at org.apache.http.impl.execchain.ResponseEntityProxy.streamClosed(ResponseEntityProxy.java:128)
        at org.apache.http.conn.EofSensorInputStream.checkClose(EofSensorInputStream.java:228)
        at org.apache.http.conn.EofSensorInputStream.close(EofSensorInputStream.java:174)
        at java.io.FilterInputStream.close(FilterInputStream.java:181)
        at java.io.FilterInputStream.close(FilterInputStream.java:181)
        at com.aliyun.oss.event.ProgressInputStream.close(ProgressInputStream.java:147)
        at java.io.FilterInputStream.close(FilterInputStream.java:181)
        at samples.HelloOSS.main(HelloOSS.java:39)
    					

    原因是两次读取数据间隔时间超过1分钟。OSS会关闭超过1分钟没有发送或接收数据的连接。

  • 解决方法

    如果您每次读取部分数据进行处理,且处理数据的时间不固定,建议使用指定范围读取,避免数据读取时连接关闭。

内存泄露

  • 错误原因

    调用OSS Java SDK的程序,运行一段时间(根据业务量,几小时到几天不等)后内存泄露。 推荐使用Eclipse Memory Analyzer (MAT)分析内存使用情况, 使用方法请参见使用MAT进行堆转储文件分析

    如果分析结果类似下图所示(PoolingHttpClientConnectionManager占96%的内存),原因是程序中可能多次执行new OSSClient,但是没有调用ossClient.shutdown,造成内存泄漏。

    常见问题_Java_SDK 参考_对象存储 OSS 阿里云技术文档 第4张
  • 解决方法

    new OSSClient一定要和ossClient.shutdown成对使用。

调用ossClient.shutdown抛异常InterruptedException

  • 错误原因

    调用ossClient.shutdown抛如下异常:

    java.lang.InterruptedException: sleep interrupted
            at java.lang.Thread.sleep(Native Method)
            at com.aliyun.oss.common.comm.IdleConnectionReaper.run(IdleConnectionReaper:76)
    					

    原因是ossClient后台线程IdleConnectionReaper会定时关闭闲置连接。IdleConnectionReaper在Sleep时,调用ossClient.shutdown,就会抛出上面的异常。

  • 解决方法

    OSS Java SDK 2.3.0已经修复该问题。

    OSS Java SDK 2.3.0之前的版本,请使用如下代码,忽略该异常:

    try {
        ossClient.shutdown();
    } catch(Exception e) {
    }
    					

请求出现异常“SDK.ServerUnreachable : Speicified endpoint or uri is not valid”

常见问题_Java_SDK 参考_对象存储 OSS 阿里云技术文档 第5张
  • 错误原因

    出现此类报错是因为用户端并发请求STS过高、网络到server端超时、所使用的STS SDK以及SDK core不是最新版本,导致用户无法连接到阿里云网关。

  • 解决方法
    • 用户端并发请求STS过高,而用户端的ECS或者本地PC不足以承载当时的并发,降低OSS并发。
    • 用户的网络到server端有超时现象可以进行抓包验证。
    • 建议将STS SDK及SDK core升级至最新版本。

NoSuchKey

常见问题_Java_SDK 参考_对象存储 OSS 阿里云技术文档 第6张
  • 错误原因

    出现此类报错原因是源文件不存在。

  • 解决方法

    参考404问题排查

socketException

常见问题_Java_SDK 参考_对象存储 OSS 阿里云技术文档 第7张
  • 错误原因

    可能是socket在init阶段就失败了,导致请求没有到达OSS。

  • 解决方法
    建议从以下几个方面进行排查:
    • 当时是否出现网络抖动。
    • 主机的socket连接数是否占满。
    • SDK中设置的maxconnection是多大。如果当时连接数超过maxconnection设置,也会出现socket异常。
    • 如果以上都没有问题,建议用户部署tcpdump或者wireshark抓包,复现问题后分析下数据包。

使用OSS PostObject的callback没有触发回调,但是通过PutObject用同样的callback触发了回调?

常见问题_Java_SDK 参考_对象存储 OSS 阿里云技术文档 第8张

一般情况下,如果JSON格式有误或者回调失败,都会返回相应的msg,这里需要分别测试下Put和Post回调效果:

常见问题_Java_SDK 参考_对象存储 OSS 阿里云技术文档 第9张
  • 错误原因
    发送请求时callback参数在file下面。常见问题_Java_SDK 参考_对象存储 OSS 阿里云技术文档 第10张
  • 解决方法
    调整callback参数与file的位置。常见问题_Java_SDK 参考_对象存储 OSS 阿里云技术文档 第11张
    此时测试结果显示业务服务器成功抓取请求。常见问题_Java_SDK 参考_对象存储 OSS 阿里云技术文档 第12张

Connection pool shut down

Caused by: java.lang.IllegalStateException: Connection pool shut down
  at org.apache.http.util.Asserts.check(Asserts.java:34)
  at org.apache.http.pool.AbstractConnPool.lease(AbstractConnPool.java:184)
  at org.apache.http.impl.conn.PoolingHttpClientConnectionManager.requestConnection(PoolingHttpClientConnectionManager.java:251)
  at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:175)
  at org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:184)
  at org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:110)
  at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:184)
  at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:82)
  at com.aliyun.oss.common.comm.DefaultServiceClient.sendRequestCore(DefaultServiceClient.java:124)
  at com.aliyun.oss.common.comm.ServiceClient.sendRequestImpl(ServiceClient.java:133)
  ... 8 more
  • 错误原因

    调用ossClient.shutdown()接口后,还继续通过ossClient发送请求。

  • 解决方法

    请检查调用逻辑,确保调用了ossClient.shutdown()接口之后,不再通过ossClient发送请求。

使用Java SDK的generatePresignedUrl生成的请求报错Request has expired

  • 错误原因

    int类型溢出,导致2038年时间戳问题。

    超出URL设置的过期时间后发起上传请求。

  • 解决方法

    如果是int类型溢出,建议Java SDK中过期时长不要超过2038年。

    如果因超出URL设置的过期时间后发起上传请求,建议设置合理的过期时间,确保过期时间大于您的发起请求时间。

其它错误

OSS返回的其它错误排查,请参见常见错误及排查