-
Notifications
You must be signed in to change notification settings - Fork 29
/
Copy pathjni.cpp
1187 lines (1046 loc) · 40.3 KB
/
jni.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
// Copyright (C) 2018 Cornell University
#include "class.h"
#include "exception.h"
#include "jni_help.h"
#include "reflect.h"
#include "monitor.h"
#include "threads.h"
#include <pthread.h>
#define GC_THREADS
#include <gc.h>
#undef GC_THREADS
// Begin official API.
extern "C" {
jint jni_GetVersion(JNIEnv *env) {
// This is the correct version for Java SE 7 too.
return JNI_VERSION_1_6;
}
jclass jni_DefineClass(JNIEnv *env, const char *name, jobject loader,
const jbyte *buf, jsize len) {
JniUnimplemented("DefineClass");
}
/* name is in the java/lang/String format and is a valid C-string */
jclass jni_FindClass(JNIEnv *env, const char *name) {
// TODO this should do a classpath (java.class.path) search for compiled
// files
if (name == NULL)
return NULL;
return FindClassFromPathName(name);
}
jmethodID jni_FromReflectedMethod(JNIEnv *env, jobject method) {
JniUnimplemented("FromReflectedMethod");
}
jfieldID jni_FromReflectedField(JNIEnv *env, jobject field) {
JniUnimplemented("FromReflectedField");
}
jobject jni_ToReflectedMethod(JNIEnv *env, jclass cls, jmethodID id,
jboolean isStatic) {
JniUnimplemented("ToReflectedMethod");
}
jclass jni_GetSuperclass(JNIEnv *env, jclass sub) {
const JavaClassInfo *info = GetJavaClassInfo(sub);
if (info->super_ptr == NULL) {
return NULL;
}
return *(info->super_ptr);
// JniUnimplemented("GetSuperclass");
}
jboolean jni_IsAssignableFrom(JNIEnv *env, jclass sup, jclass sub) {
// dw475 TODO return sub <? sup
// return JNI_TRUE;
if (sub == NULL) {
// return JNI_FALSE;
// throw null pointer
}
// there exists a superclass or superinterface of sub = sup
return JNI_TRUE;
JniUnimplemented("jni_IsAssignableFrom");
}
jobject jni_ToReflectedField(JNIEnv *env, jclass cls, jfieldID id,
jboolean isStatic) {
JniUnimplemented("ToReflectedField");
}
jint jni_Throw(JNIEnv *env, jthrowable obj) {
throwThrowable(env, obj);
return -1;
}
jint jni_ThrowNew(JNIEnv *env, jclass clazz, const char *msg) {
throwNewThrowable(env, clazz, msg);
return -1;
}
jthrowable jni_ExceptionOccurred(JNIEnv *env) {
// TODO do something here (ExceptionOccurred)
return NULL;
}
void jni_ExceptionDescribe(JNIEnv *env) {
JniUnimplemented("ExceptionDescribe");
}
void jni_ExceptionClear(JNIEnv *env) { JniUnimplemented("ExceptionClear"); }
void jni_FatalError(JNIEnv *env, const char *msg) {
JniUnimplemented("FatalError");
}
jint jni_PushLocalFrame(JNIEnv *env, jint capacity) {
JniUnimplemented("PushLocalFrame");
}
jobject jni_PopLocalFrame(JNIEnv *env, jobject result) {
JniUnimplemented("PopLocalFrame");
}
jobject jni_NewGlobalRef(JNIEnv *env, jobject lobj) {
// TODO, do something real here for global ref
return lobj;
}
void jni_DeleteGlobalRef(JNIEnv *env, jobject gref) {
// TODO handle delete global ref if necessary
// JniUnimplemented("DeleteGlobalRef");
}
void jni_DeleteLocalRef(JNIEnv *env, jobject obj) {
// TODO handle DeleteLocalRef if necessary (or remove TODO if not)
// JniUnimplemented("DeleteLocalRef");
}
jboolean jni_IsSameObject(JNIEnv *env, jobject obj1, jobject obj2) {
return obj1 == obj2;
}
jobject jni_NewLocalRef(JNIEnv *env, jobject ref) {
JniUnimplemented("NewLocalRef");
}
#define MAX_CAPACITY 4000
jint jni_EnsureLocalCapacity(JNIEnv *env, jint capacity) {
// JDK actually just does tracing here and returns false iff capacity > 4000
if (capacity > MAX_CAPACITY) {
return JNI_ERR;
} else {
return JNI_OK;
}
}
jobject jni_AllocObject(JNIEnv *env, jclass clazz) {
JniUnimplemented("AllocObject");
}
jobject jni_NewObject(JNIEnv *env, jclass clazz, jmethodID id, ...) {
va_list args;
va_start(args, id);
jobject res = CreateJavaObject(clazz);
CallJavaConstructor(res, id, args);
va_end(args);
return res;
}
jobject jni_NewObjectV(JNIEnv *env, jclass clazz, jmethodID id, va_list args) {
jobject res = CreateJavaObject(clazz);
CallJavaConstructor(res, id, args);
return res;
}
jobject jni_NewObjectA(JNIEnv *env, jclass clazz, jmethodID id,
const jvalue *args) {
jobject res = CreateJavaObject(clazz);
CallJavaNonvirtualMethod<jobject>(res, id, args);
return res;
}
jclass jni_GetObjectClass(JNIEnv *env, jobject obj) {
if (obj) {
return Unwrap(obj)->Cdv()->Class()->Wrap();
} else {
return NULL;
}
}
jboolean jni_IsInstanceOf(JNIEnv *env, jobject obj, jclass clazz) {
return InstanceOf(obj, clazz);
// JniUnimplemented("IsInstanceOf");
}
jmethodID jni_GetMethodID(JNIEnv *env, jclass clazz, const char *name,
const char *sig) {
return reinterpret_cast<jmethodID>(
GetJavaMethodInfo(clazz, name, sig).first);
}
#define ARGS JNIEnv *env, jobject obj, jmethodID id, ...
#define START_VA \
va_list args; \
va_start(args, id)
#define END_VA va_end(args)
#define CALL(jrep) CallJavaInstanceMethod<jrep>(obj, id, args)
#define IMPL(jrep) \
START_VA; \
jrep res = CALL(jrep); \
END_VA; \
return res
jobject jni_CallObjectMethod(ARGS) { IMPL(jobject); }
jboolean jni_CallBooleanMethod(ARGS) { IMPL(jboolean); }
jbyte jni_CallByteMethod(ARGS) { IMPL(jbyte); }
jchar jni_CallCharMethod(ARGS) { IMPL(jchar); }
jshort jni_CallShortMethod(ARGS) { IMPL(jshort); }
jint jni_CallIntMethod(ARGS) { IMPL(jint); }
jlong jni_CallLongMethod(ARGS) { IMPL(jlong); }
jfloat jni_CallFloatMethod(ARGS) { IMPL(jfloat); }
jdouble jni_CallDoubleMethod(ARGS) { IMPL(jdouble); }
void jni_CallVoidMethod(ARGS) {
START_VA;
CALL(void);
END_VA;
}
#undef IMPL
#undef CALL
#undef END_VA
#undef START_VA
#undef ARGS
#define ARGS JNIEnv *env, jobject obj, jmethodID id, const jvalue *args
#define IMPL(jrep) return CallJavaInstanceMethod<jrep>(obj, id, args)
jobject jni_CallObjectMethodA(ARGS) { IMPL(jobject); }
jboolean jni_CallBooleanMethodA(ARGS) { IMPL(jboolean); }
jbyte jni_CallByteMethodA(ARGS) { IMPL(jbyte); }
jchar jni_CallCharMethodA(ARGS) { IMPL(jchar); }
jshort jni_CallShortMethodA(ARGS) { IMPL(jshort); }
jint jni_CallIntMethodA(ARGS) { IMPL(jint); }
jlong jni_CallLongMethodA(ARGS) { IMPL(jlong); }
jfloat jni_CallFloatMethodA(ARGS) { IMPL(jfloat); }
jdouble jni_CallDoubleMethodA(ARGS) { IMPL(jdouble); }
void jni_CallVoidMethodA(ARGS) { IMPL(void); }
#undef IMPL
#undef ARGS
#define ARGS JNIEnv *env, jobject obj, jmethodID id, va_list args
#define IMPL(jrep) return CallJavaInstanceMethod<jrep>(obj, id, args)
jobject jni_CallObjectMethodV(ARGS) { IMPL(jobject); }
jboolean jni_CallBooleanMethodV(ARGS) { IMPL(jboolean); }
jbyte jni_CallByteMethodV(ARGS) { IMPL(jbyte); }
jchar jni_CallCharMethodV(ARGS) { IMPL(jchar); }
jshort jni_CallShortMethodV(ARGS) { IMPL(jshort); }
jint jni_CallIntMethodV(ARGS) { IMPL(jint); }
jlong jni_CallLongMethodV(ARGS) { IMPL(jlong); }
jfloat jni_CallFloatMethodV(ARGS) { IMPL(jfloat); }
jdouble jni_CallDoubleMethodV(ARGS) { IMPL(jdouble); }
void jni_CallVoidMethodV(ARGS) { IMPL(void); }
#undef IMPL
#undef ARGS
jobject jni_CallNonvirtualObjectMethod(JNIEnv *env, jobject obj, jclass clazz,
jmethodID id, ...) {
JniUnimplemented("CallNonvirtualObjectMethod");
}
jboolean jni_CallNonvirtualBooleanMethod(JNIEnv *env, jobject obj, jclass clazz,
jmethodID id, ...) {
JniUnimplemented("CallNonvirtualBooleanMethod");
}
jbyte jni_CallNonvirtualByteMethod(JNIEnv *env, jobject obj, jclass clazz,
jmethodID id, ...) {
JniUnimplemented("CallNonvirtualByteMethod");
}
jchar jni_CallNonvirtualCharMethod(JNIEnv *env, jobject obj, jclass clazz,
jmethodID id, ...) {
JniUnimplemented("CallNonvirtualCharMethod");
}
jshort jni_CallNonvirtualShortMethod(JNIEnv *env, jobject obj, jclass clazz,
jmethodID id, ...) {
JniUnimplemented("CallNonvirtualShortMethod");
}
jint jni_CallNonvirtualIntMethod(JNIEnv *env, jobject obj, jclass clazz,
jmethodID id, ...) {
JniUnimplemented("CallNonvirtualIntMethod");
}
jlong jni_CallNonvirtualLongMethod(JNIEnv *env, jobject obj, jclass clazz,
jmethodID id, ...) {
JniUnimplemented("CallNonvirtualLongMethod");
}
jfloat jni_CallNonvirtualFloatMethod(JNIEnv *env, jobject obj, jclass clazz,
jmethodID id, ...) {
JniUnimplemented("CallNonvirtualFloatMethod");
}
jdouble jni_CallNonvirtualDoubleMethod(JNIEnv *env, jobject obj, jclass clazz,
jmethodID id, ...) {
JniUnimplemented("CallNonvirtualDoubleMethod");
}
void jni_CallNonvirtualVoidMethod(JNIEnv *env, jobject obj, jclass clazz,
jmethodID id, ...) {
JniUnimplemented("CallNonvirtualVoidMethod");
}
jobject jni_CallNonvirtualObjectMethodA(JNIEnv *env, jobject obj, jclass clazz,
jmethodID id, const jvalue *args) {
JniUnimplemented("CallNonvirtualObjectMethodA");
}
jboolean jni_CallNonvirtualBooleanMethodA(JNIEnv *env, jobject obj,
jclass clazz, jmethodID id,
const jvalue *args) {
JniUnimplemented("CallNonvirtualBooleanMethodA");
}
jbyte jni_CallNonvirtualByteMethodA(JNIEnv *env, jobject obj, jclass clazz,
jmethodID id, const jvalue *args) {
JniUnimplemented("CallNonvirtualByteMethodA");
}
jchar jni_CallNonvirtualCharMethodA(JNIEnv *env, jobject obj, jclass clazz,
jmethodID id, const jvalue *args) {
JniUnimplemented("CallNonvirtualCharMethodA");
}
jshort jni_CallNonvirtualShortMethodA(JNIEnv *env, jobject obj, jclass clazz,
jmethodID id, const jvalue *args) {
JniUnimplemented("CallNonvirtualShortMethodA");
}
jint jni_CallNonvirtualIntMethodA(JNIEnv *env, jobject obj, jclass clazz,
jmethodID id, const jvalue *args) {
JniUnimplemented("CallNonvirtualIntMethodA");
}
jlong jni_CallNonvirtualLongMethodA(JNIEnv *env, jobject obj, jclass clazz,
jmethodID id, const jvalue *args) {
JniUnimplemented("CallNonvirtualLongMethodA");
}
jfloat jni_CallNonvirtualFloatMethodA(JNIEnv *env, jobject obj, jclass clazz,
jmethodID id, const jvalue *args) {
JniUnimplemented("CallNonvirtualFloatMethodA");
}
jdouble jni_CallNonvirtualDoubleMethodA(JNIEnv *env, jobject obj, jclass clazz,
jmethodID id, const jvalue *args) {
JniUnimplemented("CallNonvirtualDoubleMethodA");
}
void jni_CallNonvirtualVoidMethodA(JNIEnv *env, jobject obj, jclass clazz,
jmethodID id, const jvalue *args) {
JniUnimplemented("CallNonvirtualVoidMethodA");
}
jobject jni_CallNonvirtualObjectMethodV(JNIEnv *env, jobject obj, jclass clazz,
jmethodID id, va_list args) {
JniUnimplemented("CallNonvirtualObjectMethodV");
}
jboolean jni_CallNonvirtualBooleanMethodV(JNIEnv *env, jobject obj,
jclass clazz, jmethodID id,
va_list args) {
JniUnimplemented("CallNonvirtualBooleanMethodV");
}
jbyte jni_CallNonvirtualByteMethodV(JNIEnv *env, jobject obj, jclass clazz,
jmethodID id, va_list args) {
JniUnimplemented("CallNonvirtualByteMethodV");
}
jchar jni_CallNonvirtualCharMethodV(JNIEnv *env, jobject obj, jclass clazz,
jmethodID id, va_list args) {
JniUnimplemented("CallNonvirtualCharMethodV");
}
jshort jni_CallNonvirtualShortMethodV(JNIEnv *env, jobject obj, jclass clazz,
jmethodID id, va_list args) {
JniUnimplemented("CallNonvirtualShortMethodV");
}
jint jni_CallNonvirtualIntMethodV(JNIEnv *env, jobject obj, jclass clazz,
jmethodID id, va_list args) {
JniUnimplemented("CallNonvirtualIntMethodV");
}
jlong jni_CallNonvirtualLongMethodV(JNIEnv *env, jobject obj, jclass clazz,
jmethodID id, va_list args) {
JniUnimplemented("CallNonvirtualLongMethodV");
}
jfloat jni_CallNonvirtualFloatMethodV(JNIEnv *env, jobject obj, jclass clazz,
jmethodID id, va_list args) {
JniUnimplemented("CallNonvirtualFloatMethodV");
}
jdouble jni_CallNonvirtualDoubleMethodV(JNIEnv *env, jobject obj, jclass clazz,
jmethodID id, va_list args) {
JniUnimplemented("CallNonvirtualDoubleMethodV");
}
void jni_CallNonvirtualVoidMethodV(JNIEnv *env, jobject obj, jclass clazz,
jmethodID id, va_list args) {
JniUnimplemented("CallNonvirtualVoidMethodV");
}
jfieldID jni_GetJavaFieldID(JNIEnv *env, jclass clazz, const char *name,
const char *sig) {
// Scare casts to wrap field info in opaque pointer.
auto field = GetJavaFieldInfo(clazz, name);
auto no_const = const_cast<JavaFieldInfo *>(field);
return reinterpret_cast<jfieldID>(no_const);
}
// TODO: Ideally we would do more error checking here,
// to protect against buggy native code.
#define ARGS JNIEnv *env, jobject obj, jfieldID id
#define IMPL(jrep) return GetJavaField<jrep>(obj, id)
jboolean jni_GetBooleanField(ARGS) { IMPL(jboolean); }
jbyte jni_GetByteField(ARGS) { IMPL(jbyte); }
jchar jni_GetCharField(ARGS) { IMPL(jchar); }
jshort jni_GetShortField(ARGS) { IMPL(jshort); }
jint jni_GetIntField(ARGS) { IMPL(jint); }
jlong jni_GetLongField(ARGS) { IMPL(jlong); }
jfloat jni_GetFloatField(ARGS) { IMPL(jfloat); }
jdouble jni_GetDoubleField(ARGS) { IMPL(jdouble); }
jobject jni_GetObjectField(ARGS) { IMPL(jobject); }
#undef IMPL
#undef ARGS
#define ARGS(jrep) JNIEnv *env, jobject obj, jfieldID id, jrep val
#define IMPL(jrep) return SetJavaField<jrep>(obj, id, val)
void jni_SetBooleanField(ARGS(jboolean)) { IMPL(jboolean); }
void jni_SetByteField(ARGS(jbyte)) { IMPL(jbyte); }
void jni_SetCharField(ARGS(jchar)) { IMPL(jchar); }
void jni_SetShortField(ARGS(jshort)) { IMPL(jshort); }
void jni_SetIntField(ARGS(jint)) { IMPL(jint); }
void jni_SetLongField(ARGS(jlong)) { IMPL(jlong); }
void jni_SetFloatField(ARGS(jfloat)) { IMPL(jfloat); }
void jni_SetDoubleField(ARGS(jdouble)) { IMPL(jdouble); }
void jni_SetObjectField(ARGS(jobject)) { IMPL(jobject); }
#undef IMPL
#undef ARGS
jmethodID jni_GetStaticMethodID(JNIEnv *env, jclass clazz, const char *name,
const char *sig) {
return reinterpret_cast<jmethodID>(
GetJavaStaticMethodInfo(clazz, name, sig).first);
}
#define ARGS JNIEnv *env, jclass cls, jmethodID id, ...
#define START_VA \
va_list args; \
va_start(args, id)
#define END_VA va_end(args)
#define CALL(jrep) CallJavaStaticMethod<jrep>(cls, id, args)
#define IMPL(jrep) \
START_VA; \
jrep res = CALL(jrep); \
END_VA; \
return res
jobject jni_CallStaticObjectMethod(ARGS) { IMPL(jobject); }
jboolean jni_CallStaticBooleanMethod(ARGS) { IMPL(jboolean); }
jbyte jni_CallStaticByteMethod(ARGS) { IMPL(jbyte); }
jchar jni_CallStaticCharMethod(ARGS) { IMPL(jchar); }
jshort jni_CallStaticShortMethod(ARGS) { IMPL(jshort); }
jint jni_CallStaticIntMethod(ARGS) { IMPL(jint); }
jlong jni_CallStaticLongMethod(ARGS) { IMPL(jlong); }
jfloat jni_CallStaticFloatMethod(ARGS) { IMPL(jfloat); }
jdouble jni_CallStaticDoubleMethod(ARGS) { IMPL(jdouble); }
void jni_CallStaticVoidMethod(ARGS) {
START_VA;
CALL(void);
END_VA;
}
#undef IMPL
#undef CALL
#undef END_VA
#undef START_VA
#undef ARGS
#define ARGS JNIEnv *env, jclass cls, jmethodID id, va_list args
#define IMPL(jrep) return CallJavaStaticMethod<jrep>(cls, id, args)
jobject jni_CallStaticObjectMethodV(ARGS) { IMPL(jobject); }
jboolean jni_CallStaticBooleanMethodV(ARGS) { IMPL(jboolean); }
jbyte jni_CallStaticByteMethodV(ARGS) { IMPL(jbyte); }
jchar jni_CallStaticCharMethodV(ARGS) { IMPL(jchar); }
jshort jni_CallStaticShortMethodV(ARGS) { IMPL(jshort); }
jint jni_CallStaticIntMethodV(ARGS) { IMPL(jint); }
jlong jni_CallStaticLongMethodV(ARGS) { IMPL(jlong); }
jfloat jni_CallStaticFloatMethodV(ARGS) { IMPL(jfloat); }
jdouble jni_CallStaticDoubleMethodV(ARGS) { IMPL(jdouble); }
void jni_CallStaticVoidMethodV(ARGS) {
CallJavaStaticMethod<void>(cls, id, args);
}
#undef IMPL
#undef ARGS
jobject jni_CallStaticObjectMethodA(JNIEnv *env, jclass cls, jmethodID id,
const jvalue *args) {
JniUnimplemented("CallStaticObjectMethodA");
}
jboolean jni_CallStaticBooleanMethodA(JNIEnv *env, jclass cls, jmethodID id,
const jvalue *args) {
JniUnimplemented("CallStaticBooleanMethodA");
}
jbyte jni_CallStaticByteMethodA(JNIEnv *env, jclass cls, jmethodID id,
const jvalue *args) {
JniUnimplemented("CallStaticByteMethodA");
}
jchar jni_CallStaticCharMethodA(JNIEnv *env, jclass cls, jmethodID id,
const jvalue *args) {
JniUnimplemented("CallStaticCharMethodA");
}
jshort jni_CallStaticShortMethodA(JNIEnv *env, jclass cls, jmethodID id,
const jvalue *args) {
JniUnimplemented("CallStaticShortMethodA");
}
jint jni_CallStaticIntMethodA(JNIEnv *env, jclass cls, jmethodID id,
const jvalue *args) {
JniUnimplemented("CallStaticIntMethodA");
}
jlong jni_CallStaticLongMethodA(JNIEnv *env, jclass cls, jmethodID id,
const jvalue *args) {
JniUnimplemented("CallStaticLongMethodA");
}
jfloat jni_CallStaticFloatMethodA(JNIEnv *env, jclass cls, jmethodID id,
const jvalue *args) {
JniUnimplemented("CallStaticFloatMethodA");
}
jdouble jni_CallStaticDoubleMethodA(JNIEnv *env, jclass cls, jmethodID id,
const jvalue *args) {
JniUnimplemented("CallStaticDoubleMethodA");
}
void jni_CallStaticVoidMethodA(JNIEnv *env, jclass cls, jmethodID id,
const jvalue *args) {
JniUnimplemented("CallStaticVoidMethodA");
}
jfieldID jni_GetStaticFieldID(JNIEnv *env, jclass clazz, const char *name,
const char *sig) {
auto field = GetJavaStaticFieldInfo(clazz, name, sig);
auto no_const = const_cast<JavaStaticFieldInfo *>(field);
return reinterpret_cast<jfieldID>(no_const);
}
jobject jni_GetStaticObjectField(JNIEnv *env, jclass clazz, jfieldID id) {
JniUnimplemented("GetStaticObjectField");
}
jboolean jni_GetStaticBooleanField(JNIEnv *env, jclass clazz, jfieldID id) {
JniUnimplemented("GetStaticBooleanField");
}
jbyte jni_GetStaticByteField(JNIEnv *env, jclass clazz, jfieldID id) {
JniUnimplemented("GetStaticByteField");
}
jchar jni_GetStaticCharField(JNIEnv *env, jclass clazz, jfieldID id) {
JniUnimplemented("GetStaticCharField");
}
jshort jni_GetStaticShortField(JNIEnv *env, jclass clazz, jfieldID id) {
JniUnimplemented("GetStaticShortField");
}
jint jni_GetStaticIntField(JNIEnv *env, jclass clazz, jfieldID id) {
JniUnimplemented("GetStaticIntField");
}
jlong jni_GetStaticLongField(JNIEnv *env, jclass clazz, jfieldID id) {
JniUnimplemented("GetStaticLongField");
}
jfloat jni_GetStaticFloatField(JNIEnv *env, jclass clazz, jfieldID id) {
JniUnimplemented("GetStaticFloatField");
}
jdouble jni_GetStaticDoubleField(JNIEnv *env, jclass clazz, jfieldID id) {
JniUnimplemented("GetStaticDoubleField");
}
#define ARGS(jrep) JNIEnv *env, jclass clazz, jfieldID id, jrep val
#define IMPL(jrep) return SetJavaStaticField<jrep>(clazz, id, val)
void jni_SetStaticObjectField(ARGS(jobject)) { IMPL(jobject); }
void jni_SetStaticBooleanField(ARGS(jboolean)) { IMPL(jboolean); }
void jni_SetStaticByteField(ARGS(jbyte)) { IMPL(jbyte); }
void jni_SetStaticCharField(ARGS(jchar)) { IMPL(jchar); }
void jni_SetStaticShortField(ARGS(jshort)) { IMPL(jshort); }
void jni_SetStaticIntField(ARGS(jint)) { IMPL(jint); }
void jni_SetStaticLongField(ARGS(jlong)) { IMPL(jlong); }
void jni_SetStaticFloatField(ARGS(jfloat)) { IMPL(jfloat); }
void jni_SetStaticDoubleField(ARGS(jdouble)) { IMPL(jdouble); }
#undef IMPL
#undef ARGS
jstring jni_NewString(JNIEnv *env, const jchar *unicode, jsize len) {
return CreateJavaString(unicode, len);
}
jsize jni_GetStringLength(JNIEnv *env, jstring str) {
return Unwrap(str)->Chars()->Length();
}
const jchar *jni_GetStringChars(JNIEnv *env, jstring str, jboolean *isCopy) {
auto chars = reinterpret_cast<jcharArray>(Unwrap(str)->Chars()->Wrap());
return env->GetCharArrayElements(chars, isCopy);
}
void jni_ReleaseStringChars(JNIEnv *env, jstring str, const jchar *elems) {
auto chars = reinterpret_cast<jcharArray>(Unwrap(str)->Chars()->Wrap());
auto elems_cast = const_cast<jchar *>(elems);
env->ReleaseCharArrayElements(chars, elems_cast, /*mode*/ 0);
}
jstring jni_NewStringUTF(JNIEnv *env, const char *utf) {
jsize len = strlen(utf);
jcharArray chars = env->NewCharArray(len);
jchar *data = env->GetCharArrayElements(chars, /*isCopy*/ nullptr);
// TODO: Not a proper character encoding conversion.
for (jsize i = 0; i < len; ++i)
data[i] = static_cast<jchar>(utf[i]);
env->ReleaseCharArrayElements(chars, data, /*mode*/ 0);
jstring res = CreateJavaString(chars);
return res;
}
jsize jni_GetStringUTFLength(JNIEnv *env, jstring str) {
auto chars = env->GetStringUTFChars(str, /*isCopy*/ nullptr);
jsize len = strlen(chars);
env->ReleaseStringUTFChars(str, chars);
return len;
}
const char *jni_GetStringUTFChars(JNIEnv *env, jstring str, jboolean *isCopy) {
auto len = env->GetStringLength(str);
auto chars = env->GetStringChars(str, /*isCopy*/ nullptr);
char *res = (char *)malloc(len + 1);
// TODO: Incorrect conversion from Java string chars to UTF-8 chars.
// only works for 1 byte long UTF-16 chars (a.k.a. things that are already
// in UTF-8 form)
for (jsize i = 0; i < len; ++i)
res[i] = static_cast<char>(chars[i]);
res[len] = '\0';
env->ReleaseStringChars(str, chars);
if (isCopy != nullptr)
*isCopy = true;
return res;
}
void jni_ReleaseStringUTFChars(JNIEnv *env, jstring str, const char *chars) {
free(const_cast<char *>(chars));
}
jsize jni_GetArrayLength(JNIEnv *env, jarray array) {
return Unwrap(array)->Length();
}
jobjectArray jni_NewObjectArray(JNIEnv *env, jsize len, jclass clazz,
jobject init) {
JniUnimplemented("NewObjectArray");
}
jobject jni_GetObjectArrayElement(JNIEnv *env, jobjectArray arr, jsize index) {
if (!JavaArrayBoundsCheck(arr, index))
return nullptr;
// Assumes no copy.
auto data = GetJavaArrayData<jobject>(arr, /*isCopy*/ nullptr);
return data[index];
}
void jni_SetObjectArrayElement(JNIEnv *env, jobjectArray arr, jsize index,
jobject val) {
if (!JavaArrayBoundsCheck(arr, index))
return;
// Assumes no copy.
auto data = GetJavaArrayData<jobject>(arr, /*isCopy*/ nullptr);
data[index] = val;
}
#define ARGS JNIEnv *env, jsize len
jbooleanArray jni_NewBooleanArray(ARGS) { return CreateJavaBooleanArray(len); }
jbyteArray jni_NewByteArray(ARGS) { return CreateJavaByteArray(len); }
jcharArray jni_NewCharArray(ARGS) { return CreateJavaCharArray(len); }
jshortArray jni_NewShortArray(ARGS) { return CreateJavaShortArray(len); }
jintArray jni_NewIntArray(ARGS) { return CreateJavaIntArray(len); }
jlongArray jni_NewLongArray(ARGS) { return CreateJavaLongArray(len); }
jfloatArray jni_NewFloatArray(ARGS) { return CreateJavaFloatArray(len); }
jdoubleArray jni_NewDoubleArray(ARGS) { return CreateJavaDoubleArray(len); }
#undef ARGS
jboolean *jni_GetBooleanArrayElements(JNIEnv *env, jbooleanArray arr,
jboolean *isCopy) {
return GetJavaArrayData<jboolean>(arr, isCopy);
}
jbyte *jni_GetByteArrayElements(JNIEnv *env, jbyteArray arr, jboolean *isCopy) {
return GetJavaArrayData<jbyte>(arr, isCopy);
}
jchar *jni_GetCharArrayElements(JNIEnv *env, jcharArray arr, jboolean *isCopy) {
return GetJavaArrayData<jchar>(arr, isCopy);
}
jshort *jni_GetShortArrayElements(JNIEnv *env, jshortArray arr,
jboolean *isCopy) {
return GetJavaArrayData<jshort>(arr, isCopy);
}
jint *jni_GetIntArrayElements(JNIEnv *env, jintArray arr, jboolean *isCopy) {
return GetJavaArrayData<jint>(arr, isCopy);
}
jlong *jni_GetLongArrayElements(JNIEnv *env, jlongArray arr, jboolean *isCopy) {
return GetJavaArrayData<jlong>(arr, isCopy);
}
jfloat *jni_GetFloatArrayElements(JNIEnv *env, jfloatArray arr,
jboolean *isCopy) {
return GetJavaArrayData<jfloat>(arr, isCopy);
}
jdouble *jni_GetDoubleArrayElements(JNIEnv *env, jdoubleArray arr,
jboolean *isCopy) {
return GetJavaArrayData<jdouble>(arr, isCopy);
}
// We do not make a copy of array elements, so these are no-ops.
void jni_ReleaseBooleanArrayElements(JNIEnv *env, jbooleanArray arr,
jboolean *data, jint mode) {}
void jni_ReleaseByteArrayElements(JNIEnv *env, jbyteArray arr, jbyte *data,
jint mode) {}
void jni_ReleaseCharArrayElements(JNIEnv *env, jcharArray arr, jchar *data,
jint mode) {}
void jni_ReleaseShortArrayElements(JNIEnv *env, jshortArray arr, jshort *data,
jint mode) {}
void jni_ReleaseIntArrayElements(JNIEnv *env, jintArray arr, jint *data,
jint mode) {}
void jni_ReleaseLongArrayElements(JNIEnv *env, jlongArray arr, jlong *data,
jint mode) {}
void jni_ReleaseFloatArrayElements(JNIEnv *env, jfloatArray arr, jfloat *data,
jint mode) {}
void jni_ReleaseDoubleArrayElements(JNIEnv *env, jdoubleArray arr,
jdouble *data, jint mode) {}
void jni_GetBooleanArrayRegion(JNIEnv *env, jbooleanArray arr, jsize start,
jsize len, jboolean *buf) {
GetJavaArrayRegion<jboolean>(arr, start, len, buf);
}
void jni_GetByteArrayRegion(JNIEnv *env, jbyteArray arr, jsize start, jsize len,
jbyte *buf) {
GetJavaArrayRegion<jbyte>(arr, start, len, buf);
}
void jni_GetCharArrayRegion(JNIEnv *env, jcharArray arr, jsize start, jsize len,
jchar *buf) {
GetJavaArrayRegion<jchar>(arr, start, len, buf);
}
void jni_GetShortArrayRegion(JNIEnv *env, jshortArray arr, jsize start,
jsize len, jshort *buf) {
GetJavaArrayRegion<jshort>(arr, start, len, buf);
}
void jni_GetIntArrayRegion(JNIEnv *env, jintArray arr, jsize start, jsize len,
jint *buf) {
GetJavaArrayRegion<jint>(arr, start, len, buf);
}
void jni_GetLongArrayRegion(JNIEnv *env, jlongArray arr, jsize start, jsize len,
jlong *buf) {
GetJavaArrayRegion<jlong>(arr, start, len, buf);
}
void jni_GetFloatArrayRegion(JNIEnv *env, jfloatArray arr, jsize start,
jsize len, jfloat *buf) {
GetJavaArrayRegion<jfloat>(arr, start, len, buf);
}
void jni_GetDoubleArrayRegion(JNIEnv *env, jdoubleArray arr, jsize start,
jsize len, jdouble *buf) {
GetJavaArrayRegion<jdouble>(arr, start, len, buf);
}
void jni_SetBooleanArrayRegion(JNIEnv *env, jbooleanArray arr, jsize start,
jsize len, const jboolean *buf) {
SetJavaArrayRegion<jboolean>(arr, start, len, buf);
}
void jni_SetByteArrayRegion(JNIEnv *env, jbyteArray arr, jsize start, jsize len,
const jbyte *buf) {
SetJavaArrayRegion<jbyte>(arr, start, len, buf);
}
void jni_SetCharArrayRegion(JNIEnv *env, jcharArray arr, jsize start, jsize len,
const jchar *buf) {
SetJavaArrayRegion<jchar>(arr, start, len, buf);
}
void jni_SetShortArrayRegion(JNIEnv *env, jshortArray arr, jsize start,
jsize len, const jshort *buf) {
SetJavaArrayRegion<jshort>(arr, start, len, buf);
}
void jni_SetIntArrayRegion(JNIEnv *env, jintArray arr, jsize start, jsize len,
const jint *buf) {
SetJavaArrayRegion<jint>(arr, start, len, buf);
}
void jni_SetLongArrayRegion(JNIEnv *env, jlongArray arr, jsize start, jsize len,
const jlong *buf) {
SetJavaArrayRegion<jlong>(arr, start, len, buf);
}
void jni_SetFloatArrayRegion(JNIEnv *env, jfloatArray arr, jsize start,
jsize len, const jfloat *buf) {
SetJavaArrayRegion<jfloat>(arr, start, len, buf);
}
void jni_SetDoubleArrayRegion(JNIEnv *env, jdoubleArray arr, jsize start,
jsize len, const jdouble *buf) {
SetJavaArrayRegion<jdouble>(arr, start, len, buf);
}
jint jni_RegisterNatives(JNIEnv *env, jclass clazz,
const JNINativeMethod *methods, jint nMethods) {
for (jint i = 0; i < nMethods; ++i) {
RegisterJavaNativeFunc(clazz, methods[i].name, methods[i].signature,
methods[i].fnPtr);
}
return 0;
}
jint jni_UnregisterNatives(JNIEnv *env, jclass clazz) {
JniUnimplemented("UnregisterNatives");
}
jint jni_MonitorEnter(JNIEnv *env, jobject obj) {
Monitor::Instance().enter(obj);
return 0;
}
jint jni_MonitorExit(JNIEnv *env, jobject obj) {
Monitor::Instance().exit(obj);
return 0;
}
jint jni_GetJavaVM(JNIEnv *env, JavaVM **vm);
void jni_GetStringRegion(JNIEnv *env, jstring str, jsize start, jsize len,
jchar *buf) {
// TODO error handling on case: if (start < 0 || len <0 || start + len >
// s_len) { and throw StringIndexOutOfBoundsException
JArrayRep *str_array = Unwrap(str)->Chars();
// int str_len = str_array->Length();
int elemsize = str_array->ElemSize();
assert(elemsize == sizeof(jchar));
jchar *data = reinterpret_cast<jchar *>(str_array->Data());
memcpy(buf, &(data[start]), sizeof(jchar) * len);
}
void jni_GetStringUTFRegion(JNIEnv *env, jstring str, jsize start, jsize len,
char *buf) {
// TODO error handling on case: if (start < 0 || len < 0 || start + len >
// s_len) { and throw StringIndexOutOfBoundsException
if (len > 0) {
JArrayRep *str_array = Unwrap(str)->Chars();
// int str_len = str_array->Length();
int elemsize = str_array->ElemSize();
char *str_data = (char *)str_array->Data();
as_utf8((jchar *)(str_data + (elemsize * start)), len, (u_char *)buf);
int utf_len = (int)strlen(buf);
buf[utf_len] = 0;
} else {
if (buf != NULL) {
buf[0] = 0;
}
}
}
void *jni_GetPrimitiveArrayCritical(JNIEnv *env, jarray array,
jboolean *isCopy) {
JniUnimplemented("GetPrimitiveArrayCritical");
}
void jni_ReleasePrimitiveArrayCritical(JNIEnv *env, jarray array, void *carray,
jint mode) {
JniUnimplemented("ReleasePrimitiveArrayCritical");
}
const jchar *jni_GetStringCritical(JNIEnv *env, jstring string,
jboolean *isCopy) {
JniUnimplemented("GetStringCritical");
}
void jni_ReleaseStringCritical(JNIEnv *env, jstring string,
const jchar *cstring) {
JniUnimplemented("ReleaseStringCritical");
}
jweak jni_NewWeakGlobalRef(JNIEnv *env, jobject obj) {
JniUnimplemented("NewWeakGlobalRef");
}
void jni_DeleteWeakGlobalRef(JNIEnv *env, jweak ref) {
JniUnimplemented("DeleteWeakGlobalRef");
}
jboolean jni_ExceptionCheck(JNIEnv *env) {
// TODO implement pending exceptions
return JNI_FALSE;
}
jobject jni_NewDirectByteBuffer(JNIEnv *env, void *address, jlong capacity) {
JniUnimplemented("NewDirectByteBuffer");
}
void *jni_GetDirectBufferAddress(JNIEnv *env, jobject buf) {
JniUnimplemented("GetDirectBufferAddress");
}
jlong jni_GetDirectBufferCapacity(JNIEnv *env, jobject buf) {
JniUnimplemented("GetDirectBufferCapacity");
}
jobjectRefType jni_GetObjectRefType(JNIEnv *env, jobject obj) {
JniUnimplemented("GetObjectRefType");
}
const struct JNINativeInterface_ jni_NativeInterface = {
NULL,
NULL,
NULL,
NULL,
jni_GetVersion,
jni_DefineClass,
jni_FindClass,
jni_FromReflectedMethod,
jni_FromReflectedField,
jni_ToReflectedMethod,
jni_GetSuperclass,
jni_IsAssignableFrom,
jni_ToReflectedField,
jni_Throw,
jni_ThrowNew,
jni_ExceptionOccurred,
jni_ExceptionDescribe,
jni_ExceptionClear,
jni_FatalError,
jni_PushLocalFrame,
jni_PopLocalFrame,
jni_NewGlobalRef,
jni_DeleteGlobalRef,
jni_DeleteLocalRef,
jni_IsSameObject,
jni_NewLocalRef,
jni_EnsureLocalCapacity,
jni_AllocObject,
jni_NewObject,
jni_NewObjectV,
jni_NewObjectA,
jni_GetObjectClass,
jni_IsInstanceOf,
jni_GetMethodID,
jni_CallObjectMethod,
jni_CallObjectMethodV,
jni_CallObjectMethodA,
jni_CallBooleanMethod,
jni_CallBooleanMethodV,
jni_CallBooleanMethodA,
jni_CallByteMethod,
jni_CallByteMethodV,
jni_CallByteMethodA,
jni_CallCharMethod,
jni_CallCharMethodV,
jni_CallCharMethodA,
jni_CallShortMethod,
jni_CallShortMethodV,
jni_CallShortMethodA,
jni_CallIntMethod,
jni_CallIntMethodV,
jni_CallIntMethodA,
jni_CallLongMethod,
jni_CallLongMethodV,
jni_CallLongMethodA,
jni_CallFloatMethod,
jni_CallFloatMethodV,
jni_CallFloatMethodA,
jni_CallDoubleMethod,
jni_CallDoubleMethodV,
jni_CallDoubleMethodA,
jni_CallVoidMethod,
jni_CallVoidMethodV,
jni_CallVoidMethodA,
jni_CallNonvirtualObjectMethod,
jni_CallNonvirtualObjectMethodV,
jni_CallNonvirtualObjectMethodA,
jni_CallNonvirtualBooleanMethod,
jni_CallNonvirtualBooleanMethodV,
jni_CallNonvirtualBooleanMethodA,
jni_CallNonvirtualByteMethod,
jni_CallNonvirtualByteMethodV,
jni_CallNonvirtualByteMethodA,
jni_CallNonvirtualCharMethod,
jni_CallNonvirtualCharMethodV,
jni_CallNonvirtualCharMethodA,
jni_CallNonvirtualShortMethod,
jni_CallNonvirtualShortMethodV,
jni_CallNonvirtualShortMethodA,
jni_CallNonvirtualIntMethod,
jni_CallNonvirtualIntMethodV,
jni_CallNonvirtualIntMethodA,
jni_CallNonvirtualLongMethod,
jni_CallNonvirtualLongMethodV,
jni_CallNonvirtualLongMethodA,
jni_CallNonvirtualFloatMethod,
jni_CallNonvirtualFloatMethodV,
jni_CallNonvirtualFloatMethodA,
jni_CallNonvirtualDoubleMethod,
jni_CallNonvirtualDoubleMethodV,
jni_CallNonvirtualDoubleMethodA,
jni_CallNonvirtualVoidMethod,
jni_CallNonvirtualVoidMethodV,
jni_CallNonvirtualVoidMethodA,
jni_GetJavaFieldID,
jni_GetObjectField,
jni_GetBooleanField,
jni_GetByteField,
jni_GetCharField,
jni_GetShortField,
jni_GetIntField,
jni_GetLongField,
jni_GetFloatField,
jni_GetDoubleField,
jni_SetObjectField,
jni_SetBooleanField,
jni_SetByteField,
jni_SetCharField,
jni_SetShortField,
jni_SetIntField,
jni_SetLongField,