Fórum Root.cz

Hlavní témata => Vývoj => Téma založeno: A. F. 18. 07. 2018, 04:53:28

Název: Dvě stejné třídy různých verzí (Java)
Přispěvatel: A. F. 18. 07. 2018, 04:53:28
Ahoj.

Něco málo jsem slyšel o class loaderech v javě. Ale nemám větší zkušenosti. Zajímalo by mě, zda zvládnou následující úlohu:

Mám třídu org.vendor.App z balíčku app-1.2.3.jar a pak jinou implementaci třídy org.vendor.App z balíčku app-1.2.1.jar. Je možné, nějakým způsobem načíst a vytvořit instance těchto dvou tříd tak, abych s nimi mohl pracovat najednou v jedné metodě?
Název: Re:Dvě stejné třídy různých verzí (Java)
Přispěvatel: Starous 18. 07. 2018, 06:52:03
ano lze toho dosahnout nekolika zpusoby. Pokud používáš maven tak napr maven-shade-plugin umi vzit knihovnu a zmenit ji package tak aby se netloukli. Dalsi moznost je izolace classloaderu tak to delaji napr aplikacni servery - kazdou nacist jinym classloaderem - ale to pak je nebudes moc pouzit ze stejné třídy. Mozna jedine nejak pres reflexi.
Název: Re:Dvě stejné třídy různých verzí (Java)
Přispěvatel: Cronin 18. 07. 2018, 06:58:07
Nijako normálne.

Nejako hodne šialene by to išlo cez reflection, ale musel by si obísť nielen štandardný spôsob načítavania a inštancionovania objektov, čo vlastne postup s použitím reflection robí by definition, ale naviac aj spôsob vyhľadania samotných tried. Ďalšie problémy môžu spôsobiť potenciálne konfliktné závislosti tých tried.

Pravdepodobne sa snažíš riešiť problém hodne zlým spôsobom. Buďto si použil java triedu tam, kde mali byť použité aplikačné údaje, alebo si mal na implementáciu dvoch verzií algoritmu použiť vhodný návrhový vzor, napr. stratégiu. Ale sa kompletne mýlim, všetko robíš správne, a skutočne máš problém, kde potrebuješ použiť naraz dve inštancie vzíduvšie z triedy rovnakého FQN ale inej verzie. V tom prípade potrebuješ niekoho, kto skutočne rozumie JVM internals a rýchlo pretransformuje aktuálny problém na jeden z problémov, ktoré som naznačil vyššie, aby niekto bez takých hlbokých znalostí mohol využiť na riešenie vzniknuvšieho štandarného problému štandardné postupy.
Název: Re:Dvě stejné třídy různých verzí (Java)
Přispěvatel: Cronin 18. 07. 2018, 07:01:29
Ale sa kompletne mýlim, ...

*Alebo ...
Název: Re:Dvě stejné třídy různých verzí (Java)
Přispěvatel: ava 18. 07. 2018, 08:54:23
Odpověď máš tady: https://stackoverflow.com/questions/11759414/java-how-to-load-different-versions-of-the-same-class

Croninovy příspěvky ohledně reflection si vymaž z hlavy, nedávají smysl.
Název: Re:Dvě stejné třídy různých verzí (Java)
Přispěvatel: zdenek henek nereg. 18. 07. 2018, 09:34:24
Ahoj.

Něco málo jsem slyšel o class loaderech v javě. Ale nemám větší zkušenosti. Zajímalo by mě, zda zvládnou následující úlohu:

Mám třídu org.vendor.App z balíčku app-1.2.3.jar a pak jinou implementaci třídy org.vendor.App z balíčku app-1.2.1.jar. Je možné, nějakým způsobem načíst a vytvořit instance těchto dvou tříd tak, abych s nimi mohl pracovat najednou v jedné metodě?

Urcite to jde jak je popsane v tom linku na stackoverflow, ale urcite to tak musis delat? Neni lepsi cesta? Jestli je to jen hack pred releasem a pak to predelas, tak ok, ale jestli to je styl, ktery chces prosazovat, tak se
ujisti, ze nikdo z kolegu nevi kde bydlis. Nemuseli by pak cteni a udzbu takoveho kodu psychicky unest a mohli by te chtit navstivit ...
Název: Re:Dvě stejné třídy různých verzí (Java)
Přispěvatel: Filip Jirsák 18. 07. 2018, 09:43:26
Zaměřil bych se na to, jestli a proč zrovna tohle potřebujete. Že máte závislost na dvou různých knihovnách a ty tranzitivně závisí na třetí knihovně, ale každá v jiné verzi (které jsou vzájemně nekompatibilní), to se stává. Ale že potřebujete obě dvě ty třídy v jedné metodě, to je opravdu divné.

Pak samozřejmě záleží na tom, co si můžete dovolit s těmi org.vendor.App dělat. Pokud od nich máte zdrojáky a můžete jednu verzi přesunout do jiného package, je to nejjednodušší řešení.

Pokud musíte vzít JARka tak jak jsou, je jediná možnost použít různé classloadery. Vaše třída ovšem bude nahraná jen jedním classloaderem, takže s těmi org.vendor.App nemůžete pracovat přímo, ale jen pomocí nějaké formy odkazů – lepší by bylo pomocí MethodHandle, ale nejsem si jistý, že to půjde, a nebo pomocí reflexe.

Každopádně bych se soustředil spíš na to, jak se tomu použití dvou různých verzí jedné třídy úplně vyhnout, než jak to udělat.
Název: Re:Dvě stejné třídy různých verzí (Java)
Přispěvatel: zdenek henek nereg. 18. 07. 2018, 09:43:46
Ahoj.

Něco málo jsem slyšel o class loaderech v javě. Ale nemám větší zkušenosti. Zajímalo by mě, zda zvládnou následující úlohu:

Mám třídu org.vendor.App z balíčku app-1.2.3.jar a pak jinou implementaci třídy org.vendor.App z balíčku app-1.2.1.jar. Je možné, nějakým způsobem načíst a vytvořit instance těchto dvou tříd tak, abych s nimi mohl pracovat najednou v jedné metodě?

Ciste teoreticky (pokud neni jar obfuscovany) tak by melo byt mozne udelat toto
1. decompiluj tridu
2. zmen package a jmeno tridy
3. proved znovu kompilaci, zabal to do jaru s dostatecne varovnym jmenem
4. uloz do maven repo a pouzivej jen tu tridu (popripade jeji zavislosti z app-1.2.1) a ne cely app-1.2.1.jar
a pak puzivej jen 1.2.3.jar

Timto zamezis existenci dvou trid se stejnym jmenem ve stejnem package.

Neco podobneho jsme delali, kdyz bylo potreba opravit bug v jaru, kde nebylo mozne kontaktovat dodavatele. Nastesti to nebylo obfuscovane a po case jsme se s dodavatelem dohodli na nove verzi jaru, ktery obsahoval i fix bugu.
Název: Re:Dvě stejné třídy různých verzí (Java)
Přispěvatel: Ondra Satai Nekola 18. 07. 2018, 10:13:00
Ahoj.

Něco málo jsem slyšel o class loaderech v javě. Ale nemám větší zkušenosti. Zajímalo by mě, zda zvládnou následující úlohu:

Mám třídu org.vendor.App z balíčku app-1.2.3.jar a pak jinou implementaci třídy org.vendor.App z balíčku app-1.2.1.jar. Je možné, nějakým způsobem načíst a vytvořit instance těchto dvou tříd tak, abych s nimi mohl pracovat najednou v jedné metodě?

Ciste teoreticky (pokud neni jar obfuscovany) tak by melo byt mozne udelat toto
1. decompiluj tridu
2. zmen package a jmeno tridy
3. proved znovu kompilaci, zabal to do jaru s dostatecne varovnym jmenem
4. uloz do maven repo a pouzivej jen tu tridu (popripade jeji zavislosti z app-1.2.1) a ne cely app-1.2.1.jar
a pak puzivej jen 1.2.3.jar

Timto zamezis existenci dvou trid se stejnym jmenem ve stejnem package.

Neco podobneho jsme delali, kdyz bylo potreba opravit bug v jaru, kde nebylo mozne kontaktovat dodavatele. Nastesti to nebylo obfuscovane a po case jsme se s dodavatelem dohodli na nove verzi jaru, ktery obsahoval i fix bugu.

Tohle ti udela maven nebo gradle automagicky, pokud potrebujes. Pluginy k tomu jsou, viz vyse.

(drobne varovani - ne nutne musi fungovat, pokud se do hry dostane Scala - https://www.scala-lang.org/old/sites/default/files/sids/dubochet/Mon,%202010-05-31,%2015:25/Storage%20of%20pickled%20Scala%20signatures%20in%20class%20files.pdf a pochopitelne pokud je ve hre nejaka reflexe je nutne byt obzvlast opatrny)
Název: Re:Dvě stejné třídy různých verzí (Java)
Přispěvatel: Karel 18. 07. 2018, 10:47:36
Odpověď máš tady: https://stackoverflow.com/questions/11759414/java-how-to-load-different-versions-of-the-same-class

Croninovy příspěvky ohledně reflection si vymaž z hlavy, nedávají smysl.

Reflection je potřeba v situaci, kdy musíte použít tu třídu jako typ. Pokud proměnnou nebo parametr metody nadefinujete jako třídu ve verzi 1, pak do ní nejde vložit reference na třídu ve verzi 2. Musíte pak najít společného předka, kupříkladu Object, a na metody použít reflection.

V oblastech, kde se tohle "jedna třída ve více verzích" používá, se to ale obchází tím, že se použije interface. Ten může být nahraný default class loaderem a dokud ho obě verze používají, tak není žádný problém. Do proměnné/parametru typu interface se dají beztrestně použít obě verze té třídy.

Jo a pokud někoho zajímá, kde se to používá (spíše používalo) tak to byly systémy, kde se daly měnit zdrojové kódy za běhu. Kupříkladu Tomcat to možná dosud používá k tomu, aby uměl spustit novou verzi aplikace i bez restartu. Upravil jste třídu a aplikaci řekl, že je nová verze. Ta si ji pak natáhla novým classloaderem a nové instance pak byly už upravené. Samo o sobě to noční můra nebyla, protože se pracovalo s interface. Co už noční můra byla to byl marshalling. Jestli je u moderních VM nějaký pohodlnější mechanismus, to už nevím.
Název: Re:Dvě stejné třídy různých verzí (Java)
Přispěvatel: zdenek henek nereg. 18. 07. 2018, 10:53:40

Tohle ti udela maven nebo gradle automagicky, pokud potrebujes. Pluginy k tomu jsou, viz vyse.

(drobne varovani - ne nutne musi fungovat, pokud se do hry dostane Scala - https://www.scala-lang.org/old/sites/default/files/sids/dubochet/Mon,%202010-05-31,%2015:25/Storage%20of%20pickled%20Scala%20signatures%20in%20class%20files.pdf a pochopitelne pokud je ve hre nejaka reflexe je nutne byt obzvlast opatrny)

maven za me prejmenuje package - zmeni adresar, prejmenuje tridu  a pak to cele zase prelozi?
Název: Re:Dvě stejné třídy různých verzí (Java)
Přispěvatel: Filip Jirsák 18. 07. 2018, 11:01:08
Jo a pokud někoho zajímá, kde se to používá (spíše používalo) tak to byly systémy, kde se daly měnit zdrojové kódy za běhu. Kupříkladu Tomcat to možná dosud používá k tomu, aby uměl spustit novou verzi aplikace i bez restartu.
Tam ale nepracujete s oběma verzemi třídy v jedné metodě najednou. Tomcat prostě používá víc classloaderů, jak je to ve specifikaci Servletů.

Jestli je u moderních VM nějaký pohodlnější mechanismus, to už nevím.
Od Javy 9 k tomuhle slouží moduly ve spolupráci se ServiceLoader.
Název: Re:Dvě stejné třídy různých verzí (Java)
Přispěvatel: Ondra Satai Nekola 18. 07. 2018, 12:18:56

Tohle ti udela maven nebo gradle automagicky, pokud potrebujes. Pluginy k tomu jsou, viz vyse.

(drobne varovani - ne nutne musi fungovat, pokud se do hry dostane Scala - https://www.scala-lang.org/old/sites/default/files/sids/dubochet/Mon,%202010-05-31,%2015:25/Storage%20of%20pickled%20Scala%20signatures%20in%20class%20files.pdf a pochopitelne pokud je ve hre nejaka reflexe je nutne byt obzvlast opatrny)

maven za me prejmenuje package - zmeni adresar, prejmenuje tridu  a pak to cele zase prelozi?

Proc bys potreboval prejmenovat tu tridu?
Název: Re:Dvě stejné třídy různých verzí (Java)
Přispěvatel: Ghhh 18. 07. 2018, 12:47:34

Tohle ti udela maven nebo gradle automagicky, pokud potrebujes. Pluginy k tomu jsou, viz vyse.

(drobne varovani - ne nutne musi fungovat, pokud se do hry dostane Scala - https://www.scala-lang.org/old/sites/default/files/sids/dubochet/Mon,%202010-05-31,%2015:25/Storage%20of%20pickled%20Scala%20signatures%20in%20class%20files.pdf a pochopitelne pokud je ve hre nejaka reflexe je nutne byt obzvlast opatrny)

maven za me prejmenuje package - zmeni adresar, prejmenuje tridu  a pak to cele zase prelozi?

Proc bys potreboval prejmenovat tu tridu?

Ondro, neptej se porad jak male dite :)
Název: Re:Dvě stejné třídy různých verzí (Java)
Přispěvatel: zdenek henek nereg. 18. 07. 2018, 14:39:52

Tohle ti udela maven nebo gradle automagicky, pokud potrebujes. Pluginy k tomu jsou, viz vyse.

(drobne varovani - ne nutne musi fungovat, pokud se do hry dostane Scala - https://www.scala-lang.org/old/sites/default/files/sids/dubochet/Mon,%202010-05-31,%2015:25/Storage%20of%20pickled%20Scala%20signatures%20in%20class%20files.pdf a pochopitelne pokud je ve hre nejaka reflexe je nutne byt obzvlast opatrny)

maven za me prejmenuje package - zmeni adresar, prejmenuje tridu  a pak to cele zase prelozi?

Proc bys potreboval prejmenovat tu tridu?

Pokud se maji obe pozivat v jedne tride, tak bych ji radeji mel pojmenovanou jinak.
Název: Re:Dvě stejné třídy různých verzí (Java)
Přispěvatel: Ondra Satai Nekola 18. 07. 2018, 14:47:18

Tohle ti udela maven nebo gradle automagicky, pokud potrebujes. Pluginy k tomu jsou, viz vyse.

(drobne varovani - ne nutne musi fungovat, pokud se do hry dostane Scala - https://www.scala-lang.org/old/sites/default/files/sids/dubochet/Mon,%202010-05-31,%2015:25/Storage%20of%20pickled%20Scala%20signatures%20in%20class%20files.pdf a pochopitelne pokud je ve hre nejaka reflexe je nutne byt obzvlast opatrny)

maven za me prejmenuje package - zmeni adresar, prejmenuje tridu  a pak to cele zase prelozi?

Proc bys potreboval prejmenovat tu tridu?

Pokud se maji obe pozivat v jedne tride, tak bych ji radeji mel pojmenovanou jinak.

Rekneme, ze tohle je spis za bonusove body, potreba to neni...
Název: Re:Dvě stejné třídy různých verzí (Java)
Přispěvatel: BoneFlute 18. 07. 2018, 17:17:08
Tohle je výhoda dynamických jazyků (Python, Javascript). Tam je ta třída first-class citizen.
Název: Re:Dvě stejné třídy různých verzí (Java)
Přispěvatel: Ondrej Nemecek 19. 07. 2018, 00:48:07
Nikdy jsem to nezkoušel, ale řekl bych, že pokud instancuju pomocí dvou různých classloaderů a reflexe, tak můžu získat docela snadno dvě instance totožné třídy ze dvou různých jarek, tedy ve dvou verzích. Pak záleží co s nimi chci dělat dál. Pomocí reflexe můžu dělat zase asi cokoli.

Použití si dokážu představit při potřebě přeuložit serializovaná data v jiné verzi třídy. Ale možná existuje na uvedený případ nějaký vhodnější kanonický postup. Ale častěji se stejně serializuje do nějakého neutrálního formátu, třeba xml, takže to není moc často potřeba.
Název: Re:Dvě stejné třídy různých verzí (Java)
Přispěvatel: ava 19. 07. 2018, 07:38:22
Odpověď máš tady: https://stackoverflow.com/questions/11759414/java-how-to-load-different-versions-of-the-same-class

Croninovy příspěvky ohledně reflection si vymaž z hlavy, nedávají smysl.

Reflection je potřeba v situaci, kdy musíte použít tu třídu jako typ. Pokud proměnnou nebo parametr metody nadefinujete jako třídu ve verzi 1, pak do ní nejde vložit reference na třídu ve verzi 2. Musíte pak najít společného předka, kupříkladu Object, a na metody použít reflection.

V oblastech, kde se tohle "jedna třída ve více verzích" používá, se to ale obchází tím, že se použije interface. Ten může být nahraný default class loaderem a dokud ho obě verze používají, tak není žádný problém. Do proměnné/parametru typu interface se dají beztrestně použít obě verze té třídy.

Jo a pokud někoho zajímá, kde se to používá (spíše používalo) tak to byly systémy, kde se daly měnit zdrojové kódy za běhu. Kupříkladu Tomcat to možná dosud používá k tomu, aby uměl spustit novou verzi aplikace i bez restartu. Upravil jste třídu a aplikaci řekl, že je nová verze. Ta si ji pak natáhla novým classloaderem a nové instance pak byly už upravené. Samo o sobě to noční můra nebyla, protože se pracovalo s interface. Co už noční můra byla to byl marshalling. Jestli je u moderních VM nějaký pohodlnější mechanismus, to už nevím.

Aha, OK, díky za opravu a vysvětlení.

Pro zajímavost, kdysi jsem dělal ve Smalltalku. Tam se zcela běžně dělají úpravy tříd za běhu, je ta to nejsamozřejmější věc na světě, protože celé IDE je vlastně napsané samo v sobě a běží samo v sobě a vyvíjí se tím, že to IDE v tom IDE člověk za běhu edituje. Může vám to připadat hrozné, ale v praxi je to neuvěřitelně praktické.

Změny tříd jsou v zásadě dvojí:

1) Buď se mění pouze metody (ať už třídní nebo instanční), to vlastně neznamená změnu třídy jako takové. Reference na instanci té třídy dále fungují, a nové metody jsou okamžitě k dispozici (takže mám třeba otevřené okno debuggeru, které mi otevřel failnutý assert v testu, dostepoval jsem se k podezřelé metodě, tak tu metodu hnedka upravím aniž bych debugger zavíral, zkusím z debuggeru zavolat metodu znova, funguje to, hotovo. Edit-compile-run je překonaný mýtus :-)

2) Upravím definici třídy, což v praxi skoro vždy znamená, že jsem přidal nebo ubral instanční proměnné. To už je problém, vzniká mi nová třída. Stane se to, že např. třída Foo se přejmenuje na ObsoleteFoo, existující reference na Foo teď ukazují na ObsoleteFoo, a vytváření nových instancí už dělá nová Foo-čka. Protože si s nejvyšší pravděpodobností Foo a ObsoleteFoo budou dost podobné, většinou nevadí, že v běžící vyvíjené aplikaci je někde Foo a někde ObsoleteFoo, a když chci mít jistotu, tak aplikaci pustím znovu...

Tohle všechno by v principu mohl hojně používat třeba Python nebo Ruby, to jsou jazyky které podle mě (na designové úrovni) nepřinášejí oproti Smalltalku nic navíc, jen spoustu věcí dělají hůře a pomaleji. U jazyků se statickými typy už by to bylo komplikovanější.
Název: Re:Dvě stejné třídy různých verzí (Java)
Přispěvatel: Filip Jirsák 19. 07. 2018, 08:18:01
Pod JVM se také dělají změny tříd za běhu (třeba se takhle někdy řeší aspekty), pod JVM můžete spouštět i dynamické jazyky (Groovy, Jython). Možností je spoust a záleží na tom, čeho přesně chce tazatel docílit. Něco jiného je, pokud chce mít staticky typovaný kompilátorem kontrolovaný kód v Javě, a úplně něco jiného bude, pokud chce jen pracovat s objekty v JVM, které mají určité vlastnosti, a vůbec neřeší, jak se ten objekt v JVM vzal. Podle dotazu to vypadá spíš na první případ, ale s jistotou už se to asi nedozvíme, vzhledem k tomu, že andreaw.fean se zeptal, ale pak zjistil, že ho to vlastně nezajímá.
Název: Re:Dvě stejné třídy různých verzí (Java)
Přispěvatel: ava 19. 07. 2018, 08:26:33
Pod JVM se také dělají změny tříd za běhu (třeba se takhle někdy řeší aspekty), pod JVM můžete spouštět i dynamické jazyky (Groovy, Jython). Možností je spoust a záleží na tom, čeho přesně chce tazatel docílit. Něco jiného je, pokud chce mít staticky typovaný kompilátorem kontrolovaný kód v Javě, a úplně něco jiného bude, pokud chce jen pracovat s objekty v JVM, které mají určité vlastnosti, a vůbec neřeší, jak se ten objekt v JVM vzal. Podle dotazu to vypadá spíš na první případ, ale s jistotou už se to asi nedozvíme, vzhledem k tomu, že andreaw.fean se zeptal, ale pak zjistil, že ho to vlastně nezajímá.

Jo, já v zásadě neprskám na JVM (i když některé věci co Smalltalkovské VM umí JVM neumí, třeba https://gbracha.blogspot.com/2009/07/miracle-of-become.html ), JVM mi přijde docela dobrá, spíš ty mainstreamové jazyky za moc nestojí :)
Název: Re:Dvě stejné třídy různých verzí (Java)
Přispěvatel: A. F. 19. 07. 2018, 19:52:54
Nikdy jsem to nezkoušel, ale řekl bych, že pokud instancuju pomocí dvou různých classloaderů a reflexe, tak můžu získat docela snadno dvě instance totožné třídy ze dvou různých jarek, tedy ve dvou verzích. Pak záleží co s nimi chci dělat dál. Pomocí reflexe můžu dělat zase asi cokoli.

Použití si dokážu představit při potřebě přeuložit serializovaná data v jiné verzi třídy. Ale možná existuje na uvedený případ nějaký vhodnější kanonický postup. Ale častěji se stejně serializuje do nějakého neutrálního formátu, třeba xml, takže to není moc často potřeba.
Neměl by si nějaký odkaz? Potřebuji nasměrovat.
Název: Re:Dvě stejné třídy různých verzí (Java)
Přispěvatel: zdenek henek nereg. 19. 07. 2018, 20:04:46
Nikdy jsem to nezkoušel, ale řekl bych, že pokud instancuju pomocí dvou různých classloaderů a reflexe, tak můžu získat docela snadno dvě instance totožné třídy ze dvou různých jarek, tedy ve dvou verzích. Pak záleží co s nimi chci dělat dál. Pomocí reflexe můžu dělat zase asi cokoli.

Použití si dokážu představit při potřebě přeuložit serializovaná data v jiné verzi třídy. Ale možná existuje na uvedený případ nějaký vhodnější kanonický postup. Ale častěji se stejně serializuje do nějakého neutrálního formátu, třeba xml, takže to není moc často potřeba.
Neměl by si nějaký odkaz? Potřebuji nasměrovat.

Xstream http://x-stream.github.io/
To je jedna z moznosti jak serializovat objekty do XML.
Název: Re:Dvě stejné třídy různých verzí (Java)
Přispěvatel: A. F. 19. 07. 2018, 20:07:22
Nikdy jsem to nezkoušel, ale řekl bych, že pokud instancuju pomocí dvou různých classloaderů a reflexe, tak můžu získat docela snadno dvě instance totožné třídy ze dvou různých jarek, tedy ve dvou verzích. Pak záleží co s nimi chci dělat dál. Pomocí reflexe můžu dělat zase asi cokoli.

Použití si dokážu představit při potřebě přeuložit serializovaná data v jiné verzi třídy. Ale možná existuje na uvedený případ nějaký vhodnější kanonický postup. Ale častěji se stejně serializuje do nějakého neutrálního formátu, třeba xml, takže to není moc často potřeba.
Neměl by si nějaký odkaz? Potřebuji nasměrovat.

Xstream http://x-stream.github.io/
To je jedna z moznosti jak serializovat objekty do XML.
Tak mě samozřejmě nešlo o tu serializaci do XML.
Název: Re:Dvě stejné třídy různých verzí (Java)
Přispěvatel: Ondrej Nemecek 19. 07. 2018, 23:36:27
Nikdy jsem to nezkoušel, ale řekl bych, že pokud instancuju pomocí dvou různých classloaderů a reflexe, tak můžu získat docela snadno dvě instance totožné třídy ze dvou různých jarek, tedy ve dvou verzích. Pak záleží co s nimi chci dělat dál. Pomocí reflexe můžu dělat zase asi cokoli.

Použití si dokážu představit při potřebě přeuložit serializovaná data v jiné verzi třídy. Ale možná existuje na uvedený případ nějaký vhodnější kanonický postup. Ale častěji se stejně serializuje do nějakého neutrálního formátu, třeba xml, takže to není moc často potřeba.
Neměl by si nějaký odkaz? Potřebuji nasměrovat.

Xstream http://x-stream.github.io/
To je jedna z moznosti jak serializovat objekty do XML.
Tak mě samozřejmě nešlo o tu serializaci do XML.

Ale XML může sloužit např. v tom příkladě povýšení verze - nastartuju proces se starou verzí třídy a uložím do xml, pak nastartuju s novou verzí třídy a načtu. Pokud dokážu vyřešit nové nebo chybějící fieldy (nebo obecně změnu struktury), mám hotovo.
Název: Re:Dvě stejné třídy různých verzí (Java)
Přispěvatel: Ondrej Nemecek 19. 07. 2018, 23:38:28
Nikdy jsem to nezkoušel, ale řekl bych, že pokud instancuju pomocí dvou různých classloaderů a reflexe, tak můžu získat docela snadno dvě instance totožné třídy ze dvou různých jarek, tedy ve dvou verzích. Pak záleží co s nimi chci dělat dál. Pomocí reflexe můžu dělat zase asi cokoli.

Použití si dokážu představit při potřebě přeuložit serializovaná data v jiné verzi třídy. Ale možná existuje na uvedený případ nějaký vhodnější kanonický postup. Ale častěji se stejně serializuje do nějakého neutrálního formátu, třeba xml, takže to není moc často potřeba.
Neměl by si nějaký odkaz? Potřebuji nasměrovat.

Představuju si to stejně jako je uvedeno zde (netestoval jsem):

https://stackoverflow.com/a/11759613/5950455

Tedy:

Kód: [Vybrat]
common.jar:
BaseInterface

v1.jar:
SomeImplementation implements BaseInterface

v2.jar:
OtherImplementation implements BaseInterface

command-line:
java -classpath common.jar YourMainClass
// you don't put v1 nor v2 into the parent classloader classpath

Then in your program:

loader1 = new URLClassLoader(new URL[] {new File("v1.jar").toURL()}, Thread.currentThread().getContextClassLoader());
loader2 = new URLClassLoader(new URL[] {new File("v2.jar").toURL()}, Thread.currentThread().getContextClassLoader());

Class<?> c1 = loader1.loadClass("com.abc.Hello");
Class<?> c2 = loader2.loadClass("com.abc.Hello");

BaseInterface i1 = (BaseInterface) c1.newInstance();
BaseInterface i2 = (BaseInterface) c2.newInstance();

Pokud by obě verze nesdíleli společné rozhraní BaseInterface, tak to tolik nevadí. Mohu je instancovat jako Object a potřebné metody (nebo přímo fieldy) si dohledat a použít pomocí reflexe:

Kód: [Vybrat]
import java.lang.reflect.*

public class Test {
   public String toString(){
      return "This is toString from Test!";
   }
}

Object   o = new Test();
Method m = o.getClass().getMethod("toString");
m.invoke(o);

Takovéhle pokusy se snadno testují v jshellu (v JDK od verze 9).
Název: Re:Dvě stejné třídy různých verzí (Java)
Přispěvatel: A. F. 20. 07. 2018, 19:10:28
Nikdy jsem to nezkoušel, ale řekl bych, že pokud instancuju pomocí dvou různých classloaderů a reflexe, tak můžu získat docela snadno dvě instance totožné třídy ze dvou různých jarek, tedy ve dvou verzích. Pak záleží co s nimi chci dělat dál. Pomocí reflexe můžu dělat zase asi cokoli.

Použití si dokážu představit při potřebě přeuložit serializovaná data v jiné verzi třídy. Ale možná existuje na uvedený případ nějaký vhodnější kanonický postup. Ale častěji se stejně serializuje do nějakého neutrálního formátu, třeba xml, takže to není moc často potřeba.
Neměl by si nějaký odkaz? Potřebuji nasměrovat.

Představuju si to stejně jako je uvedeno zde (netestoval jsem):

https://stackoverflow.com/a/11759613/5950455

Tedy:

Kód: [Vybrat]
common.jar:
BaseInterface

v1.jar:
SomeImplementation implements BaseInterface

v2.jar:
OtherImplementation implements BaseInterface

command-line:
java -classpath common.jar YourMainClass
// you don't put v1 nor v2 into the parent classloader classpath

Then in your program:

loader1 = new URLClassLoader(new URL[] {new File("v1.jar").toURL()}, Thread.currentThread().getContextClassLoader());
loader2 = new URLClassLoader(new URL[] {new File("v2.jar").toURL()}, Thread.currentThread().getContextClassLoader());

Class<?> c1 = loader1.loadClass("com.abc.Hello");
Class<?> c2 = loader2.loadClass("com.abc.Hello");

BaseInterface i1 = (BaseInterface) c1.newInstance();
BaseInterface i2 = (BaseInterface) c2.newInstance();

Pokud by obě verze nesdíleli společné rozhraní BaseInterface, tak to tolik nevadí. Mohu je instancovat jako Object a potřebné metody (nebo přímo fieldy) si dohledat a použít pomocí reflexe:

Kód: [Vybrat]
import java.lang.reflect.*

public class Test {
   public String toString(){
      return "This is toString from Test!";
   }
}

Object   o = new Test();
Method m = o.getClass().getMethod("toString");
m.invoke(o);

Takovéhle pokusy se snadno testují v jshellu (v JDK od verze 9).

Excelentní. Takhle na talíři jsem to nečekal. Vyzkouším. Díky!