Obsah
1. Skryté vlastnosti Oracle JDK
2. Archivní soubory alt-rt.jar a alt-string.jar
3. Za jakých podmínek se archivy alt-rt.jar a alt-string.jar použijí?
4. Výkonnostní rozdíly mezi použitím tříd z rt.jar a alt-rt.jar
5. Zdrojový kód testovacího příkladu
6. Výsledky běhu testovacího příkladu s JDK b24
7. Podpora pro alternativní knihovny v OpenJDK (IcedTea)
8. Další vliv volby -XX:+AggressiveOpts na výkonnost aplikací
1. Skryté vlastnosti Oracle JDK
V dnešní části seriálu o programovacím jazyku Java a jeho běhovém prostředí JRE (Java Runtime Environment) si povíme základní informace o jedné poměrně neznámé a málo využívané vlastnosti, kterou je možné využít především v proprietární Oracle JDK 6. Tato varianta JDK, nebo přesněji řečeno její běhové prostředí JRE, obsahuje, jak je to ostatně obvyklé, archivní soubor s názvem rt.jar, v němž jsou uloženy prakticky všechny třídy, rozhraní a výčtové typy tvořící aplikační programové rozhraní (API) J2SDK. Pouze několik spíše doplňkových tříd je uloženo v dalších archivech. Kromě toho však můžeme v novějších verzích JDK 6 najít i dva nové archivy, které jsou pojmenované alt-rt.jar a alt-string.jar (tento soubor najdeme až v B23). Tyto archivy jsou uloženy ve stejném podadresáři, v jakém leží i archiv rt.jar, tj. v podadresáři jre/lib/. Strukturu podadresáře jre/lib/ s výpisem všech javovských archivů (*.jar) si můžeme zobrazit například pomocí utility tree:
tree jre/lib -P "*.jar"
Struktura tohoto podadresáře je zhruba následující (povšimněte si hned prvního a druhého záznamu zvýrazněného hvězdičkami):
jre/lib |-- alt-rt.jar *** |-- alt-string.jar *** |-- amd64 | |-- headless | |-- jli | |-- motif21 | |-- native_threads | |-- server | `-- xawt |-- applet |-- audio |-- charsets.jar |-- cmm |-- deploy |-- deploy.jar |-- desktop | |-- applications | |-- icons | | |-- HighContrast | | | |-- 16x16 | | | | |-- apps | | | | `-- mimetypes | | | `-- 48x48 | | | |-- apps | | | `-- mimetypes | | |-- HighContrastInverse | | | |-- 16x16 | | | | |-- apps | | | | `-- mimetypes | | | `-- 48x48 | | | |-- apps | | | `-- mimetypes | | |-- LowContrast | | | |-- 16x16 | | | | |-- apps | | | | `-- mimetypes | | | `-- 48x48 | | | |-- apps | | | `-- mimetypes | | `-- hicolor | | |-- 16x16 | | | |-- apps | | | `-- mimetypes | | `-- 48x48 | | |-- apps | | `-- mimetypes | `-- mime | `-- packages |-- endorsed |-- ext | |-- dnsns.jar | |-- localedata.jar | |-- sunjce_provider.jar | `-- sunpkcs11.jar |-- fonts |-- im | |-- indicim.jar | `-- thaiim.jar |-- images | |-- cursors | `-- icons |-- javaws.jar |-- jce.jar |-- jsse.jar |-- locale | |-- de | | `-- LC_MESSAGES | |-- es | | `-- LC_MESSAGES | |-- fr | | `-- LC_MESSAGES | |-- it | | `-- LC_MESSAGES | |-- ja | | `-- LC_MESSAGES | |-- ko | | `-- LC_MESSAGES | |-- ko.UTF-8 | | `-- LC_MESSAGES | |-- sv | | `-- LC_MESSAGES | |-- zh | | `-- LC_MESSAGES | |-- zh.GBK | | `-- LC_MESSAGES | |-- zh_HK.BIG5HK | | `-- LC_MESSAGES | |-- zh_TW | | `-- LC_MESSAGES | `-- zh_TW.BIG5 | `-- LC_MESSAGES |-- management |-- management-agent.jar |-- oblique-fonts |-- plugin.jar |-- resources.jar |-- rt.jar |-- security | |-- US_export_policy.jar -> /etc/alternatives/jce_1.6.0_sun_us_export_policy.x86_64 | `-- local_policy.jar -> /etc/alternatives/jce_1.6.0_sun_local_policy.x86_64 |-- servicetag `-- zi |-- Africa |-- America | |-- Argentina | |-- Indiana | |-- Kentucky | `-- North_Dakota |-- Antarctica |-- Asia |-- Atlantic |-- Australia |-- Etc |-- Europe |-- Indian |-- Pacific `-- SystemV 98 directories, 18 files
2. Archivní soubory alt-rt.jar a alt-string.jar
Jak již název souborů alt-rt.jar a alt-string napovídá, jedná se o javovské archivy obsahující alternativní verze některých tříd tvořících standardní API J2SDK. Tyto alternativní třídy byly vytvořeny s ohledem na dosažení co nejlepšího výkonu (zejména v oficiálních benchmarcích běžících na počítačích s větším počtem procesorových jader, typicky se jedná o benchmark SPECjbb), ovšem prozatím by se tato implementace měla považovat za experimentální, i když na žádné větší problémy či chyby pravděpodobně v praxi nenarazíte (a ve skutečnosti byste ani neměli na problémy narazit, protože žádná z voleb předávaných JRE při jeho spouštění by neměla ovlivnit chování JRE do takové míry, že by došlo k chybě v některém testu kompatibility – TCK). Archiv alt-rt-jar obsahuje především binární (přeložené) podoby optimalizovaných verzí tříd HashMap, LinkedHashMap a TreeMap (tj. tříd implementujících rozhraní Map) a samozřejmě i různé pomocné třídy a rozhraní, popř. anonymní třídy.
Zatímco všechny tři výše zmíněné třídy uložené v archivu rt.jar neobsahují prakticky žádné optimalizace, které by zapříčinily větší složitost či menší čitelnost jejich zdrojového kódu (o čemž se ostatně můžete sami přesvědčit při pohledu do zdrojových kódů těchto tříd, například při zkoumání metod put a get), jsou v archivu alt-rt.jar umístěny třídy s optimalizovaným kódem využívajícím například vyrovnávací paměti pro ty prvky mapy, ke kterým se častěji přistupuje atd. V archivu alt-string.jar můžeme najít především upravenou variantu třídy String, která dokáže pracovat s „komprimovanými řetězci“, což je ovšem jen honosně znějící název pro běžné řetězce (které se používají například v céčku) obsahující pouze ASCII znaky. Pokud je vytvořen řetězec složený výhradně z ASCII znaků (tj. řetězec neobsahuje například znaky azbuky, nabodeníčka atd.), je uložen do pole s prvky typu byte a nikoli do pole s prvky typu char. To vede jak k úspoře paměti alokované na haldě, tak i k urychlení některých operací, protože se může pracovat s polovičním počtem bajtů pro daný řetězec.
3. Za jakých podmínek se archivy alt-rt.jar a alt-string.jar použijí?
Alternativní třídy obsažené v archivu alt-rt.jar a alt-string.jar se nepoužívají automaticky při každém startu běhového prostředí Javy. Načtou a použijí se pouze při splnění dvou podmínek. První podmínkou je, že daný archiv musí existovat, což je prozatím pouze případ Oracle JDK, nikoli však OpenJDK ani dalších variant JDK. Druhou podmínkou, která musí být splněna, je použití přepínače -XX:+AggressiveOpts při startu JRE. Pokud není alespoň jedna z těchto podmínek splněna, nevypíše se žádné chybové hlášení, ale třídy HashMap, TreeMap, String atd. se jednoduše načtou z originálního archivu rt.jar. O tom, zda se načítají původní verze tříd nebo jejich alternativní a výkonnější verze, se můžeme přesvědčit použitím přepínače -verbose při startu běhového prostředí Javy, například následujícím způsobem:
java -verbose | grep Opened
Při spuštění výše uvedeného příkazu, kde se pomocí přepínače -verbose povoluje výpis všech načítaných tříd a otevíraných archivů obsahujících tyto třídy (my ovšem většinu pro nás nepodstatných informací vyfiltrujeme), získáme následující výstup. Na různých verzích Oracle JDK a na různých platformách se mohou některé údaje odlišovat, především se to samozřejmě týká cesty k javovskému archivu:
[Opened /opt/jdk/sun/jdk1.6.0_23-x86_64/jre/lib/rt.jar]
Ovšem při použití přepínače -XX:+AggressiveOpts, tj. při spuštění následujícího příkazu:
java -XX:+AggressiveOpts -verbose | grep Opened
můžeme z vyfiltrovaného standardního výstupu zjistit, že se skutečně načítají i alternativní knihovny uložené v archivu alt-rt.jar:
[Opened /opt/jdk/sun/jdk1.6.0_23-x86_64/jre/lib/alt-rt.jar] [Opened /opt/jdk/sun/jdk1.6.0_23-x86_64/jre/lib/rt.jar]
4. Výkonnostní rozdíly mezi použitím tříd z rt.jar a alt-rt.jar
V předchozí kapitole jsme si řekli, že binární (přeložené) tvary tříd uložených v javovských archivech alt-rt.jar a alt-string.jar by měly být výkonnější než originální varianty těchto tříd. Ovšem toto tvrzení je samozřejmě nutné potvrdit (navíc toto tvrzení nemusí být platné za všech podmínek!), a to buď benchmarkem stávajících aplikací, například spuštěním serverové aplikace s přepínačem -XX:+AggressiveOpts s následným měřením doby odezvy této aplikace, nebo vytvořením syntetického testu zaměřeného pouze na zjištění rychlosti implementace tříd HashMap, LinkedHashMap a TreeMap. Pro účely změření výkonnosti metod Map.put() a Map.get() za stanovených podmínek jsem vytvořil jednoduchý příklad, jehož zdrojový kód lze najít v následující kapitole. V tomto příkladu se pro instance všech tří výše zmíněných tříd testuje rychlost, s jakou se do mapy vkládají objekty typu Integer, jejichž klíče jsou taktéž hodnoty typu Integer. Taktéž se zjišťuje rychlost získávání objektů z mapy metodou Map.get().
Důvod, proč je použita rostoucí číselná posloupnost klíčů, je jednoduchý – objekty jsou v hešovací mapě (instanci třídy HashMap) uspořádány na základě hešovací hodnoty (hash code) svého klíče, což je ovšem v případě instance třídy Integer přímo hodnota tohoto klíče (opět je možné se podívat do zdrojových kódů třídy Integer). Při „vhodně“ zvolené posloupnosti hodnot klíčů tedy může docházet ke kolizím, které účinnost hešovací mapy snižují. Naopak v případě použití třídy TreeMap jsou objekty v mapě uspořádány přímo na základě hodnoty klíče, přesněji řečeno na základě porovnání klíčů pomocí komparátorů. Číselná posloupnost hodnot klíčů či jejich hešovacích hodnot pak ovlivňuje interní strukturu mapy i dobu ukládání nového prvku a čtení prvku z mapy – například třída TreeMap interně využívá Red-Black stromy, jejichž struktura se při vkládání nových prvků musí měnit (viz animace dostupná na adrese http://www.aisee.com/anim/maple.htm).
5. Zdrojový kód testovacího příkladu
Ve zdrojovém kódu testovacího příkladu se používají třídy implementující rozhraní ValueGenerator, které slouží pro generování hodnot uložených v instancích třídy Integer. Klíče jsou však tvořeny jednoduchou aritmetickou posloupností celých čísel – sami si můžete vyzkoušet, jak se doba běhu aplikace změní v případě, že se pro vytváření klíčů (ne hodnot) použije odlišná posloupnost:
import java.util.Map; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.Random; import java.util.TreeMap; interface ValueGenerator { public void reset(); public Integer nextValue(); } class SequenceGenerator implements ValueGenerator { private int value = 0; @Override public Integer nextValue() { this.value++; return Integer.valueOf(this.value); } @Override public void reset() { this.value = 0; } } class InverseSequenceGenerator implements ValueGenerator { private int value = Integer.MAX_VALUE; @Override public Integer nextValue() { this.value--; return Integer.valueOf(this.value); } @Override public void reset() { this.value = Integer.MAX_VALUE; } } class RandomSequenceGenerator implements ValueGenerator { private static final long SEED = 42; private Random rand = new Random(SEED); @Override public Integer nextValue() { return Integer.valueOf(this.rand.nextInt()); } @Override public void reset() { this.rand.setSeed(SEED); } } public class MapBenchmark { private static final int EXT_LOOP_COUNT = 100; public static final int INT_LOOP_COUNT = 100000; public static long mapTest(Map<Integer, Integer> map, ValueGenerator generator) { long t1 = System.currentTimeMillis(); for (int j = 0; j < EXT_LOOP_COUNT; j++) { map.clear(); generator.reset(); for (int i = 0; i < INT_LOOP_COUNT; i++) { Integer I = Integer.valueOf(i); map.put(I, generator.nextValue()); } generator.reset(); for (int i = 0; i < INT_LOOP_COUNT; i++) { if (!map.get(Integer.valueOf(i)).equals(generator.nextValue())) throw new RuntimeException("Cannot find value"); } } long t2 = System.currentTimeMillis(); return t2 - t1; } private static void doTests(Map<Integer, Integer> map) { System.out.print(mapTest(map, new SequenceGenerator())+"\t"); System.out.print(mapTest(map, new InverseSequenceGenerator())+"\t"); System.out.print(mapTest(map, new RandomSequenceGenerator())+"\t"); } public static void main(String[] args) { long t1 = System.currentTimeMillis(); doTests(new HashMap<Integer, Integer>()); doTests(new LinkedHashMap<Integer, Integer>()); doTests(new TreeMap<Integer, Integer>()); long t2 = System.currentTimeMillis(); System.out.println(t2 - t1); } }
6. Výsledky běhu testovacího příkladu s JDK b24
V této kapitole jsou uvedeny výsledky tří běhů výše popsaného testovacího příkladu. V prvním běhu nebyla volba -XX:+AggressiveOpts použita, tudíž se načetly třídy z archivu rt.jar. Ve druhém případě sice byla výše zmíněná volba použita, ale soubor alt-rt.jar nebyl dostupný, takže opět došlo (bez výpisu varovného hlášení!) k načtení tříd z archivu rt.jar. Teprve ve třetím případu se díky použití volby -XX:+AggressiveOpts a dostupnosti archivu alt-rt.jar načetly alternativní verze knihoven, což mělo za daných podmínek pozitivní dopad na dobu běhu aplikace. Každý test byl spuštěný dvacetkrát, aby se omezily náhodné vlivy ostatních procesů běžících v systému.
Spuštění demonstračního příkladu bez dalších voleb (použit archiv rt.jar):
HashMap LinkedHashMap TreeMap Total seq invseq random seq invseq random seq invseq random time 2533 1996 2743 2549 2340 3046 5969 5861 6861 33913 2484 1991 2747 2575 2334 3051 5936 5912 6949 33996 2583 1754 2396 2415 2086 2688 5839 5801 6826 32392 2530 1992 2742 2623 2293 3113 6065 5868 6901 34134 2519 2008 2816 2780 2406 3117 6080 5870 6921 34525 2556 2063 2790 2816 2206 3067 5914 5803 6816 34036 2598 1999 2752 2970 2319 3050 5986 5923 6882 34485 2472 1981 2791 2456 2335 3070 5995 5913 6919 33939 2502 2060 2775 2818 2203 3059 5936 5847 6838 34053 2513 2046 2787 2629 2337 3122 5927 5655 6786 33816 2521 2007 2735 2969 2316 3065 5970 5939 6918 34447 2561 2005 2756 2454 2437 3203 5990 5904 6926 34251 2579 1782 2477 2623 2490 3294 5922 5778 6856 33807 2514 2053 2779 2789 2227 3072 6039 5862 6893 34233 2541 1995 2779 2584 2329 3102 5920 5901 6902 34059 2612 1997 2741 2951 2315 3045 6120 5895 6910 34592 2482 1982 2748 2497 2444 3195 5997 5684 6873 33916 2512 2048 2786 2785 2215 3063 5995 5898 6872 34186 2509 1989 2775 2970 2623 3347 5943 5707 6853 34720 2528 1986 2735 2935 2343 3054 6020 5877 6895 34387
Spuštění demonstračního příkladu s volbou -XX:+AggressiveOpts, ovšem ve chvíli, kdy není archiv alt-rt.jar dostupný (ve výsledku je použit archiv rt.jar):
HashMap LinkedHashMap TreeMap Total seq invseq random seq invseq random seq invseq random time 2684 2276 2794 2791 2443 3202 5949 5905 6767 34823 2692 2254 2820 2698 2450 3210 6055 5937 6837 34969 2705 2247 2788 2785 2467 3275 5924 5807 6703 34708 2680 2237 2798 2755 2427 3163 6004 5857 6762 34690 2733 2257 2803 2787 2744 3462 5998 5859 6717 35369 2639 2246 2797 2746 2448 3198 6013 6207 6979 35281 2497 2262 2939 2825 2509 3212 5991 5798 6755 34802 2643 2258 2782 2735 2477 3244 6011 5837 6727 34721 2666 2268 2837 2474 2418 3156 6049 5927 6843 34643 2701 2239 2771 2458 2470 3222 5979 5879 6730 34459 2680 2271 2801 2559 2344 3153 5962 5824 6782 34384 2660 2259 2858 2744 2448 3263 5970 5939 6748 34894 2669 2249 2800 2715 2663 3439 5982 5785 6753 35059 2692 2253 2809 2743 2432 3240 5956 5884 6766 34780 2675 1844 2511 2463 2396 3090 5909 5807 6742 33443 2705 2243 2787 2425 2444 3267 5935 5861 6752 34425 2704 2240 2794 2804 2404 3184 5989 5811 6723 34660 2709 2289 2819 2721 2444 3269 5935 5820 6699 34710 2680 2244 2792 2524 2378 3095 5994 5785 6742 34240 2688 2284 2824 2425 2447 3206 5948 5846 6783 34465
Spuštění demonstračního příkladu s volbou -XX:+AggressiveOpts ve chvíli, kde je archiv alt-rt.jar dostupný:
HashMap LinkedHashMap TreeMap Total seq invseq random seq invseq random seq invseq random time 2397 1886 2527 2433 2434 3159 4709 4379 5230 29162 2390 1833 2441 2861 2748 3428 4660 4363 5209 29942 2415 1792 2472 2715 2518 3174 4688 4362 5192 29334 2412 1781 2456 2664 2385 2994 4614 4290 5188 28804 2344 1761 2428 2658 2479 3130 4806 4338 5226 29177 2473 1886 2508 2743 2487 3148 4668 4346 5202 29467 2449 1795 2403 2620 2451 3220 4665 4498 5230 29339 2499 1742 2476 2556 2398 3080 4815 4198 5353 29140 2429 1799 2472 2691 2425 3191 4663 4369 5220 29264 2453 1803 2459 2724 2431 3188 4687 4174 5240 29173 2437 1785 2374 2554 2430 3172 4638 4280 5106 28783 2374 1841 2538 2519 2382 3116 4663 4153 5236 28841 2456 1765 2414 2493 2307 2924 4563 4188 5114 28230 2357 1824 2470 2663 2465 3180 4635 4355 5237 29193 2434 1855 2446 2750 2444 3173 6883 4357 5221 31569 2466 1791 2427 2536 2488 3175 4673 4347 5251 29170 2492 1892 2506 2690 2415 3153 4694 4380 5228 29465 2471 1791 2413 2299 2410 3017 4731 4175 5228 28543 2429 1679 2369 2395 2362 2960 4595 4234 5148 28176 2364 1838 2512 2694 2426 3209 4693 4332 5188 29261
Snadno můžeme vypočítat, že zrychlení demonstračního příkladu dosahuje za daných podmínek cca 15%.
7. Podpora pro alternativní knihovny v OpenJDK (IcedTea)
Zajímavé je, že podpora pro použití alternativního archivu alt-rt.jar (nikoli však alt-string.jar) existuje i v OpenJDK a tím pádem i v IcedTea. Ostatně se není čemu divit, protože zdrojové kódy OpenJDK i proprietární Oracle JDK jsou sdílené, i když některé relativně malé části OpenJDK musely být změněny, především kvůli nekompatibilním licencím a problémům s otevřením knihoven třetích stran (tj. knihoven dodaných dalšími vývojářskými firmami společnosti Sun Microsystems a posléze Oracle). Nicméně se vraťme k oběma alternativním archivům. Ve zdrojových kódech OpenJDK lze dohledat, že se alternativní archiv alt-rt.jar skutečně při spouštění JRE hledá a popř. i načítá, a to za stejných podmínek, jako u proprietární Oracle JDK. Ostatně přesvědčit se můžeme přímo pohledem do zdrojového kódu souboru hotspot/src/share/vm/runtime/arguments.cpp na řádky 2064 až 2077 (čísla řádků odpovídají HotSpotu verze 20, jehož zdrojové kódy lze najít na adrese http://hg.openjdk.java.net/hsx/hsx20/master):
if (AggressiveOpts) { // Insert alt-rt.jar between user-specified bootclasspath // prefix and the default bootclasspath. os::set_boot_path() // uses meta_index_dir as the default bootclasspath directory. const char* altclasses_jar = "alt-rt.jar"; size_t altclasses_path_len = strlen(get_meta_index_dir()) + 1 + strlen(altclasses_jar); char* altclasses_path = NEW_C_HEAP_ARRAY(char, altclasses_path_len); strcpy(altclasses_path, get_meta_index_dir()); strcat(altclasses_path, altclasses_jar); scp.add_suffix_to_prefix(altclasses_path); scp_assembly_required = true; FREE_C_HEAP_ARRAY(char, altclasses_path); }
Jediný problém spočívá v tom, že zdrojové kódy obou alternativních archivů nejsou prozatím v OpenJDK dostupné, i když je teoreticky možné (při dodržení licenčního ujednání potvrzeného při instalaci Oracle JDK) použít archivy právě z Oracle JDK.
8. Další vliv volby -XX:+AggressiveOpts na výkonnost aplikací
Použití volby -XX:+AggressiveOpts má poměrně velký vliv na výkonnost aplikací, a to i ve chvíli, kdy nejsou alternativní knihovny dostupné a/nebo používané. Vliv této volby si můžeme vyzkoušet na již mnohokrát ukazovaném příkladu ConcatTest1.java, který je upraven takovým způsobem, aby dokázal zobrazit čas konkatenace řetězce pro různé počty iterací, což má samozřejmě vliv jak na dobu trvání smyčky, tak i na obsazení haldy a zatížení správců paměti. Zdrojový tvar upraveného testovacího příkladu má tvar:
public class ConcatTest1 { private static final int MAX_LOOP_COUNT = 200000; public static String createString(int loopCount) { String str = ""; for (int i = 0; i < loopCount; i++) { str += i + " "; } return str; } public static void main(String[] args) { for (int loopCount = 256; loopCount < MAX_LOOP_COUNT; loopCount *= 2) { long t1 = System.currentTimeMillis(); String str = createString(loopCount); //System.out.println("String length: " + str.length()); long t2 = System.currentTimeMillis(); System.out.println("loops: " + loopCount + " time:" + (t2 - t1)); } } }
V následující tabulce jsou zobrazeny časy běhu „konkatenační smyčky“ v případě spuštění JVM bez volby -XX:+AggressiveOpts i s použitím této volby (výsledky byly získány s JDK b23 na platformě x86_64):
loopCount | JVM bez dalších voleb | Volba -XX:+AggressiveOpts | Zrychlení |
---|---|---|---|
256 | 6 | 4 | 33% |
512 | 15 | 8 | 47% |
1024 | 25 | 25 | 0% |
2048 | 58 | 74 | –28% ******* |
4096 | 222 | 222 | 0% |
8192 | 731 | 727 | 1% |
16384 | 2617 | 584 | 78% |
32768 | 13674 | 3156 | 77% |
65536 | 64446 | 16102 | 75% |
131072 | 317944 | 73220 | 77% |
Vliv této volby na běh JVM si vysvětlíme příště.
9. Odkazy na Internetu
- The Java Compatibility Test Tools: JavaTest Harness
http://java.sun.com/developer/technicalArticles/JCPtools2/ - Java HotSpot VM Options
http://www.oracle.com/technetwork/java/javase/tech/vmoptions-jsp-140102.html - HugePages
http://linux-mm.org/HugePages - Tuning big java heap and linux huge pages
http://www.tikalk.com/alm/forums/tuning-big-java-heap-and-linux-huge-pages - How do I set up hugepages in Red Hat Enterprise Linux 4
http://magazine.redhat.com/2007/05/29/how-do-i-set-up-hugepages-in-red-hat-enterprise-linux-4/ - Java SE Tuning Tip: Large Pages on Windows and Linux
http://blogs.sun.com/dagastine/entry/java_se_tuning_tip_large - Translation lookaside buffer
http://en.wikipedia.org/wiki/Translation_lookaside_buffer - Physical Address Extension
http://en.wikipedia.org/wiki/Physical_Address_Extension - Java HotSpot VM Options
http://www.oracle.com/technetwork/java/javase/tech/vmoptions-jsp-140102.html - Amdahl's law
http://en.wikipedia.org/wiki/Amdahl_law - Garbage collection (computer science)
http://en.wikipedia.org/wiki/Garbage_collection_(computer_science) - Dr. Dobb's | G1: Java's Garbage First Garbage Collector
http://www.drdobbs.com/article/printableArticle.jhtml?articleId=219401061&dept_url=/java/ - Java's garbage-collected heap
http://www.javaworld.com/javaworld/jw-08–1996/jw-08-gc.html - Compressed oops in the Hotspot JVM
http://wikis.sun.com/display/HotSpotInternals/CompressedOops - 32-bit or 64-bit JVM? How about a Hybrid?
http://blog.juma.me.uk/2008/10/14/32-bit-or-64-bit-jvm-how-about-a-hybrid/ - Compressed object pointers in Hotspot VM
http://blogs.sun.com/nike/entry/compressed_object_pointers_in_hotspot - Java HotSpot™ Virtual Machine Performance Enhancements
http://download.oracle.com/javase/7/docs/technotes/guides/vm/performance-enhancements-7.html - Using jconsole
http://download.oracle.com/javase/1.5.0/docs/guide/management/jconsole.html - jconsole – Java Monitoring and Management Console
http://download.oracle.com/javase/1.5.0/docs/tooldocs/share/jconsole.html - Great Computer Language Shootout
http://c2.com/cgi/wiki?GreatComputerLanguageShootout - x86–64
http://en.wikipedia.org/wiki/X86–64 - Physical Address Extension
http://en.wikipedia.org/wiki/Physical_Address_Extension - Java performance
http://en.wikipedia.org/wiki/Java_performance - 1.6.0_14 (6u14)
http://www.oracle.com/technetwork/java/javase/6u14–137039.html?ssSourceSiteId=otncn - Update Release Notes
http://www.oracle.com/technetwork/java/javase/releasenotes-136954.html - Java virtual machine: 4.10 Limitations of the Java Virtual Machine
http://java.sun.com/docs/books/jvms/second_edition/html/ClassFile.doc.html#88659 - Java™ Platform, Standard Edition 7 Binary Snapshot Releases
http://dlc.sun.com.edgesuite.net/jdk7/binaries/index.html - Trying the prototype
http://mail.openjdk.java.net/pipermail/lambda-dev/2010-August/002179.html - Better closures (for Java)
http://blogs.sun.com/jrose/entry/better_closures - Lambdas in Java: An In-Depth Analysis
http://www.infoq.com/articles/lambdas-java-analysis - Class ReflectiveOperationException
http://download.java.net/jdk7/docs/api/java/lang/ReflectiveOperationException.html - Proposal: Indexing access syntax for Lists and Maps
http://mail.openjdk.java.net/pipermail/coin-dev/2009-March/001108.html - Proposal: Elvis and Other Null-Safe Operators
http://mail.openjdk.java.net/pipermail/coin-dev/2009-March/000047.html - Java 7 : Oracle pushes a first version of closures
http://www.baptiste-wicht.com/2010/05/oracle-pushes-a-first-version-of-closures/ - Groovy: An agile dynamic language for the Java Platform
http://groovy.codehaus.org/Operators - Better Strategies for Null Handling in Java
http://www.slideshare.net/Stephan.Schmidt/better-strategies-for-null-handling-in-java - Control Flow in the Java Virtual Machine
http://www.artima.com/underthehood/flowP.html - Java Virtual Machine
http://en.wikipedia.org/wiki/Java_virtual_machine - ==, .equals(), compareTo(), and compare()
http://leepoint.net/notes-java/data/expressions/22compareobjects.html - New JDK7 features
http://openjdk.java.net/projects/jdk7/features/ - Project Coin: Bringing it to a Close(able)
http://blogs.sun.com/darcy/entry/project_coin_bring_close - ClosableFinder source code
http://blogs.sun.com/darcy/resource/ProjectCoin/CloseableFinder.java - Joe Darcy blog about JDK
http://blogs.sun.com/darcy - Java 7 – more dynamics
http://www.baptiste-wicht.com/2010/04/java-7-more-dynamics/ - ArrayList (JDK 1.4)
http://download.oracle.com/javase/1.4.2/docs/api/java/util/ArrayList.html