2017-03-14 17 views
5

Kiedy czytałem kod bajtowy jvm, z jakiejś małej funkcji java odkryłem, że kiedy nowa zmienna lokalna jest kaculated na stosie operandów, zakładając, że będzie przechowywana w tabeli zmiennych lokalnych, ale zwykle będzie załadowana do operandu stos natychmiast (tylko w sensie kodu bajtowego dosłownie). Nie rozumiem dobrze operacji, czy to niepotrzebna operacja?Dlaczego kod bajtowy java "zapisz" często następuje po "załadowaniu"?

+0

Przykład proszę. Trudno powiedzieć, o czym mówisz inaczej. Niemożliwe, naprawdę. – EJP

+0

Rozwiąż swoje pytanie, proszę. –

+0

Nie można w zadowalającym stopniu odpowiedzieć na to pytanie w komentarzu. Edytuj go na swoje pytanie, gdzie powinno być na pierwszym miejscu. – EJP

Odpowiedz

6

Kompilator Javy ma tendencję do kompilowania rzeczy w bardzo prosty i bezpośredni sposób, pozostawiając optymalizację JIT.

Na przykład, jeśli piszesz x *= 3; x *= 4;, prawdopodobnie będziesz dostać kodu bajtowego wzdłuż linii

iload_1 
iconst_3 
imul 
istore_1 
iload_1 
iconst_4 
imul 
istore_1 

Kompilator może teoretycznie dowiedzieć się, że para sklep/obciążenie jest zbędny i wyjąć go. Ale jest kilka powodów, aby tego nie robić - 1) to dodaje wiele komplikacji, bez żadnej korzyści, ponieważ JIT i tak optymalizuje wszystko 2) powoduje, że debugowanie jest trudniejsze, ponieważ nie masz już dostępu do wartości wszystkich zmiennych lokalnych 3) jeśli wyjątek zostanie w jakiś sposób wyrzucony w środku tego wyrażenia, zmienne lokalne będą miały niepoprawne wartości.

4

Patrząc na dspin kodu binarnego

Method void dspin() 
0 dconst_0  // Push double constant 0.0 
1 dstore_1  // Store into local variables 1 and 2 
2 goto 9   // First time through don't increment 
5 dload_1  // Push local variables 1 and 2 
6 dconst_1  // Push double constant 1.0 
7 dadd   // Add; there is no dinc instruction 
8 dstore_1  // Store result in local variables 1 and 2 
9 dload_1  // Push local variables 1 and 2 
10 ldc2_w #4  // Push double constant 100.0 
13 dcmpg   // There is no if_dcmplt instruction 
14 iflt 5   // Compare and loop if less than (i < 100.0) 
17 return   // Return void when done 

The tylko load który następuje store jest przesunięcie 9. Można zauważyć, że przesunięcie 9 można osiągnąć w dwóch różnych dróg: (1) od przesunięcie 2 z goto 9; oraz (2) kolejno z przesunięciem 8

dload_1 popycha wartości zmiennych lokalnych 1 i 2 na stosie argumentu (dwie zmienne ze względu double): w przypadku (1), gdy próbuje wejść do pętli po raz pierwszy, oraz w przypadku (2) przy próbie wejścia do pętli w późniejszych punktach czasowych.

Co ciekawe, w tym przykładzie zachowanie wszystkich store i load zachowań programu nie zmieni się. Jednak kompilator Java zwykle nie stara się być inteligentny. Kompiluje kod Java mniej lub bardziej bezpośrednio. W tym przypadku lokalna zmienna i bezpośrednio odpowiada zmiennym lokalnym 1 i 2.

Aby uzyskać więcej informacji, patrz Optimization by Java Compiler.

+0

Jeśli usunę wszystkie 'store' i' load', czy powyższy kod nadal będzie działał? –

+0

@ Q_SJ, zapoznaj się z edytowaną odpowiedzią. – dejvuth

+0

Jeśli dobrze cię rozumiem, masz na myśli, że w pewnej sytuacji javac naprawdę generuje dziwną parę 'store' i' load'. Czy mam rację? –

Powiązane problemy