001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: package org.apache.harmony.luni.platform;
019:
020: import java.lang.ref.ReferenceQueue;
021: import java.lang.ref.Reference;
022: import java.lang.ref.PhantomReference;
023: import java.util.HashMap;
024: import java.util.Map;
025:
026: /**
027: * Abstract implementation for the OS memory spies.
028: *
029: */
030: abstract class AbstractMemorySpy implements IMemorySpy {
031:
032: // TODO: figure out how to prevent this being a synchronization bottleneck
033: protected Map<PlatformAddress, AddressWrapper> memoryInUse = new HashMap<PlatformAddress, AddressWrapper>(); // Shadow to Wrapper
034:
035: protected Map<Reference, PlatformAddress> refToShadow = new HashMap<Reference, PlatformAddress>(); // Reference to Shadow
036:
037: protected ReferenceQueue<Object> notifyQueue = new ReferenceQueue<Object>();
038:
039: final class AddressWrapper {
040: final PlatformAddress shadow;
041:
042: final PhantomReference<PlatformAddress> wrAddress;
043:
044: volatile boolean autoFree = false;
045:
046: AddressWrapper(PlatformAddress address) {
047: super ();
048: this .shadow = address.duplicate();
049: this .wrAddress = new PhantomReference<PlatformAddress>(
050: address, notifyQueue);
051: }
052: }
053:
054: public AbstractMemorySpy() {
055: super ();
056: }
057:
058: public void alloc(PlatformAddress address) {
059: AddressWrapper wrapper = new AddressWrapper(address);
060: synchronized (this ) {
061: memoryInUse.put(wrapper.shadow, wrapper);
062: refToShadow.put(wrapper.wrAddress, wrapper.shadow);
063: }
064: }
065:
066: public boolean free(PlatformAddress address) {
067: AddressWrapper wrapper;
068: synchronized (this ) {
069: wrapper = memoryInUse.remove(address);
070: }
071: if (wrapper == null) {
072: // Attempt to free memory we didn't alloc
073: System.err
074: .println("Memory Spy! Fixed attempt to free memory that was not allocated " + address); //$NON-NLS-1$
075: }
076: return wrapper != null;
077: }
078:
079: public void rangeCheck(PlatformAddress address, int offset,
080: int length) throws IndexOutOfBoundsException {
081: // Do nothing
082: }
083:
084: /*
085: * (non-Javadoc)
086: *
087: * @see org.apache.harmony.luni.platform.struct.IMemorySpy#autoFree(org.apache.harmony.luni.platform.struct.PlatformAddress)
088: */
089: public void autoFree(PlatformAddress address) {
090: AddressWrapper wrapper;
091: synchronized (this ) {
092: wrapper = memoryInUse.get(address);
093: }
094: if (wrapper != null) {
095: wrapper.autoFree = true;
096: }
097: }
098:
099: protected void orphanedMemory(Reference ref) {
100: AddressWrapper wrapper;
101: synchronized (this ) {
102: PlatformAddress shadow = refToShadow.remove(ref);
103: wrapper = memoryInUse.get(shadow);
104: if (wrapper != null) {
105: // There is a leak if we were not auto-freeing this memory.
106: if (!wrapper.autoFree) {
107: System.err
108: .println("Memory Spy! Fixed memory leak by freeing " + wrapper.shadow); //$NON-NLS-1$
109: }
110: wrapper.shadow.free();
111: }
112: }
113: ref.clear();
114: }
115: }
|