{"record":{"id":"eddfbf56e63c6a97","repo":"alibaba/druid","slug":"classname","errorCode":null,"errorMessage":"{className}","messagePattern":"\\{className\\}","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"core/src/main/java/com/alibaba/druid/pool/DruidAbstractDataSource.java","lineNumber":343,"sourceCode":"        return keepConnectionUnderlyingTransactionIsolation;\n    }\n\n    public void setKeepConnectionUnderlyingTransactionIsolation(boolean keepConnectionUnderlyingTransactionIsolation) {\n        this.keepConnectionUnderlyingTransactionIsolation = keepConnectionUnderlyingTransactionIsolation;\n    }\n\n    public DruidDataSourceStatLogger getStatLogger() {\n        return statLogger;\n    }\n\n    public void setStatLoggerClassName(String className) {\n        Class<?> clazz;\n        try {\n            clazz = Class.forName(className);\n            DruidDataSourceStatLogger statLogger = (DruidDataSourceStatLogger) clazz.newInstance();\n            this.setStatLogger(statLogger);\n        } catch (Exception e) {\n            throw new IllegalArgumentException(className, e);\n        }\n    }\n\n    public void setStatLogger(DruidDataSourceStatLogger statLogger) {\n        this.statLogger = statLogger;\n    }\n\n    public long getTimeBetweenLogStatsMillis() {\n        return timeBetweenLogStatsMillis;\n    }\n\n    public void setTimeBetweenLogStatsMillis(long timeBetweenLogStatsMillis) {\n        this.timeBetweenLogStatsMillis = timeBetweenLogStatsMillis;\n    }\n\n    public boolean isOracle() {\n        return isOracle;\n    }","sourceCodeStart":325,"sourceCodeEnd":361,"githubUrl":"https://github.com/alibaba/druid/blob/fa8dc9912637a2f729eef9f55356621fec18d40e/core/src/main/java/com/alibaba/druid/pool/DruidAbstractDataSource.java#L325-L361","documentation":"DruidAbstractDataSource.setStatLoggerClassName reflectively loads, instantiates, and casts a class to DruidDataSourceStatLogger. Any failure (ClassNotFoundException, InstantiationException, IllegalAccessException, ClassCastException, or a constructor-thrown exception) is wrapped as IllegalArgumentException(className, e) - note the message is just the class name and the real cause is in the exception's cause.","triggerScenarios":"Calling setStatLoggerClassName(\"foo.Bar\") where Bar is not on the classpath, is abstract/inaccessible, does not implement DruidDataSourceStatLogger, or its constructor throws.","commonSituations":"Typo in the stat logger class name; the logger class lives in a JAR not on the datasource's classloader; providing a class that implements a different Druid version's DruidDataSourceStatLogger interface.","solutions":["Confirm the class is on the classpath and implements com.alibaba.druid.stat.DruidDataSourceStatLogger.","Ensure a public no-arg constructor exists and the class is concrete/public.","Prefer setStatLogger(new MyStatLogger()) to get a compile-time type check instead of reflective loading.","Read IllegalArgumentException.getCause() to identify ClassNotFoundException vs ClassCastException vs InstantiationException."],"exampleFix":"// before\n// ds.setStatLoggerClassName(\"com.example.MyStatLogger\"); // reflective, runtime-only\n\n// after\n// ds.setStatLogger(new com.example.MyStatLogger()); // compile-time checked","handlingStrategy":"type-guard","validationCode":"Class<?> c = Class.forName(className);\nif (!com.alibaba.druid.stat.DruidDataSourceStatLogger.class.isAssignableFrom(c))\n    throw new IllegalStateException(className + \" is not a DruidDataSourceStatLogger\");\ncom.alibaba.druid.stat.DruidDataSourceStatLogger probe =\n    (com.alibaba.druid.stat.DruidDataSourceStatLogger) c.newInstance();","typeGuard":"static boolean isValidStatLoggerClass(String name) {\n    try {\n        Class<?> c = Class.forName(name);\n        return com.alibaba.druid.stat.DruidDataSourceStatLogger.class.isAssignableFrom(c)\n            && !java.lang.reflect.Modifier.isAbstract(c.getModifiers());\n    } catch (Throwable t) { return false; }\n}","tryCatchPattern":"try {\n    ds.setStatLoggerClassName(className);\n} catch (IllegalArgumentException e) {\n    // e.getMessage() == className; e.getCause() tells you which: CNFE/CCE/IE/IAE\n    // prefer ds.setStatLogger(new MyStatLogger()) instead\n    throw e;\n}","preventionTips":["Prefer setStatLogger(instance) over setStatLoggerClassName for compile-time safety.","Unit-test reflective instantiation of any custom stat logger.","Keep the stat logger class on the same classloader as the datasource."],"tags":["datasource","stat-logger","reflection","configuration"],"backgroundTag":null,"analyzedSha":"fa8dc9912637a2f729eef9f55356621fec18d40e","analyzedAt":"2026-08-14T04:55:06.789Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}