<span id="7ztzv"></span>
<sub id="7ztzv"></sub>

<span id="7ztzv"></span><form id="7ztzv"></form>

<span id="7ztzv"></span>

        <address id="7ztzv"></address>

            原文地址:http://drops.wooyun.org/binary/6927

            54.13數組


            54.13.1簡單的例子 我們首先創建一個長度是10的整型的數組,對其初始化。

            #!java
            public static void main(String[] args)
            {
                int a[]=new int[10];
                for (int i=0; i<10; i++)
                a[i]=i;
                dump (a);
            }
            

            public static void main(java.lang.String[]);
            flags: ACC_PUBLIC, ACC_STATIC
            Code:
            stack=3, locals=3, args_size=1
            0: bipush 10
            2: newarray int
            4: astore_1
            5: iconst_0
            6: istore_2
            7: iload_2
            8: bipush 10
            10: if_icmpge 23
            13: aload_1
            14: iload_2
            15: iload_2
            16: iastore
            17: iinc 2, 1
            20: goto 7
            23: aload_1
            24: invokestatic #4 // Method dump:([?
            ? I)V
            27: return
            

            newarray指令,創建了一個有10個整數元素的數組,數組的大小設置使用bipush指令,然后結果會返回到棧頂。數組類型用newarry指令操作符,進行設定。

            newarray被執行后,引用(指針)到新創建的數據,棧頂的槽中,astore_1存儲引用指向到LVA的一號槽,main()函數的第二個部分,是循環的存儲值1到相應的素組元素。 aload_1得到數據的引用并放入到棧中。lastore將integer值從堆中存儲到素組中,引用當前的棧頂。main()函數代用dump()的函數部分,參數是,準備給aload_1指令的(行偏移23)

            現在我們進入dump()函數。

            #!java
            public static void dump(int a[])
            {
                for (int i=0; i<a.length; i++)
                System.out.println(a[i]);
            }
            

            #!bash
            public static void dump(int[]);
            flags: ACC_PUBLIC, ACC_STATIC
            Code:
            stack=3, locals=2, args_size=1
            0: iconst_0
            1: istore_1
            2: iload_1
            3: aload_0
            4: arraylength
            5: if_icmpge 23
            8: getstatic #2 // Field java/?
            ? lang/System.out:Ljava/io/PrintStream;
            11: aload_0
            12: iload_1
            13: iaload
            14: invokevirtual #3 // Method java/io?
            ? /PrintStream.println:(I)V
            17: iinc 1, 1
            20: goto 2
            23: return
            

            到了引用的數組在0槽,a.length表達式在源代碼中是轉化到arraylength指令,它取得數組的引用,并且數組的大小在棧頂。 iaload在行偏移13被用于裝載數據元素。 它需要在堆棧中的數組引用。用aload_0 11并且索引(用iload_1在行偏移12準備)

            無可厚非,指令前綴可能會被錯誤的理解,就像數組指令,那樣不正確,這些指令和對象的引用一起工作的。數組和字符串都是對象。

            54.13.2 數組元素的求和

            另外的例子

            #!java
            public class ArraySum
            {
                public static int f (int[] a)
                {
                    int sum=0;
                    for (int i=0; i<a.length; i++)
                    sum=sum+a[i];
                    return sum;
                }
            }
            

            public static int f(int[]);
            flags: ACC_PUBLIC, ACC_STATIC
            Code:
            stack=3, locals=3, args_size=1
            0: iconst_0
            1: istore_1
            2: iconst_0
            3: istore_2
            4: iload_2
            5: aload_0
            6: arraylength
            7: if_icmpge 22
            10: iload_1
            11: aload_0
            12: iload_2
            13: iaload
            14: iadd
            15: istore_1
            16: iinc 2, 1
            19: goto 4
            22: iload_1
            23: ireturn
            

            LVA槽0是數組的引用,LVA槽1是本地變量和。

            54.13.3 main()函數唯一的數據參數

            讓我們使用唯一的main()函數參數,字符串數組。

            #!java
            public class UseArgument
            {
                public static void main(String[] args)
                {
                    System.out.print("Hi, ");
                    System.out.print(args[1]);
                    System.out.println(". How are you?");
                }
            }
            

            934 0參(argument)第0個參數是程序(和C/C++類似)

            因此第一個參數,而第一參數是擁護提供的。

            public static void main(java.lang.String[]);
            flags: ACC_PUBLIC, ACC_STATIC
            Code:
            stack=3, locals=1, args_size=1
            0: getstatic #2 // Field java/?
            ? lang/System.out:Ljava/io/PrintStream;
            3: ldc #3 // String Hi,
            5: invokevirtual #4 // Method java/io?
            ? /PrintStream.print:(Ljava/lang/String;)V
            8: getstatic #2 // Field java/?
            ? lang/System.out:Ljava/io/PrintStream;
            11: aload_0
            12: iconst_1
            13: aaload
            14: invokevirtual #4 // Method java/io?
            ? /PrintStream.print:(Ljava/lang/String;)V
            17: getstatic #2 // Field java/?
            ? lang/System.out:Ljava/io/PrintStream;
            20: ldc #5 // String . How ?
            ? are you?
            22: invokevirtual #6 // Method java/io?
            ? /PrintStream.println:(Ljava/lang/String;)V
            25: return
            

            aload_0在11行加載,第0個LVA槽的引用(main()函數唯一的參數) iconst_1和aload在行偏移12,13,取得數組第一個元素的引用(從0計數) 字符串對象的引用在棧頂行14行偏移,給println方法。

            54.1.34 初始化字符串數組

            #!java
            class Month
            {
            
                public static String[] months =
                {
                    "January",
                    "February",
                    "March",
                    "April",
                    "May",
                    "June",
                    "July",
                    "August",
                    "September",
                    "October",
                    "November",
                    "December"
                };
                public String get_month (int i)
                {
                    return months[i];
                };
            }
            

            get_month()函數很簡單

            public java.lang.String get_month(int);
            flags: ACC_PUBLIC
            Code:
            stack=2, locals=2, args_size=2
            0: getstatic #2 // Field months:[?
            ? Ljava/lang/String;
            3: iload_1
            4: aaload
            5: areturn
            

            aaload操作數組引用,java字符串是一個對象,所以a_instructiong被用于操作他們.areturn返回字符串對象的引用。

            month[]數值是如果初始化的?

            static {};
            flags: ACC_STATIC
            Code:
            stack=4, locals=0, args_size=0
            0: bipush 12
            2: anewarray #3 // class java/?
            ? lang/String
            5: dup
            6: iconst_0
            7: ldc #4 // String January
            9: aastore
            10: dup
            11: iconst_1
            12: ldc #5 // String ?
            ? February
            14: aastore
            15: dup
            16: iconst_2
            17: ldc #6 // String March
            19: aastore
            20: dup
            21: iconst_3
            22: ldc #7 // String April
            24: aastore
            25: dup
            26: iconst_4
            27: ldc #8 // String May
            29: aastore
            30: dup
            31: iconst_5
            32: ldc #9 // String June
            34: aastore
            35: dup
            36: bipush 6
            38: ldc #10 // String July
            40: aastore
            41: dup
            42: bipush 7
            44: ldc #11 // String August
            46: aastore
            47: dup
            48: bipush 8
            50: ldc #12 // String ?
            ? September
            52: aastore
            53: dup
            54: bipush 9
            56: ldc #13 // String October
            58: aastore
            59: dup
            60: bipush 10
            62: ldc #14 // String ?
            ? November
            64: aastore
            65: dup
            66: bipush 11
            68: ldc #15 // String ?
            ? December
            70: aastore
            71: putstatic #2 // Field months:[?
            ? Ljava/lang/String;
            74: return
            

            937 anewarray 創建一個新數組的引用(a是一個前綴)對象的類型被定義在anewarray操作數中,它在這是“java/lang/string”文本字符串,在這之前的bipush 1L是設置數組的大小。 對于我們再這看到一個新指令dup,他是一個眾所周知的堆棧操作的計算機指令。用于復制棧頂的值。(包括了之后的編程語言)它在這是用于復制數組的引用。因為aastore張玲玲 起到彈出堆棧中的數組的作用,但是之后,aastore需要在使用一次,java編譯器,最好同dup代替getstatic指令,用于生成之前的每個數組的存貯操作。例如,月份字段。

            54.13.5可變參數 可變參數 變長參數函數,實際上使用的就是數組,實際使用的就是數組。

            #!java
            public static void f(int... values)
            {
                for (int i=0; i<values.length; i++)
                    System.out.println(values[i]);
            }
            public static void main(String[] args)
            {
                f (1,2,3,4,5);
            }
            

            public static void f(int...);
            flags: ACC_PUBLIC, ACC_STATIC, ACC_VARARGS
            Code:
            stack=3, locals=2, args_size=1
            0: iconst_0
            1: istore_1
            2: iload_1
            3: aload_0
            4: arraylength
            5: if_icmpge 23
            8: getstatic #2 // Field java/?
            ? lang/System.out:Ljava/io/PrintStream;
            11: aload_0
            12: iload_1
            13: iaload
            14: invokevirtual #3 // Method java/io?
            ? /PrintStream.println:(I)V
            17: iinc 1, 1
            20: goto 2
            23: return
            

            f()函數,取得一個整數數組,使用的是aload_0 在行偏移3行。取得到了一個數組的大小,等等。

            public static void main(java.lang.String[]);
            flags: ACC_PUBLIC, ACC_STATIC
            Code:
            stack=4, locals=1, args_size=1
            0: iconst_5
            1: newarray int
            3: dup
            4: iconst_0
            5: iconst_1
            6: iastore
            7: dup
            8: iconst_1
            9: iconst_2
            10: iastore
            11: dup
            12: iconst_2
            13: iconst_3
            14: iastore
            15: dup
            16: iconst_3
            17: iconst_4
            18: iastore
            19: dup
            20: iconst_4
            21: iconst_5
            22: iastore
            23: invokestatic #4 // Method f:([I)V
            26: return
            

            素組在main()函數是構造的,使用newarray指令,被填充慢了之后f()被調用。

            939 隨便提一句,數組對象并不是在main()中銷毀的,在整個java中也沒有被析構。因為JVM的垃圾收集齊不是自動的,當他感覺需要的時候。 format()方法是做什么的?它用兩個參數作為輸入,字符串和數組對象。

            public PrintStream format(String format, Object... args?)
            

            讓我們看一下。

            #!java
            public static void main(String[] args)
            {
                int i=123;
                double d=123.456;
                System.out.format("int: %d double: %f.%n", i, d?? );
            }
            

            public static void main(java.lang.String[]);
            flags: ACC_PUBLIC, ACC_STATIC
            Code:
            stack=7, locals=4, args_size=1
            0: bipush 123
            2: istore_1
            3: ldc2_w #2 // double 123.456?
            ? d
            6: dstore_2
            7: getstatic #4 // Field java/?
            ? lang/System.out:Ljava/io/PrintStream;
            10: ldc #5 // String int: %d?
            ? double: %f.%n
            12: iconst_2
            13: anewarray #6 // class java/?
            ? lang/Object
            16: dup
            17: iconst_0
            18: iload_1
            19: invokestatic #7 // Method java/?
            ? lang/Integer.valueOf:(I)Ljava/lang/Integer;
            22: aastore
            23: dup
            24: iconst_1
            25: dload_2
            26: invokestatic #8 // Method java/?
            ? lang/Double.valueOf:(D)Ljava/lang/Double;
            29: aastore
            30: invokevirtual #9 // Method java/io?
            ? /PrintStream.format:(Ljava/lang/String;[Ljava/lang/Object?
            ? ;)Ljava/io/PrintStream;
            33: pop
            34: return
            

            所以int和double類型是被首先普生為integer和double 對象,被用于方法的值。。。format()方法需要,對象雷翔的對象作為輸入,因為integer和double類是繼承于根類root。他們適合作為數組輸入的元素, 另一方面,數組總是同質的,例如,同一個數組不能含有兩種不同的數據類型。不能同時都把integer和double類型的數據同時放入的數組。

            數組對象的對象在偏移13行,整型對象被添加到在行偏移22. double對象被添加到數組在29行。

            倒數第二的pop指令,丟棄了棧頂的元素,因此,這些return執行,堆棧是的空的(平行)

            54.13.6 二位數組

            二位數組在java 中是一個數組去引用另外一個數組 讓我們來創建二位素組。()

            #!java
            public static void main(String[] args)
            {
                int[][] a = new int[5][10];
                a[1][2]=3;
            }
            

            public static void main(java.lang.String[]);
            flags: ACC_PUBLIC, ACC_STATIC
            Code:
            stack=3, locals=2, args_size=1
            0: iconst_5
            1: bipush 10
            3: multianewarray #2, 2 // class "[[I"
            7: astore_1
            8: aload_1
            9: iconst_1
            10: aaload
            11: iconst_2
            12: iconst_3
            13: iastore
            14: return
            

            它創建使用的是multianewarry指令:對象類型和維數作為操作數,數組的大小(10*5),返回到棧中。(使用iconst_5和bipush指令)

            行引用在行偏移10加載(iconst_1和aaload)列引用是選擇使用iconst_2指令,在行偏移11行。值得寫入和設定在12行,iastore在13 行,寫入數據元素?

            #!java
            public static int get12 (int[][] in)
            {
                return in[1][2];
            }
            

            public static int get12(int[][]);
            flags: ACC_PUBLIC, ACC_STATIC
            Code:
            stack=2, locals=1, args_size=1
            0: aload_0
            1: iconst_1
            2: aaload
            3: iconst_2
            4: iaload
            5: ireturn
            

            引用數組在行2加載,列的設置是在行3,iaload加載數組。

            54.13.7 三維數組 三維數組是,引用一維數組引用一維數組。

            #!java
            public static void main(String[] args)
            {
                int[][][] a = new int[5][10][15];
                a[1][2][3]=4;
                get_elem(a);
            }
            

            public static void main(java.lang.String[]);
            flags: ACC_PUBLIC, ACC_STATIC
            Code:
            stack=3, locals=2, args_size=1
            0: iconst_5
            1: bipush 10
            3: bipush 15
            5: multianewarray #2, 3 // class "[[[I"
            9: astore_1
            10: aload_1
            11: iconst_1
            12: aaload
            13: iconst_2
            14: aaload
            15: iconst_3
            16: iconst_4
            17: iastore
            18: aload_1
            19: invokestatic #3 // Method ?
            ? get_elem:([[[I)I
            22: pop
            23: return
            

            它是用兩個aaload指令去找right引用。

            #!java
            public static int get_elem (int[][][] a)
            {
                return a[1][2][3];
            }
            

            public static int get_elem(int[][][]);
            flags: ACC_PUBLIC, ACC_STATIC
            Code:
            stack=2, locals=1, args_size=1
            0: aload_0
            1: iconst_1
            2: aaload
            3: iconst_2
            4: aaload
            5: iconst_3
            6: iaload
            7: ireturn
            

            53.13.8總結

            在java中可能出現棧溢出嗎?不可能,數組長度實際就代表有多少個對象,數組的邊界是可控的,而發生越界訪問的情況時,會拋出異常。

            54.14 字符串 54.14.1 第一個例子

            字符串也是對象,和其他對象的構造方式相同。(還有數組)

            #!java
            public static void main(String[] args)
            {
                System.out.println("What is your name?");
                String input = System.console().readLine();
                System.out.println("Hello, "+input);
            }
            

            public static void main(java.lang.String[]);
            flags: ACC_PUBLIC, ACC_STATIC
            Code:
            stack=3, locals=2, args_size=1
            0: getstatic #2 // Field java/?
            ? lang/System.out:Ljava/io/PrintStream;
            3: ldc #3 // String What is?
            ? your name?
            5: invokevirtual #4 // Method java/io?
            ? /PrintStream.println:(Ljava/lang/String;)V
            8: invokestatic #5 // Method java/?
            ? lang/System.console:()Ljava/io/Console;
            11: invokevirtual #6 // Method java/io?
            ? /Console.readLine:()Ljava/lang/String;
            14: astore_1
            15: getstatic #2 // Field java/?
            ? lang/System.out:Ljava/io/PrintStream;
            18: new #7 // class java/?
            ? lang/StringBuilder
            21: dup
            22: invokespecial #8 // Method java/?
            ? lang/StringBuilder."<init>":()V
            25: ldc #9 // String Hello,
            27: invokevirtual #10 // Method java/?
            ? lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/?
            ? StringBuilder;
            30: aload_1
            31: invokevirtual #10 // Method java/?
            ? lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/?
            ? StringBuilder;
            34: invokevirtual #11 // Method java/?
            ? lang/StringBuilder.toString:()Ljava/lang/String;
            37: invokevirtual #4 // Method java/io?
            ? /PrintStream.println:(Ljava/lang/String;)V
            40: return
            

            944 在11行偏移調用了readline()方法,字符串引用(由用戶提供)被存儲在棧頂,在14行偏移,字符串引用被存儲在LVA的1號槽中。

            用戶輸入的字符串在30行偏移處重新加載并和 “hello”字符進行了鏈接,使用的是StringBulder類,在17行偏移,構造的字符串被pirntln方法打印。

            54.14.2 第二個例子 另外一個例子

            #!java
            public class strings
            {
                public static char test (String a)
                {
                    return a.charAt(3);
                };
                public static String concat (String a, String b)
                {
                    return a+b;
                }
            }
            

            public static char test(java.lang.String);
            flags: ACC_PUBLIC, ACC_STATIC
            Code:
            stack=2, locals=1, args_size=1
            0: aload_0
            1: iconst_3
            2: invokevirtual #2 // Method java/?
            ? lang/String.charAt:(I)C
            5: ireturn
            945
            

            字符串的鏈接使用用StringBuilder類完成。

            #!java
            public static java.lang.String concat(java.lang.String, java.?
            ? lang.String);
            flags: ACC_PUBLIC, ACC_STATIC
            Code:
            stack=2, locals=2, args_size=2
            0: new #3 // class java/?
            ? lang/StringBuilder
            3: dup
            4: invokespecial #4 // Method java/?
            ? lang/StringBuilder."<init>":()V
            7: aload_0
            8: invokevirtual #5 // Method java/?
            ? lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/?
            ? StringBuilder;
            11: aload_1
            12: invokevirtual #5 // Method java/?
            ? lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/?
            ? StringBuilder;
            15: invokevirtual #6 // Method java/?
            ? lang/StringBuilder.toString:()Ljava/lang/String;
            18: areturn
            

            另外一個例子

            #!java
            public static void main(String[] args)
            {
            String s="Hello!";
            int n=123;
            System.out.println("s=" + s + " n=" + n);
            }
            

            字符串構造用StringBuilder類,和它的添加方法,被構造的字符串被傳遞給println方法。

            #!bash
            public static void main(java.lang.String[]);
            flags: ACC_PUBLIC, ACC_STATIC
            Code:
            stack=3, locals=3, args_size=1
            0: ldc #2 // String Hello!
            2: astore_1
            3: bipush 123
            5: istore_2
            6: getstatic #3 // Field java/?
            ? lang/System.out:Ljava/io/PrintStream;
            9: new #4 // class java/?
            ? lang/StringBuilder
            12: dup
            13: invokespecial #5 // Method java/?
            ? lang/StringBuilder."<init>":()V
            16: ldc #6 // String s=
            18: invokevirtual #7 // Method java/?
            ? lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/?
            ? StringBuilder;
            21: aload_1
            22: invokevirtual #7 // Method java/?
            ? lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/?
            ? StringBuilder;
            25: ldc #8 // String n=
            27: invokevirtual #7 // Method java/?
            ? lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/?
            ? StringBuilder;
            30: iload_2
            31: invokevirtual #9 // Method java/?
            ? lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
            34: invokevirtual #10 // Method java/?
            ? lang/StringBuilder.toString:()Ljava/lang/String;
            37: invokevirtual #11 // Method java/io?
            ? /PrintStream.println:(Ljava/lang/String;)V
            40: return
            

            <span id="7ztzv"></span>
            <sub id="7ztzv"></sub>

            <span id="7ztzv"></span><form id="7ztzv"></form>

            <span id="7ztzv"></span>

                  <address id="7ztzv"></address>

                      亚洲欧美在线