http://www.concurrentaffair.org/2005/12/22/destroyjavavm/

DestroyJavaVM

The that produces the synchronization points after the main method has been exited during replay, thread 9, is called “DestroyJavaVM”. It appears for the first time immediately after the main method is left.

I also realized why these sync points don’t show up during recording: Recording happens in blocks, and a block only gets sent to the master VM when the buffer is full, when the main method is entered or exited. These eight sync points in the “DestroyJavaVM” thread can’t be pushed to the master VM anymore since main has already been left, the buffer doesn’t get full anymore, and when the application terminates (VMDeathEvent event) the data is not accessible anymore — the client VM is already dead.

This is not a catastrophe, though. It simply means that we cannot guarantee that sync points are recorded properly after the main method has been left. That may require some code to be rewritten, but a simple join() to wait until other threads have died will do the trick. There are other ways to fix this: For example, after the main method has been exited, the buffer size could be set to 1, forcing the client VM to push the buffer at every sync point. I’m not sure if this is necessary, but it’s worthwhile to keep it in mind.

There is another implication that’s more important, though: The replay program has to let the client VM run without monitoring if the schedule ends prematurely. In the current case, the last eight sync points by “DestroyJavaVM” are not present in the schedule, but we have to let the client VM execute them nonetheless. Also, not a biggie.

One secret (thread 9) has been investigated. Now I’m off to a more serious debugging to find the source of the sync points at the beginning…

=======================

http://docs.oracle.com/javase/1.3/docs/guide/jni/spec/invocation.doc.html

5 - The Invocation API


The Invocation API allows software vendors to load the Java VM* into an arbitrary native application. Vendors can deliver Java-enabled applications without having to link with the Java VM source code.

This chapter begins with an overview of the Invocation API. This is followed by reference pages for all Invocation API functions.

To enhance the embeddability of the Java VM, the Invocation API is extended in JDK 1.1.2 in a few minor ways.


Overview

The following code example illustrates how to use functions in the Invocation API. In this example, the C++ code creates a Java VM and invokes a static method, called Main.test. For clarity, we omit error checking.

        #include <jni.h>       /* where everything is defined */
...
JavaVM *jvm;       /* denotes a Java VM */
JNIEnv *env;       /* pointer to native method interface */
JDK1_1InitArgs vm_args; /* JDK 1.1 VM initialization arguments */
vm_args.version = 0x00010001; /* New in 1.1.2: VM version */
/* Get the default initialization arguments and set the class
* path */
JNI_GetDefaultJavaVMInitArgs(&vm_args);
vm_args.classpath = ...;
/* load and initialize a Java VM, return a JNI interface
* pointer in env */
JNI_CreateJavaVM(&jvm, &env, &vm_args);
/* invoke the Main.test method using the JNI */
jclass cls = env->FindClass("Main");
jmethodID mid = env->GetStaticMethodID(cls, "test", "(I)V");
env->CallStaticVoidMethod(cls, mid, 100);
/* We are done. */
jvm->DestroyJavaVM();

This example uses three functions in the API. The Invocation API allows a native application to use the JNI interface pointer to access VM features. The design is similar to Netscape's JRI Embedding Interface.

Creating the VM

The JNI_CreateJavaVM() function loads and initializes a Java VM and returns a pointer to the JNI interface pointer. The thread that called JNI_CreateJavaVM() is considered to be the main thread.

Attaching to the VM

The JNI interface pointer (JNIEnv) is valid only in the current thread. Should another thread need to access the Java VM, it must first call AttachCurrentThread() to attach itself to the VM and obtain a JNI interface pointer. Once attached to the VM, a native thread works just like an ordinary Java thread running inside a native method. The native thread remains attached to the VM until it calls DetachCurrentThread() to detach itself.

Unloading the VM

The main thread cannot detach itself from the VM. Instead, it must call DestroyJavaVM() to unload the entire VM.

The VM waits until the main thread is the only user thread before it actually unloads. User threads include both Java threads and attached native threads. This restriction exists because a Java thread or attached native thread may be holding system resources, such as locks, windows, and so on. The VM cannot automatically free these resources. By restricting the main thread to be the only running thread when the VM is unloaded, the burden of releasing system resources held by arbitrary threads is on the programmer.


Initialization Structures

Different Java VM implementation will likely require different initialization arguments. It is difficult to come up with a standard initialization structure suitable for all present and future Java VMs. As a compromise, we reserve the first field (version) to identify the content of the initialization structure. Native applications embedding JDK 1.1.2 must set the version field to 0x00010001. VM implementations are encouraged to use the same initialization structure as JDK, although other implementations may choose to ignore some of the initialization arguments supported by JDK.

Version numbers 0x80000000 to 0xFFFFFFFF are reserved, and should not be recognized by any VM implementation.

The following code shows the structure used to initialize the Java VM in JDK 1.1.2.

    typedef struct JavaVMInitArgs {
/* The first two fields were reserved in JDK 1.1, and
formally introduced in JDK 1.1.2. */
/* Java VM version */
jint version;
/* System properties. */
char **properties;
/* whether to check the Java source files are newer than
* compiled class files. */
jint checkSource;
/* maximum native stack size of Java-created threads. */
jint nativeStackSize;
/* maximum Java stack size. */
jint javaStackSize;
/* initial heap size. */
jint minHeapSize;
/* maximum heap size. */
jint maxHeapSize;
/* controls whether Java byte code should be verified:
* 0 -- none, 1 -- remotely loaded code, 2 -- all code. */
jint verifyMode;
/* the local directory path for class loading. */
const char *classpath;
/* a hook for a function that redirects all VM messages. */
jint (*vfprintf)(FILE *fp, const char *format,
va_list args);
/* a VM exit hook. */
void (*exit)(jint code);
/* a VM abort hook. */
void (*abort)();
/* whether to enable class GC. */
jint enableClassGC;
/* whether GC messages will appear. */
jint enableVerboseGC;
/* whether asynchronous GC is allowed. */
jint disableAsyncGC;
/* Three reserved fields. */
jint reserved0;
jint reserved1;
jint reserved2;
} JDK1_1InitArgs;

In JDK 1.1.2, the initialization structure provides hooks so that a native application can redirect VM messages and obtain control when the VM terminates.

The structure below is passed as an argument when a native thread attaches to a Java VM in JDK 1.1.2. In actuality, no arguments are required for a native thread to attach to the JDK 1.1.2. The JDK1_1AttachArgs structure consists only of a padding slot for those C compilers that do not permit empty structures.

    typedef struct JDK1_1AttachArgs {
/*
* JDK 1.1 does not need any arguments to attach a
* native thread. The padding is here to satisfy the C
* compiler which does not permit empty structures.
*/
void *__padding;
} JDK1_1AttachArgs;

Invocation API Functions

The JavaVM type is a pointer to the Invocation API function table. The following code example shows this function table.

    typedef const struct JNIInvokeInterface *JavaVM;
const struct JNIInvokeInterface ... = {
NULL,
NULL,
NULL,
DestroyJavaVM,
AttachCurrentThread,
DetachCurrentThread,
};

Note that three Invocation API functions, JNI_GetDefaultJavaVMInitArgs(), JNI_GetCreatedJavaVMs(), and JNI_CreateJavaVM(), are not part of the JavaVM function table. These functions can be used without a preexisting JavaVM structure.

JNI_GetDefaultJavaVMInitArgs

jint JNI_GetDefaultJavaVMInitArgs(void *vm_args);

Returns a default configuration for the Java VM. Before calling this function, native code must set the vm_args->version field to the JNI version it expects the VM to support. In JDK 1.1.2, vm_args->version must be set to 0x00010001. (JDK 1.1 did not require the native code to set the version field. For backward compatibility, JDK 1.1.2 assumes that the requested version is 0x00010001 if the version field is not set. Future versions of JDK will require the version field to be set to an appropriate value.) After this function returns, vm_args->version will be set to the actual JNI version the VM supports.

PARAMETERS:

vm_args: a pointer to a VM-specific initialization structure in to which the default arguments are filled.

RETURNS:

Returns "0" if the requested version is supported; returns a negative number if the requested version is not supported.

JNI_GetCreatedJavaVMs

jint JNI_GetCreatedJavaVMs(JavaVM **vmBuf, jsize bufLen,
jsize *nVMs);

Returns all Java VMs that have been created. Pointers to VMs are written in the buffer vmBuf in the order they are created. At most bufLen number of entries will be written. The total number of created VMs is returned in *nVMs.

JDK 1.1 does not support creating more than one VM in a single process.

PARAMETERS:

vmBuf: pointer to the buffer where the VM structures will be placed.

bufLen: the length of the buffer.

nVMs: a pointer to an integer.

RETURNS:

Returns "0" on success; returns a negative number on failure.

JNI_CreateJavaVM

jint JNI_CreateJavaVM(JavaVM **p_vm, JNIEnv **p_env,
void *vm_args);

Loads and initializes a Java VM. The current thread becomes the main thread. Sets the env argument to the JNI interface pointer of the main thread.

The JDK does not support creating more than one VM in a single process. The version field in vm_args must be set to 0x00010001.

PARAMETERS:

p_vm: pointer to the location where the resulting VM structure will be placed.

p_env: pointer to the location where the JNI interface pointer for the main thread will be placed.

vm_args: Java VM initialization arguments.

RETURNS:

Returns "0" on success; returns a negative number on failure.

DestroyJavaVM

jint DestroyJavaVM(JavaVM *vm);

Unloads a Java VM and reclaims its resources. Only the main thread can unload the VM. The main thread must be the only remaining user thread when it calls DestroyJavaVM().

PARAMETERS:

vm: the Java VM that will be destroyed.

RETURNS:

Returns "0" on success; returns a negative number on failure.

JDK 1.1.2 does not support unloading the VM.

AttachCurrentThread

jint AttachCurrentThread(JavaVM *vm, JNIEnv **p_env,
void *thr_args);

Attaches the current thread to a Java VM. Returns a JNI interface pointer in the JNIEnv argument.

Trying to attach a thread that is already attached is a no-op.

A native thread cannot be attached simultaneously to two Java VMs.

When a thread is attached to the VM, the context class loader is the bootstrap loader.

PARAMETERS:

vm: the VM to which the current thread will be attached.

p_env: pointer to the location where the JNI interface pointer of the current thread will be placed.

thr_args: VM-specific thread attachment arguments.

RETURNS:

Returns "0" on success; returns a negative number on failure.

DetachCurrentThread

jint DetachCurrentThread(JavaVM *vm);

Detaches the current thread from a Java VM. All Java monitors held by this thread are released. All Java threads waiting for this thread to die are notified.

The main thread, which is the thread that created the Java VM, cannot be detached from the VM. Instead, the main thread must call JNI_DestroyJavaVM() to unload the entire VM.

PARAMETERS:

vm: the VM from which the current thread will be detached.

RETURNS:

Returns "0" on success; returns a negative number on failure.

DestroyJavaVM相关推荐

  1. 接口访问次数_系统运行缓慢,CPU 100%,Full GC次数过多,这一招帮你全搞定

    处理过线上问题的同学基本上都会遇到系统突然运行缓慢,CPU 100%,以及Full GC次数过多的问题.当然,这些问题的最终导致的直观现象就是系统运行缓慢,并且有大量的报警.本文主要针对系统运行缓慢这 ...

  2. 系统运行缓慢,CPU 100%,以及Full GC次数过多问题的排查思路

    点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试资料 来源:http://h5ip.cn/uWWR 处理过线上问题的同学 ...

  3. 面试官问:平时碰到系统CPU飙高和频繁GC,你会怎么排查?

    点击上方"方志朋",选择"设为星标" 做积极的人,而不是积极废人 处理过线上问题的同学基本上都会遇到系统突然运行缓慢,CPU 100%,以及Full GC次数过 ...

  4. Java并发编程73道面试题及答案——稳了

    点击上方"方志朋",选择"置顶或者星标" 你的关注意义重大! 1.在java中守护线程和本地线程区别? java中的线程分为两种:守护线程(Daemon)和用户 ...

  5. CPU飙高,频繁GC,怎么排查?

    作者:爱宝贝. https://my.oschina.net/zhangxufeng/blog/3017521 处理过线上问题的同学基本上都会遇到系统突然运行缓慢,CPU 100%,以及Full GC ...

  6. 【系统缓慢、CPU 100%、频繁Full GC问题】的定位排查思路!

    作者:爱宝贝 https://my.oschina.net/zhangxufeng/blog/3017521 处理过线上问题的同学基本上都会遇到系统突然运行缓慢,CPU 100%,以及Full GC次 ...

  7. 2021-03-12java性能调优三板斧

    java性能调优三板斧 1 找进程ID   jps -v 2 根据ID打印JVM活动堆栈 jstack pid Microsoft Windows [版本 6.1.7601] 版权所有 (c) 200 ...

  8. java进程未正常退出

    2019独角兽企业重金招聘Python工程师标准>>> 背景: 通过shell脚本定时启动的java进程一直都没有退出 #0 */2 * * * /shell/command.sh ...

  9. java jstack dump 线程 介绍 解释

    最近抽时间把JVM运行过程中产生的一些线程进行了整理,主要是围绕着我们系统jstack生成的文件为参照依据.  前段时间因为系统代码问题,造成性能到了天花板,于是就dump了一份stack出来进行分析 ...

最新文章

  1. 11 Java程序员面试宝典视频课程之网络编程
  2. 通过WM_COPYDATA消息完成进程间通信
  3. 给后辈的一点建议,分享PDF高清版
  4. elementui的tree组件页面显示不出数据_只要10分钟,教你配置出炫酷的数据可视化大屏...
  5. 电脑遇到DNS服务器未响应的情况该怎么办
  6. 矩阵运算_SLAM中用到的矩阵计算_基本公式及知识汇总
  7. 射击类游戏html代码,超简单射击游戏
  8. 3套鱼塘合作引流话术模板?
  9. SpringMVC框架(一)
  10. 基于SpringBoot监控Java项目,暴漏springboot内置端点
  11. A79T三极管,A79T芯片规格书
  12. MLCC(贴片)电容啸叫分析
  13. 梅林安装opkg后安装iperf3_路由器最高速度/性能测试 - Windows 安装 IPerf3 及 使用方法...
  14. iOS--归档和解档(Archiver)、(UnArchiver)
  15. 从0到1,搭建离线下载器
  16. [ lucene扩展 ] 自定义Collector实现统计功能
  17. EFI启动盘修改BIOS隐藏选项DVMT等显存参数提升性能
  18. 关于mt6572不能开机问题
  19. 【TypeScript】TypeScript基础
  20. Spring初步了解

热门文章

  1. HarmonyOS之深入解析Ability的功能和使用
  2. 2020/Province_C_C++_A/A/门牌制作
  3. Java常用API (四) 包装类
  4. 【机器视觉】 dev_get_exception_data算子
  5. 【Ubuntu】 Ubuntu16.04搭建NFS服务
  6. 【Linux网络编程】原始套接字实例:发送 UDP 数据包
  7. python openstack oslo_config使用_OpenStack配置解析库oslo.config的使用方法
  8. 叉乘点乘混合运算公式_初中数学学不会?公式这样记,让你做题效率翻倍!
  9. 详解C++11智能指针
  10. 汇编---输出AX的地址值