obabichevjb opened a new issue, #16493:
URL: https://github.com/apache/dubbo/issues/16493

   ### Pre-check
   
   - [x] I am sure that all the content I provide is in English.
   
   
   ### Search before asking
   
   - [x] I had searched in the 
[issues](https://github.com/apache/dubbo/issues?q=is%3Aissue) and found no 
similar issues.
   
   
   ### Apache Dubbo Component
   
   Java SDK (apache/dubbo)
   
   ### Dubbo Version
   
   Dubbo Java 3.3.6, OpenJDK 21 (Amazon Corretto 21.0.5), macOS 15.6 
(OS-independent)
   
   
   ### Steps to reproduce this issue
   
   
   `ServiceConfigBase.checkRef` reports a service whose `ref` does not 
implement the declared
   interface. Its message is built by `getClassDesc`, which dereferences 
`Class#getClassLoader()`:
   
   ```java
   private String getClassDesc(Class clazz) {
       ClassLoader classLoader = clazz.getClassLoader();
       return clazz.getName() + "[classloader=" + 
classLoader.getClass().getName() + "@"
               + classLoader.hashCode() + "]";
   }
   ```
   
   `Class#getClassLoader()` returns **null for any bootstrap-loaded class**, 
i.e. every JDK type. So
   when a JDK type is on either side of the mismatch, the check throws 
`NullPointerException` from
   inside its own diagnostic and the real misconfiguration is never reported.
   
   Export a service whose declared interface is a JDK type that the ref does 
not implement. This is a
   complete `main`, with a `dubbo` dependency and nothing else — no registry or 
other infrastructure:
   
   ```java
   import org.apache.dubbo.config.ApplicationConfig;
   import org.apache.dubbo.config.ProtocolConfig;
   import org.apache.dubbo.config.RegistryConfig;
   import org.apache.dubbo.config.ServiceConfig;
   import org.apache.dubbo.config.bootstrap.DubboBootstrap;
   
   public class JavaRepro {
       public static void main(String[] args) {
           ServiceConfig<Object> service = new ServiceConfig<>();
           service.setInterface(Runnable.class); // GreeterServiceImpl does not 
implement Runnable
           service.setRef(new GreeterServiceImpl());
   
           DubboBootstrap.newInstance()
                   .application(new ApplicationConfig("java-repro"))
                   .registry(new RegistryConfig("N/A"))
                   .protocol(new ProtocolConfig("dubbo", 20896))
                   .service(service)
                   .start();
       }
   }
   ```
   
   Result on 3.3.6:
   
   ```
   Exception in thread "main" java.lang.NullPointerException: Cannot invoke 
"Object.getClass()" because "classLoader" is null
       at 
org.apache.dubbo.config.ServiceConfigBase.getClassDesc(ServiceConfigBase.java:162)
       at 
org.apache.dubbo.config.ServiceConfigBase.checkRef(ServiceConfigBase.java:156)
       at 
org.apache.dubbo.config.ServiceConfig.checkAndUpdateSubConfigs(ServiceConfig.java:508)
       at 
org.apache.dubbo.config.ServiceConfig.postProcessRefresh(ServiceConfig.java:549)
       at 
org.apache.dubbo.config.AbstractConfig.refresh(AbstractConfig.java:734)
       ...
       at 
org.apache.dubbo.config.bootstrap.DubboBootstrap.start(DubboBootstrap.java:219)
   ```
   
   Note it surfaces during application start, several frames from the config 
that caused it, with
   nothing naming the service or the interface.
   
   Substituting a **user-defined** wrong interface reports correctly, because 
its loader is non-null:
   
   ```
   java.lang.IllegalStateException: The class 
ergo.GreeterServiceImpl[classloader=jdk.internal.loader.ClassLoaders$AppClassLoader@746933701]
   unimplemented interface 
ergo.UnrelatedService[classloader=jdk.internal.loader.ClassLoaders$AppClassLoader@746933701]!
   ```
   
   That contrast is what narrows the bug to a JDK type being on either side.
   
   
   ### What you expected to happen
   
   `checkRef` should report the misconfiguration it was written to report, 
regardless of which loader
   the classes came from:
   
   ```
   The class 
ergo.GreeterServiceImpl[classloader=jdk.internal.loader.ClassLoaders$AppClassLoader@746933701]
   unimplemented interface java.lang.Runnable[classloader=bootstrap]!
   ```
   
   That is what a local build of the fix produces for the same `main`.
   
   
   ### Anything else
   
   I kinda added new term `bootstrap` to the API, so user may be surprised by 
that. I think if you have a better name, it could be replaced (I was about 
`no-classloader` or just `default`)
   
   ### Do you have a (mini) reproduction demo?
   
   - [ ] Yes, I have a minimal reproduction demo to help resolve this issue 
more effectively!
   
   ### Are you willing to submit a pull request to fix on your own?
   
   - [x] Yes I am willing to submit a pull request on my own!
   
   ### Code of Conduct
   
   - [x] I agree to follow this project's [Code of 
Conduct](https://www.apache.org/foundation/policies/conduct)
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to