Java EE 7 ja Java Community Process JCP

Pikahuomio: Java EE 7 on vahvasti suunnassaan, ja näyttäisi aikataulumielessä siltä että esiversio speksistä tulisi vuoden loppuun mennessä ja lopullinen EE 7 standardi saapuisi ensi vuoden loppupuolella eli mahdollisesti 2012 syyskuussa. Pääteemojahan ovat pilvipalvelut ja cachet, sekä tietysti kaikkien päärajapintojen päivityksiä ja korjauksia.

Toinen huomio jonka tein: Oracle suunnittelee elvyttää Java Community Processia Apachen lähdön jälkeen, teemoina mm. läpinäkyvyys, notkeus saada uusia spesifikaatioita ketterämmin, ja yhdistää jälleen me/se/ee alustat yhdeksi hallinnolliseksi Java alustakokonaisuudeksi. Toivottavasti tästä syntyy jotain hyvää, Apachen sanoutuminen irti Java standardien määrittelystä ja kehittämisestä iski syvälle Javan sydämeen, joskin muut open source tahot kuten esim. RedHat ovat astuneet kiitettävästi esiin paikkaamaan aukkoa.

Päivitys: Niin, huvittava juttu on että korjaus on itsessään JSR, JSR 348 joka tunnetaan myös nimellä JSR.next – saapa nähdä mitä siitä tulee.

http://jcp.org/en/jsr/summary?id=348

Mainokset

Netbeans 7, JDK 7, ja Googlen uudet puhelimet

Yep, tällä kertaa ei taas mitään koodeja, mutta mietelmiä. Netbeans 7 on ollut jo hetken aikaa jaossa ja käytössä, siirryin siihen heti ja mitään migraatio-ongelmia ei ole projekteilla ollut. Se on selkeästi parannettu versio aiemmasta, ja tukee myös Java 7:ää. Maven projektit siirtyivät heittämällä uuteen ja yhteensopivuus vanhaan Netbeansiin ei tuota ongelmia.

Java 7 developer preview on pyörinyt myös omassa kehityskoneessani jo hetken aikaa ja hienosti toimii, Netbeansin kera. Käytössä kaikki kivat uudet kielen piirteet ja kirjastot. Ainoa kysymysmerkki alustan suhteen on miten tuleva jako ilmaiseen ja kaupalliseen tulee menemään ja millaisia seurantatyökaluja kaikenkaikkiaan tulee maksuttoman Java-version mukana. Ainakin visualvm paranee entisestäänkin.

Google I/O konferenssi on pidetty ja Android alustalla on taas tiekarttaa näkyvissä.. Olen itse ihmetellyt miten Android 2.x ja 3.x sarjojen tulevaisuus menee, kun Honeycomb ei ole menossa kännyköihin millään aikataululla. Nyt se selvisi, tuleva Android alusta Ice Cream Sandwich (En edes pilaile, ihan tosi ;), yhdistää Gingerbread ja Honeycomb alustat ja on sekä mobiili että sormitietokoneiden käyttöjärjestelmä. Musiikkipalvelu on mukava lisä, taisin vertaillakin aiemmin Xoom ja IPad tabletteja ja Androidilla tuo sisältöpuoli on ollut heikompaa, palvelut sensijaan aika hyvässä iskussa samoin kuin alusta. Home Automation on myös kiinnostava alue, aina sen parissa on puuhasteltu – saa nähdä tuoko Android pakkaan jotain uutta.

http://java.dzone.com/articles/google-io-day-1-summary

EJB 3 Yksikkötestauksesta 4/3

Jep, otsikko ei ole virhe. Kirjailin aikanaan inspiroituneena artikkelisarjan siitä miten EJB 3.0 komponentteja voi yksikkötestata eri tavoin esim. test driven development hengessä tai vain 100% testikattavuuden merkeissä. Nyt tuli ajankohtaiseksi tehdä uusi täydennys koska kurssia pitäessä tuli puheeksi Java EE 6 Embedded Container malli, joten teen siitä tähän pienen muistion.

Yksi pienemmistä EE 6 päivityksistä oli Embedded Container, eli ohjelmakoodista käynnistettävä EJB säiliö joka sopii loistavasti esim. EJB komponenttien yksikkötestaukseen. Tässä esimerkki yksinkertaisen laskimen testauskoodista:

@Test
  public void hello() throws NamingException {
    EJBContainer ejbC = EJBContainer.createEJBContainer();
    Context ctx = ejbC.getContext();

    CalculatorBeanRemote helloWorld = 
      (CalculatorBeanRemote) ctx.lookup("java:global/classes/CalculatorBean");

    assertNotNull(helloWorld);
    double expected=11;
    double result = helloWorld.add(5, 6);
    assertEquals(expected, result, 0.0);
    ejbC.close();
}

Komento oli siis EJBContainer.createEJBContainer(). Tämä käynnistää kevyen sisäänrakennetun glassfish serverin, jolta voi pyytää Context tyyppisen viittauksen nimipalveluun, ja sieltä taas voi pyydää luokkia jotka ovat ejb annotaatiolla varustettuja ja löytyvät luokkapolusta – niitä ei siis tarvitse erikseen asentaa.

Huomioitavaa.. Container antaa mahdollisuuden testata beaniä säiliön elinkaaripalveluiden kera, joka antaa realistisemman kuvan. Toisaalta säiliön käynnistäminen vie hetken, vaatii porttiosoitteita, ja ei testaa luokkaa aidosti eristyksissä vaan on tosiasiassa enemmänkin integraatiotestausta. Mutta tällekin on varmasti käyttönsä ja valinnanvara ei ole yleensä huono juttu.

Tässä vielä vähän vertailua POJO tyyppisen yksikkötestin suoritusajasta vs Embedded Container yksikkötesti, molemmat netbeansissä junitilla.

Toki rehellisyyden nimissä myönnettävä että container käynnistyminen on kertaluonteinen operaatio eli se ei siitä enää paljoa hidastu kun lataat useampia EJB luokkia, näin siis 100 EJB testiä ei ole 100x7sekuntia vaan 100×0.07s + 7s 😉

Oracle vs Google

Java ja etenkin Android kehittäjät tietenkin seuraavat mielenkiinnolla miten titaanien taistelussa Oracle-Google käy. Kyseessähän on oikeusjuttu koskien Java patenttien käyttöä Android alustalla ja toisaalta nyt myös Apache Harmony virtuaalikoneessa.

Oikeudenkäynti esti viime vuonna mm. Googlen osallistumisen JavaOne tapahtumaan ja saattaa tehdä saman tänä vuonna. On myös ollut hupaisaa seurata miten jenkkituomaria on koulutettu ymmärtämään olioista ja ohjelmoinnista jotain, jotta hän voi tehdä päätöksiä.

Viimeisin jopa hieman yllättävä käänne joka osui silmiini on, että tuomari määräsi Oraclen tiputtamaan 132 syytöksestä määrän kolmeen, eli 98% kanteista pois. Tuomarilta tuli myös molemmille tahoille määräys miettiä kannattaako näiden kolmen jäljelle jääneen kanteen edestä taistella.

Mielenkiintoisia aikoja siis elämme. Puoleen tai toiseen jonkinmoisia päätöksiä tuosta pitäisi syntymän, ja kyseessähän on taas patentti-ennakkotapauksia jotka vaikuttavat kovasti mm. avoimen lähdekoodin ohjelmistojen käytettävyyteen ja toisaalta ohjelmistopatenttien vaikuttavuuteen. Java-kehittäjien kannalta tämä myös vaikuttaa siihen mikä on tulevaisuuden mobiilijava. Jos Oracle saa tahtonsa läpi, on luultavaa että Androidia taivutetaan jyrkemmin standardi java-talliin ja kenties korvataan java me sillä. Joka voi pistää kapuloita rattaisiin ja onnistua jopa hidastamaan itse Androidin marssia. Jos Google voittaa, Android jatkaa myrskyn lailla voittokulkuaan ja murskaa java me alustan (ainakin älypuhelimien osalta) lopullisesti, ja rökittää myös applen sun muiden tarjonnat lopullisesti. Mahdollista on myös jonkunasteinen kompromissi, itse luulen että jonkunmoinen neuvotteluasetelma on ollut alunperinkin tämän oikeusjupakan taustasyy, ei rojaltit tai korvaukset.

Seurataan tilannetta mielenkiinnolla. Muuten oma aika on pääosin mennyt Honeycomb sormitietokoneen ohjelmointi sekä REST integraatiohommissa.

Lähde:

http://www.groklaw.net/article.php?story=2011050505150858

Java, optimointi, ja muistivuodot

Hiljattain tuli konsultoinnin yhteydessä pohdiskeltua tarkemmin miten huonosti käyttäytyviä Java-sovelluksia tuunataan. Javassa alustanahan on pari erityispiirrettä jonka vuoksi se toimii eri tavalla kuin esim. C++.

– Koska Java on dynaaminen alusta, sen kokonaisympäristö selviää vasta ajon aikana, ja voi mahdollisesti poiketa kehitysympäristöstä. Tarkoittaa että esim. log4j kirjastosta voi olla eri tavoin toimiva kirjasto ajon aikana. Kenties näin ei pitäisi olla mutta näin useinkin on.

– Tehokkuudesta vastaa pääosin virtuaalikone, eli ajoympäristö, ja se onkin uskomattoman hyvä optimoimaan. Java koodi benchmarkattuna C++ koodia vastaan on viime aikoina useasti jopa rökittänyt kilpailijansa suoritusnopeudessa. Mutta virtuaalikone tekee parhaiten työntä koodille joka on selkeää ja kikkailematonta, vähän kuin rautalangasta väännettyä. Yksi pahimpia hölmöilyjä mitä voi tehdä on lisätä koodiinsa kutsu System.gc() sinne sun tänne. Virtuaalikoneen idea on nimenomaan skaalata sovellus ympäristön mukaan aina parhaiten optimoiduksi. Mitä enemmän koodi pyrkii pakottamaan ja rajoittamaan sitä huonommin automaattioptimointi voi toimia.

– Kooditasolla ei ole mitään erityisiä optimointi-avainsanoja kuten esim. inline.. Koodin optimoinnilla on muutenkin hyvin vähän merkitystä sujuvuuteen – kunhan siellä ei ole hölmöilty. Pääosa koodin optimointia on siis hölmöilyjen purkamista.

– Automaattinen roskankeruu on tunnettu tehosyöppö, edellämainityt hölmöilyt ovat usein koodia joka aiheuttaa tarpeetonta roskankeruuta. Tarpeeton roskankeruu syö prosessoritehoa ja pysäyttää suorittavat säikeet, eli mitä enemmän roskankeruuta tehdään sitä enemmän varastetaan kellosyklejä suorittavilta osilta. Näin ollen roskankeruun minimoiminen on hyvä lähtökohta suorituskyvyn parantamiselle. Mutta huom. tarpeettoman roskankeruun.

Suorituskykyä parannetaan siis roskankeruuta vähentämällä – tarpeetonta sellaista. Miten tämä tapahtuu? Pidentämällä olioiden elinkaarta ja lisäämällä uudelleenkäyttöä, välttämällä kaikkea turhaa olioiden luontia ja tuhoamista.  Tähän on monia keinoja: staattiset muuttujat ja alustusblokit, objektipoolit, cachet, valmiiksi lasketut tulokset, jne.

Muistivuotoja ei pitäisi Javassa periaatteessa olla – automaattisen roskankeruun ansiosta. Javassa kun ohjelmoija ei itse varaa muistia eikä vapauta muistia vaan nämä piirteet on abstraktoitu virtuaalikoneen tehtäviksi. Mutta virtuaalikoneessakin voi olla bugeja, ja missä hyvänsä JNI palikoissa voi olla ja todella usein onkin muistivuoto-ongelmia. Ja jos ohjelma yksinkertaisesti varaa olioita muistiin jatkuvasti eikä milloinkaan päästä niistä irti niin eipä roskankeruukaan voi toimia ja toki siinä muisti aikanaan sitten loppuu. Jos haluat saada java-sovelluksen kaatumaan muistiongelmaan et tarvi tätä enempää:

        List<String> list = new ArrayList();
        while(true)
            list.add("HELLOWORLD" + list.toString());

Tässä on IBM:n Developerworks-sivuilta hienostuneempi esimerkki joka esittää paria vivahdetta:

import java.io.IOException;
import java.util.HashSet;
import java.util.Random;
import java.util.Vector;

public class LeakExample {
	static Vector myVector = new Vector();
	static HashSet pendingRequests = new HashSet();

	public void slowlyLeakingVector(int iter, int count) {
		for (int i=0; i<iter; i++) {
			for (int n=0; n<count; n++) {
				myVector.add(Integer.toString(n+i));
			}
			for (int n=count-1; n>0; n--) {
				// Oops, it should be n>=0
				myVector.removeElementAt(n);
			}
		}
	}

	public void leakingRequestLog(int iter) {
		Random requestQueue = new Random();
		for (int i=0; i<iter; i++) {
			int newRequest = requestQueue.nextInt();
			pendingRequests.add(new Integer(newRequest));
			// processed request, but forgot to remove it
			// from pending requests
		}
	}

	public void noLeak(int size) {
		HashSet tmpStore = new HashSet();
		for (int i=0; i<size; ++i) {
			String leakingUnit = new String("Object: " + i);
			tmpStore.add(leakingUnit);
		}
		// Though highest memory allocation happens in this
		// function, but all these objects get garbage
		// collected at the end of this method, so no leak.
	}

	public static void main(String[] args) throws IOException {
		LeakExample javaLeaks = new LeakExample();
		for (int i=0; true; i++) {
			try { // sleep to slow down leaking process
				Thread.sleep(1000);
			} catch (InterruptedException e) { /* do nothing */ }
			System.out.println("Iteration: " + i);
			javaLeaks.slowlyLeakingVector(1000,10);
			javaLeaks.leakingRequestLog(5000);
			javaLeaks.noLeak(100000);
		}
	}
}

Miten tällaisia roskankeruuseen tai muistivuotoon liittyviä ongelmia sitten voi jahdata? Aika monellakin tapaa, Java tuo mukanaan jo useita työkaluja joiden avulla pääsee näkemään tarkemmin mitä virtuaalikoneen sisällä tapahtuu. Näistä on monesta kursseillakin asiaa, mutta viime aikoina olen perehtynyt enemmän visualvm työkaluun joka on jdk 6  uudemmissa versioissa sekä jdk 7:ssa vakiovarusteena. Sen saa ladatuksi myös erillisenä verkosta. VisualVM sisältää mahdollisuuden profiloida prosessorin käyttöä tai muistin käyttöä, ja sillä voi ottaa snapshotteja joita voi analysoida kaikessa rauhassa myöhemmin. Näin voi kiinnittää huomiota pisteisiin jossa käytetään paljon aikaa, tai jossa luodaan paljon olioita.

Miten em. muistivuoto sitten Javasta löytyy? Helposti. Otetaan snapshot tilanteesta, ja toinen snapshot jonkin aikaa myöhemmin. Muistivuodon tunnusmerkki ei ole että olio varaa paljon muistia. Muistivuodon tunnusmerkki on kasvu, josta kertoo kahden snapshotin delta, ero. Ja visualvm pystyy ottamaan kaksi snapshottia ja vertailemaan niitä, jolloin voidaan pistää oliot kasvun mukaan järjestykseen. Kovasti kasvava olio ei ole välttämättä signaali muistivuodosta, voi olla että se on vain kovasti kasvava olio 😉 Mutta jos ohjelmassa on muistivuoto, näiden joukosta se löytyy. Ellei se ole esim. virtuaalikoneen tai JNI moduulin bugi – koska nämä ovat java heapin ulkopuolella toimivia, ei niihin javan sisäiset välineet pure.

Yksi muistivuodoksi nimetty ongelma on se kun vastaanottaa ihastuttavan OutOfPermGenSpace -poikkeuksen. Tämä ei ole tosiasiassa varsinainen muistivuoto vaan ilmiö joka on joissain versioissa ilmentynyt mm. Tomcat ja JBOSS palvelimilla. Se aiheutuu kun serverille tehdään hot deploy operaatioita uudelleen ja uudelleen. Riippuen hot deploy toteutuksesta, java asentaessaan softan uuden version saattaa päätyä käyttämään enemmän ja enemmän permgen-aluetta kunnes se loppuu kesken. Tähän voi reagoida joko lisäämällä permgen alueen viipaletta (joka lykkää ongelman esiintymistä vähän pidemmälle), tai buuttaamalla serverin ihan oikeasti aika ajoin, esim. aina neljän hot deployn jälkeen, tai tarkistamalla että oma serveri tukee hot deployta ilman näitä oireita.

Yksi itseä kiehtova asia on rinnakkaisuuden jatkuva lisääntyminen. Omassa Xoom tabletissani on pari prosessoriydintä, samoin puhelimessani. Pöytäkoneissa on jo 2, 4, 8, ja pian 64 ydintä. Lisäboostia saa tekemällä asiat rinnakkain, silloin kun se on mahdollista, ja tähän tarvitaan tietysti osaamista jo suunnittelun alusta alkaen aina toteutustekniikoihin asti. Miten rinnakkaisessa maailmassa hallitaan jaettuja resursseja? Kiinnostavat projektit kuten Akka ja Scala vastaavat että Actor frameworkeillä ja postilaatikoilla. Java sanoo että synkronoinnilla ja lukituksilla. NIO tarjoaa sokettien osalta mukavan selector mallin jossa säikeitä tarvitaan vain kaksi, ja asiakkaita voi silti olla vaikka tuhat. Tässä ollaan vielä lastenkengissä, ja 2010 luku on rinnakkaisuuden vuosiluku, sanokaa minun sanoneen.

Tämä kirjoitelma syntyi Tehokas Java-kurssin tiimoilta, eli jos suorituskyvyn säätö Java-alustalla herättää kiinnostusta ja tässä artikkelissa tuli jotain uutta, niin kannattaa kurkata http://www.tieturi.fi/java alta ko kurssi esille.