I think that more-less everybody have by now been burned at least once by some memory leaks in Java. Although it sounds impossible (it is a managed language after all, isn’t it?), that actually happens quite often. The problem is usually with leaky abstractions - we, the developers are lead to belive that we don’t really have to worry about memory - GC is taking care of that stuff, isn’t it? In reality, you actually do have to worry about memory. Even though the garbage collector will free all unreferenced memory chunks, you as a developer have to make sure that no chunks end up being referenced.

Usually, the culprits are either some action listeners that are left hanging, or some references in some long forgotten collections (Singletons really are evil sometimes!).

In our case, it was neither. Here are the symptoms: the application does a whole lot of calculation and uses some tree-like data structures to do the math. We feed it with a lot of data and the memory footprint at one moment in time is ~ 700megs (we’ve got ~ 1G of heap). Then we’re done. And it’s not yet freed. But that’s OK, since GC tends to be lazy. The problem occurs when you want to do the same operation twice - the second time time, JVM runs out of memory.

So, after a couple of days of tracing the leak (my first suspicion was that we had some sort of a leak in our tree-like structure), it can all boil down to this small code snippet:

public class MemoryLeakTest {
    public static void main(String[] args) {
        for (int i = 0; i < 1000; i++) {
            JDialog dialog = new JDialog() {
                int[] take4Megs = new int[1000000];
            };
           dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
           dialog.setVisible(true);
           dialog.setVisible(false);
        }
    }
}

Here, we create a JDialog instance that has one neat attachment to it - a 4meg worth of empty integer. Set up -Xmx64m for this test case and only after a few runs, you’ll run out of memory. How is it possible that I run out of memory here? There are no collections, all variables are locally scoped - GC should be picking JDialog up after each loop iteration (or at least after a few). However, it seems that this does not occur. The only thing that seems to fix the issue is calling dispose manually like this:

public class MemoryLeakTest {
    public static void main(String[] args) {
        for (int i = 0; i < 1000; i++) {
            JDialog dialog = new JDialog() {
                int[] take4Megs = new int[1000000];
            };
           dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
           dialog.setVisible(true);
           dialog.setVisible(false);
           dialog.dispose();
        }
    }
}

Please note that the tested platform is JVM 1.6.0_19, Windows7 Ultimate (it also happens on XP). Here is what the Java documentation says about dispose:

“Releases all of the native screen resources used by this Window, its subcomponents, and all of its owned children. That is, the resources for these Components will be destroyed, any memory they consume will be returned to the OS, and they will be marked as undisplayable.”

Inspecting heap dumps of both cases revealed that if we don’t explicitly call dispose(), that JDialog (actually, MemoryLeakTest$1 instances) instances remain in memory (I guess Swing has some references to them - we obviously don’t have them) and are not garbage collected. However, doing dispose() seems to have cleaned up the system resources and removed those references in Swing because we can’t see a single dialog instance on the heap anymore. The worst thing here is that it seems that this behaviour is not documented in the documentation (dispose() docs don’t say anything about this - see http://java.sun.com/javase/6/docs/api/java/awt/Window.html#dispose() ).

Everybody already knows how great file-handling tools *NIX operating systems have. I’m just constantly amazed with how much you can get done in a single command line. For example, imagine a process that does some data processing on a remote machine and logs all the communication between the client and the server machine in one file. Now, imagine this process running for 30+ hours, producing a 220+ Mb log file.

After the process is done, your boss wants some kind of reporting - how many entries were processed, how many were processed sucessful, how many errors were there and which errors they were. Not much of a problem when working on a UNIX machine:

A:    cat out.txt | grep 'COMMAND SUCCESS' | wc -l
B:    cat out.txt | grep 'COMMAND FAILED' | wc -l

… and just to make sure, lets check if A+B = C:

C:    cat in.txt | wc -l

Now, lets report on errors:

cat out.txt | grep 'ERROR_CODE:' | sort | uniq

returns a list of errors:

ERROR_CODE: 10065
ERROR_CODE: 11245
ERROR_CODE: 19543

and now just lets find out how many of each we got:

cat out.txt | grep 'ERROR_CODE: 10065' | wc -l
cat out.txt | grep 'ERROR_CODE: 11245' | wc -l
cat out.txt | grep 'ERROR_CODE: 19543' | wc -l

Email to the boss, and we’re done. All good? Great. But, another email comes in: “Could you please send me a list of all the IDs that caused an error #11245″. Sure, no problem:

cat out.txt | grep -B 7 'ERROR_CODE: 11245' | grep 'REQUEST_ID' | awk '{ print $2; }' | sed 's/REQUEST_ID:\([0-9*]\)/\1/g’ > ids.txt

Lets explain this one a bit:

  • the initial request that was sent to the system was logged 7 lines before the ERROR_CODE (therefore the “-B 7″)
  • the line with the request had the following format:
    START REQUEST_ID:XXXXX SOME_OTHER_STUFF
    (therefore the awk part)
  • with sed we just extracted the number from the request_id column

Can it get any more powerful than this?

Exactly two years ago, a couple of geeks from Croatia decided to make a living off of being geeks. Calyx was born exactly two years ago. Actually, it was born a bit before that, but this is the legal birthday, so we celebrate it as the real one. Anyway, they say that your company has to survive for three years to be a “real” company, so I guess we just have one more to go :-) If we look at what we did in the last two years, I would say that a lot has been accomplished, but there is still much of the road ahead of us. We’re getting a bit stronger these days, so a new member should join the lot, but more on that in the days to come.

BTW, did you know that the next two suggestions for the company name were InCumulo and FooBar? Whoever can guess the explanation for those two names has a beer ;-)

This is a service I would like to have:

POIs

I could browse the map, draw circles of various sizes and associate tasks to them.

Later, as I enter the designated areas (which is easily determined via GPS or cell tower info), I receive an SMS with the reminder.

Bonus: conditional reminders –> “if(time >= 6pm)” or “if(date >= 16.3.2009. and mySpeed < 10 km/h)”

Fresh stuff from Calyx Labs!

Since our dissatisfaction with the e-banking web site we all use (described in a previous post) grows by the day, we decided to tackle the problem ourselves :)

To cut a long story short, our beloved e-banking web app lets you see your transactions for a certain period - and that’s about it. No export to CSV/XLS possibility, no graphic representations.

That’s why we decided to build some kind of add-on which will help you visualize your data. We chose to implement it as a bookmarklet, using the JavaScript plotting library flot. Here’s the result:

[caption id="attachment_136" align="aligncenter" width="480" caption="ZaBaPlot"]ZaBaPlot[/caption]

The functionality is rather limited - you can track your account balance, individual transactions and some kind of moving average. Zooming in/out is also possible. + the killer feature: tooltips with transaction details :)

The source code is yours to do whatever you want.

Installation and usage guide. (WARNING: Croatian language)

Goran joined our dev team today. We had to upgrade the office, and God knows developers were not meant to use the hammer. As you can see in the picture below, Pablo was quite worried.

Approval, we haz it

Luckily, everything turned out fine in the end. The office is upgraded, no reboot needed. Pablo is now satisfied.

[caption id="attachment_124" align="aligncenter" width="372" caption="Approval, we haz it!"]Approval, we haz it![/caption]

p.s. A quite fascinating thing just happened. Venus aligned with the moon to form something looking extremely similar to the Turkish flag inverted horizontally.

This must be an omen, the One has come! :)

I suppose you all feel a warming/familiar sensation when observing at the following image :)

Am I the only one puzzled by the location of the sign-in link?

Although “personal reccomendations” is probably the most used functionality of the personalized Amazon web site, I don’t think it should replace the widely used “Sign in” paradigm.

E.g. I signed in a few moments ago to track my recent order. I had to click “personalized reccomendations” in order to get the status of my orders. Not really intuitive.

I know they want me to check the newest reccomendations no matter what. And I know that the fact that “Sign in” is not a link to the sign in page should not bother me that much :)

,

As I mentioned in the previous post, I’m going to write about an observation. I named it McAtom.

Take a random group of software developers. Put them on a project. After some time, their individual RSS/Atom subscriptions will converge to an identical set.

The real-world source of this post, the McClintock effect, is also referred to as the “social regulation of ovulation”. I guess that would make my observation the “social regulation of procrastination”.

, , ,

So, this is the second (and hopefully last) part of my e-banking rant. It’s a question of my mental health to get this through, so please excuse me. And stay tuned, as I had an epiphany this morning and new post is just behind the corner :) It’s about the developer’s version of the McClintock effect (I sincerely hope you have to google this term). Bye!

A mi, osuđenici na kombinaciju amaterizma i visokih marži, možemo nastaviti dalje sa analizom meni omiljene web aplikacije. Danas ću se baviti nalozima, vjerojatno najkorištenijom funkcionalnošću e-bankarstva.

[caption id="attachment_97" align="aligncenter" width="500" caption="Unos naloga"]Unos naloga[/caption]

Prijavu na sustavu i nelogičnosti “početne” stranice sam već obradio u proteklom postu, pa nastavljam izravno sa unosom novog kunskog naloga. Sam unos podataka je, što bi mi hrvati rekli, pretty straightforward. Unos podataka je ipak nešto što rade korisnici, pa tu Zaba nije imalo puno manevarskog prostora za napraviti nešto krivo. No, po unosu računa primatelja otvara se mogućnost prve interakcije sa sustavom (provjera računa), što u zabinom slučaju neminovno rezultira … pogodite kako :)

Akcija “Provjera računa primatelja” otvara prozorčić s podacima primatelja za zadani broj računa:

[caption id="attachment_94" align="aligncenter" width="486" caption="Podaci o primatelju"]Podaci o primatelju[/caption]

Očekivano, “Popuni kunski nalog” ne radi web pregledniku Firefox 3. Zašto podržavati web preglednik čiji je tržišni udio 42.6%  (statistike od rujna 2008)? Podržavanje isključivo Internet Explorer web preglednika ipak ne čudi s obzirom na ostatak “silovanja” Microsoft tehnologija. Razloge odabira Microsofta kao platforme nije potrebno dodatno analizirati. U situaciji ili/ili i ja bi odabrao isto. Problem je što te dileme uopće nema. Zašto korištenje Zabine smart-kartice kao preduvjet ima Windowse? Ne, nije istina da firme rade samo na Windowsima. Da, aplikacija za smart kartice mogla se napraviti na način da ne ovisi o platformi. Sva sreća da smo kao firma odabrali drugu banku, koja pravnim osobama dopušta korištenje tokena. Jer kao što znamo, tokeni su jako nesigurni i zato ih pravne osobe ne bi smjele koristiti. A čitač kartice, kojeg 99% ljudi koristi tako da svoju smart karticu drži konstantno u čitaču, je izuzetno siguran. Odličan način stvaranja osjećaja prividne sigurnosti kod korisnika.
Evo i primjera iz stvarnog svijeta: kartica cijelo vrijeme u čitaču, na polici kraj kompjutera Zabin instalacijski paket koji sadrži i 4-znamenkasti PIN.

No, nastavimo sa svojim nalogom. Što točno znači “spremiti nalog”? Pretpostavljam da se kod njih na sustavu nalog prvo “sprema” da bi se kasnije “proveo”, samo neznam zašto bi mene kao korisnika zanimalo što se dešava ispod haube. Ja želim svoj nalog provesti, a ne spremiti. Glagol spremiti je kod mene asociran uz englesku riječ “save”, a to nije ono sto želim napraviti.
Nadalje, provođenje naloga je akcija. Prema tome čak i da je glagol “spremiti” ispravan za ovu namjenu, trebalo bi pisati “Spremi nalog” a ne “Spremanje naloga”. Ja nalažem sustavu da moj nalog “spremi”. Inače nisam ljubitelj lokaliziranih aplikacija (navike), ali koliko sam upoznat s hrvatskim lokalizacijama, meniji sadrže stavke “Spremi”, “Zatvori”, “Kopiraj”, “Izreži”. A ne “Spremanje”, “Kopiranje”, “Rezanje” i ostale imenice.

U trećem činu zbunjivanja korisnika, stavke “Izbriši sva polja”, “Izbor predloška” i “Spremanje naloga” predstavljene su linkovima. Linkovi asociraju na akciju koja ima navigacijski smisao. Link “Izbor predloška” ima smisla jer nas vodi na drugu lokaciju. S druge strane, stavke “Izbriši sva polja” i “Spremanje naloga” su akcije i moraju biti predstavljene gumbićem. Ispravan odabir kontrola pristuan je u odjeljku “UNOS NALOGA IZ DATOTEKE” (”Browse” gumbić). Nažalost, kad već hvalim odabir gumbića za “Browse” akciju, moram primjetiti kako to nije zasluga dizajnera stranice nego se gumbić pojavio u sklopu standardne kontrola za odabir datoteke, koju web majstori očito nisu bili u stanju niti lokalizirati. Sličnu situaciju opisao sam u proteklom postu - opet postoji jedna jedina kontrola koja nije lokalizirana, na stranici gdje je sve ostalo na hrvatskom. Za ne vjerovati, postoje ljudi koji neznaju engleski a htjeli bi možda koristiti ovu web aplikaciju. Ali bolje da ih uguramo u koš s onima koji ne koriste Windowse i ostalim luđacima.

I još malo šlaga za kraj. Nakon borbe sa spremanjem naloga i popunjavanjem polja, evo me konačno pred samim činom provođenja naloga. Tu postaje jasno kako je Zaba previdila još jednu sitnicu. Iako na nalogu koji je spreman za izvršenje postoji polje “Datum izvršenja”, čini se da je to samo ukras. Zaista je odlična pretpostavka da svaki nalog koji želim provesti, želim provesti sada. Vjerovatno je Zaba namjerno htjela ljudima ublažiti prijelaz sa šalterskog poslovanja na e-poslovanje. Ovdje je zaista analogno dolasku na šalter i plaćanju računa :)

A kada sam već izvršio nalog kojeg sam mislio izvršiti za par dana, kao vječni optimist nadao sam da će bar postojati opcija “Spremi izvršeni nalog kao predložak”. Ali čemu?

,

Dear readers, I apologize beforehand for writing this post in Croatian language. It’s a rant about the user experience of the e-banking web site of one of our biggest banks (Zagrebacka banka). It would be uninteresting to non-Croatians anyway. I hope banks in your countries have more competition and better-suited people at relevant positions :)

Pa da krenemo na hrvatski. Već se neko vrijeme premišljam o pisanju ovog posta, akumulirajući pritom nezadovoljstvo korištenjem e-bankarske web stranice Zagrebačke banke. Rijetko koja profesionalna web stranica, čija svrha nije samo čitanje već podrazumijeva izvjestan stupanj korisničke interakcije, sadrži ovoliku količinu nelogičnosti, nekonzistentnosti i, moram reći, neprofesionalnosti.

Krećući jutros u sakupljanje konkretnog materijala shvatio sam da ću neminovno morati ovu lamentaciju podijeliti u više od jednog posta, tako da - očekujte nastavak :)

Kao početnu napomenu, reći ću da je moja struka razvoj softvera. Nisam profesionalni dizajner korisničke interakcije, iako mi je ta sfera izuzetno zanimljiva. Volio bi da ovaj post pročitaju odgovorne osobe u Zagrebačkoj banci, možda ih potakne da krenu misliti o stvarima s kojima se njihovi korisnici/klijenti bore na dnevnoj bazi.

Post je dovoljno dug i bez dodatnog uvoda, pa bolje da krenem.

[caption id="attachment_70" align="alignleft" width="412" caption="Link za prijavu na sustav"]Link za prijavu na sustav[/caption]

U web preglednik upišem “http://www.zaba.hr”. Znajući već da moram kliknuti na link “bankarstvo” u sekciji “e-zaba za građane”, mišem dolazim na link već tijekom učitavanja. U tom trenutku me web stranica redovito prevari, ubacujući sličicu “VeriSign Secured” što rezultira naknadnim pomicanjem linka kojeg sam već “naciljao” mišem. Sitnica, ali jednom kad primjetite ne može a da ne smeta. Sličicu su zaista mogli staviti ispod navigacijskih linkova.

[caption id="attachment_71" align="alignleft" width="191" caption="Navigacija"]Navigacija[/caption]

Nakon uspješne prijave u sustav nalazim se na početnoj stranici. Zapravo, na stranici koja se samo zove “početna stranica”. Koncept početne stranice odnosi se na centralno mjesto jednog weba, mjesto s kojeg korisnik započinje svoju navigaciju i mjesto na koje se korisnik najlakše vraća. Upravo zato je početna stranica najčešće prva u navigacijskoj strukturi, ili je istaknuta na neki drugi način.

Na slici lijevo može se vidjeti zabina lokacija “Početne stranice”. Rezultat - svaki puta kada trebam na početnu stranicu iznova je tražim po meniju. Valja dodati kako se ponekad na prvoj navigacijskoj poziciji javlja izuzetno iritirajuća blinkajuća sličica koja vrišti “NOVA PORUKA”. Osim što izgleda na klasične navlakuše zlonamjernih web stranica koje svim silama žele privući vaš klik, svrha tog linka je da vas odvede u vaš osobni pretinac s porukama gdje ste dobili reklamu za zabinu novu uslugu. Zabo, hvala ti!

Inače, “početna stranica” je prilično logična, očekivano prikazuje stanja svih računa. U ovom postu baviti ću se najjednostavnijom funkcionalnošću e-bankarstva - pregledavanjem stanja na računu i dohvatom transakcija po istome. Budući da želim odabrati tekući račun, klikćem na njegov broj (ne bi škodilo da i opisni naziv, “tekući račun”, bude link na isto). Stranica na koju sam odveden prikazuje sve relevantne podatke za moj tekući račun, poput stanja, iznose prekoračenja i slično. Zabava počinje.

[caption id="attachment_74" align="alignleft" width="263" caption="Opcije"]Opcije[/caption]

Na slici lijevo prikazane su ponuđene opcije. U sljedećem ću postu više pažnje posvetiti (lošem) odabiru kontrola, zasad ću samo reći kako su sve opcije prikazane kao linkovi, iako je priroda istih potpuno drugačija. Linkovi asociraju na navigaciju i korisnik očekuje da će klikom na link biti odveden s trenutne stranice. S druge strane, akcija poput “Download” ili “Save” ili “Print” mora biti označena gumbićem. A kad smo već kod downloada, čini se da ta riječ ima čast biti jedina engleska riječ na sučelju. Zaista konzistentno :) Moglo je pisati “Dohvat datoteke …”, vjerujem da bi korisnici razumjeli. Dodatno, isti link spominje i “označene promete po računu”, iako se ne stranici ne mogu označiti nikakvi prometi. Postoji samo odabir vremenskog perioda, koji isto tako zaslužuje svojih 5 minuta slave.

[caption id="attachment_76" align="aligncenter" width="500" caption="Kalendari"][/caption]

Gornja slika prikazuje dio stranice namjenjen odabiru vremenskog intervala. Klik na sliku kalendarčića otvara prozorčić s kalendarom, no zanimljiv je odabir lokacije. Nije li logično da se prozorčić kalendara otvori u neposrednoj blizini kalendarčića na kojeg sam kliknuo? Zašto moram šetati mišem na drugi kraj zaslona?

Kad smo već kod odabira datuma, neugodno me iznenadila spoznaja da je “Prikaz prometa po računu” dostupan samo za period od godine dana. Nakon što sam odabrao datum koji je od danas udaljen manje od 365 dana, konačno sam uspio doći do nekih podataka. U mojem slučaju, dobio sam tablicu s preko 320 redova. U jednom komadu. Što se točno desilo straničenju (engl. paging) ? Iz mojeg iskustva, tablice podataka najčešće se raspodjeljuju na stranice od 20ak redaka. Ja sam upravo suočen sa tablicom visine 60ak centimetara.

Nažalost, to nije sve što primjećujem (odnosno ne primjećujem) kod ispisa prometa po računu. Polje “Opis” je prazno za sve transakcije u protekloj kalendarskoj godini. Zaista neznam koji bi mogao biti razlog tomu, osim čuvanja diskovnog prostora na poslužiteljima. U svakom slučaju, krasan odnos prema klijentu koji kod dotične banke ima najveći korisnički paket, stambenu štednju, kreditnu karticu i III. mirovinski fond. Nemogu ne imati osjećaj da imam “ograničeni” paket dok istovremeno neznam gdje da nadoplatim kako bi imao pristup svim svojim podacima (moj bankovni račun star je oko 10 godina).

Prilikom testiranja opcije “Download prikazanih podataka” greškom sam odabrao početni datum koji je veći od završnog. Sustav me uredno propustio na sljedeću stranicu koja nosi samo jednu informaciju: “Početni datum mora biti manji ili jednak današnjem datumu”. Mislim da je bilo jednostavnije to provjeriti JavaScriptom na klijentskoj strani, odnosno uopće ne dopustiti odabir besmislenog vremenskog perioda. Dodajmo to u košaru s nesmotrenostima koje razbijaju slijed korisničke interakcije.

Nadajući se da sam konačno pronašao vremenski period koji sustavu odgovara, gledam u link “Download označenih prometa po računu”. Što da očekujem pokretanjem te akcije? Ništa ne daje za naslutiti o kakvom je formatu datoteke riječ. Budući da je priroda podataka tablična, a aritmetičke operacije nad njima imaju smisla, za očekivati je nekakvu tabličnu (spreadsheet) datoteku.

[caption id="attachment_79" align="aligncenter" width="500" caption="Izvoz podataka"]Izvoz podataka[/caption]

Na moje razočaranje, datoteka koju sustav generira je u PDF formatu, a u gornjoj slici prikazan je dio iste. Saldo je naravno posve izmišljen i ne odgovara stvarnom stanju na mojem računu :)

Dokument izgleda sve samo ne profesionalno. Sadržaj ćelija dira njene rubove, ne postoji zaglavlje ili logo. Sve u svemu, ne može se razaznati da je riječ o dokumentu kojeg je izdala Zagrebačka banka. Uz navedeno, portabilnost (slovo P od PDF) kod ovog dokumenta nema nikakvog smisla, osim u slučaju da svoje stanje računa želim podijeliti sa svojim prijateljima. Pregled podataka ionako je moguć direktno s web stranice, tako da tu nema nikakve dodane vrijednosti. Vjerujem da nisam jedini koji numeričke podatke, pogotovo ovako stvarne, želi prikazati u vidu grafova, štrudli ili pita. Razočaran, usudio bi se reći da je čitava stvar razvijena u jedno popodne, koristeći neku gotovu programsku biblioteku za stvaranje PDF datoteka (iText?) s “defaultnim” postavkama. U svakom slučaju, daleko od nivoa kojeg očekujem od organizacije ovog kalibra.

Sumnjajući da je itko imao dovoljno strpljenja doći do ovog dijela posta, pozdravljam čitatelje do sljedećeg nastavka.

[Update: komentar kolege fressnera pogađa u sridu, u sljedećem nastavku istražujem misterij "spremanja" naloga]

,