@D3X:
Ja w dużej mierze wiem jak działa Java pod spodem. Kiedyś przez wiele lat klepałem w czystym asemblerze i ręcznie optymalizowałem pod rozszerzenia procesora (typu MMX czy SSE2), deasemblowałem i łamałem programy (jakoś łatwiej mi było w taki sposób to robić niż przy użyciu debuggera), poznawałem architektury procesorów x86 (nawet zacząłem tłumaczyć tutoriale Agnera Foga na polski, ale nie opublikowałem tego), poczytałem o sposobie działania Garbage Collectora w Javie, poczytałem o optymalizacjach w JVMie (typu dynamiczna dewirtualizacja funkcji, dynamiczna deoptymalizacja, gdy poprzednie optymalizacje przestają się sprawdzać dla nowych danych, sprawdzanie zasięgu obiektów i alokowanie ich na stosie zamiast stercie jeśli się da, dynamiczne wklejanie funkcji w miejsce wywołania, itp itd). Rzeczy do ogarnięcia jest bardzo dużo i jeśli chciałbyś dobrze poznać temat od podszewki to musiałbyś posiedzieć nad tym wiele lat.
Z drugiej strony jednak doświadczenie z TDD zaprocentuje od razu, gdy zaczniesz tworzyć nietrywialne programy. Samo TDD jest w pewnym stopniu wyznacznikiem profesjonalizmu - programiście płaci się przede wszystkim za działający kod, a TDD pozwala na efektywne testowanie (i tanie, bo w pełni zautomatyzowane) i stabilny rozwój oprogramowania. Im szybciej przyzwyczaisz się do TDD tym lepiej, bo stare nawyki ciężko zmieniać.
O architekturze procesora przypominam sobie, gdy trzeba mocno zoptymalizować program pod kątem szybkości. Zdarza się to jednak bardzo rzadko w pracy komercyjnej. Jako hobby bardzo często, bo lubię sobie zakodzić jakiś algorytm sortowania czy kompresji, ale takich rzeczy się w pracy nie robi (korzysta się z gotowców).
Jeśli już bardzo chcesz schodzić na niski poziom to możesz zdeasemblować sobie bajtkod Javowy. Możesz to zrobić używając narzędzia javap
, które jest dostępne w JDK. Wycinek z manuala:
EXAMPLE
Compile the following DocFooter class:
import java.awt.*;
import java.applet.*;
public class DocFooter extends Applet {
String date;
String email;
public void init() {
resize(500,100);
date = getParameter("LAST_UPDATED");
email = getParameter("EMAIL");
}
public void paint(Graphics g) {
g.drawString(date + " by ",100, 15);
g.drawString(email,290,15);
}
}
The output from the javap DocFooter.class command yields the following:
Compiled from "DocFooter.java"
public class DocFooter extends java.applet.Applet {
java.lang.String date;
java.lang.String email;
public DocFooter();
public void init();
public void paint(java.awt.Graphics);
}
The output from javap -c DocFooter.class command yields the following:
Compiled from "DocFooter.java"
public class DocFooter extends java.applet.Applet {
java.lang.String date;
java.lang.String email;
public DocFooter();
Code:
0: aload_0
1: invokespecial #1 // Method
java/applet/Applet."<init>":()V
4: return
public void init();
Code:
0: aload_0
1: sipush 500
4: bipush 100
6: invokevirtual #2 // Method resize:(II)V
9: aload_0
10: aload_0
11: ldc #3 // String LAST_UPDATED
13: invokevirtual #4 // Method
getParameter:(Ljava/lang/String;)Ljava/lang/String;
16: putfield #5 // Field date:Ljava/lang/String;
19: aload_0
20: aload_0
21: ldc #6 // String EMAIL
23: invokevirtual #4 // Method
getParameter:(Ljava/lang/String;)Ljava/lang/String;
26: putfield #7 // Field email:Ljava/lang/String;
29: return
public void paint(java.awt.Graphics);
Code:
0: aload_1
1: new #8 // class java/lang/StringBuilder
4: dup
5: invokespecial #9 // Method
java/lang/StringBuilder."<init>":()V
8: aload_0
9: getfield #5 // Field date:Ljava/lang/String;
12: invokevirtual #10 // Method
java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
15: ldc #11 // String by
17: invokevirtual #10 // Method
java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
20: invokevirtual #12 // Method
java/lang/StringBuilder.toString:()Ljava/lang/String;
23: bipush 100
25: bipush 15
27: invokevirtual #13 // Method
java/awt/Graphics.drawString:(Ljava/lang/String;II)V
30: aload_1
31: aload_0
32: getfield #7 // Field email:Ljava/lang/String;
35: sipush 290
38: bipush 15
40: invokevirtual #13 // Method
java/awt/Graphics.drawString:(Ljava/lang/String;II)V
43: return
}
Porównując bajtkod z kodem źródłowym możesz z czasem nabrać intuicji jak kod Javowy będzie kompilował się do bajtkodu. Potem np będziesz mógł wziąć inny język na JVMa, np Scalę i porównać jak Scala kompiluje się do bajtkodu oraz porównać w czym jest podobna do Javy, a w czym różna jeśli chodzi właśnie o tą postać niskopoziomową.