1 /* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.ahat.heapdump; 18 19 /** 20 * A Java instance or primitive value from a parsed heap dump. 21 * Note: To save memory, a null Value is used to represent a null Java 22 * instance from the heap dump. 23 */ 24 public abstract class Value { 25 /** 26 * Constructs a Value for an AhatInstance. 27 * Note: returns null for null <code>value</code>. 28 * 29 * @param value the AhatInstance to make into a value 30 * @return the constructed value. 31 */ pack(AhatInstance value)32 public static Value pack(AhatInstance value) { 33 return value == null ? null : new InstanceValue(value); 34 } 35 36 /** 37 * Constructs a Value for a boolean. 38 * 39 * @param value the boolean to make into a value 40 * @return the constructed value. 41 */ pack(boolean value)42 public static Value pack(boolean value) { 43 return new BooleanValue(value); 44 } 45 46 /** 47 * Constructs a Value for a char. 48 * 49 * @param value the char to make into a value 50 * @return the constructed value. 51 */ pack(char value)52 public static Value pack(char value) { 53 return new CharValue(value); 54 } 55 56 /** 57 * Constructs a Value for a float. 58 * 59 * @param value the float to make into a value 60 * @return the constructed value. 61 */ pack(float value)62 public static Value pack(float value) { 63 return new FloatValue(value); 64 } 65 66 /** 67 * Constructs a Value for a double. 68 * 69 * @param value the double to make into a value 70 * @return the constructed value. 71 */ pack(double value)72 public static Value pack(double value) { 73 return new DoubleValue(value); 74 } 75 76 /** 77 * Constructs a Value for a byte. 78 * 79 * @param value the byte to make into a value 80 * @return the constructed value. 81 */ pack(byte value)82 public static Value pack(byte value) { 83 return new ByteValue(value); 84 } 85 86 /** 87 * Constructs a Value for a short. 88 * 89 * @param value the short to make into a value 90 * @return the constructed value. 91 */ pack(short value)92 public static Value pack(short value) { 93 return new ShortValue(value); 94 } 95 96 /** 97 * Constructs a Value for a int. 98 * 99 * @param value the int to make into a value 100 * @return the constructed value. 101 */ pack(int value)102 public static Value pack(int value) { 103 return new IntValue(value); 104 } 105 106 /** 107 * Constructs a Value for a long. 108 * 109 * @param value the long to make into a value 110 * @return the constructed value. 111 */ pack(long value)112 public static Value pack(long value) { 113 return new LongValue(value); 114 } 115 116 /** 117 * Returns the type of the given value. 118 * 119 * @param value the value to get the type of 120 * @return the value's type 121 */ getType(Value value)122 public static Type getType(Value value) { 123 return value == null ? Type.OBJECT : value.getType(); 124 } 125 126 /** 127 * Return the type of the given value. 128 */ getType()129 abstract Type getType(); 130 131 /** 132 * Returns true if the Value is an AhatInstance rather than a primitive 133 * value. 134 * 135 * @return true if the value is an AhatInstance 136 */ isAhatInstance()137 public boolean isAhatInstance() { 138 return false; 139 } 140 141 /** 142 * Returns the Value as an AhatInstance if it is one. 143 * Returns null if the Value represents a Java primitive value. 144 * 145 * @return the AhatInstance packed into this value 146 */ asAhatInstance()147 public AhatInstance asAhatInstance() { 148 return null; 149 } 150 151 /** 152 * Returns true if the Value is an int. 153 * 154 * @return true if the value is an int. 155 */ isInteger()156 public boolean isInteger() { 157 return false; 158 } 159 160 /** 161 * Returns the Value as an int if it is one. 162 * Returns null if the Value does not represent an int. 163 * 164 * @return the int packed into this value 165 */ asInteger()166 public Integer asInteger() { 167 return null; 168 } 169 170 /** 171 * Returns true if the Value is an long. 172 * 173 * @return true if the value is an long. 174 */ isLong()175 public boolean isLong() { 176 return false; 177 } 178 179 /** 180 * Returns the Value as an long if it is one. 181 * Returns null if the Value does not represent an long. 182 * 183 * @return the long packed into this value 184 */ asLong()185 public Long asLong() { 186 return null; 187 } 188 189 /** 190 * Returns the Value as an byte if it is one. 191 * Returns null if the Value does not represent an byte. 192 * 193 * @return the byte packed into this value 194 */ asByte()195 public Byte asByte() { 196 return null; 197 } 198 199 /** 200 * Returns the Value as an char if it is one. 201 * Returns null if the Value does not represent an char. 202 * 203 * @return the char packed into this value 204 */ asChar()205 public Character asChar() { 206 return null; 207 } 208 209 @Override toString()210 public abstract String toString(); 211 getBaseline()212 private Value getBaseline() { 213 return this; 214 } 215 216 /** 217 * Returns the baseline of the given value for the purposes of diff. 218 * This method can be used to handle the case when the Value is null. 219 * 220 * @param value the value to get the baseline of 221 * @return the baseline of the value 222 * @see Diffable#getBaseline 223 */ getBaseline(Value value)224 public static Value getBaseline(Value value) { 225 return value == null ? null : value.getBaseline(); 226 } 227 228 @Override equals(Object other)229 public abstract boolean equals(Object other); 230 231 private static class BooleanValue extends Value { 232 private boolean mBool; 233 BooleanValue(boolean bool)234 BooleanValue(boolean bool) { 235 mBool = bool; 236 } 237 238 @Override getType()239 Type getType() { 240 return Type.BOOLEAN; 241 } 242 243 @Override toString()244 public String toString() { 245 return Boolean.toString(mBool); 246 } 247 equals(Object other)248 @Override public boolean equals(Object other) { 249 if (other instanceof BooleanValue) { 250 BooleanValue value = (BooleanValue)other; 251 return mBool == value.mBool; 252 } 253 return false; 254 } 255 } 256 257 private static class ByteValue extends Value { 258 private byte mByte; 259 ByteValue(byte b)260 ByteValue(byte b) { 261 mByte = b; 262 } 263 264 @Override asByte()265 public Byte asByte() { 266 return mByte; 267 } 268 269 @Override getType()270 Type getType() { 271 return Type.BYTE; 272 } 273 274 @Override toString()275 public String toString() { 276 return Byte.toString(mByte); 277 } 278 equals(Object other)279 @Override public boolean equals(Object other) { 280 if (other instanceof ByteValue) { 281 ByteValue value = (ByteValue)other; 282 return mByte == value.mByte; 283 } 284 return false; 285 } 286 } 287 288 private static class CharValue extends Value { 289 private char mChar; 290 CharValue(char c)291 CharValue(char c) { 292 mChar = c; 293 } 294 295 @Override asChar()296 public Character asChar() { 297 return mChar; 298 } 299 300 @Override getType()301 Type getType() { 302 return Type.CHAR; 303 } 304 305 @Override toString()306 public String toString() { 307 return Character.toString(mChar); 308 } 309 equals(Object other)310 @Override public boolean equals(Object other) { 311 if (other instanceof CharValue) { 312 CharValue value = (CharValue)other; 313 return mChar == value.mChar; 314 } 315 return false; 316 } 317 } 318 319 private static class DoubleValue extends Value { 320 private double mDouble; 321 DoubleValue(double d)322 DoubleValue(double d) { 323 mDouble = d; 324 } 325 326 @Override getType()327 Type getType() { 328 return Type.DOUBLE; 329 } 330 331 @Override toString()332 public String toString() { 333 return Double.toString(mDouble); 334 } 335 equals(Object other)336 @Override public boolean equals(Object other) { 337 if (other instanceof DoubleValue) { 338 DoubleValue value = (DoubleValue)other; 339 return mDouble == value.mDouble; 340 } 341 return false; 342 } 343 } 344 345 private static class FloatValue extends Value { 346 private float mFloat; 347 FloatValue(float f)348 FloatValue(float f) { 349 mFloat = f; 350 } 351 352 @Override getType()353 Type getType() { 354 return Type.FLOAT; 355 } 356 357 @Override toString()358 public String toString() { 359 return Float.toString(mFloat); 360 } 361 equals(Object other)362 @Override public boolean equals(Object other) { 363 if (other instanceof FloatValue) { 364 FloatValue value = (FloatValue)other; 365 return mFloat == value.mFloat; 366 } 367 return false; 368 } 369 } 370 371 private static class InstanceValue extends Value { 372 private AhatInstance mInstance; 373 InstanceValue(AhatInstance inst)374 InstanceValue(AhatInstance inst) { 375 assert(inst != null); 376 mInstance = inst; 377 } 378 379 @Override isAhatInstance()380 public boolean isAhatInstance() { 381 return true; 382 } 383 384 @Override asAhatInstance()385 public AhatInstance asAhatInstance() { 386 return mInstance; 387 } 388 389 @Override getType()390 Type getType() { 391 return Type.OBJECT; 392 } 393 394 @Override toString()395 public String toString() { 396 return mInstance.toString(); 397 } 398 getBaseline()399 public Value getBaseline() { 400 return InstanceValue.pack(mInstance.getBaseline()); 401 } 402 equals(Object other)403 @Override public boolean equals(Object other) { 404 if (other instanceof InstanceValue) { 405 InstanceValue value = (InstanceValue)other; 406 return mInstance.equals(value.mInstance); 407 } 408 return false; 409 } 410 } 411 412 private static class IntValue extends Value { 413 private int mInt; 414 IntValue(int i)415 IntValue(int i) { 416 mInt = i; 417 } 418 419 @Override isInteger()420 public boolean isInteger() { 421 return true; 422 } 423 424 @Override asInteger()425 public Integer asInteger() { 426 return mInt; 427 } 428 429 @Override getType()430 Type getType() { 431 return Type.INT; 432 } 433 434 @Override toString()435 public String toString() { 436 return Integer.toString(mInt); 437 } 438 equals(Object other)439 @Override public boolean equals(Object other) { 440 if (other instanceof IntValue) { 441 IntValue value = (IntValue)other; 442 return mInt == value.mInt; 443 } 444 return false; 445 } 446 } 447 448 private static class LongValue extends Value { 449 private long mLong; 450 LongValue(long l)451 LongValue(long l) { 452 mLong = l; 453 } 454 455 @Override isLong()456 public boolean isLong() { 457 return true; 458 } 459 460 @Override asLong()461 public Long asLong() { 462 return mLong; 463 } 464 465 @Override getType()466 Type getType() { 467 return Type.LONG; 468 } 469 470 @Override toString()471 public String toString() { 472 return Long.toString(mLong); 473 } 474 equals(Object other)475 @Override public boolean equals(Object other) { 476 if (other instanceof LongValue) { 477 LongValue value = (LongValue)other; 478 return mLong == value.mLong; 479 } 480 return false; 481 } 482 } 483 484 private static class ShortValue extends Value { 485 private short mShort; 486 ShortValue(short s)487 ShortValue(short s) { 488 mShort = s; 489 } 490 491 @Override getType()492 Type getType() { 493 return Type.SHORT; 494 } 495 496 @Override toString()497 public String toString() { 498 return Short.toString(mShort); 499 } 500 equals(Object other)501 @Override public boolean equals(Object other) { 502 if (other instanceof ShortValue) { 503 ShortValue value = (ShortValue)other; 504 return mShort == value.mShort; 505 } 506 return false; 507 } 508 } 509 } 510