[hibernate-dev] A framework JDBC code change suggestion...
Hi all. In debugging a JDBC-related issue with hibernate and WebLogic I found a file: org.springframework.jdbc.datasource.DriverManagerDataSource. There is a part of this file that hurts JDBC concurrency in multithreaded applications like WebLogic, and I have a solution. I would like to suggest a better alternative that would probably be named DriverDataSource. The problem is that *all* java.sql.DriverManager calls are class-synchronized. This include getConnection() and some very simple methods like DriverManager.println() which every driver may be calling continually at runtime (whether or not there is a DriverManager log stream). The constructor for SQLException calls this method. This means that one slow call to DriverManager.getConnection() can temporarily block all other JDBC in the whole JVM. In some cases we have even seen deadlocks where one thread that holds the DriverManager lock calls another thread that wants to do JDBC. The solution is to remove all calls to DriverManager.getConnection() and replace them with a simple call to Driver.connect(). In fact, this is what the DriverManager itself does, except that for every getConnection() call, the DriverManager goes through it's list of every registered driver in the JVM, trying each one with your URL and properties until it finds one that doesn't throw an exception and returns a connection. I decompiled and altered the DriverManagerDataSource to do that, for a customer to try, and I have attached it to this email as a suggestion for your consideration. HTH, Joe Weinstein at BEA Systems___ Notice: This email message, together with any attachments, may contain information of BEA Systems, Inc., its subsidiaries and affiliated entities, that may be confidential, proprietary, copyrighted and/or legally privileged, and is intended solely for the use of the individual or entity named in this message. If you are not the intended recipient, and have received this message in error, please immediately return this by email and then delete it. // Decompiled by Jad v1.5.8e2. Copyright 2001 Pavel Kouznetsov. // Jad home page: http://kpdus.tripod.com/jad.html // Decompiler options: packimports(3) // Source File Name: DriverManagerDataSource.java package org.springframework.jdbc.datasource; import java.sql.*; import java.util.Properties; import org.apache.commons.logging.Log; import org.springframework.jdbc.CannotGetJdbcConnectionException; import org.springframework.util.ClassUtils; import org.springframework.util.StringUtils; // Referenced classes of package org.springframework.jdbc.datasource: //AbstractDataSource public class DriverManagerDataSource extends AbstractDataSource { public DriverManagerDataSource() { } public DriverManagerDataSource(String driverClassName, String url, String username, String password) throws CannotGetJdbcConnectionException { setDriverClassName(driverClassName); setUrl(url); setUsername(username); setPassword(password); } public DriverManagerDataSource(String url, String username, String password) throws CannotGetJdbcConnectionException { setUrl(url); setUsername(username); setPassword(password); } public DriverManagerDataSource(String url) throws CannotGetJdbcConnectionException { setUrl(url); } public void setDriverClassName(String driverClassName) throws CannotGetJdbcConnectionException { if(!StringUtils.hasText(driverClassName)) throw new IllegalArgumentException(driverClassName must not be empty); this.driverClassName = driverClassName; try { d = (Driver)ClassUtils.forName(this.driverClassName).newInstance(); } catch(ClassNotFoundException ex) { throw new CannotGetJdbcConnectionException(Could not load JDBC driver class [ + this.driverClassName + ], ex); } catch(Exception ex2) { throw new CannotGetJdbcConnectionException(Could not load JDBC driver class [ + this.driverClassName + ], new SQLException(ex2.getMessage()) ); } if(logger.isInfoEnabled()) logger.info(Loaded JDBC driver: + this.driverClassName); } public String getDriverClassName() { return driverClassName; } public void setUrl(String url) { if(!StringUtils.hasText(url)) { throw new IllegalArgumentException(url must not be empty); } else { this.url = url; return; } } public String getUrl() { return url; } public void setUsername(String username) { this.username = username; } public String getUsername() { return username; } public void setPassword(String password)
Re: [hibernate-dev] A framework JDBC code change suggestion...
At 01:05 PM 12/13/2006, Max Rydahl Andersen wrote: Hi Joseph, It would probably be more relevant to report this to Spring since the code you are referring to is not within Hibernate. p.s. first time i've seen someone having to decompile opensource classes to fix things ;) Thanks, I'm just flying by the seat of the pants, never looked for the source. This must be clear how quick-and-dirty because I chose the wrong dev group to talk to... thanks Joe /max Hi all. In debugging a JDBC-related issue with hibernate and WebLogic I found a file: org.springframework.jdbc.datasource.DriverManagerDataSource. There is a part of this file that hurts JDBC concurrency in multithreaded applications like WebLogic, and I have a solution. I would like to suggest a better alternative that would probably be named DriverDataSource. The problem is that *all* java.sql.DriverManager calls are class-synchronized. This include getConnection() and some very simple methods like DriverManager.println() which every driver may be calling continually at runtime (whether or not there is a DriverManager log stream). The constructor for SQLException calls this method. This means that one slow call to DriverManager.getConnection() can temporarily block all other JDBC in the whole JVM. In some cases we have even seen deadlocks where one thread that holds the DriverManager lock calls another thread that wants to do JDBC. The solution is to remove all calls to DriverManager.getConnection() and replace them with a simple call to Driver.connect(). In fact, this is what the DriverManager itself does, except that for every getConnection() call, the DriverManager goes through it's list of every registered driver in the JVM, trying each one with your URL and properties until it finds one that doesn't throw an exception and returns a connection. I decompiled and altered the DriverManagerDataSource to do that, for a customer to try, and I have attached it to this email as a suggestion for your consideration. HTH, Joe Weinstein at BEA Systems___ Notice: This email message, together with any attachments, may contain information of BEA Systems, Inc., its subsidiaries and affiliated entities, that may be confidential, proprietary, copyrighted and/or legally privileged, and is intended solely for the use of the individual or entity named in this message. If you are not the intended recipient, and have received this message in error, please immediately return this by email and then delete it. -- -- Max Rydahl Andersen callto://max.rydahl.andersen Hibernate [EMAIL PROTECTED] http://hibernate.org JBoss a division of Red Hat [EMAIL PROTECTED] ___ Notice: This email message, together with any attachments, may contain information of BEA Systems, Inc., its subsidiaries and affiliated entities, that may be confidential, proprietary, copyrighted and/or legally privileged, and is intended solely for the use of the individual or entity named in this message. If you are not the intended recipient, and have received this message in error, please immediately return this by email and then delete it. ___ hibernate-dev mailing list hibernate-dev@lists.jboss.org https://lists.jboss.org/mailman/listinfo/hibernate-dev