java静态资源(静态方法,静态属性)是程序一运行就加载到jvm中,还是当被调用的时候才进行加载呢

java静态资源(静态方法,静态属性)是程序一运行就加载到jvm中,还是当被调用的时候才进行加载呢,第1张

当类第一次被调用时加载(静态方法,静态属性的加载就是类加载) 。

1、类中的静态属性会被加入到类对象(也可以叫做类的模板,是类的描述) 的构造器中,静态方法也会被加入到类对象中。

2、当第一次使用类时,JVM会通过类加载器,加载类对象,从而初始化静态属性,并装入类的方法,包括静态方法和实例方法(方法不会被调用,只是加载,从这个意义上来说,静态方法和实例方法是类似的)。

3、当创建类的实例对象时,JVM会调用类的构造器,从而初始化类的属性。

扩展资料:

类(包括静态方法、属性)加载过程:

一、加载。

根据一个类的全限定名(如cneduhdutestHelloWorldclass)来读取此类的二进制字节流到JVM内部。

将字节流所代表的静态存储结构转换为方法区的运行时数据结构(hotspot选择将Class对象存储在方法区中,Java虚拟机规范并没有明确要求一定要存储在方法区或堆区中)转换为一个与目标类型对应的javalangClass对象。

二、连接。

1、验证。

验证阶段主要包括四个检验过程:文件格式验证、元数据验证、字节码验证和符号引用验证;

2、准备。

为类中的所有静态变量分配内存空间,并为其设置一个初始值(由于还没有产生对象,实例变量将不再此 *** 作范围内);

3、解析。

将常量池中所有的符号引用转为直接引用(得到类或者字段、方法在内存中的指针或者偏移量,以便直接调用该方法)。这个阶段可以在初始化之后再执行。

参考资料:

百度百科--Java类加载器

百度百科--JVM

;我们在深入Java核心系列文章中给大家讲过JVM中的栈和局部变量 在做Java开发的时候常用的JVM内存管理有两种 一种是堆内存 一种是栈内存 堆内存主要用来存储程序在运行时创建或实例化的对象与变量 例如 我们通过new MyClass()创建的类MyClass的对象 而栈内存则是用来存储程序代码中声明为静态(或非静态)的方法 下面我给大家举个例子  就拿上面的例子来说 放在栈内存中的有 main makeThings 放在堆内存中有 Test list object JVM中对象的生命周期大致可以分为 个阶段 创建阶段 应用阶段 不可视阶段 不可到达阶段 可收集阶段 终结阶段与释放阶段 创建阶段 ( )为对象分配存储空间 ( )开始构造对象 ( )递归调用其超类的构造方法 ( )进行对象实力初始化与变量初始化 ( )执行构造方法体 还有就是你在创建对象的时候需要注意的地方 ( )避免在循环体中创建对象 即使该对象占用内存空间不大 ( )尽量及时使对象符合垃圾回收标准 ( )不要采用过深的继承层次 ( )访问本地变量优于访问类中的变量 应用阶段 在应用阶段涉及到 个引用 ( )强引用 是指JVM内存管理器从根引用集合出发遍寻堆中所有到达对象的路径 ( )软引用 是具有较强的引用功能 只有当内存不够的时候 才回收这类内存 因此内存足够的时候 不会被回收 ( )弱引用 弱引用与软引用对象的最大不同在于 GC在进行回收时 需要通过算法检查是否回收软引用对象 而对于弱引用来说 GC总是进行回收 ( )虚引用 主要用于辅助finalize函数的使用 虚引用主要适用于以某种比Java终结机制更灵活的方式调度pre mortem清除 *** 作

不可视阶段 先看一段代码 如果一个对象已使用完了 应该主动将其设置为null 可以在上面的代码行obj doSomething();下添加代码行obj=null;这样一行代码强制将obj对象置为空值 这样做的意义就是帮助JVM及时的发现这个垃圾对象 并且可以及时的回收该对象占用的系统资源 不可到达阶段 处于不可到达阶段的对象 在虚拟机所管理的对象引用根集合中再也找不到直接或间接的强引用 这些对象通常是指多有线程栈中的临时变量 所有已装载的类的静态变量或者对本地代码接口(JNI)引用 可收集阶段 终结阶段与释放阶段 当对象处于这个阶段的时候 可能处于下面三种情况 ( )垃圾回收器发现该对象已经不可到达 ( )finalize方法已经被执行 ( )对象空间已被重用 当对象处于上面三种清空的时候 虚拟机就可以直接将该对象回收了 析构方法finalize 前面我们说了JVM的垃圾回收机制和JVM中对象的生命周期 今天给大家讲个方法 叫做析构方法finalize 我想搞过C++的人都知道 而且是内存管理技术中相当重要的一部分 但是 在Java中好像没有这个概念 这是因为 理论上JVM负责对象的析构(销毁与回收)工作 finalize是Object类中的一个方法 并且是protected 由于所有的类都继承了Object对象 因此 就都隐式的继承了改方法 不过可以重写这个方法 如果重写此方法 最后一句必须写上super finalize()语句 因为finalize方法没有自动实现递归调用 那我们在什么时候要重写它呢?当有一些不容易控制并且非常重要的资源时 要放到finalize方法中 例如 一些I/O的 *** 作 数据的连接等等 这些资源的释放对整个应用程序是非常关键的 我先让大家看一段代码  finalize方法最终是由JVM中的垃圾回收器调用的 由于垃圾回收器调用finalize的时间是不确定或者不及时的 调用时机对我们来说是不可控的 因此我们可以在自己的类中声明一个destory()方法 在这个方法中添加释放系统资源的处理代码 但是还是建议你将对destroy()方法的调用放入当前类的finalize()方法体中 因为这样做更保险 更安全

静态变量 我们知道类中的静态变量在程序运行期间 其内存空间对所有该类的对象实例而言是共享的 为了节省系统内存开销 共享资源 应该将一些变量声明为静态变量 通过下面的例子 你就会发现有什么不同 代码一 代码二   我想大家应该发现上面那两个类的区别了吧!

代码一会在内存中保存 个weeks的副本 而代码二则在内存中保存 个weeks的副本 然后共享该副本 这样的话就不会造成内存的浪费 虽然静态的变量能节约大量的内存 但是并不是所有的地方都适合用 建议大家在下列条件都符合的情况下 尽量用静态变量 ( )变量所包含的对象体积较大 占用内存较多 ( )变量所包含的对象生命周期较长 ( )变量所包含的对象数据稳定 ( )该类的对象实例有对该变量所包含的对象的共享需求 如果变量不具备上述特点 建议不要轻易使用静态变量 以免弄巧成拙 最后 再提一点内存的优化 就是有关对象的重用 比如 对象池和数据库连接池等 那样的话 是很节约内存空间的 不过 在用的时候要考虑各个方面 比如 运行环境的内存资源的限制等 为了防止对象池中的对象过多 要记得清除 内存管理有许多技巧和方式 其实内存管理有许多技巧和方式 在这 我给大家介绍一下 ( )要尽早的释放无用对象的引用 如果 该对象不用了 你可以把它设置为null 但要注意 如果该对象是某方法的返回值 千万不要这样处理 否则你从该方法中得到的返回值永远为空 而且这种错误不易被发现 因此这时很难及时抓住 排除NullPointerException异常 ( )尽量少用finalize函数 因为它会加大GC的工作量 因此尽量少用finalize方式回收资源 ( )如果需要使用经常用到的 可以使用soft应用类型(也就是转换为软引用类型) 它可以尽可能将保存在内存中 供程序调用 而不引起OutOfMemory ( )注意集合数据类型 包括数组 树 图 链表等数据结构 这些数据结构对于GC来说 回收更为复杂 另外 要注意那些全局变量 静态变量 这些对象往往容易引起悬挂对象 造成内存浪费 ( )尽量避免在类的默认构造器中创建 初始化大量的对象 防止在调用其子类的构造器时造成不必要的内存资源浪费 ( )尽量避免强制系统做垃圾内存回收(通过显式调用方法System gc()) 增长系统做垃圾回收的最终时间 降低系统性能 ( )尽量避免显式申请数组空间 当不得不显式申请数组空间时尽量准确的估计出其合理值 以免造成不必要的系统内存开销 ( )尽量在做远程方法调用(RMI)类应用开发时使用瞬间值变量 除非远程调用端需要获取该瞬间值变量的值 ( )尽量在合适的场景下使用对象池技术以提高系统的性能 缩减系统内存开销 但是要注意对象池的尺寸不易过大 及时清除无效对象释放内存资源 综合考虑应用运行环境的内存资源限制 避免过高估计运行环境所提供内存资源的数量 虽然 这些技巧提高不了多少性能 但是 在嵌入式开发 或者要求性能比较高的系统中却很有用 lishixinzhi/Article/program/Java/hx/201311/27137

jmap命令是一个可以输出所有内存中对象的工具,甚至可以将VM 中的heap,以二进制输出成文本。

打印出某个java进程(使用pid)内存内的,所有‘对象’的情况(如:产生那些对象,及其数量)。

64位机上使用需要使用如下方式:

就是替换[option]位置的参数

1、 -dump:[live,]format=b,file=<filename> 使用hprof二进制形式,输出jvm的heap内容到文件= live子选项是可选的,假如指定live选项,那么只输出活的对象到文件。

命令:

结果:

即可在/root目录打开myjmapfiletxt文件。

当然,file=后面也可以指定文件存放的目录,就可以在指定目录查看文件了。

2、 -finalizerinfo 打印正等候回收的对象的信息

命令:

结果:

Number of objects pending for finalization: 0 (等候回收的对象为0个)

3、 -heap 打印heap的概要信息,GC使用的算法,heap(堆)的配置及JVM堆内存的使用情况

命令:

结果:

4、 -histo[:live] 打印每个class的实例数目,内存占用,类全名信息 VM的内部类名字开头会加上前缀”” 如果live子参数加上后,只统计活的对象数量。

命令:

采用jmap -histo pid>alog日志将其保存,在一段时间后,使用文本对比工具,可以对比出GC回收了哪些对象。

jmap -dump:format=b,file=outfile 3024可以将3024进程的内存heap输出出来到outfile文件里,再配合MAT(内存分析工具)。

5、 -permstat 打印classload和jvm heap长久层的信息 包含每个classloader的名字,活泼性,地址,父classloader和加载的class数量 另外,内部String的数量和占用内存数也会打印出来

命令:

通过jmap和jvm之间进行通信,有两种实现方式:attach 和 SA。

attach方式,简单来说就是客户端和服务端之间的通信,客户端发送请求,主要逻辑在服务端执行,jmap相当于客户端,JVM相当于服务端。

在JVM中,有一个叫"Attach Listener"的线程,专门负责监听attach的请求,并执行对应的 *** 作。

比如现在执行"jmap -histo:live 5409",一步一步的实现如下:

1、在Jmapjava类的main函数中,对参数进行解析。

2、解析出来参数中有“-histo:live”,则执行histo方法:

"jmap -dump"实现的原理和"jmap -histo"类似,都是通过attach的方式实现,

attach API的实现方式是:

1、客户端连接到目标JVM,向其发出一个类似“inspectheap”命令;

2、目标JVM接收到命令,执行JVM内相关函数,将收集到的结果以文本形式返回;

3、客户端接收到返回的文本并将其显示出来

假如执行"jmap -heap 5409",就不会使用attach方式实现了。

在参数解析中,如果参数是"-heap|-heap:format=b|-permstat|-finalizerinfo"中的一种,或者添加了"-F",比如"jmap -histo -F 5409",则使用SA的方式。

SA方式,和attach方式不同的是,相关的主要逻辑都在SA中实现,从JVM中获取数据即可。

可以大概看下"jmap -heap"的实现,对应的实现类是"HeapSummary",内部通过BugSpotAgent工具类attach到目标VM

执行jmap -heap有些时候可能会导致进程变T,一般是有一个线程在等信号量,这时会block住其它所有线程,可以执行kill -CONT <pid>进行恢复,不过还是强烈建议别执行这个命令。

可看到jvm线程少说几百,多则几千甚至过万,并且如果服务不重启,可发现线程数随着时间的推移持续上升,并且没有下降趋势,因此可以看出服务中一定有某些编码没有使用线程池,在持续的new Thread()创建线程,导致线程数飙升。

由于线上服务是云部署,在我们公司开发是没有权限登录服务终端查看应用jvm情况,包括线程信息,所以给定位带来的很多困难。

起初我们定位问题方案是通过测试环境开启Spring Actuator监控,通过访问 /actuator/threaddump获取运行时的线程dump信息,相当于直接在终端执行jstack命令获取jvm线程信息。然后在测试环境观察线程数量变化,通过几次的对比去判断哪些线程名在持续飙升,进而定位问题。

无奈。就开始实现二套方案,直接找运维配合导出线上实例机器上的jvm-thread dump文件,然后直接分析thread-dump文件定位问题,文件大致内容如下。

>

以上就是关于java静态资源(静态方法,静态属性)是程序一运行就加载到jvm中,还是当被调用的时候才进行加载呢全部的内容,包括:java静态资源(静态方法,静态属性)是程序一运行就加载到jvm中,还是当被调用的时候才进行加载呢、技术分享 把JVM移植到ARM环境中、jmap命令详解----查看JVM内存使用详情等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/web/9570988.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2023-04-29
下一篇2023-04-29

发表评论

登录后才能评论

评论列表(0条)

    保存