############### 关于java内存中静态区域(static)的问题 ###############(问题解决另100分相送)

hpq852 2004-10-27 12:18:06
假如有一个web容器,当我在这个容器里执行了一个Servlet,而这个Servlet初始 化了一个静态的对象,那么以后我在执行这个servlet的时候,这个静态方法就不用再次初始化了,因为上次执行已经初始化了该静态对象,该静态对象已经常驻内存的静态区域,知道容器关闭为止。

而对于一个Application来说,此时没有容器,只是一个简单的java程序,我同样执行一个java程序,让这个java程序来初始化一个静态对象,同样此时静态对象也会创建于静态区域,但是问题是,当我程序执行结束时候该静态对象也就不存在了,当我再次执行这个java程序的时候,还必须再次创建这个静态对象,也就是说当我执行10次这个java程序的时候,就会创建10次静态对象,但在web容器里却只是创建一次而已,以后就直接利用上次创建的那个就可以了

用代码说明如下:
public class Hello
{
private static String str;
public static void doTest()
{
if(str==null)
{
str = "Hello";
System.out.println("init str......" +str);
}

}
}
如果这段代码运行与web容器内,而且运行10次,那么web容器只会打印出一条"init str......Hello"
而如果只是简单的用jb或是cmd运行这段程序的话,就会打印出来10条语句,

我的问题是web容器是如何实现每次执行的时候都共享静态区域呢,而在Application中又该如何实现象web容器那样共享静态区域呢?也就是说静态对象我只创建一次,以后每次在运行的话,就不在创建了,而是运用以前创建的那个呢?或者谁可以说一下static创建的原理呢?如何才可以共享呢?让静态区域不随着程序运行的结束而消失呢?象web容器那样?
...全文
185 点赞 收藏 15
写回复
15 条回复
切换为时间正序
请发表友善的回复…
发表回复
eureka0891 2004-12-30
楼主这么做有什么原因吗?
用序列化可能可以解决楼主的问题.
回复
chgLin 2004-12-29
顶!!
回复
gutensu 2004-12-29
我觉得是这样:web app中jvm一直运行,所以只有一份的静态区一直存在

而在app中,你在控制台中输入:java Hello
这时候jvm的一个实例也会启动,随后就是jvm读取byte code, 分配内存,开始执行,main方法结束后,jvm也就退出。

当你再次在控制台中输入:java Hello
就会重复上述过程,所以那句话还会打印
回复
fireflyqt 2004-12-29
这个恐怕不行吧,servlet可以是因为其容器一直运行着,所以已经加载过的类不用再重新加载,如果你重新启动容器的话,所有静态数据也一样要重新生成。
而一个应用程序和一个容器属于同一级,如果你想实现这个的话,那么也要有个应用程序来一直维持这些已经加载的类,不然它是不会孤立而且还一直存在的。
回复
classjava 2004-12-29
帮up
回复
pmaster 2004-12-29
我不知道,但可以帮你UP几下
回复
coolroy2000 2004-12-29
很简单,持久化,就可以模拟web容器的运行了哈
回复
zairwolfi 2004-10-28
,+***+,
,*********, , ,@@,
.****+++****,*: ,WW.
,***:.,,,.+****+ ,WW.
***., ,:***+ ,WW.
.**: ****+ ,WW.
+*+, ,.+++. :@@*, +@@:,WW.*@*.#@:
**: ,,,,,WWWWWW: ,WWWWWWWW.#WWWWWWW,+++,
,**: @WW@*WW. WWW**WWWW.#WWW#*WW* ::
,**: WWW*,.., #WW:,,.@WW.#WW+.,+WW,. .
+*+, .WWWW+, WW+, .WW.#W@. .WW,+#
.**, ,:WWWWW:,WW: ,WW.#W@, .WW,@@,
,***, ., ,.:#WWW.WW*, .WW.#W#, .WW.#+,
.***, +**, +,,,WWW:+WW. WWW.#W#, .WW. ,
,.*****+*****. WWWWWWW.,WWWWWWWWW.#W#, .WW,**,
,.********+., :WWWWWW+, .@WWWW@WW.#W#, .WW,**
,.+++++:, ,.:++:., ,:++:.++..++, ,++,,,
,,,,, ,,,, ,,, ,,,,,, ,,
用http://bbs.soulsky.net/pub/ascii/做的。
回复
追求自由 2004-10-27
程序启动时才会给它分配堆、栈、静态存储区这些内存空间,程序结束后再次运行,当然就是重新分配了。你重新启动web server,它也是要重新分配的。
回复
hpq852 2004-10-27
web容器中,确实是jvm从来没有关闭,所以静态变量一直存在,所以无论客户端运行多少次,始终是只创建一次静态对象,这种情况是所有线程共享一个静态区,而在application中是每个线程都有一个独自的静态区,所以才会出现每运行一次application都会创建一次静态对象。

其实你上面写的那个程序,如果程序运行结束后再次运行的话,还是会打印出"init str......Hello"
而我想要的结果是再次运行的话就不打印这个语句了,因为静态对象在上次运行的时候已经创建,所以if(str==null)不成立,不知道能不能实现。
回复
jackkui 2004-10-27
在应用程序中,有专门的静态区来存放静态的变量和方法,当你一个类初始化时,里面如果有静态变量或者方法,那么它先看静态区中有没有这个静态变量,如果有的话,直接使用这个变量,如果没有则在静态区中申请新的空间来存储变量,所以引用的时候,如果修改了一个类的静态变量,再次申请一个新的类实例时他的静态变量的值,和原有的实例的值是相同的。但是在applacation中,每个变量的生命周期不同,所以不是所有的静态变量都能像Web中那样,我觉得Web中就好像一个程序始终在运行着,所以创建的实例始终在内存中,和Scope相关,如果你要在Applacation中使用静态变量像在Web中一样,你要保证你的静态实例不被destroy。
这是我的理解。
你的例子改成这样就只打印一次了。
public class Hello
{
private static String str;
public static void doTest()
{
if(str==null)
{
str = "Hello";
System.out.println("init str......" +str);
}

}
public static void main(String[] args){
Hello h1 = new Hello();
h1.doTest();
Hello h2 = new Hello();
h2.doTest();
}
}
回复
smagt 2004-10-27
照楼主的意思,只能把你想要一直保存在内存中的静态内容写在一个线程中,让其一直运行,当然如果destroy了这个线程,照样得重新初始化。
回复
Sunboyjava 2004-10-27
帮你顶。。。。。学习
回复
朋友别哭 2004-10-27
up
回复
hpq852 2004-10-27
up
回复
发动态
发帖子
Web 开发
创建于2007-09-28

7.9w+

社区成员

Java Web 开发
申请成为版主
社区公告
暂无公告