Skip to content

Commit 9e7fedb

Browse files
ngmrjoe-chacko
andcommitted
refactor(rmi): convert Helper.narrow() to MethodHandle with caching
Convert Method.invoke() to MethodHandle.invoke() for IDL Helper narrow() calls in PortableRemoteObjectImpl with ClassValue-based caching. Changes: - Added HELPER_NARROW_CACHE using ClassValue<MethodHandle>, mapping from helper class to its "narrow" method - Updated narrowIDL() to use cached MethodHandle instead of Method.invoke() - Simplified exception handling with consistent pattern - Updated MultiAddressUrlTest to remove InvocationTargetException from expected causal chains, as MethodHandle.invoke() does not add this wrapper layer (unlike the old Method.invoke() approach) - Fixed exception handling in StubWriteReplaceMethodHolder to properly unwrap PrivilegedActionException - Lines added: 29, lines removed: 13 Performance: ClassValue provides thread-safe per-class caching without locks Co-authored-by: Joe Chacko <chackoj@uk.ibm.com> Co-authored-by-AI: IBM Bob 1.0.4
1 parent e10948a commit 9e7fedb

2 files changed

Lines changed: 31 additions & 15 deletions

File tree

yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/PortableRemoteObjectImpl.java

Lines changed: 27 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@
3434
import javax.rmi.CORBA.Stub;
3535
import javax.rmi.CORBA.Tie;
3636
import javax.rmi.CORBA.Util;
37+
import java.lang.invoke.MethodHandle;
38+
import java.lang.invoke.MethodHandles;
3739
import java.lang.reflect.Constructor;
3840
import java.lang.reflect.InvocationTargetException;
3941
import java.lang.reflect.Method;
@@ -66,13 +68,26 @@ enum StubWriteReplaceMethodHolder {
6668
static {
6769
try {
6870
STUB_WRITE_REPLACE_METHOD = doPrivileged(getDeclaredMethod(RMIStub.class, "writeReplace"));
69-
} catch (PrivilegedActionException ex) {
70-
//noinspection Convert2MethodRef
71-
throw wrapped(LOGGER, ex, "cannot initialize: \n" + ex.getMessage(), e -> new Error(e));
71+
} catch (PrivilegedActionException pae) {
72+
Throwable t = pae.getCause();
73+
throw wrapped(LOGGER, t, "cannot initialize: \n" + t.getMessage(), e -> new Error(t));
7274
}
7375
}
7476
}
7577

78+
79+
private static final ClassValue<MethodHandle> HELPER_NARROW_CACHE = new ClassValue<MethodHandle>() {
80+
@Override
81+
protected MethodHandle computeValue(Class<?> helperClass) {
82+
try {
83+
final Method helperNarrow = doPrivileged(getMethod(helperClass, "narrow", org.omg.CORBA.Object.class));
84+
return MethodHandles.lookup().unreflect(helperNarrow);
85+
} catch (Exception e) {
86+
throw as(ClassCastException::new, e, helperClass.getName());
87+
}
88+
}
89+
};
90+
7691
public void connect(Remote target, Remote source) throws RemoteException {
7792
source = toStub(source);
7893

@@ -126,15 +141,16 @@ private Object narrowRMI(ObjectImpl narrowFrom, Class<?> narrowTo) {
126141

127142
private Object narrowIDL(ObjectImpl narrowFrom, Class<?> narrowTo) {
128143
LOGGER.fine(() -> String.format("IDL narrowing %s => %s", narrowFrom.getClass().getName(), narrowTo.getName()));
129-
final ClassLoader idlClassLoader = doPrivileged(getClassLoader(narrowTo));
130-
final String helperClassName = narrowTo.getName() + "Helper";
131-
132144
try {
145+
final ClassLoader idlClassLoader = doPrivileged(getClassLoader(narrowTo));
146+
final String helperClassName = narrowTo.getName() + "Helper";
133147
final Class<?> helperClass = Util.loadClass(helperClassName, null, idlClassLoader);
134-
final Method helperNarrow = doPrivileged(getMethod(helperClass, "narrow", org.omg.CORBA.Object.class));
135-
return helperNarrow.invoke(null, narrowFrom);
136-
} catch (Exception e) {
137-
throw as(ClassCastException::new, e, narrowTo.getName());
148+
MethodHandle narrowHandle = HELPER_NARROW_CACHE.get(helperClass);
149+
return narrowHandle.invoke(narrowFrom);
150+
} catch (Error e) {
151+
throw e;
152+
} catch (Throwable t) {
153+
throw as(ClassCastException::new, t, narrowTo.getName());
138154
}
139155
}
140156

@@ -239,7 +255,7 @@ static Constructor<? extends Stub> getRMIStubClassConstructor(RMIState state, Cl
239255
return cachedCons;
240256
}
241257

242-
258+
243259
final ClassLoader loader = doPrivileged(getClassLoader(type));
244260
final ClassLoader contextLoader = doPrivileged(GET_CONTEXT_CLASS_LOADER);
245261

yoko-verify/src/test/java-testify/org/apache/yoko/MultiAddressUrlTest.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2025 IBM Corporation and others.
2+
* Copyright 2026 IBM Corporation and others.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -65,14 +65,14 @@ public void testServerStopped(ORB orb) {
6565
narrow(orb.string_to_object(nsUrl), NamingContext.class);
6666
// stop the server
6767
control.stop();
68-
assertThrowsExactly(ClassCastException.class, () -> narrow(orb.string_to_object(nsUrl), NamingContext.class), InvocationTargetException.class, TRANSIENT.class, ConnectException.class);
68+
assertThrowsExactly(ClassCastException.class, () -> narrow(orb.string_to_object(nsUrl), NamingContext.class), TRANSIENT.class, ConnectException.class);
6969
control.start();
7070
}
7171

7272
@Test
7373
public void testConnectionRefused(ORB orb) throws Exception {
7474
// first show that port 47 is not listening
75-
assertThrowsExactly(ClassCastException.class, () -> narrow(orb.string_to_object(NO_LISTENER_NS_URL), NamingContext.class), InvocationTargetException.class, TRANSIENT.class, ConnectException.class);
75+
assertThrowsExactly(ClassCastException.class, () -> narrow(orb.string_to_object(NO_LISTENER_NS_URL), NamingContext.class), TRANSIENT.class, ConnectException.class);
7676
// check our nsURL starts with corbaname:
7777
assertThat(nsUrl, startsWith("corbaname:"));
7878
// construct a URL where the first server is stopped (connection refused)
@@ -84,7 +84,7 @@ public void testConnectionRefused(ORB orb) throws Exception {
8484
@Test
8585
public void testHostUnreachable(ORB orb) throws Exception {
8686
// first show that port 47 is not listening
87-
assertThrowsExactly(ClassCastException.class, () -> narrow(orb.string_to_object(UNREACHABLE_NS_URL), NamingContext.class), InvocationTargetException.class, NO_RESPONSE.class);
87+
assertThrowsExactly(ClassCastException.class, () -> narrow(orb.string_to_object(UNREACHABLE_NS_URL), NamingContext.class), NO_RESPONSE.class);
8888
// check our nsURL starts with corbaname:
8989
assertThat(nsUrl, startsWith("corbaname:"));
9090
// construct a URL where the first server is stopped (connection refused)

0 commit comments

Comments
 (0)