加载只有静态方法的类

时间:2011-06-11 17:38:42

标签: java jdbc

我有一个具有静态变量的类MyClass。类实现了像singleton一样的smth(它有java.sql.DataSource作为静态变量,并且有方法getConnection(),它检查DataSource变量是否为null,如果为null,则获取连接,否则返回dataSource.getConnection() ) 当我第一次调用MyClass.getConnection()方法时,将类加载到内存中并获取DataSource变量。当程序运行时,此类是否会保留在内存中,或者当程序的控制流将在调用MyClass.getConnection()的方法之外退出时,它将被垃圾收集? 其实我想知道我是否必须在每个方法中获取Connection对象(获取连接对象是相当长的操作,不是吗?)我在哪里使用它或在某个地方只使用一次?

修改 这是我的类获取连接

public class ResourceManager {

    private static DataSource dataSource;


    public static synchronized Connection getConnection() throws NamingException, SQLException {
        if (dataSource == null) {
            Locale.setDefault(Locale.ENGLISH);
            Context context = (Context) new InitialContext().lookup("java:comp/env");
            dataSource = (DataSource) context.lookup("jdbc/Project");
            context.close();
        }
        return dataSource.getConnection();
    }


    public static void close(Connection con) {
        if (con != null)
            try {
            con.close();
        } catch (SQLException ex) {
            Logger.getLogger(ResourceManager.class.getName()).log(Level.SEVERE, null, ex);
        }
    }


    public static void close(ResultSet rs) {
        if (rs != null)
            try {
            rs.close();
        } catch (SQLException ex) {
            Logger.getLogger(ResourceManager.class.getName()).log(Level.SEVERE, null, ex);
        }
    }


    public static void close(PreparedStatement stmt) {
        if (stmt != null)
            try {
            stmt.close();
        } catch (SQLException ex) {
            Logger.getLogger(ResourceManager.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
}

在这个类中我从tomcat池获取连接

因此,如果在一个方法中我调用ResourseManager.getConnection()并获取数据源,那么在经过一段时间后调用此方法时它是同一个数据源还是GC?

P.S。我在finally块中使用close方法

2 个答案:

答案 0 :(得分:2)

  

这节课会留在记忆中吗?   程序正在运行或将会运行   控制时收集垃圾   程序的流程将从外面退出   方法在哪里   调用了MyClass.getConnection()?

类对象将像任何其他对象一样有资格进行垃圾收集 - 当Class对象不存在引用时。通常,这些引用由首先加载Class的ClassLoader持有。因此,只要引用它的类加载器正在使用中,该类将保持不变。方法执行后不会卸载它,除非类型加载器是由调用者创建的,并且对类加载器的引用不再存在。

在长时间运行的应用程序(如Java EE应用程序)中,类和类加载器(每个应用程序通常都存在一个唯一的应用程序)将无法进行垃圾回收,直到应用程序本身被关闭。

单例模式及其对GC的影响

实现单例模式的类的垃圾收集是一种独特的情况。该类继续被其实例引用,因此它永远不会有资格进行垃圾回收。这可能导致类加载器本身可能不被垃圾收集的问题,尤其是在容器中的应用程序重新启动期间,从而导致内存泄漏。防止出现此类问题的解决方案是销毁侦听上下文(应用程序)销毁事件的上下文侦听器中的单例实例。

更新#2

更新问题:

  

其实我想知道我是否必须在每个方法中获取Connection对象(获取连接对象是相当长的操作,不是吗?)我在哪里使用它或在某个地方只使用一次?

获取连接非常昂贵,但前提是您管理连接。这就是您使用连接池支持的数据源的原因。每次需要连接时,数据源都将从池中获取一个。完成连接后,应将其关闭,以便将其返回到池中。我的建议是不要过早优化;连接池在现代Java EE应用程序中是一个事实,应用程序服务器执行足够的优化以确保此处的延迟非常短。恕我直言,一个经过适当调整的池将为您提供比手工制作的类更好的性能,以集中访问连接对象。

答案 1 :(得分:0)

当您处理静态方法等时,它们不属于实例。因此,在收集实例时,它们不会被垃圾收集。相反,他们留在记忆中。理论上,他们应该留在记忆中,直到有关的申请被终止。只要它继续运行,静态项就会留在内存中。

这对你意味着什么?如果你要关闭应用程序,Singleton将被设置为收集并在某个时间点收集。否则,它将留在那里。