java OOM 解决思路

来源:互联网 发布:域名解析到ip端口号 编辑:程序博客网 时间:2024/06/05 15:51

最近在一个项目中遇到一个内存泄露的异常。网上查了一些资料,总结一下解决步骤,以免以后忘记了。

1.首先下载JProfiler ,它能分析Java的JVM中的对象数量,线程数量等等。

2.安装好之后 ,查看程序运行时,是否有对象数量在不断的上升,如果有的话则检查一下这个对象相关的业务逻辑。

3.如果对象的数量都很稳定,则可以查看是否是因为线程数量过多而导致的内存溢出。

  3.1  如果是线程数量过多而导致的内存溢出首先检查你的程序的线程是否有死循环而导致线程数量的骤增。

  3.2  如果没有线程死循环的话则可以用 jstack -l pid  查看线程的状态。但是首先得通过tasklist 获取工程的线程ID

  3.3 获取线程ID之后  通过jstack -l pid >> c://1.txt中即可查看当前线程的状态,即可分析新增线程的原因

4.我在导出的txt中看到了这样的信息at com.mchange.v2.resourcepool.BasicResourcePool.awaitAvailable(BasicResourcePool.java:1459)
    这个线程一直在等待可用的连接。于是我检查了一下连接池的配置。以及是否每个涉及到DB操作的方法都有Close掉连接。
5.检查之后发现每个连接用完都是有关闭的,但是还是会出现等待可用连接的情况,于是我重新配置了一下连接池,问题解决了。有空的话在去研究一下为什么

package net.dudugo.utils;

import java.beans.PropertyVetoException;
import java.io.IOException;
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

import org.springframework.core.io.support.PropertiesLoaderUtils;

import com.mchange.v2.c3p0.ComboPooledDataSource;

public class C3P0Util {

    public static String DATA_SOURCE = "DataSource";
    public static String BUSS_DATA_SOURCE = "BussdataSource";
    private static String user;
    private static String password;
    private static String jdbcUrl;
    private static String bussdataUrl;
    public static int port;
    public static String imgsrc;
    public static String frontIP;// 前置机IP
    public static long velID;
    private ComboPooledDataSource dataSource = null;
    private ComboPooledDataSource bussdataSource = null;

    private static C3P0Util instance = null;

    private C3P0Util() {
        java.util.Properties props;
        try {
            props = PropertiesLoaderUtils.loadAllProperties("jdbc.properties");
            user = props.getProperty("user");
            password = props.getProperty("password");
            jdbcUrl = props.getProperty("jdbcUrl");
            bussdataUrl = props.getProperty("bussUrl");
            imgsrc = props.getProperty("imgsrc");
            frontIP = props.getProperty("frontIP");
            velID = Long.parseLong(props.getProperty("velID"));
            port = Integer.parseInt(props.getProperty("port"));
            dataSource = new ComboPooledDataSource();
            bussdataSource = new ComboPooledDataSource();

            initdataSource(jdbcUrl, dataSource);
            initdataSource(bussdataUrl, bussdataSource);
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    private static void initdataSource(String url,
            ComboPooledDataSource dataSource) {
        dataSource.setUser(user);
        dataSource.setPassword(password);
        dataSource.setJdbcUrl(url);
        try {
            dataSource.setDriverClass("com.mysql.jdbc.Driver");
            dataSource.setInitialPoolSize(20);
            dataSource.setMinPoolSize(10);
            dataSource.setMaxPoolSize(100);
            dataSource.setMaxIdleTime(7200);
            dataSource.setIdleConnectionTestPeriod(360);
            dataSource.setAcquireIncrement(5);
            dataSource.setAcquireRetryAttempts(500);
            dataSource.setAcquireRetryDelay(1000);
            dataSource.setBreakAfterAcquireFailure(true);
            dataSource.setCheckoutTimeout(20000);
            dataSource.setAutoCommitOnClose(false);
            dataSource.setForceIgnoreUnresolvedTransactions(false);
            dataSource.setUnreturnedConnectionTimeout(1000);
            dataSource.setMaxStatements(0);
            dataSource.setMaxStatementsPerConnection(0);
            dataSource.setTestConnectionOnCheckin(true);
            dataSource.setTestConnectionOnCheckout(false);
            dataSource.setUsesTraditionalReflectiveProxies(false);
            dataSource.setNumHelperThreads(5);

        } catch (PropertyVetoException e) {
            e.printStackTrace();
        }

    }

    public static final synchronized C3P0Util getInstance() {
        if (instance == null) {
            instance = new C3P0Util();
        }
        return instance;
    }

    public synchronized Connection getConnection(String dataSourceName)
            throws SQLException {

        if (DATA_SOURCE.equals(dataSourceName)) {
//            System.out.println("dataSource 正在使用连接数  "
//                    + dataSource.getNumBusyConnections());
//            System.out.println("dataSource  空闲连接数  "
//                    + dataSource.getNumIdleConnections());// 空闲连接数
            return dataSource.getConnection();
        } else if (BUSS_DATA_SOURCE.equals(dataSourceName)) {
//            System.out.println("bussdataSource 正在使用连接数  "
//                    + bussdataSource.getNumBusyConnections());
//            System.out.println("bussdataSource  空闲连接数  "
//                    + bussdataSource.getNumIdleConnections());// 空闲连接数
            return bussdataSource.getConnection();
        }
        return null;
    }

    public synchronized void close(Connection conn) {
        try {
            if (conn != null) {
                conn.close();
                conn = null;
            }
        } catch (SQLException e) {
        }
    }

    public synchronized void close(Statement stat) {
        try {
            if (stat != null) {
                stat.close();
                stat = null;
            }
        } catch (SQLException e) {
        }
    }

    public synchronized void close(ResultSet rest) {
        try {
            if (rest != null) {
                rest.close();
                rest = null;
            }
        } catch (SQLException e) {
        }
    }

    public synchronized void close(CallableStatement proc) {
        try {
            if (proc != null) {
                proc.close();
                proc = null;
            }
        } catch (SQLException e) {
        }
    }

    public static void main(String[] args) {
        new Thread(new TestThread(), "test").start();
    }

    private static class TestThread implements Runnable {

        private String dataSource = DATA_SOURCE;

        @Override
        public void run() {
            try {
                String sql = "select vel_id from vehicle_info where dev_no = ?";
                Connection conn = C3P0Util.getInstance().getConnection(
                        C3P0Util.DATA_SOURCE);
                java.sql.PreparedStatement ps = conn.prepareStatement(sql);
                ps.setString(1, "000000912345");
                ResultSet rs = ps.executeQuery();
                while (rs.next()) {
                    System.out.println(rs.getLong(1));
                }

            } catch (Exception e) {
                e.printStackTrace();
            }

        }

    }
}


0 0
原创粉丝点击