Resolving Java 8 Upgrade Issues: Spring 4.0 Pitfalls and Metaspace Problems
This article details the challenges encountered when upgrading a production environment from Java 7 to Java 8, including Spring 4.0 compatibility issues, JVM crashes, GC and JIT tuning, and Metaspace memory management, and provides concrete solutions and best‑practice recommendations.
1 Background
Java 8 has been officially released for over two years and offers many performance improvements such as G1 GC, enhanced JIT, tiered compilation, and the elimination of the classic java.lang.OutOfMemoryError: PermGen space. However, the main reason for the upgrade in our case was a JVM crash bug (see JDK bug 8021898 ) that was fixed after JDK 1.7.0_60. We attempted to upgrade directly to Java 8, but encountered serious problems that are described below, focusing on Spring 4.0 pitfalls and the new Metaspace issue.
2 Spring 4.0 Issues
2.1 Introduction
After fixing the JVM crash bug by upgrading the JDK, we performed regression testing in a test environment without any issues and proceeded to roll out the upgrade to production.
2.2 Symptoms
Initial low‑traffic machines restarted without incident, but when we upgraded higher‑QPS machines, the load gradually increased, followed by a large number of request time‑outs, as shown in the following diagram:
2.3 Investigation Process
2.3.1 Stack Trace Analysis
We captured several Tomcat stack logs and observed many threads blocked on locks:
Further inspection showed threads stuck in Spring code paths, even though the Spring version itself had not been upgraded.
2.3.2 GC Investigation
GC activity was slightly more frequent than before but no full GCs were triggered, so GC was not the root cause.
2.3.3 JIT Investigation
We examined JIT settings. Increasing the JIT cache size only delayed the load increase. Adjusting the number of JIT compilation threads had mixed results and ultimately did not solve the problem.
2.3.4 Spring Investigation
We found a Spring bug reported in JDK 1.7.0_51 related to SerializableTypeWrapper causing performance degradation (see SPR-11335 ). Our environment used JDK 1.7.0_45, so the issue was not present before the upgrade.
2.4 Solution
Upgrading Spring to version 4.0.3 or later resolves the issue, as Spring added significant improvements for Java 8.
2.5 Problem Analysis
2.5.1 ResolvableType
The ResolvableType class caches results without proper validation, leading to heavy lock contention when many threads concurrently access the cache.
2.5.2 ConcurrentReferenceHashMap Issue
This soft‑cache implementation acquires locks during expiration, causing additional thread blocking, increased GC pressure, and eventual cache eviction under high QPS workloads.
2.6 Spring Fixes
2.6.1 ResolvableType
The fix adds a pre‑check before cache retrieval to verify validity and evict expired entries, reducing lock contention.
2.6.2 SerializableTypeWrapper
The equals method is now bypassed for the original implementation, avoiding the costly proxy chain and improving performance for high‑frequency calls.
3 Metaspace Issues
3.1 Introduction
After a few days of stable operation on Java 8, we received alerts about swap usage and service crashes.
3.2 Symptoms
Late‑night alerts indicated that the online service was swapping or being killed.
3.3 Investigation
The root cause was identified as the new Metaspace implementation in Java 8.
3.4 Concepts
3.4.1 PermGen
PermGen (Permanent Generation) stored class metadata and could cause OutOfMemoryError: PermGen space when many classes were loaded.
3.4.2 Metaspace
Java 8 replaces PermGen with Metaspace, which uses native memory. Old JVM flags -XX:PermSize and -XX:MaxPermSize are ignored.
3.5 Metaspace Capacity
By default, Metaspace grows until it exhausts native memory. The -XX:MaxMetaspaceSize flag can limit its size.
3.6 Root Cause Analysis
Without explicit -XX:MetaspaceSize and -XX:MaxMetaspaceSize settings, Metaspace can expand unchecked, consuming all system memory, triggering swap and eventual process termination.
4 Summary
When upgrading to Java 8, keep the following two points in mind:
Use Spring 4.0.3 or newer.
Configure Metaspace size appropriately.
With these precautions, the Java 8 upgrade should proceed smoothly.
If you are planning a Java 8 upgrade, this article should help you avoid two common pitfalls.
Future articles may explore why ResolvableType.equals performance degrades on Java 8.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
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.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
