add
メソッドが何をするかを知ることができないため、コンパイラができることはあまりありません。ループ本体の生成コードを次に示します。ご覧のとおり、単純に呼び出しadd
て結果を保存します。
25: iload 5
27: iload 4
29: if_icmpge 51
32: aload_3
33: iload 5
35: aaload
36: astore 6
38: aload_1
39: aload 6
41: invokevirtual #5; //Method java/math/BigInteger.add:(Ljava/math/BigInteger;)Ljava/math/BigInteger;
44: astore_1
45: iinc 5, 1
48: goto 25
理論的には、Java 仮想マシンのランタイム システムの方が優れている可能性があります。たとえば、あるオブジェクトが割り当てられたばかりの別のオブジェクトを継続的に上書きしていることを検出し、2 つの割り当てバッファーを交換するだけです。ただし、ガベージ コレクションのログ記録を有効にして次のプログラムを実行するとわかるように、残念ながらそうではありません。
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Random;
class Test {
public static void main(String[] args) {
ArrayList <BigInteger> nums = new ArrayList<BigInteger>();
final int NBITS = 100;
final int NVALS = 1000000;
System.out.println("Filling ArrayList");
Random r = new Random();
for (int i = 0; i < NVALS; i++)
nums.add(new BigInteger(NBITS, r));
System.out.println("Adding ArrayList values");
BigInteger A = new BigInteger("0");
for(BigInteger n : nums) {
A = A.add(n);
}
System.gc();
}
}
追加プロセス中のガベージ コレクション呼び出しを参照してください。
C:\tmp>java -verbose:gc Test
Filling ArrayList
[GC 16256K->10471K(62336K), 0.0257655 secs]
[GC 26727K->21107K(78592K), 0.0304749 secs]
[GC 53619K->42090K(78592K), 0.0567912 secs]
[Full GC 42090K->42090K(122304K), 0.1019642 secs]
[GC 74602K->65857K(141760K), 0.0601406 secs]
[Full GC 65857K->65853K(182144K), 0.1485418 secs]
Adding ArrayList values
[GC 117821K->77213K(195200K), 0.0381312 secs]
[GC 112746K->77245K(228288K), 0.0111372 secs]
[Full GC 77245K->137K(228288K), 0.0327287 secs]
C:\tmp>java -version
java version "1.6.0_25"
Java(TM) SE Runtime Environment (build 1.6.0_25-b06)
Java HotSpot(TM) 64-Bit Server VM (build 20.0-b11, mixed mode)