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