Loading class which have only static methods

2019-07-09 02:57发布

问题:

I have a class MyClass that has a static variable. Class implements smth like singleton(it has java.sql.DataSource as static variable and has method getConnection() which checks whether DataSource variable is not null and if it is null - obtains the connection, else - return dataSource.getConnection()) When I call MyClass.getConnection() method for the first time the class is loaded to the memory and DataSource variable is obtained. 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? 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?

edit This is my class that obtains a 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);
        }
    }
}

in this class I obtain connection from tomcat pool

So, if in one method I call ResourseManager.getConnection() and it obtains the datasource, will it be the same datasource when I call this method after some time passed or it will be GC?

P.S. I use close methods in finally blocks

回答1:

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?

Class objects will become eligible for garbage collection just like any other object - when no references exist to the Class objects. Typically, these references are held by the ClassLoader that loaded the Class in the first place. So, the class will stay as long as the Classloader that references it, is in use. It will not be unloaded after method execution, unless the Classloader was created by the caller, and the reference to the classloader no longer exists.

In long running applications (like Java EE applications), the class and the classloader (a unique one will typically exist for every application) will not be eligible for garbage collection, until the application itself is brought down.

The singleton pattern and its effect on GC

The garbage collection of classes that implement the singleton pattern is a unique situation. The class continues to be referenced by its instance, so it will never be eligible for garbage collection. This could lead to problems where the classloaders themselves may not be garbage collected, especially during application restarts in a container, thus leading to a memory leak. The solution to prevent such a problem, is to destroy the singleton instance in a context listener that listens for the context (application) destruction event.

Update #2

For the updated question:

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?

Obtaining a connection is expensive, but only if you manage the connection. That's why you use a datasource backed by a connection pool. Everytime you need a connection, the datasource will fetch one from the pool. Once you are done with the connection, you should close it, so that it can be returned to the pool. My advice is to not perform premature optimizations; connection pools are a fact in modern Java EE applications, and application servers perform enough optimization to ensure that there is very little latency here. IMHO, a properly tuned pool will give you better performance than a hand-crafted class put in place to centralize access to connection objects.



回答2:

When you deal with static methods, etc., they do not belong to an instance. As such, they are not garbage collected when instances are collected. Instead, they stay in memory. In theory, they should stay in memory until the application in question is terminated. As long as it continues to run, the static items stay in memory.

What this means to you? if you are shutting down the application, the Singleton will be set for collection and collected at some point in time. Otherwise, it will stay there.



标签: java jdbc