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;
}

像这样的简单循环,迭代超过 1000 次,将导致内存错误。但不在调试模式下。

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

3 回答 3

2

Rob,如果您在评论中使用很多建议,您的代码可能会更有效率并使用更少的内存......这自然会解决您最初的问题。

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(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 回答