Mi a hiba a kódban? #2

A [intlink id=”1249″ type=”post”]múltkori, nagy sikerű írásom[/intlink] hatására Tompika küldött nekem egy hasonlóan izgalmas problémát.

[cc_java]while (true) {
Process p = Runtime.getRuntime().exec(“macska”);
p.waitFor();
}[/cc_java]

A kód eredeti, Tompika kedvenc állatait, a macskákat felemlegetve. A kód elméletben a következőt kellene, hogy csinálja: az első sor a [cci_java]p[/cci_java] referenciával elérhető módon indít egy processzt; míg a második sor vár, amíg a processz fut.

Ha megnézzük a kapcsolódó JavaDoc kommenteket, ez így működőképes is lehet. Ezzel szemben futásidőben problémák léptek fel, amiket feltehetőleg a következő kódrészletre való kicserélés javított:

[cc_java]while (true)
{
Process p = Runtime.getRuntime().exec(“macska”);
p.waitFor();
p.getErrorStream().close();
p.getOutputStream().close();
p.getInputStream().close();
p.destroy();
}
[/cc_java]

A kódrészlet utolsó sora vicces. Idézném a Javadoc kommentet:

[cci_java]public abstract void destroy()[/cci_java]

Kills the subprocess. The subprocess represented by this [cci_java]Process[/cci_java] object is forcibly terminated.

Amit én úgy értelmeznék, hogy a függvényt meghívva explicite lezárom a Processt. Viszont állítólag nem így történik. Valaki tudja a magyarázatot? Kíváncsi lennék rá.

PS.: ha valaki hozzájut hasonló gyöngyszemekhez, és eljuttatja hozzám, szívesen közzéteszem.

New service release: 0.7.2

I’m proud to announce that after a long time, we finally managed to throw out a new release. I’ve managed to improve the core functionality therefore this release contains a significant advance in overall performance.

Also, Stampie managed to fix a long-awaited feature, the two-way synchronization with the variables view.

In the future, we plan to redesign the use-cases of the tool. Currently, we’re in an experimental phase, which means we do not know how we want it to work.

Eclipse GEF wtf

Az előző kitérő után most térjünk vissza egy kis kocka témához. A minap érdekes felfedezést tettem, miközben véletlenül a GEF belső kódjába tévedtem debug közben. Alapvetően egyébként meg vagyok elégedve a GEF és általában az eclipse platform minőségével, ritka az az eset, hogy a fejemet fogom egy-egy megoldás láttán.

A következő kódrészlet ugyan működik és mivel a publikus api elrejti, az átlag fejlesztő nem találkozik vele, mégis érdemes rávetni egy pillantást. További szócséplés helyett következzék a kód, szerintem magáért beszél:


//AbstractEditPart.class

private Object[] policies;

//...

/**
* @see EditPart#installEditPolicy(Object, EditPolicy)
*/
public void installEditPolicy(Object key, EditPolicy editPolicy) {
Assert.isNotNull(key, "Edit Policies must be installed with keys");//$NON-NLS-1$
if (policies == null) {
policies = new Object[2];
policies[0] = key;
policies[1] = editPolicy;
} else {
int index = 0;
while (index < policies.length && !key.equals(policies[index])) index += 2; if (index < policies.length) { index++; EditPolicy old = (EditPolicy)policies[index]; if (old != null && isActive()) old.deactivate(); policies[index] = editPolicy; } else { Object newPolicies[] = new Object[policies.length + 2]; System.arraycopy(policies, 0, newPolicies, 0, policies.length); policies = newPolicies; policies[index] = key; policies[index + 1] = editPolicy; } } if (editPolicy != null) { editPolicy.setHost(this); if (isActive()) editPolicy.activate(); } }

Akinek nem világos elsőre, kifejteném a problémát: láthatóan egy tömböt használ a java-ban alapértelmezésként elérhető "Map" funkcionalitásának a kiváltására. A tömb páros (és nulladik) helyén szereplő elem tárolja a kulcsot, az utána lévő páratlan helyen lévő elem az érték.

Minden elem hozzáadásakor dinamikusan növeli a tömb méretét, törléskor meg egyszerűen null-ra állítja a tömb megfelelő elemét. Ehhez még társul egy custom iterátor is, ami a tömb nem null elemeit listázza.

Őszintén nem értem a tervezési döntést, ami a tömb-alapú Map-hez vezethetett. A memóriaigénye a HashMap-nek nem sokkal több, és mivel jellemzően kis elemszámú esetek fordulnak elő, ez nem számottevő. A sebessége a HashMap-nek jobb, a "get" és "put" metódusok általános esetben konstans, de mindenképpen kevesebb a tömb végigjárásánál. Mindennek a tetejébe a fenti kód Map alkalmazásával kb. 3 sorra cserélhető, nem beszélve az osztály egyéb kódjáról, ami a tömböt piszkálja.

Egyetlen érthető mentségként csak arra tudok gondolni, hogy esetleg a kód korábban íródott, minthogy a java collections API-ba belekerült volna a Map. Ez viszont az 1.2-es verzióban történt meg, tehát elég régen. Nem tudom mennyi idős a GEF, így ezt nem tudom eldönetni.. Mindenesetre ez a kód nálam megütötte a WTF szintet.

És mégis leng az inga…

A sok elborult, kocka téma után most egy kicsit könnyedebb vizekre eveznék. Ez nagyjából azt jelenti, hogy a következő írást úgy tervezem, hogy ne csak informatikusok számára legyen érthető (noha ők meglehetősen furcsa okokból nem hemzsegnek az oldal olvasói között).

Kicsit nehezen kezdek hozzá, ugyanis még könyvet nem ajánlottam ezeken a hasábokon – pedig olvastam párat, köztük olyat is, amit tényleg érdemesnek tartok arra, hogy többen olvassák. Ami mondjuk hasznos lenne, hiszen egyre kevesebbet olvasunk.

Viszont a mostani könyvajánlatom nem fog ezen segíteni, ugyanis Umberto Eco Foucault-inga című műve kifejezetten ijesztő: csaknem 800 oldal, nem nagy betűkkel szedve, kemény táblával. De szemben a múltkor emlegetett Ügyféllel itt tartalom is van mellé: Eco professzor úr igen hosszadalmas kutatómunkáját (is) tartalmazza ez a könyv, benne a templomosokról, rózsakeresztesekről és hatalmas rejtett titkokról.

Ha van Terv, akkor minden mindennel összefügg. Ha van Terv, akkor nem kétséges, mi közük a templomos lovagoknak a hasszaszinokhoz, az alkimistáknak a párizsi metróhoz, a titokzatos Saint-Germain grófnak Shakespeare-hez, a rózsakereszteseknek Arsène Lupinhez, a druidáknak az Eiffel-toronyhoz, a Föld forgását bizonyító Foucault-féle ingának… Kihez-mihez is?

Ha van Terv, minden kiderül.

Mi is ez a Terv? Sokat nem mondanék róla, valamit a könyvnek is érdemes meghagyni, de röviden annyit tehetnék hozzá még, hogy negyvenkettő. Azaz a Terv mindent leír, ami a történelmünkben az elmúlt néhány száz évben történt. És a lehetőségekhez képest mégkonzisztens módon is.

Az értékelésem szükségképpen szubjektív, részrehajló vagyok. Én kedvelem a történelmi regényeket, szintúgy azokat a könyveket, amiben a természetfeletti erők is előkerülnek, de azért emberközpontúak maradnak. Ha ehhez még titkok is társulnak, és a főszereplőkkel még azonosulni is tudok, akkor borítékolható, hogy jól érzem magam olvasás közben.

  • Nem rossz – mondta Belbo. – Engem viszont ez a piramisokról szóló ötszáz oldal, ez nem hagy nyugodni.Tudták-e, hogy a Kheopsz-piramis pont a harmincadik szélességi fokon áll, és hogy az a szélességi kör szeli át a legtöbb szárazföldet? És hogy a Kheopsz-piramisnak ugyanazok  a geometriai arányai, mint az amazóniai Pedra Pintadának? És azt, hogy Egyiptomban két tollas kígyó is volt: az egyik Tutankamon trónján, a másik pedig a szakkarai piramison, és ez Quetzalcoatlra utal?
  • Quetzalcoatl a mexikói pantheon tagja. Mi köze neki Amazóniához? – kérdeztem.
  • Mit tudom én, valamit biztos kihagytam. […]

Érdemes lehet megfigyelni, hogy noha összeesküvéselméletekből van bőven a könyvben, a szerző megmarad a tudományos elfogadott módszerek mellett, azaz lehetőség szerint mindent támasszunk alá tényekkel, de legalábbis más művekkel. Jó ez?

Egy biztos: olyan mennyiségű forrásra hivatkozik menet közben, hogy a végén levő függelék kicsit kevés – csak kilenc oldal. Kevésszer fordult eddig elő, hogy egy könyv olvasása közben totál műveletlennek éreztem magam, de itt szinte folyamatosan ez az érzésem volt. Kevés olyan könyv van, ahol egyszerre kap szerepet a Rózsakeresztes kiáltvány, a Gergely-féle naptárreform, kombinatorika (némi programozással együtt) és a Föld forgását kísérleti úton kimutató Foucault-inga.

Szerencsére mindenhol elég pontosan megnevezi a forrásokat – még az elborult, “ördöngös” könyveket is. Így viszont eléri azt, amit nagyon sok könyvnek nem sikerül: hitelesség.

Mindezek mellett a könyv részletesen meg van tervezve: a fejezeteket tíz szakaszra osztotta, amelyeket a szefirák mentén oszt be. Azok kedvéért, akik nem tudnák, mik azok a szefirák (közétek tartoztam a könyv olvasása, illetve az értékelés írása előtt), a héber kabbalisztika tíz állomása a megvilágosodás felé. Emellett a fejezeteket rövid, kapcsolódó idézetek vezetik be.

Ugyanakkor fontosnak tartom megemlíteni, hogy a könyv nem kalandregény, semmilyen formában. Leginkább fejlődésregény: megmutatja, hogyan érti meg Doktor Casaubon a világ legfőbb titkait.

És itt jön az a pont, ahol találkozik a könyv a szakmai érdeklődésemmel is: megmutatja, hogyan lehet leírni a világot egy jól definiált rendszerben. Gondolom, informatikusok/szoftverfejlesztők ismerik ezt a feladatot – ezt rendszeresen kell csinálnunk. Jó tudatosítani az ilyesmit.

És mi különbözteti meg a regény összeesküvéselméleteit a tényleges igazságoktól? Ne akarjuk a hibákat is tökéletesen modellezni. Ha van két, az összes adatunkkal konzisztens hipotézisünk, válasszuk az egyszerűbbet. Meglepően sokszor használható.

Lassan lezárva gondolataimat azzal fejezném be ezt az írást, hogy mindenkinek sok szeretettel ajánlom Eco professzor úr könyvét elolvasásra, a könyv elejéről Raymond Smullyen mottóját idézve:

A babona bajt hoz.

Az idézetek az Európa Kiadó 1992-es magyar nyelvű kiadásából származnak.

Ganymede fejlesztés Java 6-tal OSX-en

Elég sok időt töltöttem már azzal, hogy Java 6 alapú fejlesztést lehessen végezni [intlink id=”570″ type=”post”]Eclipse-szel és OSX-szel[/intlink].

Az alapprobléma az volt, hogy egyszerre kellett 32 (az SWT Carbon API-ja kötelezően 32 bites) és 64 biten dolgozni (mert a Java 6 kötelezően 64 bites). Szerencsére ezt a fejlesztők is belátták, és elkészítették az SWT Cocoa portját (ami mellesleg nem lett rossz, de ez nem ennek az írásnak a témája).

Eredmény: némi varázslás után 3.5-ös Eclipse-szel lehetett Java6-ra fejleszteni (a varázslás nem ártott, de erről szintén nem most írok). De ez bizonyos esetekben nem elég. Például, ha az ember kénytelen 3.4-es Eclipse-szel is kompatibilis maradni, és ezt még ellenőrizni is szeretné.

Ez, és az apróbb problémák a 64 bites Java 6-tal győztek meg végül arról, hogy kb. egy hónappal a megjelenés után frissítsek Snow Leopardra. Elvégre abban van 32 bites Java 6 is, ezért elvileg mennie kellene a dolognak. Sőt, csak Java 6 van a rendszerben, szóval ez még jobb.

Na, Ganymede indul, szépen megy is. Összegyűjtöm a tesztelendő projekteket, és indítanám a runtime workbenchet, mire közli velem, hogy a Carbon SWT nem működik a 64 bites JVM-en. No comment.

A szokásos trükkjeimet ilyen esetekre végigpróbáltam, eredmény teljes kudarc, mígnem  az ESE konferenciáról beszámoló blogbejegyzés kommentjében Kevin Barnes leírja a megoldást: a VM-nek a -d32 paramétert átadva 32 bites JVM-et indít.

És ez tökéletesen működött. Szuper.

PS.: jellemző Eclipse probléma, hogy a megoldás triviális, csak megtalálni nehézkes. De legalább most már tudom, hogyan lehet 32 bitre force-olni a JVM-et.