00001 /* 00002 * HeapAnalyzer.hpp 00003 * 00004 * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. 00005 * 00006 * Oracle is a registered trademarks of Oracle Corporation and/or its 00007 * affiliates. 00008 * 00009 * This software is the confidential and proprietary information of Oracle 00010 * Corporation. You shall not disclose such confidential and proprietary 00011 * information and shall use it only in accordance with the terms of the 00012 * license agreement you entered into with Oracle. 00013 * 00014 * This notice may not be removed or altered. 00015 */ 00016 #ifndef COH_HEAP_ANALYZER_HPP 00017 #define COH_HEAP_ANALYZER_HPP 00018 00019 #include "coherence/lang/interface_spec.hpp" 00020 #include "coherence/lang/Object.hpp" 00021 #include "coherence/lang/TypedHandle.hpp" 00022 00023 COH_OPEN_NAMESPACE2(coherence,lang) 00024 00025 00026 /** 00027 * HeapAnalyzer provides a base diagnostics interface for tracking heap usage. 00028 * 00029 * There is at most one HeapAnalyzer registered with the system for the 00030 * lifetime of the process. The HeapAnalyzer implementation may be specified 00031 * via the "tangosol.coherence.heap.analyzer" system property. The property 00032 * can be set to one of the following values: 00033 * <ul> 00034 * <li>none No heap analysis will be performed.</li> 00035 * <li>object The coherence::lang::ObjectCountHeapAnalyzer will be used.</li> 00036 * <li>class The coherence::lang::ClassBasedHeapAnalyzer will be used.</li> 00037 * <li>alloc The coherence::lang::ClassBasedHeapAnalyzer will be used, 00038 * in allocation analysis mode.</li> 00039 * <li>[custom] The name of a class registered with the SystemClassLoader.</li> 00040 * </ul> 00041 * 00042 * In the case where a custom class is specified, it must implement this 00043 * interface. The custom analyzer will be initialized as soon as the class 00044 * is registered with the SystemClassLoader. As static initialization order 00045 * cannot be guaranteed, this custom analyzer will not be notified of managed 00046 * objects created earlier in the static initialization order. 00047 * 00048 * The active analyzer may be obtained from the System::getHeapAnalyzer() 00049 * method. 00050 * 00051 * The HeapAnalyzer and Snapshot interfaces are intentionally narrow. 00052 * Implementations are expected to provide useful information via the toStream 00053 * method, as well as by possibly augmenting the interfaces. The minimal 00054 * interface is sufficient for detecting memory leaks. 00055 * 00056 * HeapAnalyzer::Snapshot::View vSnap = hAnalyzer->capture(); 00057 * ... 00058 * ... 00059 * std::cout << "Heap changed by: " << hAnalyzer->delta(vSnap) << std::endl; 00060 * 00061 * @see ObjectCountHeapAnalyzer 00062 * @see ClassBasedHeapAnalyzer 00063 * 00064 * @author mf 2008.04.27 00065 */ 00066 class COH_EXPORT HeapAnalyzer 00067 : public interface_spec<HeapAnalyzer> 00068 { 00069 // ----- nested interface: Snapshot ------------------------------------- 00070 00071 public: 00072 /** 00073 * Snapshot provides a abstract mechanism for comparing successive 00074 * heap analysis points. 00075 */ 00076 class COH_EXPORT Snapshot 00077 : public interface_spec<Snapshot> 00078 { 00079 // ----- Snapshot interface --------------------------------- 00080 00081 public: 00082 /** 00083 * Return the number of registered objects reflected by this 00084 * snapshot. 00085 * 00086 * @return the number of registered objects 00087 */ 00088 virtual int64_t getObjectCount() const = 0; 00089 00090 /** 00091 * Return the result of "subtracting" the supplied Snapshot 00092 * from this Snapshot. 00093 * 00094 * @param vThat the snapshot to compare against 00095 * 00096 * @return the delta between two snapshots 00097 */ 00098 virtual Snapshot::View delta(Snapshot::View vThat) const = 0; 00099 }; 00100 00101 00102 // ----- HeapAnalyzer interface ----------------------------------------- 00103 00104 public: 00105 /** 00106 * Capture a Snapshot of the current state of the heap. 00107 * 00108 * Note, when performing captures in a loop, and assigning the captured 00109 * snapshot to a handle referencing a snapshot, it is advisable to 00110 * NULL out the handle first, so as to avoid the new snapshot including 00111 * the "cost" of snapshot it is about to replace. 00112 * 00113 * @return a Snapshot of the current state of the heap. 00114 */ 00115 virtual Snapshot::View capture() const = 0; 00116 00117 /** 00118 * Compute the delta between the supplied Snapshot and the current heap 00119 * state. 00120 * 00121 * @param vThat the snapshot to compare against. 00122 * 00123 * @return a snapshot containing the delta 00124 */ 00125 virtual Snapshot::View delta(Snapshot::View vThat) const = 0; 00126 00127 /** 00128 * Return the number of registered objects. 00129 * 00130 * @return the number of registered objects 00131 */ 00132 virtual int64_t getObjectCount() const = 0; 00133 00134 protected: 00135 /** 00136 * Register a newly created Object with the system. 00137 * 00138 * This method is called automatically by coherence::lang::Object once 00139 * the Object has finished construction. 00140 * 00141 * @param o the newly created Object. 00142 */ 00143 virtual void registerObject(const Object& o) = 0; 00144 00145 /** 00146 * Unregister an Object with the system. 00147 * 00148 * This method is called automatically by coherence::lang::Object 00149 * just prior to the deletion of the Object. No new handles or views 00150 * may be created to the object. 00151 * 00152 * @param o the Object to unregister 00153 */ 00154 virtual void unregisterObject(const Object& o) = 0; 00155 00156 00157 // ----- static helper methods ------------------------------------------ 00158 00159 public: 00160 /** 00161 * Ensure that the delta between the current heap and the supplied 00162 * snapshot is as expected. 00163 * 00164 * This method can be used to perform quick memory leak assertions. 00165 * 00166 * @code 00167 * HeapAnalyzer::Snapshot::View vSnapStart = HeapAnalyzer::ensureHeap(); 00168 * ... 00169 * ... 00170 * HeapAnalyzer::ensureHeap(vSnapStart); 00171 * @endcode 00172 * 00173 * @param vSnap the snapshot to ensure; or NULL for return only 00174 * @param cDelta the allowable change in the heap's object count 00175 * 00176 * @return a new Snapshot 00177 * 00178 * @throws IllegalStateException if the delta does not contain the 00179 * expected amount. The text of the exception will include the 00180 * output of the Snapshots toStream() method. 00181 */ 00182 static Snapshot::View ensureHeap(Snapshot::View vSnap = NULL, 00183 int64_t cDelta = 0); 00184 00185 00186 // ----- inner class: Block --------------------------------------------- 00187 00188 public: 00189 /** 00190 * The HeapAnalyzer::Block allows for easily verifying that a block 00191 * of code does not leak memory. 00192 * 00193 * @code 00194 * COH_ENSURE_HEAP 00195 * { 00196 * ... // your code here 00197 * } 00198 * @endcode 00199 */ 00200 class Block 00201 { 00202 // ----- constructors --------------------------------------- 00203 00204 public: 00205 /** 00206 * Construct a ZeroBlock object. 00207 * 00208 * This will automatically capture an initial snapshot 00209 */ 00210 Block() 00211 : m_vSnap(ensureHeap()) 00212 { 00213 } 00214 00215 /** 00216 * Copy constructor for COH_ENSURE_HEAP macro. 00217 */ 00218 Block(const Block& that) 00219 : m_vSnap(that.m_vSnap) 00220 { 00221 that.m_vSnap = NULL; 00222 } 00223 00224 /** 00225 * Destroy a Block object. 00226 * 00227 * This will test that no memory has been leaked 00228 */ 00229 ~Block() 00230 { 00231 ensureHeap(m_vSnap); 00232 } 00233 00234 00235 // ----- operators ------------------------------------------ 00236 00237 public: 00238 /* 00239 * Boolean conversion for use in COH_ENSURE_HEAP macro. 00240 * 00241 * @return false if snapshot is held, true otherwise 00242 */ 00243 operator bool() const 00244 { 00245 return m_vSnap == NULL; 00246 } 00247 00248 private: 00249 /** 00250 * Blocked assignment operator. 00251 */ 00252 const Block& operator=(const Block&); 00253 00254 /** 00255 * Blocked dynamic allocation. 00256 */ 00257 static void* operator new(size_t); 00258 00259 00260 // ----- data members --------------------------------------- 00261 00262 protected: 00263 mutable Snapshot::View m_vSnap; // on stack 00264 }; 00265 00266 // ----- friends -------------------------------------------------------- 00267 00268 friend class Object; 00269 }; 00270 00271 COH_CLOSE_NAMESPACE2 00272 00273 00274 /** 00275 * Macro for making more readable HeapAnalyzer::Block code blocks See the 00276 * documentation of Block for a usage example. 00277 * 00278 * @see coherence::lang::HeapAnalyzer::Block 00279 */ 00280 #define COH_ENSURE_HEAP \ 00281 if (coherence::lang::HeapAnalyzer::Block COH_UNIQUE_IDENTIFIER(_coh_heap_) \ 00282 = coherence::lang::HeapAnalyzer::Block()) \ 00283 { \ 00284 COH_THROW(coherence::lang::IllegalStateException::create()); \ 00285 } \ 00286 else 00287 00288 00289 #endif // COH_HEAP_ANALYZER_HPP