JVM内存分析:线程死锁

提要

线程转储可用于分析Java应用在某一运行时刻的内部线程的运行情况,包括线程数、线程状态(死锁、运行、等待等),并且可得到线程的执行轨迹,对于分析线程死锁十分有益。

通过JDK内置的工具jstack可转储Java线程:sudo -u tomcat jstack -l <java_pid> > jstack.dump,注意,<java_pid>为主进程ID,无法dump某个线程。

获取Java线程ID:ps aux | grep java
需确保转储用户与线程用户相同,否则,易出现Unable to open socket file: target process not responding or HotSpot VM not loaded的问题;
当出现死锁时,dump操作可能失败,可以通过kill -3 <java_pid>终止死锁(其不会杀死进程或线程!);

得到转储文件后,可将其上传到fastThread进行在线分析,该服务可提供直观的分析图表和相关报告。

也可以下载IBM提供的工具IBM Thread and Monitor Dump Analyze,其同样提供图表分析功能,但整体上没有fastThread的直观。其启动命令为:java -jar jca447.jar

阅读更多
JVM内存分析:内存都去哪儿了

提要

在开始分析之前先了解一下下面几个相关术语:

  • Shallow Heap:对象自身占用的内存大小(包含基本数据类型),不包括它引用对象的大小;
  • Retained HeapShallow Heap + 所有直接或者间接引用对象占用的内存(即该对象被GC回收后,可以被回收的内存);
  • GC Root:被堆外对象引用的对象;
  • Dominator Tree:以支配树方式描述的对象引用关系;

有关JVM内存转储方式的说明见JVM内存分析:Tomcat内存泄漏

案例分析

最近服务器的内存又在狂飙了,网关响应缓慢,Jenkins完成构建需要长达2个多小时。到底疯狂到什么程度呢?用htop命令看看:


阅读更多
JVM内存分析:数据库连接池耗尽

提要

由于数据库连接十分耗时,采取即需即连的方式会导致应用响应缓慢,因此,在Java应用中均采用数据库连接池统一维护一定数量的Connection对象,连接池中的Connection均保持与数据库的长连接,这样,该连接将随时可用,从而提高应用响应和处理速度。

但是,在普遍的使用不当的情形中,最多的问题便是没有及时释放连接,这里的释放是指将Connection对象归还连接池。若连接未被释放,则连接池将被很快耗尽(Exhausted),从而无法提供新的连接,最终导致应用不能进行数据库操作,并在尝试获取新的连接时出现以下异常:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
...
Caused by: org.hibernate.exception.GenericJDBCException: Could not open connection
at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:54)
at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:125)
at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:110)
at org.hibernate.engine.jdbc.internal.LogicalConnectionImpl.obtainConnection(LogicalConnectionImpl.java:221)
at org.hibernate.engine.jdbc.internal.LogicalConnectionImpl.getConnection(LogicalConnectionImpl.java:157)
at org.hibernate.internal.SessionImpl.connection(SessionImpl.java:550)
at org.springframework.orm.hibernate4.HibernateTransactionManager.doBegin(HibernateTransactionManager.java:426)
... 9 more
Caused by: org.apache.commons.dbcp.SQLNestedException: Cannot get a connection, pool error Timeout waiting for idle object
at org.apache.commons.dbcp.PoolingDataSource.getConnection(PoolingDataSource.java:114)
at org.apache.commons.dbcp.BasicDataSource.getConnection(BasicDataSource.java:1044)
at org.hibernate.service.jdbc.connections.internal.DatasourceConnectionProviderImpl.getConnection(DatasourceConnectionProviderImpl.java:141)
at org.hibernate.internal.AbstractSessionImpl$NonContextualJdbcConnectionAccess.obtainConnection(AbstractSessionImpl.java:292)
at org.hibernate.engine.jdbc.internal.LogicalConnectionImpl.obtainConnection(LogicalConnectionImpl.java:214)
... 12 more
Caused by: java.util.NoSuchElementException: Timeout waiting for idle object
at org.apache.commons.pool.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:1174)
at org.apache.commons.dbcp.PoolingDataSource.getConnection(PoolingDataSource.java:106)
... 16 more

阅读更多
JVM内存分析:Tomcat内存泄漏

提要

通过内存转储可对Java应用内各对象的内存使用情况进行分析,从而找出过度消耗内存或无法及时释放的对象,进而为异常修复以及提升应用加载速度和运行性能提供帮助。

内存转储使用JDK自带的工具jmapsudo -u tomcat jmap -dump:format=b,file=heap-dump.bin <java_pid>)将应用内存以二进制格式转储到heap-dump.bin中。

需确保转储用户与线程用户相同,否则会出现Unable to open socket file: target process not responding or HotSpot VM not loaded的问题;

转储文件可能会被放到临时目录中,该目录会在Tomcat重启时被删除,所以,一定要在重启前将转储文件转移到安全位置;

转储的文件一般为GB级,可通过命令xz -k heap-dump.bin进行高强度压缩,得到压缩文件heap-dump.bin.xz。解压使用命令unxz -k heap-dump.bin.xz,其中,-k选项均表示保留原文件,否则原文件将会被删除;

阅读更多
算法分析:求解最长公共子序列

算法分析系列文章中的代码可被任何人无偿使用于任何场景且无需注明来源也不必在使用前征得本文作者同意。

算法分析系列文章旨在传播准确、完整、简洁、易懂、规范的代码实现,并传授基本的编程思想和良好的编码习惯与技巧。

若文章中的代码存在问题或逻辑错误,请通过邮件等形式(见文章结尾)告知于本文作者以便及时修正错误或改进代码。

算法系列文章不可避免地会参考和学习众多网友的成果,在行文风格、内容及求解思路上也会进行借鉴,如有侵权嫌疑,请联系本文作者。

PS:若为转载该文章,请务必注明来源,本站点欢迎大家转载。

问题描述

如果序列 中的所有元素按照其在 中的出现顺序依次出现在另一个序列 中,则称 子序列

子序列不要求位置的连续性(即,元素相邻),只要相对顺序不变即可。

若给定一个序列集合(数量大于或等于2,但通常为两个序列),则这些序列所共同拥有的子序列,称为公共子序列。而在这些公共子序列中长度最长的子序列则称为该序列集合的最长公共子序列(Longest Common Sequence, LCS)。

本例所要求的便是求解任意两个序列的最长公共子序列(可能存在多个不同的序列),并打印其长度及其其中的任意一个序列。

阅读更多
算法分析:求解最大子段和

算法分析系列文章中的代码可被任何人无偿使用于任何场景且无需注明来源也不必在使用前征得本文作者同意。

算法分析系列文章旨在传播准确、完整、简洁、易懂、规范的代码实现,并传授基本的编程思想和良好的编码习惯与技巧。

若文章中的代码存在问题或逻辑错误,请通过邮件等形式(见文章结尾)告知于本文作者以便及时修正错误或改进代码。

算法系列文章不可避免地会参考和学习众多网友的成果,在行文风格、内容及求解思路上也会进行借鉴,如有侵权嫌疑,请联系本文作者。

PS:若为转载该文章,请务必注明来源,本站点欢迎大家转载。

问题描述

给定一个整数(正负数不限)序列 $a_1, a_2, a_3, …, a_n$ ,从该序列中选取任意相邻的一段求和(简称为「子段和」),求解该序列的最大子段和。注:若整个序列的所有元素均为负数,则其最大子段和固定为0。

例如,序列[64, -24, 88, -39, -54, 16]的最大子段和为128(= 64 + (-24) + 88)。

阅读更多
算法分析:求解斐波那契数列

算法分析系列文章中的代码可被任何人无偿使用于任何场景且无需注明来源也不必在使用前征得本文作者同意。

算法分析系列文章旨在传播准确、完整、简洁、易懂、规范的代码实现,并传授基本的编程思想和良好的编码习惯与技巧。

若文章中的代码存在问题或逻辑错误,请通过邮件等形式(见文章结尾)告知于本文作者以便及时修正错误或改进代码。

算法系列文章不可避免地会参考和学习众多网友的成果,在行文风格、内容及求解思路上也会进行借鉴,如有侵权嫌疑,请联系本文作者。

PS:若为转载该文章,请务必注明来源,本站点欢迎大家转载。

问题描述

从0和1开始,之后的每一个数均为前两个数的和,这样性质的数依次排列,便称为斐波那契数列。即形成如下数列形式:

1
0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, ...

用数学公式表示该数列即为:

本案例所要解决的就是:给定一个整数n,求解斐波那契数列中第n项的数值。注意,0表示第零项,而不是第一项。

阅读更多
算法分析:分治法求解给定集合中的众数及其重数

算法分析系列文章中的代码可被任何人无偿使用于任何场景且无需注明来源也不必在使用前征得本文作者同意。

算法分析系列文章旨在传播准确、完整、简洁、易懂、规范的代码实现,并传授基本的编程思想和良好的编码习惯与技巧。

若文章中的代码存在问题或逻辑错误,请通过邮件等形式(见文章结尾)告知于本文作者以便及时修正错误或改进代码。

算法系列文章不可避免地会参考和学习众多网友的成果,在行文风格、内容及求解思路上也会进行借鉴,如有侵权嫌疑,请联系本文作者。

PS:若为转载该文章,请务必注明来源,本站点欢迎大家转载。

问题描述

给定含有n个元素的多重集合S,每个元素在S出现的次数称为该元素的重数。多重集S重数最大的元素称为众数mode)。

例如,S={1,2,2,2,3,5},则,多重集S的众数是2,其重数为3

注:众数可能存在多个。

本案例要求采用分治法求解给定集合中的众数及其重数,存在多个众数时选择第一个即可。

分治法,即,把一个复杂的问题分成两个或更多的相同或相似的子问题,直到最后子问题可以简单的直接求解,原问题的解即子问题的解的合并。(引用自「维基百科」)

阅读更多
记一次惊心动魄的CentOS系统升级经历
阅读更多
Nginx特例场景配置

本文所使用的相关代码片段可从 https://github.com/flytreeleft/docker-nginx-gateway 得到完整内容。

Nginx随机展示自定义错误页面

Source code: https://github.com/flytreeleft/docker-nginx-gateway/tree/master/config/error-pages
Custom error pages: https://github.com/flytreeleft/docker-nginx-gateway/tree/master/examples/epage.d/all

关键字

  • 随机展示多个错误页面
  • Nginx自定义错误页面

在访问HTTP站点时最容易出现的错误就是404,于是就有许多非常有个性的404错误页面。而为我们自己的站点放置一些简洁、清爽的错误页面,在资源再利用的前提下,也将为我们自身增加不少好感和亲和力。

这里将要介绍的便是如何为我们的站点配置自定义错误页面,并同时支持为相同错误随机展示不同的错误页面。

阅读更多