Performance Analysis and Optimization of Synchronized Reflection Calls in a Java Backend Service

The article investigates a high‑traffic Java backend issue caused by synchronized reflection calls, analyzes thread‑blocking stack traces, demonstrates the problematic code, and presents a compile‑time PropertyDescriptor optimization that eliminates runtime locking, resulting in significant latency improvements and a deeper understanding of JVM lock mechanisms.

Qunar Tech Salon
Qunar Tech Salon
Qunar Tech Salon
Performance Analysis and Optimization of Synchronized Reflection Calls in a Java Backend Service

Background: A Java backend service for a travel platform experienced severe latency spikes during high traffic because a reflection utility used PropertyDescriptor which internally invoked synchronized methods, causing many threads to block.

Problem discovery: Slow queries were observed on both PC and mobile list pages. Using QTrace and jstack samples under load revealed numerous threads in the BLOCKED state while waiting for a monitor inside java.beans.Introspector.getPublicDeclaredMethods. The stack traces pointed to ReflectUtils.invokeGetMethod creating a new PropertyDescriptor for each field.

Root cause analysis: Each call to new PropertyDescriptor(fieldName, clazz) triggers a synchronized block inside the JDK’s introspection code, which becomes a bottleneck when many fields (≈60 per product) are accessed concurrently.

Solution: Move the creation of PropertyDescriptor to compile time, pre‑instantiating a descriptor for each field so the runtime no longer performs the synchronized reflection step. The revised code replaces the dynamic creation with a cached descriptor, eliminating the monitor contention.

Performance results: After the change, a load test on six machines with 200 concurrent users showed fetches per second increasing from ~202 to ~306, and average first‑response time dropping from ~958 ms to ~572 ms, demonstrating a clear latency reduction.

Re‑examining synchronized: The article explains that modern JVMs (since JDK 1.6) use biased locking and lightweight locking to reduce the cost of synchronized. It describes the lock acquisition process, safe points, and how the JVM inflates a lock from biased → lightweight → heavyweight when contention occurs.

JVM lock details: Code snippets from HotSpot’s ObjectSynchronizer::fast_enter and ObjectSynchronizer::slow_enter illustrate how the VM checks for bias, attempts CAS operations, and falls back to lock inflation, providing insight into the underlying mechanisms that caused the original performance issue.

References: The article links to several Chinese blog posts that dive deeper into the implementation of synchronized, JDK source compilation, and lock theory.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

JVMperformanceconcurrencyReflectionsynchronized
Qunar Tech Salon
Written by

Qunar Tech Salon

Qunar Tech Salon is a learning and exchange platform for Qunar engineers and industry peers. We share cutting-edge technology trends and topics, providing a free platform for mid-to-senior technical professionals to exchange and learn.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.