I have a java webapp and want to introduce kotlin 2.3.0. I migrated my servlets into kotlin, project compiles but during runtime I get this error. The webserver is running tomcat 9 and JDK 17
java.lang.ClassNotFoundException: kotlin.collections.ArraysKt___ArraysKt
Complete stack trace.
Dec 22, 2025 7:11:43 AM org.apache.catalina.core.StandardWrapperValve invoke
SEVERE: Servlet.service() for servlet [plotDataServlet] in context with path [/pqm] threw exception [Servlet execution threw an exception] with root cause
java.lang.ClassNotFoundException: kotlin.collections.ArraysKt___ArraysKt
at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1354)
at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1163)
at java.base/java.lang.ClassLoader.defineClass1(Native Method)
at java.base/java.lang.ClassLoader.defineClass(ClassLoader.java:1027)
at java.base/java.security.SecureClassLoader.defineClass(SecureClassLoader.java:150)
at org.apache.catalina.loader.WebappClassLoaderBase.findClassInternal(WebappClassLoaderBase.java:2342)
at org.apache.catalina.loader.WebappClassLoaderBase.findClassInternal(WebappClassLoaderBase.java:2216)
at com.controlj.green.webserver.impl.CustomWebappClassLoader.findClassInternal(CustomWebappClassLoader.java:129)
at org.apache.catalina.loader.WebappClassLoaderBase.findClass(WebappClassLoaderBase.java:824)
at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1315)
at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1163)
at kotlin.collections.CollectionsKt__CollectionsKt.listOf(Collections.kt:81)
at dev.dev01.addon.pqm.chart.PlotlyJsonBuilderKt.buildPlotlyJson(PlotlyJsonBuilder.kt:76)
at dev.dev01.addon.pqm.servlets.PlotDataServlet.doGet(PlotDataServlet.kt:87)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:529)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:623)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:199)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:144)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:168)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:144)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:168)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:90)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:482)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:130)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:93)
at org.apache.catalina.authenticator.SingleSignOn.invoke(SingleSignOn.java:289)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74)
at com.controlj.green.webserver.impl.StandardHeaderValve.invoke(StandardHeaderValve.java:87)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:346)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:397)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:63)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:935)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1826)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:52)
at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1189)
at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:658)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:63)
at java.base/java.lang.Thread.run(Thread.java:1583)
This error is thrown because I’m using listof(“test1”,”test2”, “test3”)" which is part of the standard library but not sure why it throws this error works fine with listof(“test”)
I’ve verified that the kotlin stdlib is packaged in the final war file and I added some diagnostic lines in the servlet. The tomcat server doesn’t have any kotlin libs that would conflict.
here’s my servlet. so the servlet has these println() statements and on initial load of the servlet but it crashes and throws no class def error when it gets to buildPlotlyJson() where I have a function with listof() method called.
....
val threadCl = Thread.currentThread().contextClassLoader
val servletCl = this::class.java.classLoader
println("CLIDS: threadCl=${System.identityHashCode(threadCl)} servletCl=${System.identityHashCode(servletCl)}")
println("Context classloader: $threadCl")
println("Servlet classloader: $servletCl")
// resource lookup
val resourcePath = "kotlin/collections/ArraysKt___ArraysKt.class"
println("getResource(thread): ${threadCl.getResource(resourcePath)}")
println("getResource(servlet): ${servletCl.getResource(resourcePath)}")
// check physical file on disk (exploded path)
val libPath = "C:/WC/programdata/webserver_base/work/TomcatEngine/root/pqm/webapp/WEB-INF/lib"
java.io.File(libPath).listFiles()?.forEach {
println("LIB FILE: ${it.name} size=${it.length()} modified=${java.util.Date(it.lastModified())}")
}
// Error thrown inside buildPlotlyJson() function which has listOf(0,1)
val plotlyJson: String = buildPlotlyJson(analogChannelDtos, digitalChannelDtos)
....
Here’s the output, on initial load printed to the console.
Inside doGet
Context classloader: AddOnClassLoader
context: pqm
delegate: false
----------> Parent Classloader:
jdk.internal.loader.ClassLoaders$AppClassLoader@70dea4e
Servlet classloader: AddOnClassLoader
context: pqm
delegate: false
----------> Parent Classloader:
jdk.internal.loader.ClassLoaders$AppClassLoader@70dea4e
getResource(thread): jar:file:/C:/WC/programdata/webserver_base/work/TomcatEngine/root/pqm/webapp/WEB-INF/lib/kotlin-stdlib-2.3.0.jar!/kotlin/collections/ArraysKt___ArraysKt.class
getResource(servlet): jar:file:/C:/WC/programdata/webserver_base/work/TomcatEngine/root/pqm/webapp/WEB-INF/lib/kotlin-stdlib-2.3.0.jar!/kotlin/collections/ArraysKt___ArraysKt.class
LIB FILE: annotations-13.0.jar size=17536 modified=Mon Dec 22 07:11:35 PST 2025
LIB FILE: error_prone_annotations-2.41.0.jar size=20389 modified=Mon Dec 22 07:11:35 PST 2025
LIB FILE: gson-2.13.2.jar size=289901 modified=Mon Dec 22 07:11:35 PST 2025
LIB FILE: htmx.org-2.0.8.jar size=233384 modified=Mon Dec 22 07:11:35 PST 2025
LIB FILE: jstl-1.2.jar size=414240 modified=Mon Dec 22 07:11:35 PST 2025
LIB FILE: kotlin-stdlib-2.3.0.jar size=1796996 modified=Mon Dec 22 07:11:35 PST 2025
LIB FILE: kotlin-stdlib-jdk7-2.3.0.jar size=946 modified=Mon Dec 22 07:11:35 PST 2025
LIB FILE: kotlin-stdlib-jdk8-2.3.0.jar size=952 modified=Mon Dec 22 07:11:35 PST 2025
LIB FILE: picocss__pico-2.1.1.jar size=2891622 modified=Mon Dec 22 07:11:35 PST 2025
LIB FILE: plotly.js-dist-min-3.0.1.jar size=1416657 modified=Mon Dec 22 07:11:35 PST 2025
LIB FILE: pqm-0.0.1.jar size=1093157 modified=Mon Dec 22 07:11:35 PST 2025
but then when I resend adoGet() request the same servlet. and I get null when it tries to find the ArrowsKt class and the stack trace is thrown.
Inside doGet
CLIDS: threadCl=2055081295 servletCl=2055081295
Context classloader: AddOnClassLoader
context: pqm
delegate: false
----------> Parent Classloader:
jdk.internal.loader.ClassLoaders$AppClassLoader@70dea4e
Servlet classloader: AddOnClassLoader
context: pqm
delegate: false
----------> Parent Classloader:
jdk.internal.loader.ClassLoaders$AppClassLoader@70dea4e
getResource(thread): null
getResource(servlet): null
LIB FILE: annotations-13.0.jar size=17536 modified=Mon Dec 22 07:11:35 PST 2025
LIB FILE: error_prone_annotations-2.41.0.jar size=20389 modified=Mon Dec 22 07:11:35 PST 2025
LIB FILE: gson-2.13.2.jar size=289901 modified=Mon Dec 22 07:11:35 PST 2025
LIB FILE: htmx.org-2.0.8.jar size=233384 modified=Mon Dec 22 07:11:35 PST 2025
LIB FILE: jstl-1.2.jar size=414240 modified=Mon Dec 22 07:11:35 PST 2025
LIB FILE: kotlin-stdlib-2.3.0.jar size=1796996 modified=Mon Dec 22 07:11:35 PST 2025
LIB FILE: kotlin-stdlib-jdk7-2.3.0.jar size=946 modified=Mon Dec 22 07:11:35 PST 2025
LIB FILE: kotlin-stdlib-jdk8-2.3.0.jar size=952 modified=Mon Dec 22 07:11:35 PST 2025
LIB FILE: picocss__pico-2.1.1.jar size=2891622 modified=Mon Dec 22 07:11:35 PST 2025
LIB FILE: plotly.js-dist-min-3.0.1.jar size=1416657 modified=Mon Dec 22 07:11:35 PST 2025
LIB FILE: pqm-0.0.1.jar size=1093157 modified=Mon Dec 22 07:11:35 PST 2025
Something happens when listof() is called crashes and burns. what’s weird is I can debug the app and I can use listof(“test”) but I can’t use listof(“test1”,”test2”)
