Search code examples
javajava-bytecode-asmbytecode-manipulation

Java Byte Code manipulation: Adding a method to a jdk abstract class


Problem: I need to add a method to the java.util.prefs.Preferences abstract class, the reasons are as follows:

  1. I have implemented a clusterable preferences implementation and i need to enrich it with more than basic api that java.util.prefs.Preferences provides.
  2. I do not want to break the usage contract, i.e., a client gets the Preference implementation and uses the Preferences api only(obviously the enriched one).

How can I add a method to an existing Java bytecode?


Solution

  • For java.util.prefs.Preferences, you are out of luck. This class cannot be instrumented unless you change the classes that are put onto the bootstrap class path. And even if, note that is considered a breach of the JVM's user license agreement to ship an installation with a changed bootstrap class path.

    Normally, you can change a class during load time using a Java agent. This way, you could add methods. However, the Preferences class is used by the JVM internally and it gets loaded before an agent would be loaded. This way, the agent cannot be applied.

    Alternatively, the Instrumentation interface would allow you to change a loaded class at runtime. Using this approach, it is however illegal to add methods which is why this does not work either.

    As a third option, you could consider to implement a child-first class loader that shadows the Preferences class but no class loader other than the bootstrap class loader is allowed to define a class in a java.* package. Thus, this does not work either.

    What you want to do instead:

    1. Write a wrapper object, some EnhancedPreferences that delegate to another Preferences object it keeps in a field.
    2. Write a utility class which operates on a Preferences object using static methods.