How to Check JVM Keystore Locations
In Java applications, understanding which keystore the JVM is using is crucial for troubleshooting SSL/TLS issues, debugging certificate problems, or ensuring our applications use the correct keys and certificates. The JVM typically relies on a keystore to manage cryptographic keys and certificates, but depending on configuration, it might not always be obvious which keystore is being used. This article examines multiple approaches to determine the keystore our JVM is utilising.
1. Checking Default Keystore Locations
When no specific keystore is set via system properties, the JVM automatically falls back to its default locations. By default, the truststore is located at $JAVA_HOME/lib/security/cacerts.
We can manually verify this path by examining our Java installation directory, which allows us to confirm the presence of the cacerts file and ensure the JVM will use it for SSL/TLS certificate validation.
echo $JAVA_HOME ls $JAVA_HOME/lib/security/
This lists security-related files and keystores in the JVM’s directory. The typical output may vary depending on the JDK distribution and version, but generally, we can expect to see files such as cacerts, and other security-related files within the $JAVA_HOME/lib/security/ directory.
blocked.certs default.policy cacerts public_suffix_list.dat
2. Inspecting the Keystore Programmatically
One way to determine which keystore the JVM is using is by checking system properties. The JVM exposes properties, such as javax.net.ssl.trustStore, which indicates the path to the truststore used for validating certificates. By reading these properties at runtime, we can programmatically identify the default keystore, any custom truststore, and the user-specific keystore location.
public class KeystoreLocator {
private static final Logger logger = Logger.getLogger(KeystoreLocator.class.getName());
public static void main(String[] args) {
// Java installation directory
String javaHomeDir = System.getProperty("java.home");
String fileSeparator = System.getProperty("file.separator");
if (javaHomeDir == null) {
logger.severe("Java home directory is not defined!");
return;
}
// Default JVM truststore path
String defaultTruststorePath = javaHomeDir + fileSeparator + "lib" + fileSeparator
+ "security" + fileSeparator + "cacerts";
logger.log(Level.INFO, "Java Home Directory: {0}", javaHomeDir);
logger.log(Level.INFO, "Default JVM truststore expected at: {0}", defaultTruststorePath);
File defaultTruststoreFile = new File(defaultTruststorePath);
if (defaultTruststoreFile.exists()) {
logger.info("Default JVM truststore found.");
logger.log(Level.INFO, "Absolute path: {0}", defaultTruststoreFile.getAbsolutePath());
} else {
logger.warning("Default JVM truststore not found at the expected location.");
}
// Check for a custom truststore specified via system property
String truststoreProperty = System.getProperty("javax.net.ssl.trustStore");
String trustStorePath;
if (truststoreProperty != null) {
logger.log(Level.INFO, "Custom truststore detected at: {0}", truststoreProperty);
trustStorePath = truststoreProperty;
} else {
logger.info("No custom truststore specified; JVM will use the default.");
trustStorePath = defaultTruststorePath;
}
// User-specific keystore
String userHomeDir = System.getProperty("user.home");
if (userHomeDir == null) {
logger.severe("User home directory is not defined!");
return;
}
String userKeystorePath = userHomeDir + fileSeparator + ".keystore";
logger.log(Level.INFO, "User keystore path: {0}", userKeystorePath);
File userKeystoreFile = new File(userKeystorePath);
if (userKeystoreFile.exists()) {
logger.info("User keystore detected.");
logger.log(Level.INFO, "Absolute path: {0}", userKeystoreFile.getAbsolutePath());
} else {
logger.log(Level.INFO, "No user keystore found at the default location.");
}
// Inspecting the keystore programmatically
try {
// Default algorithm for key managers
String keystoreAlgorithm = KeyManagerFactory.getDefaultAlgorithm();
logger.log(Level.INFO, "Keystore algorithm: {0}", keystoreAlgorithm);
// Load the keystore
KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
try (FileInputStream fis = new FileInputStream(trustStorePath)) {
// Default password for cacerts is "changeit" unless modified
ks.load(fis, "changeit".toCharArray());
}
logger.log(Level.INFO, "Keystore type: {0}", ks.getType());
logger.log(Level.INFO, "Keystore entry count: {0}", ks.size());
} catch (Exception e) {
logger.log(Level.SEVERE, "Error loading keystore: {0}", e.getMessage());
e.printStackTrace();
}
}
}
This program examines the JVM system properties and common keystore locations, including the default JVM truststore (cacerts in $JAVA_HOME/lib/security), any custom truststore specified via javax.net.ssl.trustStore, and the user-specific keystore ($HOME/.keystore). By running it, we can quickly identify which keystores are present and determine which one the JVM will use for certificate validation.
3. Using JVM Arguments
We can explicitly instruct the JVM to use a specific keystore using these arguments.
-Djavax.net.ssl.trustStore=/path/to/truststore -Djavax.net.ssl.trustStorePassword=yourpassword
Adding these arguments at JVM startup ensures the application uses the intended keystore.
4. Conclusion
In this article, we discussed how to determine which keystore the Java JVM is using, covering the default truststore, any custom truststores, and user-specific keystores. We also demonstrated how to verify these keystore locations both manually and programmatically, providing a clear approach to managing and inspecting the JVM’s certificate stores.
This article walks through how to identify the keystore currently in use by the Java JVM.

