Guava ImmutableMap中getProperty()引发ExceptionInInitializerError问题排查
Problem Context
I have this utility class:
public final class EnvironmentUriAndAuth { public static final String ENVIRONMENT = getProperty("environment_type"); private static final ImmutableMap<EnvironmentConstants, String> AUTH_HEADER = ImmutableMap.of( DEV, getProperty("devTestAuth"), TEST, getProperty("devTestAuth"), PRELIVE, getProperty("preliveAuth")); // Private constructor omitted public static String getAuthHeader() { return AUTH_HEADER.get(EnvironmentConstants.valueOf(ENVIRONMENT)); } }
When calling getAuthHeader() from another class, a java.lang.ExceptionInInitializerError is thrown exactly at the line where ImmutableMap is initialized. I suspect it's related to the initialization order of getProperty() calls, but I can't figure out the correct sequence. Is this error caused by initialization issues, or something else?
Yes, This Is Definitely a Static Initialization Issue
The ExceptionInInitializerError directly signals a failure during the static initialization phase of your EnvironmentUriAndAuth class. Here's the breakdown of what's happening:
JVM initializes static variables in the exact order they're declared in the class. For your code:
- First,
ENVIRONMENTis initialized by callinggetProperty("environment_type") - Next,
AUTH_HEADERis built by callinggetProperty()three times to populate the map values
If any of these getProperty calls throws an uncaught runtime exception (like missing configuration, invalid property sources, or null values that break downstream logic), or if the EnvironmentConstants enum itself has initialization problems (e.g., missing the DEV/TEST/PRELIVE constants), the static initialization fails, and the JVM throws ExceptionInInitializerError.
How to Fix & Debug This
Here are actionable steps to resolve the issue:
Audit Your
getPropertyImplementation- If
getPropertythrows an exception when a property is missing (instead of returning a default value), that's likely the culprit. Update it to handle missing keys gracefully:private static String getProperty(String key) { // Replace with your actual config read logic String value = System.getProperty(key); // Return a safe default instead of throwing return value != null ? value : "DEFAULT_AUTH_TOKEN"; }
- If
Validate the
EnvironmentConstantsEnum- Double-check that
DEV,TEST, andPRELIVEare valid constants in theEnvironmentConstantsenum. Missing or misnamed constants will throw an error when referenced duringImmutableMapinitialization. - Ensure the enum itself doesn't have static initialization logic that could fail (e.g., a constructor that calls external services).
- Double-check that
Use Static Blocks for Explicit Initialization Control
- Replace inline static variable initialization with a static block to gain full control over the sequence, and add validation steps to catch issues early:
public final class EnvironmentUriAndAuth { public static final String ENVIRONMENT; private static final ImmutableMap<EnvironmentConstants, String> AUTH_HEADER; static { try { // Initialize ENVIRONMENT first ENVIRONMENT = getProperty("environment_type"); // Validate ENVIRONMENT is a valid enum value upfront if (ENVIRONMENT == null) { throw new IllegalArgumentException("environment_type property is missing"); } EnvironmentConstants.valueOf(ENVIRONMENT); // Throws if invalid // Build the auth header map AUTH_HEADER = ImmutableMap.of( EnvironmentConstants.DEV, getProperty("devTestAuth"), EnvironmentConstants.TEST, getProperty("devTestAuth"), EnvironmentConstants.PRELIVE, getProperty("preliveAuth") ); } catch (Exception e) { // Print detailed stack trace to pinpoint the failure e.printStackTrace(); throw new ExceptionInInitializerError("Failed to initialize EnvironmentUriAndAuth: " + e.getMessage()); } } // Private constructor to prevent instantiation private EnvironmentUriAndAuth() {} public static String getAuthHeader() { return AUTH_HEADER.get(EnvironmentConstants.valueOf(ENVIRONMENT)); } } - This approach makes the initialization order explicit and catches invalid
environment_typevalues before they cause further issues.
- Replace inline static variable initialization with a static block to gain full control over the sequence, and add validation steps to catch issues early:
Debug the Exact Cause
- The try-catch block in the static block will print the full stack trace, showing you exactly which
getPropertycall or enum reference is failing.
- The try-catch block in the static block will print the full stack trace, showing you exactly which
内容的提问来源于stack exchange,提问作者Vitali Plagov

