Hoi allen, ik ben een beetje aan het kutten met een classloader en wel om het volgende:
Ik heb een verzameling classes die allemaal een interface implementeren. Deze interface zegt me dat er op de class in kwestie een statische methode beschikbaar is (klopt, dat wordt niet afgedwongen door de interface zelf). Nu zou ik willen dat op het moment dat de class wordt geladen, de statische methode op de class wordt aangeroepen.
Mijn idee was: stel op de één of andere manier een 'default classloader' in zodat al het laden van classes hier langs gaat. Deze classloader kan dan proberen de class te laden (maakt me niet zoveel uit hoe, dus wellicht via de systeemclassloader?) en als dat is gedaan, een Class.isAssignableFrom() aanroep toe te passen, om te checken of de class de interface in kwestie implementeert, etc, etc.
Maar goed, wat ik had bedacht werkt nog niet helemaal. Nu heb ik begrepen dat er in (vanaf?) Java 1.4 een systemproperty beschikbaar is om de defaultclassloader op te geven.. maar ik zit nog vast aan 1.3, helaas.
Anyways, wat ik heb:
Daarbij:
Hiermee wordt de main op de class Loader aangeroepen met de argumenten die bij de huidige main-methode waren binnengekomen. Hiermee is het net alsof Loader.main rechtstreeks was aangeroepen, maar nu dus in opdracht van mijn eigen classloader. Verder heb ik geen code aangepast om maar te zorgen/proberen dat de classes via de eigen classloader worden geladen, dus dit is een mate van transparantie die ik zoek.
Naja, voor zover ik kan zien gaat het laden van classes nu inderdaad via mijn eigen classloader en dan zodanig dat als ie een class niet in de directory kan vinden, de benodigde class toch wel wordt gevonden (via de parent loader). Maar op een bepaald moment krijg ik toch een java.lang.LinkageError.
Het gaat misschien te ver om te roepen: "Help, hoe komt dit en hoe los ik dit op?!", maar ik vraag me in ieder geval af of ik op de goede weg ben.
Dus, iemand comments en/of feedback? Doe ik iets doms dat het niet werkt, of is het dusdanig briljant dat ik voorbij de specs van de Java-API aan het opereren ben?
Thanks!
Ik heb een verzameling classes die allemaal een interface implementeren. Deze interface zegt me dat er op de class in kwestie een statische methode beschikbaar is (klopt, dat wordt niet afgedwongen door de interface zelf). Nu zou ik willen dat op het moment dat de class wordt geladen, de statische methode op de class wordt aangeroepen.
Mijn idee was: stel op de één of andere manier een 'default classloader' in zodat al het laden van classes hier langs gaat. Deze classloader kan dan proberen de class te laden (maakt me niet zoveel uit hoe, dus wellicht via de systeemclassloader?) en als dat is gedaan, een Class.isAssignableFrom() aanroep toe te passen, om te checken of de class de interface in kwestie implementeert, etc, etc.
Maar goed, wat ik had bedacht werkt nog niet helemaal. Nu heb ik begrepen dat er in (vanaf?) Java 1.4 een systemproperty beschikbaar is om de defaultclassloader op te geven.. maar ik zit nog vast aan 1.3, helaas.
Anyways, wat ik heb:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
| import java.lang.reflect.*;
import java.net.*;
public class TranslatingClassLoader extends URLClassLoader
{
private static final URL[] getUrl()
{
try
{
return new URL[]
{
new URL("file:///s:/classes/")
};
}
catch (MalformedURLException ex)
{
return new URL[0];
}
}
public TranslatingClassLoader()
{
super(getUrl());
}
public TranslatingClassLoader(ClassLoader parent)
{
super(getUrl(), parent);
}
protected Class loadClass(String name, boolean resolve) throws ClassNotFoundException
{
try
{
Class c = findClass(name);
if (resolve)
resolveClass(c);
return c;
}
catch (ClassNotFoundException ex)
{
Class c = super.loadClass(name, resolve);
return c;
}
}
protected Class findClass(String name) throws ClassNotFoundException
{
Class c = super.findClass(name);
boolean assignable = TranslatableClass.class.isAssignableFrom(c);
if (assignable)
{
try
{
Method m = c.getMethod("_translate", new Class[]{Translator.class});
m.invoke(null, new Object[] {TranslatorImpl.getInstance()});
}
catch (Exception ex)
{
Logger.log("Could not translate: " + name + " [" + ex.getMessage() + "]", Logger.LEVEL_ERROR);
}
}
return c;
}
} |
Daarbij:
code:
1
2
3
4
5
6
7
| public static void main(String[] args)
{
TranslatingClassLoader loader = new TranslatingClassLoader();
Class loaderClass = loader.loadClass("menu.Loader");
java.lang.reflect.Method m = loaderClass.getMethod("main", new Class[] {args.getClass()});
m.invoke(null, new Object[] {args});
} |
Hiermee wordt de main op de class Loader aangeroepen met de argumenten die bij de huidige main-methode waren binnengekomen. Hiermee is het net alsof Loader.main rechtstreeks was aangeroepen, maar nu dus in opdracht van mijn eigen classloader. Verder heb ik geen code aangepast om maar te zorgen/proberen dat de classes via de eigen classloader worden geladen, dus dit is een mate van transparantie die ik zoek.
Naja, voor zover ik kan zien gaat het laden van classes nu inderdaad via mijn eigen classloader en dan zodanig dat als ie een class niet in de directory kan vinden, de benodigde class toch wel wordt gevonden (via de parent loader). Maar op een bepaald moment krijg ik toch een java.lang.LinkageError.
Het gaat misschien te ver om te roepen: "Help, hoe komt dit en hoe los ik dit op?!", maar ik vraag me in ieder geval af of ik op de goede weg ben.
Dus, iemand comments en/of feedback? Doe ik iets doms dat het niet werkt, of is het dusdanig briljant dat ik voorbij de specs van de Java-API aan het opereren ben?
Thanks!