JVM & Memory (3) thread

本文探讨了Java虚拟机(JVM)中的线程实现原理及其对内存的影响,包括Java栈、本地方法栈等概念,并分析了调用深度对性能的影响。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

转自:http://spaces.msn.com/songsun/

 

以下继续探讨,说说jvm的线程(thread)及其执行中和内存相关的问题。but今天是写不完了,请保持关注,先写个预告栏咯

记得当年学java之初,总是很鄙夷它,因为那时候对c/c++很痴迷,结果呢,第一个多线程程序还是拿java写出来的。而线程(thread),本是 操作系统的所提供/支持的,所以当初有一段时间,我总在怀疑我那java程序创建的线程到底是不是真正的操作系统线程,现在看来很可笑。

题外,再继续质疑一下: 在有些平台上,比如Linux或者大 部分的unix,只有进程而没有线程的概念的,但这些平台上,进程间通讯的手段极其发达,所以jvm会用进程模拟线程,效果也是一样的。不过,也有一些平 台如sorlaris,在java线程和os内核线程间,存在着不是1对1的关系,实在让我挠头,容以后再去把它搞明白。

简单的说,jvm如何实现多线程呢,首先要有os的支持包括变相的支持,那么jvm通过os提供线程接口创建新线程,这些新线程当然还不能直接执行你的 thread对象的run方法,但它会拥有并执行属于该线程的一个java interpreter实例或者上下文,java解释器再去执行你的run方法,当run方法结束(自然结束时),java interpreter发现没有字节码可以解释了,也宣告结束,OS线程也就自然终结了。至于要实现线程的终止,挂起,恢复,也都可以从OS那里找到相应 的接口,这里不再细说,而主要关注对内存的影响,主要是java stack和native call等问题。

待续


当执行引擎(即java interpreter,对应一个ExecEnv)开始解释执行一个java method以前,它首先初始化自身,即分配自己的initial java stack,栈开始时尺寸很小,随着使用的需要而扩展,存在一个400k的默认长度限制( -Xss<size>可更改该值);ExecEnv有两个重要的标志(或指针),一个是pc,即程序计数器,另一个是optop,即栈顶,也 是最上面一个操作数(即本地变量)的位置。 pc总是指向要执行的byte code(随着每一条byte code的执行,pc自动改变),而optop指向java stack的顶端(也随某些byte code的执行而改动)。当方法执行时,方法的invoker将pc指向method block的code位,同时,在java stack里为该方法新建java frame(每一个方法在编译期就确定了运行它所需的最大stack size,所以,新建java freame时,会按照这个size去检查java stack是否满足,若不足,则扩展java stack,而java stack已经达到最大长度限制时,扩展失败,发生stack overflow),准备工作完成后,还给ExecEnv继续解释和执行;当方法执行完毕时,一条ret字节指令将pc和optop送回前一个java frame所记录的位置。所以,对于某个线程来说,其java stack完整的记录了所深入的每一层java method(每层一个java frame),除了native method,本质上是因为c的堆栈不能记录。

以上是执行java method,若是native method呢?很简单,native method在类加载时,即被jvm安排了一个native invoker在其method block中,继而在ExecEnv执行一条call该native method的字节指令时,native invoker被执行,如果是首次执行,那么这个native mothod的method block的code段尚未挂接,native invoker检查到这个信息,将根据method name和signature搜索系统中已加载的dll的合适挂接点,将找到的挂接点挂在code上,而后调用该code段即可(找不到挂接点,会发生什 么异常你应该清楚)。过程中,除非你的native method中又反调了java method,那么,java stack将毫无变化。

再来关注一下native method的内存模型:native mthod自身的机器码code存在于dll镜像(image)中;nm的本地变量存在于线程堆栈内(指native thread,和java thread是绑定着的);nm用到的静态变量存在于dll的共享变量区中;nm制造的java对象(通过jni手段new来的)依然在java heap;而nm声明的global ref以及local ref存放在jvm的native c heap上。本地方法也会带来内存泄露(c的内存泄露,也可能是java heap的global ref的未释放),特别是c heap的泄露,运行期是极难探测和定位的。

最后,说说调用深度过深(即java stack会很长)带来的负面影响。在前一节,我们知道本地变量都寄存在java stack中。如果调用深度过深,特别是jvm长时间运行在较高深度调用的情形下,意味着在栈上的各frame中,存在着很多变量,它们中的引用类型将一 直保持对java heap上对应对象的引用而导致gc器始终不能释放它们;其次,较长的java stack也给gc器造成了较多的扫描时间(为何要扫描后面再说);第三,method call本身也是一种时间开销,对于很短小的method,call它比它本身代码执行的时间还要多,好比机关枪打蚊子,这也是现代编译器非常讲究inline优化的原因。

--- lowercaseOutputLabelNames: true lowercaseOutputName: true whitelistObjectNames: [&quot;java.lang:type=OperatingSystem&quot;] blacklistObjectNames: [] rules: - pattern: &#39;java.lang&lt;type=OperatingSystem&gt;&lt;&gt;(committed_virtual_memory|free_physical_memory|free_swap_space|total_physical_memory|total_swap_space)_size:&#39; name: os_$1_bytes type: GAUGE attrNameSnakeCase: true - pattern: &#39;java.lang&lt;type=OperatingSystem&gt;&lt;&gt;((?!process_cpu_time)\w+):&#39; name: os_$1 type: GAUGE attrNameSnakeCase: true 解释代码后,解释# HELP jvm_info VM version info # TYPE jvm_info gauge jvm_info{runtime=&quot;Java(TM) SE Runtime Environment&quot;,vendor=&quot;Oracle Corporation&quot;,version=&quot;1.7.0_79-b15&quot;,} 1.0 # HELP os_process_cpu_load java.lang:name=null,type=OperatingSystem,attribute=ProcessCpuLoad # TYPE os_process_cpu_load gauge os_process_cpu_load 0.07142857142857142 # HELP os_open_file_descriptor_count java.lang:name=null,type=OperatingSystem,attribute=OpenFileDescriptorCount # TYPE os_open_file_descriptor_count gauge os_open_file_descriptor_count 84.0 # HELP os_max_file_descriptor_count java.lang:name=null,type=OperatingSystem,attribute=MaxFileDescriptorCount # TYPE os_max_file_descriptor_count gauge os_max_file_descriptor_count 4096.0 # HELP os_total_swap_space_bytes java.lang:name=null,type=OperatingSystem,attribute=TotalSwapSpaceSize # TYPE os_total_swap_space_bytes gauge os_total_swap_space_bytes 4.160745472E9 # HELP os_total_physical_memory_bytes java.lang:name=null,type=OperatingSystem,attribute=TotalPhysicalMemorySize # TYPE os_total_physical_memory_bytes gauge os_total_physical_memory_bytes 8.201289728E9 # HELP os_system_cpu_load java.lang:name=null,type=OperatingSystem,attribute=SystemCpuLoad # TYPE os_system_cpu_load gauge os_system_cpu_load 0.10714285714285714 # HELP os_committed_virtual_memory_bytes java.lang:name=null,type=OperatingSystem,attribute=CommittedVirtualMemorySize # TYPE os_committed_virtual_memory_bytes gauge os_committed_virtual_memory_bytes 3.57505024E9 # HELP os_system_load_average java.lang:name=null,type=OperatingSystem,attribute=SystemLoadAverage # TYPE os_system_load_average gauge os_system_load_average 0.17 # HELP os_free_physical_memory_bytes java.lang:name=null,type=OperatingSystem,attribute=FreePhysicalMemorySize # TYPE os_free_physical_memory_bytes gauge os_free_physical_memory_bytes 6.509023232E9 # HELP os_available_processors java.lang:name=null,type=OperatingSystem,attribute=AvailableProcessors # TYPE os_available_processors gauge os_available_processors 2.0 # HELP os_free_swap_space_bytes java.lang:name=null,type=OperatingSystem,attribute=FreeSwapSpaceSize # TYPE os_free_swap_space_bytes gauge os_free_swap_space_bytes 4.160745472E9 # HELP jmx_scrape_duration_seconds Time this JMX scrape took, in seconds. # TYPE jmx_scrape_duration_seconds gauge jmx_scrape_duration_seconds 0.001119413 # HELP jmx_scrape_error Non-zero if this scrape failed. # TYPE jmx_scrape_error gauge jmx_scrape_error 0.0 # HELP jmx_scrape_cached_beans Number of beans with their matching rule cached # TYPE jmx_scrape_cached_beans gauge jmx_scrape_cached_beans 0.0 # HELP jvm_buffer_pool_used_bytes Used bytes of a given JVM buffer pool. # TYPE jvm_buffer_pool_used_bytes gauge jvm_buffer_pool_used_bytes{pool=&quot;direct&quot;,} 8192.0 jvm_buffer_pool_used_bytes{pool=&quot;mapped&quot;,} 0.0 # HELP jvm_buffer_pool_capacity_bytes Bytes capacity of a given JVM buffer pool. # TYPE jvm_buffer_pool_capacity_bytes gauge jvm_buffer_pool_capacity_bytes{pool=&quot;direct&quot;,} 8192.0 jvm_buffer_pool_capacity_bytes{pool=&quot;mapped&quot;,} 0.0 # HELP jvm_buffer_pool_used_buffers Used buffers of a given JVM buffer pool. # TYPE jvm_buffer_pool_used_buffers gauge jvm_buffer_pool_used_buffers{pool=&quot;direct&quot;,} 1.0 jvm_buffer_pool_used_buffers{pool=&quot;mapped&quot;,} 0.0 # HELP jvm_memory_objects_pending_finalization The number of objects waiting in the finalizer queue. # TYPE jvm_memory_objects_pending_finalization gauge jvm_memory_objects_pending_finalization 0.0 # HELP jvm_memory_bytes_used Used bytes of a given JVM memory area. # TYPE jvm_memory_bytes_used gauge jvm_memory_bytes_used{area=&quot;heap&quot;,} 2.38314152E8 jvm_memory_bytes_used{area=&quot;nonheap&quot;,} 5.160628E7 # HELP jvm_memory_bytes_committed Committed (bytes) of a given JVM memory area. # TYPE jvm_memory_bytes_committed gauge jvm_memory_bytes_committed{area=&quot;heap&quot;,} 5.19569408E8 jvm_memory_bytes_committed{area=&quot;nonheap&quot;,} 5.2822016E7 # HELP jvm_memory_bytes_max Max (bytes) of a given JVM memory area. # TYPE jvm_memory_bytes_max gauge jvm_memory_bytes_max{area=&quot;heap&quot;,} 1.823473664E9 jvm_memory_bytes_max{area=&quot;nonheap&quot;,} 1.3631488E8 # HELP jvm_memory_bytes_init Initial bytes of a given JVM memory area. # TYPE jvm_memory_bytes_init gauge jvm_memory_bytes_init{area=&quot;heap&quot;,} 1.28145152E8 jvm_memory_bytes_init{area=&quot;nonheap&quot;,} 2.4576E7 # HELP jvm_memory_pool_bytes_used Used bytes of a given JVM memory pool. # TYPE jvm_memory_pool_bytes_used gauge jvm_memory_pool_bytes_used{pool=&quot;Code Cache&quot;,} 3370048.0 jvm_memory_pool_bytes_used{pool=&quot;PS Eden Space&quot;,} 1.78591736E8 jvm_memory_pool_bytes_used{pool=&quot;PS Survivor Space&quot;,} 2.4223408E7 jvm_memory_pool_bytes_used{pool=&quot;PS Old Gen&quot;,} 3.5499008E7 jvm_memory_pool_bytes_used{pool=&quot;PS Perm Gen&quot;,} 4.8236232E7 # HELP jvm_memory_pool_bytes_committed Committed bytes of a given JVM memory pool. # TYPE jvm_memory_pool_bytes_committed gauge jvm_memory_pool_bytes_committed{pool=&quot;Code Cache&quot;,} 4063232.0 jvm_memory_pool_bytes_committed{pool=&quot;PS Eden Space&quot;,} 4.09468928E8 jvm_memory_pool_bytes_committed{pool=&quot;PS Survivor Space&quot;,} 2.4641536E7 jvm_memory_pool_bytes_committed{pool=&quot;PS Old Gen&quot;,} 8.5458944E7 jvm_memory_pool_bytes_committed{pool=&quot;PS Perm Gen&quot;,} 4.8758784E7 # HELP jvm_memory_pool_bytes_max Max bytes of a given JVM memory pool. # TYPE jvm_memory_pool_bytes_max gauge jvm_memory_pool_bytes_max{pool=&quot;Code Cache&quot;,} 5.0331648E7 jvm_memory_pool_bytes_max{pool=&quot;PS Eden Space&quot;,} 6.31242752E8 jvm_memory_pool_bytes_max{pool=&quot;PS Survivor Space&quot;,} 2.4641536E7 jvm_memory_pool_bytes_max{pool=&quot;PS Old Gen&quot;,} 1.367343104E9 jvm_memory_pool_bytes_max{pool=&quot;PS Perm Gen&quot;,} 8.5983232E7 # HELP jvm_memory_pool_bytes_init Initial bytes of a given JVM memory pool. # TYPE jvm_memory_pool_bytes_init gauge jvm_memory_pool_bytes_init{pool=&quot;Code Cache&quot;,} 2555904.0 jvm_memory_pool_bytes_init{pool=&quot;PS Eden Space&quot;,} 3.2505856E7 jvm_memory_pool_bytes_init{pool=&quot;PS Survivor Space&quot;,} 5242880.0 jvm_memory_pool_bytes_init{pool=&quot;PS Old Gen&quot;,} 8.5458944E7 jvm_memory_pool_bytes_init{pool=&quot;PS Perm Gen&quot;,} 2.2020096E7 # HELP jvm_memory_pool_collection_used_bytes Used bytes after last collection of a given JVM memory pool. # TYPE jvm_memory_pool_collection_used_bytes gauge jvm_memory_pool_collection_used_bytes{pool=&quot;PS Eden Space&quot;,} 0.0 jvm_memory_pool_collection_used_bytes{pool=&quot;PS Survivor Space&quot;,} 2.4223408E7 jvm_memory_pool_collection_used_bytes{pool=&quot;PS Old Gen&quot;,} 0.0 jvm_memory_pool_collection_used_bytes{pool=&quot;PS Perm Gen&quot;,} 0.0 # HELP jvm_memory_pool_collection_committed_bytes Committed after last collection bytes of a given JVM memory pool. # TYPE jvm_memory_pool_collection_committed_bytes gauge jvm_memory_pool_collection_committed_bytes{pool=&quot;PS Eden Space&quot;,} 4.09468928E8 jvm_memory_pool_collection_committed_bytes{pool=&quot;PS Survivor Space&quot;,} 2.4641536E7 jvm_memory_pool_collection_committed_bytes{pool=&quot;PS Old Gen&quot;,} 0.0 jvm_memory_pool_collection_committed_bytes{pool=&quot;PS Perm Gen&quot;,} 0.0 # HELP jvm_memory_pool_collection_max_bytes Max bytes after last collection of a given JVM memory pool. # TYPE jvm_memory_pool_collection_max_bytes gauge jvm_memory_pool_collection_max_bytes{pool=&quot;PS Eden Space&quot;,} 6.31242752E8 jvm_memory_pool_collection_max_bytes{pool=&quot;PS Survivor Space&quot;,} 2.4641536E7 jvm_memory_pool_collection_max_bytes{pool=&quot;PS Old Gen&quot;,} 1.367343104E9 jvm_memory_pool_collection_max_bytes{pool=&quot;PS Perm Gen&quot;,} 8.5983232E7 # HELP jvm_memory_pool_collection_init_bytes Initial after last collection bytes of a given JVM memory pool. # TYPE jvm_memory_pool_collection_init_bytes gauge jvm_memory_pool_collection_init_bytes{pool=&quot;PS Eden Space&quot;,} 3.2505856E7 jvm_memory_pool_collection_init_bytes{pool=&quot;PS Survivor Space&quot;,} 5242880.0 jvm_memory_pool_collection_init_bytes{pool=&quot;PS Old Gen&quot;,} 8.5458944E7 jvm_memory_pool_collection_init_bytes{pool=&quot;PS Perm Gen&quot;,} 2.2020096E7 # HELP jvm_classes_currently_loaded The number of classes that are currently loaded in the JVM # TYPE jvm_classes_currently_loaded gauge jvm_classes_currently_loaded 8198.0 # HELP jvm_classes_loaded_total The total number of classes that have been loaded since the JVM has started execution # TYPE jvm_classes_loaded_total counter jvm_classes_loaded_total 8198.0 # HELP jvm_classes_unloaded_total The total number of classes that have been unloaded since the JVM has started execution # TYPE jvm_classes_unloaded_total counter jvm_classes_unloaded_total 0.0 # HELP jmx_exporter_build_info A metric with a constant &#39;1&#39; value labeled with the version of the JMX exporter. # TYPE jmx_exporter_build_info gauge jmx_exporter_build_info{version=&quot;0.18.0&quot;,name=&quot;jmx_prometheus_javaagent&quot;,} 1.0 # HELP jvm_threads_current Current thread count of a JVM # TYPE jvm_threads_current gauge jvm_threads_current 29.0 # HELP jvm_threads_daemon Daemon thread count of a JVM # TYPE jvm_threads_daemon gauge jvm_threads_daemon 28.0 # HELP jvm_threads_peak Peak thread count of a JVM # TYPE jvm_threads_peak gauge jvm_threads_peak 31.0 # HELP jvm_threads_started_total Started thread count of a JVM # TYPE jvm_threads_started_total counter jvm_threads_started_total 33.0 # HELP jvm_threads_deadlocked Cycles of JVM-threads that are in deadlock waiting to acquire object monitors or ownable synchronizers # TYPE jvm_threads_deadlocked gauge jvm_threads_deadlocked 0.0 # HELP jvm_threads_deadlocked_monitor Cycles of JVM-threads that are in deadlock waiting to acquire object monitors # TYPE jvm_threads_deadlocked_monitor gauge jvm_threads_deadlocked_monitor 0.0 # HELP jvm_threads_state Current count of threads by state # TYPE jvm_threads_state gauge jvm_threads_state{state=&quot;NEW&quot;,} 0.0 jvm_threads_state{state=&quot;WAITING&quot;,} 14.0 jvm_threads_state{state=&quot;TIMED_WAITING&quot;,} 7.0 jvm_threads_state{state=&quot;UNKNOWN&quot;,} 0.0 jvm_threads_state{state=&quot;TERMINATED&quot;,} 0.0 jvm_threads_state{state=&quot;RUNNABLE&quot;,} 8.0 jvm_threads_state{state=&quot;BLOCKED&quot;,} 0.0 # HELP process_cpu_seconds_total Total user and system CPU time spent in seconds. # TYPE process_cpu_seconds_total counter process_cpu_seconds_total 17.38 # HELP process_start_time_seconds Start time of the process since unix epoch in seconds. # TYPE process_start_time_seconds gauge process_start_time_seconds 1.749808021796E9 # HELP process_open_fds Number of open file descriptors. # TYPE process_open_fds gauge process_open_fds 84.0 # HELP process_max_fds Maximum number of open file descriptors. # TYPE process_max_fds gauge process_max_fds 4096.0 # HELP process_virtual_memory_bytes Virtual memory size in bytes. # TYPE process_virtual_memory_bytes gauge process_virtual_memory_bytes 3.575046144E9 # HELP process_resident_memory_bytes Resident memory size in bytes. # TYPE process_resident_memory_bytes gauge process_resident_memory_bytes 6.88590848E8 # HELP jmx_config_reload_failure_total Number of times configuration have failed to be reloaded. # TYPE jmx_config_reload_failure_total counter jmx_config_reload_failure_total 0.0 # HELP jmx_config_reload_success_total Number of times configuration have successfully been reloaded. # TYPE jmx_config_reload_success_total counter jmx_config_reload_success_total 0.0 # HELP jvm_memory_pool_allocated_bytes_total Total bytes allocated in a given JVM memory pool. Only updated after GC, not continuously. # TYPE jvm_memory_pool_allocated_bytes_total counter jvm_memory_pool_allocated_bytes_total{pool=&quot;PS Survivor Space&quot;,} 3.523552E7 jvm_memory_pool_allocated_bytes_total{pool=&quot;Code Cache&quot;,} 3718208.0 jvm_memory_pool_allocated_bytes_total{pool=&quot;PS Perm Gen&quot;,} 4.5692072E7 jvm_memory_pool_allocated_bytes_total{pool=&quot;PS Eden Space&quot;,} 1.43917056E9 jvm_memory_pool_allocated_bytes_total{pool=&quot;PS Old Gen&quot;,} 3.5499008E7 # HELP jvm_gc_collection_seconds Time spent in a given JVM garbage collector in seconds. # TYPE jvm_gc_collection_seconds summary jvm_gc_collection_seconds_count{gc=&quot;PS Scavenge&quot;,} 11.0 jvm_gc_collection_seconds_sum{gc=&quot;PS Scavenge&quot;,} 0.15 jvm_gc_collection_seconds_count{gc=&quot;PS MarkSweep&quot;,} 0.0 jvm_gc_collection_seconds_sum{gc=&quot;PS MarkSweep&quot;,} 0.0 # HELP jmx_config_reload_failure_created Number of times configuration have failed to be reloaded. # TYPE jmx_config_reload_failure_created gauge jmx_config_reload_failure_created 1.749808021823E9 # HELP jmx_config_reload_success_created Number of times configuration have successfully been reloaded. # TYPE jmx_config_reload_success_created gauge jmx_config_reload_success_created 1.749808021822E9 # HELP jvm_memory_pool_allocated_bytes_created Total bytes allocated in a given JVM memory pool. Only updated after GC, not continuously. # TYPE jvm_memory_pool_allocated_bytes_created gauge jvm_memory_pool_allocated_bytes_created{pool=&quot;PS Survivor Space&quot;,} 1.749808022447E9 jvm_memory_pool_allocated_bytes_created{pool=&quot;Code Cache&quot;,} 1.749808022448E9 jvm_memory_pool_allocated_bytes_created{pool=&quot;PS Perm Gen&quot;,} 1.749808022448E9 jvm_memory_pool_allocated_bytes_created{pool=&quot;PS Eden Space&quot;,} 1.749808022448E9 jvm_memory_pool_allocated_bytes_created{pool=&quot;PS Old Gen&quot;,} 1.749808022448E9
最新发布
06-14
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值