Dawid
2011/2/23 Ula K. <ukr...@gmail.com>:
> --
> Otrzymujesz tę wiadomość, ponieważ subskrybujesz grupę dyskusyjną Google o
> nazwie „Poznań Java User Group”.
> Aby zamieszczać posty w tej grupie, wyślij e-mail na adres
> jug-p...@googlegroups.com.
> Aby anulować subskrypcję tej grupy, wyślij e-mail na adres
> jug-poznan+...@googlegroups.com.
> Aby uzyskać więcej informacji, odwiedź tę grupę pod adresem
> http://groups.google.com/group/jug-poznan?hl=pl.
>
Dawid zawsze AspectJ wcisnie :)
skoro nie korzystasz z Saxona to mozna tez bezczelnie zmockowac
net.sf.saxon.TransformerFactoryImpl (albo zrobic proxy do innej fabryki)
- byle sie uruchomilo.
lg
--
Leszek Gawron http://www.mobilebox.pl/krs.html
CTO at MobileBox Ltd.
Dawid
2011/2/23 Leszek Gawron <lga...@mobilebox.pl>:
> On 2011-02-23 12:29, Dawid Weiss wrote:
>>
>> Podaj pełen stack trace, Ula, to będzie widać skąd ten wyjątek się
>> bierze. Rozwiązań jest parę -- od poszukania czy nie masz w
>> META-INF/services gdzieś przesłoniętego parsera (w którymś z jarów w
>> classpath) do owinięcia problematycznej biblioteki AspectJem w
>> runtime...
>>
>
> Dawid zawsze AspectJ wcisnie :)
>
>
> skoro nie korzystasz z Saxona to mozna tez bezczelnie zmockowac
> net.sf.saxon.TransformerFactoryImpl (albo zrobic proxy do innej fabryki) -
> byle sie uruchomilo.
>
> lg
>
> --
> Leszek Gawron http://www.mobilebox.pl/krs.html
> CTO at MobileBox Ltd.
>
Caused by: java.lang.NoClassDefFoundError: net/sf/saxon/TransformerFactoryImplPluginRegistry.loadClass ładuje inna klasę, która zależy od saxona.
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:169)
at org.pentaho.di.core.plugins.PluginRegistry.loadClass(PluginRegistry.java:297)
Jeżeli masz to najprawdopodobniej saxon.jar zawiera plik
META-INF/services/javax.xml.transform.TransformerFactory, gdzie jest
odwołanie do fabryki Saxona, która faktycznie przesłania tą domyślną.
Ale wtedy nie powinnaś dostawać NoClassDefFoundError…
Sprawdź, czy inny z jarów nie zawiera wyżej wymienionego pliku w
swojej strukturze.
Jaka jest kolejność kroków procedury, która szuka odpowiedniej
implementacji fabryki TransformerFactory można przeczytać tutaj:
http://download.oracle.com/javase/6/docs/api/javax/xml/transform/TransformerFactory.html#newInstance()
Jeżeli chcesz być pewna jaka implementacja zostanie wykorzystana
najlepiej podaj ją ręcznie do drugiej wersji metody
newInstance(String, ClassLoader), np.
"javax.xml.transform.sax.SAXTransformerFactory".
-- Maciej
2011/2/23 Ula K. <ukr...@gmail.com>:
> Oki. Po kolei.
> Stack trace:
>
> Caused by: java.lang.NoClassDefFoundError:
> net/sf/saxon/TransformerFactoryImpl
> at java.lang.Class.forName0(Native Method)
> at java.lang.Class.forName(Class.java:169)
>
> at
> org.pentaho.di.core.plugins.PluginRegistry.loadClass(PluginRegistry.java:297)
>
> PluginRegistry.loadClass ładuje inna klasę, która zależy od saxona.
>
> W bibliotece saxon.jar jest plik META-INF/services/... które pewnie
> przesłania domyślnego parsera.
>
> Ula
>
--
Maciej Biłas
maciej at inszy dot org
a wiec dodalas saxon.jar do classpath, czy nie?
>
> Ula
>
> W dniu 23 lutego 2011 12:42 u�ytkownik Dawid Weiss
> <dawid...@cs.put.poznan.pl <mailto:dawid...@cs.put.poznan.pl>>
> napisaďż˝:
>
> Napisa�em od...do.
ale� �art przecie� :)
Ula, czy w takim razie masz czy nie masz saxon.jar w classpathie
projektu, z którego podajesz nam teraz stacktrace?
Jeżeli masz to najprawdopodobniej saxon.jar zawiera plik
META-INF/services/javax.xml.transform.TransformerFactory, gdzie jest
odwołanie do fabryki Saxona, która faktycznie przesłania tą domyślną.
Ale wtedy nie powinnaś dostawać NoClassDefFoundError...
--
Otrzymujesz tę wiadomość, ponieważ subskrybujesz grupę dyskusyjną Google o nazwie "Poznań Java User Group".
Aby zamieszczać posty w tej grupie, wyślij e-mail na adres jug-p...@googlegroups.com.
Aby anulować subskrypcję tej grupy, wyślij e-mail na adres jug-poznan+...@googlegroups.com.
Aby uzyskać więcej informacji, odwiedź tę grupę pod adresem http://groups.google.com/group/jug-poznan?hl=pl.
Wygląda na to, że tajemnicza inna biblioteka używa go bezpośrednio.
Jak pytałem o stack, to pełen, a ta część, której nie podałaś to
właśnie istota problemu -- jadem zajrzyj do środka klasy, która robi
ClassNotFound i zobacz gdzie ona fizycznie używa tego Saxona i do
czego. Pewnie instancjonuje bezpośrednio klasę factory -- to ichni
błąd, trudno.
> Jeśli mam w classpathie: są problemy z systemem, bo nagle inna klasa jest
> używana do parsowania XMLa w innych miejscach.
Z przyczyn podanych przeze mnie i Macieja -- zmienia się domyślne factory.
> Nie mam wpływu na to jak jest tworzony TransformerFactory, jest to robione
> wewnątrz zewnętrznej biblioteki.
1. Możesz więc zrobić tak: hack na bibliotekę (statycznie zaaplikowany
aspekt na samą bibliotekę lub jej przekompilowanie jeśli masz źródła).
Rezultat: spójnie wszędzie będzie używany ten sam parser.
2. Zrobić adapter z API Saxona tak, jak napisał Leszek i tam
przekierować na domyślny parser systemowy. Rezultat: jak wyżej, tylko
w inny sposób.
3. Wywalić META-INF/services z saxon.jar. Rezultat: będziesz miała dwa
parsery pewnie w runtime, ale jeśli to nikogo nie boli, to nie ma
problemu.
4. Używać saxona globalnie. Rezultat: powinno być ok. Saxon jest dosyć
dobry i w miarę szybki.
D.
Pozdrawiam,
Tomek
W dniu 23 lutego 2011 13:47 użytkownik Dawid Weiss
<dawid...@cs.put.poznan.pl> napisał:
"Kod, który potrzebuje Saxona się nigdy nie wykonuje."
Jeśli jest tak, jak piszesz, to dość ciekawe. Nie pamiętam jak to
jest, ale class name resolution jest chyba odroczony jeśli to jest
wywołanie z kodu (to można łatwo sprawdzić, jeśli ktoś ma czas --
hint, hint :), więc ta klasa ma albo pole, albo statyczny inicjalizer,
albo hierarchię dziedziczenia związaną z saxonem. Nie możesz rozumiem
powiedzieć co to? Na priva nawet? :)
D.
2011/2/23 Tomek Matynia <tomek....@gmail.com>:
> "Kod, który potrzebuje Saxona się nigdy nie wykonuje."
>
> (...) więc ta klasa ma albo pole, albo statyczny inicjalizer,
> albo hierarchię dziedziczenia związaną z saxonem.
Na to właśnie wygląda. Klasa może nie być instancjonowana, jednak
jeśli jest ładowana, to błąd właśnie tam może wystąpić.
Pozdrawiam,
Tomek
W dniu 23 lutego 2011 14:22 użytkownik Dawid Weiss
Tylko czy przypadkiem w takim razie stacktrace, o którym pisałaś
wcześniej nie był z innego miejsca w kodzie? Nie widzę tutaj wywołania
metody Class.forName(String)?
PS. Standardowa implementacja TransformerFactory to
javax.xml.transform.sax.SAXTransformerFactory. Możesz śmiało ustawić w
pliku usługi tę implementację podając nazwę w/w. klasy w jego treści
(i tyle).
-- m.
2011/2/23 Ula K. <ukr...@gmail.com>:
> Moge powiedzieć.
> Chodzi o project Pentaho Data Integration, aka Kettle, a konkretnie klasa
> org.pentaho.di.job.entries.xslt.JobEntryXSLT.
>
> Sprawdziłam source code i jest bezczelne wołanie konstruktora:
> transformer = new net.sf.saxon.TransformerFactoryImpl();
No tak... i nic dziwnego skąd NoClassDefError.
Tylko czy przypadkiem w takim razie stacktrace, o którym pisałaś
wcześniej nie był z innego miejsca w kodzie? Nie widzę tutaj wywołania
metody Class.forName(String)?
PS. Standardowa implementacja TransformerFactory to
javax.xml.transform.sax.SAXTransformerFactory. Możesz śmiało ustawić w
pliku usługi tę implementację podając nazwę w/w. klasy w jego treści
(i tyle).
-- m.
--
Maciej Biłas
maciej at inszy dot org
--
Otrzymujesz tę wiadomość, ponieważ subskrybujesz grupę dyskusyjną Google o nazwie "Poznań Java User Group".
Aby zamieszczać posty w tej grupie, wyślij e-mail na adres jug-p...@googlegroups.com.
Aby anulować subskrypcję tej grupy, wyślij e-mail na adres jug-poznan+...@googlegroups.com.
Aby uzyskać więcej informacji, odwiedź tę grupę pod adresem http://groups.google.com/group/jug-poznan?hl=pl.
To nie jest prawda. import jest klauzulą kompilatora (języka), a nie
bytecode'u. Referencje do konkretnych klas znajdują się w constant
pool w klasie i w zasadzie nie są używane dopóki nie są wykonywane.
Możesz sprawdzić: uruchom sobie klasę z załącznika przez
java -cp test.jar test.A
Kod tej klasy odwołuje się do czegoś, czego nie ma, a wygląda tak:
package test;
public class A {
public static void main(String [] args) {
System.out.println("Hello.");
}
public void deref() {
new B();
}
}
Dopóki nie wywołasz deref (i dopóki ten konstruktor nie odpali) nie
będzie class not found. Innymi słowy, ta klasa musi jakoś ładować ten
fragment z saxonem (tak jak wspomniałem -- deklaracja, konstruktor lub
statyczny inicjalizer).
Dawid
--
Otrzymujesz tę wiadomość, ponieważ subskrybujesz grupę dyskusyjną Google o nazwie "Poznań Java User Group".
Aby zamieszczać posty w tej grupie, wyślij e-mail na adres jug-p...@googlegroups.com.
Aby anulować subskrypcję tej grupy, wyślij e-mail na adres jug-poznan+...@googlegroups.com.
Aby uzyskać więcej informacji, odwiedź tę grupę pod adresem http://groups.google.com/group/jug-poznan?hl=pl.
no wlasnie nie
a = Class.forName( "A" ); // ok
A obj = (A) a.newInstance(); //ok
a.deref(); // exception
ale za to :
public class A {
public final static Object factory;
static {
factory = new SaxonFactory();
}
}
spowoduje wyjatek juz podczas Class.forName( "A" ) bo samo zaladowanie
klasy powoduje w dalszej kolejnosci inicjalizacje statyczna.
On 2011-02-23 15:31, Ula K. wrote:
Dawid, a spróbuj z innej klasy załadować Twoją klasę test.A uzywając
Class.forName(). Jeśli dobrze Tomka zrozumiałam, to właśnie powoduje
problemy.
no wlasnie nie
a = Class.forName( "A" ); // ok
A obj = (A) a.newInstance(); //ok
a.deref(); // exception
ale za to :
public class A {
public final static Object factory;
static {
factory = new SaxonFactory();
}
}
spowoduje wyjatek juz podczas Class.forName( "A" ) bo samo zaladowanie klasy powoduje w dalszej kolejnosci inicjalizacje statyczna.
--
--
http://www.koders.com/java/fid59E5F44DAC70E7215C7FEC821199443FDEA69B5E.aspx?s=ConstEntry
pytanie czy to ta sama wersja, ale jesli tak to instrukcja w linii 288
nie musi byc wykonywana jesli instancja JobEntryXSLT jest odpowiednio
"skonfigurowana".
W sumie odpisywałem w tym samym momencie, kiedy Ula wysłała kod
źródłowy. Chodziło mi o inny przypadek, tak z głowy o coś takiego:
public class A {
public static String TEST = "test";
public static B TEST2 = new B();
}
W przypadku odwołania do A.TEST, a przy braku B na classpath powinien
wystąpić właśnie ten błąd. Ale to tak jak piszę -- zupełnie inny
przypadek.
Pozdrawiam,
Tomek
nie w przypadku wywolania A.TEST tylko juz w momencie ladowania klasy A.
Klasa ladowana jest inicjalizowana to znaczy:
- tworzone sa zmienne statyczne
- uruchamiane sa bloki kodu static {}
dowod:
public class A {
private final static B BINSTANCE = new B();
public static void main( String[] args ) {
// nothing here
}
public void hello() {
System.out.println( "Hello." );
}
}
D:\mp3\Flogging Molly>java A
Exception in thread "main" java.lang.NoClassDefFoundError: B
at A.<clinit>(A.java:2)
Caused by: java.lang.ClassNotFoundException: B
at java.net.URLClassLoader$1.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
... 1 more
Could not find the main class: A. Program will exit.
PS. prosze zignorowac mp3/Flogging Molly :)))
Niestety przedstawiony kod ma się nijak do tego co napisałeś nad nim
:) Tworzenie instancji to nie to samo co ładowanie klasy.
Pozdrawiam
Artur
Pozdrawiam,
Tomek
W dniu 23 lutego 2011 16:12 użytkownik Leszek Gawron
<lga...@mobilebox.pl> napisał:
> On 2011-02-23 16:07, Tomek Matynia wrote:
>>
>> Rzeczywiście w przypadku konstruktora jest tak jak piszesz, zgadzam się.
>>
>> W sumie odpisywałem w tym samym momencie, kiedy Ula wysłała kod
>> źródłowy. Chodziło mi o inny przypadek, tak z głowy o coś takiego:
>>
>> public class A {
>> public static String TEST = "test";
>> public static B TEST2 = new B();
>> }
>>
>> W przypadku odwołania do A.TEST, a przy braku B na classpath powinien
>> wystąpić właśnie ten błąd. Ale to tak jak piszę -- zupełnie inny
a gdzie ja tutaj tworze instancje klasy A?
odpowiadalem na :
> public class A {
> public static String TEST = "test";
> public static B TEST2 = new B();
> }
>
> W przypadku odwo�ania do A.TEST, a przy braku B na classpath powinien
> wyst�pi� w�a�nie ten b��d. Ale to tak jak pisz� -- zupe�nie inny
> przypadek.
>
to jest prawdziwa teza wynikajaca z falszywego zalozenia. Blad powoduje
nie odwolanie A.TEST tylko zaladowanie klasy A, ktora posiada STATYCZNE
POLE typu B, ktora to klasa B nie jest dostepna.
PS. this is fun :)
Pozdrawiam,
Tomek
W dniu 23 lutego 2011 16:17 użytkownik Tomek Matynia
<tomek....@gmail.com> napisał:
Nigdzie. Tworzona jest natomiast instancja klasy B, ponieważ pole
statyczne jest inicjalizowane w momencie odwołania do statycznej
metody main().
egzaktly, wszyscy rozumieja, skonczmy podw�tek.
Ula, masz tego wiecej? Jak widzisz nar�d sie nudzi :)
--
Urszula Krukar
ukr...@gmail.com
nie w przypadku wywolania A.TEST tylko juz w momencie ladowania klasy A. Klasa ladowana jest inicjalizowana to znaczy:
- tworzone sa zmienne statyczne
- uruchamiane sa bloki kodu static {}
No chyba cały czas czegoś nie widzę, czemu nie można zrobić tego tak:
test1:
((ReferencesSaxon1) Class.forName("saxons.ReferencesSaxon1").newInstance())
.doCall(args.length > 0);
test2:
((ReferencesSaxon2) Class.forName("saxons.ReferencesSaxon2").newInstance())
.doCall(args.length > 0);
pzdr miluch
W dniu 23 lutego 2011 19:30 użytkownik Dawid Weiss
<dawid...@cs.put.poznan.pl> napisał:
>
ďż˝
nie w przypadku wywolania A.TEST tylko juz w momencie ladowania klasy A. Klasa ladowana jest inicjalizowana to znaczy:
- tworzone sa zmienne statyczne
- uruchamiane sa bloki kodu static {}
Oj tam zaraz. To co poda�am to by� najg��bszy podwyjatek.Sprawa jest nieco bardziej skomplikowana je�li si� u�ywa forName(String, boolean, ClassLoader) bo wtedy mo�na j� za�adowa� i nie inicjalizowa� :)�
Kiedy� te� wspomina�em, �e w zasadzie nie ma "tworzenia zmiennych statycznych" -- bloki kodu b�d�ce przypisaniem do zmiennych statycznych l�duj� w metodzie clinit klasy razem z tym, co jest w static {...} (kompilator ��czy wszystkie deklaracje w jedn�, w kolejno�ci wyst�pie�). Dlatego ma znaczenie je�li kto� wo�a z takich blok�w (lub przypisa�) inne metody statyczne klasy, bo mog� zobaczy� niezainicjalizowane pola final, s� zale�ne od kolejno�ci deklaracji itd.
Co do oryginalnego problemu Uli, to jest dosy� fascynuj�cy, bo ta klasa powinna si� za�adowa�, a dopiero wywo�anie metody execute() waln�� wyj�tek braku Saxona (i zgodnie z tym, co powiedzia� Leszek -- je�li jest mo�liwo�� konfiguracji, to mo�na to wywo�anie pomin�� i nie powinno by� class not found!).
Ula nie przes�a�a pe�nego stack trace'a (z podwyj�tkami), wi�c pewnie co� ukrywa :)
-- Urszula Krukar ukr...@gmail.com
Oj tam zaraz. To co podałam to był najgłębszy podwyjatek.
Co do oryginalnego problemu: ten kod jest uruchamiany na JBossie w ramach webapp. Tam hierarchia classloaderów jest dosyć skomplikowana, to pewnie stanowi jakieś rozwiązanie tej zagadki.
to już powoduje (przynajmniej u mnie) załadowanie klasy i wyjątek
a dla test1 teoretycznie załadowanie klasy i tak nie powoduje wyjątku.
U mnie StackTrace są identyczne niezależnie od tego czy mam interfejs czy nie.
pzdr miluch
W dniu 23 lutego 2011 20:09 użytkownik Dawid Weiss
Dawid--
Otrzymujesz tę wiadomość, ponieważ subskrybujesz grupę dyskusyjną Google o nazwie „Poznań Java User Group”.
Aby zamieszczać posty w tej grupie, wyślij e-mail na adres jug-p...@googlegroups.com.
Aby anulować subskrypcję tej grupy, wyślij e-mail na adres jug-poznan+...@googlegroups.com.
Aby uzyskać więcej informacji, odwiedź tę grupę pod adresem http://groups.google.com/group/jug-poznan?hl=pl.
To nie jest chyba pełen wyjątek, Ula -- dlatego nie widać gdzie dokładnie
idzie ścieżka wywołań... a przynajmniej tak mi się wydaje... Ostatnie,
co widać bierze się stąd:
w linii 121-125 jest:
} catch (Throwable e) {
String message = "Unable to read Job Entry copy info from XML node :
" + e.toString();
throw new KettleXMLException(message, e);
}
PluginRegistry, który rzuca wyjątek wywalany dalej stąd robi zaś:
catch (Throwable e)
{
e.printStackTrace();
throw new KettlePluginException(BaseMessages.getString(PKG,
"PluginRegistry.RuntimeError.UnExpectedErrorLoadingClass.PLUGINREGISTRY007"),
e);
}
Ech... pamiętacie wykład o debugowaniu? Przekleństwo
e.printStackTrace! W każdym razie wyjątek zagnieżdżony niby wygląda
tak:
Caused by: java.lang.NoClassDefFoundError: net/sf/saxon/TransformerFactoryImpl
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:169)
at org.pentaho.di.core.plugins.PluginRegistry.loadClass(PluginRegistry.java:297)
... 35 more
Caused by: java.lang.ClassNotFoundException: net.sf.saxon.TransformerFactoryImpl
at java.net.URLClassLoader$1.run(URLClassLoader.java:200)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:188)
at java.lang.ClassLoader.loadClass(ClassLoader.java:303)
at java.lang.ClassLoader.loadClass(ClassLoader.java:248)
at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:316)
... 38 more
co by jednak sugerowało, że gdzieś tam w środku coś tego saxona
potrzebuje w trakcie ładowania... ale co to jest -- doprawdy nie wiem
i nie wiem dlaczego nie widać żadnej metody <clinit> w tym stosie,
choć powinno być.
Ciekawy problem, z chęcią bym się pobawił. Można jeszcze pobadać, np. przez:
-XX:+TraceClassLoading
i zobaczyć jakie klasy się ładują po kolei, albo sprawdzić czy to na
pewno ta klasa, o której była mowa się wtedy ładuje. Bez żywego kodu
to jest zgadywanie, ale jeśli mi udostępnisz remote desktop... :D
D.
--
Otrzymujesz tę wiadomość, ponieważ subskrybujesz grupę dyskusyjną Google o nazwie "Poznań Java User Group".
Aby zamieszczać posty w tej grupie, wyślij e-mail na adres jug-p...@googlegroups.com.
Aby anulować subskrypcję tej grupy, wyślij e-mail na adres jug-poznan+...@googlegroups.com.
Aby uzyskać więcej informacji, odwiedź tę grupę pod adresem http://groups.google.com/group/jug-poznan?hl=pl.
Zrobimy repetę wykładu za jakiś czas, to przypomnę :)
Dawid
Okazuje się, że jest to bardzo ciekawy przypadek, którego szczerze
mówiąc w ogóle nie brałem pod uwagę, a który mnie bardzo zaskoczył i
czegoś nowego nauczył. A więc jest tak.
1. Klasą, która powoduje oryginalny wyjątek u Uli jest JobEntryXSLT i
faktycznie w niej referencja do Saxona:
factory = new net.sf.saxon.TransformerFactoryImpl();
2. Powyższy kod nigdy nie jest wykonywany, ale powoduje
ClassNotFoundError w forName().
3. Te przykłady, które podawałem również są poprawne (i działają, co
widzieliśmy).
Czym owe przypadki się różnią? Otóż różnią się tym, że JVM musi
przeprowadzić proces weryfikacji kodu, między innymi zgodności
przypisań. Ten fragment w oryginale klasy JobEntryXSLT jest taki:
// Create transformer factory
TransformerFactory factory = TransformerFactory.newInstance();
if (xsltfactory.equals(FACTORY_SAXON))
{
// TODO: replace the active line with this code and
// forName() will pass just fine
// Object temporary = new net.sf.saxon.TransformerFactoryImpl();
factory = new net.sf.saxon.TransformerFactoryImpl();
}
Ponieważ TransformerFactory to interfejs, więc JVM chce sprawdzić, czy
TransformerFactoryImpl ten interfejs na pewno implementuje. To z kolei
powoduje próbę załadowania klasy (bez jej inicjalizacji nawet) i wtedy
wszystko idzie w maliny. Można to sprawdzić, jeśli się zrobi taki
"stub" klasy TransformerFactoryImpl, który nie implementuje
TransformerFactory... wynik jest taki (Class.forName, bez żadnej
inicjalizacji!)
Exception in thread "main" java.lang.VerifyError: (class:
org/pentaho/di/job/entries/xslt/JobEntryXSLT, method:
processOneXMLFile signature:
(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lorg/pentaho/di/core/Result;Lorg/pentaho/di/job/Job;)Z)
Incompatible object argument for function call
Tadaaa.
Uwaga, teraz najlepsze: zmiana powyższego fragmentu na Object lub typ
dokładny powoduje, że weryfikacja przechodzi bez ładowania klasy
TransformerFactoryImpl (a więc przechodzi bez classnotfound elegancko
tak, jak byśmy tego oczekiwali). Podobnie jest, gdy się doda cast
explicite na TransformerFactory:
factory = (TransformerFactory) new net.sf.saxon.TransformerFactoryImpl();
i znów -- wszystko ładnie się ładuje i przechodzi.
Fajne, nie? :)
Żeby być kompletnym sprawdziłem w JVM spec jak dokładnie przebiega
ładowanie klas. Cytat z p. 2.17.3:
"For example, an implementation may choose to resolve each symbolic
reference in a class or interface individually, only when it is used
(lazy or late resolution), or to resolve them all at once, for
example, while the class is being verified (static resolution). This
means that the resolution process may continue, in some
implementations, after a class or interface has been initialized"
Innymi słowy reguły nie ma: może być albo lazy, albo eager
initialization. Sprawdziłem na JRockit, HotSpocie i J9 IBMa i wszędzie
było identycznie, tzn. weryfikacja przypisania powoduje class not
found, jeśli typy mogą być uzgodnione bez znajomości klasy docelowej,
wszystko jest ok.
Ciekawy, pouczający przykład. Jeśli by mi tylko teraz ktoś zapłacił za
ten czas, który mi to zajęło, argh.
Pozdrowienia,
Dawid
--
Otrzymujesz tę wiadomość, ponieważ subskrybujesz grupę dyskusyjną Google o nazwie "Poznań Java User Group".
Aby zamieszczać posty w tej grupie, wyślij e-mail na adres jug-p...@googlegroups.com.
Aby anulować subskrypcję tej grupy, wyślij e-mail na adres jug-poznan+...@googlegroups.com.
Aby uzyskać więcej informacji, odwiedź tę grupę pod adresem http://groups.google.com/group/jug-poznan?hl=pl.
Raz tylko miałem przyjemność tzn nieprzyjemność działania na JBOSS i
tam zachowanie związane z classloadingiem jest albo słabo
udokumentowane albo po prostu nie działa jak napisane. Poza tym wiem
że różnie to działało w zależnośći od wersji JBossa.
Kolejna rzecz którą trzeba wziąść pod uwage to jest to, że nawet jeśli
wiesz dokładnie który classloader zacznie czytać to może on mieć do
wyboru parę plików META-INF/services/* - czyli przykładowo wrzuć do
WEB-INF/lib aplikacji webowej oba jary: saxon i xalan.
Wtedy która implementacja zostanie zaczytana ?
pzdr miluch
W dniu 25 lutego 2011 13:19 użytkownik Artur Keska
<artur...@gmail.com> napisał:
Witam
Raz tylko miałem przyjemność tzn nieprzyjemność działania na JBOSS i
tam zachowanie związane z classloadingiem jest albo słabo
udokumentowane albo po prostu nie działa jak napisane. Poza tym wiem
że różnie to działało w zależnośći od wersji JBossa.
Kolejna rzecz którą trzeba wziąść pod uwage to jest to, że nawet jeśli
wiesz dokładnie który classloader zacznie czytać to może on mieć do
wyboru parę plików META-INF/services/* - czyli przykładowo wrzuć do
WEB-INF/lib aplikacji webowej oba jary: saxon i xalan.
Wtedy która implementacja zostanie zaczytana ?
Nie ma możliwości stwierdzenia, bo to zależy od kolejności, w jakiej
system plików zwróci te JARy do classloadera aplikacji webowej. Dla
systemów plików, które mają alfabetyczny iterator kolejność będzie
stała i przewidywalna :)
To jednak jest nie tyle błąd systemowy, ile logiczny, bo masz dwóch
dostawców tego samego serwisu w aplikacji; pytanie, czy to ma sens.
Dawid
Dawid
log(Thread.currentThread().getContextClassLoader().getResource("META-INF/...").toString())
powinien być URI do pierwszego pasującego zasobu (można też
przeiterować po wszystkich i dowiedzieć się ile w ogóle ich jest i
skąd). Trudno mi powiedzieć jak robi resource lookup JBoss, bo nigdy
go nie używałem, ale powinien być zgodny z servlet API (czyli izolować
aplikacje webowe i robić inwersję poszukiwania -- najpierw WARa i jego
zasoby, później zasoby współdzielone).
Dawid
2011/2/25 Artur Keska <artur...@gmail.com>:
W dniu 25 lutego 2011 14:44 użytkownik Artur Keska
<artur...@gmail.com> napisał:
> W dniu 25 lutego 2011 14:09 użytkownik Dawid Weiss
> <dawid...@cs.put.poznan.pl> napisał:
>>
>> >> WEB-INF/lib aplikacji webowej oba jary: saxon i xalan.
>> >> Wtedy która implementacja zostanie zaczytana ?
>>
>> Nie ma możliwości stwierdzenia, bo to zależy od kolejności, w jakiej
>> system plików zwróci te JARy do classloadera aplikacji webowej. Dla
>> systemów plików, które mają alfabetyczny iterator kolejność będzie
>> stała i przewidywalna :)
>>
>> To jednak jest nie tyle błąd systemowy, ile logiczny, bo masz dwóch
>> dostawców tego samego serwisu w aplikacji; pytanie, czy to ma sens.
>>
>
> No i właśnie pytanie tylko czy gdzieś jeszcze jest services w którym z jarów
> (chyba że coś przeoczyłem w dyskusji - sporo tego ;-) )?
>
Jak rozumiem jeden jest w saxon.jar a drugi to ten stworzony przez
Ulę: siedzi w WEB-INF/classes
(zgodnie z jej opisem dodała dwa pliki: jeden wyląduje w
WEB-INF/classes a drugi bezpośrednio w META-INF wara - by trzeba by
sprawdzić czy ten plik też nie zostanie wzięty pod uwagę przez
classloader) .
pzdr miluch
W dniu 25 lutego 2011 14:09 użytkownik Dawid Weiss
<dawid...@cs.put.poznan.pl> napisał:
>>> WEB-INF/lib aplikacji webowej oba jary: saxon i xalan.
>>> Wtedy która implementacja zostanie zaczytana ?
>
> Nie ma możliwości stwierdzenia, bo to zależy od kolejności, w jakiej
> system plików zwróci te JARy do classloadera aplikacji webowej. Dla
> systemów plików, które mają alfabetyczny iterator kolejność będzie
> stała i przewidywalna :)
Jesteś pewien że na czymś takim można polegać ? W apliacji standalone
kolejność jarów na classpath ma znacznie - znaleziony zostnanie
pierwszy w kolejności.
Jednak gdy działamy w kontenerze, np JBOSS to classloader contextowy
został (który zostanie wybrany do wyszukania pliku
META-INF/services/*) został napisany przez vendora i to on sobie
określił jaka będzie kolejność.
> To jednak jest nie tyle błąd systemowy, ile logiczny, bo masz dwóch
> dostawców tego samego serwisu w aplikacji; pytanie, czy to ma sens.
Moim zdaniem nie ma: dlatego w moim problemie wywaliłem plik
META-INF/services/* którego nie chciałem. Minus jest taki że taka
zmiana "psuje" tzn moddyfikuje artefakt, a to ma znaczenie gdy
ciągniesz jary z repozytorium mavena.
pzdr miluch
> Dawid
Witam
W dniu 25 lutego 2011 14:09 użytkownik Dawid Weiss
<dawid...@cs.put.poznan.pl> napisał:
>>> WEB-INF/lib aplikacji webowej oba jary: saxon i xalan.Jesteś pewien że na czymś takim można polegać ? W apliacji standalone
>>> Wtedy która implementacja zostanie zaczytana ?
>
> Nie ma możliwości stwierdzenia, bo to zależy od kolejności, w jakiej
> system plików zwróci te JARy do classloadera aplikacji webowej. Dla
> systemów plików, które mają alfabetyczny iterator kolejność będzie
> stała i przewidywalna :)
kolejność jarów na classpath ma znacznie - znaleziony zostnanie
pierwszy w kolejności.
Jednak gdy działamy w kontenerze, np JBOSS to classloader contextowy
został (który zostanie wybrany do wyszukania pliku
META-INF/services/*) został napisany przez vendora i to on sobie
określił jaka będzie kolejność.
Moim zdaniem nie ma: dlatego w moim problemie wywaliłem plik
> To jednak jest nie tyle błąd systemowy, ile logiczny, bo masz dwóch
> dostawców tego samego serwisu w aplikacji; pytanie, czy to ma sens.
META-INF/services/* którego nie chciałem. Minus jest taki że taka
zmiana "psuje" tzn moddyfikuje artefakt, a to ma znaczenie gdy
ciągniesz jary z repozytorium mavena.
Zawsze można sprawdzić skąd go bierze przez (w aplikacji webowej):
log(Thread.currentThread().getContextClassLoader().getResource("META-INF/...").toString())
powinien być URI do pierwszego pasującego zasobu (można też
przeiterować po wszystkich i dowiedzieć się ile w ogóle ich jest i
skąd). Trudno mi powiedzieć jak robi resource lookup JBoss, bo nigdy
go nie używałem, ale powinien być zgodny z servlet API (czyli izolować
aplikacje webowe i robić inwersję poszukiwania -- najpierw WARa i jego
zasoby, później zasoby współdzielone).
Chyba nie do końca rozumiem co masz na myśli ? Przed którymi jarami ?
pzdr miluch
W przypadku kontenerów aplikacji kolejność przeszukiwania klas jest
określona w specyfikacji (miałeś to na zajęciach ze mną, przypominam
więc tylko). Jeśli kontener ma inne rozszerzenia, to są one dodatkiem
(niezgodnym ze specyfikacją) i powinny być określone w jego
dokumentacji.
Dawid
Dzięki za informację. Ale zajęc z Tobą na ten temat nie miałem -
chodziłem tylko na przedmiot na którym była CORBA, głownie CORBA :)
Z tego co pamiętam to specyfikacja mówi o tym że WEB-INF/classes są
ładowane przed WEB-INF/lib ale wątpię aby zdefiniowany był porządek
ładowania klas pośród tych zawartych w jarach w WEB-INF/lib.
pzdr miluch
W dniu 25 lutego 2011 16:01 użytkownik Dawid Weiss
<dawid...@cs.put.poznan.pl> napisał:
Ula, podaj to property które wymusza service lookup, bo ja też nie
pamiętam, a to chyba utnie dyskusję...
D.
2011/2/25 jmilk...@gmail.com <jmilk...@gmail.com>:
-- Z powazaniem / Best Regards / Mit freundlichen Gruessen / Meilleures salutations Pawel Debski Managing Consultant, e-mail: PDe...@econsulting.pl Tel. 0048-504-766-316, 0048-22-730-2794 To join us: cv (o) econsulting (!) pl To contract us: salesteam (o) econsulting (!) pl