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