有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

只有静态方法的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方法


共 (2) 个答案

  1. # 1 楼答案

    当处理静态方法等时,它们不属于实例。因此,在收集实例时不会对它们进行垃圾收集。相反,它们会留在记忆中。理论上,它们应该一直保存在内存中,直到相关应用程序终止。只要它继续运行,静态项就会留在内存中

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

  2. # 2 楼答案

    Will this class stay in memory while the program is running or it will be garbage collected when the control flow of the program will exit outside the method where MyClass.getConnection() was invoked?

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

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

    单子模式及其对GC的影响

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

    更新#2

    更新后的问题:

    Actually I want to know whether I have to obtain Connection object in each method(obtaining connection object is rather long operation, isn't it?) where I use it or only once in some place?

    获取连接的成本很高,但前提是你要管理连接。这就是为什么要使用连接池支持的数据源。每次需要连接时,数据源都会从池中获取一个连接。连接完成后,应将其关闭,以便将其返回到池中。我的建议是不要过早地进行优化;连接池是现代JavaEE应用程序中的一个事实,应用程序服务器执行了足够的优化,以确保这里的延迟非常小。依我看,一个经过适当调整的池将比一个手工制作的类提供更好的性能,该类用于集中访问连接对象