一次Tomcat溢出的临时处理

公司服务器上Tomcat不知哪个项目有隐患代码,经常溢出,不停的重启!

起初打算用Jprofiler监控下内存(本文后面有完整例子),但发现线上环境bin目录下的.sh被修改的乱七八糟,导致某些.sh无法运行,所以就打算写个RMI的定时gc程序,现用虚拟机模拟下线上环境

环境信息如下:

Red Hat Enterprise Linux Server release 6.3 (Santiago)

Java(TM) SE Runtime Environment (build 1.6.0_45-b06)

apache-tomcat-6.0.41

jprofiler7 linux-x64

ip:    10.211.55.4

------------------------------------------------------------------------------------------------------------------------

1.配置Tomcat RMI


Tomcat打开RMI

JAVA_OPTS="-Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=9999 -Djava.rmi.server.hostname=10.211.55.4 -Dcom.sun.management.jmxremote.authenticate=true -Dcom.sun.management.jmxremote.ssl=false"

    配置hostname

hostname 10.211.55.4

    防火墙开放端口

-A INPUT -m state --state NEW -m tcp -p tcp --dport 9999 -j ACCEPT

 重启防火墙

/etc/init.d/iptables restart

配置授权

a.拷贝jmxremote.password.template到本地目录,名为jmxremote.password

cd /usr/java/jdk1.6.0_45/jre/lib/management
cp jmxremote.password.template jmxremote.password

b.编辑jmxremote.access文件,添加用户和权限

tango         readwrite               create javax.management.monitor.*,javax.management.timer.*               unregister

c.编辑jmxremote.password文件,设置用户密码

tango   rmipassword

d.修改jmxremote.password文件为只读

chmod 600 jmxremote.password

用Jconsole测试RMI

a.启动Tomcat

./startup.sh

b.测试RMI,客户端键入如下命令,前提是java安装目录配置到PATH中

显示以上画面,则说明rmi连接成功!

2.编写程序

需求:

1.定时通过RMI通知remote jvm 执行gc任务,

2.执行次数和运行时间


代码片段如下:

public static void main(String[] args) throws IOException, MalformedObjectNameException {
        Properties properties = Console.parseArguments(args);
        //
        final String host = properties.getProperty(HOST, "localhost");
        final String port = properties.getProperty(PORT, "1099");
        final String interval = properties.getProperty(INTERVAL);
        final String tryCount = properties.getProperty(TRY);
        final String rmiServer = getRMIServer(host, port);
        final String user = properties.getProperty(USER);
        final String pass = properties.getProperty(PASS);
        final String report = properties.getProperty(REPORT, "./gc.out");
        //
        final Invoke invoke = new Invoke() {
            @Override
            public Object execute(JMXConnector connector) throws IOException, MalformedObjectNameException {
                MBeanServerConnection mBeanServerConnection = connector.getMBeanServerConnection();
                MemoryMXBean memoryMXBean = JMX.newMBeanProxy(mBeanServerConnection, ObjectName.getInstance("java.lang:type=Memory"), MemoryMXBean.class);
                memoryMXBean.gc();
                return null;
            }
        };
        if (interval == null) {
            execute(rmiServer, user, pass, invoke);
        } else {
            final int i = interval.matches("\\d+") ? Integer.parseInt(interval) : 6000;
            final int t = tryCount.matches("\\d+") ? Integer.parseInt(tryCount) : 3;

            final File reportFile = new File(report);
            if (!reportFile.exists()) {
                reportFile.createNewFile();
            } else if (reportFile.isDirectory()) {
                throw new RuntimeException(new MessageFormat("can`t write file {0},file is directory!").format(new String[]{reportFile.getAbsolutePath()}));
            } else if (!reportFile.canWrite()) {
                throw new RuntimeException(new MessageFormat("can`t write file {0},file is readonly!").format(new String[]{reportFile.getAbsolutePath()}));
            }
            new Thread(new Runnable() {

                private final ThreadLocal<AtomicInteger> error = new ThreadLocal<AtomicInteger>();
                private final ThreadLocal<AtomicInteger> local = new ThreadLocal<AtomicInteger>();
                private final ThreadLocal<Date> start = new ThreadLocal<Date>();

                @Override
                public void run() {
                    local.set(new AtomicInteger(0));
                    error.set(new AtomicInteger(0));
                    start.set(new Date());
                    while (true) {
                        AtomicInteger errorAtomic = error.get();
                        try {
                            if (errorAtomic.get() > t) {
                                return;
                            }
                            execute(rmiServer, user, pass, invoke);
                            Thread.sleep(i);
                        } catch (Exception e) {
                            e.printStackTrace();
                            errorAtomic.addAndGet(1);
                        }
                        report();
                    }
                }

                private void report() {
                    AtomicInteger runAtomic = local.get();
                    AtomicInteger errorAtomic = local.get();
                    Date date = start.get();
                    runAtomic.addAndGet(1);
                    try {
                        FileOutputStream fileOutputStream = new FileOutputStream(reportFile);
                        PrintWriter writer = new PrintWriter(fileOutputStream, false);
                        writer.write("run : ".concat(String.valueOf(runAtomic.get())));
                        writer.write("\r\n");
                        long l = (new Date().getTime() - date.getTime()) / 1000;
                        writer.write("run time: ".concat(String.valueOf(l).concat("s")));
                        writer.write("\r\n");
                        writer.write("error : ".concat(String.valueOf(errorAtomic.get())));
                        writer.write("\r\n");
                        writer.flush();
                        writer.close();
                    } catch (FileNotFoundException e) {
                        System.err.println(e.getMessage());
                        throw new RuntimeException(e);
                    }
                }
            }).start();
        }
    }

get start:

java -classpath "..." org.tango.tools.Gc --host=10.211.55.4 --port=9999 --interval=10000 --try=10 --user=tango --pass=rmipassword

此方法是被逼无奈,最好还是检查工程代码,查看溢出原因!

下回说Jprofiler监控Tomcat

本文完!(下附工程代码,maven构建)

一次Tomcat溢出的临时处理,布布扣,bubuko.com

时间: 2025-01-17 11:42:28

一次Tomcat溢出的临时处理的相关文章

eclipse项目配置tomcat后浏览器访问不到项目解决方案

先把项目从tomcat溢出,并删除tomcat,然后再次导入 双击: 修改:

使用jvisualvm调试本地Tomcat应用

今天想用jvisualvm调试下Tomcat,却发现jvisualvm中找不到Tomcat,原来是因为Tomcat的临时目录设置问题.jvisualvm是通过pid来查找本地java应用的,pid文件存放在临时目录下的hsperfdata_<username>文件夹下.而Tomcat的临时目录使用的是CATALINA_TMPDIR: %_EXECJAVA% %JAVA_OPTS% %CATALINA_OPTS% %DEBUG_OPTS% -Djava.endorsed.dirs="%

web服务器是什莫: tomcat各个目录简介

1. 时间Web服务器可以解析Http协议,Web服务器就是收到客户端的Http请求会返回客户端一个Http响应2.tomcat下各个目录     bin: 存放启动和关闭tomcat的脚本文件如打开startup.bat 关闭shutdown.bat     conf: 存放tomcat各种的配置文件     lib:存放tomcat服务器和web程序需要访问的JAR文件     logs:存放tomcat的日志文件     temp:存放tomcat运行时临时产生的文件     webapp

spring boot应用启动原理分析

spring boot quick start 在spring boot里,很吸引人的一个特性是可以直接把应用打包成为一个jar/war,然后这个jar/war是可以直接启动的,不需要另外配置一个Web Server. 如果之前没有使用过spring boot可以通过下面的demo来感受下. 下面以这个工程为例,演示如何启动Spring boot项目: git clone [email protected]:hengyunabc/spring-boot-demo.git mvn spring-b

SQLite剖析之动态内存分配

SQLite通过动态内存分配来获取各种对象(例如数据库连接和SQL预处理语句)所需内存.建立数据库文件的内存Cache.以及保存查询结果.我们做了很多努力来让SQLite的动态内存分配子系统可靠.可预测.健壮并且高效.本文概述SQLite的动态内存分配,软件开发人员在使用SQLite时可以据此获得最佳性能. 1.特性    SQLite内核和它的内存分配子系统提供以下特性:    (1)对内存分配失败的健壮处理.如果一个内存分配请求失败(即malloc()或realloc()返回NULL),SQ

DiskFileItemFactory用法

在使用servlet上传文件时,使用DiskFileItemFactory(在使用struts时利用InputStream和OutputStream) 将请求消息实体中的每一个项目封装成单独的DiskFileItem (FileItem接口的实现) 对象的任务由 org.apache.commons.fileupload.FileItemFactory 接口的默认实现 org.apache.commons.fileupload.disk.DiskFileItemFactory 来完成.当上传的文

jsp中include的两种用法

JSP中的include的两种用法 1.两种用法 <%@ include file=” ”%> <jsp:include page=” ” flush=”true”/> 2.用法区别 (1)执行时间上区别 <%@ include file=”relativeURI”%>                   是在翻译阶段执行 <jsp:include page=”relativeURI” flush=”true” />  在请求处理阶段执行. (2)引入内容的

maven(三):maven项目结构及其运行机制

在上一篇中讲了如何创建maven项目,现在回到那个项目 项目结构 src/main/java:java代码目录 src/main/resources:资源目录,比如spring.xml文件,properties参数等 java和resources目录的内容都会编译到classpath下,也就是和传统项目的src目录一样的作用,这里分成多个目录是为了开发时方便管理资源 libraries:默认只有jre和maven,没有引入tomcat库,我们的项目应该可以在所有的web服务器中运行,而不仅仅是t

Apache FileUpload详细介绍

Apache FileUpload组件 在最初的 http 协议中,没有上传文件方面的功能.RFC1867("Form-based File Upload in HTML".)为 http 协议添加了这个功能.客户端的浏览器,如 Microsoft IE, Mozila, Opera 等,按照此规范将用户指定的文件发送到服务器.服务器端的网页程序,如 php, asp, jsp 等,可以按照此规范,解析出用户发送来的文件. 1.1.客户端 简单来说,RFC1867规范要求http协议增