14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package java.lang;
27
28 import java.lang.annotation.Annotation;
29 import java.lang.constant.ClassDesc;
30 import java.lang.constant.ConstantDescs;
31 import java.lang.invoke.TypeDescriptor;
32 import java.lang.invoke.MethodHandles;
33 import java.lang.module.ModuleReader;
34 import java.lang.ref.SoftReference;
35 import java.io.IOException;
36 import java.io.InputStream;
37 import java.io.ObjectStreamField;
38 import java.lang.reflect.AnnotatedElement;
39 import java.lang.reflect.AnnotatedType;
40 import java.lang.reflect.AccessFlag;
41 import java.lang.reflect.Array;
42 import java.lang.reflect.Constructor;
43 import java.lang.reflect.Executable;
44 import java.lang.reflect.Field;
45 import java.lang.reflect.GenericArrayType;
46 import java.lang.reflect.GenericDeclaration;
47 import java.lang.reflect.InvocationTargetException;
48 import java.lang.reflect.Member;
49 import java.lang.reflect.Method;
50 import java.lang.reflect.Modifier;
51 import java.lang.reflect.Proxy;
52 import java.lang.reflect.RecordComponent;
53 import java.lang.reflect.Type;
54 import java.lang.reflect.TypeVariable;
442 * by this method fails
443 * @throws ClassNotFoundException if the class cannot be located
444 *
445 * @jls 12.2 Loading of Classes and Interfaces
446 * @jls 12.3 Linking of Classes and Interfaces
447 * @jls 12.4 Initialization of Classes and Interfaces
448 */
449 @CallerSensitive
450 public static Class<?> forName(String className)
451 throws ClassNotFoundException {
452 Class<?> caller = Reflection.getCallerClass();
453 return forName(className, caller);
454 }
455
456 // Caller-sensitive adapter method for reflective invocation
457 @CallerSensitiveAdapter
458 private static Class<?> forName(String className, Class<?> caller)
459 throws ClassNotFoundException {
460 ClassLoader loader = (caller == null) ? ClassLoader.getSystemClassLoader()
461 : ClassLoader.getClassLoader(caller);
462 return forName0(className, true, loader, caller);
463 }
464
465 /**
466 * Returns the {@code Class} object associated with the class or
467 * interface with the given string name, using the given class loader.
468 * Given the {@linkplain ClassLoader##binary-name binary name} for a class or interface,
469 * this method attempts to locate and load the class or interface. The specified
470 * class loader is used to load the class or interface. If the parameter
471 * {@code loader} is {@code null}, the class is loaded through the bootstrap
472 * class loader. The class is initialized only if the
473 * {@code initialize} parameter is {@code true} and if it has
474 * not been initialized earlier.
475 *
476 * <p> This method cannot be used to obtain any of the {@code Class} objects
477 * representing primitive types or void, hidden classes or interfaces,
478 * or array classes whose element type is a hidden class or interface.
479 * If {@code name} denotes a primitive type or void, for example {@code I},
480 * an attempt will be made to locate a user-defined class in the unnamed package
481 * whose name is {@code I} instead.
558 }
559
560 // Caller-sensitive adapter method for reflective invocation
561 @CallerSensitiveAdapter
562 private static Class<?> forName(String name, boolean initialize, ClassLoader loader, Class<?> caller)
563 throws ClassNotFoundException
564 {
565 @SuppressWarnings("removal")
566 SecurityManager sm = System.getSecurityManager();
567 if (sm != null) {
568 // Reflective call to get caller class is only needed if a security manager
569 // is present. Avoid the overhead of making this call otherwise.
570 if (loader == null) {
571 ClassLoader ccl = ClassLoader.getClassLoader(caller);
572 if (ccl != null) {
573 sm.checkPermission(
574 SecurityConstants.GET_CLASSLOADER_PERMISSION);
575 }
576 }
577 }
578 return forName0(name, initialize, loader, caller);
579 }
580
581 /** Called after security check for system loader access checks have been made. */
582 private static native Class<?> forName0(String name, boolean initialize,
583 ClassLoader loader,
584 Class<?> caller)
585 throws ClassNotFoundException;
586
587
588 /**
589 * Returns the {@code Class} with the given {@linkplain ClassLoader##binary-name
590 * binary name} in the given module.
591 *
592 * <p> This method attempts to locate and load the class or interface.
593 * It does not link the class, and does not run the class initializer.
594 * If the class is not found, this method returns {@code null}. </p>
595 *
596 * <p> If the class loader of the given module defines other modules and
597 * the given name is a class defined in a different module, this method
3381 }
3382
3383 /**
3384 * Atomic operations support.
3385 */
3386 private static class Atomic {
3387 // initialize Unsafe machinery here, since we need to call Class.class instance method
3388 // and have to avoid calling it in the static initializer of the Class class...
3389 private static final Unsafe unsafe = Unsafe.getUnsafe();
3390 // offset of Class.reflectionData instance field
3391 private static final long reflectionDataOffset
3392 = unsafe.objectFieldOffset(Class.class, "reflectionData");
3393 // offset of Class.annotationType instance field
3394 private static final long annotationTypeOffset
3395 = unsafe.objectFieldOffset(Class.class, "annotationType");
3396 // offset of Class.annotationData instance field
3397 private static final long annotationDataOffset
3398 = unsafe.objectFieldOffset(Class.class, "annotationData");
3399
3400 static <T> boolean casReflectionData(Class<?> clazz,
3401 SoftReference<ReflectionData<T>> oldData,
3402 SoftReference<ReflectionData<T>> newData) {
3403 return unsafe.compareAndSetReference(clazz, reflectionDataOffset, oldData, newData);
3404 }
3405
3406 static boolean casAnnotationType(Class<?> clazz,
3407 AnnotationType oldType,
3408 AnnotationType newType) {
3409 return unsafe.compareAndSetReference(clazz, annotationTypeOffset, oldType, newType);
3410 }
3411
3412 static boolean casAnnotationData(Class<?> clazz,
3413 AnnotationData oldData,
3414 AnnotationData newData) {
3415 return unsafe.compareAndSetReference(clazz, annotationDataOffset, oldData, newData);
3416 }
3417 }
3418
3419 /**
3420 * Reflection support.
3421 */
3422
3430 volatile Constructor<T>[] declaredConstructors;
3431 volatile Constructor<T>[] publicConstructors;
3432 // Intermediate results for getFields and getMethods
3433 volatile Field[] declaredPublicFields;
3434 volatile Method[] declaredPublicMethods;
3435 volatile Class<?>[] interfaces;
3436
3437 // Cached names
3438 String simpleName;
3439 String canonicalName;
3440 static final String NULL_SENTINEL = new String();
3441
3442 // Value of classRedefinedCount when we created this ReflectionData instance
3443 final int redefinedCount;
3444
3445 ReflectionData(int redefinedCount) {
3446 this.redefinedCount = redefinedCount;
3447 }
3448 }
3449
3450 private transient volatile SoftReference<ReflectionData<T>> reflectionData;
3451
3452 // Incremented by the VM on each call to JVM TI RedefineClasses()
3453 // that redefines this class or a superclass.
3454 private transient volatile int classRedefinedCount;
3455
3456 // Lazily create and cache ReflectionData
3457 private ReflectionData<T> reflectionData() {
3458 SoftReference<ReflectionData<T>> reflectionData = this.reflectionData;
3459 int classRedefinedCount = this.classRedefinedCount;
3460 ReflectionData<T> rd;
3461 if (reflectionData != null &&
3462 (rd = reflectionData.get()) != null &&
3463 rd.redefinedCount == classRedefinedCount) {
3464 return rd;
3465 }
3466 // else no SoftReference or cleared SoftReference or stale ReflectionData
3467 // -> create and replace new instance
3468 return newReflectionData(reflectionData, classRedefinedCount);
3469 }
3470
3471 private ReflectionData<T> newReflectionData(SoftReference<ReflectionData<T>> oldReflectionData,
3472 int classRedefinedCount) {
3473 while (true) {
3474 ReflectionData<T> rd = new ReflectionData<>(classRedefinedCount);
3475 // try to CAS it...
3476 if (Atomic.casReflectionData(this, oldReflectionData, new SoftReference<>(rd))) {
3477 return rd;
3478 }
3479 // else retry
3480 oldReflectionData = this.reflectionData;
3481 classRedefinedCount = this.classRedefinedCount;
3482 if (oldReflectionData != null &&
3483 (rd = oldReflectionData.get()) != null &&
3484 rd.redefinedCount == classRedefinedCount) {
3485 return rd;
3486 }
3487 }
3488 }
3489
3490 // Generic signature handling
3491 private native String getGenericSignature0();
3492
3493 // Generic info repository; lazily initialized
3494 private transient volatile ClassRepository genericInfo;
3495
3496 // accessor for factory
3497 private GenericsFactory getFactory() {
3498 // create scope and factory
3499 return CoreReflectionFactory.make(this, ClassScope.make(this));
3500 }
3501
3502 // accessor for generic info repository;
3503 // generic info is lazily initialized
3504 private ClassRepository getGenericInfo() {
4834 private int getClassFileVersion() {
4835 Class<?> c = isArray() ? elementType() : this;
4836 return c.getClassFileVersion0();
4837 }
4838
4839 private native int getClassFileVersion0();
4840
4841 /*
4842 * Return the access flags as they were in the class's bytecode, including
4843 * the original setting of ACC_SUPER.
4844 *
4845 * If the class is an array type then the access flags of the element type is
4846 * returned. If the class is a primitive then ACC_ABSTRACT | ACC_FINAL | ACC_PUBLIC.
4847 */
4848 private int getClassAccessFlagsRaw() {
4849 Class<?> c = isArray() ? elementType() : this;
4850 return c.getClassAccessFlagsRaw0();
4851 }
4852
4853 private native int getClassAccessFlagsRaw0();
4854 }
|
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package java.lang;
27
28 import java.lang.annotation.Annotation;
29 import java.lang.constant.ClassDesc;
30 import java.lang.constant.ConstantDescs;
31 import java.lang.invoke.TypeDescriptor;
32 import java.lang.invoke.MethodHandles;
33 import java.lang.module.ModuleReader;
34 import java.io.IOException;
35 import java.io.InputStream;
36 import java.io.ObjectStreamField;
37 import java.lang.reflect.AnnotatedElement;
38 import java.lang.reflect.AnnotatedType;
39 import java.lang.reflect.AccessFlag;
40 import java.lang.reflect.Array;
41 import java.lang.reflect.Constructor;
42 import java.lang.reflect.Executable;
43 import java.lang.reflect.Field;
44 import java.lang.reflect.GenericArrayType;
45 import java.lang.reflect.GenericDeclaration;
46 import java.lang.reflect.InvocationTargetException;
47 import java.lang.reflect.Member;
48 import java.lang.reflect.Method;
49 import java.lang.reflect.Modifier;
50 import java.lang.reflect.Proxy;
51 import java.lang.reflect.RecordComponent;
52 import java.lang.reflect.Type;
53 import java.lang.reflect.TypeVariable;
441 * by this method fails
442 * @throws ClassNotFoundException if the class cannot be located
443 *
444 * @jls 12.2 Loading of Classes and Interfaces
445 * @jls 12.3 Linking of Classes and Interfaces
446 * @jls 12.4 Initialization of Classes and Interfaces
447 */
448 @CallerSensitive
449 public static Class<?> forName(String className)
450 throws ClassNotFoundException {
451 Class<?> caller = Reflection.getCallerClass();
452 return forName(className, caller);
453 }
454
455 // Caller-sensitive adapter method for reflective invocation
456 @CallerSensitiveAdapter
457 private static Class<?> forName(String className, Class<?> caller)
458 throws ClassNotFoundException {
459 ClassLoader loader = (caller == null) ? ClassLoader.getSystemClassLoader()
460 : ClassLoader.getClassLoader(caller);
461 if (loader instanceof BuiltinClassLoader bcl) {
462 if (bcl.usePositiveCache) {
463 Class<?> result = bcl.checkPositiveLookupCache(className);
464 if (result != null) {
465 return result;
466 }
467 }
468 if (bcl.useNegativeCache && bcl.checkNegativeLookupCache(className)) {
469 throw new ClassNotFoundException(className);
470 }
471 }
472 return forName0(className, true, loader, caller);
473 }
474
475 /**
476 * Returns the {@code Class} object associated with the class or
477 * interface with the given string name, using the given class loader.
478 * Given the {@linkplain ClassLoader##binary-name binary name} for a class or interface,
479 * this method attempts to locate and load the class or interface. The specified
480 * class loader is used to load the class or interface. If the parameter
481 * {@code loader} is {@code null}, the class is loaded through the bootstrap
482 * class loader. The class is initialized only if the
483 * {@code initialize} parameter is {@code true} and if it has
484 * not been initialized earlier.
485 *
486 * <p> This method cannot be used to obtain any of the {@code Class} objects
487 * representing primitive types or void, hidden classes or interfaces,
488 * or array classes whose element type is a hidden class or interface.
489 * If {@code name} denotes a primitive type or void, for example {@code I},
490 * an attempt will be made to locate a user-defined class in the unnamed package
491 * whose name is {@code I} instead.
568 }
569
570 // Caller-sensitive adapter method for reflective invocation
571 @CallerSensitiveAdapter
572 private static Class<?> forName(String name, boolean initialize, ClassLoader loader, Class<?> caller)
573 throws ClassNotFoundException
574 {
575 @SuppressWarnings("removal")
576 SecurityManager sm = System.getSecurityManager();
577 if (sm != null) {
578 // Reflective call to get caller class is only needed if a security manager
579 // is present. Avoid the overhead of making this call otherwise.
580 if (loader == null) {
581 ClassLoader ccl = ClassLoader.getClassLoader(caller);
582 if (ccl != null) {
583 sm.checkPermission(
584 SecurityConstants.GET_CLASSLOADER_PERMISSION);
585 }
586 }
587 }
588 if (loader instanceof BuiltinClassLoader bcl) {
589 if (bcl.usePositiveCache) {
590 Class<?> result = bcl.checkPositiveLookupCache(name);
591 if (result != null) {
592 return result;
593 }
594 }
595 if (bcl.useNegativeCache && bcl.checkNegativeLookupCache(name)) {
596 throw new ClassNotFoundException(name);
597 }
598 }
599 return forName0(name, initialize, loader, caller);
600 }
601
602 /** Called after security check for system loader access checks have been made. */
603 private static native Class<?> forName0(String name, boolean initialize,
604 ClassLoader loader,
605 Class<?> caller)
606 throws ClassNotFoundException;
607
608
609 /**
610 * Returns the {@code Class} with the given {@linkplain ClassLoader##binary-name
611 * binary name} in the given module.
612 *
613 * <p> This method attempts to locate and load the class or interface.
614 * It does not link the class, and does not run the class initializer.
615 * If the class is not found, this method returns {@code null}. </p>
616 *
617 * <p> If the class loader of the given module defines other modules and
618 * the given name is a class defined in a different module, this method
3402 }
3403
3404 /**
3405 * Atomic operations support.
3406 */
3407 private static class Atomic {
3408 // initialize Unsafe machinery here, since we need to call Class.class instance method
3409 // and have to avoid calling it in the static initializer of the Class class...
3410 private static final Unsafe unsafe = Unsafe.getUnsafe();
3411 // offset of Class.reflectionData instance field
3412 private static final long reflectionDataOffset
3413 = unsafe.objectFieldOffset(Class.class, "reflectionData");
3414 // offset of Class.annotationType instance field
3415 private static final long annotationTypeOffset
3416 = unsafe.objectFieldOffset(Class.class, "annotationType");
3417 // offset of Class.annotationData instance field
3418 private static final long annotationDataOffset
3419 = unsafe.objectFieldOffset(Class.class, "annotationData");
3420
3421 static <T> boolean casReflectionData(Class<?> clazz,
3422 ReflectionData<T> oldData,
3423 ReflectionData<T> newData) {
3424 return unsafe.compareAndSetReference(clazz, reflectionDataOffset, oldData, newData);
3425 }
3426
3427 static boolean casAnnotationType(Class<?> clazz,
3428 AnnotationType oldType,
3429 AnnotationType newType) {
3430 return unsafe.compareAndSetReference(clazz, annotationTypeOffset, oldType, newType);
3431 }
3432
3433 static boolean casAnnotationData(Class<?> clazz,
3434 AnnotationData oldData,
3435 AnnotationData newData) {
3436 return unsafe.compareAndSetReference(clazz, annotationDataOffset, oldData, newData);
3437 }
3438 }
3439
3440 /**
3441 * Reflection support.
3442 */
3443
3451 volatile Constructor<T>[] declaredConstructors;
3452 volatile Constructor<T>[] publicConstructors;
3453 // Intermediate results for getFields and getMethods
3454 volatile Field[] declaredPublicFields;
3455 volatile Method[] declaredPublicMethods;
3456 volatile Class<?>[] interfaces;
3457
3458 // Cached names
3459 String simpleName;
3460 String canonicalName;
3461 static final String NULL_SENTINEL = new String();
3462
3463 // Value of classRedefinedCount when we created this ReflectionData instance
3464 final int redefinedCount;
3465
3466 ReflectionData(int redefinedCount) {
3467 this.redefinedCount = redefinedCount;
3468 }
3469 }
3470
3471 private transient volatile ReflectionData<T> reflectionData;
3472
3473 // Incremented by the VM on each call to JVM TI RedefineClasses()
3474 // that redefines this class or a superclass.
3475 private transient volatile int classRedefinedCount;
3476
3477 // Lazily create and cache ReflectionData
3478 private ReflectionData<T> reflectionData() {
3479 ReflectionData<T> reflectionData = this.reflectionData;
3480 int classRedefinedCount = this.classRedefinedCount;
3481 if (reflectionData != null &&
3482 reflectionData.redefinedCount == classRedefinedCount) {
3483 return reflectionData;
3484 }
3485 // else no SoftReference or cleared SoftReference or stale ReflectionData
3486 // -> create and replace new instance
3487 return newReflectionData(reflectionData, classRedefinedCount);
3488 }
3489
3490 private ReflectionData<T> newReflectionData(ReflectionData<T> oldReflectionData,
3491 int classRedefinedCount) {
3492 while (true) {
3493 ReflectionData<T> rd = new ReflectionData<>(classRedefinedCount);
3494 // try to CAS it...
3495 if (Atomic.casReflectionData(this, oldReflectionData, rd)) {
3496 return rd;
3497 }
3498 // else retry
3499 oldReflectionData = this.reflectionData;
3500 classRedefinedCount = this.classRedefinedCount;
3501 if (oldReflectionData != null && oldReflectionData.redefinedCount == classRedefinedCount) {
3502 return rd;
3503 }
3504 }
3505 }
3506
3507 // Generic signature handling
3508 private native String getGenericSignature0();
3509
3510 // Generic info repository; lazily initialized
3511 private transient volatile ClassRepository genericInfo;
3512
3513 // accessor for factory
3514 private GenericsFactory getFactory() {
3515 // create scope and factory
3516 return CoreReflectionFactory.make(this, ClassScope.make(this));
3517 }
3518
3519 // accessor for generic info repository;
3520 // generic info is lazily initialized
3521 private ClassRepository getGenericInfo() {
4851 private int getClassFileVersion() {
4852 Class<?> c = isArray() ? elementType() : this;
4853 return c.getClassFileVersion0();
4854 }
4855
4856 private native int getClassFileVersion0();
4857
4858 /*
4859 * Return the access flags as they were in the class's bytecode, including
4860 * the original setting of ACC_SUPER.
4861 *
4862 * If the class is an array type then the access flags of the element type is
4863 * returned. If the class is a primitive then ACC_ABSTRACT | ACC_FINAL | ACC_PUBLIC.
4864 */
4865 private int getClassAccessFlagsRaw() {
4866 Class<?> c = isArray() ? elementType() : this;
4867 return c.getClassAccessFlagsRaw0();
4868 }
4869
4870 private native int getClassAccessFlagsRaw0();
4871
4872 // Support for "OLD" CDS workflow -- {
4873 private static final int RD_PUBLIC_METHODS = (1 << 0);
4874 private static final int RD_PUBLIC_FIELDS = (1 << 1);
4875 private static final int RD_DECLARED_CTORS = (1 << 2);
4876 private static final int RD_PUBLIC_CTORS = (1 << 3);
4877 private static final int RD_DECLARED_METHODS = (1 << 4);
4878 private static final int RD_DECLARED_PUBLIC_METHODS = (1 << 5);
4879 private static final int RD_DECLARED_FIELDS = (1 << 6);
4880 private static final int RD_DECLARED_PUBLIC_FIELDS = (1 << 7);
4881 private static final int RD_DECLARED_INTERFACES = (1 << 8);
4882 private static final int RD_DECLARED_SIMPLE_NAME = (1 << 9);
4883 private static final int RD_DECLARED_CANONICAL_NAME = (1 << 10);
4884 private static final int CLS_NAME = (1 << 10);
4885
4886
4887 private int encodeReflectionData() {
4888 int flags = CLS_NAME;
4889 if (reflectionData != null) {
4890 flags = (reflectionData.publicMethods != null ? RD_PUBLIC_METHODS : 0) |
4891 (reflectionData.publicFields != null ? RD_PUBLIC_FIELDS : 0) |
4892 (reflectionData.declaredConstructors != null ? RD_DECLARED_CTORS : 0) |
4893 (reflectionData.publicConstructors != null ? RD_PUBLIC_CTORS : 0) |
4894 (reflectionData.declaredMethods != null ? RD_DECLARED_METHODS : 0) |
4895 (reflectionData.declaredPublicMethods != null ? RD_DECLARED_PUBLIC_METHODS : 0) |
4896 (reflectionData.declaredFields != null ? RD_DECLARED_FIELDS : 0) |
4897 (reflectionData.declaredPublicFields != null ? RD_DECLARED_PUBLIC_FIELDS : 0) |
4898 (reflectionData.interfaces != null ? RD_DECLARED_INTERFACES : 0) |
4899 (reflectionData.simpleName != null ? RD_DECLARED_SIMPLE_NAME : 0) |
4900 (reflectionData.canonicalName != null ? RD_DECLARED_CANONICAL_NAME : 0);
4901 }
4902 return flags;
4903 }
4904 private void generateReflectionData(int flags) {
4905 if ((flags & CLS_NAME ) != 0) { getName(); } // String name
4906 if ((flags & RD_PUBLIC_METHODS ) != 0) { privateGetPublicMethods(); } // Method[] publicMethods;
4907 if ((flags & RD_PUBLIC_FIELDS ) != 0) { privateGetPublicFields(); } // Field[] publicFields;
4908 if ((flags & RD_DECLARED_CTORS ) != 0) { privateGetDeclaredConstructors(false); } // Constructor<T>[] declaredConstructors;
4909 if ((flags & RD_PUBLIC_CTORS ) != 0) { privateGetDeclaredConstructors(true); } // Constructor<T>[] publicConstructors;
4910 if ((flags & RD_DECLARED_METHODS ) != 0) { privateGetDeclaredMethods(false); } // Method[] declaredMethods;
4911 if ((flags & RD_DECLARED_PUBLIC_METHODS) != 0) { privateGetDeclaredMethods(true); } // Method[] declaredPublicMethods;
4912 if ((flags & RD_DECLARED_FIELDS ) != 0) { privateGetDeclaredFields(false); } // Field[] declaredFields;
4913 if ((flags & RD_DECLARED_PUBLIC_FIELDS ) != 0) { privateGetDeclaredFields(true); } // Field[] declaredPublicFields;
4914 if ((flags & RD_DECLARED_INTERFACES ) != 0) { getInterfaces(false); } // Class<?>[] interfaces;
4915 if ((flags & RD_DECLARED_SIMPLE_NAME ) != 0) { getSimpleName(); } // String simpleName;
4916 if ((flags & RD_DECLARED_CANONICAL_NAME) != 0) { getCanonicalName(); } // String canonicalName;
4917 }
4918
4919 // -- }
4920 }
|