1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
3 * ***** BEGIN LICENSE BLOCK *****
4 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
6 * The contents of this file are subject to the Mozilla Public License Version
7 * 1.1 (the "License"); you may not use this file except in compliance with
8 * the License. You may obtain a copy of the License at
9 * http://www.mozilla.org/MPL/
11 * Software distributed under the License is distributed on an "AS IS" basis,
12 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13 * for the specific language governing rights and limitations under the
16 * The Original Code is Mozilla Communicator client code, released
19 * The Initial Developer of the Original Code is
20 * Netscape Communications Corporation.
21 * Portions created by the Initial Developer are Copyright (C) 1998
22 * the Initial Developer. All Rights Reserved.
26 * Alternatively, the contents of this file may be used under the terms of
27 * either of the GNU General Public License Version 2 or later (the "GPL"),
28 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29 * in which case the provisions of the GPL or the LGPL are applicable instead
30 * of those above. If you wish to allow use of your version of this file only
31 * under the terms of either the GPL or the LGPL, and not to allow others to
32 * use your version of this file under the terms of the MPL, indicate your
33 * decision by deleting the provisions above and replace them with the notice
34 * and other provisions required by the GPL or the LGPL. If you do not delete
35 * the provisions above, a recipient may use your version of this file under
36 * the terms of any one of the MPL, the GPL or the LGPL.
38 * ***** END LICENSE BLOCK ***** */
41 * This file is part of the Java-vendor-neutral implementation of LiveConnect
43 * It contains the code that constructs and manipulates JavaClassDescriptor
44 * structs, which are the native wrappers for Java classes.
45 * JavaClassDescriptors are used to describe the signatures of methods and
46 * fields. There is a JavaClassDescriptor associated with the reflection of
53 #include "jsj_private.h" /* LiveConnect internals */
54 #include "jsj_hash.h" /* Hash tables */
60 /* A one-to-one mapping between all referenced java.lang.Class objects and
61 their corresponding JavaClassDescriptor objects */
62 static JSJHashTable
*java_class_reflections
;
65 static PRMonitor
*java_class_reflections_monitor
;
69 * Given a JVM handle to a java.lang.Class object, malloc a C-string
70 * containing the UTF8 encoding of the fully qualified name of the class.
71 * It's the caller's responsibility to free the returned string.
73 * If an error occurs, NULL is returned and the error reporter called.
76 jsj_GetJavaClassName(JSContext
*cx
, JNIEnv
*jEnv
, jclass java_class
)
78 jstring java_class_name_jstr
;
79 const char *java_class_name
;
81 /* Get java.lang.String object containing class name */
82 java_class_name_jstr
=
83 (*jEnv
)->CallObjectMethod(jEnv
, java_class
, jlClass_getName
);
85 if (!java_class_name_jstr
)
88 /* Fix bugzilla #183092
89 * It is necessary to check Exception from JPI
90 * even though java_class_name_jstr != null */
92 if ((*jEnv
)->ExceptionOccurred(jEnv
))
96 /* Convert to UTF8 encoding and copy */
97 java_class_name
= jsj_DupJavaStringUTF(cx
, jEnv
, java_class_name_jstr
);
99 (*jEnv
)->DeleteLocalRef(jEnv
, java_class_name_jstr
);
100 return java_class_name
;
103 jsj_UnexpectedJavaError(cx
, jEnv
, "Can't get Java class name using"
104 "java.lang.Class.getName()");
109 * Convert in-place a string of the form "java.lang.String" into "java/lang/String".
110 * Though the former style is conventionally used by Java programmers, the latter is
111 * what the JNI functions require.
114 jsj_MakeJNIClassname(char * class_name
)
117 for (c
= class_name
; *c
; c
++)
123 * Classify an instance of java.lang.Class as either one of the primitive
124 * types, e.g. int, char, etc., as an array type or as a non-array object type
125 * (subclass of java.lang.Object) by returning the appropriate enum member.
128 static JavaSignatureChar
129 get_signature_type(JSContext
*cx
, JavaClassDescriptor
*class_descriptor
)
131 JavaSignatureChar type
;
132 const char *java_class_name
;
134 /* Get UTF8 encoding of class name */
135 java_class_name
= class_descriptor
->name
;
136 JS_ASSERT(java_class_name
);
137 if (!java_class_name
)
138 return JAVA_SIGNATURE_UNKNOWN
;
140 if (!strcmp(java_class_name
, "byte"))
141 type
= JAVA_SIGNATURE_BYTE
;
142 else if (!strcmp(java_class_name
, "char"))
143 type
= JAVA_SIGNATURE_CHAR
;
144 else if (!strcmp(java_class_name
, "float"))
145 type
= JAVA_SIGNATURE_FLOAT
;
146 else if (!strcmp(java_class_name
, "double"))
147 type
= JAVA_SIGNATURE_DOUBLE
;
148 else if (!strcmp(java_class_name
, "int"))
149 type
= JAVA_SIGNATURE_INT
;
150 else if (!strcmp(java_class_name
, "long"))
151 type
= JAVA_SIGNATURE_LONG
;
152 else if (!strcmp(java_class_name
, "short"))
153 type
= JAVA_SIGNATURE_SHORT
;
154 else if (!strcmp(java_class_name
, "boolean"))
155 type
= JAVA_SIGNATURE_BOOLEAN
;
156 else if (!strcmp(java_class_name
, "void"))
157 type
= JAVA_SIGNATURE_VOID
;
158 else if (!strcmp(java_class_name
, "java.lang.Boolean"))
159 type
= JAVA_SIGNATURE_JAVA_LANG_BOOLEAN
;
160 else if (!strcmp(java_class_name
, "java.lang.Double"))
161 type
= JAVA_SIGNATURE_JAVA_LANG_DOUBLE
;
162 else if (!strcmp(java_class_name
, "java.lang.String"))
163 type
= JAVA_SIGNATURE_JAVA_LANG_STRING
;
164 else if (!strcmp(java_class_name
, "java.lang.Object"))
165 type
= JAVA_SIGNATURE_JAVA_LANG_OBJECT
;
166 else if (!strcmp(java_class_name
, "java.lang.Class"))
167 type
= JAVA_SIGNATURE_JAVA_LANG_CLASS
;
168 else if (!strcmp(java_class_name
, "netscape.javascript.JSObject"))
169 type
= JAVA_SIGNATURE_NETSCAPE_JAVASCRIPT_JSOBJECT
;
171 type
= JAVA_SIGNATURE_OBJECT
;
176 is_java_array_class(JNIEnv
*jEnv
, jclass java_class
)
178 return (*jEnv
)->CallBooleanMethod(jEnv
, java_class
, jlClass_isArray
);
182 * Return the class of a Java array's component type. This is not the same
183 * as the array's element type. For example, the component type of an array
184 * of type SomeType[][][] is SomeType[][], but its element type is SomeType.
186 * If an error occurs, NULL is returned and an error reported.
189 get_java_array_component_class(JSContext
*cx
, JNIEnv
*jEnv
, jclass java_class
)
192 result
= (*jEnv
)->CallObjectMethod(jEnv
, java_class
, jlClass_getComponentType
);
194 jsj_UnexpectedJavaError(cx
, jEnv
,
195 "Can't get Java array component class using "
196 "java.lang.Class.getComponentType()");
203 * Given a Java class, fill in the signature structure that describes the class.
204 * If an error occurs, JS_FALSE is returned and the error reporter called.
207 compute_java_class_signature(JSContext
*cx
, JNIEnv
*jEnv
, JavaSignature
*signature
)
209 jclass java_class
= signature
->java_class
;
211 if (is_java_array_class(jEnv
, java_class
)) {
212 jclass component_class
;
214 signature
->type
= JAVA_SIGNATURE_ARRAY
;
216 component_class
= get_java_array_component_class(cx
, jEnv
, java_class
);
217 if (!component_class
)
220 signature
->array_component_signature
=
221 jsj_GetJavaClassDescriptor(cx
, jEnv
, component_class
);
222 if (!signature
->array_component_signature
) {
223 (*jEnv
)->DeleteLocalRef(jEnv
, component_class
);
227 signature
->type
= get_signature_type(cx
, signature
);
233 * Convert from JavaSignatureChar enumeration to single-character
234 * signature used by the JDK and JNI methods.
237 get_jdk_signature_char(JavaSignatureChar type
)
239 return "XVZCBSIJFD[LLLLLL"[(int)type
];
243 * Convert a JavaSignature object into a string format as used by
244 * the JNI functions, e.g. java.lang.Object ==> "Ljava/lang/Object;"
245 * The caller is responsible for freeing the resulting string.
247 * If an error is encountered, NULL is returned and an error reported.
250 jsj_ConvertJavaSignatureToString(JSContext
*cx
, JavaSignature
*signature
)
254 if (IS_OBJECT_TYPE(signature
->type
)) {
255 /* A non-array object class */
256 sig
= JS_smprintf("L%s;", signature
->name
);
258 jsj_MakeJNIClassname(sig
);
260 } else if (signature
->type
== JAVA_SIGNATURE_ARRAY
) {
262 const char *component_signature_string
;
264 component_signature_string
=
265 jsj_ConvertJavaSignatureToString(cx
, signature
->array_component_signature
);
266 if (!component_signature_string
)
268 sig
= JS_smprintf("[%s", component_signature_string
);
269 JS_smprintf_free((char*)component_signature_string
);
272 /* A primitive class */
273 sig
= JS_smprintf("%c", get_jdk_signature_char(signature
->type
));
277 JS_ReportOutOfMemory(cx
);
284 * Convert a JavaSignature object into a human-readable string format as seen
285 * in Java source files, e.g. "byte", or "int[][]" or "java.lang.String".
286 * The caller is responsible for freeing the resulting string.
288 * If an error is encountered, NULL is returned and an error reported.
291 jsj_ConvertJavaSignatureToHRString(JSContext
*cx
,
292 JavaSignature
*signature
)
297 if (signature
->type
== JAVA_SIGNATURE_ARRAY
) {
299 const char *component_signature_string
;
300 acs
= signature
->array_component_signature
;
301 component_signature_string
=
302 jsj_ConvertJavaSignatureToHRString(cx
, acs
);
303 if (!component_signature_string
)
305 sig
= JS_smprintf("%s[]", component_signature_string
);
306 JS_smprintf_free((char*)component_signature_string
);
309 /* A primitive class or a non-array object class */
310 sig
= JS_smprintf("%s", signature
->name
);
314 JS_ReportOutOfMemory(cx
);
321 destroy_java_member_descriptor(JSContext
*cx
, JNIEnv
*jEnv
, JavaMemberDescriptor
*member_descriptor
)
323 JavaMethodSpec
*method
, *next_method
;
324 if (member_descriptor
->field
)
325 jsj_DestroyFieldSpec(cx
, jEnv
, member_descriptor
->field
);
327 method
= member_descriptor
->methods
;
329 next_method
= method
->next
;
330 jsj_DestroyMethodSpec(cx
, jEnv
, method
);
331 method
= next_method
;
334 JS_RemoveRoot(cx
, &member_descriptor
->invoke_func_obj
);
335 JS_FREE_IF(cx
, (char *)member_descriptor
->name
);
336 JS_free(cx
, member_descriptor
);
340 destroy_class_member_descriptors(JSContext
*cx
, JNIEnv
*jEnv
, JavaMemberDescriptor
*member_descriptor
)
342 JavaMemberDescriptor
*next_member
;
344 while (member_descriptor
) {
345 next_member
= member_descriptor
->next
;
346 destroy_java_member_descriptor(cx
, jEnv
, member_descriptor
);
347 member_descriptor
= next_member
;
352 destroy_class_descriptor(JSContext
*cx
, JNIEnv
*jEnv
, JavaClassDescriptor
*class_descriptor
)
354 JS_FREE_IF(cx
, (char *)class_descriptor
->name
);
355 if (class_descriptor
->java_class
)
356 (*jEnv
)->DeleteGlobalRef(jEnv
, class_descriptor
->java_class
);
358 if (class_descriptor
->array_component_signature
)
359 jsj_ReleaseJavaClassDescriptor(cx
, jEnv
, class_descriptor
->array_component_signature
);
361 destroy_class_member_descriptors(cx
, jEnv
, class_descriptor
->instance_members
);
362 destroy_class_member_descriptors(cx
, jEnv
, class_descriptor
->static_members
);
363 destroy_class_member_descriptors(cx
, jEnv
, class_descriptor
->constructors
);
364 JS_free(cx
, class_descriptor
);
367 static JavaClassDescriptor
*
368 new_class_descriptor(JSContext
*cx
, JNIEnv
*jEnv
, jclass java_class
)
370 JavaClassDescriptor
*class_descriptor
;
372 class_descriptor
= (JavaClassDescriptor
*)JS_malloc(cx
, sizeof(JavaClassDescriptor
));
373 if (!class_descriptor
)
375 memset(class_descriptor
, 0, sizeof(JavaClassDescriptor
));
377 class_descriptor
->name
= jsj_GetJavaClassName(cx
, jEnv
, java_class
);
378 if (!class_descriptor
->name
)
381 java_class
= (*jEnv
)->NewGlobalRef(jEnv
, java_class
);
383 jsj_UnexpectedJavaError(cx
, jEnv
, "Unable to reference Java class");
386 class_descriptor
->java_class
= java_class
;
388 if (!compute_java_class_signature(cx
, jEnv
, class_descriptor
))
391 class_descriptor
->modifiers
=
392 (*jEnv
)->CallIntMethod(jEnv
, java_class
, jlClass_getModifiers
);
393 class_descriptor
->ref_count
= 1;
395 if (!JSJ_HashTableAdd(java_class_reflections
, java_class
, class_descriptor
,
399 return class_descriptor
;
402 destroy_class_descriptor(cx
, jEnv
, class_descriptor
);
406 /* Trivial helper for jsj_DiscardJavaClassReflections(), below */
408 enumerate_remove_java_class(JSJHashEntry
*he
, JSIntn i
, void *arg
)
410 JSJavaThreadState
*jsj_env
= (JSJavaThreadState
*)arg
;
411 JavaClassDescriptor
*class_descriptor
;
413 class_descriptor
= (JavaClassDescriptor
*)he
->value
;
415 destroy_class_descriptor(jsj_env
->cx
, jsj_env
->jEnv
, class_descriptor
);
417 return HT_ENUMERATE_REMOVE
;
420 /* This shutdown routine discards all JNI references to Java objects
421 that have been reflected into JS, even if there are still references
424 jsj_DiscardJavaClassReflections(JNIEnv
*jEnv
)
426 JSJavaThreadState
*jsj_env
;
430 /* Get the per-thread state corresponding to the current Java thread */
431 jsj_env
= jsj_MapJavaThreadToJSJavaThreadState(jEnv
, &err_msg
);
436 /* Get the JSContext that we're supposed to use for this Java thread */
439 /* We called spontaneously into JS from Java, rather than from JS into
440 Java and back into JS. Invoke a callback to obtain/create a
441 JSContext for us to use. */
442 if (JSJ_callbacks
->map_jsj_thread_to_js_context
) {
444 cx
= JSJ_callbacks
->map_jsj_thread_to_js_context(jsj_env
,
445 NULL
, /* FIXME: What should this argument be ? */
448 cx
= JSJ_callbacks
->map_jsj_thread_to_js_context(jsj_env
,
454 err_msg
= JS_smprintf("Unable to find/create JavaScript execution "
455 "context for JNI thread 0x%08x", jEnv
);
460 if (java_class_reflections
) {
461 JSJ_HashTableEnumerateEntries(java_class_reflections
,
462 enumerate_remove_java_class
,
464 JSJ_HashTableDestroy(java_class_reflections
);
465 java_class_reflections
= NULL
;
473 jsj_LogError(err_msg
);
474 JS_smprintf_free(err_msg
);
478 extern JavaClassDescriptor
*
479 jsj_GetJavaClassDescriptor(JSContext
*cx
, JNIEnv
*jEnv
, jclass java_class
)
481 JavaClassDescriptor
*class_descriptor
= NULL
;
483 #ifdef JSJ_THREADSAFE
484 PR_EnterMonitor(java_class_reflections_monitor
);
487 if (java_class_reflections
) {
488 class_descriptor
= JSJ_HashTableLookup(java_class_reflections
,
489 (const void *)java_class
,
492 if (!class_descriptor
) {
493 class_descriptor
= new_class_descriptor(cx
, jEnv
, java_class
);
495 #ifdef JSJ_THREADSAFE
496 PR_ExitMonitor(java_class_reflections_monitor
);
498 return class_descriptor
;
501 #ifdef JSJ_THREADSAFE
502 PR_ExitMonitor(java_class_reflections_monitor
);
505 JS_ASSERT(class_descriptor
->ref_count
> 0);
506 class_descriptor
->ref_count
++;
507 return class_descriptor
;
511 jsj_ReleaseJavaClassDescriptor(JSContext
*cx
, JNIEnv
*jEnv
, JavaClassDescriptor
*class_descriptor
)
514 /* The ref-counting code doesn't work very well because cycles in the data
515 structures routinely lead to uncollectible JavaClassDescriptor's. Skip it. */
516 JS_ASSERT(class_descriptor
->ref_count
>= 1);
517 if (!--class_descriptor
->ref_count
) {
518 JSJ_HashTableRemove(java_class_reflections
,
519 class_descriptor
->java_class
, (void*)jEnv
);
520 destroy_class_descriptor(cx
, jEnv
, class_descriptor
);
525 #ifdef JSJ_THREADSAFE
526 static PRMonitor
*java_reflect_monitor
= NULL
;
530 reflect_java_methods_and_fields(JSContext
*cx
,
532 JavaClassDescriptor
*class_descriptor
,
533 JSBool reflect_statics_only
)
535 JavaMemberDescriptor
*member_descriptor
;
538 success
= JS_TRUE
; /* optimism */
540 #ifdef JSJ_THREADSAFE
541 PR_EnterMonitor(java_reflect_monitor
);
544 /* See if we raced with another thread to reflect members of this class.
545 If the status is REFLECT_COMPLETE, another thread beat us to it. If
546 the status is REFLECT_IN_PROGRESS, we've recursively called this
547 function within a single thread. Either way, we're done. */
548 if (reflect_statics_only
) {
549 if (class_descriptor
->static_members_reflected
!= REFLECT_NO
)
551 class_descriptor
->static_members_reflected
= REFLECT_IN_PROGRESS
;
553 if (class_descriptor
->instance_members_reflected
!= REFLECT_NO
)
555 class_descriptor
->instance_members_reflected
= REFLECT_IN_PROGRESS
;
558 if (!jsj_ReflectJavaMethods(cx
, jEnv
, class_descriptor
, reflect_statics_only
))
560 if (!jsj_ReflectJavaFields(cx
, jEnv
, class_descriptor
, reflect_statics_only
))
563 if (reflect_statics_only
) {
564 member_descriptor
= class_descriptor
->static_members
;
565 while (member_descriptor
) {
566 class_descriptor
->num_static_members
++;
567 member_descriptor
= member_descriptor
->next
;
569 class_descriptor
->static_members_reflected
= REFLECT_COMPLETE
;
571 member_descriptor
= class_descriptor
->instance_members
;
572 while (member_descriptor
) {
573 class_descriptor
->num_instance_members
++;
574 member_descriptor
= member_descriptor
->next
;
576 class_descriptor
->instance_members_reflected
= REFLECT_COMPLETE
;
580 #ifdef JSJ_THREADSAFE
581 PR_ExitMonitor(java_reflect_monitor
);
590 JavaMemberDescriptor
*
591 jsj_GetClassStaticMembers(JSContext
*cx
,
593 JavaClassDescriptor
*class_descriptor
)
595 if (class_descriptor
->static_members_reflected
!= REFLECT_COMPLETE
)
596 reflect_java_methods_and_fields(cx
, jEnv
, class_descriptor
, JS_TRUE
);
597 return class_descriptor
->static_members
;
600 JavaMemberDescriptor
*
601 jsj_GetClassInstanceMembers(JSContext
*cx
,
603 JavaClassDescriptor
*class_descriptor
)
605 if (class_descriptor
->instance_members_reflected
!= REFLECT_COMPLETE
)
606 reflect_java_methods_and_fields(cx
, jEnv
, class_descriptor
, JS_FALSE
);
607 return class_descriptor
->instance_members
;
610 JavaMemberDescriptor
*
611 jsj_LookupJavaStaticMemberDescriptorById(JSContext
*cx
,
613 JavaClassDescriptor
*class_descriptor
,
616 JavaMemberDescriptor
*member_descriptor
;
618 member_descriptor
= jsj_GetClassStaticMembers(cx
, jEnv
, class_descriptor
);
619 while (member_descriptor
) {
620 if (id
== member_descriptor
->id
)
621 return member_descriptor
;
622 member_descriptor
= member_descriptor
->next
;
627 JavaMemberDescriptor
*
628 jsj_GetJavaStaticMemberDescriptor(JSContext
*cx
,
630 JavaClassDescriptor
*class_descriptor
,
631 jstring member_name_jstr
)
633 JavaMemberDescriptor
*member_descriptor
;
636 if (!JavaStringToId(cx
, jEnv
, member_name_jstr
, &id
))
639 member_descriptor
= jsj_LookupJavaStaticMemberDescriptorById(cx
, jEnv
, class_descriptor
, id
);
640 if (member_descriptor
)
641 return member_descriptor
;
643 member_descriptor
= JS_malloc(cx
, sizeof(JavaMemberDescriptor
));
644 if (!member_descriptor
)
646 memset(member_descriptor
, 0, sizeof(JavaMemberDescriptor
));
648 member_descriptor
->name
= jsj_DupJavaStringUTF(cx
, jEnv
, member_name_jstr
);
649 if (!member_descriptor
->name
) {
650 JS_free(cx
, member_descriptor
);
653 member_descriptor
->id
= id
;
655 member_descriptor
->next
= class_descriptor
->static_members
;
656 class_descriptor
->static_members
= member_descriptor
;
658 return member_descriptor
;
661 JavaMemberDescriptor
*
662 jsj_GetJavaClassConstructors(JSContext
*cx
,
663 JavaClassDescriptor
*class_descriptor
)
665 JavaMemberDescriptor
*member_descriptor
;
667 if (class_descriptor
->constructors
)
668 return class_descriptor
->constructors
;
670 member_descriptor
= JS_malloc(cx
, sizeof(JavaMemberDescriptor
));
671 if (!member_descriptor
)
673 memset(member_descriptor
, 0, sizeof(JavaMemberDescriptor
));
675 member_descriptor
->name
= JS_strdup(cx
, "<init>");
676 if (!member_descriptor
->name
) {
677 JS_free(cx
, member_descriptor
);
681 class_descriptor
->constructors
= member_descriptor
;
683 return member_descriptor
;
686 JavaMemberDescriptor
*
687 jsj_LookupJavaClassConstructors(JSContext
*cx
, JNIEnv
*jEnv
,
688 JavaClassDescriptor
*class_descriptor
)
690 if (class_descriptor
->static_members_reflected
!= REFLECT_COMPLETE
)
691 reflect_java_methods_and_fields(cx
, jEnv
, class_descriptor
, JS_TRUE
);
692 return class_descriptor
->constructors
;
695 JavaMemberDescriptor
*
696 jsj_LookupJavaMemberDescriptorById(JSContext
*cx
, JNIEnv
*jEnv
,
697 JavaClassDescriptor
*class_descriptor
,
700 JavaMemberDescriptor
*member_descriptor
;
702 member_descriptor
= jsj_GetClassInstanceMembers(cx
, jEnv
, class_descriptor
);
703 while (member_descriptor
) {
704 if (id
== member_descriptor
->id
)
705 return member_descriptor
;
706 member_descriptor
= member_descriptor
->next
;
711 JavaMemberDescriptor
*
712 jsj_GetJavaMemberDescriptor(JSContext
*cx
,
714 JavaClassDescriptor
*class_descriptor
,
715 jstring member_name_jstr
)
717 JavaMemberDescriptor
*member_descriptor
;
720 if (!JavaStringToId(cx
, jEnv
, member_name_jstr
, &id
))
723 member_descriptor
= jsj_LookupJavaMemberDescriptorById(cx
, jEnv
, class_descriptor
, id
);
724 if (member_descriptor
)
725 return member_descriptor
;
727 member_descriptor
= JS_malloc(cx
, sizeof(JavaMemberDescriptor
));
728 if (!member_descriptor
)
730 memset(member_descriptor
, 0, sizeof(JavaMemberDescriptor
));
732 member_descriptor
->name
= jsj_DupJavaStringUTF(cx
, jEnv
, member_name_jstr
);
733 if (!member_descriptor
->name
) {
734 JS_free(cx
, member_descriptor
);
737 member_descriptor
->id
= id
;
739 member_descriptor
->next
= class_descriptor
->instance_members
;
740 class_descriptor
->instance_members
= member_descriptor
;
742 return member_descriptor
;
746 jsj_InitJavaClassReflectionsTable()
748 if (!java_class_reflections
) {
749 java_class_reflections
=
750 JSJ_NewHashTable(64, jsj_HashJavaObject
, jsj_JavaObjectComparator
,
753 if (!java_class_reflections
)
756 #ifdef JSJ_THREADSAFE
757 java_class_reflections_monitor
=
758 (struct PRMonitor
*) PR_NewMonitor();
759 if (!java_class_reflections_monitor
)
762 java_reflect_monitor
=
763 (struct PRMonitor
*) PR_NewMonitor();
764 if (!java_reflect_monitor
)