Program: 85848
Project: 85848
Buggy source:
@Test public void testFinalizedBlocks() throws Exception {
  ECKey outKey=new ECKey();
  Block rollingBlock=unitTestParams.genesisBlock.createNextBlockWithCoinbase(outKey.getPubKey());
  chain.add(rollingBlock);
  TransactionOutPoint spendableOutput=new TransactionOutPoint(unitTestParams,0,rollingBlock.getTransactions().get(0).getHash());
  byte[] spendableOutputScriptPubKey=rollingBlock.getTransactions().get(0).getOutputs().get(0).getScriptBytes();
  for (int i=1; i < unitTestParams.getSpendableCoinbaseDepth(); i++) {
    rollingBlock=rollingBlock.createNextBlockWithCoinbase(outKey.getPubKey());
    chain.add(rollingBlock);
  }
  WeakReference<StoredTransactionOutput> out=new WeakReference<StoredTransactionOutput>(store.getTransactionOutput(spendableOutput.getHash(),spendableOutput.getIndex()));
  rollingBlock=rollingBlock.createNextBlock(null);
  Transaction t=new Transaction(unitTestParams);
  t.addOutput(new TransactionOutput(unitTestParams,t,Utils.toNanoCoins(50,0),new byte[]{}));
  addInputToTransaction(t,spendableOutput,spendableOutputScriptPubKey,outKey);
  rollingBlock.addTransaction(t);
  rollingBlock.solve();
  chain.add(rollingBlock);
  WeakReference<StoredUndoableBlock> undoBlock=new WeakReference<StoredUndoableBlock>(store.getUndoBlock(rollingBlock.getHash()));
  assertTrue(undoBlock.get() != null);
  assertTrue(undoBlock.get().getTransactions() == null);
  WeakReference<TransactionOutputChanges> changes=new WeakReference<TransactionOutputChanges>(undoBlock.get().getTxOutChanges());
  assertTrue(changes.get() != null);
  for (int i=0; i < UNDOABLE_BLOCKS_STORED; i++) {
    rollingBlock=rollingBlock.createNextBlock(null);
    chain.add(rollingBlock);
  }
  System.gc();
  assertTrue(undoBlock.get() == null);
  assertTrue(changes.get() == null);
  assertTrue(out.get() == null);
}

Fixed version (ground truth):
@Test public void testFinalizedBlocks() throws Exception {
  ECKey outKey=new ECKey();
  Block rollingBlock=unitTestParams.genesisBlock.createNextBlockWithCoinbase(outKey.getPubKey());
  chain.add(rollingBlock);
  TransactionOutPoint spendableOutput=new TransactionOutPoint(unitTestParams,0,rollingBlock.getTransactions().get(0).getHash());
  byte[] spendableOutputScriptPubKey=rollingBlock.getTransactions().get(0).getOutputs().get(0).getScriptBytes();
  for (int i=1; i < unitTestParams.getSpendableCoinbaseDepth(); i++) {
    rollingBlock=rollingBlock.createNextBlockWithCoinbase(outKey.getPubKey());
    chain.add(rollingBlock);
  }
  WeakReference<StoredTransactionOutput> out=new WeakReference<StoredTransactionOutput>(store.getTransactionOutput(spendableOutput.getHash(),spendableOutput.getIndex()));
  rollingBlock=rollingBlock.createNextBlock(null);
  Transaction t=new Transaction(unitTestParams);
  t.addOutput(new TransactionOutput(unitTestParams,t,Utils.toNanoCoins(50,0),new byte[]{}));
  addInputToTransaction(t,spendableOutput,spendableOutputScriptPubKey,outKey);
  rollingBlock.addTransaction(t);
  rollingBlock.solve();
  chain.add(rollingBlock);
  WeakReference<StoredUndoableBlock> undoBlock=new WeakReference<StoredUndoableBlock>(store.getUndoBlock(rollingBlock.getHash()));
  StoredUndoableBlock storedUndoableBlock=undoBlock.get();
  assertTrue(storedUndoableBlock != null);
  assertTrue(storedUndoableBlock.getTransactions() == null);
  WeakReference<TransactionOutputChanges> changes=new WeakReference<TransactionOutputChanges>(storedUndoableBlock.getTxOutChanges());
  assertTrue(changes.get() != null);
  storedUndoableBlock=null;
  for (int i=0; i < UNDOABLE_BLOCKS_STORED; i++) {
    rollingBlock=rollingBlock.createNextBlock(null);
    chain.add(rollingBlock);
  }
  System.gc();
  assertTrue(undoBlock.get() == null);
  assertTrue(changes.get() == null);
  assertTrue(out.get() == null);
}