0

Java's Dynamic Proxy Docs describe these constructors as the following:

A dynamic proxy class is a class that implements a list of interfaces specified at runtime such that a method invocation through one of the interfaces on an instance of the class will be encoded and dispatched to another object through a uniform interface. Thus, a dynamic proxy class can be used to create a type-safe proxy object for a list of interfaces without requiring pre-generation of the proxy class.

Now, while everything in this sentence is accurate. All of this information is in fact present at compile time. In Java, when you are creating a proxy, you specify the exact interface you want to proxy in your code.

Now the first thing that really confuses me, is why the byte code here needs to be generated at run time? All of this information is present at the compile time... (and you don't even have to deal with type erasure)

P.S: I am not sure if this is still the case, basing this on a quite dated accepted answer here: How does Java's Dynamic Proxy actually work?)

The next step in getting this work is the type checking/type inference. I am not sure how Java actually handles this, but you need to be able to use Proxy<A> interchangeably with A. In order to pull this of you need the following:

∀ method m ∈ A, m ∈ Proxy<A>

Which means that

  1. you need your proxy to have the same structure
  2. you need some kind of delegation (i.e. dynamic dispatch).

Once you start writing out the inference rules, this gives us something very familiar. Structural Typing

Now Java doesn't have structural typing but one could easily add the few inference rules (i.e. Typescript) especially given Java has boxed primitives (Scala for example doesn't which makes it very difficult to introduce structural inference).

The Actual Question

Reflection is hard, not safe and not super performant. My question is why and how Java's proxies use reflection? It seems like most of this functionality could be implemented using other features already present in the language.

sinanspd
  • 2,589
  • 3
  • 19
  • 37
  • 1
    It isn't present at compile-time. The arguments to `Proxy.newProxyInstance()` are variables. They can be assigned at runtime. And consider `java.rmi.server.UnicastRemoteObject.exportObject()`. It doesn't know at compile time what remote objects it is going to have to create proxy stubs for, and those remote object classes aren't even present at this compile time. The feature would be useless in your envisaged implementation. – user207421 Jun 11 '21 at 03:58
  • @user207421 When you call `Proxy.newProxyInstance()` you pass in what class/interface you want to proxy, no? Sure it can be a variable but the eventually that binding resolves to a concrete value. Maybe I am missing a detail about the Java compiler but it's not like it's introducing an entirely new type at runtime – sinanspd Jun 11 '21 at 04:23
  • Who says you pass in an interface that's known at compile time? You could pass in a _randomly selected_ interface, depending on what time it is the program gets run. – Louis Wasserman Jun 11 '21 at 04:27
  • @LouisWasserman That was my understanding which obviously was wrong. Thank you for the example. I guess it comes down to the flexibility of IFC of Java. – sinanspd Jun 11 '21 at 04:31
  • I've explained this. When I call `UnicastRemoteObject.exportObject()` it calls `Proxy.newProxyInstance()` with a class that *I* supply. Not one that was present when `UnicastRemoteObject` was compiled, in Cupertino, several thousand miles away and several years earlier or later. – user207421 Jun 11 '21 at 04:49
  • @user207421 makes sense. I had to look up `UnicastRemoteObject`. Wasn't familiar with it so I misinterpreted the comment – sinanspd Jun 11 '21 at 04:54

0 Answers0