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