2015-01-31 12 views
9

Jest to kod źródłowy mam:Kiedy i gdzie jest łańcuch inicjalizowany/przechowywany w kodzie źródłowym Java?

public class Koray { 
    public static void main(String [] args) { 
      System.out.println("This is a sample program."); 
    } 
} 

I kiedy to skompilować, otrzymuję kodu bajtowego. Kiedy patrzę na kod bajtowy z szesnastkowy widza widzę część:

19 54 68 69 73 20 69 73 20 61 20 73 61 6D 70 6C 65 20 70 72 6F 67 72 61 6D 2E 

które mogą być odczytywane jako

This is a sample program. 

jeżeli bajty są interpretowane jako znaki.

I kiedy zrobić

javap -c Koray.class 

należy zdemontować tę klasę widać:

Compiled from "Koray.java" 
public class Koray { 
    public Koray(); 
    Code: 
     0: aload_0  
     1: invokespecial #1     // Method java/lang/Object."<init>":()V 
     4: return   

    public static void main(java.lang.String[]); 
    Code: 
     0: getstatic  #2     // Field java/lang/System.out:Ljava/io/PrintStream; 
     3: ldc   #3     // String This is a sample program. 
     5: invokevirtual #4     // Method java/io/PrintStream.println:(Ljava/lang/String;)V 
     8: bipush  10 
     10: istore_1  
     11: return   
} 

Moje pytanie brzmi, gdzie jest to String widziany w zdemontowanego tekście? Widzę to tylko w komentarzu.

Odpowiedz

4

Zobacz ten ldcinstruction? Ładuje stałą ze puli stałej środowiska wykonawczego. Tam jest przechowywany twój ciąg. Aby wydrukować także pulę stałą, dodaj -verboseoption do wywołania javap.

+0

Czy możemy powiedzieć, że nie powinniśmy używać łańcuchów w kodzie źródłowym, ponieważ zapełni to pamięć, gdy klasa zostanie załadowana i nigdy nie zostanie usunięta z pamięć, ponieważ znajduje się w puli stałej? –

+0

@KorayTugay nie martw się, _interned_ Ciągi (i wszystkie literały łańcuchowe są _interned_) są przechowywane w stercie od JDK7. –

+0

@KorayTugay Używaj ich w kodzie źródłowym, jeśli czyni to kod jaśniejszym niż robienie czegoś innego. Obciążenie pamięci stałych łańcuchowych jest pomijalne. – chrylis

4
ldC#3; //String This is a sample program. 

Linia ta wykorzystuje opcodeldc, który ładuje stały na stosie argumentu. W tym momencie załadujemy cokolwiek, co jest w indeksie #3 naszej stałej tabeli bilardowej.

Stała tabela puli to miejsce, gdzie przechowywana jest większość stałych wartości literowych. (ref) Polecenie javap -c -verbose <classfile> dostarcza danych wyjściowych dla stałej tabeli puli.

Przykład Wydajność:

const #22 = String  #23; // This is a sample program 
const #23 = Asciz  This is a sample program; 

Więcej informacji z VM spec (http://java.sun.com/docs/books/jvms/second_edition/html/ClassFile.doc.html)

constant_pool tabelę struktury (§ 4.4) reprezentujących różne stałe łańcuchowe klasy i interfejs nazwy, nazwy pól i inne stałe określone w strukturze ClassFile i jej podstrukturach. Format każdego wpisu tabeli constant_pool to oznaczony pierwszym bajtem "znacznika". Tabela constant_pool jest indeksowana od 1 do constant_pool_count-1.

+0

Ale co jest w indeksie 3? –

+0

"Indeks 3" jest indeksem w tabeli. –

+0

Jakiej tabeli, możesz być bardziej szczegółowe? –

4

ldc #3 wczytuje ciąg stałe przechowywane w stałej puli, która jest oddzielna tabela przechowująca stałych takich jak String literałów i nazwy klas.

Zobacz http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html#jvms-4.4 ze specyfikacji JVM:

constant_pool jest stół struktur (§ 4.4) reprezentujących różne stałe ciągów znaków, nazw klas i interfejsów, nazwy pól i inne stałe, które są określone w ramach Struktura ClassFile i jej podstruktury. Format każdego wpisu tabeli constant_pool jest wskazywany przez jego pierwszy bajt "znacznika".

Możesz wyświetlić tabelę ciągów przy użyciu javap -verbose ClassName.

Wyjście próbki byłoby coś jak:

Compiled from "Test.java" 
public class tests.Test extends java.lang.Object 
    SourceFile: "Test.java" 
    minor version: 0 
    major version: 50 
    Constant pool: 
const #1 = class  #2;  // tests/Test 
const #2 = Asciz  tests/Test; 
const #3 = String  #4;  // This is a sample program. 
...