diff --git a/src/main/java/com/zaxxer/hikari/HikariPool.java b/src/main/java/com/zaxxer/hikari/HikariPool.java index 2d6070b4..3b863320 100644 --- a/src/main/java/com/zaxxer/hikari/HikariPool.java +++ b/src/main/java/com/zaxxer/hikari/HikariPool.java @@ -80,15 +80,15 @@ public final class HikariPool implements HikariPoolMBean try { - Class clazz = ClassLoaderUtils.loadClass(configuration.getDataSourceClassName()); - this.dataSource = (DataSource) clazz.newInstance(); - PropertyBeanSetter.setTargetFromProperties(dataSource, configuration.getDataSourceProperties()); - delegationProxies = !AgentRegistrationElf.loadTransformerAgent(configuration.getDataSourceClassName()); if (delegationProxies) { LOGGER.info("Falling back to Javassist delegate-based proxies."); } + + Class clazz = ClassLoaderUtils.loadClass(configuration.getDataSourceClassName()); + this.dataSource = (DataSource) clazz.newInstance(); + PropertyBeanSetter.setTargetFromProperties(dataSource, configuration.getDataSourceProperties()); } catch (Exception e) { diff --git a/src/main/java/com/zaxxer/hikari/javassist/AgentRegistrationElf.java b/src/main/java/com/zaxxer/hikari/javassist/AgentRegistrationElf.java index 979f20d7..5fb2688b 100644 --- a/src/main/java/com/zaxxer/hikari/javassist/AgentRegistrationElf.java +++ b/src/main/java/com/zaxxer/hikari/javassist/AgentRegistrationElf.java @@ -50,7 +50,6 @@ public class AgentRegistrationElf { Properties systemProperties = System.getProperties(); - systemProperties.put("com.zaxxer.hikari.classloader", AgentRegistrationElf.class.getClassLoader()); HikariClassTransformer transformer = new HikariClassTransformer(); systemProperties.put("com.zaxxer.hikari.transformer", transformer); @@ -59,19 +58,20 @@ public class AgentRegistrationElf LOGGER.info("Successfully loaded instrumentation agent. Scanning classes..."); HikariClassScanner scanner = new HikariClassScanner(transformer); - scanner.scanClasses(dsClassName); - - return true; + return scanner.scanClasses(dsClassName); } catch (Exception e) { LOGGER.warn("Instrumentation agent could not be loaded. Please report at http://github.com/brettwooldridge/HikariCP.", e); return false; } -// finally -// { -// unregisterInstrumenation(); -// } + finally + { + if (HikariInstrumentationAgent.unregisterInstrumenation()) + { + LOGGER.info("Unloaded instrumentation agent."); + } + } } /** diff --git a/src/main/java/com/zaxxer/hikari/javassist/HikariClassScanner.java b/src/main/java/com/zaxxer/hikari/javassist/HikariClassScanner.java index f2f76e0d..f1f8c216 100644 --- a/src/main/java/com/zaxxer/hikari/javassist/HikariClassScanner.java +++ b/src/main/java/com/zaxxer/hikari/javassist/HikariClassScanner.java @@ -17,25 +17,11 @@ package com.zaxxer.hikari.javassist; import java.io.BufferedReader; -import java.io.DataInputStream; -import java.io.File; -import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; -import java.net.URI; -import java.net.URL; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Enumeration; -import java.util.HashMap; import java.util.HashSet; -import java.util.LinkedHashMap; import java.util.Properties; -import java.util.jar.JarEntry; -import java.util.jar.JarFile; - -import javassist.bytecode.ClassFile; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -50,29 +36,12 @@ public class HikariClassScanner { private static final Logger LOGGER = LoggerFactory.getLogger(HikariClassScanner.class); - private static final LinkedHashMap completionMap; - private final HashMap instrumentableClasses; - - // Static initializer - static - { - completionMap = new LinkedHashMap<>(); - completionMap.put("java.sql.Connection", false); - completionMap.put("java.sql.ResultSet", false); - completionMap.put("java.sql.CallableStatement", false); - completionMap.put("java.sql.PreparedStatement", false); - completionMap.put("java.sql.Statement", false); - } - private HikariClassTransformer transformer; - private String sniffPackage; - private Properties codex; public HikariClassScanner(HikariClassTransformer transformer) { - instrumentableClasses = new HashMap<>(); this.transformer = transformer; } @@ -93,7 +62,7 @@ public class HikariClassScanner HashSet hash = (HashSet) codex.get(dsClassName); if (hash == null) { - LOGGER.warn("DataSource {} not found in instrumentation codex. Please report at http://github.com/brettwooldridge/HikariCP.", dsClassName); + LOGGER.warn("DataSource {} not found in the instrumentation codex. Please report at http://github.com/brettwooldridge/HikariCP.", dsClassName); LOGGER.info("Using delegation instead of instrumentation"); return false; } diff --git a/src/main/java/com/zaxxer/hikari/javassist/HikariClassTransformer.java b/src/main/java/com/zaxxer/hikari/javassist/HikariClassTransformer.java index 38c7c498..eae331d6 100644 --- a/src/main/java/com/zaxxer/hikari/javassist/HikariClassTransformer.java +++ b/src/main/java/com/zaxxer/hikari/javassist/HikariClassTransformer.java @@ -172,9 +172,9 @@ public class HikariClassTransformer implements ClassFileTransformer copyFields(proxy, target); copyMethods(proxy, target, classFile); - for (CtConstructor constructor : target.getConstructors()) + for (CtConstructor constructor : target.getDeclaredConstructors()) { - constructor.insertAfter("__init();"); + constructor.insertBeforeBody("__init();"); } mergeClassInitializers(proxy, target, classFile); @@ -197,7 +197,7 @@ public class HikariClassTransformer implements ClassFileTransformer for (CtConstructor constructor : target.getDeclaredConstructors()) { - constructor.insertAfter("__init();"); + constructor.insertBeforeBody("__init();"); } return target.toBytecode(); @@ -261,7 +261,6 @@ public class HikariClassTransformer implements ClassFileTransformer private void copyMethods(CtClass srcClass, CtClass targetClass, ClassFile targetClassFile) throws Exception { - CtMethod[] destMethods = targetClass.getMethods(); ConstPool constPool = targetClassFile.getConstPool(); for (CtMethod method : srcClass.getDeclaredMethods()) @@ -271,20 +270,6 @@ public class HikariClassTransformer implements ClassFileTransformer continue; } - if (targetClassFile.getMethod(method.getName()) != null) // maybe we have a name collision - { - String signature = method.getSignature(); - for (CtMethod destMethod : destMethods) - { - if (destMethod.getName().equals(method.getName()) && destMethod.getSignature().equals(signature)) - { - LOGGER.debug("Rename method {}.{} to __{}", targetClass.getSimpleName(), destMethod.getName(), destMethod.getName()); - destMethod.setName("__" + destMethod.getName()); - break; - } - } - } - CtMethod copy = CtNewMethod.copy(method, targetClass, null); AnnotationsAttribute attr = new AnnotationsAttribute(constPool, AnnotationsAttribute.visibleTag); Annotation annotation = new Annotation("com.zaxxer.hikari.javassist.HikariInject", constPool); diff --git a/src/main/java/com/zaxxer/hikari/javassist/HikariInstrumentationAgent.java b/src/main/java/com/zaxxer/hikari/javassist/HikariInstrumentationAgent.java index 03b5c7e5..43409e30 100644 --- a/src/main/java/com/zaxxer/hikari/javassist/HikariInstrumentationAgent.java +++ b/src/main/java/com/zaxxer/hikari/javassist/HikariInstrumentationAgent.java @@ -26,8 +26,6 @@ import java.util.Properties; */ public class HikariInstrumentationAgent { - private static Instrumentation ourInstrumentation; - /** * The method that is called when VirtualMachine.loadAgent() is invoked to register our * class transformer. @@ -37,11 +35,29 @@ public class HikariInstrumentationAgent */ public static void agentmain(String agentArgs, Instrumentation instrumentation) { - ourInstrumentation = instrumentation; - Properties systemProperties = System.getProperties(); + systemProperties.put("com.zaxxer.hikari.instrumentation", instrumentation); + ClassFileTransformer transformer = (ClassFileTransformer) systemProperties.get("com.zaxxer.hikari.transformer"); + instrumentation.addTransformer(transformer, false); + } + + static boolean unregisterInstrumenation() + { + boolean unregistered = false; + + Properties systemProperties = System.getProperties(); + Instrumentation instrumentation = (Instrumentation) systemProperties.get("com.zaxxer.hikari.instrumentation"); + if (instrumentation != null) + { + ClassFileTransformer transformer = (ClassFileTransformer) systemProperties.get("com.zaxxer.hikari.transformer"); + instrumentation.removeTransformer(transformer); + unregistered = true; + } + + systemProperties.remove("com.zaxxer.hikari.instrumentation"); + systemProperties.remove("com.zaxxer.hikari.transformer"); - ourInstrumentation.addTransformer(transformer, false); + return unregistered; } } diff --git a/src/main/java/com/zaxxer/hikari/proxy/ConnectionProxy.java b/src/main/java/com/zaxxer/hikari/proxy/ConnectionProxy.java index e8532158..72a6c306 100644 --- a/src/main/java/com/zaxxer/hikari/proxy/ConnectionProxy.java +++ b/src/main/java/com/zaxxer/hikari/proxy/ConnectionProxy.java @@ -58,8 +58,6 @@ public class ConnectionProxy implements IHikariConnectionProxy @HikariInject protected ArrayList _openStatements; @HikariInject protected HikariPool _parentPool; - protected final Connection delegate; - @HikariInject protected volatile boolean _forceClose; @HikariInject protected long _creationTime; @HikariInject protected long _lastAccess; @@ -67,6 +65,8 @@ public class ConnectionProxy implements IHikariConnectionProxy @HikariInject protected StackTraceElement[] _stackTrace; @HikariInject protected TimerTask _leakTask; + protected final Connection delegate; + // static initializer static { @@ -158,8 +158,11 @@ public class ConnectionProxy implements IHikariConnectionProxy @HikariInject protected void __init() { - _openStatements = new ArrayList(64); - _creationTime = _lastAccess = System.currentTimeMillis(); + if (_openStatements == null) + { + _openStatements = new ArrayList(64); + _creationTime = _lastAccess = System.currentTimeMillis(); + } } @HikariInject @@ -194,8 +197,9 @@ public class ConnectionProxy implements IHikariConnectionProxy try { - // Faster than an iterator - for (int i = _openStatements.size() - 1; i >= 0; i--) + // Faster than an iterator most times + final int length = _openStatements.size(); + for (int i = 0; i < length; i++) { _openStatements.get(i).close(); } diff --git a/src/main/resources/META-INF/codex.properties b/src/main/resources/META-INF/codex.properties index 48283ea9..71783f75 100644 --- a/src/main/resources/META-INF/codex.properties +++ b/src/main/resources/META-INF/codex.properties @@ -84,5 +84,19 @@ mysql.subResultSet=com.mysql.jdbc.JDBC4ResultSet mysql.subResultSet=com.mysql.jdbc.UpdatableResultSet mysql.subResultSet=com.mysql.jdbc.JDBC4UpdatableResultSet -# ------ Driver v0.0.0 ---------------------------------------------------------- +# ------ HikariCP Testing v0.0.0 ---------------------------------------------------------- # +com.zaxxer.hikari.mocks.StubDataSource=hikari + +hikari.baseConnection=com.zaxxer.hikari.mocks.StubBaseConnection +hikari.subConnection=com.zaxxer.hikari.mocks.StubConnection +hikari.baseStatement=com.zaxxer.hikari.mocks.StubStatement +hikari.subPreparedStatement=com.zaxxer.hikari.mocks.StubPreparedStatement +hikari.baseResultSet=com.zaxxer.hikari.mocks.StubResultSet + +com.zaxxer.hikari.performance.StubDataSource=hikari-perf + +hikari-perf.baseConnection=com.zaxxer.hikari.performance.StubConnection +hikari-perf.baseStatement=com.zaxxer.hikari.performance.StubStatement +hikari-perf.subPreparedStatement=com.zaxxer.hikari.performance.StubPreparedStatement +hikari-perf.baseResultSet=com.zaxxer.hikari.performance.StubResultSet diff --git a/src/test/java/com/zaxxer/hikari/mocks/StubResultSet.java b/src/test/java/com/zaxxer/hikari/mocks/StubResultSet.java index 0e5525c8..4cb05695 100644 --- a/src/test/java/com/zaxxer/hikari/mocks/StubResultSet.java +++ b/src/test/java/com/zaxxer/hikari/mocks/StubResultSet.java @@ -63,7 +63,7 @@ public class StubResultSet implements ResultSet /** {@inheritDoc} */ public boolean next() throws SQLException { - return (counter < 10); + return (counter > 100000); } /** {@inheritDoc} */ diff --git a/src/test/java/com/zaxxer/hikari/performance/Benchmark1.java b/src/test/java/com/zaxxer/hikari/performance/Benchmark1.java index 390d857e..dff04a05 100644 --- a/src/test/java/com/zaxxer/hikari/performance/Benchmark1.java +++ b/src/test/java/com/zaxxer/hikari/performance/Benchmark1.java @@ -76,12 +76,10 @@ public class Benchmark1 System.out.println(" Warming up JIT"); benchmarks.startMixedBench(100, 10000); System.out.println(" MixedBench Final Timing Runs"); - long elapsed = 0; - elapsed += benchmarks.startMixedBench(THREADS, 1000); - elapsed += benchmarks.startMixedBench(THREADS, 1000); - elapsed += benchmarks.startMixedBench(THREADS, 1000); - elapsed += benchmarks.startMixedBench(THREADS, 1000); - System.out.printf("Elapsed time for timing runs (excluding thread start): %dms\n", TimeUnit.NANOSECONDS.toMillis(elapsed)); + benchmarks.startMixedBench(THREADS, 1000); + benchmarks.startMixedBench(THREADS, 1000); + benchmarks.startMixedBench(THREADS, 1000); + benchmarks.startMixedBench(THREADS, 1000); System.out.println("\nBoneBench"); System.out.println(" Warming up JIT"); @@ -168,7 +166,7 @@ public class Benchmark1 config.setConnectionTimeout(8000); config.setIdleTimeout(TimeUnit.MINUTES.toMillis(30)); config.setJdbc4ConnectionTest(true); - config.setDataSourceClassName("com.zaxxer.hikari.mocks.StubDataSource"); + config.setDataSourceClassName("com.zaxxer.hikari.performance.StubDataSource"); HikariDataSource ds = new HikariDataSource(config); return ds; @@ -178,7 +176,7 @@ public class Benchmark1 { try { - Class.forName("com.zaxxer.hikari.mocks.StubDriver"); + Class.forName("com.zaxxer.hikari.performance.StubDriver"); } catch (ClassNotFoundException e) { @@ -205,7 +203,7 @@ public class Benchmark1 private DataSource setupDbPool() { DBPoolDataSource ds = new DBPoolDataSource(); - ds.setDriverClassName("com.zaxxer.hikari.mocks.StubDriver"); + ds.setDriverClassName("com.zaxxer.hikari.performance.StubDriver"); ds.setUrl("jdbc:stub"); ds.setMinPool(POOL_MAX / 2); ds.setMaxPool(POOL_MAX); @@ -222,7 +220,7 @@ public class Benchmark1 try { ComboPooledDataSource cpds = new ComboPooledDataSource(); - cpds.setDriverClass( "com.zaxxer.hikari.mocks.StubDriver" ); + cpds.setDriverClass( "com.zaxxer.hikari.performance.StubDriver" ); cpds.setJdbcUrl( "jdbc:stub" ); cpds.setMinPoolSize(POOL_MAX / 2); cpds.setMaxPoolSize(POOL_MAX); diff --git a/src/test/java/com/zaxxer/hikari/performance/StubResultSet.java b/src/test/java/com/zaxxer/hikari/performance/StubResultSet.java index 8f726189..12860d6d 100644 --- a/src/test/java/com/zaxxer/hikari/performance/StubResultSet.java +++ b/src/test/java/com/zaxxer/hikari/performance/StubResultSet.java @@ -117,7 +117,7 @@ public class StubResultSet implements ResultSet /** {@inheritDoc} */ public float getFloat(int columnIndex) throws SQLException { - throw new SQLException("No reason", "08999"); + return 0; } /** {@inheritDoc} */ diff --git a/src/test/java/com/zaxxer/hikari/performance/StubStatement.java b/src/test/java/com/zaxxer/hikari/performance/StubStatement.java index fd9db13b..c2063bc2 100644 --- a/src/test/java/com/zaxxer/hikari/performance/StubStatement.java +++ b/src/test/java/com/zaxxer/hikari/performance/StubStatement.java @@ -45,8 +45,7 @@ public class StubStatement implements Statement /** {@inheritDoc} */ public ResultSet executeQuery(String sql) throws SQLException { - StubResultSet resultSet = new StubResultSet(); - return resultSet; + return new StubResultSet(); } /** {@inheritDoc} */