只有静态方法的java加载类
我有一个类MyClass
,它有一个静态变量。类实现类似smth的单例(它将java.sql.DataSource
作为静态变量,并具有方法getConnection()
,该方法检查数据源变量是否为null,如果为null,则获取连接,否则返回dataSource.getConnection()
)
当我第一次调用MyClass.getConnection()
方法时,类被加载到内存中,并获得数据源变量。当程序运行时,这个类会留在内存中吗?或者当程序的控制流在调用MyClass.getConnection()
的方法之外退出时,它会被垃圾收集吗?
实际上我想知道我是否必须在每个方法中获取连接对象(获取连接对象是一个相当长的操作,不是吗?)我在哪里使用它,还是在某个地方只使用一次
编辑 这是我的类获得连接
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池获得连接
所以,如果我用一种方法调用ResourceManager。getConnection()并获取数据源,经过一段时间后调用此方法时,它是同一个数据源还是GC
另外,我在finally块中使用close方法
# 1 楼答案
当处理静态方法等时,它们不属于实例。因此,在收集实例时不会对它们进行垃圾收集。相反,它们会留在记忆中。理论上,它们应该一直保存在内存中,直到相关应用程序终止。只要它继续运行,静态项就会留在内存中
这对你意味着什么?如果要关闭应用程序,则将单例设置为收集,并在某个时间点收集。否则,它将留在那里
# 2 楼答案
当不存在对类对象的引用时,类对象将像任何其他对象一样有资格进行垃圾收集。通常,这些引用由首先加载类的类加载器持有。因此,只要引用该类的类加载器在使用中,该类就会一直存在。除非类加载器是由调用方创建的,并且对类加载器的引用不再存在,否则在方法执行后不会卸载它
在长时间运行的应用程序(如JavaEE应用程序)中,类和类加载器(每个应用程序通常都有一个唯一的类加载器)将无法进行垃圾收集,直到应用程序本身被关闭
单子模式及其对GC的影响
实现单例模式的类的垃圾收集是一种独特的情况。该类将继续被其实例引用,因此它将永远无法进行垃圾收集。这可能会导致类加载器本身可能无法被垃圾收集的问题,尤其是在容器中的应用程序重新启动期间,从而导致内存泄漏。防止此类问题的解决方案是在侦听上下文(应用程序)销毁事件的上下文侦听器中销毁单例实例
更新#2
更新后的问题:
获取连接的成本很高,但前提是你要管理连接。这就是为什么要使用连接池支持的数据源。每次需要连接时,数据源都会从池中获取一个连接。连接完成后,应将其关闭,以便将其返回到池中。我的建议是不要过早地进行优化;连接池是现代JavaEE应用程序中的一个事实,应用程序服务器执行了足够的优化,以确保这里的延迟非常小。依我看,一个经过适当调整的池将比一个手工制作的类提供更好的性能,该类用于集中访问连接对象