RMI's MarshalInputStream.resolveProxyClass currently always defines a dynamic proxy class to be returned in the internal "RMI class loader" for the codebase annotation, in order to thwart possible loss of codebase annotations when the proxy passes through a VM with its interfaces locally visible: a proxy class always gets treated like it were a downloaded (non-local) stub class (one could almost say "preferred").
This choice can cause a problem with a non-public interfaces, however if the interface is visible locally (i.e. by the context class loader), because language-level package access is only allowed between classes in the same class loader. If the proxy class for the non-public interface is defined in the RMI class loader for the codebase annotation that delegates to the defining loader of the non-public interface, an IllegalAccessError will be thrown because the implementing class is in a different loader from one of its interfaces.
In such a case, it seems preferable to define the proxy class in the same loader as the non-public interface, forgoing concerns about codebase lossage in favor of not failing more absolutely with the IllegalAccessError.
Thinking parallel to the non-proxy case, it seems that one can never use dynamic class loading to download a (conventional) RMI stub class for a local but NON-public remote interface; rather, the stub class must always be bundled with such a remote interface (either locally or all downloaded together). This same restriction must be true in the dynamic proxy case as well, but the problem is just that MarshalInputStream currently tries to always make the dynamic proxy case work like the dynamically downloaded stub case, which is not always appropriate, as demonstrated by this bug. See the "Suggested Fix" section for how it should probably behave.
(This problem also likely exists to some extent in ObjectInputStream's default resolveProxyClass, although the solution in that case would seem to be more straightforward, since ObjectInputStream need not be concerned with losing codebase annotations.)
This choice can cause a problem with a non-public interfaces, however if the interface is visible locally (i.e. by the context class loader), because language-level package access is only allowed between classes in the same class loader. If the proxy class for the non-public interface is defined in the RMI class loader for the codebase annotation that delegates to the defining loader of the non-public interface, an IllegalAccessError will be thrown because the implementing class is in a different loader from one of its interfaces.
In such a case, it seems preferable to define the proxy class in the same loader as the non-public interface, forgoing concerns about codebase lossage in favor of not failing more absolutely with the IllegalAccessError.
Thinking parallel to the non-proxy case, it seems that one can never use dynamic class loading to download a (conventional) RMI stub class for a local but NON-public remote interface; rather, the stub class must always be bundled with such a remote interface (either locally or all downloaded together). This same restriction must be true in the dynamic proxy case as well, but the problem is just that MarshalInputStream currently tries to always make the dynamic proxy case work like the dynamically downloaded stub case, which is not always appropriate, as demonstrated by this bug. See the "Suggested Fix" section for how it should probably behave.
(This problem also likely exists to some extent in ObjectInputStream's default resolveProxyClass, although the solution in that case would seem to be more straightforward, since ObjectInputStream need not be concerned with losing codebase annotations.)
- relates to
-
JDK-4413817 ObjectInputStream.resolveProxyClass can fail for non-public interface cases
-
- Closed
-