You are viewing a plain text version of this content. The canonical link for it is here.
Posted to general@logging.apache.org by ps...@apache.org on 2008/09/10 07:15:03 UTC
svn commit: r693706 - in /logging/chainsaw/trunk/src: changes/changes.xml
main/java/org/apache/log4j/chainsaw/ChainsawCyclicBufferTableModel.java
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))) {