1

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?

3
  • Spring and Hibernate are written with Aspect Oriented Programming (AOP) and Dependency Injection in mind. Preferences isn't. Commented May 12, 2015 at 17:17
  • I believe this would involve tinkering with system class loader, which sounds extremely difficult, especially in something like a web application. Not to mention that if it is for a library, you should not do something like this. Commented May 12, 2015 at 18:35
  • 2
    Alternatively, could you just create a subclass of Preferences through a subclass of PreferencesFactory and set the system property java.util.prefs.PreferencesFactory? This would allow you to define your custom, enriched Preferences class and have it instantiated as the default Preferences instance. Commented May 13, 2015 at 8:32

1 Answer 1

2

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.
Sign up to request clarification or add additional context in comments.

3 Comments

Good note on the breach of license, but otherwise this answer doesn't seem to address direct bytecode modification through libraries like ASM, which (unless Preferences is indeed a special case here too) can modify any class, even if it comes from the JVM.
Yes, you can read the class file and modifiy it but you are not able to load the modified byte code to actually represent the bootstrap class loader's java.util.prefs.Preferences class. As my answer states, you cannot hot swap the code or intercept the loading of the class as any agent is only attached after the class is already loaded.
Eventually, this was taken care with the approach Rafael mentioned using a wrapper.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.