4

私が一貫して得ているエラーメッセージは次のとおりです。

ロケーション 0x8 rip=0x10cf4ab28 の無効なメモリ アクセス

私がやっていることは、最新の Mac Os X で Java + Eclipse を使用して、さまざまなアルゴリズムにわたって株式/履歴データの膨大な配列を反復する、基本的な株式バックテスト システムを作成することです。

原因と思われるコードを追跡しました。大量のデータ配列を取得するために使用され、何千回も呼び出されるメソッド。何も保持されないので、メモリリークはないと思います。ただし、メモリエラーが発生する前に反復できる約7000回の制限があるようです。

奇妙なことは、デバッグモードで完全に機能することです。Eclipseでどのデバッグモードが異なるか知っている人はいますか?

jvm にメモリを追加しても効果はなく、-xint を使用すると問題なく動作するようです。また、デバッグモードでも完全に機能します。

public static List<Stock> getStockArray(ExchangeType e){
    List<Stock> stockArray = new ArrayList<Stock>();
    if(e == ExchangeType.ALL){
        stockArray.addAll(getStockArray(ExchangeType.NYSE));
        stockArray.addAll(getStockArray(ExchangeType.NASDAQ));
    }else if(e == ExchangeType.ETF){
        stockArray.addAll(etfStockArray);
    }else if(e == ExchangeType.NYSE){
        stockArray.addAll(nyseStockArray);
    }else if(e == ExchangeType.NASDAQ){
        stockArray.addAll(nasdaqStockArray);
    }
    return stockArray;
}

このような単純なループを何千回も繰り返すと、メモリ エラーが発生します。ただし、デバッグ モードではありません。

for (Stock stock : StockDatabase.getStockArray(ExchangeType.ETF)) {
    System.out.println(stock.symbol);
}
4

3 に答える 3

2

ロブ、コメントで多くの提案を使用すると、コードがはるかに効率的になり、メモリの使用量が大幅に減る可能性があります...これにより、元の問題が自然に修正されます。

public enum ExchangeType {
    ALL, ETF, NYSE, NASDAQ;

    private static EnumMap<ExchangeType, List<Stock> stocks;

    // Do this during your initialization routine, or if something changes
    public static loadStock(ExchangeType et, List<stock> stockList) {
        stocks.put(et, stockList);
    }

    public List<Stock> getStocks() {
        return stocks.get(this);
    }
}

次に、セキュリティのために、独自の実装を行うこともできますImmutableList...

public class ImmutableList<E> implements List<E> {
    private ArrayList<E> _internal;

    // Do something like this for modification methods
    public boolean add(E e) {
        throw new UnsupportedOperationException("This list is immutable!");
    }

    // Do something like this for access methods
    public E get(int index) {
        return _internal.get(index);
    }
}

これにより、メモリが制御され、パフォーマンスが大幅に向上します。

いずれにせよ、これで問題が解決しない場合は、他の多くの人がこれはおそらくJVMのバグであると述べています。あなたが指摘したように、コンパイルしきい値(すなわち-XX:CompileThreshold=100000)は、少なくとも今のところあなたの問題を解決するはずの迅速で汚い修正です...

于 2012-11-19T16:05:04.620 に答える
2

これはおそらく手遅れですが、この問題を抱えている他の人にとっては、これが修正方法です. 拡張 for ループを使用する代わりに、通常の for ループを使用します。私は真剣です。

元:

for(int stock = 0; stocks < StockDataBase.getStockArray(ExchangeType.ETF).size(); stock++)

そこから取ることができます。

これは、強化された for ループがループするたびに新しいオブジェクトを作成しているためですが、通常の for ループではそうではありません。ガベージ コレクターには、これらの新しいオブジェクトすべてを一度に処理する十分な時間がない可能性があります。

于 2013-06-25T22:18:28.170 に答える
0

最善の解決策ではありませんが、リストを変更しないと言うので、次のようなことを行うことができます。

public static List<Stock> getStockArray(ExchangeType e){
    if(e == ExchangeType.ALL){
        List<Stock> stockArray = new ArrayList<Stock>(nyseStockArray.size() + nasdaqStockArray.size());
        stockArray.addAll(nyseStockArray);
        stockArray.addAll(nasdaqStockArray);
        return stockArray;
    }else if(e == ExchangeType.ETF){
        return etfStockArray;
    }else if(e == ExchangeType.NYSE){
        return nyseStockArray;
    }else if(e == ExchangeType.NASDAQ){
        return nasdaqStockArray;
    } else {
       return new ArrayList<Stock>();
}
于 2012-11-19T15:50:29.673 に答える