001/**
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements.  See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership.  The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License.  You may obtain a copy of the License at
009 *
010 *     http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018package org.apache.hadoop.hbase.io;
019
020import static org.junit.Assert.assertEquals;
021import static org.junit.Assert.assertTrue;
022
023import java.io.IOException;
024import java.lang.management.ManagementFactory;
025import java.lang.management.RuntimeMXBean;
026import java.nio.ByteBuffer;
027import java.util.ArrayList;
028import java.util.LinkedList;
029import java.util.Map;
030import java.util.TreeMap;
031import java.util.concurrent.ConcurrentHashMap;
032import java.util.concurrent.ConcurrentSkipListMap;
033import java.util.concurrent.CopyOnWriteArrayList;
034import java.util.concurrent.CopyOnWriteArraySet;
035import java.util.concurrent.atomic.AtomicBoolean;
036import java.util.concurrent.atomic.AtomicInteger;
037import java.util.concurrent.atomic.AtomicLong;
038import java.util.concurrent.atomic.AtomicReference;
039import java.util.concurrent.locks.ReentrantReadWriteLock;
040import org.apache.hadoop.hbase.HBaseClassTestRule;
041import org.apache.hadoop.hbase.KeyValue;
042import org.apache.hadoop.hbase.client.Delete;
043import org.apache.hadoop.hbase.client.Mutation;
044import org.apache.hadoop.hbase.client.Put;
045import org.apache.hadoop.hbase.io.hfile.BlockCacheKey;
046import org.apache.hadoop.hbase.io.hfile.ExclusiveMemHFileBlock;
047import org.apache.hadoop.hbase.io.hfile.HFileBlock;
048import org.apache.hadoop.hbase.io.hfile.HFileContext;
049import org.apache.hadoop.hbase.io.hfile.LruBlockCache;
050import org.apache.hadoop.hbase.io.hfile.LruCachedBlock;
051import org.apache.hadoop.hbase.io.hfile.SharedMemHFileBlock;
052import org.apache.hadoop.hbase.regionserver.CSLMImmutableSegment;
053import org.apache.hadoop.hbase.regionserver.CellArrayImmutableSegment;
054import org.apache.hadoop.hbase.regionserver.CellArrayMap;
055import org.apache.hadoop.hbase.regionserver.CellSet;
056import org.apache.hadoop.hbase.regionserver.CompactingMemStore;
057import org.apache.hadoop.hbase.regionserver.CompactionPipeline;
058import org.apache.hadoop.hbase.regionserver.DefaultMemStore;
059import org.apache.hadoop.hbase.regionserver.HRegion;
060import org.apache.hadoop.hbase.regionserver.HStore;
061import org.apache.hadoop.hbase.regionserver.ImmutableSegment;
062import org.apache.hadoop.hbase.regionserver.MemStoreCompactor;
063import org.apache.hadoop.hbase.regionserver.MutableSegment;
064import org.apache.hadoop.hbase.regionserver.Segment;
065import org.apache.hadoop.hbase.regionserver.TimeRangeTracker.NonSyncTimeRangeTracker;
066import org.apache.hadoop.hbase.regionserver.TimeRangeTracker.SyncTimeRangeTracker;
067import org.apache.hadoop.hbase.regionserver.throttle.StoreHotnessProtector;
068import org.apache.hadoop.hbase.testclassification.IOTests;
069import org.apache.hadoop.hbase.testclassification.SmallTests;
070import org.apache.hadoop.hbase.util.ClassSize;
071import org.junit.BeforeClass;
072import org.junit.ClassRule;
073import org.junit.Test;
074import org.junit.experimental.categories.Category;
075import org.slf4j.Logger;
076import org.slf4j.LoggerFactory;
077
078/**
079 * Testing the sizing that HeapSize offers and compares to the size given by
080 * ClassSize.
081 */
082@Category({IOTests.class, SmallTests.class})
083public class TestHeapSize  {
084
085  @ClassRule
086  public static final HBaseClassTestRule CLASS_RULE =
087      HBaseClassTestRule.forClass(TestHeapSize.class);
088
089  private static final Logger LOG = LoggerFactory.getLogger(TestHeapSize.class);
090  // List of classes implementing HeapSize
091  // BatchOperation, BatchUpdate, BlockIndex, Entry, Entry<K,V>, HStoreKey
092  // KeyValue, LruBlockCache, Put, WALKey
093
094  @BeforeClass
095  public static void beforeClass() throws Exception {
096    // Print detail on jvm so we know what is different should below test fail.
097    RuntimeMXBean b = ManagementFactory.getRuntimeMXBean();
098    LOG.info("name=" + b.getName());
099    LOG.info("specname=" + b.getSpecName());
100    LOG.info("specvendor=" + b.getSpecVendor());
101    LOG.info("vmname=" + b.getVmName());
102    LOG.info("vmversion=" + b.getVmVersion());
103    LOG.info("vmvendor=" + b.getVmVendor());
104    Map<String, String> p = b.getSystemProperties();
105    LOG.info("properties=" + p);
106  }
107
108  /**
109   * Test our hard-coded sizing of native java objects
110   */
111  @Test
112  public void testNativeSizes() throws IOException {
113    Class<?> cl;
114    long expected;
115    long actual;
116
117    // ArrayList
118    cl = ArrayList.class;
119    expected = ClassSize.estimateBase(cl, false);
120    actual = ClassSize.ARRAYLIST;
121    if(expected != actual) {
122      ClassSize.estimateBase(cl, true);
123      assertEquals(expected, actual);
124    }
125
126    // ByteBuffer
127    cl = ByteBuffer.class;
128    expected = ClassSize.estimateBase(cl, false);
129    actual = ClassSize.BYTE_BUFFER;
130    if(expected != actual) {
131      ClassSize.estimateBase(cl, true);
132      assertEquals(expected, actual);
133    }
134
135    // Integer
136    cl = Integer.class;
137    expected = ClassSize.estimateBase(cl, false);
138    actual = ClassSize.INTEGER;
139    if(expected != actual) {
140      ClassSize.estimateBase(cl, true);
141      assertEquals(expected, actual);
142    }
143
144    // Map.Entry
145    // Interface is public, all others are not.  Hard to size via ClassSize
146//    cl = Map.Entry.class;
147//    expected = ClassSize.estimateBase(cl, false);
148//    actual = ClassSize.MAP_ENTRY;
149//    if(expected != actual) {
150//      ClassSize.estimateBase(cl, true);
151//      assertEquals(expected, actual);
152//    }
153
154    // Object
155    cl = Object.class;
156    expected = ClassSize.estimateBase(cl, false);
157    actual = ClassSize.align(ClassSize.OBJECT);
158    if(expected != actual) {
159      ClassSize.estimateBase(cl, true);
160      assertEquals(expected, actual);
161    }
162
163    // TreeMap
164    cl = TreeMap.class;
165    expected = ClassSize.estimateBase(cl, false);
166    actual = ClassSize.TREEMAP;
167    if(expected != actual) {
168      ClassSize.estimateBase(cl, true);
169      assertEquals(expected, actual);
170    }
171
172    // String
173    cl = String.class;
174    expected = ClassSize.estimateBase(cl, false);
175    actual = ClassSize.STRING;
176    if(expected != actual) {
177      ClassSize.estimateBase(cl, true);
178      assertEquals(expected, actual);
179    }
180
181    // ConcurrentHashMap
182    cl = ConcurrentHashMap.class;
183    expected = ClassSize.estimateBase(cl, false);
184    actual = ClassSize.CONCURRENT_HASHMAP;
185    if(expected != actual) {
186      ClassSize.estimateBase(cl, true);
187      assertEquals(expected, actual);
188    }
189
190    // ConcurrentSkipListMap
191    cl = ConcurrentSkipListMap.class;
192    expected = ClassSize.estimateBase(cl, false);
193    actual = ClassSize.CONCURRENT_SKIPLISTMAP;
194    if(expected != actual) {
195      ClassSize.estimateBase(cl, true);
196      assertEquals(expected, actual);
197    }
198
199    // CellArrayMap
200    cl = CellArrayMap.class;
201    expected = ClassSize.estimateBase(cl, false);
202    actual = ClassSize.CELL_ARRAY_MAP;
203    if(expected != actual) {
204      ClassSize.estimateBase(cl, true);
205      assertEquals(expected, actual);
206    }
207
208    // ReentrantReadWriteLock
209    cl = ReentrantReadWriteLock.class;
210    expected = ClassSize.estimateBase(cl, false);
211    actual = ClassSize.REENTRANT_LOCK;
212    if(expected != actual) {
213      ClassSize.estimateBase(cl, true);
214      assertEquals(expected, actual);
215    }
216
217    // AtomicLong
218    cl = AtomicLong.class;
219    expected = ClassSize.estimateBase(cl, false);
220    actual = ClassSize.ATOMIC_LONG;
221    if(expected != actual) {
222      ClassSize.estimateBase(cl, true);
223      assertEquals(expected, actual);
224    }
225
226    // AtomicInteger
227    cl = AtomicInteger.class;
228    expected = ClassSize.estimateBase(cl, false);
229    actual = ClassSize.ATOMIC_INTEGER;
230    if(expected != actual) {
231      ClassSize.estimateBase(cl, true);
232      assertEquals(expected, actual);
233    }
234
235    // AtomicBoolean
236    cl = AtomicBoolean.class;
237    expected = ClassSize.estimateBase(cl, false);
238    actual = ClassSize.ATOMIC_BOOLEAN;
239    if(expected != actual) {
240      ClassSize.estimateBase(cl, true);
241      assertEquals(expected, actual);
242    }
243
244    // CopyOnWriteArraySet
245    cl = CopyOnWriteArraySet.class;
246    expected = ClassSize.estimateBase(cl, false);
247    actual = ClassSize.COPYONWRITE_ARRAYSET;
248    if(expected != actual) {
249      ClassSize.estimateBase(cl, true);
250      assertEquals(expected, actual);
251    }
252
253    // CopyOnWriteArrayList
254    cl = CopyOnWriteArrayList.class;
255    expected = ClassSize.estimateBase(cl, false);
256    actual = ClassSize.COPYONWRITE_ARRAYLIST;
257    if(expected != actual) {
258      ClassSize.estimateBase(cl, true);
259      assertEquals(expected, actual);
260    }
261
262    // SyncTimeRangeTracker
263    cl = SyncTimeRangeTracker.class;
264    expected = ClassSize.estimateBase(cl, false);
265    actual = ClassSize.SYNC_TIMERANGE_TRACKER;
266    if (expected != actual) {
267      ClassSize.estimateBase(cl, true);
268      assertEquals(expected, actual);
269    }
270
271    // NonSyncTimeRangeTracker
272    cl = NonSyncTimeRangeTracker.class;
273    expected = ClassSize.estimateBase(cl, false);
274    actual = ClassSize.NON_SYNC_TIMERANGE_TRACKER;
275    if (expected != actual) {
276      ClassSize.estimateBase(cl, true);
277      assertEquals(expected, actual);
278    }
279
280    // CellSet
281    cl = CellSet.class;
282    expected = ClassSize.estimateBase(cl, false);
283    actual = ClassSize.CELL_SET;
284    if (expected != actual) {
285      ClassSize.estimateBase(cl, true);
286      assertEquals(expected, actual);
287    }
288  }
289
290  /**
291   * Testing the classes that implements HeapSize and are a part of 0.20.
292   * Some are not tested here for example BlockIndex which is tested in
293   * TestHFile since it is a non public class
294   * @throws IOException
295   */
296  @Test
297  public void testSizes() throws IOException {
298    Class<?> cl;
299    long expected;
300    long actual;
301
302    //KeyValue
303    cl = KeyValue.class;
304    expected = ClassSize.estimateBase(cl, false);
305    KeyValue kv = new KeyValue();
306    actual = kv.heapSize();
307    if(expected != actual) {
308      ClassSize.estimateBase(cl, true);
309      assertEquals(expected, actual);
310    }
311
312    //LruBlockCache Overhead
313    cl = LruBlockCache.class;
314    actual = LruBlockCache.CACHE_FIXED_OVERHEAD;
315    expected = ClassSize.estimateBase(cl, false);
316    if(expected != actual) {
317      ClassSize.estimateBase(cl, true);
318      assertEquals(expected, actual);
319    }
320
321    // CachedBlock Fixed Overhead
322    // We really need "deep" sizing but ClassSize does not do this.
323    // Perhaps we should do all these more in this style....
324    cl = LruCachedBlock.class;
325    actual = LruCachedBlock.PER_BLOCK_OVERHEAD;
326    expected = ClassSize.estimateBase(cl, false);
327    expected += ClassSize.estimateBase(String.class, false);
328    expected += ClassSize.estimateBase(ByteBuffer.class, false);
329    if(expected != actual) {
330      ClassSize.estimateBase(cl, true);
331      ClassSize.estimateBase(String.class, true);
332      ClassSize.estimateBase(ByteBuffer.class, true);
333      assertEquals(expected, actual);
334    }
335
336    // DefaultMemStore Overhead
337    cl = DefaultMemStore.class;
338    actual = DefaultMemStore.FIXED_OVERHEAD;
339    expected = ClassSize.estimateBase(cl, false);
340    if(expected != actual) {
341      ClassSize.estimateBase(cl, true);
342      assertEquals(expected, actual);
343    }
344
345    // DefaultMemStore Deep Overhead
346    actual = DefaultMemStore.DEEP_OVERHEAD;
347    expected = ClassSize.estimateBase(cl, false);
348    if (expected != actual) {
349      ClassSize.estimateBase(cl, true);
350      assertEquals(expected, actual);
351    }
352
353    // CompactingMemStore Deep Overhead
354    cl = CompactingMemStore.class;
355    actual = CompactingMemStore.DEEP_OVERHEAD;
356    expected = ClassSize.estimateBase(cl, false);
357    expected += ClassSize.estimateBase(AtomicBoolean.class, false);
358    expected += ClassSize.estimateBase(AtomicBoolean.class, false);
359    expected += ClassSize.estimateBase(CompactionPipeline.class, false);
360    expected += ClassSize.estimateBase(LinkedList.class, false); //inside CompactionPipeline
361    expected += ClassSize.estimateBase(LinkedList.class, false); //inside CompactionPipeline
362    expected += ClassSize.estimateBase(MemStoreCompactor.class, false);
363    expected += ClassSize.estimateBase(AtomicBoolean.class, false);// inside MemStoreCompactor
364    if (expected != actual) {
365      ClassSize.estimateBase(cl, true);
366      ClassSize.estimateBase(AtomicBoolean.class, true);
367      ClassSize.estimateBase(AtomicBoolean.class, true);
368      ClassSize.estimateBase(CompactionPipeline.class, true);
369      ClassSize.estimateBase(LinkedList.class, true);
370      ClassSize.estimateBase(LinkedList.class, true);
371      ClassSize.estimateBase(MemStoreCompactor.class, true);
372      ClassSize.estimateBase(AtomicBoolean.class, true);
373      assertEquals(expected, actual);
374    }
375
376    // Segment Deep overhead
377    cl = Segment.class;
378    actual = Segment.DEEP_OVERHEAD;
379    expected = ClassSize.estimateBase(cl, false);
380    expected += 2 * ClassSize.estimateBase(AtomicLong.class, false);
381    expected += ClassSize.estimateBase(AtomicReference.class, false);
382    expected += ClassSize.estimateBase(CellSet.class, false);
383    expected += ClassSize.estimateBase(ReentrantReadWriteLock.class, false);
384    if (expected != actual) {
385      ClassSize.estimateBase(cl, true);
386      ClassSize.estimateBase(AtomicLong.class, true);
387      ClassSize.estimateBase(AtomicReference.class, true);
388      ClassSize.estimateBase(CellSet.class, true);
389      ClassSize.estimateBase(ReentrantReadWriteLock.class,true);
390      assertEquals(expected, actual);
391    }
392
393    // MutableSegment Deep overhead
394    cl = MutableSegment.class;
395    actual = MutableSegment.DEEP_OVERHEAD;
396    expected = ClassSize.estimateBase(cl, false);
397    expected += 2 * ClassSize.estimateBase(AtomicLong.class, false);
398    expected += ClassSize.estimateBase(AtomicReference.class, false);
399    expected += ClassSize.estimateBase(CellSet.class, false);
400    expected += ClassSize.estimateBase(ReentrantReadWriteLock.class, false);
401    expected += ClassSize.estimateBase(SyncTimeRangeTracker.class, false);
402    expected += ClassSize.estimateBase(ConcurrentSkipListMap.class, false);
403    expected += ClassSize.estimateBase(AtomicBoolean.class, false);
404    if (expected != actual) {
405      ClassSize.estimateBase(cl, true);
406      ClassSize.estimateBase(AtomicLong.class, true);
407      ClassSize.estimateBase(AtomicLong.class, true);
408      ClassSize.estimateBase(AtomicReference.class, true);
409      ClassSize.estimateBase(CellSet.class, true);
410      ClassSize.estimateBase(ReentrantReadWriteLock.class,true);
411      ClassSize.estimateBase(SyncTimeRangeTracker.class, true);
412      ClassSize.estimateBase(ConcurrentSkipListMap.class, true);
413      ClassSize.estimateBase(AtomicBoolean.class,true);
414      assertEquals(expected, actual);
415    }
416
417    // ImmutableSegments Deep overhead
418    cl = ImmutableSegment.class;
419    actual = ImmutableSegment.DEEP_OVERHEAD;
420    expected = ClassSize.estimateBase(cl, false);
421    expected += 2 * ClassSize.estimateBase(AtomicLong.class, false);
422    expected += ClassSize.estimateBase(AtomicReference.class, false);
423    expected += ClassSize.estimateBase(CellSet.class, false);
424    expected += ClassSize.estimateBase(ReentrantReadWriteLock.class, false);
425    expected += ClassSize.estimateBase(NonSyncTimeRangeTracker.class, false);
426    if (expected != actual) {
427      ClassSize.estimateBase(cl, true);
428      ClassSize.estimateBase(AtomicLong.class, true);
429      ClassSize.estimateBase(AtomicLong.class, true);
430      ClassSize.estimateBase(AtomicReference.class, true);
431      ClassSize.estimateBase(CellSet.class, true);
432      ClassSize.estimateBase(ReentrantReadWriteLock.class,true);
433      ClassSize.estimateBase(NonSyncTimeRangeTracker.class, true);
434      assertEquals(expected, actual);
435    }
436
437    cl = CSLMImmutableSegment.class;
438    actual = CSLMImmutableSegment.DEEP_OVERHEAD_CSLM;
439    expected = ClassSize.estimateBase(cl, false);
440    expected += 2 * ClassSize.estimateBase(AtomicLong.class, false);
441    expected += ClassSize.estimateBase(AtomicReference.class, false);
442    expected += ClassSize.estimateBase(CellSet.class, false);
443    expected += ClassSize.estimateBase(ReentrantReadWriteLock.class, false);
444    expected += ClassSize.estimateBase(NonSyncTimeRangeTracker.class, false);
445    expected += ClassSize.estimateBase(ConcurrentSkipListMap.class, false);
446    if (expected != actual) {
447      ClassSize.estimateBase(cl, true);
448      ClassSize.estimateBase(AtomicLong.class, true);
449      ClassSize.estimateBase(AtomicLong.class, true);
450      ClassSize.estimateBase(AtomicReference.class, true);
451      ClassSize.estimateBase(CellSet.class, true);
452      ClassSize.estimateBase(ReentrantReadWriteLock.class,true);
453      ClassSize.estimateBase(NonSyncTimeRangeTracker.class, true);
454      ClassSize.estimateBase(ConcurrentSkipListMap.class, true);
455      assertEquals(expected, actual);
456    }
457    cl = CellArrayImmutableSegment.class;
458    actual = CellArrayImmutableSegment.DEEP_OVERHEAD_CAM;
459    expected = ClassSize.estimateBase(cl, false);
460    expected += 2 * ClassSize.estimateBase(AtomicLong.class, false);
461    expected += ClassSize.estimateBase(AtomicReference.class, false);
462    expected += ClassSize.estimateBase(CellSet.class, false);
463    expected += ClassSize.estimateBase(ReentrantReadWriteLock.class, false);
464    expected += ClassSize.estimateBase(NonSyncTimeRangeTracker.class, false);
465    expected += ClassSize.estimateBase(CellArrayMap.class, false);
466    if (expected != actual) {
467      ClassSize.estimateBase(cl, true);
468      ClassSize.estimateBase(AtomicLong.class, true);
469      ClassSize.estimateBase(AtomicLong.class, true);
470      ClassSize.estimateBase(AtomicReference.class, true);
471      ClassSize.estimateBase(CellSet.class, true);
472      ClassSize.estimateBase(ReentrantReadWriteLock.class,true);
473      ClassSize.estimateBase(NonSyncTimeRangeTracker.class, true);
474      ClassSize.estimateBase(CellArrayMap.class, true);
475      assertEquals(expected, actual);
476    }
477
478    // Store Overhead
479    cl = HStore.class;
480    actual = HStore.FIXED_OVERHEAD;
481    expected = ClassSize.estimateBase(cl, false);
482    if(expected != actual) {
483      ClassSize.estimateBase(cl, true);
484      assertEquals(expected, actual);
485    }
486
487    // Region Overhead
488    cl = HRegion.class;
489    actual = HRegion.FIXED_OVERHEAD;
490    expected = ClassSize.estimateBase(cl, false);
491    if (expected != actual) {
492      ClassSize.estimateBase(cl, true);
493      assertEquals(expected, actual);
494    }
495
496    cl = StoreHotnessProtector.class;
497    actual = StoreHotnessProtector.FIXED_SIZE;
498    expected = ClassSize.estimateBase(cl, false);
499    if (expected != actual) {
500      ClassSize.estimateBase(cl, true);
501      assertEquals(expected, actual);
502    }
503
504    // Block cache key overhead. Only tests fixed overhead as estimating heap
505    // size of strings is hard.
506    cl = BlockCacheKey.class;
507    actual = BlockCacheKey.FIXED_OVERHEAD;
508    expected  = ClassSize.estimateBase(cl, false);
509    if (expected != actual) {
510      ClassSize.estimateBase(cl, true);
511      assertEquals(expected, actual);
512    }
513
514    // Currently NOT testing Deep Overheads of many of these classes.
515    // Deep overheads cover a vast majority of stuff, but will not be 100%
516    // accurate because it's unclear when we're referencing stuff that's already
517    // accounted for.  But we have satisfied our two core requirements.
518    // Sizing is quite accurate now, and our tests will throw errors if
519    // any of these classes are modified without updating overhead sizes.
520  }
521
522  @Test
523  public void testHFileBlockSize() throws IOException {
524    long expected;
525    long actual;
526
527    actual = HFileContext.FIXED_OVERHEAD;
528    expected = ClassSize.estimateBase(HFileContext.class, false);
529    assertEquals(expected, actual);
530
531    actual = HFileBlock.FIXED_OVERHEAD;
532    expected = ClassSize.estimateBase(HFileBlock.class, false);
533    assertEquals(expected, actual);
534
535    actual = ExclusiveMemHFileBlock.FIXED_OVERHEAD;
536    expected = ClassSize.estimateBase(ExclusiveMemHFileBlock.class, false);
537    assertEquals(expected, actual);
538
539    actual = SharedMemHFileBlock.FIXED_OVERHEAD;
540    expected = ClassSize.estimateBase(SharedMemHFileBlock.class, false);
541    assertEquals(expected, actual);
542  }
543
544  @Test
545  public void testMutations(){
546    Class<?> cl;
547    long expected;
548    long actual;
549
550    cl = TimeRange.class;
551    actual = ClassSize.TIMERANGE;
552    expected  = ClassSize.estimateBase(cl, false);
553    if (expected != actual) {
554      ClassSize.estimateBase(cl, true);
555      assertEquals(expected, actual);
556    }
557
558    byte[] row = new byte[] { 0 };
559    cl = Put.class;
560    actual = Mutation.MUTATION_OVERHEAD + ClassSize.align(ClassSize.ARRAY);
561    expected = ClassSize.estimateBase(cl, false);
562    //The actual TreeMap is not included in the above calculation
563    expected += ClassSize.align(ClassSize.TREEMAP);
564    expected += ClassSize.align(ClassSize.INTEGER); // priority
565    if (expected != actual) {
566      ClassSize.estimateBase(cl, true);
567      assertEquals(expected, actual);
568    }
569
570    cl = Delete.class;
571    actual = Mutation.MUTATION_OVERHEAD + ClassSize.align(ClassSize.ARRAY);
572    expected  = ClassSize.estimateBase(cl, false);
573    //The actual TreeMap is not included in the above calculation
574    expected += ClassSize.align(ClassSize.TREEMAP);
575    expected += ClassSize.align(ClassSize.INTEGER); // priority
576    if (expected != actual) {
577      ClassSize.estimateBase(cl, true);
578      assertEquals(expected, actual);
579    }
580  }
581
582  @Test
583  public void testReferenceSize() {
584    LOG.info("ClassSize.REFERENCE is " + ClassSize.REFERENCE);
585    // oop should be either 4 or 8
586    assertTrue(ClassSize.REFERENCE == 4 || ClassSize.REFERENCE == 8);
587  }
588
589  @Test
590  public void testObjectSize() throws IOException {
591    LOG.info("header:" + ClassSize.OBJECT);
592    LOG.info("array header:" + ClassSize.ARRAY);
593
594    if (ClassSize.is32BitJVM()) {
595      assertEquals(ClassSize.OBJECT, 8);
596    } else {
597      assertTrue(ClassSize.OBJECT == 12 || ClassSize.OBJECT == 16); // depending on CompressedOops
598    }
599    if (ClassSize.useUnsafeLayout()) {
600      assertEquals(ClassSize.ARRAY, ClassSize.OBJECT + 4);
601    } else {
602      assertEquals(ClassSize.ARRAY, ClassSize.OBJECT + 8);
603    }
604  }
605}
606