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