Chapter 1: Introduction to JVMTI
- 1.1 Real-World Use Cases
- 1.2 Evolution: JVMPI, JVMDI → JVMTI
- 1.3 JVMTI vs Other Tooling Interfaces
- 1.4 Requirements and Environment Setup
- 1.5 What You’ll Learn in This Book
Chapter 2: Anatomy of a JVMTI Agent
- 2.1 What is a JVMTI Agent?
- 2.2 Lifecycle Entry Points
- 2.3 Minimum Viable Agent
- 2.4 Compiling with CMake
- 2.5 Running the Agent with Java
- 2.6 Troubleshooting Tips
- 2.7 Optional: Logging with stderr or a file
- 2.8 What’s Next?
Chapter 3: Capabilities and Events in JVMTI
- 3.1 Understanding JVMTI Capabilities
- 3.2 Registering Event Callbacks
- 3.3 Commonly Used Events
- 3.4 Best Practices for Event Handling
- 3.5 Example: Counting Method Entries
- 3.6 Troubleshooting
- 3.7 What’s Next?
Chapter 4: Inspecting Threads, Stacks, and Methods
- 4.1 Enumerating All Threads
- 4.2 Walking the Stack of a Thread
- 4.3 Retrieving Method Details
- 4.4 Inspecting Local Variables
- 4.5 Example: Print Stack Trace for All Threads
- 4.6 Best Practices
- 4.7 What’s Next?
Chapter 5: Heap Inspection and Object Tagging
- 5.1 Iterating Over Heap Objects
- 5.2 Object Tagging
- 5.3 Finding Instances of a Class
- 5.4 Heap Summary and Statistics
- 5.5 Monitoring Object Allocations (Optional)
- 5.6 Example: Count Instances by Class
- 5.7 Best Practices
- 5.8 What’s Next?
Chapter 6: Class Transformation and Bytecode Instrumentation
- 6.1 The Class File Load Hook
- 6.2 Using ASM for Bytecode Instrumentation
- 6.3 Retransformation
- 6.4 Filtering Classes
- 6.5 Safety Tips and Pitfalls
- 6.6 Example: Insert Logging in All Methods
- 6.7 What’s Next?
Chapter 7: Event Notification and Callback Handling
- 7.1 How Event Notification Works
- 7.2 Commonly Used Events
- 7.3 Writing Event Handlers
- 7.4 Conditional Event Registration
- 7.5 Working with Threads in Callbacks
- 7.6 Use Case Examples
- 7.7 Event Chaining with Other Tools
- 7.8 What’s Next?
Chapter 8: Interacting with the JVM Runtime
- 8.1 Querying JVM Capabilities
- 8.2 Working with System Properties
- 8.3 Interacting with Threads
- 8.4 Memory Information and GC Control
- 8.5 Managing Native Memory
- 8.6 Advanced: Environment Manipulation
- 8.7 Best Practices
- 8.8 What’s Next?
Chapter 9: Stack Traces and Heap Walking
- 9.1 Capturing Stack Traces
- 9.2 Object Tagging and Metadata
- 9.3 Walking the Heap
- 9.4 Heap Analysis Use Cases
- 9.5 Safely Walking the Heap
- 9.6 Integration Tip: Combining Stack + Heap
- 9.7 Best Practices
- 9.8 What’s Next?
Chapter 10: Handling Exceptions and Debugging
- 10.1 Introduction to Exception Handling in the JVM
- 10.2 Exception Callback Events
- 10.3 Stack Trace Capture on Exceptions
- 10.4 Instrumenting Try-Catch Blocks
- 10.5 Exception Suppression or Transformation
- 10.6 Integration Tips
- 10.7 Architecture Summary
- 10.8 Real-World Relevance
- 10.9 Summary and Next Steps
Chapter 11: Building a Minimal Profiler
- 11.1 Profiling Approaches: Sampling vs Instrumentation
- 11.2 Method Entry/Exit and Stack Trace Sampling
- 11.3 Aggregating and Presenting Performance Data
- 11.4 Timers and Signal Handling
- 11.5 Open-Source Profiler Architecture
- 11.6 Summary and Next Steps
Chapter 12: Advanced Topics
- 12.1 Retransforming Classes
- 12.2 Bytecode Verification and Redefinition
- 12.3 Agent Reentrancy and Performance Trade-offs
- 12.4 Thread-Local Storage and Thread Safety
- 12.5 Native Memory Management (Allocation Tracking)
- 12.6 Architecture Summary
- 12.7 Real-World Relevance
- 12.8 Summary and Next Steps
Chapter 13: Deploying and Testing JVMTI Agents
- 13.1 Agent Packaging and Versioning
- 13.2 Debug vs Release Builds
- 13.3 Logging and Error Handling
- 13.4 Using Attach API on Remote JVMs
- 13.5 Monitoring Agent Impact
- 13.6 Architecture Summary
- 13.7 Real-World Relevance
- 13.8 Summary and Next Steps
Chapter 14: Security and Stability Considerations
- 14.1 Crash Handling and Signal Safety
- 14.2 Thread Safety and Reentrancy
- 14.3 Sandbox and Permissions
- 14.4 JVMTI and Containerization
- 14.5 JVM Compatibility Across Vendors and Versions
- 14.6 Architecture Summary
- 14.7 Real-World Relevance
- 14.8 Summary and Next Steps
Chapter 15: Case Study: Building a Real-World Agent
- 15.1 Full Project Structure
- 15.2 Design Decisions
- 15.3 Integrating with Other Tools
- 15.4 Performance and Memory Impact Tuning
- 15.5 CI/CD for Native Agents
- 15.6 Architecture Summary
- 15.7 Real-World Relevance
- 15.8 Summary and Next Steps
Appendix A: Full JVMTI Capabilities Table
Appendix B: JVMTI Error Codes Cheat Sheet
Appendix C: Reference to Open-Source Tools using JVMTI
- Open-Source Tools
- Commercial Tools (JVMTI-based)
- How to Learn from These Tools
Appendix D: Setting Up Debugging for Crashes in Native Code
- 1. Enable Core Dumps
- 2. Build with Debug Symbols
- 3. Use Native Debuggers
- 4. Analyze JVM Crash Logs
- 5. Attach Debugger to Running JVM
- Tips
- Example: GDB Session
Appendix E: Compatibility Matrix (JVM Versions and JVMTI Capabilities)
- How to Check Capabilities at Runtime
- Additional Resources
Appendix F: Java Native Interface (JNI)
- JNI Types and Handles
- Accessing Java Classes, Methods, and Fields
- Working with Strings and Arrays
- Exception Handling
- Creating and Managing References
- Registering Native Methods
- Common JNI Function Signatures
- Best Practices and Gotchas
- Additional Resources