Weil loadClass des SystemClassLoaders bereits durch new Foo() explizit aufgerunfen wird, bevor dir dein Classloader überhaupt Bar liefern kann.
Aber so wie du das hier machst, wird das nichts, weil Bar in jedem Fall als Bar geladen wird und deshalb auch nur mit new Bar instanziert werden kann. Das new Foo() müsste also auch über deinen Classloader erfolgen und die Instanzierung ebenfalls mit newInstance().
Das Äquivalent von Foo wird innerhalb einer Bibliothek in einer anderen Klasse instanziiert und ausgelesen. Leider sind in dem Foo Sachen fest verdrahtet, die wir gerne geändert hätten. Da wir die Objekterzeugung dort nicht unter Kontrolle haben und auch nicht an die Instanz rankommen (um sie z.B. mit Reflection zu manipulieren, bevor sie ausgelesen wird), war das meine Idee, um zu reinzuschummeln.
Nun, es gibt ja andere Wege, um der JVM irgendwas unterzujubeln. Ich denke, eine komplett andere Klasse wird schwierig. Wer soll wo sicherstellen, dass die Klassen die gleichen Methoden haben? Selbst wenn es ginge, müßte man/ich mal drüber nachdenken, ob man dann nicht einfach mit sowas wie
class MyClassLoader {
...
if (name.equals("SecurityManager")) return MyVerySpecialSecurityManager();
};
someGlobalThreadGroup.setClassLoader(new MyClassLoader());
solltest du ihm jede beliebige Klasse unterjubeln können, die in „fixedLibrary.jar“ liegt - sofern sie den gleichen Namen hat, wie das Original. (Das hatte ich mal für https://stackoverflow.com/a/22098863/3182664 - d.h. das geht sogar mit solchen Innereien wie java.lang.String ! ). Ob das hilft oder bei dir andwendbar ist, ist nicht ganz klar…
Was du benötigst ist ein FilteringClassLoader, der entsprechend verhindert, dass bereits geladene Klassen genutzt werden. Dies geschieht dadurch, dass du den Parent-ClassLoader löscht (um die automatische Delegation zu verhindern) und dann Packages die der FCL laden soll, selber behandelst und erst nachfolgend an den ehemaligen Parent weitergibst (oder ganz abblockst).
Allerdings ist bei dir ein anderes Problem. Du willst von der Original-Klasse ableiten, ergo müsste diese wiederbekannt sein. Am einfachsten kannst du das fixen, indem Foo und Bar ein gemeinsames Interface implementieren. Im letzten Schritt muss MyRunnable.class dann, ähnlich wie du es auch schon machst, vom FilteringClassLoader geladen werden. Denk hier daran, dass der FCL entsprechend das original Package auf der Blacklist hat.
In Hazelcast nutzen wir das übrigens in den Client Tests um sicherzustellen, dass, obwohl Client und Node in der selben JVM laufen, der Node keinen Zugriff auf die Modellklassen hat, also rein mit den serialisierten Objekten arbeiten muss.
Falls ich das richtig verstanden habe, wird das mit dem gemeinsamen Interface schwierig: Wenn man Kontrolle über alles hätte, könnte man ja direkt die Implementierung ändern Aber zumindest gut zu wissen, dass solches „Filtering“ zumindest grundsätzlich möglich ist.
OT: parent.setAccessible(true); Gerüchten zufolge soll das mit Java 9 doch krachen, oder?