Author: psmith
Date: Tue Sep 9 22:15:02 2008
New Revision: 693706
URL: http://svn.apache.org/viewvc?rev=693706&view=rev
Log:
Bug 42670 - Fixed memory leak in cyclic buffer mode.
The CyclicBufferListModel is designed to reduce memory consumption but over
time a HashSet keeping track of duplicate event IDs grows forever.
When the cyclic buffer is full, the oldest event will drop off the cliff, so
just prior to that we remove it's event ID from the HashSet.
Modified:
logging/chainsaw/trunk/src/changes/changes.xml
logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/ChainsawCyclicBufferTableModel.java
Modified: logging/chainsaw/trunk/src/changes/changes.xml
URL:
http://svn.apache.org/viewvc/logging/chainsaw/trunk/src/changes/changes.xml?rev=693706&r1=693705&r2=693706&view=diff
==============================================================================
--- logging/chainsaw/trunk/src/changes/changes.xml (original)
+++ logging/chainsaw/trunk/src/changes/changes.xml Tue Sep 9 22:15:02 2008
@@ -33,9 +33,10 @@
<action dev="psmith" issue="43158" type="add" due-to="Isuru
Suriarachchi" due-to-email="">
Added ability to remember last created receivers in an xml
file, and load them at startup.
</action>
- <action dev="psmith" issue="ASF Bugzilla Bug 42883" type="add"
due-to="Isuru Suriarachchi" due-to-email="">
+ <action dev="psmith" issue="42883" type="add" due-to="Isuru
Suriarachchi" due-to-email="">
Added ability to remember hidden log panels.
</action>
+ <action dev="psmith" issue="42670" type="fix">Address memory leak when
using cyclic model</action>
</release>
</body>
</document>
Modified:
logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/ChainsawCyclicBufferTableModel.java
URL:
http://svn.apache.org/viewvc/logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/ChainsawCyclicBufferTableModel.java?rev=693706&r1=693705&r2=693706&view=diff
==============================================================================
---
logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/ChainsawCyclicBufferTableModel.java
(original)
+++
logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/ChainsawCyclicBufferTableModel.java
Tue Sep 9 22:15:02 2008
@@ -28,10 +28,8 @@
import java.util.Iterator;
import java.util.List;
import java.util.Set;
-import java.awt.EventQueue;
import javax.swing.ProgressMonitor;
-import javax.swing.SwingUtilities;
import javax.swing.event.EventListenerList;
import javax.swing.table.AbstractTableModel;
@@ -40,8 +38,8 @@
import org.apache.log4j.chainsaw.helper.SwingHelper;
import org.apache.log4j.helpers.Constants;
import org.apache.log4j.rule.Rule;
-import org.apache.log4j.spi.LoggingEvent;
import org.apache.log4j.spi.LocationInfo;
+import org.apache.log4j.spi.LoggingEvent;
/**
@@ -60,6 +58,7 @@
*/
class ChainsawCyclicBufferTableModel extends AbstractTableModel
implements EventContainer, PropertyChangeListener {
+
private static final int DEFAULT_CAPACITY = 5000;
private boolean cyclic = true;
private int cyclicBufferSize = DEFAULT_CAPACITY;
@@ -68,22 +67,22 @@
Set idSet = new HashSet(cyclicBufferSize);
private boolean currentSortAscending;
private int currentSortColumn;
- private EventListenerList eventListenerList = new EventListenerList();
- private List columnNames = new ArrayList(ChainsawColumns.getColumnsNames());
+ private final EventListenerList eventListenerList = new EventListenerList();
+ private final List columnNames = new
ArrayList(ChainsawColumns.getColumnsNames());
private boolean sortEnabled = false;
private boolean reachedCapacity = false;
private final Logger logger =
LogManager.getLogger(ChainsawCyclicBufferTableModel.class);
// protected final Object syncLock = new Object();
- private LoggerNameModel loggerNameModelDelegate =
+ private final LoggerNameModel loggerNameModelDelegate =
new LoggerNameModelSupport();
//because we may be using a cyclic buffer, if an ID is not provided in the
property,
//use and increment this row counter as the ID for each received row
int uniqueRow;
- private Set uniquePropertyKeys = new HashSet();
+ private final Set uniquePropertyKeys = new HashSet();
private Rule displayRule;
- private PropertyChangeSupport propertySupport =
+ private final PropertyChangeSupport propertySupport =
new PropertyChangeSupport(this);
public ChainsawCyclicBufferTableModel(int cyclicBufferSize) {
@@ -92,6 +91,7 @@
unfilteredList = new CyclicBufferList(cyclicBufferSize);
filteredList = new CyclicBufferList(cyclicBufferSize);
+ idSet = new HashSet(cyclicBufferSize);
}
/* (non-Javadoc)
@@ -463,6 +463,21 @@
}
idSet.add(id);
+
+ /**
+ * If we're in cyclic mode and over budget on the size, the addition
of a new event will
+ * cause the oldest event to fall off the cliff. We need to remove
that events ID from the
+ * Set so we are not keeping track of IDs for all events ever received
(we'd run out of
+ * memory...)
+ */
+ if (isCyclic()) {
+ CyclicBufferList bufferList = (CyclicBufferList) unfilteredList;
+ if (bufferList.size() == bufferList.getMaxSize()) {
+ LoggingEvent aboutToBeDropped = (LoggingEvent)
unfilteredList.get(0);
+
idSet.remove(Integer.valueOf(aboutToBeDropped.getProperty(Constants.LOG4J_ID_KEY)));
+ reachedCapacity = true;
+ }
+ }
unfilteredList.add(e);
if ((displayRule == null) || (displayRule.evaluate(e))) {