Java tutorial
/* * Copyright 2004-2012 the Seasar Foundation and the Others. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. See the License for the specific language * governing permissions and limitations under the License. */ package org.seasar.mayaa.impl.engine; import java.lang.ref.SoftReference; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.seasar.mayaa.ParameterAware; import org.seasar.mayaa.engine.specification.Specification; import org.seasar.mayaa.impl.util.ReferenceCache; /** * @author Taro Kato (Gluegent, Inc.) */ public class SpecificationCache { static final Log LOG = LogFactory.getLog(SpecificationCache.class); /** ??????????? */ protected static volatile boolean _sweepThreadAlive = true; protected int _surviveLimit; //@GuardedBy(this) protected Map _specifications = new HashMap(); protected ReferenceCache _gcChecker; protected SoftReference _gabage; public SpecificationCache(int surviveLimit) { _surviveLimit = surviveLimit; if (surviveLimit > 0 && !ParameterAware.IS_SECURE_WEB) { _gcChecker = new ReferenceCache(Object.class, ReferenceCache.SOFT, new GCReceiver()); postNewGabage(); } } protected static void relaseThread() { _sweepThreadAlive = false; } protected void postNewGabage() { Object gabage = new Object(); _gabage = new SoftReference(gabage); _gcChecker.add(gabage); } public boolean contains(String systemID) { synchronized (this) { return _specifications.containsKey(systemID); } } public Specification get(String systemID) { if (systemID == null) { throw new IllegalArgumentException(); } ReferSpecification refer; synchronized (this) { refer = (ReferSpecification) _specifications.get(systemID); } if (refer == null) { return null; } Specification result = refer.getSpecification(); if (refer.isDeprecated()) { return null; } return result; } public void add(Specification specification) { if (specification == null) { throw new IllegalArgumentException(); } synchronized (this) { Specification old = get(specification.getSystemID()); if (old != null) { if (old == specification) { return; } } ReferSpecification refer = new ReferSpecification(specification); _specifications.put(specification.getSystemID(), refer); } } public void release() { synchronized (this) { _specifications = null; relaseThread(); } } // support class private class ReferSpecification { private Specification _specification; private volatile int _survivingCount; volatile boolean _deprecated; public ReferSpecification(Specification specification) { if (specification == null) { throw new IllegalArgumentException(); } _specification = specification; } public Specification getSpecification() { // ????? _survivingCount = 0; return _specification; } public boolean isDeprecated() { if (_deprecated == false) { if (_specification.isDeprecated()) { _deprecated = true; } } return _deprecated; } public boolean requestRelease() { _survivingCount++; if (_survivingCount > _surviveLimit) { _survivingCount = 0; _deprecated = true; return true; } return false; } } private class GCReceiver implements ReferenceCache.SweepListener { private volatile int _receiveCount = 0; protected GCReceiver() { // do nothing. } public Object labeling(Object referent) { return new Integer(++_receiveCount); } public void sweepFinish(ReferenceCache monitor, Object label) { synchronized (SpecificationCache.this) { if (_specifications == null || _sweepThreadAlive == false) { return; } if (LOG.isDebugEnabled()) { LOG.debug("remove " + label + "th time." + " free:" + Runtime.getRuntime().freeMemory() + " / total:" + Runtime.getRuntime().totalMemory()); } List releaseItems = null; for (Iterator it = _specifications.values().iterator(); it.hasNext();) { ReferSpecification refer = (ReferSpecification) it.next(); if (refer.requestRelease()) { if (releaseItems == null) { releaseItems = new ArrayList(); } releaseItems.add(refer); } } if (releaseItems != null) { for (Iterator it = releaseItems.iterator(); it.hasNext();) { ReferSpecification refer = (ReferSpecification) it.next(); Specification spec = refer.getSpecification(); _specifications.remove(spec.getSystemID()); if (LOG.isDebugEnabled()) { LOG.debug("remove " + label + "th time. " + spec.getSystemID() + " remove from cache"); } } } postNewGabage(); /*gabage polling next*/ } } } }