Description
Driver version
7.0.0
SQL Server version
Microsoft SQL Server 2016 (SP2) (KB4052908) - 13.0.5026.0 (X64)
Mar 18 2018 09:11:49
Copyright (c) Microsoft Corporation
Standard Edition (64-bit) on Windows Server 2016 Standard 10.0 <X64> (Build 14393: ) (Hypervisor)
Client Operating System
Windows 10
JAVA/JVM version
java version "1.8.0_181"
Java(TM) SE Runtime Environment (build 1.8.0_181-b13)
Java HotSpot(TM) 64-Bit Server VM (build 25.181-b13, mixed mode)
Problem description
-
Expected behaviour: All threads should be stopped when shutting down the application in Tomcat
-
Actual behaviour: One thread is still running after shutdown and produces a possible memory leak
-
Error message/stack trace:
WARNING: The web application [test] appears to have started a thread named [Thread-3] but has failed to stop it. This is very likely to create a memory leak. Stack trace of thread: sun.net.dns.ResolverConfigurationImpl.notifyAddrChange0(Native Method) sun.net.dns.ResolverConfigurationImpl$AddressChangeListener.run(ResolverConfigurationImpl.java:144)
-
I debugged the web application and found out that the thread is started in a static initialization block in
sun.net.dns.ResolverConfigurationImpl
(see stack trace below):static { AccessController.doPrivileged(new PrivilegedAction() { public Void run() { System.loadLibrary("net"); return null; } }); init0(); ResolverConfigurationImpl.AddressChangeListener var0 = new ResolverConfigurationImpl.AddressChangeListener(); var0.setDaemon(true); var0.start(); }
Daemon Thread [localhost-startStop-2] (Class load: ResolverConfigurationImpl) owns: Object (id=91) owns: Object (id=92) owns: EntityManagerFactoryDelegate (id=93) owns: ApplicationContextListener (id=94) owns: StandardContext (id=95) ResolverConfiguration.open() line: 56 [local variables unavailable] DnsContextFactory.serversForUrls(DnsUrl[]) line: 149 DnsContextFactory.getContext(String, DnsUrl[], Hashtable<?,?>) line: 81 dnsURLContext.getRootURLContext(String, Hashtable<?,?>) line: 71 dnsURLContext(GenericURLDirContext).getAttributes(String, String[]) line: 100 KrbServiceLocator.lambda$getKerberosService$1(Context, String) line: 168 1747531283.run() line: not available AccessController.doPrivileged(PrivilegedExceptionAction<T>, AccessControlContext) line: not available [native method] AccessController.doPrivileged(PrivilegedExceptionAction<T>, AccessControlContext, Permission...) line: 713 KrbServiceLocator.getKerberosService(String, String) line: 166 Config.getKDCFromDNS(String) line: 1171 Config.getKDCList(String) line: 1057 NativeMethodAccessorImpl.invoke0(Method, Object, Object[]) line: not available [native method] NativeMethodAccessorImpl.invoke(Object, Object[]) line: 62 DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: 43 Method.invoke(Object, Object...) line: 498 KerbAuthentication$2.isRealmValid(String) line: 301 KerbAuthentication.getRealmValidator(String) line: 312 KerbAuthentication.enrichSpnWithRealm(String, boolean) line: 254 KerbAuthentication.<init>(SQLServerConnection, String, int) line: 231 SQLServerConnection.logon(SQLServerConnection$LogonCommand) line: 3557 SQLServerConnection.access$000(SQLServerConnection, SQLServerConnection$LogonCommand) line: 81 SQLServerConnection$LogonCommand.doExecute() line: 3541 SQLServerConnection$LogonCommand(TDSCommand).execute(TDSWriter, TDSReader) line: 7240 SQLServerConnection.executeCommand(TDSCommand) line: 2869 SQLServerConnection.connectHelper(ServerPortPlaceHolder, int, int, boolean, boolean, boolean, int) line: 2395 SQLServerConnection.login(String, String, int, String, FailoverInfo, int, long) line: 2042 SQLServerConnection.connectInternal(Properties, SQLServerPooledConnection) line: 1889 SQLServerConnection.connect(Properties, SQLServerPooledConnection) line: 1120 SQLServerDriver.connect(String, Properties) line: 700 DriverManager.getConnection(String, Properties, Class<?>) line: 664 DriverManager.getConnection(String, Properties) line: 208 DefaultConnector.connect(Properties, Session) line: 98 DatabaseLogin(DatasourceLogin).connectToDatasource(Accessor, Session) line: 162 ServerSession(DatabaseSessionImpl).setOrDetectDatasource(boolean) line: 207 ServerSession(DatabaseSessionImpl).loginAndDetectDatasource() line: 760 EntityManagerFactoryProvider.login(DatabaseSessionImpl, Map, boolean) line: 265 EntityManagerSetupImpl.deploy(ClassLoader, Map) line: 731 EntityManagerFactoryDelegate.getAbstractSession() line: 205 EntityManagerFactoryDelegate.createEntityManagerImpl(Map, SynchronizationType) line: 305 EntityManagerFactoryImpl.createEntityManagerImpl(Map, SynchronizationType) line: 337 EntityManagerFactoryImpl.createEntityManager() line: 303 ApplicationContextListener.createEntityManager() line: 229 [...]
The thread itself is started by a Java core class but my question is if we can prevent the thread from starting in the first place (stopping it correctly seems to be out of the question as there is no reference available).
I think others using Kerberos for authentication (with username/password) should experience this problem, too. It would be nice to know if this is a general problem or if I'm doing something wrong.
Currently the code is embedded in a bigger web application (with JPA and others) but I'll try to strip it down to a minimal example if necessary.