java中的静态方法、静态类

sprouting 发布于 11/11 14:33
阅读 785
收藏 0

这应该算是基础问题了,但能答好的估计也不多,特地求教各位大佬。

java的版本以 jdk8 为准,不说之前的版本。

问题主要有几个:

1、一个普通类中的静态方法,如果不去调用它,这个时候是否已经将相关的代码加载到内存中了,或者这么说,我创建非常非常多的静态方法,是否这些都会在项目一启动就进入到了内存中,导致内存爆炸

2、一个普通类中的静态方法,我调用过后,是否就一直常驻在内存中了?

3、常驻在内存中的到底是什么东西,是变量,还是执行代码之类的什么东西?哪些会影响到内存的占用?

4、针对静态方法(比如常见的工具类)我们应该怎么设计来避免这些问题?

加载中
1
ArchitectureMaster
ArchitectureMaster

题主有这方面的想法是好的,但有点想多了。因为代码都需要加载到内存中。

一个应用程序分配的内存分为四块:代码全局栈与堆。

java编译成字节码后,你的代码也会被加载到内存中。

如果声明为static的块则表明这一块是可以由实例或其它静态成员直接访问的。而如果不标记为static则jvm不容许访问,当然也不是绝对的,有方法可以直接访问内存中非static的区域。

说白了,你的代码在内存看来只是一堆字符串,而static final的值也只是字符串的值而已。如果你用反射的方式所有的都可以读取到。

static这里可以理解成语法糖,方便你直接修改或读取代码区的内容。

但是实例成员却无法访问即或在内存的栈或堆中加载。

每个应用的内存是有限的,你代码全部都设计成static也就是你代码的大小。而一般代码的大小能有多少?一个项目几十万行代码也不过几百兆。全加载也没什么。一般几万行代码的项目则只几十兆到几兆全部加载也没什么。

你可以这样理解静态方法<= 代码总数。而默认是你的运行代码需要全部加载的。当然如果你使用了第三方的jar包,加载jar有懒加载这时就可以少加载一些代码到内存了。

其实说到内存的控制,尽量要控制的是数组及结构数量,数组是加载到栈中,而栈只有15-16k。

而流则多数是以byte[]进行操作的,这时你如果不控制好就容易内存溢出。如一次加载几十MB的文件。而不使用stream也不使用buff。

ArchitectureMaster
ArchitectureMaster
回复 @sprouting : 所谓Static相对于Dynamic而言的,系统分配一部分内存地址给应用程序后,如果这一部分内存地址的分配相对于Dynamic区静止,那就是static。如果你是做底层开发,你就明白,其实内存只要是程序可直接访问,不过是os给你加了限制。从广义上来讲static访问的就是你加载到内存中的代码文本内容的规格化。
sprouting
sprouting
按照兄弟你的意思,static只是语法糖吗?我感觉这样说还是有点问题的,我个人理解为一般的类在内存里面就是一个没充气的气球,只有在使用的时候才会吹起来,用完又放掉气,而static相关的静态类、静态方法,则是会一直存在内存中的充满气的气球。这里面的气就是填充的数据
hello_bear
hello_bear
大哥解释的清晰明了。
0
MZHS
MZHS

特高频调用的方法写成静态的,普通的写成对象调用就可以了。一般来说开发者不用关心这个,咱写那点代码,编译完还没一首歌占用的内存大呢,别慌。往往导致内存暴涨的原因都是数据不及时释放导致的,像图片,数据库数据,文件等。

sprouting
sprouting
哥,我并不担心内存爆炸,只是对上面几个问题的想搞清楚
0
凌小宇
凌小宇

如果类被使用,会被装载进内存的方法区,包括其方法代码;被装载后类可能被卸载,但很少。内存占用的大头还是堆区,方法这块不需要过多考虑。

sprouting
sprouting
单纯的静态方法不会在系统初始化的时候就装载到内存吗?我记得很早就会装载到内存中 的
0
尚浩宇
尚浩宇

1、无论是否静态,jvm加载class,解析时都会加载到内存,如果class总大小超过内存大小就会报内存溢出异常,可通过如下设置增大内存

-XX:PermSize=100M -XX:MaxPermSize=100M -XX:PrintGCDetails

2、静态方法,随class加载就常驻jvm方法区

3、变量不会常驻方法区,常驻的是方法的相关信息

4、常量改为配置或者数据库读取,静态方法改成非静态,通过DI注入使用等

404_can_fount
404_can_fount
回复 @sprouting : 说实话,你应该稍微看下jvm的理论知识,搞懂new一个对象的全过程,有了自己的思考再来问效果会更好。
尚浩宇
尚浩宇
回复 @sprouting : jvm的顺序是加载、验证、解析、初始化
sprouting
sprouting
针对第一点,是不是加载到jvm的是class而已,但如果是静态类或者方法,我记得是会进行初始化的,等于加载了实例
0
piaoyaoi
piaoyaoi

静态方法变量不会被垃圾回收机制回收

OSCHINA
登录后可查看更多优质内容
返回顶部
顶部