java.io.IOException 断开的管道 解决方法 ClientAbortException: java.io.IOException: Broken pipe-程序员宅基地

转载于:https://blog.csdn.net/zqz_zqz/article/details/52235479

 

今天公司技术支持的童鞋报告一个客户的服务不工作了,紧急求助,于是远程登陆上服务器排查问题。

    查看采集数据的tomcat日志,习惯性的先翻到日志的最后去查看有没有异常的打印,果然发现了好几种异常信息,但是最多还是这个:

 
  1. 24-Nov-2016 09:54:21.116 SEVERE [http-nio-8081-Acceptor-0] org.apache.tomcat.util.net.NioEndpoint$Acceptor.run Socket accept failed

  2. java.io.IOException: Too many open files

  3. at sun.nio.ch.ServerSocketChannelImpl.accept0(Native Method)

  4. at sun.nio.ch.ServerSocketChannelImpl.accept(ServerSocketChannelImpl.java:241)

  5. at org.apache.tomcat.util.net.NioEndpoint$Acceptor.run(NioEndpoint.java:688)

  6. at java.lang.Thread.run(Thread.java:745)

    “Too manay open files” 问题很明显啊,文件描述符超出限制导致无法打开文件或创建网络连接,这个问题又会导致一些其它问题的产生,肯定是ulimit没有优化,于是检查ulimit的设置;

[root@sdfassd logs]# ulimit -a
core file size          (blocks, -c) 0
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 0
file size               (blocks, -f) unlimited
pending signals                 (-i) 62819
max locked memory       (kbytes, -l) 64
max memory size         (kbytes, -m) unlimited
open files                      (-n) 65535
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
real-time priority              (-r) 0
stack size              (kbytes, -s) 10240
cpu time               (seconds, -t) unlimited
max user processes              (-u) 62819
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited

 

     open files竟然是65535,已经做过了优化,是不是先启动的tomcat等服务,然后才对ulimit做的优化?有可能,这样的话重启一下服务就ok了,于是将全部服务重启了一遍,运行正常了,不一会报表就显示数据了,然后告诉技术支持,问题已经解决了,然后就去处理别的case了;

 

    结果还不到20分钟,技术支持说,报表又没有数据了,于是又打数据采集的应用的tomcat日志查看,发现了一堆异常,全都是一个错:

 
  1. 24-Nov-2016 09:54:24.574 WARNING [http-nio-18088-exec-699] org.apache.catalina.core.StandardHostValve.throwable Exception Processing ErrorPage[exceptionType=java.lang.Throwable, location=/views/error/500.jsp]

  2. org.apache.catalina.connector.ClientAbortException: java.io.IOException: Broken pipe

  3. at org.apache.catalina.connector.OutputBuffer.realWriteBytes(OutputBuffer.java:393)

  4. at org.apache.tomcat.util.buf.ByteChunk.flushBuffer(ByteChunk.java:426)

  5. at org.apache.catalina.connector.OutputBuffer.doFlush(OutputBuffer.java:342)

  6. at org.apache.catalina.connector.OutputBuffer.close(OutputBuffer.java:295)

  7. at org.apache.catalina.connector.Response.finishResponse(Response.java:453)

  8. at org.apache.catalina.core.StandardHostValve.throwable(StandardHostValve.java:378)

  9. at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:174)

  10. at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)

  11. at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:610)

  12. at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:610)

  13. at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88)

  14. at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:537)

  15. at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1085)

  16. at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:658)

  17. at org.apache.coyote.http11.Http11NioProtocol$Http11ConnectionHandler.process(Http11NioProtocol.java:222)

  18. at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1556)

  19. at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1513)

  20. at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)

  21. at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)

  22. at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)

  23. at java.lang.Thread.run(Thread.java:745)


    这个异常非常多,看报错信息,是tomcat的connector在执行写操作的时候发生了Broken pipe异常,connector是tomcat处理网络请求的,难道是网络出问题了,但是为什么发生异常的都是写,读就没问题呢?为了判断是不是网络问题,于是用wget命令在本地访问了一下服务器的一个接口,结果发现等了好久都没有响应,正常情况下应该是马上就有响应的,这说明不是网络的原因,是服务器的问题,又用命令查看了下当前tcpip连接的状态:

[root@sdfassd logs]# netstat -n | awk '/^tcp/ {++state[$NF]} END {for(key in state) print key,"\t",state[key]}'
CLOSE_WAIT        3853
TIME_WAIT         40
ESTABLISHED       285
LAST_ACT          6


    CLOSE_WAIT 状态的连接竟然有3853个,这太不正常了,这说明是客户端先关闭了连接,服务器端没有执行关闭连接的操作,导致服务器端一直维持在CLOSE_WAIT的状态,如果不对操作系统的keepalive做优化,这个状态默认会维持两个小时,查看了下系统的设置:

[root@sdfassd logs]# sysctl -a |grep keepalive
net.ipv4.tcp_keepalive_time = 7200
net.ipv4.tcp_keepalive_probes = 9
net.ipv4.tcp_keepalive_intvl = 75

    果然是7200秒,这就解释通了,为什么第一次查看tomcat日志最后报错都是“Too manay open files”异常,一定是在两个小时内,close_wait状态暴增,导致文件描述符超过了65535的最大限制;

    而这个状态应该就是broken pipe 异常导致的,是什么导致的broken pipe异常呢?为什么探针关闭了连接,但是数据采集服务器却没有关闭连接?报异常的是tomcat的connector,tomcat不可能会忘记调用close方法去关闭连接,排除了程序的问题,也想不出来是什么导致的了;

    于是去拿了往采集服务器上传数据的探针的日志查看,竟然有大量的一个异常:

2016-11-24 16:27:36,217 [TingYun Harvest Service 1] 166 WARN  - Error occurred sending metric data to TingYun. There can be intermittent connection failures. Please wait for a short period of time: java.net.SocketTimeoutException: Read timed out
java.net.SocketTimeoutException: Read timed out
	at java.net.SocketInputStream.socketRead0(Native Method) ~[na:1.7.0_60]
	at java.net.SocketInputStream.read(SocketInputStream.java:152) ~[na:1.7.0_60]
	at java.net.SocketInputStream.read(SocketInputStream.java:122) ~[na:1.7.0_60]
	at com.tingyun.agent.libs.org.apache.http.impl.io.SessionInputBufferImpl.streamRead(SourceFile:136) ~[tingyun-agent-java.jar:2.1.3]
        .................

    都是read time out异常,那么问题就明确了,  是探针端读取超时了,断开了连接,而这时候数据采集服务器还在处理请求,它并不知道探针端已经断开了连接,处理完请求后再将处理结果发给探针,就broken pipe了;

    原来这个异常是客户端读取超时关闭了连接,这时候服务器端再向客户端已经断开的连接写数据时就发生了broken pipe异常!

 

    探针读超时的时间是2分钟,服务器为什么这么长的时间都没有响应呢?于是使用jstack命令导出了tomcat的线程栈信息进行分析,最后发现代码中有耗时的操作加了锁,导致线程阻塞(保密原因,在这里就不贴代码了);

 

这里总结一下,给我发私信的有些朋友没有get到Broken piple问题的重点,并不是只有超时才会导致这个问题,只要是连接断开,再往这个断开的连接上去执行写操作,都会出现这个异常,客户端超时断开只是其中的一种情况:

另外,当看到“Too manay open files”异常的时候,通常做法除了检查ulimit系统限制外,还应该看一下进程打开的文件句柄数,cat /proc/sys/fs/file-nr命令查看系统总句柄数,当前应用打开的文件句柄数使用ls -l /proc/<pid>/fd | wc -l命令,这里还好忽略了这一步,否则可能又要花费一些时间来查找系统真正的问题;

通过这个案例可知,排查问题时,在有些情况下,你第一眼看到的异常信息未必就是问题的根源所在,而是后续一些连锁反应,尤其是当大量出现同一个异常的情况下,不要看最后一条异常日志,应该先去日志里面查找第一出现该异常的位置,看看这个异常发生之前系统的状况;

java tcp/ip异常

 

 

  • 1 java.net.SocketTimeoutException . 

这 个异 常比较常见,socket 超时。一般有 2 个地方会抛出这个,一个是 connect 的 时 候 , 这 个 超 时 参 数 由connect(SocketAddress endpoint,int timeout) 中的后者来决定,还有就是 setSoTimeout(int timeout),这个是设定读取的超时时间。它们设置成 0 均表示无限大。

 

 

  • 2 java.net.BindException:Address already in use: JVM_Bind 

该 异 常 发 生 在 服 务 器 端 进 行 new ServerSocket(port) 或者 socket.bind(SocketAddress bindpoint)操作时。

原因:与 port 一样的一个端口已经被启动,并进行监听。此时用 netstat –an 命令,可以看到一个 Listending 状态的端口。只需要找一个没有被占用的端口就能解决这个问题。

 

 

  • 3 java.net.ConnectException: Connection refused: connect

该异常发生在客户端进行 new Socket(ip, port)或者 socket.connect(address,timeout)操作时,原 因:指定 ip 地址的机器不能找到(也就是说从当前机器不存在到指定 ip 路由),或者是该 ip 存在,但找不到指定的端口进行监听。应该首先检查客户端的 ip 和 port是否写错了,假如正确则从客户端 ping 一下服务器看是否能 ping 通,假如能 ping 通(服务服务器端把 ping 禁掉则需要另外的办法),则 看在服务器端的监听指定端口的程序是否启动。

 

 

  • 4 java.net.SocketException: Socket is closed 

该异常在客户端和服务器均可能发生。异常的原因是己方主动关闭了连接后(调用了 Socket 的 close 方法)再对网络连接进行读写操作。

 

 

  • 5 java.net.SocketException: Connection reset 或者Connect reset by peer:Socket write error

connection reset by peer在调用write或者read的时候都会出现。按照glibc的说法,是such as by the remote machine rebooting or an unrecoverable protocol violation。从字面意义上来看,是表示远端机器重启或者发生不可恢复的错误。从我的测试来看,目前只出现在对端直接kill掉进程的情况。这两种情况有什么不同呢?对比tcpdump的截包图来看,直接kill掉远端进程的话,远端并没有发送FIN序号,来告诉对方,我已经关闭管道,而是直接发送了RST序号,而远端如果调用close或者shutdown的话,是会发送FIN序号的。按照TCP的四次挥手来看,是需要FIN这个序号的。个人猜测,如果在本端没有收到对方的FIN序号而直接收到了RST序号的话,表明对端出现了machine rebooting or an unrecoverable protocol violation,这时候对这个管道的IO操作,就会出现connection reset by peer错误。

该异常在客户端和服务器端均有可能发生,引起该异常的原因有两个,第一个就是假如一端的 Socket 被关闭(或主动关闭或者因为异常退出而引起的关闭), 另一端仍发送数据,发送的第一个数据包引发该异常(Connect reset by peer)。另一个是一端退出,但退出时并未关闭该连接,另 一 端 假 如 在 从 连 接 中 读 数 据 则 抛 出 该 异 常(Connection reset)。简单的说就是在连接断开后的读和写操作引起的。

还有一种情况,如果一端发送RST数据包中断了TCP连接,另外一端也会出现这个异常,如果是tomcat,异常如下:

 

org.apache.catalina.connector.ClientAbortException: java.io.IOException: Connection reset by peer

 

阿里的tcp方式的健康检查为了提高性能,省去挥手交互,直接发送一个RST来终断连接,就会导致服务器端出现这个异常;

 

对于服务器,一般的原因可以认为:

a) 服务器的并发连接数超过了其承载量,服务器会将其中一些连接主动 Down 掉.

b) 在数据传输的过程中,浏览器或者接收客户端关闭了,而服务端还在向客户端发送数据。

 

 

  • 6 java.net.SocketException: Broken pipe

更详细连接在这里:https://www.cnblogs.com/metoy/p/6565486.html

该异常在客户端和服务器均有可能发生。在抛出SocketExcepton:Connect reset by peer:Socket write error 后,假如再继续写数据则抛出该异常。前两个异常的解决方法是首先确保程序退出前关闭所有的网络连接,其次是要检测对方的关闭连接操作,发现对方 关闭连接后自己也要关闭该连接。

broken pipe只出现在调用write的时候。broken pipe的意思是对端的管道已经断开,往往发生在远端把这个读/写管道关闭了,你无法在对这个管道进行读写操作。从tcp的四次挥手来讲,远端已经发送了FIN序号,告诉你我这个管道已经关闭,这时候,如果你继续往管道里写数据,第一次,你会收到一个远端发送的RST信号,如果你继续往管道里write数据,操作系统就会给你发送SIGPIPE的信号,并且将errno置为Broken pipe(32),如果你的程序默认没有对SIGPIPE进行处理,那么程序会中断退出。一般情况下,可以用signal(SIGPIPE,SIG_IGN)忽略这个信号,这样的话程序不会退出,但是write会返回-1并且将errno置为Broken pipe(32)。broken pipe只会出现在往对端已经关闭的管道里写数据的情况下(在收到对端的RST序号后第一次写不会出现broke pipe,而是write返回-1,这时候正确的做法应该是本端也close这个管道,如果继续write,那么就会出现这个错误)。

 

 
  1. java.net.SocketException: Broken pipe (Write failed)

  2. at java.net.SocketOutputStream.socketWrite0(Native Method)

  3. at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:111)

  4. at java.net.SocketOutputStream.write(SocketOutputStream.java:155)

  5. at sun.security.ssl.OutputRecord.writeBuffer(OutputRecord.java:431)

  6. at sun.security.ssl.OutputRecord.write(OutputRecord.java:417)

  7. at sun.security.ssl.SSLSocketImpl.writeRecordInternal(SSLSocketImpl.java:886)

  8. at sun.security.ssl.SSLSocketImpl.writeRecord(SSLSocketImpl.java:857)

  9. at sun.security.ssl.AppOutputStream.write(AppOutputStream.java:123)

  10. at org.apache.http.impl.io.SessionOutputBufferImpl.streamWrite(SessionOutputBufferImpl.java:124)

  11. at org.apache.http.impl.io.SessionOutputBufferImpl.write(SessionOutputBufferImpl.java:160)

  12. at org.apache.http.impl.io.ContentLengthOutputStream.write(ContentLengthOutputStream.java:113)

  13. at org.apache.http.impl.io.ContentLengthOutputStream.write(ContentLengthOutputStream.java:120)

  14. at org.apache.http.entity.StringEntity.writeTo(StringEntity.java:167)

  15. at org.apache.http.impl.DefaultBHttpClientConnection.sendRequestEntity(DefaultBHttpClientConnection.java:156)

  16. at org.apache.http.impl.conn.CPoolProxy.sendRequestEntity(CPoolProxy.java:160)

  17. at org.apache.http.protocol.HttpRequestExecutor.doSendRequest(HttpRequestExecutor.java:238)

  18. at org.apache.http.protocol.HttpRequestExecutor.execute(HttpRequestExecutor.java:123)

  19. at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:272)

  20. at org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:185)

  21. at org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:89)

  22. at org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:110)

  23. at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:185)

  24. at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:83)

  25. at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:108)

 

对于 4 和 5 这两种情况的异常,需要特别注意连接的维护。在短连接情况下还好,如果是长连接情况,对于连接状态的维护不当,则非常容易出现异常。基本上对长连接需要做的就是:

 

a) 检测对方的主动断连(对方调用了 Socket 的 close 方法)。因为对方主动断连,另一方如果在进行读操作,则此时的返回值是-1。所以一旦检测到对方断连,则主动关闭己方的连接(调用 Socket 的 close 方法)。

 

b) 检测对方的宕机、异常退出及网络不通,一般做法都是心跳检测。双方周期性的发送数据给对方,同时也从对方接收“心跳数据”,如果连续几个周期都没有收到 对方心跳,则可以判断对方或者宕机或者异常退出或者网络不通,此时也需要主动关闭己方连接;如果是客户端可在延迟一定时间后重新发起连接。虽然 Socket 有一个keep alive 选项来维护连接,如果用该选项,一般需要两个小时才能发现对方的宕机、异常退出及网络不通。

 

 

  • 7 java.net.SocketException: Too many open files

原因: 操作系统的中打开文件的最大句柄数受限所致,常常发生在很多个并发用户访问服务器的时候。因为为了执行每个用户的应用服务器都要加载很多文件(new 一个socket 就需要一个文件句柄),这就会导致打开文件的句柄的缺乏。

解决方式:

 

a) 尽量把类打成 jar 包,因为一个 jar 包只消耗一个文件句柄,如果不打包,一个类就消耗一个文件句柄。

b) java 的 GC 不能关闭网络连接打开的文件句柄,如果没有执行 close()则文件句柄将一直存在,而不能被关闭。

也可以考虑设置 socket 的最大打开 数来控制这个问题。对操作系统做相关的设置,增加最大文件句柄数量。

ulimit -a 可以查看系统目前资源限制,ulimit -n 10240 则可以修改,这个修改只对当前窗口有效。

 

  • 8 Cannot assign requested address                                    

1. 端口号被占用,导致地址无法绑定:

java.net.BindException: Cannot assign requested address: bind:是由于IP地址变化导致的;

2. 服务器网络配置异常:

/etc/hosts  中配置的地址错误;

3.还有一种情况是执行ipconfig 发现没有环路地址,这是因为环路地址配置文件丢失了;

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/ainizfb/article/details/108871521

智能推荐

oracle 12c 集群安装后的检查_12c查看crs状态-程序员宅基地

文章浏览阅读1.6k次。安装配置gi、安装数据库软件、dbca建库见下:http://blog.csdn.net/kadwf123/article/details/784299611、检查集群节点及状态:[root@rac2 ~]# olsnodes -srac1 Activerac2 Activerac3 Activerac4 Active[root@rac2 ~]_12c查看crs状态

解决jupyter notebook无法找到虚拟环境的问题_jupyter没有pytorch环境-程序员宅基地

文章浏览阅读1.3w次,点赞45次,收藏99次。我个人用的是anaconda3的一个python集成环境,自带jupyter notebook,但在我打开jupyter notebook界面后,却找不到对应的虚拟环境,原来是jupyter notebook只是通用于下载anaconda时自带的环境,其他环境要想使用必须手动下载一些库:1.首先进入到自己创建的虚拟环境(pytorch是虚拟环境的名字)activate pytorch2.在该环境下下载这个库conda install ipykernelconda install nb__jupyter没有pytorch环境

国内安装scoop的保姆教程_scoop-cn-程序员宅基地

文章浏览阅读5.2k次,点赞19次,收藏28次。选择scoop纯属意外,也是无奈,因为电脑用户被锁了管理员权限,所有exe安装程序都无法安装,只可以用绿色软件,最后被我发现scoop,省去了到处下载XXX绿色版的烦恼,当然scoop里需要管理员权限的软件也跟我无缘了(譬如everything)。推荐添加dorado这个bucket镜像,里面很多中文软件,但是部分国外的软件下载地址在github,可能无法下载。以上两个是官方bucket的国内镜像,所有软件建议优先从这里下载。上面可以看到很多bucket以及软件数。如果官网登陆不了可以试一下以下方式。_scoop-cn

Element ui colorpicker在Vue中的使用_vue el-color-picker-程序员宅基地

文章浏览阅读4.5k次,点赞2次,收藏3次。首先要有一个color-picker组件 <el-color-picker v-model="headcolor"></el-color-picker>在data里面data() { return {headcolor: ’ #278add ’ //这里可以选择一个默认的颜色} }然后在你想要改变颜色的地方用v-bind绑定就好了,例如:这里的:sty..._vue el-color-picker

迅为iTOP-4412精英版之烧写内核移植后的镜像_exynos 4412 刷机-程序员宅基地

文章浏览阅读640次。基于芯片日益增长的问题,所以内核开发者们引入了新的方法,就是在内核中只保留函数,而数据则不包含,由用户(应用程序员)自己把数据按照规定的格式编写,并放在约定的地方,为了不占用过多的内存,还要求数据以根精简的方式编写。boot启动时,传参给内核,告诉内核设备树文件和kernel的位置,内核启动时根据地址去找到设备树文件,再利用专用的编译器去反编译dtb文件,将dtb还原成数据结构,以供驱动的函数去调用。firmware是三星的一个固件的设备信息,因为找不到固件,所以内核启动不成功。_exynos 4412 刷机

Linux系统配置jdk_linux配置jdk-程序员宅基地

文章浏览阅读2w次,点赞24次,收藏42次。Linux系统配置jdkLinux学习教程,Linux入门教程(超详细)_linux配置jdk

随便推点

matlab(4):特殊符号的输入_matlab微米怎么输入-程序员宅基地

文章浏览阅读3.3k次,点赞5次,收藏19次。xlabel('\delta');ylabel('AUC');具体符号的对照表参照下图:_matlab微米怎么输入

C语言程序设计-文件(打开与关闭、顺序、二进制读写)-程序员宅基地

文章浏览阅读119次。顺序读写指的是按照文件中数据的顺序进行读取或写入。对于文本文件,可以使用fgets、fputs、fscanf、fprintf等函数进行顺序读写。在C语言中,对文件的操作通常涉及文件的打开、读写以及关闭。文件的打开使用fopen函数,而关闭则使用fclose函数。在C语言中,可以使用fread和fwrite函数进行二进制读写。‍ Biaoge 于2024-03-09 23:51发布 阅读量:7 ️文章类型:【 C语言程序设计 】在C语言中,用于打开文件的函数是____,用于关闭文件的函数是____。

Touchdesigner自学笔记之三_touchdesigner怎么让一个模型跟着鼠标移动-程序员宅基地

文章浏览阅读3.4k次,点赞2次,收藏13次。跟随鼠标移动的粒子以grid(SOP)为partical(SOP)的资源模板,调整后连接【Geo组合+point spirit(MAT)】,在连接【feedback组合】适当调整。影响粒子动态的节点【metaball(SOP)+force(SOP)】添加mouse in(CHOP)鼠标位置到metaball的坐标,实现鼠标影响。..._touchdesigner怎么让一个模型跟着鼠标移动

【附源码】基于java的校园停车场管理系统的设计与实现61m0e9计算机毕设SSM_基于java技术的停车场管理系统实现与设计-程序员宅基地

文章浏览阅读178次。项目运行环境配置:Jdk1.8 + Tomcat7.0 + Mysql + HBuilderX(Webstorm也行)+ Eclispe(IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持)。项目技术:Springboot + mybatis + Maven +mysql5.7或8.0+html+css+js等等组成,B/S模式 + Maven管理等等。环境需要1.运行环境:最好是java jdk 1.8,我们在这个平台上运行的。其他版本理论上也可以。_基于java技术的停车场管理系统实现与设计

Android系统播放器MediaPlayer源码分析_android多媒体播放源码分析 时序图-程序员宅基地

文章浏览阅读3.5k次。前言对于MediaPlayer播放器的源码分析内容相对来说比较多,会从Java-&amp;amp;gt;Jni-&amp;amp;gt;C/C++慢慢分析,后面会慢慢更新。另外,博客只作为自己学习记录的一种方式,对于其他的不过多的评论。MediaPlayerDemopublic class MainActivity extends AppCompatActivity implements SurfaceHolder.Cal..._android多媒体播放源码分析 时序图

java 数据结构与算法 ——快速排序法-程序员宅基地

文章浏览阅读2.4k次,点赞41次,收藏13次。java 数据结构与算法 ——快速排序法_快速排序法