本文编写时,公司代码已被重构过,所以无法彻底重现当时环境。文章配图之间也已经过了多次 thread dump,所以 PID 与 TID 无法对上号。

最近公司一个新项目在测试环境运行的时候出现长期 CPU 占用 100% 的情况。经过检查,MySQL 和 SQL Server 均无慢查询以及长时间 IO 占用,最后将注意力集中在应用本身。

由于 Windows 自带的 Task Manager 功能太弱,请选择 Sysinternals 套件内的 Process Explorer 作为监测工具。

首先使用 Process Explorer 检查高占用的进程,记下 PID(Process ID),随后双击打开 Threads 选项卡

由图可知,TID 为 22172 的线程消耗大量的 CPU 时间。因而可以初步锁定问题所在。

接下来请出 jstack, 他是 jdk 自带的线程堆栈分析工具,可以查看或导出 Java 应用程序中线程堆栈信息。

输入 jstack -l <PID> 输出 Thread Dump

如有必要,可将 Dump 导出,如 jstack -l <PID> > C:\trace.log

在 thread dump 中每个线程都有一个 nid, 将上述高占用的 TID 转成十六进制后, 找到与 dump 相对应的 nid。便是该线程的工作详情了。

从图上我们可以看出,当前正在跑的 MainThread.java 的是第 36 行

得到了 dump 详情以后,就可以着手在对应的代码中找错优化了。

之前在使用 Systemd 运行 Haproxy 的时候经常遇到一些莫名奇妙的问题, Google 一番后得知是 SELinux 的锅。

既然找到了问题,在还没学会怎么配置 SELinux 之前,只需要暴力禁用他就好了(

修改 /etc/selinux/config

将文件改为以下内容并保存

#SELINUX=enforcing
#SELINUXTYPE=targeted
SELINUX=disabled

最后执行 setenforce 0 使配置立即生效

方法 1:添加 isELIgnored

在 Maven 项目中的每个 JSP 页面添加以下语句,否则将无法解析 EL 表达式

<%@ page isELIgnored="false" %>

以下为 EL 表达式示例:

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page isELIgnored="false" %>

<table>
    <table width="%80" border="1" height="56">
        <tr align="center">
            <td>用户名</td>
            <td>用户密码</td>
            <td>用户年龄</td>
        </tr>

        <c:forEach var="users" items="${userList}">
            <tr align="center">
                <td>${users.username }</td>
                <td>${users.password }</td>
                <td>${users.age }</td>
            </tr>
        </c:forEach>
    </table>

 

方法 2 :修改 web.xml

将 Maven 工程默认的 web.xml 头部这一段

<!DOCTYPE web-app PUBLIC
 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 "http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app>

替换成如下格式

<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
         http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
     version="3.0" metadata-complete="true">