1
yonka 2015-10-19 10:55:06 +08:00 1
java 里没有全局变量,所以从可达性来说,你的 v 估计会被回收吧。
除非在线程 local 、静态属性、 spring context 等中... |
2
zjengjie 2015-10-19 11:16:30 +08:00 2
进程退出后,内存会被操作系统回收。
|
3
anexplore 2015-10-19 11:25:14 +08:00
不存在了;这里面的泄露是发生在 jvm 管理的堆里面,其实你在程序中将 v = null;就可以通过 gc 回收内存了
|
4
iyangyuan 2015-10-19 11:45:15 +08:00 via iPhone
进程? jvm 进程在一个容器里只有一个,楼主应该是在说线程,线程退出后很可能还存在,否则就不会泄露了具体看你代码怎么写,很难一概而论。
|
5
RangerWolf OP @iyangyuan 比如在 linux 里面, 使用 top 命令 看到 command 列 不止一个 java~ 这是进程还是线程?
|
6
HunterPan 2015-10-19 13:42:57 +08:00
@RangerWolf 进程
|
7
iShao 2015-10-19 14:53:05 +08:00 via Android
学过 java 但是怎么这段代码看不懂了…现在用 OC
|
8
Cloudee 2015-10-19 15:01:20 +08:00 via iPhone
就这段代码而言,什么时候 v 释放了,里面东西就释放了
|
9
cnhongwei 2015-10-19 15:02:20 +08:00 1
@RangerWolf JVM 只有一个进程,是多线程的,在 Linux 中看到多个进程,是因为 Linux 使用多进程来模拟多线程的(不要以为这个代价高、性能低哟)。
回复楼主的就是 最重要的是 v 你放到什么地方了,只是没有放到静态属性中(或其它类似的地方,如 web 应用中 application , spring 中的 context)中就行了。 java gc 时,大部分的垃圾回收器,都是从在使用的类与实例开始遍历,遍历完后,没有被遍历上的实例都认为是没有用的,直接全部回收就行了。 |
10
Cloudee 2015-10-19 15:02:42 +08:00 via iPhone
另外进程退出所有的内存和文件句柄都会被操作系统释放掉,这个是和 java 没关系的
|
11
domty 2015-10-19 15:06:44 +08:00 1
不好说啊,说句废话, java 的垃圾回收主要依赖 jvm 的实现。
所以回收的时机本身是不确定的。当你的这段代码块执行结束后,代码块内的对象没有在代码中没有被引用的话,应该就是处于一个待回收的状态。如何没有手动触发 GC 的方法的话,是不知道 jvm 是何时回收这部分内存的。 好久以前看过的一部分 java 虚拟机知识了,所以有点记不到了,不确定说的是不是对的.. |
13
RangerWolf OP @cnhongwei 那 JVM 在 windows 之中呢? 应该是多进程了吧? 原来多个 java 是模拟出来的,第一次知道,学习了。。。
另外,那比如 public static final String a = 'aaaa' 类似这种变量,会内存泄漏吗? |
14
RangerWolf OP @domty 想问下 你是从哪边看的资料? 我也去学习学习,多谢!
|
15
honam 2015-10-19 22:19:48 +08:00
弱弱的问句,即使程序不退出,也不会造成内存泄露吧? v add 的不是 o 的引用而已嚒, o 为 null 了那 v 里面全是 null 喇不是吗?菜鸟一只大神勿喷,求解
|
18
CRVV 2015-10-19 23:14:19 +08:00
@honam
我印象中 Vector 在非远古版本的 Java 里,就是一个线程安全的 ArrayList 其实写一下就明白了,下面输出 45 和 null Integer a = 45; Integer b = a; b = null; System.out.println(a); System.out.println(b); 等价的 C 代码是: int a = 45; int* x = &a; int* y = x; y = NULL; 这并不是一个问题,很多语言都是这么设计的,只不过通常不像 Java 一样非要把这种变量类型叫“引用” |
19
rundis 2015-10-20 07:56:27 +08:00 via iPhone
进程退出之后是肯定不能够泄露的,都被回收了
运行中想回收掉 v 就直接 v = null 建议不要 System.gc()跑 gc 另外 vector 和 arraylist 有点不同,属于遗留集合了吧,看看接口都不是常用的集合接口的 |
20
cnhongwei 2015-10-20 09:06:10 +08:00 1
@RangerWolf 不好意思,上面说的有误, Linux 线程实现有几种,其中一种是使用进程来模拟线程,但使用 ps 看到的还是一个进程。
public static final String a = 'aaaa' ,这种,类加载器会把 'aaaa' 放到常量池中,类加载后,内存就不会释放,但不算是内存泄漏,这是因为:我们说的内存泄漏,主要是指动态分配了内存,不再需要的时候,应能释放,如果没有办法释放,就算内存泄漏,所以,比如一些程序就需要很大的内存空间,但这是正常使用,就不算内存泄漏。 如果连接池之类的这种池化技术,就是让一些资源不释放,使得下一次使用的时候速度更快,这就是故意这样设计的,这就不算内存泄漏。 但如果我是做一个程序,把文件文件中行读到一个 List 中去,使用完后,这个数据没有用了,应释放,但因为自己到这个 List 定义到一个类的 static filed 中去了,所以不会被 gc 到,这就算内存泄漏了。 内存泄漏也是相对的, 比如程序就那么几个泄漏,程序调用一次后也没有再调用过,泄漏了也没有关系,怕的就是频繁调用的地方有泄漏,最后让 jvm crash 了,这就严重了。 写程序的时候,一般的普遍 object (除超大的 String 外),泄漏也没有什么大的关系,最容易是 jvm crash 的是,把 object 不停的加入到 Collection 中。所以写程序注意一下超长的 String 及 Collection 的应用,少使用 static 变量(常量不算内存泄漏, static 作为性能优化常用,但在现代的 jvm 优化技术下,基本没有太大的必要),一般不会内存泄漏。 |
21
RangerWolf OP @CRVV 具体我不是非常了解,应该是属于 可达 无引用?
|
22
RangerWolf OP @cnhongwei 您说的非常详细,学习到很多东西,非常感谢!
|
23
domty 2015-10-20 10:59:56 +08:00
@CRVV
java 是彻底的值传递,不存在引用传递的。 同理 java 里也没有传指针的概念。 Integer a = 10; //声明了一个 Integer 指向 Integer 型变量 10 。 Integer b = a; //声明了一个变量 b ,指向的地址和 a 指向的地址相同。 a = 20; //改变了 a 指向的地址, a 的指向为一个 20 的 Integer 型变量。这个时候 b 的指向还是 Integer 型 10 的地址。 这也是为什么 java 无法实现 swap(a,b)方法来交换两个变量的值得原因。 |
24
xiuc001 2015-10-20 11:04:19 +08:00
进程是操作系统创建的,进程没了,相应的堆栈信息都会被收回,而 java 程序是跑在这个进程中的,堆栈也是在进程的堆栈中,所以会被一起收回。。
简单的说 一起被收回~ |
25
CRVV 2015-10-20 11:23:42 +08:00 via Android
@domty
所以在你举的例子里,把所有的变量都当成指针,是不是完全符合 Java 的行为? 所以我前面用 C 的指针来类比 Java 的变量 关键是搞清楚语言的语义,至于有没有传指针的概念,我认为并不重要 |
27
sunnyhust2005 2015-10-20 15:05:26 +08:00
首先关于内存泄漏的概念需要澄清, Java 与 C/C++在这点上有很大的区别。从技术上来说, Java 不会出现 C/C++/Objective-C 所出现的内存泄漏。当在堆中分配的对象不再有指针指向时,就发生了内存泄漏;而对 Java 而言,不再有引用指向对象会被 GC 清除,所以不会有内存泄漏的问题。如果硬要认为 Java 也有内存泄漏,可以理解为“当对象的生命周期已经结束,但是有引用指向它,导致它无法被 GC 从堆中释放”。而后者和前者效果相同:都是内存中保留了不再需要的对象。
具体来看这个问题,在对局部变量 o 赋值为 null 前, Vector 对象在内部的数组里已经保存下来了 o 引用,所以不会发生 Java 意义上的内存泄漏。 |