// File: hoehermann[P]TypedJNI/test.cpp
// Function: main
int main(int argc, char **argv)
{
    JavaVMInitArgs  vm_args;
    JavaVMOption jvmo;
    std::vector<JavaVMOption> options;
    //jvmo.optionString = const_cast<char*>("-verbose:gc"); options.push_back(jvmo);
    //jvmo.optionString = const_cast<char*>("-XX:+PrintGCTimeStamps"); options.push_back(jvmo);
    //jvmo.optionString = const_cast<char*>("-XX:+PrintGCDetails"); options.push_back(jvmo);
    vm_args.options = options.data();
    vm_args.nOptions = options.size();
    vm_args.version  = JNI_VERSION_1_8;
    TypedJNIEnv tenv(vm_args);
    TypedJNIClass javacls = tenv.find_class("TypedJNITest");
    javacls.GetStaticMethod<void()>("printHelloWorld");
    javacls.GetStaticMethod<void(jlong)>("printLong")(1);
    javacls.GetStaticMethod<void(jlong,jlong)>("print2Long")(1,2);
    {
        const long l = 1;
        std::cout << l << " incremented by Java is " << javacls.GetStaticMethod<jint(jint)>("increment")(l) << std::endl;
    }
    
    TypedJNIObject javaobj = javacls.GetConstructor<jstring>()(tenv.make_jstring("5"));
    {
        jint i = javaobj.GetMethod<jint(jint)>("incrementCounterBy")(2);
        std::cout << "After incrementing, counter is " << i << "." << std::endl;
    }
    javaobj.GetMethod<void(void)>("printCounter")();
    
    TypedJNIString s = tenv.make_jstring(std::string("Some words"));
    javaobj.GetMethod<void(jstring, jint)>("printInBackground")(s, 10);
    std::this_thread::sleep_for(std::chrono::seconds(5));

    return 0;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x470, %rsp            # imm = 0x470
movl $0x0, -0x4(%rbp)
movl %edi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
leaq -0x50(%rbp), %rdi
movq %rdi, -0x3a0(%rbp)
callq 0x40a0
movq -0x3a0(%rbp), %rdi
callq 0x40c0
movq -0x3a0(%rbp), %rdi
movq %rax, -0x20(%rbp)
callq 0x40e0
movl %eax, -0x24(%rbp)
movl $0x10008, -0x28(%rbp)   # imm = 0x10008
movq -0x18(%rbp), %rax
movq %rax, -0x70(%rbp)
movups -0x28(%rbp), %xmm0
movaps %xmm0, -0x80(%rbp)
movq -0x70(%rbp), %rcx
movq %rsp, %rax
movq %rcx, 0x10(%rax)
movaps -0x80(%rbp), %xmm0
movups %xmm0, (%rax)
leaq -0x68(%rbp), %rdi
callq 0x9ba0
jmp 0x35fc
leaq -0xc1(%rbp), %rdi
movq %rdi, -0x3a8(%rbp)
callq 0x33d0
movq -0x3a8(%rbp), %rdx
leaq 0xaa67(%rip), %rsi      # 0xe084
leaq -0xc0(%rbp), %rdi
callq 0x4100
jmp 0x362b
leaq -0x68(%rbp), %rdi
leaq -0xc0(%rbp), %rsi
callq 0x9de0
movq %rdx, -0x3b8(%rbp)
movq %rax, -0x3b0(%rbp)
jmp 0x364b
movq -0x3b8(%rbp), %rax
movq -0x3b0(%rbp), %rcx
movq %rcx, -0xa0(%rbp)
movq %rax, -0x98(%rbp)
leaq -0xc0(%rbp), %rdi
callq 0x3180
leaq -0xc1(%rbp), %rdi
callq 0x3290
leaq -0x109(%rbp), %rdi
movq %rdi, -0x3c0(%rbp)
callq 0x33d0
movq -0x3c0(%rbp), %rdx
leaq 0xa9f1(%rip), %rsi      # 0xe091
leaq -0x108(%rbp), %rdi
callq 0x4100
jmp 0x36ae
leaq -0xe8(%rbp), %rdi
leaq -0xa0(%rbp), %rsi
leaq -0x108(%rbp), %rdx
callq 0x41b0
jmp 0x36ca
leaq -0xe8(%rbp), %rdi
callq 0x41f0
leaq -0x108(%rbp), %rdi
callq 0x3180
leaq -0x109(%rbp), %rdi
callq 0x3290
leaq -0x151(%rbp), %rdi
movq %rdi, -0x3c8(%rbp)
callq 0x33d0
movq -0x3c8(%rbp), %rdx
leaq 0xa992(%rip), %rsi      # 0xe0a1
leaq -0x150(%rbp), %rdi
callq 0x4100
jmp 0x371d
leaq -0x130(%rbp), %rdi
leaq -0xa0(%rbp), %rsi
leaq -0x150(%rbp), %rdx
callq 0x4210
jmp 0x3739
leaq -0x130(%rbp), %rdi
movl $0x1, %esi
callq 0x4250
jmp 0x374c
leaq -0x130(%rbp), %rdi
callq 0x4290
leaq -0x150(%rbp), %rdi
callq 0x3180
leaq -0x151(%rbp), %rdi
callq 0x3290
leaq -0x199(%rbp), %rdi
movq %rdi, -0x3d0(%rbp)
callq 0x33d0
movq -0x3d0(%rbp), %rdx
leaq 0xa91a(%rip), %rsi      # 0xe0ab
leaq -0x198(%rbp), %rdi
callq 0x4100
jmp 0x379f
leaq -0x178(%rbp), %rdi
leaq -0xa0(%rbp), %rsi
leaq -0x198(%rbp), %rdx
callq 0x42b0
jmp 0x37bb
leaq -0x178(%rbp), %rdi
movl $0x1, %esi
movl $0x2, %edx
callq 0x42f0
jmp 0x37d3
leaq -0x178(%rbp), %rdi
callq 0x4340
leaq -0x198(%rbp), %rdi
callq 0x3180
leaq -0x199(%rbp), %rdi
callq 0x3290
movq $0x1, -0x1a8(%rbp)
movq 0x127bf(%rip), %rdi     # 0x15fc8
movl $0x1, %esi
callq 0x33f0
movq %rax, -0x3d8(%rbp)
jmp 0x381c
movq -0x3d8(%rbp), %rdi
leaq 0xa88c(%rip), %rsi      # 0xe0b6
callq 0x3240
movq %rax, -0x3e0(%rbp)
jmp 0x3838
leaq -0x1e9(%rbp), %rdi
movq %rdi, -0x3e8(%rbp)
callq 0x33d0
movq -0x3e8(%rbp), %rdx
leaq 0xa876(%rip), %rsi      # 0xe0cf
leaq -0x1e8(%rbp), %rdi
callq 0x4100
jmp 0x3867
leaq -0x1c8(%rbp), %rdi
leaq -0xa0(%rbp), %rsi
leaq -0x1e8(%rbp), %rdx
callq 0x4360
jmp 0x3883
leaq -0x1c8(%rbp), %rdi
movl $0x1, %esi
callq 0x4400
movl %eax, -0x3ec(%rbp)
jmp 0x389c
movl -0x3ec(%rbp), %esi
movq -0x3e0(%rbp), %rdi
callq 0x33b0
movq %rax, -0x3f8(%rbp)
jmp 0x38b7
movq -0x3f8(%rbp), %rdi
movq 0x126eb(%rip), %rsi     # 0x15fb0
callq 0x3270
jmp 0x38cc
leaq -0x1c8(%rbp), %rdi
callq 0x4440
leaq -0x1e8(%rbp), %rdi
callq 0x3180
leaq -0x1e9(%rbp), %rdi
callq 0x3290
leaq -0x230(%rbp), %rdi
leaq -0xa0(%rbp), %rsi
callq 0x4460
jmp 0x3905
leaq -0x269(%rbp), %rdi
movq %rdi, -0x400(%rbp)
callq 0x33d0
movq -0x400(%rbp), %rdx
leaq 0xa7b3(%rip), %rsi      # 0xe0d9
leaq -0x268(%rbp), %rdi
callq 0x4100
jmp 0x3934
leaq -0x248(%rbp), %rdi
leaq -0x68(%rbp), %rsi
leaq -0x268(%rbp), %rdx
callq 0x9f40
jmp 0x394d
leaq -0x248(%rbp), %rdi
callq 0x9a60
movq %rax, -0x408(%rbp)
jmp 0x3962
movq -0x408(%rbp), %rdx
leaq -0x210(%rbp), %rdi
leaq -0x230(%rbp), %rsi
callq 0x44a0
jmp 0x397e
leaq -0x248(%rbp), %rdi
callq 0x4500
leaq -0x268(%rbp), %rdi
callq 0x3180
leaq -0x269(%rbp), %rdi
callq 0x3290
leaq -0x230(%rbp), %rdi
callq 0x4520
leaq -0x2b1(%rbp), %rdi
movq %rdi, -0x410(%rbp)
callq 0x33d0
movq -0x410(%rbp), %rdx
leaq 0xa70c(%rip), %rsi      # 0xe0db
leaq -0x2b0(%rbp), %rdi
callq 0x4100
jmp 0x39dd
leaq -0x290(%rbp), %rdi
leaq -0x210(%rbp), %rsi
leaq -0x2b0(%rbp), %rdx
callq 0x4540
jmp 0x39f9
leaq -0x290(%rbp), %rdi
movl $0x2, %esi
callq 0x4400
movl %eax, -0x414(%rbp)
jmp 0x3a12
leaq -0x290(%rbp), %rdi
callq 0x4440
leaq -0x2b0(%rbp), %rdi
callq 0x3180
leaq -0x2b1(%rbp), %rdi
callq 0x3290
movl -0x414(%rbp), %eax
movl %eax, -0x270(%rbp)
movq 0x1257f(%rip), %rdi     # 0x15fc8
leaq 0xa69e(%rip), %rsi      # 0xe0ee
callq 0x3240
movq %rax, -0x420(%rbp)
jmp 0x3a5e
movq -0x420(%rbp), %rdi
movl -0x270(%rbp), %esi
callq 0x33b0
movq %rax, -0x428(%rbp)
jmp 0x3a79
movq -0x428(%rbp), %rdi
leaq 0xab08(%rip), %rsi      # 0xe58f
callq 0x3240
movq %rax, -0x430(%rbp)
jmp 0x3a95
movq -0x430(%rbp), %rdi
movq 0x1250d(%rip), %rsi     # 0x15fb0
callq 0x3270
jmp 0x3aaa
leaq -0x2f9(%rbp), %rdi
movq %rdi, -0x438(%rbp)
callq 0x33d0
movq -0x438(%rbp), %rdx
leaq 0xa643(%rip), %rsi      # 0xe10e
leaq -0x2f8(%rbp), %rdi
callq 0x4100
jmp 0x3ad9
leaq -0x2d8(%rbp), %rdi
leaq -0x210(%rbp), %rsi
leaq -0x2f8(%rbp), %rdx
callq 0x45f0
jmp 0x3af5
leaq -0x2d8(%rbp), %rdi
callq 0x4660
jmp 0x3b03
leaq -0x2d8(%rbp), %rdi
callq 0x41f0
leaq -0x2f8(%rbp), %rdi
callq 0x3180
leaq -0x2f9(%rbp), %rdi
callq 0x3290
leaq -0x339(%rbp), %rdi
movq %rdi, -0x440(%rbp)
callq 0x33d0
movq -0x440(%rbp), %rdx
leaq 0xa5d3(%rip), %rsi      # 0xe11b
leaq -0x338(%rbp), %rdi
callq 0x4100
jmp 0x3b56
leaq -0x318(%rbp), %rdi
leaq -0x68(%rbp), %rsi
leaq -0x338(%rbp), %rdx
callq 0x9f40
jmp 0x3b6f
leaq -0x338(%rbp), %rdi
callq 0x3180
leaq -0x339(%rbp), %rdi
callq 0x3290
leaq -0x381(%rbp), %rdi
movq %rdi, -0x448(%rbp)
callq 0x33d0
movq -0x448(%rbp), %rdx
leaq 0xa57e(%rip), %rsi      # 0xe126
leaq -0x380(%rbp), %rdi
callq 0x4100
jmp 0x3bb6
leaq -0x360(%rbp), %rdi
leaq -0x210(%rbp), %rsi
leaq -0x380(%rbp), %rdx
callq 0x46a0
jmp 0x3bd2
leaq -0x318(%rbp), %rdi
callq 0x9a60
movq %rax, -0x450(%rbp)
jmp 0x3be7
movq -0x450(%rbp), %rsi
leaq -0x360(%rbp), %rdi
movl $0xa, %edx
callq 0x4710
jmp 0x3c01
leaq -0x360(%rbp), %rdi
callq 0x4760
leaq -0x380(%rbp), %rdi
callq 0x3180
leaq -0x381(%rbp), %rdi
callq 0x3290
movl $0x5, -0x394(%rbp)
leaq -0x390(%rbp), %rdi
leaq -0x394(%rbp), %rsi
callq 0x4830
jmp 0x3c44
leaq -0x390(%rbp), %rdi
callq 0x4780
jmp 0x3c52
movl $0x0, -0x4(%rbp)
leaq -0x318(%rbp), %rdi
callq 0x4500
leaq -0x210(%rbp), %rdi
callq 0x4850
leaq -0x68(%rbp), %rdi
callq 0x9d60
leaq -0x50(%rbp), %rdi
callq 0x4870
movl -0x4(%rbp), %eax
addq $0x470, %rsp            # imm = 0x470
popq %rbp
retq
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x88(%rbp)
movl %eax, -0x8c(%rbp)
jmp 0x408b
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x88(%rbp)
movl %eax, -0x8c(%rbp)
jmp 0x3cd8
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x88(%rbp)
movl %eax, -0x8c(%rbp)
leaq -0xc0(%rbp), %rdi
callq 0x3180
leaq -0xc1(%rbp), %rdi
callq 0x3290
jmp 0x4082
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x88(%rbp)
movl %eax, -0x8c(%rbp)
jmp 0x3d1b
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x88(%rbp)
movl %eax, -0x8c(%rbp)
leaq -0x108(%rbp), %rdi
callq 0x3180
leaq -0x109(%rbp), %rdi
callq 0x3290
jmp 0x4082
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x88(%rbp)
movl %eax, -0x8c(%rbp)
jmp 0x3d7e
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x88(%rbp)
movl %eax, -0x8c(%rbp)
jmp 0x3d72
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x88(%rbp)
movl %eax, -0x8c(%rbp)
leaq -0x130(%rbp), %rdi
callq 0x4290
leaq -0x150(%rbp), %rdi
callq 0x3180
leaq -0x151(%rbp), %rdi
callq 0x3290
jmp 0x4082
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x88(%rbp)
movl %eax, -0x8c(%rbp)
jmp 0x3de1
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x88(%rbp)
movl %eax, -0x8c(%rbp)
jmp 0x3dd5
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x88(%rbp)
movl %eax, -0x8c(%rbp)
leaq -0x178(%rbp), %rdi
callq 0x4340
leaq -0x198(%rbp), %rdi
callq 0x3180
leaq -0x199(%rbp), %rdi
callq 0x3290
jmp 0x4082
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x88(%rbp)
movl %eax, -0x8c(%rbp)
jmp 0x4082
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x88(%rbp)
movl %eax, -0x8c(%rbp)
jmp 0x3e5b
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x88(%rbp)
movl %eax, -0x8c(%rbp)
jmp 0x3e4f
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x88(%rbp)
movl %eax, -0x8c(%rbp)
leaq -0x1c8(%rbp), %rdi
callq 0x4440
leaq -0x1e8(%rbp), %rdi
callq 0x3180
leaq -0x1e9(%rbp), %rdi
callq 0x3290
jmp 0x4082
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x88(%rbp)
movl %eax, -0x8c(%rbp)
jmp 0x3ebe
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x88(%rbp)
movl %eax, -0x8c(%rbp)
jmp 0x3eb2
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x88(%rbp)
movl %eax, -0x8c(%rbp)
leaq -0x248(%rbp), %rdi
callq 0x4500
leaq -0x268(%rbp), %rdi
callq 0x3180
leaq -0x269(%rbp), %rdi
callq 0x3290
leaq -0x230(%rbp), %rdi
callq 0x4520
jmp 0x4082
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x88(%rbp)
movl %eax, -0x8c(%rbp)
jmp 0x3f2d
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x88(%rbp)
movl %eax, -0x8c(%rbp)
jmp 0x3f21
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x88(%rbp)
movl %eax, -0x8c(%rbp)
leaq -0x290(%rbp), %rdi
callq 0x4440
leaq -0x2b0(%rbp), %rdi
callq 0x3180
leaq -0x2b1(%rbp), %rdi
callq 0x3290
jmp 0x4076
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x88(%rbp)
movl %eax, -0x8c(%rbp)
jmp 0x4076
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x88(%rbp)
movl %eax, -0x8c(%rbp)
jmp 0x3fa7
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x88(%rbp)
movl %eax, -0x8c(%rbp)
jmp 0x3f9b
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x88(%rbp)
movl %eax, -0x8c(%rbp)
leaq -0x2d8(%rbp), %rdi
callq 0x41f0
leaq -0x2f8(%rbp), %rdi
callq 0x3180
leaq -0x2f9(%rbp), %rdi
callq 0x3290
jmp 0x4076
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x88(%rbp)
movl %eax, -0x8c(%rbp)
jmp 0x3fea
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x88(%rbp)
movl %eax, -0x8c(%rbp)
leaq -0x338(%rbp), %rdi
callq 0x3180
leaq -0x339(%rbp), %rdi
callq 0x3290
jmp 0x4076
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x88(%rbp)
movl %eax, -0x8c(%rbp)
jmp 0x404a
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x88(%rbp)
movl %eax, -0x8c(%rbp)
jmp 0x403e
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x88(%rbp)
movl %eax, -0x8c(%rbp)
leaq -0x360(%rbp), %rdi
callq 0x4760
leaq -0x380(%rbp), %rdi
callq 0x3180
leaq -0x381(%rbp), %rdi
callq 0x3290
jmp 0x406a
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x88(%rbp)
movl %eax, -0x8c(%rbp)
leaq -0x318(%rbp), %rdi
callq 0x4500
leaq -0x210(%rbp), %rdi
callq 0x4850
leaq -0x68(%rbp), %rdi
callq 0x9d60
leaq -0x50(%rbp), %rdi
callq 0x4870
movq -0x88(%rbp), %rdi
callq 0x33c0