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.

Qunar Tech Salon
Qunar Tech Salon
Qunar Tech Salon
Resolving Java 8 Upgrade Issues: Spring 4.0 Pitfalls and Metaspace Problems

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.

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.

BackendJVMperformancespringjava8Metaspace
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.