[ https://issues.apache.org/jira/browse/HIVE-5296?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=13775564#comment-13775564 ]
Kousuke Saruta commented on HIVE-5296: -------------------------------------- I found the instance of Hashtable$Entry continuing to increase. This is caused by two reasons as follows. 1. opHandle wouldn't release if Exception is thrown during executing query or command When Exception is thrown during executing query or command, operation handle object will not be released from Map (OperationManager#handleToOperation) because opHandleSet.add(opHandle) will not be executed in HiveSessionImpl (Hiveserver2 side) and execResp.getOperationHandle() will not be executed in HiveStatement (JDBC Client side). {code} public OperationHandle executeStatementInternal() throws HiveSQLException { acquire(); try { ExecuteStatementOperation operation = getOperationManager() .newExecuteStatementOperation(getSession(), statement, confOverlay, runAsync); opHandle operation.run(); <--------------- Throws exception and cannot get handle. OperationHandle opHandle = operation.getHandle(); opHandleSet.add(opHandle); return opHandle; } finally { release(); } } {code} {code} public boolean execute(String sql) throws SQLException { ... try { closeClientOperation(); TExecuteStatementReq execReq = new TExecuteStatementReq(sessHandle, sql); execReq.setConfOverlay(sessConf); TExecuteStatementResp execResp = client.ExecuteStatement(execReq); Utils.verifySuccessWithInfo(execResp.getStatus()); <--------------- Throws exception and cannot get handle. stmtHandle = execResp.getOperationHandle(); } catch (SQLException eS) { throw eS; } catch (Exception ex) { throw new SQLException(ex.toString(), "08S01", ex); } ... {code} 2. FileSystem$Cache will be increase. When we call FileSystem#get, FileSystem object is cached in FileSystem$Cache. Cache is implemented using HashMap and equality of Key is implemented as follows. {code} /** {@inheritDoc} */ public int hashCode() { return (scheme + authority).hashCode() + ugi.hashCode() + (int)unique; } static boolean isEqual(Object a, Object b) { return a == b || (a != null && a.equals(b)); } /** {@inheritDoc} */ public boolean equals(Object obj) { if (obj == this) { return true; } if (obj != null && obj instanceof Key) { Key that = (Key)obj; return isEqual(this.scheme, that.scheme) && isEqual(this.authority, that.authority) && isEqual(this.ugi, that.ugi) && (this.unique == that.unique); } return false; } {code} Key contains UserGroupInformation and two UserGroupInformation objects are equivalent when the Subject objects included in each UserGroupInformation object are same (not equivalent). {code} public boolean equals(Object o) { if (o == this) { return true; } else if (o == null || getClass() != o.getClass()) { return false; } else { return subject == ((UserGroupInformation) o).subject; } } {code} In Hiveserver2, it will get UserGroupInformation UserGroupInformation#createRemoteUser or UserGroupInformation#createProxyUser. Those methods create new Subject objects so Cache doesn't work. If FileSystem.closeAll or FileSystem#close method are called, FileSystem object will be removed from Cache. > Memory leak: OOM Error after multiple open/closed JDBC connections. > -------------------------------------------------------------------- > > Key: HIVE-5296 > URL: https://issues.apache.org/jira/browse/HIVE-5296 > Project: Hive > Issue Type: Bug > Components: HiveServer2 > Affects Versions: 0.12.0 > Environment: Hive 0.12.0, Hadoop 1.1.2, Debian. > Reporter: Douglas > Labels: hiveserver > Fix For: 0.12.0 > > Original Estimate: 168h > Remaining Estimate: 168h > > This error seems to relate to https://issues.apache.org/jira/browse/HIVE-3481 > However, on inspection of the related patch and my built version of Hive > (patch carried forward to 0.12.0), I am still seeing the described behaviour. > Multiple connections to Hiveserver2, all of which are closed and disposed of > properly show the Java heap size to grow extremely quickly. > This issue can be recreated using the following code > {code} > import java.sql.DriverManager; > import java.sql.Connection; > import java.sql.ResultSet; > import java.sql.SQLException; > import java.sql.Statement; > import java.util.Properties; > import org.apache.hive.service.cli.HiveSQLException; > import org.apache.log4j.Logger; > /* > * Class which encapsulates the lifecycle of a query or statement. > * Provides functionality which allows you to create a connection > */ > public class HiveClient { > > Connection con; > Logger logger; > private static String driverName = "org.apache.hive.jdbc.HiveDriver"; > private String db; > > > public HiveClient(String db) > { > logger = Logger.getLogger(HiveClient.class); > this.db=db; > > try{ > Class.forName(driverName); > }catch(ClassNotFoundException e){ > logger.info("Can't find Hive driver"); > } > > String hiveHost = GlimmerServer.config.getString("hive/host"); > String hivePort = GlimmerServer.config.getString("hive/port"); > String connectionString = "jdbc:hive2://"+hiveHost+":"+hivePort > +"/default"; > logger.info(String.format("Attempting to connect to > %s",connectionString)); > try{ > con = > DriverManager.getConnection(connectionString,"",""); > > }catch(Exception e){ > logger.error("Problem instantiating the > connection"+e.getMessage()); > } > } > > public int update(String query) > { > Integer res = 0; > Statement stmt = null; > try{ > stmt = con.createStatement(); > String switchdb = "USE "+db; > logger.info(switchdb); > stmt.executeUpdate(switchdb); > logger.info(query); > res = stmt.executeUpdate(query); > logger.info("Query passed to server"); > stmt.close(); > }catch(HiveSQLException e){ > logger.info(String.format("HiveSQLException thrown, > this can be valid, " + > "but check the error: %s from the query > %s",query,e.toString())); > }catch(SQLException e){ > logger.error(String.format("Unable to execute query > SQLException %s. Error: %s",query,e)); > }catch(Exception e){ > logger.error(String.format("Unable to execute query %s. > Error: %s",query,e)); > } > > if(stmt!=null) > try{ > stmt.close(); > }catch(SQLException e){ > logger.error("Cannot close the statment, > potentially memory leak "+e); > } > > return res; > } > > public void close() > { > if(con!=null){ > try { > con.close(); > } catch (SQLException e) { > logger.info("Problem closing connection "+e); > } > } > } > > > > } > {code} > And by creating and closing many HiveClient objects. The heap space used by > the hiveserver2 runjar process is seen to increase extremely quickly, without > such space being released. -- This message is automatically generated by JIRA. If you think it was sent incorrectly, please contact your JIRA administrators For more information on JIRA, see: http://www.atlassian.com/software/jira