WALA/com.ibm.wala.core/src/com/ibm/wala/util/ref/ReferenceCleanser.java

95 lines
2.9 KiB
Java

/*******************************************************************************
* Copyright (c) 2002 - 2006 IBM Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package com.ibm.wala.util.ref;
import java.lang.ref.WeakReference;
import com.ibm.wala.classLoader.IClass;
import com.ibm.wala.classLoader.IMethod;
import com.ibm.wala.classLoader.ShrikeCTMethod;
import com.ibm.wala.classLoader.ShrikeClass;
import com.ibm.wala.ipa.callgraph.AnalysisCacheImpl;
import com.ibm.wala.ipa.callgraph.IAnalysisCacheView;
import com.ibm.wala.ipa.cha.IClassHierarchy;
/**
* For some reason (either a bug in our code that defeats soft references, or a
* bad policy in the GC), leaving soft reference caches to clear themselves out
* doesn't work. Help it out.
*
* It's unfortunate that this class exists.
*/
public class ReferenceCleanser {
private final static float OCCUPANCY_TRIGGER = 0.5f;
private static WeakReference<IClassHierarchy> cha;
private static WeakReference<AnalysisCacheImpl> cache;
public static void registerClassHierarchy(IClassHierarchy cha) {
ReferenceCleanser.cha = new WeakReference<>(cha);
}
private static IClassHierarchy getClassHierarchy() {
IClassHierarchy result = null;
if (cha != null) {
result = cha.get();
}
return result;
}
public static void registerCache(IAnalysisCacheView cache) {
if (cache instanceof AnalysisCacheImpl) {
ReferenceCleanser.cache = new WeakReference<>((AnalysisCacheImpl) cache);
}
}
private static AnalysisCacheImpl getAnalysisCache() {
AnalysisCacheImpl result = null;
if (cache != null) {
result = cache.get();
}
return result;
}
/**
* A debugging aid. TODO: move this elsewhere
*/
public static void clearSoftCaches() {
float occupancy = 1f - ((float)Runtime.getRuntime().freeMemory() / (float)Runtime.getRuntime().totalMemory());
if (occupancy < OCCUPANCY_TRIGGER) {
return;
}
AnalysisCacheImpl cache = getAnalysisCache();
if (cache != null) {
cache.getSSACache().wipe();
}
IClassHierarchy cha = getClassHierarchy();
if (cha != null) {
for (IClass klass : cha) {
if (klass instanceof ShrikeClass) {
ShrikeClass c = (ShrikeClass) klass;
c.clearSoftCaches();
} else {
if (klass.getDeclaredMethods() != null) {
for (IMethod m : klass.getDeclaredMethods()) {
if (m instanceof ShrikeCTMethod) {
((ShrikeCTMethod)m).clearCaches();
}
}
}
}
}
}
}
}