feat: implement Java tracer agent for function profiling and ranking#1648
feat: implement Java tracer agent for function profiling and ranking#1648aseembits93 wants to merge 6 commits intoomni-javafrom
Conversation
Add a Java agent using ASM bytecode instrumentation that profiles method calls during test execution. The agent records call counts, timing data, caller-callee relationships, and serialized arguments to SQLite — matching the Python tracer's schema so ProfileStats and FunctionRanker work unchanged. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Use rsplit instead of split when parsing dotted function names so that "com.testapp.Calculator.fibonacci" correctly extracts class_name="Calculator" and base_function_name="fibonacci" instead of class_name="com". Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
PR Review SummaryPrek Checks
Code Review2 inline comments posted:
Other observations (not blocking):
Test Coverage
* Coverage notes:
Optimization PRs
Last updated: 2026-02-24T16:37:00Z |
| public void reset() { | ||
| timings.clear(); | ||
| functionCallCount.clear(); | ||
| capturedArgs.clear(); | ||
| globalStartNs.set(0); | ||
| globalEndNs.set(0); | ||
| } |
There was a problem hiding this comment.
Bug: reset() doesn't clear the onStack and callStack ThreadLocals. After reset(), any method keys still in the thread-local onStack set will persist, causing incorrect recursion detection on subsequent uses. Similarly, stale frames on callStack will remain.
This matters for tests (where reset() is called in @BeforeEach) and for any scenario where the tracker is reused after reset.
| public void reset() { | |
| timings.clear(); | |
| functionCallCount.clear(); | |
| capturedArgs.clear(); | |
| globalStartNs.set(0); | |
| globalEndNs.set(0); | |
| } | |
| public void reset() { | |
| timings.clear(); | |
| functionCallCount.clear(); | |
| capturedArgs.clear(); | |
| globalStartNs.set(0); | |
| globalEndNs.set(0); | |
| callStack.get().clear(); | |
| onStack.get().clear(); | |
| } |
| optimizer.run_with_args(full_args) | ||
| return ArgumentParser() # Return dummy parser since we're done | ||
| return ArgumentParser() | ||
| except (IndexError, OSError, Exception): |
There was a problem hiding this comment.
Exception is a superclass of both IndexError and OSError, so this is equivalent to except Exception. Catching all exceptions silently can hide real bugs (e.g., import errors, broken module initialization). Consider narrowing to just the expected failures:
| except (IndexError, OSError, Exception): | |
| except (IndexError, OSError, ImportError, ValueError): |
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Summary
com.codeflash.agent.*) using ASM bytecode instrumentation that profiles method calls during test execution, recording call counts, timing, caller-callee relationships, and serialized arguments to SQLiteProfileStatsandFunctionRankerwork unchanged for ranking Java functions by addressable timeJavaTracerPython class that attaches the agent via-javaagentin Maven Surefire's argLine, and integrates with the existing tracer/optimizer pipelineNew Java files (6 source + 4 test)
CodeflashAgent.javapremain()entry point — parses args, registers transformer, shutdown hookCodeflashTransformer.javaClassFileTransformer— instruments methods withenter()/exit()callsCallTracker.javaMethodKey.java(filename, lineno, funcname, classname)MethodStats.javaPstatsWriter.javapstats,function_calls,metadata,total_timetablesModified files
pom.xmlPremain-Class/Can-Retransform-Classesmanifest attrscodeflash/tracer.pyJavaTracerinstead of directly to optimizercodeflash/optimization/optimizer.pyargs.trace_filewhen discovery returns no trace pathcodeflash/languages/java/tracer.pyJavaTracerclass for running Maven tests with the agentTest plan
Premain-Class,Can-Retransform-Classes)codeflash --file SomeJavaFile.javaon a real Java project and verify agent attaches, trace SQLite produced, functions ranked🤖 Generated with Claude Code