Mercurial > hg > graal-compiler
comparison src/share/vm/prims/unsafe.cpp @ 431:a45484ea312d
6653858: dynamic languages need to be able to load anonymous classes
Summary: low-level privileged sun.misc.Unsafe.defineAnonymousClass
Reviewed-by: kvn
author | jrose |
---|---|
date | Wed, 12 Nov 2008 22:33:26 -0800 |
parents | 1ee8caae33af |
children | df6caf649ff7 |
comparison
equal
deleted
inserted
replaced
430:4d20a3aaf1ab | 431:a45484ea312d |
---|---|
835 | 835 |
836 return Unsafe_DefineClass(env, name, data, offset, length, loader, pd); | 836 return Unsafe_DefineClass(env, name, data, offset, length, loader, pd); |
837 } | 837 } |
838 UNSAFE_END | 838 UNSAFE_END |
839 | 839 |
840 #define DAC_Args CLS"[B["OBJ | |
841 // define a class but do not make it known to the class loader or system dictionary | |
842 // - host_class: supplies context for linkage, access control, protection domain, and class loader | |
843 // - data: bytes of a class file, a raw memory address (length gives the number of bytes) | |
844 // - cp_patches: where non-null entries exist, they replace corresponding CP entries in data | |
845 | |
846 // When you load an anonymous class U, it works as if you changed its name just before loading, | |
847 // to a name that you will never use again. Since the name is lost, no other class can directly | |
848 // link to any member of U. Just after U is loaded, the only way to use it is reflectively, | |
849 // through java.lang.Class methods like Class.newInstance. | |
850 | |
851 // Access checks for linkage sites within U continue to follow the same rules as for named classes. | |
852 // The package of an anonymous class is given by the package qualifier on the name under which it was loaded. | |
853 // An anonymous class also has special privileges to access any member of its host class. | |
854 // This is the main reason why this loading operation is unsafe. The purpose of this is to | |
855 // allow language implementations to simulate "open classes"; a host class in effect gets | |
856 // new code when an anonymous class is loaded alongside it. A less convenient but more | |
857 // standard way to do this is with reflection, which can also be set to ignore access | |
858 // restrictions. | |
859 | |
860 // Access into an anonymous class is possible only through reflection. Therefore, there | |
861 // are no special access rules for calling into an anonymous class. The relaxed access | |
862 // rule for the host class is applied in the opposite direction: A host class reflectively | |
863 // access one of its anonymous classes. | |
864 | |
865 // If you load the same bytecodes twice, you get two different classes. You can reload | |
866 // the same bytecodes with or without varying CP patches. | |
867 | |
868 // By using the CP patching array, you can have a new anonymous class U2 refer to an older one U1. | |
869 // The bytecodes for U2 should refer to U1 by a symbolic name (doesn't matter what the name is). | |
870 // The CONSTANT_Class entry for that name can be patched to refer directly to U1. | |
871 | |
872 // This allows, for example, U2 to use U1 as a superclass or super-interface, or as | |
873 // an outer class (so that U2 is an anonymous inner class of anonymous U1). | |
874 // It is not possible for a named class, or an older anonymous class, to refer by | |
875 // name (via its CP) to a newer anonymous class. | |
876 | |
877 // CP patching may also be used to modify (i.e., hack) the names of methods, classes, | |
878 // or type descriptors used in the loaded anonymous class. | |
879 | |
880 // Finally, CP patching may be used to introduce "live" objects into the constant pool, | |
881 // instead of "dead" strings. A compiled statement like println((Object)"hello") can | |
882 // be changed to println(greeting), where greeting is an arbitrary object created before | |
883 // the anonymous class is loaded. This is useful in dynamic languages, in which | |
884 // various kinds of metaobjects must be introduced as constants into bytecode. | |
885 // Note the cast (Object), which tells the verifier to expect an arbitrary object, | |
886 // not just a literal string. For such ldc instructions, the verifier uses the | |
887 // type Object instead of String, if the loaded constant is not in fact a String. | |
888 | |
889 static oop | |
890 Unsafe_DefineAnonymousClass_impl(JNIEnv *env, | |
891 jclass host_class, jbyteArray data, jobjectArray cp_patches_jh, | |
892 HeapWord* *temp_alloc, | |
893 TRAPS) { | |
894 | |
895 if (UsePerfData) { | |
896 ClassLoader::unsafe_defineClassCallCounter()->inc(); | |
897 } | |
898 | |
899 if (data == NULL) { | |
900 THROW_0(vmSymbols::java_lang_NullPointerException()); | |
901 } | |
902 | |
903 jint length = typeArrayOop(JNIHandles::resolve_non_null(data))->length(); | |
904 jint word_length = (length + sizeof(HeapWord)-1) / sizeof(HeapWord); | |
905 HeapWord* body = NEW_C_HEAP_ARRAY(HeapWord, word_length); | |
906 if (body == NULL) { | |
907 THROW_0(vmSymbols::java_lang_OutOfMemoryError()); | |
908 } | |
909 | |
910 // caller responsible to free it: | |
911 (*temp_alloc) = body; | |
912 | |
913 { | |
914 jbyte* array_base = typeArrayOop(JNIHandles::resolve_non_null(data))->byte_at_addr(0); | |
915 Copy::conjoint_words((HeapWord*) array_base, body, word_length); | |
916 } | |
917 | |
918 u1* class_bytes = (u1*) body; | |
919 int class_bytes_length = (int) length; | |
920 if (class_bytes_length < 0) class_bytes_length = 0; | |
921 if (class_bytes == NULL | |
922 || host_class == NULL | |
923 || length != class_bytes_length) | |
924 THROW_0(vmSymbols::java_lang_IllegalArgumentException()); | |
925 | |
926 objArrayHandle cp_patches_h; | |
927 if (cp_patches_jh != NULL) { | |
928 oop p = JNIHandles::resolve_non_null(cp_patches_jh); | |
929 if (!p->is_objArray()) | |
930 THROW_0(vmSymbols::java_lang_IllegalArgumentException()); | |
931 cp_patches_h = objArrayHandle(THREAD, (objArrayOop)p); | |
932 } | |
933 | |
934 KlassHandle host_klass(THREAD, java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(host_class))); | |
935 const char* host_source = host_klass->external_name(); | |
936 Handle host_loader(THREAD, host_klass->class_loader()); | |
937 Handle host_domain(THREAD, host_klass->protection_domain()); | |
938 | |
939 GrowableArray<Handle>* cp_patches = NULL; | |
940 if (cp_patches_h.not_null()) { | |
941 int alen = cp_patches_h->length(); | |
942 for (int i = alen-1; i >= 0; i--) { | |
943 oop p = cp_patches_h->obj_at(i); | |
944 if (p != NULL) { | |
945 Handle patch(THREAD, p); | |
946 if (cp_patches == NULL) | |
947 cp_patches = new GrowableArray<Handle>(i+1, i+1, Handle()); | |
948 cp_patches->at_put(i, patch); | |
949 } | |
950 } | |
951 } | |
952 | |
953 ClassFileStream st(class_bytes, class_bytes_length, (char*) host_source); | |
954 | |
955 instanceKlassHandle anon_klass; | |
956 { | |
957 symbolHandle no_class_name; | |
958 klassOop anonk = SystemDictionary::parse_stream(no_class_name, | |
959 host_loader, host_domain, | |
960 &st, host_klass, cp_patches, | |
961 CHECK_NULL); | |
962 if (anonk == NULL) return NULL; | |
963 anon_klass = instanceKlassHandle(THREAD, anonk); | |
964 } | |
965 | |
966 // let caller initialize it as needed... | |
967 | |
968 return anon_klass->java_mirror(); | |
969 } | |
970 | |
971 UNSAFE_ENTRY(jclass, Unsafe_DefineAnonymousClass(JNIEnv *env, jobject unsafe, jclass host_class, jbyteArray data, jobjectArray cp_patches_jh)) | |
972 { | |
973 UnsafeWrapper("Unsafe_DefineAnonymousClass"); | |
974 ResourceMark rm(THREAD); | |
975 | |
976 HeapWord* temp_alloc = NULL; | |
977 | |
978 jobject res_jh = NULL; | |
979 | |
980 { oop res_oop = Unsafe_DefineAnonymousClass_impl(env, | |
981 host_class, data, cp_patches_jh, | |
982 &temp_alloc, THREAD); | |
983 if (res_oop != NULL) | |
984 res_jh = JNIHandles::make_local(env, res_oop); | |
985 } | |
986 | |
987 // try/finally clause: | |
988 if (temp_alloc != NULL) { | |
989 FREE_C_HEAP_ARRAY(HeapWord, temp_alloc); | |
990 } | |
991 | |
992 return (jclass) res_jh; | |
993 } | |
994 UNSAFE_END | |
995 | |
996 | |
840 | 997 |
841 UNSAFE_ENTRY(void, Unsafe_MonitorEnter(JNIEnv *env, jobject unsafe, jobject jobj)) | 998 UNSAFE_ENTRY(void, Unsafe_MonitorEnter(JNIEnv *env, jobject unsafe, jobject jobj)) |
842 UnsafeWrapper("Unsafe_MonitorEnter"); | 999 UnsafeWrapper("Unsafe_MonitorEnter"); |
843 { | 1000 { |
844 if (jobj == NULL) { | 1001 if (jobj == NULL) { |
1290 JNINativeMethod memcopy_methods_15[] = { | 1447 JNINativeMethod memcopy_methods_15[] = { |
1291 {CC"setMemory", CC"("ADR"JB)V", FN_PTR(Unsafe_SetMemory)}, | 1448 {CC"setMemory", CC"("ADR"JB)V", FN_PTR(Unsafe_SetMemory)}, |
1292 {CC"copyMemory", CC"("ADR ADR"J)V", FN_PTR(Unsafe_CopyMemory)} | 1449 {CC"copyMemory", CC"("ADR ADR"J)V", FN_PTR(Unsafe_CopyMemory)} |
1293 }; | 1450 }; |
1294 | 1451 |
1452 JNINativeMethod anonk_methods[] = { | |
1453 {CC"defineAnonymousClass", CC"("DAC_Args")"CLS, FN_PTR(Unsafe_DefineAnonymousClass)}, | |
1454 }; | |
1295 | 1455 |
1296 #undef CC | 1456 #undef CC |
1297 #undef FN_PTR | 1457 #undef FN_PTR |
1298 | 1458 |
1299 #undef ADR | 1459 #undef ADR |
1352 } | 1512 } |
1353 env->ExceptionClear(); | 1513 env->ExceptionClear(); |
1354 } | 1514 } |
1355 } | 1515 } |
1356 } | 1516 } |
1517 if (AnonymousClasses) { | |
1518 env->RegisterNatives(unsafecls, anonk_methods, sizeof(anonk_methods)/sizeof(JNINativeMethod)); | |
1519 if (env->ExceptionOccurred()) { | |
1520 if (PrintMiscellaneous && (Verbose || WizardMode)) { | |
1521 tty->print_cr("Warning: SDK 1.7 Unsafe.defineClass (anonymous version) not found."); | |
1522 } | |
1523 env->ExceptionClear(); | |
1524 } | |
1525 } | |
1357 int status = env->RegisterNatives(unsafecls, methods, sizeof(methods)/sizeof(JNINativeMethod)); | 1526 int status = env->RegisterNatives(unsafecls, methods, sizeof(methods)/sizeof(JNINativeMethod)); |
1358 if (env->ExceptionOccurred()) { | 1527 if (env->ExceptionOccurred()) { |
1359 if (PrintMiscellaneous && (Verbose || WizardMode)) { | 1528 if (PrintMiscellaneous && (Verbose || WizardMode)) { |
1360 tty->print_cr("Warning: SDK 1.6 version of Unsafe not found."); | 1529 tty->print_cr("Warning: SDK 1.6 version of Unsafe not found."); |
1361 } | 1530 } |