You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@fury.apache.org by "theigl (via GitHub)" <gi...@apache.org> on 2024/10/09 15:11:13 UTC

[I] ClassLoader issues reading proxy with ThreadPoolFury [fury]

theigl opened a new issue, #1878:
URL: https://github.com/apache/fury/issues/1878

   ### Search before asking
   
   - [X] I had searched in the [issues](https://github.com/apache/fury/issues) and found no similar issues.
   
   
   ### Version
   
   0.8.0
   
   ### Component(s)
   
   Java
   
   ### Minimal reproduce step
   
   It is quite difficult to simulate this behavior:
   
   ```java
   import org.apache.fury.Fury;
   import org.apache.fury.ThreadSafeFury;
   import org.apache.fury.config.Language;
   import org.junit.jupiter.api.Test;
   
   import java.io.Serializable;
   import java.lang.reflect.*;
   import java.util.concurrent.CountDownLatch;
   
   import static org.junit.jupiter.api.Assertions.assertEquals;
   
   class ProxySerializerTest {
   	
   	static class MyClassLoader extends ClassLoader {
   		//dummy implementation
   	}
   	
   	@Test
   	void readProxy() throws InterruptedException, ClassNotFoundException {
   		final MyClassLoader myClassLoader = new MyClassLoader();
   		final Class<?> bf = Class.forName(getClass().getPackageName() + ".TestClass$TestInterface", true, myClassLoader);
   		final Class<?>[] interfaces = new Class<?>[] {bf, Serializable.class};
   		final Object type = Proxy.newProxyInstance(myClassLoader, interfaces, (proxy, method, args) -> null);
   		
   		final ThreadSafeFury fury = Fury.builder()
   				.withClassLoader(myClassLoader)
   				.withLanguage(Language.JAVA)
   				.requireClassRegistration(false)
   				.buildThreadSafeFuryPool(0, 10);
   
   		final CountDownLatch latch = new CountDownLatch(1);
   		new Thread(() -> {
   			final byte[] s = fury.serialize(type);
   			assertEquals(fury.deserialize(s), type);
   			latch.countDown();
   		}).start();
   		latch.await();
   	}
   }
   ```
   
   In the same package, put the following class:
   
   ```java
   public class TestClass {
   
   	interface TestInterface {
   
   	}
   }
   ``
   
   ### What did you expect to see?
   
   I can read proxies for private interfaces loaded during application startup.
   
   ### What did you see instead?
   
   The following exception is thrown in a Spring Boot app when reading a proxy created by Spring's `SerializableTypeWrapper`:
   
   ```java
   Caused by: java.lang.IllegalArgumentException: non-public interface is not defined by the given loader
   	at java.base/java.lang.reflect.Proxy$ProxyBuilder.proxyClassContext(Proxy.java:812)
   	at java.base/java.lang.reflect.Proxy$ProxyBuilder.<init>(Proxy.java:638)
   	at java.base/java.lang.reflect.Proxy.lambda$getProxyConstructor$1(Proxy.java:440)
   	at java.base/jdk.internal.loader.AbstractClassLoaderValue$Memoizer.get(AbstractClassLoaderValue.java:329)
   	at java.base/jdk.internal.loader.AbstractClassLoaderValue.computeIfAbsent(AbstractClassLoaderValue.java:205)
   	at java.base/java.lang.reflect.Proxy.getProxyConstructor(Proxy.java:438)
   	at java.base/java.lang.reflect.Proxy.newProxyInstance(Proxy.java:1034)
   	at org.apache.fury.serializer.JdkProxySerializer.read(JdkProxySerializer.java:83)
   	at org.apache.fury.Fury.readDataInternal(Fury.java:958)
   	at org.apache.fury.Fury.readRef(Fury.java:873)
   	at org.apache.fury.serializer.ObjectSerializer.readOtherFieldValue(ObjectSerializer.java:368)
   	at org.apache.fury.serializer.ObjectSerializer.readAndSetFields(ObjectSerializer.java:312)
   	at org.apache.fury.serializer.ObjectSerializer.read(ObjectSerializer.java:246)
   	at org.apache.fury.serializer.ReplaceResolveSerializer.readObject(ReplaceResolveSerializer.java:316)
   	at org.apache.fury.serializer.ReplaceResolveSerializer.read(ReplaceResolveSerializer.java:305)
   	at org.apache.wicket.spring.SpringBeanLocatorFuryRefCodec_0.readFields1$(SpringBeanLocatorFuryRefCodec_0.java:159)
   	at org.apache.wicket.spring.SpringBeanLocatorFuryRefCodec_0.read(SpringBeanLocatorFuryRefCodec_0.java:192)
   ```
   
   The class was loaded by Spring during application startup using the `AppClassLoader`. `ThreadPoolFury` always uses the current thread context which is `TomcatEmbeddedClassLoader` in my case. It is not possible to force `ThreadPoolFury` to use the class loader provided to Fury.
   
   ### Anything Else?
   
   _No response_
   
   ### Are you willing to submit a PR?
   
   - [ ] I'm willing to submit a PR!


-- 
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: commits-unsubscribe@fury.apache.org.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@fury.apache.org
For additional commands, e-mail: commits-help@fury.apache.org


Re: [I] ClassLoader issues reading proxy with ThreadPoolFury [fury]

Posted by "chaokunyang (via GitHub)" <gi...@apache.org>.
chaokunyang closed issue #1878: ClassLoader issues reading proxy with ThreadPoolFury
URL: https://github.com/apache/fury/issues/1878


-- 
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: commits-unsubscribe@fury.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@fury.apache.org
For additional commands, e-mail: commits-help@fury.apache.org


Re: [I] ClassLoader issues reading proxy with ThreadPoolFury [fury]

Posted by "chaokunyang (via GitHub)" <gi...@apache.org>.
chaokunyang commented on issue #1878:
URL: https://github.com/apache/fury/issues/1878#issuecomment-2409884097

   But this is indeed a bug, we need to use classloader set in FuryBuilder for ThreadSafeFury too. Would you like to submit a PR?


-- 
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: commits-unsubscribe@fury.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@fury.apache.org
For additional commands, e-mail: commits-help@fury.apache.org


Re: [I] ClassLoader issues reading proxy with ThreadPoolFury [fury]

Posted by "theigl (via GitHub)" <gi...@apache.org>.
theigl commented on issue #1878:
URL: https://github.com/apache/fury/issues/1878#issuecomment-2402709230

   Is there a reason that Fury prefers the context class loader over the configured class loader in `FuryPooledObjectFactory`?
   
   ```java
     /** ThreadLocal: ClassLoader. */
     private final ThreadLocal<ClassLoader> classLoaderLocal =
         ThreadLocal.withInitial(
             () -> {
               ClassLoader loader = Thread.currentThread().getContextClassLoader();
               if (loader == null) {
                 loader = Fury.class.getClassLoader();
               }
               return loader;
             });
   ```


-- 
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: commits-unsubscribe@fury.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@fury.apache.org
For additional commands, e-mail: commits-help@fury.apache.org


Re: [I] ClassLoader issues reading proxy with ThreadPoolFury [fury]

Posted by "chaokunyang (via GitHub)" <gi...@apache.org>.
chaokunyang commented on issue #1878:
URL: https://github.com/apache/fury/issues/1878#issuecomment-2409883120

   You can do that by:
   
   ```java
   new ThreadPoolFury(classloader -> Fury.builder()
   				.withClassLoader(myClassLoader)
   				.withLanguage(Language.JAVA)
   				.requireClassRegistration(false))
   ```


-- 
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: commits-unsubscribe@fury.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@fury.apache.org
For additional commands, e-mail: commits-help@fury.apache.org


Re: [I] ClassLoader issues reading proxy with ThreadPoolFury [fury]

Posted by "theigl (via GitHub)" <gi...@apache.org>.
theigl commented on issue #1878:
URL: https://github.com/apache/fury/issues/1878#issuecomment-2404302673

   Unfortunately, it does not work. Here is a simplified test-case that demonstrates the issue:
   
   ```java
   import org.apache.fury.Fury;
   import org.apache.fury.ThreadSafeFury;
   import org.apache.fury.config.Language;
   import org.junit.jupiter.api.Test;
   
   import java.util.concurrent.CountDownLatch;
   
   import static org.junit.jupiter.api.Assertions.assertInstanceOf;
   
   class ClassLoaderTest {
   
   	static class MyClassLoader extends ClassLoader {}
   
   	@Test
   	void shouldUseProvidedClassLoader() throws InterruptedException {
   		final MyClassLoader myClassLoader = new MyClassLoader();
   		final ThreadSafeFury fury = Fury.builder()
   				.withClassLoader(myClassLoader)
   				.withLanguage(Language.JAVA)
   				.requireClassRegistration(false)
   				.buildThreadSafeFuryPool(1, 1);
   		fury.setClassLoader(myClassLoader);
   
   		final CountDownLatch latch = new CountDownLatch(1);
   		new Thread(() -> {
   			final ClassLoader t = fury.getClassLoader();
   			assertInstanceOf(MyClassLoader.class, t);
   			latch.countDown();
   		}).start();
   		latch.await();
   	}
   }
   ```


-- 
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: commits-unsubscribe@fury.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@fury.apache.org
For additional commands, e-mail: commits-help@fury.apache.org


Re: [I] ClassLoader issues reading proxy with ThreadPoolFury [fury]

Posted by "theigl (via GitHub)" <gi...@apache.org>.
theigl commented on issue #1878:
URL: https://github.com/apache/fury/issues/1878#issuecomment-2403334390

   I will try this tomorrow!


-- 
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: commits-unsubscribe@fury.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@fury.apache.org
For additional commands, e-mail: commits-help@fury.apache.org


Re: [I] ClassLoader issues reading proxy with ThreadPoolFury [fury]

Posted by "theigl (via GitHub)" <gi...@apache.org>.
theigl commented on issue #1878:
URL: https://github.com/apache/fury/issues/1878#issuecomment-2408870141

   Ah OK! Thanks for clarifying this.
   
   Is there a reason the API has to be so complicated for `ThreadPoolFury`? I understand that it has to be this way if I want to customize the class loader on a per-call or per-thread basis. But in my case I just want to use a "hard-coded" class  loader for each and every thread. Could it not use the class loader passed to `.withClassLoader(xyz)` by default?


-- 
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: commits-unsubscribe@fury.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@fury.apache.org
For additional commands, e-mail: commits-help@fury.apache.org


Re: [I] ClassLoader issues reading proxy with ThreadPoolFury [fury]

Posted by "chaokunyang (via GitHub)" <gi...@apache.org>.
chaokunyang commented on issue #1878:
URL: https://github.com/apache/fury/issues/1878#issuecomment-2403140085

   Could you try to invoke ThreadSafeFury#setClassLoader? It should work


-- 
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: commits-unsubscribe@fury.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@fury.apache.org
For additional commands, e-mail: commits-help@fury.apache.org


Re: [I] ClassLoader issues reading proxy with ThreadPoolFury [fury]

Posted by "chaokunyang (via GitHub)" <gi...@apache.org>.
chaokunyang commented on issue #1878:
URL: https://github.com/apache/fury/issues/1878#issuecomment-2408767041

   It's not how this API be used, you should invoke `fury.setClassLoader(myClassLoader);` just before you invoke `Fury#deserialize`. This set classloader is cached as a thread local variable, thus is only visible on your setting thread


-- 
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: commits-unsubscribe@fury.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@fury.apache.org
For additional commands, e-mail: commits-help@fury.apache.org


Re: [I] ClassLoader issues reading proxy with ThreadPoolFury [fury]

Posted by "theigl (via GitHub)" <gi...@apache.org>.
theigl commented on issue #1878:
URL: https://github.com/apache/fury/issues/1878#issuecomment-2410422282

   I'm on holiday for the next 7-10 days. If the issue is still open when I come back, I can take a look!


-- 
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: commits-unsubscribe@fury.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@fury.apache.org
For additional commands, e-mail: commits-help@fury.apache.org


Re: [I] ClassLoader issues reading proxy with ThreadPoolFury [fury]

Posted by "theigl (via GitHub)" <gi...@apache.org>.
theigl commented on issue #1878:
URL: https://github.com/apache/fury/issues/1878#issuecomment-2440095037

   Fantastic, thanks a lot @Aliothmoon and @chaokunyang!


-- 
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: commits-unsubscribe@fury.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@fury.apache.org
For additional commands, e-mail: commits-help@fury.apache.org