ObjectOutputStream and ObjectInputStream can provide an application with 53 | * persistent storage for graphs of objects when used with a FileOutputStream 54 | * and FileInputStream respectively. ObjectInputStream is used to recover 55 | * those objects previously serialized. Other uses include passing objects 56 | * between hosts using a socket stream or for marshaling and unmarshaling 57 | * arguments and parameters in a remote communication system. 58 | * 59 | *
ObjectInputStream ensures that the types of all objects in the graph 60 | * created from the stream match the classes present in the Java Virtual 61 | * Machine. Classes are loaded as required using the standard mechanisms. 62 | * 63 | *
Only objects that support the java.io.Serializable or 64 | * java.io.Externalizable interface can be read from streams. 65 | * 66 | *
The method readObject is used to read an object from the
67 | * stream. Java's safe casting should be used to get the desired type. In
68 | * Java, strings and arrays are objects and are treated as objects during
69 | * serialization. When read they need to be cast to the expected type.
70 | *
71 | *
Primitive data types can be read from the stream using the appropriate 72 | * method on DataInput. 73 | * 74 | *
The default deserialization mechanism for objects restores the contents 75 | * of each field to the value and type it had when it was written. Fields 76 | * declared as transient or static are ignored by the deserialization process. 77 | * References to other objects cause those objects to be read from the stream 78 | * as necessary. Graphs of objects are restored correctly using a reference 79 | * sharing mechanism. New objects are always allocated when deserializing, 80 | * which prevents existing objects from being overwritten. 81 | * 82 | *
Reading an object is analogous to running the constructors of a new 83 | * object. Memory is allocated for the object and initialized to zero (NULL). 84 | * No-arg constructors are invoked for the non-serializable classes and then 85 | * the fields of the serializable classes are restored from the stream starting 86 | * with the serializable class closest to java.lang.object and finishing with 87 | * the object's most specific class. 88 | * 89 | *
For example to read from a stream as written by the example in
90 | * ObjectOutputStream:
91 | *
92 | *
93 | * FileInputStream fis = new FileInputStream("t.tmp");
94 | * ObjectInputStream ois = new ObjectInputStream(fis);
95 | *
96 | * int i = ois.readInt();
97 | * String today = (String) ois.readObject();
98 | * Date date = (Date) ois.readObject();
99 | *
100 | * ois.close();
101 | *
102 | *
103 | * Classes control how they are serialized by implementing either the 104 | * java.io.Serializable or java.io.Externalizable interfaces. 105 | * 106 | *
Implementing the Serializable interface allows object serialization to 107 | * save and restore the entire state of the object and it allows classes to 108 | * evolve between the time the stream is written and the time it is read. It 109 | * automatically traverses references between objects, saving and restoring 110 | * entire graphs. 111 | * 112 | *
Serializable classes that require special handling during the 113 | * serialization and deserialization process should implement the following 114 | * methods: 115 | * 116 | *
117 | * private void writeObject(java.io.ObjectOutputStream stream) 118 | * throws IOException; 119 | * private void readObject(java.io.ObjectInputStream stream) 120 | * throws IOException, ClassNotFoundException; 121 | * private void readObjectNoData() 122 | * throws ObjectStreamException; 123 | *124 | * 125 | *
The readObject method is responsible for reading and restoring the state 126 | * of the object for its particular class using data written to the stream by 127 | * the corresponding writeObject method. The method does not need to concern 128 | * itself with the state belonging to its superclasses or subclasses. State is 129 | * restored by reading data from the ObjectInputStream for the individual 130 | * fields and making assignments to the appropriate fields of the object. 131 | * Reading primitive data types is supported by DataInput. 132 | * 133 | *
Any attempt to read object data which exceeds the boundaries of the 134 | * custom data written by the corresponding writeObject method will cause an 135 | * OptionalDataException to be thrown with an eof field value of true. 136 | * Non-object reads which exceed the end of the allotted data will reflect the 137 | * end of data in the same way that they would indicate the end of the stream: 138 | * bytewise reads will return -1 as the byte read or number of bytes read, and 139 | * primitive reads will throw EOFExceptions. If there is no corresponding 140 | * writeObject method, then the end of default serialized data marks the end of 141 | * the allotted data. 142 | * 143 | *
Primitive and object read calls issued from within a readExternal method
144 | * behave in the same manner--if the stream is already positioned at the end of
145 | * data written by the corresponding writeExternal method, object reads will
146 | * throw OptionalDataExceptions with eof set to true, bytewise reads will
147 | * return -1, and primitive reads will throw EOFExceptions. Note that this
148 | * behavior does not hold for streams written with the old
149 | * ObjectStreamConstants.PROTOCOL_VERSION_1 protocol, in which the
150 | * end of data written by writeExternal methods is not demarcated, and hence
151 | * cannot be detected.
152 | *
153 | *
The readObjectNoData method is responsible for initializing the state of 154 | * the object for its particular class in the event that the serialization 155 | * stream does not list the given class as a superclass of the object being 156 | * deserialized. This may occur in cases where the receiving party uses a 157 | * different version of the deserialized instance's class than the sending 158 | * party, and the receiver's version extends classes that are not extended by 159 | * the sender's version. This may also occur if the serialization stream has 160 | * been tampered; hence, readObjectNoData is useful for initializing 161 | * deserialized objects properly despite a "hostile" or incomplete source 162 | * stream. 163 | * 164 | *
Serialization does not read or assign values to the fields of any object 165 | * that does not implement the java.io.Serializable interface. Subclasses of 166 | * Objects that are not serializable can be serializable. In this case the 167 | * non-serializable class must have a no-arg constructor to allow its fields to 168 | * be initialized. In this case it is the responsibility of the subclass to 169 | * save and restore the state of the non-serializable class. It is frequently 170 | * the case that the fields of that class are accessible (public, package, or 171 | * protected) or that there are get and set methods that can be used to restore 172 | * the state. 173 | * 174 | *
Any exception that occurs while deserializing an object will be caught by 175 | * the ObjectInputStream and abort the reading process. 176 | * 177 | *
Implementing the Externalizable interface allows the object to assume 178 | * complete control over the contents and format of the object's serialized 179 | * form. The methods of the Externalizable interface, writeExternal and 180 | * readExternal, are called to save and restore the objects state. When 181 | * implemented by a class they can write and read their own state using all of 182 | * the methods of ObjectOutput and ObjectInput. It is the responsibility of 183 | * the objects to handle any versioning that occurs. 184 | * 185 | *
Enum constants are deserialized differently than ordinary serializable or
186 | * externalizable objects. The serialized form of an enum constant consists
187 | * solely of its name; field values of the constant are not transmitted. To
188 | * deserialize an enum constant, ObjectInputStream reads the constant name from
189 | * the stream; the deserialized constant is then obtained by calling the static
190 | * method If a security manager is installed, this constructor will check for
308 | * the "enableSubclassImplementation" SerializablePermission when invoked
309 | * directly or indirectly by the constructor of a subclass which overrides
310 | * the ObjectInputStream.readFields or ObjectInputStream.readUnshared
311 | * methods.
312 | *
313 | * @param in input stream to read from
314 | * @throws StreamCorruptedException if the stream header is incorrect
315 | * @throws IOException if an I/O error occurs while reading stream header
316 | * @throws SecurityException if untrusted subclass illegally overrides
317 | * security-sensitive methods
318 | * @throws NullPointerException if If there is a security manager installed, this method first calls the
339 | * security manager's The root object is completely restored when all of its fields and the
371 | * objects it references are completely restored. At this point the object
372 | * validation callbacks are executed in order based on their registered
373 | * priorities. The callbacks are registered by objects (in the readObject
374 | * special methods) as they are individually restored.
375 | *
376 | * Exceptions are thrown for problems with the InputStream and for
377 | * classes that should not be deserialized. All exceptions are fatal to
378 | * the InputStream and leave it in an indeterminate state; it is up to the
379 | * caller to ignore or recover the stream state.
380 | *
381 | * @throws ClassNotFoundException Class of a serialized object cannot be
382 | * found.
383 | * @throws InvalidClassException Something is wrong with a class used by
384 | * serialization.
385 | * @throws StreamCorruptedException Control information in the
386 | * stream is inconsistent.
387 | * @throws OptionalDataException Primitive data was found in the
388 | * stream instead of objects.
389 | * @throws IOException Any of the usual Input/Output related exceptions.
390 | */
391 | public final Object readObject()
392 | throws IOException, ClassNotFoundException
393 | {
394 | String enabled = java.security.Security.getProperty("paranoid.serialization.enabled");
395 | if (! Boolean.parseBoolean(enabled)) {
396 | throw new InvalidClassException("Object deserialization is disabled!");
397 | }
398 |
399 | if (enableOverride) {
400 | return readObjectOverride();
401 | }
402 |
403 | // if nested read, passHandle contains handle of enclosing object
404 | int outerHandle = passHandle;
405 | try {
406 | Object obj = readObject0(false);
407 | handles.markDependency(outerHandle, passHandle);
408 | ClassNotFoundException ex = handles.lookupException(passHandle);
409 | if (ex != null) {
410 | throw ex;
411 | }
412 | if (depth == 0) {
413 | vlist.doCallbacks();
414 | }
415 | return obj;
416 | } finally {
417 | passHandle = outerHandle;
418 | if (closed && depth == 0) {
419 | clear();
420 | }
421 | }
422 | }
423 |
424 | /**
425 | * This method is called by trusted subclasses of ObjectOutputStream that
426 | * constructed ObjectOutputStream using the protected no-arg constructor.
427 | * The subclass is expected to provide an override method with the modifier
428 | * "final".
429 | *
430 | * @return the Object read from the stream.
431 | * @throws ClassNotFoundException Class definition of a serialized object
432 | * cannot be found.
433 | * @throws OptionalDataException Primitive data was found in the stream
434 | * instead of objects.
435 | * @throws IOException if I/O errors occurred while reading from the
436 | * underlying stream
437 | * @see #ObjectInputStream()
438 | * @see #readObject()
439 | * @since 1.2
440 | */
441 | protected Object readObjectOverride()
442 | throws IOException, ClassNotFoundException
443 | {
444 | return null;
445 | }
446 |
447 | /**
448 | * Reads an "unshared" object from the ObjectInputStream. This method is
449 | * identical to readObject, except that it prevents subsequent calls to
450 | * readObject and readUnshared from returning additional references to the
451 | * deserialized instance obtained via this call. Specifically:
452 | * ObjectInputStream subclasses which override this method can only be
476 | * constructed in security contexts possessing the
477 | * "enableSubclassImplementation" SerializablePermission; any attempt to
478 | * instantiate such a subclass without this permission will cause a
479 | * SecurityException to be thrown.
480 | *
481 | * @return reference to deserialized object
482 | * @throws ClassNotFoundException if class of an object to deserialize
483 | * cannot be found
484 | * @throws StreamCorruptedException if control information in the stream
485 | * is inconsistent
486 | * @throws ObjectStreamException if object to deserialize has already
487 | * appeared in stream
488 | * @throws OptionalDataException if primitive data is next in stream
489 | * @throws IOException if an I/O error occurs during deserialization
490 | * @since 1.4
491 | */
492 | public Object readUnshared() throws IOException, ClassNotFoundException {
493 | // if nested read, passHandle contains handle of enclosing object
494 | int outerHandle = passHandle;
495 | try {
496 | Object obj = readObject0(true);
497 | handles.markDependency(outerHandle, passHandle);
498 | ClassNotFoundException ex = handles.lookupException(passHandle);
499 | if (ex != null) {
500 | throw ex;
501 | }
502 | if (depth == 0) {
503 | vlist.doCallbacks();
504 | }
505 | return obj;
506 | } finally {
507 | passHandle = outerHandle;
508 | if (closed && depth == 0) {
509 | clear();
510 | }
511 | }
512 | }
513 |
514 | /**
515 | * Read the non-static and non-transient fields of the current class from
516 | * this stream. This may only be called from the readObject method of the
517 | * class being deserialized. It will throw the NotActiveException if it is
518 | * called otherwise.
519 | *
520 | * @throws ClassNotFoundException if the class of a serialized object
521 | * could not be found.
522 | * @throws IOException if an I/O error occurs.
523 | * @throws NotActiveException if the stream is not currently reading
524 | * objects.
525 | */
526 | public void defaultReadObject()
527 | throws IOException, ClassNotFoundException
528 | {
529 | SerialCallbackContext ctx = curContext;
530 | if (ctx == null) {
531 | throw new NotActiveException("not in call to readObject");
532 | }
533 | Object curObj = ctx.getObj();
534 | ObjectStreamClass curDesc = ctx.getDesc();
535 | bin.setBlockDataMode(false);
536 | defaultReadFields(curObj, curDesc);
537 | bin.setBlockDataMode(true);
538 | if (!curDesc.hasWriteObjectData()) {
539 | /*
540 | * Fix for 4360508: since stream does not contain terminating
541 | * TC_ENDBLOCKDATA tag, set flag so that reading code elsewhere
542 | * knows to simulate end-of-custom-data behavior.
543 | */
544 | defaultDataEnd = true;
545 | }
546 | ClassNotFoundException ex = handles.lookupException(passHandle);
547 | if (ex != null) {
548 | throw ex;
549 | }
550 | }
551 |
552 | /**
553 | * Reads the persistent fields from the stream and makes them available by
554 | * name.
555 | *
556 | * @return the The corresponding method in The default implementation of this method in
630 | * This method is called exactly once for each unique proxy class
714 | * descriptor in the stream.
715 | *
716 | * The corresponding method in The default implementation of this method in
724 | * This method is called after an object has been read but before it is
800 | * returned from readObject. The default resolveObject method just returns
801 | * the same object.
802 | *
803 | * When a subclass is replacing objects it must insure that the
804 | * substituted object is compatible with every field where the reference
805 | * will be stored. Objects whose type is not a subclass of the type of the
806 | * field or array element abort the serialization by raising an exception
807 | * and the object is not be stored.
808 | *
809 | * This method is called only once when each object is first
810 | * encountered. All subsequent references to the object will be redirected
811 | * to the new object.
812 | *
813 | * @param obj object to be substituted
814 | * @return the substituted object
815 | * @throws IOException Any of the usual Input/Output exceptions.
816 | */
817 | protected Object resolveObject(Object obj) throws IOException {
818 | return obj;
819 | }
820 |
821 | /**
822 | * Enable the stream to allow objects read from the stream to be replaced.
823 | * When enabled, the resolveObject method is called for every object being
824 | * deserialized.
825 | *
826 | * If enable is true, and there is a security manager installed,
827 | * this method first calls the security manager's
828 | * General use of the table is as follows: during deserialization, a
3296 | * given object is first assigned a handle by calling the assign method.
3297 | * This method leaves the assigned handle in an "open" state, wherein
3298 | * dependencies on the exception status of other handles can be registered
3299 | * by calling the markDependency method, or an exception can be directly
3300 | * associated with the handle by calling markException. When a handle is
3301 | * tagged with an exception, the HandleTable assumes responsibility for
3302 | * propagating the exception to any other objects which depend
3303 | * (transitively) on the exception-tagged object.
3304 | *
3305 | * Once all exception information/dependencies for the handle have been
3306 | * registered, the handle should be "closed" by calling the finish method
3307 | * on it. The act of finishing a handle allows the exception propagation
3308 | * algorithm to aggressively prune dependency links, lessening the
3309 | * performance/memory impact of exception tracking.
3310 | *
3311 | * Note that the exception propagation algorithm used depends on handles
3312 | * being assigned/finished in LIFO order; however, for simplicity as well
3313 | * as memory conservation, it does not enforce this constraint.
3314 | */
3315 | // REMIND: add full description of exception propagation algorithm?
3316 | private static class HandleTable {
3317 |
3318 | /* status codes indicating whether object has associated exception */
3319 | private static final byte STATUS_OK = 1;
3320 | private static final byte STATUS_UNKNOWN = 2;
3321 | private static final byte STATUS_EXCEPTION = 3;
3322 |
3323 | /** array mapping handle -> object status */
3324 | byte[] status;
3325 | /** array mapping handle -> object/exception (depending on status) */
3326 | Object[] entries;
3327 | /** array mapping handle -> list of dependent handles (if any) */
3328 | HandleList[] deps;
3329 | /** lowest unresolved dependency */
3330 | int lowDep = -1;
3331 | /** number of handles in table */
3332 | int size = 0;
3333 |
3334 | /**
3335 | * Creates handle table with the given initial capacity.
3336 | */
3337 | HandleTable(int initialCapacity) {
3338 | status = new byte[initialCapacity];
3339 | entries = new Object[initialCapacity];
3340 | deps = new HandleList[initialCapacity];
3341 | }
3342 |
3343 | /**
3344 | * Assigns next available handle to given object, and returns assigned
3345 | * handle. Once object has been completely deserialized (and all
3346 | * dependencies on other objects identified), the handle should be
3347 | * "closed" by passing it to finish().
3348 | */
3349 | int assign(Object obj) {
3350 | if (size >= entries.length) {
3351 | grow();
3352 | }
3353 | status[size] = STATUS_UNKNOWN;
3354 | entries[size] = obj;
3355 | return size++;
3356 | }
3357 |
3358 | /**
3359 | * Registers a dependency (in exception status) of one handle on
3360 | * another. The dependent handle must be "open" (i.e., assigned, but
3361 | * not finished yet). No action is taken if either dependent or target
3362 | * handle is NULL_HANDLE.
3363 | */
3364 | void markDependency(int dependent, int target) {
3365 | if (dependent == NULL_HANDLE || target == NULL_HANDLE) {
3366 | return;
3367 | }
3368 | switch (status[dependent]) {
3369 |
3370 | case STATUS_UNKNOWN:
3371 | switch (status[target]) {
3372 | case STATUS_OK:
3373 | // ignore dependencies on objs with no exception
3374 | break;
3375 |
3376 | case STATUS_EXCEPTION:
3377 | // eagerly propagate exception
3378 | markException(dependent,
3379 | (ClassNotFoundException) entries[target]);
3380 | break;
3381 |
3382 | case STATUS_UNKNOWN:
3383 | // add to dependency list of target
3384 | if (deps[target] == null) {
3385 | deps[target] = new HandleList();
3386 | }
3387 | deps[target].add(dependent);
3388 |
3389 | // remember lowest unresolved target seen
3390 | if (lowDep < 0 || lowDep > target) {
3391 | lowDep = target;
3392 | }
3393 | break;
3394 |
3395 | default:
3396 | throw new InternalError();
3397 | }
3398 | break;
3399 |
3400 | case STATUS_EXCEPTION:
3401 | break;
3402 |
3403 | default:
3404 | throw new InternalError();
3405 | }
3406 | }
3407 |
3408 | /**
3409 | * Associates a ClassNotFoundException (if one not already associated)
3410 | * with the currently active handle and propagates it to other
3411 | * referencing objects as appropriate. The specified handle must be
3412 | * "open" (i.e., assigned, but not finished yet).
3413 | */
3414 | void markException(int handle, ClassNotFoundException ex) {
3415 | switch (status[handle]) {
3416 | case STATUS_UNKNOWN:
3417 | status[handle] = STATUS_EXCEPTION;
3418 | entries[handle] = ex;
3419 |
3420 | // propagate exception to dependents
3421 | HandleList dlist = deps[handle];
3422 | if (dlist != null) {
3423 | int ndeps = dlist.size();
3424 | for (int i = 0; i < ndeps; i++) {
3425 | markException(dlist.get(i), ex);
3426 | }
3427 | deps[handle] = null;
3428 | }
3429 | break;
3430 |
3431 | case STATUS_EXCEPTION:
3432 | break;
3433 |
3434 | default:
3435 | throw new InternalError();
3436 | }
3437 | }
3438 |
3439 | /**
3440 | * Marks given handle as finished, meaning that no new dependencies
3441 | * will be marked for handle. Calls to the assign and finish methods
3442 | * must occur in LIFO order.
3443 | */
3444 | void finish(int handle) {
3445 | int end;
3446 | if (lowDep < 0) {
3447 | // no pending unknowns, only resolve current handle
3448 | end = handle + 1;
3449 | } else if (lowDep >= handle) {
3450 | // pending unknowns now clearable, resolve all upward handles
3451 | end = size;
3452 | lowDep = -1;
3453 | } else {
3454 | // unresolved backrefs present, can't resolve anything yet
3455 | return;
3456 | }
3457 |
3458 | // change STATUS_UNKNOWN -> STATUS_OK in selected span of handles
3459 | for (int i = handle; i < end; i++) {
3460 | switch (status[i]) {
3461 | case STATUS_UNKNOWN:
3462 | status[i] = STATUS_OK;
3463 | deps[i] = null;
3464 | break;
3465 |
3466 | case STATUS_OK:
3467 | case STATUS_EXCEPTION:
3468 | break;
3469 |
3470 | default:
3471 | throw new InternalError();
3472 | }
3473 | }
3474 | }
3475 |
3476 | /**
3477 | * Assigns a new object to the given handle. The object previously
3478 | * associated with the handle is forgotten. This method has no effect
3479 | * if the given handle already has an exception associated with it.
3480 | * This method may be called at any time after the handle is assigned.
3481 | */
3482 | void setObject(int handle, Object obj) {
3483 | switch (status[handle]) {
3484 | case STATUS_UNKNOWN:
3485 | case STATUS_OK:
3486 | entries[handle] = obj;
3487 | break;
3488 |
3489 | case STATUS_EXCEPTION:
3490 | break;
3491 |
3492 | default:
3493 | throw new InternalError();
3494 | }
3495 | }
3496 |
3497 | /**
3498 | * Looks up and returns object associated with the given handle.
3499 | * Returns null if the given handle is NULL_HANDLE, or if it has an
3500 | * associated ClassNotFoundException.
3501 | */
3502 | Object lookupObject(int handle) {
3503 | return (handle != NULL_HANDLE &&
3504 | status[handle] != STATUS_EXCEPTION) ?
3505 | entries[handle] : null;
3506 | }
3507 |
3508 | /**
3509 | * Looks up and returns ClassNotFoundException associated with the
3510 | * given handle. Returns null if the given handle is NULL_HANDLE, or
3511 | * if there is no ClassNotFoundException associated with the handle.
3512 | */
3513 | ClassNotFoundException lookupException(int handle) {
3514 | return (handle != NULL_HANDLE &&
3515 | status[handle] == STATUS_EXCEPTION) ?
3516 | (ClassNotFoundException) entries[handle] : null;
3517 | }
3518 |
3519 | /**
3520 | * Resets table to its initial state.
3521 | */
3522 | void clear() {
3523 | Arrays.fill(status, 0, size, (byte) 0);
3524 | Arrays.fill(entries, 0, size, null);
3525 | Arrays.fill(deps, 0, size, null);
3526 | lowDep = -1;
3527 | size = 0;
3528 | }
3529 |
3530 | /**
3531 | * Returns number of handles registered in table.
3532 | */
3533 | int size() {
3534 | return size;
3535 | }
3536 |
3537 | /**
3538 | * Expands capacity of internal arrays.
3539 | */
3540 | private void grow() {
3541 | int newCapacity = (entries.length << 1) + 1;
3542 |
3543 | byte[] newStatus = new byte[newCapacity];
3544 | Object[] newEntries = new Object[newCapacity];
3545 | HandleList[] newDeps = new HandleList[newCapacity];
3546 |
3547 | System.arraycopy(status, 0, newStatus, 0, size);
3548 | System.arraycopy(entries, 0, newEntries, 0, size);
3549 | System.arraycopy(deps, 0, newDeps, 0, size);
3550 |
3551 | status = newStatus;
3552 | entries = newEntries;
3553 | deps = newDeps;
3554 | }
3555 |
3556 | /**
3557 | * Simple growable list of (integer) handles.
3558 | */
3559 | private static class HandleList {
3560 | private int[] list = new int[4];
3561 | private int size = 0;
3562 |
3563 | public HandleList() {
3564 | }
3565 |
3566 | public void add(int handle) {
3567 | if (size >= list.length) {
3568 | int[] newList = new int[list.length << 1];
3569 | System.arraycopy(list, 0, newList, 0, list.length);
3570 | list = newList;
3571 | }
3572 | list[size++] = handle;
3573 | }
3574 |
3575 | public int get(int index) {
3576 | if (index >= size) {
3577 | throw new ArrayIndexOutOfBoundsException();
3578 | }
3579 | return list[index];
3580 | }
3581 |
3582 | public int size() {
3583 | return size;
3584 | }
3585 | }
3586 | }
3587 |
3588 | /**
3589 | * Method for cloning arrays in case of using unsharing reading
3590 | */
3591 | private static Object cloneArray(Object array) {
3592 | if (array instanceof Object[]) {
3593 | return ((Object[]) array).clone();
3594 | } else if (array instanceof boolean[]) {
3595 | return ((boolean[]) array).clone();
3596 | } else if (array instanceof byte[]) {
3597 | return ((byte[]) array).clone();
3598 | } else if (array instanceof char[]) {
3599 | return ((char[]) array).clone();
3600 | } else if (array instanceof double[]) {
3601 | return ((double[]) array).clone();
3602 | } else if (array instanceof float[]) {
3603 | return ((float[]) array).clone();
3604 | } else if (array instanceof int[]) {
3605 | return ((int[]) array).clone();
3606 | } else if (array instanceof long[]) {
3607 | return ((long[]) array).clone();
3608 | } else if (array instanceof short[]) {
3609 | return ((short[]) array).clone();
3610 | } else {
3611 | throw new AssertionError();
3612 | }
3613 | }
3614 |
3615 | }
3616 |
--------------------------------------------------------------------------------
Enum.valueOf(Class, String) with the enum constant's
191 | * base type and the received constant name as arguments. Like other
192 | * serializable or externalizable objects, enum constants can function as the
193 | * targets of back references appearing subsequently in the serialization
194 | * stream. The process by which enum constants are deserialized cannot be
195 | * customized: any class-specific readObject, readObjectNoData, and readResolve
196 | * methods defined by enum types are ignored during deserialization.
197 | * Similarly, any serialPersistentFields or serialVersionUID field declarations
198 | * are also ignored--all enum types have a fixed serialVersionUID of 0L.
199 | *
200 | * @author Mike Warres
201 | * @author Roger Riggs
202 | * @see java.io.DataInput
203 | * @see java.io.ObjectOutputStream
204 | * @see java.io.Serializable
205 | * @see Object Serialization Specification, Section 3, Object Input Classes
206 | * @since JDK1.1
207 | */
208 | public class ObjectInputStream
209 | extends InputStream implements ObjectInput, ObjectStreamConstants
210 | {
211 | /** handle value representing null */
212 | private static final int NULL_HANDLE = -1;
213 |
214 | /** marker for unshared objects in internal handle table */
215 | private static final Object unsharedMarker = new Object();
216 |
217 | /** table mapping primitive type names to corresponding class objects */
218 | private static final HashMapin is null
319 | * @see ObjectInputStream#ObjectInputStream()
320 | * @see ObjectInputStream#readFields()
321 | * @see ObjectOutputStream#ObjectOutputStream(OutputStream)
322 | */
323 | public ObjectInputStream(InputStream in) throws IOException {
324 | verifySubclass();
325 | bin = new BlockDataInputStream(in);
326 | handles = new HandleTable(10);
327 | vlist = new ValidationList();
328 | enableOverride = false;
329 | readStreamHeader();
330 | bin.setBlockDataMode(true);
331 | }
332 |
333 | /**
334 | * Provide a way for subclasses that are completely reimplementing
335 | * ObjectInputStream to not have to allocate private data just used by this
336 | * implementation of ObjectInputStream.
337 | *
338 | * checkPermission method with the
340 | * SerializablePermission("enableSubclassImplementation")
341 | * permission to ensure it's ok to enable subclassing.
342 | *
343 | * @throws SecurityException if a security manager exists and its
344 | * checkPermission method denies enabling
345 | * subclassing.
346 | * @throws IOException if an I/O error occurs while creating this stream
347 | * @see SecurityManager#checkPermission
348 | * @see java.io.SerializablePermission
349 | */
350 | protected ObjectInputStream() throws IOException, SecurityException {
351 | SecurityManager sm = System.getSecurityManager();
352 | if (sm != null) {
353 | sm.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION);
354 | }
355 | bin = null;
356 | handles = null;
357 | vlist = null;
358 | enableOverride = true;
359 | }
360 |
361 | /**
362 | * Read an object from the ObjectInputStream. The class of the object, the
363 | * signature of the class, and the values of the non-transient and
364 | * non-static fields of the class and all of its supertypes are read.
365 | * Default deserializing for a class can be overriden using the writeObject
366 | * and readObject methods. Objects referenced by this object are read
367 | * transitively so that a complete equivalent graph of objects is
368 | * reconstructed by readObject.
369 | *
370 | *
453 | *
462 | * Deserializing an object via readUnshared invalidates the stream handle
463 | * associated with the returned object. Note that this in itself does not
464 | * always guarantee that the reference returned by readUnshared is unique;
465 | * the deserialized object may define a readResolve method which returns an
466 | * object visible to other parties, or readUnshared may return a Class
467 | * object or enum constant obtainable elsewhere in the stream or through
468 | * external means. If the deserialized object defines a readResolve method
469 | * and the invocation of that method returns an array, then readUnshared
470 | * returns a shallow clone of that array; this guarantees that the returned
471 | * array object is unique and cannot be obtained a second time from an
472 | * invocation of readObject or readUnshared on the ObjectInputStream,
473 | * even if the underlying data stream has been manipulated.
474 | *
475 | * GetField object representing the persistent
557 | * fields of the object being deserialized
558 | * @throws ClassNotFoundException if the class of a serialized object
559 | * could not be found.
560 | * @throws IOException if an I/O error occurs.
561 | * @throws NotActiveException if the stream is not currently reading
562 | * objects.
563 | * @since 1.2
564 | */
565 | public ObjectInputStream.GetField readFields()
566 | throws IOException, ClassNotFoundException
567 | {
568 | SerialCallbackContext ctx = curContext;
569 | if (ctx == null) {
570 | throw new NotActiveException("not in call to readObject");
571 | }
572 | Object curObj = ctx.getObj();
573 | ObjectStreamClass curDesc = ctx.getDesc();
574 | bin.setBlockDataMode(false);
575 | GetFieldImpl getField = new GetFieldImpl(curDesc);
576 | getField.readFields();
577 | bin.setBlockDataMode(true);
578 | if (!curDesc.hasWriteObjectData()) {
579 | /*
580 | * Fix for 4360508: since stream does not contain terminating
581 | * TC_ENDBLOCKDATA tag, set flag so that reading code elsewhere
582 | * knows to simulate end-of-custom-data behavior.
583 | */
584 | defaultDataEnd = true;
585 | }
586 |
587 | return getField;
588 | }
589 |
590 | /**
591 | * Register an object to be validated before the graph is returned. While
592 | * similar to resolveObject these validations are called after the entire
593 | * graph has been reconstituted. Typically, a readObject method will
594 | * register the object with the stream so that when all of the objects are
595 | * restored a final set of validations can be performed.
596 | *
597 | * @param obj the object to receive the validation callback.
598 | * @param prio controls the order of callbacks;zero is a good default.
599 | * Use higher numbers to be called back earlier, lower numbers for
600 | * later callbacks. Within a priority, callbacks are processed in
601 | * no particular order.
602 | * @throws NotActiveException The stream is not currently reading objects
603 | * so it is invalid to register a callback.
604 | * @throws InvalidObjectException The validation object is null.
605 | */
606 | public void registerValidation(ObjectInputValidation obj, int prio)
607 | throws NotActiveException, InvalidObjectException
608 | {
609 | if (depth == 0) {
610 | throw new NotActiveException("stream inactive");
611 | }
612 | vlist.register(obj, prio);
613 | }
614 |
615 | /**
616 | * Load the local class equivalent of the specified stream class
617 | * description. Subclasses may implement this method to allow classes to
618 | * be fetched from an alternate source.
619 | *
620 | * ObjectOutputStream is
621 | * annotateClass. This method will be invoked only once for
622 | * each unique class in the stream. This method can be implemented by
623 | * subclasses to use an alternate loading mechanism but must return a
624 | * Class object. Once returned, if the class is not an array
625 | * class, its serialVersionUID is compared to the serialVersionUID of the
626 | * serialized class, and if there is a mismatch, the deserialization fails
627 | * and an {@link InvalidClassException} is thrown.
628 | *
629 | * ObjectInputStream returns the result of calling
631 | *
632 | * Class.forName(desc.getName(), false, loader)
633 | *
634 | * where loader is determined as follows: if there is a
635 | * method on the current thread's stack whose declaring class was
636 | * defined by a user-defined class loader (and was not a generated to
637 | * implement reflective invocations), then loader is class
638 | * loader corresponding to the closest such method to the currently
639 | * executing frame; otherwise, loader is
640 | * null. If this call results in a
641 | * ClassNotFoundException and the name of the passed
642 | * ObjectStreamClass instance is the Java language keyword
643 | * for a primitive type or void, then the Class object
644 | * representing that primitive type or void will be returned
645 | * (e.g., an ObjectStreamClass with the name
646 | * "int" will be resolved to Integer.TYPE).
647 | * Otherwise, the ClassNotFoundException will be thrown to
648 | * the caller of this method.
649 | *
650 | * @param desc an instance of class ObjectStreamClass
651 | * @return a Class object corresponding to desc
652 | * @throws IOException any of the usual Input/Output exceptions.
653 | * @throws ClassNotFoundException if class of a serialized object cannot
654 | * be found.
655 | */
656 | protected Class> resolveClass(ObjectStreamClass desc)
657 | throws IOException, ClassNotFoundException
658 | {
659 | String name = desc.getName();
660 | logger.fine("resolveClass: resolving " + name);
661 |
662 | // From https://github.com/ikkisoft/SerialKiller by luca.carettoni@ikkisoft.com
663 |
664 | //Enforce blacklist
665 | for (Pattern blackPattern : blacklistPatterns) {
666 | Matcher blackMatcher = blackPattern.matcher(name);
667 | if (blackMatcher.find()) {
668 | logger.warning("resolveClass: rejecting blacklisted class " + name);
669 | String msg = "[!] Blocked by blacklist '"
670 | + blackPattern.pattern() + "'. Match found for '" + name + "'";
671 | throw new InvalidClassException(msg);
672 | }
673 | }
674 |
675 | //Enforce whitelist if it exists.
676 | if (! whitelistPatterns.isEmpty()) {
677 | boolean safeClass = false;
678 | for (Pattern whitePattern: whitelistPatterns) {
679 | Matcher whiteMatcher = whitePattern.matcher(name);
680 | if (whiteMatcher.find()) {
681 | safeClass = true;
682 | break;
683 | }
684 | }
685 |
686 | if (!safeClass) {
687 | logger.warning("resolveClass: rejecting class " + name + " not found in whitelist.");
688 | String msg = "[!] Blocked by whitelist. No match found for '" + name + "'";
689 | throw new InvalidClassException(msg);
690 | }
691 | }
692 |
693 | try {
694 | logger.fine("resolveClass: accepting class " + name);
695 | return Class.forName(name, false, latestUserDefinedLoader());
696 | } catch (ClassNotFoundException ex) {
697 | Class> cl = primClasses.get(name);
698 | if (cl != null) {
699 | return cl;
700 | } else {
701 | throw ex;
702 | }
703 | }
704 | }
705 |
706 | /**
707 | * Returns a proxy class that implements the interfaces named in a proxy
708 | * class descriptor; subclasses may implement this method to read custom
709 | * data from the stream along with the descriptors for dynamic proxy
710 | * classes, allowing them to use an alternate loading mechanism for the
711 | * interfaces and the proxy class.
712 | *
713 | * ObjectOutputStream is
717 | * annotateProxyClass. For a given subclass of
718 | * ObjectInputStream that overrides this method, the
719 | * annotateProxyClass method in the corresponding subclass of
720 | * ObjectOutputStream must write any data or objects read by
721 | * this method.
722 | *
723 | * ObjectInputStream returns the result of calling
725 | * Proxy.getProxyClass with the list of Class
726 | * objects for the interfaces that are named in the interfaces
727 | * parameter. The Class object for each interface name
728 | * i is the value returned by calling
729 | *
730 | * Class.forName(i, false, loader)
731 | *
732 | * where loader is that of the first non-null
733 | * class loader up the execution stack, or null if no
734 | * non-null class loaders are on the stack (the same class
735 | * loader choice used by the resolveClass method). Unless any
736 | * of the resolved interfaces are non-public, this same value of
737 | * loader is also the class loader passed to
738 | * Proxy.getProxyClass; if non-public interfaces are present,
739 | * their class loader is passed instead (if more than one non-public
740 | * interface class loader is encountered, an
741 | * IllegalAccessError is thrown).
742 | * If Proxy.getProxyClass throws an
743 | * IllegalArgumentException, resolveProxyClass
744 | * will throw a ClassNotFoundException containing the
745 | * IllegalArgumentException.
746 | *
747 | * @param interfaces the list of interface names that were
748 | * deserialized in the proxy class descriptor
749 | * @return a proxy class for the specified interfaces
750 | * @throws IOException any exception thrown by the underlying
751 | * InputStream
752 | * @throws ClassNotFoundException if the proxy class or any of the
753 | * named interfaces could not be found
754 | * @see ObjectOutputStream#annotateProxyClass(Class)
755 | * @since 1.3
756 | */
757 | protected Class> resolveProxyClass(String[] interfaces)
758 | throws IOException, ClassNotFoundException
759 | {
760 | ClassLoader latestLoader = latestUserDefinedLoader();
761 | ClassLoader nonPublicLoader = null;
762 | boolean hasNonPublicInterface = false;
763 |
764 | // define proxy in class loader of non-public interface(s), if any
765 | Class>[] classObjs = new Class>[interfaces.length];
766 | for (int i = 0; i < interfaces.length; i++) {
767 | Class> cl = Class.forName(interfaces[i], false, latestLoader);
768 | if ((cl.getModifiers() & Modifier.PUBLIC) == 0) {
769 | if (hasNonPublicInterface) {
770 | if (nonPublicLoader != cl.getClassLoader()) {
771 | throw new IllegalAccessError(
772 | "conflicting non-public interface class loaders");
773 | }
774 | } else {
775 | nonPublicLoader = cl.getClassLoader();
776 | hasNonPublicInterface = true;
777 | }
778 | }
779 | classObjs[i] = cl;
780 | }
781 | try {
782 | return Proxy.getProxyClass(
783 | hasNonPublicInterface ? nonPublicLoader : latestLoader,
784 | classObjs);
785 | } catch (IllegalArgumentException e) {
786 | throw new ClassNotFoundException(null, e);
787 | }
788 | }
789 |
790 | /**
791 | * This method will allow trusted subclasses of ObjectInputStream to
792 | * substitute one object for another during deserialization. Replacing
793 | * objects is disabled until enableResolveObject is called. The
794 | * enableResolveObject method checks that the stream requesting to resolve
795 | * object can be trusted. Every reference to serializable objects is passed
796 | * to resolveObject. To insure that the private state of objects is not
797 | * unintentionally exposed only trusted streams may use resolveObject.
798 | *
799 | * checkPermission method with the
829 | * SerializablePermission("enableSubstitution") permission to
830 | * ensure it's ok to enable the stream to allow objects read from the
831 | * stream to be replaced.
832 | *
833 | * @param enable true for enabling use of resolveObject for
834 | * every object being deserialized
835 | * @return the previous setting before this method was invoked
836 | * @throws SecurityException if a security manager exists and its
837 | * checkPermission method denies enabling the stream
838 | * to allow objects read from the stream to be replaced.
839 | * @see SecurityManager#checkPermission
840 | * @see java.io.SerializablePermission
841 | */
842 | protected boolean enableResolveObject(boolean enable)
843 | throws SecurityException
844 | {
845 | if (enable == enableResolve) {
846 | return enable;
847 | }
848 | if (enable) {
849 | SecurityManager sm = System.getSecurityManager();
850 | if (sm != null) {
851 | sm.checkPermission(SUBSTITUTION_PERMISSION);
852 | }
853 | }
854 | enableResolve = enable;
855 | return !enableResolve;
856 | }
857 |
858 | /**
859 | * The readStreamHeader method is provided to allow subclasses to read and
860 | * verify their own stream headers. It reads and verifies the magic number
861 | * and version number.
862 | *
863 | * @throws IOException if there are I/O errors while reading from the
864 | * underlying InputStream
865 | * @throws StreamCorruptedException if control information in the stream
866 | * is inconsistent
867 | */
868 | protected void readStreamHeader()
869 | throws IOException, StreamCorruptedException
870 | {
871 | short s0 = bin.readShort();
872 | short s1 = bin.readShort();
873 | if (s0 != STREAM_MAGIC || s1 != STREAM_VERSION) {
874 | throw new StreamCorruptedException(
875 | String.format("invalid stream header: %04X%04X", s0, s1));
876 | }
877 | }
878 |
879 | /**
880 | * Read a class descriptor from the serialization stream. This method is
881 | * called when the ObjectInputStream expects a class descriptor as the next
882 | * item in the serialization stream. Subclasses of ObjectInputStream may
883 | * override this method to read in class descriptors that have been written
884 | * in non-standard formats (by subclasses of ObjectOutputStream which have
885 | * overridden the writeClassDescriptor method). By default,
886 | * this method reads class descriptors according to the format defined in
887 | * the Object Serialization specification.
888 | *
889 | * @return the class descriptor read
890 | * @throws IOException If an I/O error has occurred.
891 | * @throws ClassNotFoundException If the Class of a serialized object used
892 | * in the class descriptor representation cannot be found
893 | * @see java.io.ObjectOutputStream#writeClassDescriptor(java.io.ObjectStreamClass)
894 | * @since 1.3
895 | */
896 | protected ObjectStreamClass readClassDescriptor()
897 | throws IOException, ClassNotFoundException
898 | {
899 | ObjectStreamClass desc = new ObjectStreamClass();
900 | desc.readNonProxy(this);
901 | return desc;
902 | }
903 |
904 | /**
905 | * Reads a byte of data. This method will block if no input is available.
906 | *
907 | * @return the byte read, or -1 if the end of the stream is reached.
908 | * @throws IOException If an I/O error has occurred.
909 | */
910 | public int read() throws IOException {
911 | return bin.read();
912 | }
913 |
914 | /**
915 | * Reads into an array of bytes. This method will block until some input
916 | * is available. Consider using java.io.DataInputStream.readFully to read
917 | * exactly 'length' bytes.
918 | *
919 | * @param buf the buffer into which the data is read
920 | * @param off the start offset of the data
921 | * @param len the maximum number of bytes read
922 | * @return the actual number of bytes read, -1 is returned when the end of
923 | * the stream is reached.
924 | * @throws IOException If an I/O error has occurred.
925 | * @see java.io.DataInputStream#readFully(byte[],int,int)
926 | */
927 | public int read(byte[] buf, int off, int len) throws IOException {
928 | if (buf == null) {
929 | throw new NullPointerException();
930 | }
931 | int endoff = off + len;
932 | if (off < 0 || len < 0 || endoff > buf.length || endoff < 0) {
933 | throw new IndexOutOfBoundsException();
934 | }
935 | return bin.read(buf, off, len, false);
936 | }
937 |
938 | /**
939 | * Returns the number of bytes that can be read without blocking.
940 | *
941 | * @return the number of available bytes.
942 | * @throws IOException if there are I/O errors while reading from the
943 | * underlying InputStream
944 | */
945 | public int available() throws IOException {
946 | return bin.available();
947 | }
948 |
949 | /**
950 | * Closes the input stream. Must be called to release any resources
951 | * associated with the stream.
952 | *
953 | * @throws IOException If an I/O error has occurred.
954 | */
955 | public void close() throws IOException {
956 | /*
957 | * Even if stream already closed, propagate redundant close to
958 | * underlying stream to stay consistent with previous implementations.
959 | */
960 | closed = true;
961 | if (depth == 0) {
962 | clear();
963 | }
964 | bin.close();
965 | }
966 |
967 | /**
968 | * Reads in a boolean.
969 | *
970 | * @return the boolean read.
971 | * @throws EOFException If end of file is reached.
972 | * @throws IOException If other I/O error has occurred.
973 | */
974 | public boolean readBoolean() throws IOException {
975 | return bin.readBoolean();
976 | }
977 |
978 | /**
979 | * Reads an 8 bit byte.
980 | *
981 | * @return the 8 bit byte read.
982 | * @throws EOFException If end of file is reached.
983 | * @throws IOException If other I/O error has occurred.
984 | */
985 | public byte readByte() throws IOException {
986 | return bin.readByte();
987 | }
988 |
989 | /**
990 | * Reads an unsigned 8 bit byte.
991 | *
992 | * @return the 8 bit byte read.
993 | * @throws EOFException If end of file is reached.
994 | * @throws IOException If other I/O error has occurred.
995 | */
996 | public int readUnsignedByte() throws IOException {
997 | return bin.readUnsignedByte();
998 | }
999 |
1000 | /**
1001 | * Reads a 16 bit char.
1002 | *
1003 | * @return the 16 bit char read.
1004 | * @throws EOFException If end of file is reached.
1005 | * @throws IOException If other I/O error has occurred.
1006 | */
1007 | public char readChar() throws IOException {
1008 | return bin.readChar();
1009 | }
1010 |
1011 | /**
1012 | * Reads a 16 bit short.
1013 | *
1014 | * @return the 16 bit short read.
1015 | * @throws EOFException If end of file is reached.
1016 | * @throws IOException If other I/O error has occurred.
1017 | */
1018 | public short readShort() throws IOException {
1019 | return bin.readShort();
1020 | }
1021 |
1022 | /**
1023 | * Reads an unsigned 16 bit short.
1024 | *
1025 | * @return the 16 bit short read.
1026 | * @throws EOFException If end of file is reached.
1027 | * @throws IOException If other I/O error has occurred.
1028 | */
1029 | public int readUnsignedShort() throws IOException {
1030 | return bin.readUnsignedShort();
1031 | }
1032 |
1033 | /**
1034 | * Reads a 32 bit int.
1035 | *
1036 | * @return the 32 bit integer read.
1037 | * @throws EOFException If end of file is reached.
1038 | * @throws IOException If other I/O error has occurred.
1039 | */
1040 | public int readInt() throws IOException {
1041 | return bin.readInt();
1042 | }
1043 |
1044 | /**
1045 | * Reads a 64 bit long.
1046 | *
1047 | * @return the read 64 bit long.
1048 | * @throws EOFException If end of file is reached.
1049 | * @throws IOException If other I/O error has occurred.
1050 | */
1051 | public long readLong() throws IOException {
1052 | return bin.readLong();
1053 | }
1054 |
1055 | /**
1056 | * Reads a 32 bit float.
1057 | *
1058 | * @return the 32 bit float read.
1059 | * @throws EOFException If end of file is reached.
1060 | * @throws IOException If other I/O error has occurred.
1061 | */
1062 | public float readFloat() throws IOException {
1063 | return bin.readFloat();
1064 | }
1065 |
1066 | /**
1067 | * Reads a 64 bit double.
1068 | *
1069 | * @return the 64 bit double read.
1070 | * @throws EOFException If end of file is reached.
1071 | * @throws IOException If other I/O error has occurred.
1072 | */
1073 | public double readDouble() throws IOException {
1074 | return bin.readDouble();
1075 | }
1076 |
1077 | /**
1078 | * Reads bytes, blocking until all bytes are read.
1079 | *
1080 | * @param buf the buffer into which the data is read
1081 | * @throws EOFException If end of file is reached.
1082 | * @throws IOException If other I/O error has occurred.
1083 | */
1084 | public void readFully(byte[] buf) throws IOException {
1085 | bin.readFully(buf, 0, buf.length, false);
1086 | }
1087 |
1088 | /**
1089 | * Reads bytes, blocking until all bytes are read.
1090 | *
1091 | * @param buf the buffer into which the data is read
1092 | * @param off the start offset of the data
1093 | * @param len the maximum number of bytes to read
1094 | * @throws EOFException If end of file is reached.
1095 | * @throws IOException If other I/O error has occurred.
1096 | */
1097 | public void readFully(byte[] buf, int off, int len) throws IOException {
1098 | int endoff = off + len;
1099 | if (off < 0 || len < 0 || endoff > buf.length || endoff < 0) {
1100 | throw new IndexOutOfBoundsException();
1101 | }
1102 | bin.readFully(buf, off, len, false);
1103 | }
1104 |
1105 | /**
1106 | * Skips bytes.
1107 | *
1108 | * @param len the number of bytes to be skipped
1109 | * @return the actual number of bytes skipped.
1110 | * @throws IOException If an I/O error has occurred.
1111 | */
1112 | public int skipBytes(int len) throws IOException {
1113 | return bin.skipBytes(len);
1114 | }
1115 |
1116 | /**
1117 | * Reads in a line that has been terminated by a \n, \r, \r\n or EOF.
1118 | *
1119 | * @return a String copy of the line.
1120 | * @throws IOException if there are I/O errors while reading from the
1121 | * underlying InputStream
1122 | * @deprecated This method does not properly convert bytes to characters.
1123 | * see DataInputStream for the details and alternatives.
1124 | */
1125 | @Deprecated
1126 | public String readLine() throws IOException {
1127 | return bin.readLine();
1128 | }
1129 |
1130 | /**
1131 | * Reads a String in
1132 | * modified UTF-8
1133 | * format.
1134 | *
1135 | * @return the String.
1136 | * @throws IOException if there are I/O errors while reading from the
1137 | * underlying InputStream
1138 | * @throws UTFDataFormatException if read bytes do not represent a valid
1139 | * modified UTF-8 encoding of a string
1140 | */
1141 | public String readUTF() throws IOException {
1142 | return bin.readUTF();
1143 | }
1144 |
1145 | /**
1146 | * Provide access to the persistent fields read from the input stream.
1147 | */
1148 | public static abstract class GetField {
1149 |
1150 | /**
1151 | * Get the ObjectStreamClass that describes the fields in the stream.
1152 | *
1153 | * @return the descriptor class that describes the serializable fields
1154 | */
1155 | public abstract ObjectStreamClass getObjectStreamClass();
1156 |
1157 | /**
1158 | * Return true if the named field is defaulted and has no value in this
1159 | * stream.
1160 | *
1161 | * @param name the name of the field
1162 | * @return true, if and only if the named field is defaulted
1163 | * @throws IOException if there are I/O errors while reading from
1164 | * the underlying InputStream
1165 | * @throws IllegalArgumentException if name does not
1166 | * correspond to a serializable field
1167 | */
1168 | public abstract boolean defaulted(String name) throws IOException;
1169 |
1170 | /**
1171 | * Get the value of the named boolean field from the persistent field.
1172 | *
1173 | * @param name the name of the field
1174 | * @param val the default value to use if name does not
1175 | * have a value
1176 | * @return the value of the named boolean field
1177 | * @throws IOException if there are I/O errors while reading from the
1178 | * underlying InputStream
1179 | * @throws IllegalArgumentException if type of name is
1180 | * not serializable or if the field type is incorrect
1181 | */
1182 | public abstract boolean get(String name, boolean val)
1183 | throws IOException;
1184 |
1185 | /**
1186 | * Get the value of the named byte field from the persistent field.
1187 | *
1188 | * @param name the name of the field
1189 | * @param val the default value to use if name does not
1190 | * have a value
1191 | * @return the value of the named byte field
1192 | * @throws IOException if there are I/O errors while reading from the
1193 | * underlying InputStream
1194 | * @throws IllegalArgumentException if type of name is
1195 | * not serializable or if the field type is incorrect
1196 | */
1197 | public abstract byte get(String name, byte val) throws IOException;
1198 |
1199 | /**
1200 | * Get the value of the named char field from the persistent field.
1201 | *
1202 | * @param name the name of the field
1203 | * @param val the default value to use if name does not
1204 | * have a value
1205 | * @return the value of the named char field
1206 | * @throws IOException if there are I/O errors while reading from the
1207 | * underlying InputStream
1208 | * @throws IllegalArgumentException if type of name is
1209 | * not serializable or if the field type is incorrect
1210 | */
1211 | public abstract char get(String name, char val) throws IOException;
1212 |
1213 | /**
1214 | * Get the value of the named short field from the persistent field.
1215 | *
1216 | * @param name the name of the field
1217 | * @param val the default value to use if name does not
1218 | * have a value
1219 | * @return the value of the named short field
1220 | * @throws IOException if there are I/O errors while reading from the
1221 | * underlying InputStream
1222 | * @throws IllegalArgumentException if type of name is
1223 | * not serializable or if the field type is incorrect
1224 | */
1225 | public abstract short get(String name, short val) throws IOException;
1226 |
1227 | /**
1228 | * Get the value of the named int field from the persistent field.
1229 | *
1230 | * @param name the name of the field
1231 | * @param val the default value to use if name does not
1232 | * have a value
1233 | * @return the value of the named int field
1234 | * @throws IOException if there are I/O errors while reading from the
1235 | * underlying InputStream
1236 | * @throws IllegalArgumentException if type of name is
1237 | * not serializable or if the field type is incorrect
1238 | */
1239 | public abstract int get(String name, int val) throws IOException;
1240 |
1241 | /**
1242 | * Get the value of the named long field from the persistent field.
1243 | *
1244 | * @param name the name of the field
1245 | * @param val the default value to use if name does not
1246 | * have a value
1247 | * @return the value of the named long field
1248 | * @throws IOException if there are I/O errors while reading from the
1249 | * underlying InputStream
1250 | * @throws IllegalArgumentException if type of name is
1251 | * not serializable or if the field type is incorrect
1252 | */
1253 | public abstract long get(String name, long val) throws IOException;
1254 |
1255 | /**
1256 | * Get the value of the named float field from the persistent field.
1257 | *
1258 | * @param name the name of the field
1259 | * @param val the default value to use if name does not
1260 | * have a value
1261 | * @return the value of the named float field
1262 | * @throws IOException if there are I/O errors while reading from the
1263 | * underlying InputStream
1264 | * @throws IllegalArgumentException if type of name is
1265 | * not serializable or if the field type is incorrect
1266 | */
1267 | public abstract float get(String name, float val) throws IOException;
1268 |
1269 | /**
1270 | * Get the value of the named double field from the persistent field.
1271 | *
1272 | * @param name the name of the field
1273 | * @param val the default value to use if name does not
1274 | * have a value
1275 | * @return the value of the named double field
1276 | * @throws IOException if there are I/O errors while reading from the
1277 | * underlying InputStream
1278 | * @throws IllegalArgumentException if type of name is
1279 | * not serializable or if the field type is incorrect
1280 | */
1281 | public abstract double get(String name, double val) throws IOException;
1282 |
1283 | /**
1284 | * Get the value of the named Object field from the persistent field.
1285 | *
1286 | * @param name the name of the field
1287 | * @param val the default value to use if name does not
1288 | * have a value
1289 | * @return the value of the named Object field
1290 | * @throws IOException if there are I/O errors while reading from the
1291 | * underlying InputStream
1292 | * @throws IllegalArgumentException if type of name is
1293 | * not serializable or if the field type is incorrect
1294 | */
1295 | public abstract Object get(String name, Object val) throws IOException;
1296 | }
1297 |
1298 | /**
1299 | * Verifies that this (possibly subclass) instance can be constructed
1300 | * without violating security constraints: the subclass must not override
1301 | * security-sensitive non-final methods, or else the
1302 | * "enableSubclassImplementation" SerializablePermission is checked.
1303 | */
1304 | private void verifySubclass() {
1305 | Class> cl = getClass();
1306 | if (cl == ObjectInputStream.class) {
1307 | return;
1308 | }
1309 | SecurityManager sm = System.getSecurityManager();
1310 | if (sm == null) {
1311 | return;
1312 | }
1313 | processQueue(Caches.subclassAuditsQueue, Caches.subclassAudits);
1314 | WeakClassKey key = new WeakClassKey(cl, Caches.subclassAuditsQueue);
1315 | Boolean result = Caches.subclassAudits.get(key);
1316 | if (result == null) {
1317 | result = Boolean.valueOf(auditSubclass(cl));
1318 | Caches.subclassAudits.putIfAbsent(key, result);
1319 | }
1320 | if (result.booleanValue()) {
1321 | return;
1322 | }
1323 | sm.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION);
1324 | }
1325 |
1326 | /**
1327 | * Performs reflective checks on given subclass to verify that it doesn't
1328 | * override security-sensitive non-final methods. Returns true if subclass
1329 | * is "safe", false otherwise.
1330 | */
1331 | private static boolean auditSubclass(final Class> subcl) {
1332 | Boolean result = AccessController.doPrivileged(
1333 | new PrivilegedAction