kamon-io/kanela

org.postgresql.jdbc.PgPreparedStatement Class versions V1_5 or less must use F_NEW frames when using kanela agent

Closed this issue · 3 comments

I'm trying to implement kamon tracing for an akka application written in Scala. The application is backed by a postgres database. and I'm running into issues with asm from what i can tell.

as far as I can tell I'm on the latest possible versions of the relevant libraries while maintaining compatibility but maybe I'm making a mistake somewhere. it seems like the failure is occurring in a transitive dependency on ASM

relevant library versions:
kamon version 2.7.0
kanela-agent: 1.0.18
akka: 2.6.19
jdbc adatpter: net.postgis:postgis-jdbc:2.5.0
doobie 0.13.4
hikariCP 5.0.3
typesafe slick 3.3.2

my code is extremely simply and based on the kamon docs for installing on a plain application calling

import kamon.Kamon

// this is a mixing for my main App

class App extends Init {
// start app
}

trait Init {
Kamon.init()
// start up akka server
// start up grpc server
// ... etc
}

build tool is bazel 5.4.0

If I remove Kamon.init() the application runs perfectly normal.

error stack trace.

[slick.db-1] ERROR 2024-01-18 14:33:00  Logger : Error => org.postgresql.jdbc.PgPreparedStatement with message Class versions V1_5 or less must use F_NEW frames.. Class loader: jdk.internal.loader.ClassLoaders$AppClassLoader@67424e82: java.lang.IllegalArgumentException: Class versions V1_5 or less must use F_NEW frames.
	at kanela.agent.libs.net.bytebuddy.jar.asm.MethodWriter.visitFrame(MethodWriter.java:780)
	at kanela.agent.libs.net.bytebuddy.jar.asm.MethodVisitor.visitFrame(MethodVisitor.java:312)
	at kanela.agent.libs.net.bytebuddy.utility.visitor.ExceptionTableSensitiveMethodVisitor.onVisitFrame(ExceptionTableSensitiveMethodVisitor.java:76)
	at kanela.agent.libs.net.bytebuddy.utility.visitor.ExceptionTableSensitiveMethodVisitor.visitFrame(ExceptionTableSensitiveMethodVisitor.java:63)
	at kanela.agent.libs.net.bytebuddy.jar.asm.MethodVisitor.visitFrame(MethodVisitor.java:312)
	at kanela.agent.libs.net.bytebuddy.utility.visitor.StackAwareMethodVisitor.visitFrame(StackAwareMethodVisitor.java:478)
	at kanela.agent.api.advisor.AdviceExceptionHandler$1.apply(AdviceExceptionHandler.java:72)
	at kanela.agent.libs.net.bytebuddy.asm.Advice$Dispatcher$SuppressionHandler$Suppressing$Bound.onEnd(Advice.java:8014)
	at kanela.agent.libs.net.bytebuddy.asm.Advice$Dispatcher$Inlining$CodeTranslationVisitor.visitEnd(Advice.java:10287)
	at kanela.agent.libs.net.bytebuddy.jar.asm.MethodVisitor.visitEnd(MethodVisitor.java:796)
	at kanela.agent.libs.net.bytebuddy.jar.asm.ClassReader.readMethod(ClassReader.java:1518)
	at kanela.agent.libs.net.bytebuddy.jar.asm.ClassReader.accept(ClassReader.java:744)
	at kanela.agent.libs.net.bytebuddy.jar.asm.ClassReader.accept(ClassReader.java:424)
	at kanela.agent.libs.net.bytebuddy.asm.Advice$Dispatcher$Inlining$Resolved$AdviceMethodInliner.apply(Advice.java:9225)
	at kanela.agent.libs.net.bytebuddy.asm.Advice$AdviceVisitor.onAfterExceptionTable(Advice.java:11514)
	at kanela.agent.libs.net.bytebuddy.utility.visitor.ExceptionTableSensitiveMethodVisitor.considerEndOfExceptionTable(ExceptionTableSensitiveMethodVisitor.java:49)
	at kanela.agent.libs.net.bytebuddy.utility.visitor.ExceptionTableSensitiveMethodVisitor.visitLabel(ExceptionTableSensitiveMethodVisitor.java:81)
	at kanela.agent.libs.net.bytebuddy.jar.asm.MethodVisitor.visitLabel(MethodVisitor.java:501)
	at kanela.agent.libs.net.bytebuddy.utility.visitor.ExceptionTableSensitiveMethodVisitor.onVisitLabel(ExceptionTableSensitiveMethodVisitor.java:92)
	at kanela.agent.libs.net.bytebuddy.utility.visitor.ExceptionTableSensitiveMethodVisitor.visitLabel(ExceptionTableSensitiveMethodVisitor.java:82)
	at kanela.agent.libs.net.bytebuddy.utility.visitor.LineNumberPrependingMethodVisitor.onAfterExceptionTable(LineNumberPrependingMethodVisitor.java:50)
	at kanela.agent.libs.net.bytebuddy.utility.visitor.ExceptionTableSensitiveMethodVisitor.considerEndOfExceptionTable(ExceptionTableSensitiveMethodVisitor.java:49)
	at kanela.agent.libs.net.bytebuddy.utility.visitor.ExceptionTableSensitiveMethodVisitor.visitLabel(ExceptionTableSensitiveMethodVisitor.java:81)
	at kanela.agent.libs.net.bytebuddy.jar.asm.MethodVisitor.visitLabel(MethodVisitor.java:501)
	at kanela.agent.libs.net.bytebuddy.utility.visitor.StackAwareMethodVisitor.visitLabel(StackAwareMethodVisitor.java:411)
	at kanela.agent.libs.net.bytebuddy.asm.Advice$Dispatcher$SuppressionHandler$Suppressing$Bound.onStart(Advice.java:8001)
	at kanela.agent.libs.net.bytebuddy.asm.Advice$Dispatcher$Inlining$CodeTranslationVisitor.visitCode(Advice.java:10204)
	at kanela.agent.libs.net.bytebuddy.jar.asm.MethodVisitor.visitCode(MethodVisitor.java:242)
	at kanela.agent.libs.net.bytebuddy.jar.asm.ClassReader.readMethod(ClassReader.java:1513)
	at kanela.agent.libs.net.bytebuddy.jar.asm.ClassReader.accept(ClassReader.java:744)
	at kanela.agent.libs.net.bytebuddy.jar.asm.ClassReader.accept(ClassReader.java:424)
	at kanela.agent.libs.net.bytebuddy.asm.Advice$Dispatcher$Inlining$Resolved$AdviceMethodInliner.apply(Advice.java:9225)
	at kanela.agent.libs.net.bytebuddy.asm.Advice$AdviceVisitor.onAfterExceptionTable(Advice.java:11514)
	at kanela.agent.libs.net.bytebuddy.utility.visitor.ExceptionTableSensitiveMethodVisitor.considerEndOfExceptionTable(ExceptionTableSensitiveMethodVisitor.java:49)
	at kanela.agent.libs.net.bytebuddy.utility.visitor.ExceptionTableSensitiveMethodVisitor.visitLabel(ExceptionTableSensitiveMethodVisitor.java:81)
	at kanela.agent.libs.net.bytebuddy.jar.asm.Label.accept(Label.java:362)
	at kanela.agent.libs.net.bytebuddy.jar.asm.ClassReader.readCode(ClassReader.java:2058)
	at kanela.agent.libs.net.bytebuddy.jar.asm.ClassReader.readMethod(ClassReader.java:1514)
	at kanela.agent.libs.net.bytebuddy.jar.asm.ClassReader.accept(ClassReader.java:744)
	at kanela.agent.libs.net.bytebuddy.jar.asm.ClassReader.accept(ClassReader.java:424)
	at kanela.agent.libs.net.bytebuddy.dynamic.scaffold.TypeWriter$Default$ForInlining.create(TypeWriter.java:4014)
	at kanela.agent.libs.net.bytebuddy.dynamic.scaffold.TypeWriter$Default.make(TypeWriter.java:2224)
	at kanela.agent.libs.net.bytebuddy.dynamic.DynamicType$Builder$AbstractBase$UsingTypeWriter.make(DynamicType.java:4057)
	at kanela.agent.libs.net.bytebuddy.agent.builder.AgentBuilder$Default$ExecutingTransformer.doTransform(AgentBuilder.java:12225)
	at kanela.agent.libs.net.bytebuddy.agent.builder.AgentBuilder$Default$ExecutingTransformer.transform(AgentBuilder.java:12160)
	at kanela.agent.libs.net.bytebuddy.agent.builder.AgentBuilder$Default$ExecutingTransformer.access$1800(AgentBuilder.java:11869)
	at kanela.agent.libs.net.bytebuddy.agent.builder.AgentBuilder$Default$ExecutingTransformer$Java9CapableVmDispatcher.run(AgentBuilder.java:12647)
	at kanela.agent.libs.net.bytebuddy.agent.builder.AgentBuilder$Default$ExecutingTransformer$Java9CapableVmDispatcher.run(AgentBuilder.java:12579)
	at java.base/java.security.AccessController.doPrivileged(Native Method)
	at kanela.agent.libs.net.bytebuddy.agent.builder.AgentBuilder$Default$ExecutingTransformer.doPrivileged(AgentBuilder.java)
	at kanela.agent.libs.net.bytebuddy.agent.builder.AgentBuilder$Default$ExecutingTransformer.transform(AgentBuilder.java:12103)
	at kanela.agent.libs.net.bytebuddy.agent.builder.AgentBuilder$Default$ExecutingTransformer$ByteBuddy$ModuleSupport.transform(Unknown Source)
	at java.instrument/sun.instrument.TransformerManager.transform(TransformerManager.java:188)
	at java.instrument/sun.instrument.InstrumentationImpl.transform(InstrumentationImpl.java:563)
	at java.base/java.lang.ClassLoader.defineClass1(Native Method)
	at java.base/java.lang.ClassLoader.defineClass(ClassLoader.java:1017)
	at java.base/java.security.SecureClassLoader.defineClass(SecureClassLoader.java:174)
	at java.base/jdk.internal.loader.BuiltinClassLoader.defineClass(BuiltinClassLoader.java:800)
	at java.base/jdk.internal.loader.BuiltinClassLoader.findClassOnClassPathOrNull(BuiltinClassLoader.java:698)
	at java.base/jdk.internal.loader.BuiltinClassLoader.loadClassOrNull(BuiltinClassLoader.java:621)
	at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:579)
	at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178)
	at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522)
	at org.postgresql.jdbc.PgConnection.prepareStatement(PgConnection.java:1240)
	at org.postgresql.jdbc.PgConnection.prepareStatement(PgConnection.java:1605)
	at org.postgresql.jdbc.PgConnection.prepareStatement(PgConnection.java:410)
	at com.zaxxer.hikari.pool.ProxyConnection.prepareStatement(ProxyConnection.java:337)
	at com.zaxxer.hikari.pool.HikariProxyConnection.prepareStatement(HikariProxyConnection.java)
	at slick.jdbc.JdbcBackend$SessionDef.prepareStatement(JdbcBackend.scala:375)
	at slick.jdbc.JdbcBackend$SessionDef.prepareStatement$(JdbcBackend.scala:365)
	at slick.jdbc.JdbcBackend$BaseSession.prepareStatement(JdbcBackend.scala:489)
	at slick.jdbc.StatementInvoker.results(StatementInvoker.scala:33)
	at slick.jdbc.StatementInvoker.iteratorTo(StatementInvoker.scala:22)
	at slick.jdbc.Invoker.foreach(Invoker.scala:47)
	at slick.jdbc.Invoker.foreach$(Invoker.scala:46)
	at slick.jdbc.StatementInvoker.foreach(StatementInvoker.scala:16)
	at slick.jdbc.StreamingInvokerAction.run(StreamingInvokerAction.scala:22)
	at slick.jdbc.StreamingInvokerAction.run$(StreamingInvokerAction.scala:20)
	at slick.jdbc.JdbcActionComponent$QueryActionExtensionMethodsImpl$$anon$2.run(JdbcActionComponent.scala:214)
	at slick.jdbc.JdbcActionComponent$QueryActionExtensionMethodsImpl$$anon$2.run(JdbcActionComponent.scala:214)
	at slick.basic.BasicBackend$DatabaseDef$$anon$3.liftedTree1$1(BasicBackend.scala:276)
	at slick.basic.BasicBackend$DatabaseDef$$anon$3.run(BasicBackend.scala:276)
	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
	at java.base/java.lang.Thread.run(Thread.java:829) 

I am a novice when it comes to the low level realm of JVM bytecode but I noticed that the asm code compiles to byte code major version 49

javap -v -cp ~/kanela-agent-1.0.18.jar kanela.agent.libs.net.bytebuddy.jar.asm.MethodWriter
...
Classfile jar:file:///Users/travis.perdue/Downloads/kanela-agent-1.0.18.jar!/kanela/agent/libs/net/bytebuddy/jar/asm/MethodWriter.class
  Last modified Feb 1, 1980; size 35153 bytes
  MD5 checksum 09a2ccbb914420266563caded17ede51
  Compiled from "MethodWriter.java"
final class kanela.agent.libs.net.bytebuddy.jar.asm.MethodWriter extends kanela.agent.libs.net.bytebuddy.jar.asm.MethodVisitor
  minor version: 0
  major version: 49

the hikariCP code compiles to major version 52 of the bytecode

javap -v -cp ~/HikariCP-5.0.1.jar com.zaxxer.hikari.pool.HikariProxyConnection
Classfile jar:file:///Users/travis.perdue/Downloads/HikariCP-5.0.1.jar!/com/zaxxer/hikari/pool/HikariProxyConnection.class
  Last modified Jan 9, 2022; size 7706 bytes
  MD5 checksum d3ba403b863a2284b165d785193b5821
  Compiled from "HikariProxyConnection.java"
public final class com.zaxxer.hikari.pool.HikariProxyConnection extends com.zaxxer.hikari.pool.ProxyConnection implements java.sql.Wrapper,java.lang.AutoCloseable,java.sql.Connection
  minor version: 0
  major version: 52

Is this a red herring or could there be an issue with the asm code that compiles down to version 49 trying to manipulate version 52 byecode cause this sort of error?

I am going to close this as I discovered the source of the problem. I'll post the answer here as an artifact in case anyone else runs into the problem.

The org I was working with labeled the base docker image as jdk_slim but it was actually a jre image. The kanela agent requires access to JVM modules that are only present in the full JDK (note that I haven't tested this with the slim JDK). The module in question for this error was jdk.attach. This dependency is found in the java docs on the byte-buddy install() method. When I switched the base image to the full jdk the errors went away.

https://javadoc.io/static/net.bytebuddy/byte-buddy-agent/1.14.5/net/bytebuddy/agent/ByteBuddyAgent.html#install--