JDK-8335333 : Jdk DynamicProxy throw java.lang.NoClassDefFoundError
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.lang:reflect
  • Affected Version: 17,21,22,23
  • Priority: P4
  • Status: Closed
  • Resolution: Duplicate
  • OS: generic
  • CPU: generic
  • Submitted: 2024-06-26
  • Updated: 2024-07-01
  • Resolved: 2024-07-01
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 24
24Resolved
Related Reports
Duplicate :  
Description
A DESCRIPTION OF THE PROBLEM :
run my code, I excepted StackOverflowError,but it print error : java.lang.NoClassDefFoundError: Could not initialize class java.lang.reflect.UndeclaredThrowableException  why? this is bug?

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
I expected StackOverflowError
ACTUAL -
java.lang.NoClassDefFoundError: Could not initialize class java.lang.reflect.UndeclaredThrowableException

---------- BEGIN SOURCE ----------
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;


public class JdkDynamicProxy {
    public static void main(String[] args) {
//        new UndeclaredThrowableException(new RuntimeException());
        ClassLoader classLoader = JdkDynamicProxy.class.getClassLoader();
        MaiPiao proxyMaiPiao = (MaiPiao) Proxy.newProxyInstance(classLoader, new Class[]{MaiPiao.class}, (proxy, method, args1) -> {
            if(method.getName().equals("maiPiao")){
                System.out.println("卖票");
                return null;
            }else if(method.getName().equals("getName")){
                return "name1";
            }
            return method.invoke(proxy);
        });
        proxyMaiPiao.maiPiao();
        String name = proxyMaiPiao.getName();
        System.out.println(name);
        proxyMaiPiao.doSomething();
    }

    public interface MaiPiao{
        void maiPiao();

        String getName();

        void doSomething();
    }
}

---------- END SOURCE ----------


Comments
Proxy is working as intended, and this error is from Method.invoke, which is described as intended per JEP 416. Here, `Method.invoke` is not used properly; it should be wrapped in try-catch to catch InvocationTargetException, and throw the cause if it is a RuntimeException or an Error. API notes will be added to `Method.invoke` for best practices of unwrapping the errors in the duplicated issue link.
01-07-2024

This issue is not related to Proxy or UndeclaredThrowableException, but to Method.invoke. A minimal reproduction has been attached as Recur.java, and the same NoClassDefFoundError is replicated with ExceptionInInitializerError. Couldn't reproduce it on 17 but could reproduce it on 18, for both original and minimized reproducers. In "risks and assumptions" section of JEP 416: Method-handle invocation may consume more resources than the old core reflection implementation. Such invocation involves calling multiple Java methods to ensure that the declaring class of a member is initialized prior to access, and thus may require more stack space for the necessary execution frames. This may result in a StackOverflowError or, if a StackOverflowError is thrown while initializing a class, then a NoClassDefFoundError.
28-06-2024

I usually run with -Xlog:exception in these cases as it can be hard to see the SOE sometimes.
28-06-2024

This should be a bug from JEP 416; the last significant rework of Proxy between 11 and 17 happened in 14, and archived 14.0.2 gets StackOverflowError. [~alanb] Here the StackOverflowError still happens, but in 17 and later this error is wrapped as a cause of NoClassDefFoundError for initializing UndeclaredThrowableException class; it's not that UndeclaredThrowableException is actually thrown.
28-06-2024

Proxy and the core reflection implementation have changed over the releases so you will get a bit of variance. In general, if you get SOE during class loading or running a class initializer then it may surface as a NCDFE with SOE as cause, or somewhere else this example might throw UndeclaredThrowableException (with SOE as cause).
28-06-2024

The observations on Windows 11: JDK 8: Passed. JDK 11: Passed, NoClassDefFoundError is not found JDK 17ea+1: Failed, NoClassDefFoundError observed JDK 22: Failed. JDK 23ea+14: Failed.
28-06-2024