How can I create dynamic proxy for final Class?

前端 未结 2 2034
别那么骄傲
别那么骄傲 2021-02-03 12:00

In short: 1. I have some final class that I want to create dynamic proxy for it. How can I do it? 2. Can I convert MethodHandle to Method?

Detai

相关标签:
2条回答
  • 2021-02-03 12:11

    It depends on what kind of proxy you need. There are basically three aproaches of how you can achieve this, of which two are feasible in production code. As @probrekely stated, the problem of cglib or javassist ist that they dynamically create a subclass what is not possible for final classes. You can avoid this by:

    • Disabling byte code verification. The Java run time verifies byte code in order to secure that no malicious byte code is loaded. This is important when for example receiving classes over the network or the internet, for example an applet. This way, you could create a subclass of a final class since the byte code verifier would not stop you. Hypothetically, you can disable this verification if you run trusted code only. This can be done by running:

      java -Xverify:none ApplicationName
      

      This is however the solution I would recommend you the least. I would not use this aproach for production code but it is most certainly the easiest solution to implement.

    • Remove the final modifier from loaded classes, either before or after the classes are loaded. This can be achieve by using a Java agent. A Java agent can be installed at application startup via the command line or at runtime via the Attach API. With a byte code tool like ASM, you could parse the original byte array and remove the final modifier from all classes of interest. It is also possible to redefine classes that were already loaded. Remove a final modifier does not introduce conflicts with old class versions such that such a redefinition is always possible.

    • Do the same as I described with removing the final modifier but redefine the loaded class to actually contain all your instrumentation logic within the original class. This aporach will most certanly require the biggest effort but this will make your instrumentation transperent to all other code. This would be the cleanest solution of all solutions.

    0 讨论(0)
  • 2021-02-03 12:21

    Sorry, what you want isn't possible:

    You can use CGLIB or Javassist to create proxies for concrete classes because these libraries dynamically generate a subclass of the class you're trying to proxy. A final class can't be subclassed, so you can't create a proxy this way.

    PowerMock does let you proxy final classes and methods, but this is because it runs your tests under its special ClassLoader which uses Javassist to modify the bytecode of the classes you wish to proxy as they're being loaded. (You wouldn't want to use this sort of thing in production, as generally the modified "zombie" version of the class that results won't be good for much else than running a specific mock unit test.)

    The PowerMock approach wouldn't work here, however - you want to proxy java.lang.reflect.Method, which is on the bootstrap classpath, and so would load before any PowerMock/Javassist type tool and therefore not be proxiable.

    0 讨论(0)
提交回复
热议问题