Internet Info, s.r.o. Lupa Měšec Podnikatel Root Zdroják DigiZone Slunečnice Vitalia TopDrive KupDnes Navrcholu NovýTarif Dobrý web Weblogy Woko Jagg Computer.cz SK: MojeLinky

Hlavní navigace

Názory k článku
Pohled pod kapotu JVM (1.část - prohlížení a modifikace bajtkódu)

Xerces
Xerces (neregistrovaný) ---.blue4.cz
13. 12. 2011 4:17 Nový

Tak konečně

celé vlákno

jsem si po letech přečetl zajímavej článek o jinak nezajimavý JAVĚ. Díky.

krtek
krtek (neregistrovaný) 217.77.165.---
13. 12. 2011 8:52 Nový

Zajímavá soutěž

celé vlákno

Pro trénink hrátek s bajtkódem doporučuju následující soutěž:
http://zeroturnaround.com/blog/celebrate-the-programmers-day-with-zeroturnaround/

Pavel Tišnovský aura:98
13. 12. 2011 10:36 Nový

Re: Zajímavá soutěž

celé vlákno

To je nefalsovana nerdovska soutez, dokonce i dny pocitaji v hexa :-)

Vít Šesták (v6ak) aura:79
13. 12. 2011 12:29 Nový

Runtime constant pool

celé vlákno

Tvrzení, že u dvou řetězcových konstant v téže třídě funguje == jako porovnání řetězců, bych rozšířil silnějším tvrzením: Ono to funguje, i když jsou třídy různé. Je to tak díky runtime constant poolu, které sdílí všechny třídy (AFAIK napříč classloadery). Udělal jsem takový malý experiment: http://ideone.com/snJNS

Trošku problém to může být u testů. Jednou (pri doučování Javy) jsem se setkal s kódem, který na první pohled fungoval korektně, ale jen díky tomu, že stringy pocházely z konstant. Teď přemýšlím, proč jsem nefunkčnost ukazoval tak krkolomně, když by mělo stačit new String("foo").

Na druhou stranu, nepamatuji si, že by se mi někdy povedlo takovou chybu udělat a podepřít si jí funkčním testem.

Pavel Tišnovský aura:98
13. 12. 2011 12:38 Nový

Re: Runtime constant pool

celé vlákno

Ano mate pravdu. Ja jsem se o tom operatoru == popravde nechtel moc rozepisovat, protoze jeho pouziti nad stringy (=objekty) vede ke spatne odhalitelnym chybam (postacuje "pouze" nejakou metodu volat jako beanu na jinem pocitaci).

Implementace new String(String) vypada v OpenJDK takto:

public String(String original) {
    int size = original.count;
    char[] originalValue = original.value;
    char[] v;
    if (originalValue.length > size) {
        // The array representing the String is bigger than the new
        // String itself.  Perhaps this constructor is being called
        // in order to trim the baggage, so make a copy of the array.
        int off = original.offset;
        v = Arrays.copyOfRange(originalValue, off, off+size);
    } else {
        // The array representing the String is the same
        // size as the String, so no point in making a copy.
        v = originalValue;
    }
    this.offset = 0;
    this.count = size;
    this.value = v;
}

coz znamena dalsi zdroj potencialnich problemu v zavislosti na tom, jestli se vytvari novy objekt nebo ne.

Vít Šesták (v6ak) aura:79
13. 12. 2011 13:50 Nový

Re: Runtime constant pool

celé vlákno

Když použiju new, tak se nový objekt vytváří vždy, ne? Druhá věc je, jestli se kopíruje pole uvnitř řetězce, ale pokud porovnávám pomocí == dva Stringy, tak to nepoznám.

Speciální případ by teda byl, kdyby ten konstruktor si uložil vytvořený řetězec do nějakého poolu (třeba jen dočasně) a řetězec by pak byl znovupoužit při vytváření nové třídy. Ale to by byla hodně krkolomná implementace.

Napadá mě pro testovací účely napsat skript, který by každou řetězcovok konstantu obaloval výrazem new String(...). Dělal bych to úpravou bytecode. Myslím, že by to šlo takto: skript by našel všechna ldc (popř. ldc_w) odkazující na řetězec a udělal by s tím toto:
* před tuto instrukci by hodil dvojici instrukcí new java/lang/String a dup
* za tuto instrukci by hodil instrukci invokespecial java/lang/Strin­g.<init>(java/lan­g/String)V

S BCELem by to měla být otázka na chvilku, pokud člověk nenarazí na nějaký jeho bug. (Což na druhou stranu taky jde lehce, bohužel.) Mohlo by to být takové cvičení pro nováčky, kteří se chtějí v BCELu zorientovat. Skoky by už měl BCEL přečíslovat sám.

(Obdobně (ale možná i o něco jednodušeji) by šlo vyřešit Integery apod. Tam by pro zjednodušení stačilo nahradit volání továrny java/lang/Inte­ger.valueOf(I)Lja­va/lang/Integer; vlastní továrnou, která by vždy volala new Integer.)

Pavel Tišnovský aura:98
13. 12. 2011 14:13 Nový

Re: Runtime constant pool

celé vlákno

Objekt se pres operator new() vytvari vzdy, to se neda obejit, jedine tak, ze by konstruktory byly zakazany a musely by se volat tovarni metody (coz se doporucuje treba u Integeru atd.)

No bugy v BCELu jsou to mate pravdu, ale zrovna pri zmene instrukci v bajtkodu me to fungovalo dobre. Kdyztak to resi (IMHO elegantnejsi) ASM :-)

Karell aura:90
14. 12. 2011 11:10 Nový

Re: Runtime constant pool

celé vlákno

K tomu new se chci zeptat - kdyz budu mit treba v cyklu new String("foo"), je tedy zaruceno, ze se pokazde vytvori novy objekt, nebo se muze stat ze behem optimalizaci se to hodi pred cyklus nebo uplne nahradi konstantou?
Jeste me napada treti moznost - ze je to nahrazeno pokud optimalizator dokaze, ze ten kod s adresou instance nijak nepracuje.

Vít Šesták (v6ak) aura:79
14. 12. 2011 14:24 Nový

Re: Runtime constant pool

celé vlákno

Sémanticky je tu new pro vytvoření nové instance a toto nesmí optimalizace porušit. Není nutné pokaždé vytvořit nový objekt v heapu, ale pak se musí JIT ujistit, že to nezmění sémantiku programu.

Pro představu:
* Oracle Java 7 umí v některých případech zjistit, že se vytváří defensivní kopie nějakého objektu, ale děje se tak naprosto zbytečně, tak se místo vytvoření kopie prostě předá původní objekt. Toto asi nebude zrovna triviální optimalizace, je nutné se například přesvědčit, že oba objekty nejsou porovnávány podle identity, jinak by to změnilo sémantiku.
* Údajně se taky někdy nové instance vytváří na zásobníku, když JVM dokáže zjistit samotný cyklus.
* Někde jsem taky četl o recyklaci výjimek a nevyplňování stack trace, když JVM zjistí, že to nezmění sémantiku. Možná to říkal Lukáš Křečan, už nevím.

Prostě JVM musí v takových případech dělat dokonalou potěmkinovu vesnici. Nemusí dělat přesně to, co tomu člověk řekne, ale musí ten "podvod" být uvěřitelný pro libovolného vnějšího pozorovatele, ať se v tom šťourá, jak chce.

Pavel Tišnovský aura:98
14. 12. 2011 15:22 Nový

Re: Runtime constant pool

celé vlákno

JVM se muze chovat podobne jako Schrödingerova kocka :-)

Myslim tim to, ze pokud nezacnete explicitne zkoumat, jestli se skutecne vytvori novy objekt, tak se objekt nemusi vytvorit (ale samozrejme muze). Ale jakmile se ve vasem zdrojaku objevi neco, co zavisi na tom, ze se skutecne novy objekt vytvari (typicky pouziti ==), tak se skutecne objekt vytvori :-)

Vzhledem k tomu, ze Stringy jsou nemenitelne objekty (immutable), tak vetsinou neni nutne tvorit defenzivni kopii a zapis new String("foo") je ve vetsine pripadu (ne vzdy) jen neefektivnim zapisem "foo", protoze "foo" je instance tridy String, na ktere lze volat vsechny metody ("foo".toLower­Case() a tak dale).

Leoš
Leoš (neregistrovaný) ---.eurotel.cz
15. 12. 2011 11:33 Nový

Re: Runtime constant pool

celé vlákno

Překvapuje mě že doposud nikdo nezmínil tenhle podraz který je přímo oficiálně dokumentovaný: http://docs.oracle.com/javase/6/docs/api/java/lang/String.html#intern()

JV
JV (neregistrovaný) 2001:718:2:----:----:----:----:----
15. 12. 2011 13:38 Nový

Re: Runtime constant pool

celé vlákno

Jo jo, na tohle jsme narazili nedavno. Predstavte si kod

class A {
public static final CNST = "Hello";
}

class B {
String foo() {
return A.CNST;
}
}

Clovek by cekal, ze kod metody foo() bude neco jako

GETSTATIC A.CNST
ARETURN

Nicmene javac vygeneruje
LDC "Hello"
ARETURN

Tohle me stalo mnoho veceru nez jsem odladil...fix ve VM byl trivialni.

Pavel Tišnovský aura:98
13. 12. 2011 22:39 Nový

Re: Runtime constant pool

celé vlákno

S těmi int/Integery mě to připomělo chybu v jedné aplikaci, kdy se při refaktoringu nahradily některé inty za Integery, tj. primitivní datový typ za objektový typ. Díky autoboxingu to skoro všude pracovalo dobře, ale v jedné metodě se používal operátor ==, který funguje pouze ve třech případech ze čtyř:

int == int ok

int == Integer ok

Integer == int ok

Integer == Integer dela to, co je napsano, tedy nikoli to, co chtel programator :-)

phi
phi (neregistrovaný) ---.systinet.com
13. 12. 2011 14:28 Nový

Re: Runtime constant pool

celé vlákno

ja bych to s pouzivanim operatoru == na Stringy nevidel tak spatne, staci chapat ze porovnam na totoznost objektu, nikoliv na jejich equalitu (nebo jak to nazvat).

Pavel Tišnovský aura:98
13. 12. 2011 15:18 Nový

Re: Runtime constant pool

celé vlákno

ano, to je jasne, ale docela dost lidi v tom rozlisovani dela chybu (je to videt na testech, popr. staci si pustit FindBugs na skoro kazdem vetsim Javovskem projektu). Urcita zakernost operatoru == nad retezci je v tom, ze nekdy to funguje (kdyz se porovnavaji retezce z constant poolu) a nekdy ne (kdyz se retezce ziskavaji jinde).

A pokud je situace takova, ze je treba cast aplikace testovana na "statickych datech" a projde testy a v praxi se namisto "statickych dat" neco nacita ze souboru ci databaze, je o problem postarano.

Pavel Tišnovský aura:98
13. 12. 2011 15:23 Nový

Re: Runtime constant pool

celé vlákno

jeste doplnim, ze na rozdil mezi String.equals() a == narazi hodne lidi i u pohovoru, takze pozor na to :-)

phi
phi (neregistrovaný) ---.systinet.com
13. 12. 2011 15:41 Nový

Re: Runtime constant pool

celé vlákno

coz jen dokresluje tu bidu v lidskych zdrojich, kdyz ja coby tester topim na podobnych trivialitach pri pohovorech lidi, co si napsali do CV Javu :)

ceckar
ceckar (neregistrovaný) ---.tmcz.cz
13. 12. 2011 22:34 Nový

Re: Runtime constant pool

celé vlákno

Nojo, to si do CVcka prece napise kazdy, kdo si projde zakladnim kurzem Javy nekde na skole, kde se takove "podruznosti" jako je rozdil mezi == a .equals() pri praci s objekty ani neprobiraji.

Ono se staci zeptat i na nejake zakladni veci ohledne kolekci napriklad, nemluvim o propojeni Javy a relacni DB, kde se taky dozvite spoustu zajimavosti a novinek z oboru relacnich databazi :-)

Marek
Marek (neregistrovaný) 85.162.33.---
13. 12. 2011 16:52 Nový

super

celé vlákno

Jsem rád, že je seriál zpátky. Díky za něj!

Pavel Tišnovský aura:98
13. 12. 2011 17:29 Nový

Re: super

celé vlákno

Taky diky :-)

Jen jsem se trosku bal, ze skalni javisti budou zklamani z toho, ze se jde trosku na moc low-level uroven (i kdyz to jeste nic neni proti analyze prace hotspotu).

sid
sid (neregistrovaný) ---.178-40-0.t-com.sk
13. 12. 2011 20:42 Nový

Re: super

celé vlákno

Tiez sa pripajam k pochvale, radost citat podobny clanok

Peter Augustin
Peter Augustin (neregistrovaný) ---.rev.bonet.sk
14. 12. 2011 0:21 Nový

Re: super

celé vlákno

Tiez sa pridavam k dakovaniu, velmi prijemny clanok, tato nizsia uroven je celkom prijemne osviezenie popri rieseni problemov z praxe, ze ktoryze to superframework je najmensie zlo :)
a myslim ze filozofovanie nad bytecode je velmi dobry namet na niektoru z nasledujucich vecernych univerzit u nas vo firme

Michal Kára
Michal Kára (neregistrovaný) 78.102.8.---
14. 12. 2011 7:32 Nový

Re: super

celé vlákno

Naopak, o těhle low-level věcech se moc nepíše. Sice to člověk akutně nepotřebuje, ale někdy se může hodit, že má člověk alespoň základní představu, jak tyhle věci fungují :)

Zasílat nově přidané příspěvky e-mailem