当Spring Boot应用从Java 17升级到Java 25时,会抛出异常java.lang.NoClassDefFoundError: sun/security/action/GetPropertyAction
我有一个基于Java 17的应用程序,使用IIOP CORBA协议来监听JMS消息连接并对其进行后续处理。
从Java 17升级到Java25之后,我得到如下错误,提示 “Exception java.lang.NoClassDefFoundError: sun/security/action/GetPropertyAction”。
我不想将系统降级到Java 21或更低版本,我希望系统继续使用Java 25。
我想监听来自仅支持IIOP CORBA协议的服务器的JMS消息/事件。现在在Java 25中,如何实现?我听说IBM在 Java 25中移除了这项支持。
import java.util.Properties;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.ReentrantLock;
import javax.jms.*;
import javax.naming.Context;
import javax.naming.InitialContext;
import com.ibm.ws.sib.api.jms.impl.JmsObjectMessageImpl;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import com.aa.oss.dd.access.notification.Event;
@Component
public class NasdaNotificationListener
implements MessageListener
{
private static final Logger LOGGER = LogManager.getLogger( NasdaNotificationListener.class );
private static final int MAX_RECONNECT_BACKOFF_MS = 60000; // 1 minute max backoff
private static final int INITIAL_RECONNECT_DELAY_MS = 2000; // 2 seconds initial delay
private final ReentrantLock lock = new ReentrantLock();
@Value( "${java-naming-provider-url}" )
private String javaNamingProviderUrl;
private TopicConnection connection = null;
private TopicSession subSession = null;
private TopicSubscriber subscriber = null;
private volatile boolean isConnected = false;
private final AtomicInteger consecutiveFailures = new AtomicInteger( 0 );
public void startConnection()
{
lock.lock();
try
{
// If already connected, skip
if( isConnected )
{
LOGGER.info( "NotificationListener already connected, skipping startConnection" );
return;
}
String methodName = "startConnection";
LOGGER.info( NWConstants.SE_NAME + " " + methodName + " Trust store: " + System.getProperty(
"javax.net.ssl.trustStore" ) );
LOGGER.info( NWConstants.SE_NAME + " " + methodName + " Key store: " + System.getProperty(
"javax.net.ssl.keyStore" ) );
Properties properties = new Properties();
properties.put( Context.INITIAL_CONTEXT_FACTORY,
NWConstants.NASDA_INITIAL_CONTEXT_FACTORY );
properties.put( Context.PROVIDER_URL, javaNamingProviderUrl );
InitialContext jndi = new InitialContext( properties );
LOGGER.info( NWConstants.SE_NAME + " " + methodName + " got initial context" );
TopicConnectionFactory conFactory = (TopicConnectionFactory)jndi.lookup(
NWConstants.NASDA_TCF_NAME );
connection = conFactory.createTopicConnection();
LOGGER.info( NWConstants.SE_NAME + " " + methodName + " creating sub session" );
subSession = connection.createTopicSession( false, Session.AUTO_ACKNOWLEDGE );
LOGGER.info( NWConstants.SE_NAME + " " + methodName + " creating topic" );
// Look up a JMS topic
Topic nasdaTopic = (Topic)jndi.lookup( NWConstants.NASDA_TOPIC_NAME );
LOGGER.info( NWConstants.SE_NAME + " " + methodName + " creating subscriber" );
subscriber = subSession.createSubscriber( nasdaTopic );
LOGGER.info( NWConstants.SE_NAME + " " + methodName + " creating message listener" );
// Set a JMS message listener
subscriber.setMessageListener( this );
LOGGER.info( NWConstants.SE_NAME + " " + methodName + " starting consumer" );
// Start the JMS connection; allows messages to be delivered
connection.start();
isConnected = true;
consecutiveFailures.set( 0 ); // Reset backoff counter on success
Message msg = new JmsObjectMessageImpl(
new Event( NWConstants.NASDA_EVENT_CLIENT_START, null ) );
msg.setJMSMessageID( NWConstants.NASDA_START_NOTIFICATION_MESSAGE_ID );
NotificationQueue.getInstance().offerMessage( msg );
connection.setExceptionListener( jmsexception -> {
LOGGER.warn( NWConstants.SE_NAME + " connection exception handler: " + jmsexception.getMessage(),
jmsexception );
silentStopConnection();
} );
LOGGER.info( "NasdaNotificationListener startConnection end" );
}
catch( Exception e )
{
isConnected = false;
int failures = consecutiveFailures.incrementAndGet();
LOGGER.error( NWConstants.SE_NAME + " Starting connection failed (attempt {}): {}",
failures, e.getMessage(), e );
// Clean up partially created resources to avoid resource leaks
silentStopConnection();
}
finally
{
lock.unlock();
}
}
public final void stopConnection()
{
lock.lock();
try
{
silentClose( subscriber, "subscriber" );
subscriber = null;
silentClose( subSession, "subSession" );
subSession = null;
if( connection != null )
{
try
{
connection.close();
LOGGER.info( NWConstants.SE_NAME + " Closed connection" );
}
catch( Exception e )
{
LOGGER.debug( "Error closing JMS connection (may already be closed): {}", e.getMessage() );
}
connection = null;
}
try
{
Message msg = new JmsObjectMessageImpl(
new Event( NWConstants.NASDA_EVENT_CLIENT_STOP, null ) );
msg.setJMSMessageID( NWConstants.NASDA_STOP_NOTIFICATION_MESSAGE_ID );
NotificationQueue.getInstance().offerMessage( msg );
}
catch( Exception e )
{
LOGGER.debug( "Error sending stop notification message: {}", e.getMessage() );
}
}
finally
{
isConnected = false;
lock.unlock();
}
}
/**
* Stop connection silently without acquiring lock (used from exception listener
* which may be called while lock is not held by this thread).
*/
private void silentStopConnection()
{
try
{
silentClose( subscriber, "subscriber" );
subscriber = null;
silentClose( subSession, "subSession" );
subSession = null;
if( connection != null )
{
try
{
connection.close();
}
catch( Exception ignored )
{
// Already broken
}
connection = null;
}
}
catch( Exception e )
{
LOGGER.debug( "Error during silent stop: {}", e.getMessage() );
}
finally
{
isConnected = false;
}
}
/**
* Safely close a JMS resource, ignoring any exceptions.
*/
private void silentClose( AutoCloseable resource, String name )
{
if( resource != null )
{
try
{
if( resource instanceof TopicSubscriber )
{
( (TopicSubscriber)resource ).setMessageListener( null );
}
resource.close();
}
catch( Exception e )
{
LOGGER.debug( "Error closing {} (may already be closed): {}", name, e.getMessage() );
}
}
}
@Override
public final void onMessage( Message msg )
{
try
{
LOGGER.debug( NWConstants.SE_NAME + " Recieved message from topic: " + msg );
}
catch( Exception e )
{
LOGGER.error( NWConstants.SE_NAME + "Invalid notifiaction from Nasda.", e );
}
}
}
并出现如下错误:
Failed to initialize the ORB
javax.naming.NamingException: Failed to initialize the ORB
at com.ibm.ws.naming.util.Helpers.getOrb(Helpers.java:517)
at com.ibm.ws.naming.util.WsnInitCtxFactory.getInitialContextInternal(WsnInitCtxFactory.java:478)
at com.ibm.ws.naming.util.WsnInitCtx.getContext(WsnInitCtx.java:128)
at com.ibm.ws.naming.util.WsnInitCtx.getContextIfNull(WsnInitCtx.java:765)
at com.ibm.ws.naming.util.WsnInitCtx.lookup(WsnInitCtx.java:164)
at com.ibm.ws.naming.util.WsnInitCtx.lookup(WsnInitCtx.java:179)
at java.naming/javax.naming.InitialContext.lookup(InitialContext.java:409)
at com.nokia.oss.mediation.ne3sws.nasda.NasdaNotificationListener.startConnection(NasdaNotificationListener.java:62)
at com.nokia.oss.mediation.ne3sws.NE3SWSApplicationRunner.run(NE3SWSApplicationRunner.java:59)
at org.springframework.boot.SpringApplication.lambda$callRunner$0(SpringApplication.java:788)
at org.springframework.util.function.ThrowingConsumer$1.acceptWithException(ThrowingConsumer.java:82)
at org.springframework.util.function.ThrowingConsumer.accept(ThrowingConsumer.java:60)
at org.springframework.util.function.ThrowingConsumer$1.accept(ThrowingConsumer.java:86)
at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:800)
at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:788)
at org.springframework.boot.SpringApplication.lambda$callRunners$0(SpringApplication.java:776)
at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:186)
at java.base/java.util.stream.SortedOps$SizedRefSortingSink.end(SortedOps.java:357)
at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:571)
at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:560)
at java.base/java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:153)
at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:176)
at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:265)
at java.base/java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:632)
at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:776)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:328)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1365)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1354)
at com.nokia.oss.mediation.ne3sws.NE3SWSMediationApp.main(NE3SWSMediationApp.java:36)
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:104)
at java.base/java.lang.reflect.Method.invoke(Method.java:565)
at org.springframework.boot.loader.launch.Launcher.launch(Launcher.java:106)
at org.springframework.boot.loader.launch.Launcher.launch(Launcher.java:64)
at org.springframework.boot.loader.launch.JarLauncher.main(JarLauncher.java:40)
Caused by: java.lang.reflect.InvocationTargetException
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:119)
at java.base/java.lang.reflect.Method.invoke(Method.java:565)
at com.ibm.ws.naming.util.Helpers.getOrb(Helpers.java:508)
... 33 more
Caused by: java.lang.NoClassDefFoundError: Could not initialize class javax.rmi.CORBA.Util
at com.ibm.rmi.corba.PluginRegistry.instantiatePlugins(PluginRegistry.java:116)
at com.ibm.rmi.corba.ORB.instantiatePlugins(ORB.java:1525)
at com.ibm.rmi.corba.ORB.orbParameters(ORB.java:1430)
at com.ibm.rmi.corba.ORB.set_parameters(ORB.java:1356)
at com.ibm.CORBA.iiop.ORB.set_parameters(ORB.java:1697)
at org.omg.CORBA.ORB.init(ORB.java:473)
at com.ibm.ws.orb.GlobalORBFactory.init(GlobalORBFactory.java:95)
at com.ibm.ejs.oa.EJSORBImpl.initializeORB(EJSORBImpl.java:169)
at com.ibm.ejs.oa.EJSClientORBImpl.<init>(EJSClientORBImpl.java:64)
at com.ibm.ejs.oa.EJSClientORBImpl.<init>(EJSClientORBImpl.java:44)
at com.ibm.ejs.oa.EJSORB.init(EJSORB.java:85)
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:104)
... 35 more
Caused by: java.lang.ExceptionInInitializerError: Exception java.lang.NoClassDefFoundError: sun/security/action/GetPropertyAction [in thread "P=286519:O=0:CT"]
at javax.rmi.CORBA.Util.createDelegate(Util.java:338)
at javax.rmi.CORBA.Util.<clinit>(Util.java:65)
at com.ibm.rmi.corba.PluginRegistry.instantiatePlugins(PluginRegistry.java:116)
at com.ibm.rmi.corba.ORB.instantiatePlugins(ORB.java:1525)
at com.ibm.rmi.corba.ORB.orbParameters(ORB.java:1430)
at com.ibm.rmi.corba.ORB.set_parameters(ORB.java:1356)
at com.ibm.CORBA.iiop.ORB.set_parameters(ORB.java:1697)
at org.omg.CORBA.ORB.init(ORB.java:473)
at com.ibm.ws.orb.GlobalORBFactory.init(GlobalORBFactory.java:95)
at com.ibm.ejs.oa.EJSORBImpl.initializeORB(EJSORBImpl.java:169)
at com.ibm.ejs.oa.EJSClientORBImpl.<init>(EJSClientORBImpl.java:64)
at com.ibm.ejs.oa.EJSClientORBImpl.<init>(EJSClientORBImpl.java:44)
at com.ibm.ejs.oa.EJSORB.init(EJSORB.java:85)
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:104)
at java.base/java.lang.reflect.Method.invoke(Method.java:565)
at com.ibm.ws.naming.util.Helpers.getOrb(Helpers.java:508)
at com.ibm.ws.naming.util.WsnInitCtxFactory.getInitialContextInternal(WsnInitCtxFactory.java:478)
at com.ibm.ws.naming.util.WsnInitCtx.getContext(WsnInitCtx.java:128)
at com.ibm.ws.naming.util.WsnInitCtx.getContextIfNull(WsnInitCtx.java:765)
at com.ibm.ws.naming.util.WsnInitCtx.lookup(WsnInitCtx.java:164)
at com.ibm.ws.naming.util.WsnInitCtx.lookup(WsnInitCtx.java:179)
at java.naming/javax.naming.InitialContext.lookup(InitialContext.java:409)
at org.springframework.jndi.JndiTemplate.lambda$lookup$0(JndiTemplate.java:154)
at org.springframework.jndi.JndiTemplate.execute(JndiTemplate.java:89)
at org.springframework.jndi.JndiTemplate.lookup(JndiTemplate.java:154)
at org.springframework.jndi.JndiTemplate.lookup(JndiTemplate.java:176)
at org.springframework.jndi.JndiLocatorSupport.lookup(JndiLocatorSupport.java:106)
at org.springframework.jndi.JndiLocatorDelegate.lookup(JndiLocatorDelegate.java:65)
at org.springframework.jndi.JndiLocatorSupport.lookup(JndiLocatorSupport.java:79)
at org.springframework.jndi.JndiLocatorDelegate.lookup(JndiLocatorDelegate.java:60)
at org.springframework.jndi.JndiPropertySource.getProperty(JndiPropertySource.java:93)
at org.springframework.boot.context.properties.source.SpringConfigurationPropertySource.getPropertySourceProperty(SpringConfigurationPropertySource.java:110)
at org.springframework.boot.context.properties.source.SpringConfigurationPropertySource.getConfigurationProperty(SpringConfigurationPropertySource.java:92)
at org.springframework.boot.context.properties.source.ConfigurationPropertySourcesPropertySource.findConfigurationProperty(ConfigurationPropertySourcesPropertySource.java:72)
at org.springframework.boot.context.properties.source.ConfigurationPropertySourcesPropertyResolver.findPropertyValue(ConfigurationPropertySourcesPropertyResolver.java:101)
at org.springframework.boot.context.properties.source.ConfigurationPropertySourcesPropertyResolver.getProperty(ConfigurationPropertySourcesPropertyResolver.java:78)
at org.springframework.boot.context.properties.source.ConfigurationPropertySourcesPropertyResolver.getProperty(ConfigurationPropertySourcesPropertyResolver.java:64)
at org.springframework.core.env.AbstractEnvironment.getProperty(AbstractEnvironment.java:552)
at org.springframework.boot.cloud.CloudPlatform.isActive(CloudPlatform.java:191)
at org.springframework.boot.cloud.CloudFoundryVcapEnvironmentPostProcessor.postProcessEnvironment(CloudFoundryVcapEnvironmentPostProcessor.java:120)
at org.springframework.boot.support.EnvironmentPostProcessorApplicationListener.onApplicationEnvironmentPreparedEvent(EnvironmentPostProcessorApplicationListener.java:137)
at org.springframework.boot.support.EnvironmentPostProcessorApplicationListener.onApplicationEvent(EnvironmentPostProcessorApplicationListener.java:120)
at org.springframework.context.event.SimpleApplicationEventMulticaster.doInvokeListener(SimpleApplicationEventMulticaster.java:180)
at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:173)
at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:151)
at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:133)
at org.springframework.boot.context.event.EventPublishingRunListener.multicastInitialEvent(EventPublishingRunListener.java:137)
at org.springframework.boot.context.event.EventPublishingRunListener.environmentPrepared(EventPublishingRunListener.java:82)
at org.springframework.boot.SpringApplicationRunListeners.lambda$environmentPrepared$0(SpringApplicationRunListeners.java:66)
at java.base/java.util.ImmutableCollections$List12.forEach(ImmutableCollections.java:681)
at org.springframework.boot.SpringApplicationRunListeners.doWithListeners(SpringApplicationRunListeners.java:123)
at org.springframework.boot.SpringApplicationRunListeners.doWithListeners(SpringApplicationRunListeners.java:117)
at org.springframework.boot.SpringApplicationRunListeners.environmentPrepared(SpringApplicationRunListeners.java:65)
at org.springframework.boot.SpringApplication.prepareEnvironment(SpringApplication.java:356)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:316)
... 8 more
解决方案
You’re hitting two separate but related issues caused by moving to JDK 25:
sun.security.action.GetPropertyAction是一个内部JDK类,已不再对外部访问(并且实际已移除以供外部使用)。- CORBA/IIOP支持自Java 11起就从JDK中移除(JEP 320),因此依赖内置ORB的任何内容在JDK 25上都无法工作。
There is no supported way to re-enable the old CORBA/IIOP stack in JDK 25.
Why your application breaks
Your JMS 客户端正在使用IIOP(很可能通过 JNDI 与一个基于CORBA的提供者一起使用)。
That stack depends on:
- The old JDK CORBA implementation (removed)
- Internal
sun.*classes (now strongly encapsulated/absent)
Even if you work around the sun.* access, the CORBA transport itself is gone, so the client cannot function.
What will NOT work:
- Downgrading compiler flags or adding --add-exports is not a real solution in JDK 25.
- Adding --add-opens or similar may bypass some reflective access in older JDKs, but does not restore CORBA.
- There is no official replacement for
java.corbainside the JDK.
Viable options
1) Replace IIOP with a supported transport (recommended)
Check whether your JMS provider supports a non-IIOP protocol:
Direct TCP-based JMS client Vendor “thin client” HTTP-based JMS endpoints
Examples:
- IBM MQ: use the MQ JMS client over TCP instead of IIOP
- WebSphere: use thin client libraries instead of CORBA-based JNDI
This is the only clean solution that works natively on JDK 25.
2) Use an external CORBA implementation
You can try adding a third-party ORB such as JacORB.
This requires:
- Adding CORBA libraries manually
- Reconfiguring ORB initialization
- Ensuring your JMS provider supports a non-vendor-specific ORB
In practice, this often fails with older enterprise servers (e.g., WebSphere) because they rely on proprietary ORB behavior.
3) Introduce a bridge service (common enterprise workaround)
Run the legacy integration on an older JDK that still works (e.g., 8 or 17), and connect your JDK 25 application to it via a modern protocol.
Architecture:
Legacy service (JDK 8/11/17):
- Connects via IIOP
- Consumes JMS messages
New service (JDK 25):
- Communicates via REST, HTTP, Kafka, etc.
This isolates the unsupported technology while allowing the main system to run on JDK 25.
4) Migrate the server side (long-term)
If you control the JMS server:
Disable IIOP Enable modern protocols (TCP, AMQP, HTTP) Upgrade middleware if necessary
About the specific error
NoClassDefFoundError: sun/security/action/GetPropertyAction
This indicates a dependency (likely your JMS client or CORBA stack) is using internal JDK APIs.
Even if you try:
--add-exports java.base/sun.security.action=ALL-UNNAMED
this is not reliable in JDK 25 and does not solve the missing CORBA implementation.
Bottom line
- JDK 25 does not include support for CORBA/IIOP.
- Your current approach (JMS over IIOP using JDK-provided CORBA) cannot be made to work directly.
You must:
- Switch to a non-IIOP JMS client, or
- Use a bridge service on an older JDK, or
- Attempt (with risk) a third-party CORBA ORB.