java应用堆空间问题

今天突然想到一个问题,我们项目用到了一个ConstantService类,这个类在spring容器初始化时创建

View Code
  1 import java.io.FileNotFoundException;
  2 import java.io.IOException;
  3 import java.net.URL;
  4 import java.util.ArrayList;
  5 import java.util.HashMap;
  6 import java.util.Iterator;
  7 import java.util.Map;
  8 import java.util.Properties;
  9 
 10 import org.apache.log4j.Logger;
 11 import org.springframework.core.io.Resource;
 12 import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
 13 import org.springframework.core.io.support.ResourcePatternResolver;
 14 
 15 public class ConstantService {
 16 
 17     private static final Logger log = Logger.getLogger(ConstantService.class);
 18     
 19     private static Map<String, String> constantsMap = null;
 20     private static String DEFAULT_FILENAME = "Constants.properties";
 21     private String configfile;
 22 
 23     public void init() {
 24         loadConstants();
 25     }
 26 
 27     private boolean loadConstants() {
 28         if (constantsMap == null)
 29             constantsMap = new HashMap();
 30         boolean retFlag = true;
 31         log.info("开始初始化常量配置!");
 32         URL files[] = genRealConfigFile();
 33         URL aurl[] = files;
 34         int i = 0;
 35         for (int j = aurl.length; i < j; ++i) {
 36             URL strFileName = aurl[i];
 37             Properties props = new Properties();
 38             try {
 39                 props.load(strFileName.openStream());
 40                 for (Iterator localIterator = props.entrySet().iterator(); localIterator
 41                         .hasNext();) {
 42                     Map.Entry entry = (Map.Entry) localIterator.next();
 43                     if (constantsMap.containsKey((String) entry.getKey()))
 44                         log.error(LoggerUtils.format(
 45                                 "常量初始化时,常量名[#1]重复。框架采用覆盖原则!",
 46                                 new String[] { (String) entry.getKey() }));
 47                     constantsMap.put((String) entry.getKey(), (String) entry
 48                             .getValue());
 49                 }
 50             } catch (FileNotFoundException e) {
 51                 retFlag = false;
 52                 log.error(LoggerUtils.format("Can't find config file:[#1]",
 53                         new String[] { strFileName.getFile() }));
 54             } catch (IOException e) {
 55                 retFlag = false;
 56                 log.error(LoggerUtils.format(
 57                         "Error when loading config file:[#1]",
 58                         new String[] { strFileName.getFile() }));
 59             }
 60         }
 61         log.info(LoggerUtils.format("常量配置初始化完毕!共[#1]个常量",
 62                 new String[constantsMap.size()]));
 63         log.info(constantsMap);
 64         return retFlag;
 65     }
 66 
 67     private URL[] genRealConfigFile() {
 68         String[] aryConfigFile = (String[]) null;
 69         if (!(StringUtils.hasText(this.configfile)))
 70             aryConfigFile = new String[] { DEFAULT_FILENAME };
 71         else
 72             aryConfigFile = StringUtils.tokenizeToStringArray(this.configfile,
 73                     ",");
 74         ArrayList tmpList = new ArrayList();
 75         String[] arrayOfString1 = aryConfigFile;
 76         int i = 0;
 77         for (int j = arrayOfString1.length; i < j; ++i) {
 78             String strResource = arrayOfString1[i];
 79             ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();
 80             try {
 81                 Resource[] resources = resourcePatternResolver
 82                         .getResources(strResource);
 83                 for (int k = 0; k < resources.length; ++k)
 84                     tmpList.add(resources[k].getURL());
 85             } catch (Exception e) {
 86                 e.printStackTrace();
 87             }
 88         }
 89         URL[] ret = new URL[tmpList.size()];
 90         return ((URL[]) tmpList.toArray(ret));
 91     }
 92 
 93       public static String getConstant(String strKey)
 94       {
 95         return StringUtils.trimText((String)constantsMap.get(strKey));
 96       }
 97 
 98       public static Map<String, String> getConstants(String strPreFix)
 99       {
100         if (!(StringUtils.hasText(strPreFix)))
101           return null;
102 
103         Map retMap = null;
104         Iterator itrKey = constantsMap.keySet().iterator();
105         while (itrKey.hasNext()) {
106           String strTmpKey = (String)itrKey.next();
107           if (strTmpKey.startsWith(strPreFix + ".")) {
108             if (retMap == null)
109               retMap = new HashMap();
110 
111             retMap.put(strTmpKey.substring(strPreFix.length() + 1), (String)constantsMap.get(strTmpKey));
112           }
113         }
114 
115         return retMap;
116       }
117       
118     public static Map getConstantsMap() {
119         return constantsMap;
120     }
121 
122     public static void setConstantsMap(Map constantsMap) {
123         ConstantService.constantsMap = constantsMap;
124     }
125 
126     public static String getDEFAULT_FILENAME() {
127         return DEFAULT_FILENAME;
128     }
129 
130     public static void setDEFAULT_FILENAME(String default_filename) {
131         DEFAULT_FILENAME = default_filename;
132     }
133 
134     public String getConfigfile() {
135         return configfile;
136     }
137 
138     public void setConfigfile(String configfile) {
139         this.configfile = configfile;
140     }
141 }
1     <!-- 初始化加载文本 -->
2     <bean class="com.cvicse.jaf.utils.ConstantService"
3         init-method="init">
4         <!-- 初始化和加载常量文件 -->
5         <property name="configfile"
6             value="constant/Constants*.properties" />
7     </bean>

在项目的其它很多地方都用到了类似如下的代码

1 String jmsIp = ConstantService.getConstant("jmsIp");
2 String uuapJmsUserName = ConstantService.getConstant("uuapJmsUserName");
3 String uuapJmsPwd = ConstantService.getConstant("uuapJmsPwd");

我是这样理解的ConstantService这个类在spring容器初始化后单例模式实例化,且在spring容器存活期间一直持有,那么这个类在spring容器的生命周期里只会

加载一次,且一直被容器持有。

然后我又想,因为对象是保存在堆内存中的,也就是说整个项目会使用同一个堆,以前因为项目在导出excel数据过多时,而导致堆内存不足,手动设置过开发使用的tomcat生产使用的和websphere,jvm内存大小,如下:

tomcat
 -Xms800m -Xmx800m -XX:PermSize=64M -XX:MaxNewSize=512m -XX:MaxPermSize=256m
Websphere
在应用程序服务器>server1>进程定义>Java虚拟机>配置里面设置初始堆大小和最大堆大小

而我重写一个带main方法的java类,run as Java Application,调用这个ConstantService的静态属性,并不会得到已经配置过的静态属性

然后我就想了是不是我们的jvm可以创建多个jvm实例,而整个tomcat就是一个jvm实例,我新创建的这个带main方法的类运行时也会唯一对应一个jvm实例,唯一对应自己的堆空间。

然后我查了下,百度知道上有个人的回答基本吻合了我的想法。

Java项目跟jvm进程数量没什么直接关系。通常我们用java 命令运行一个程序就会启动一个jvm进程,就是你所说的jvm实例。可以看看tomcat的启动脚本(非常复杂),但最终是通过一个java命令启动tomcat容器。webapp运行于tomcat容器基础之上,和tomcat同属于一个jvm进程是必然的。至于spring,容器的概念更多是逻辑上的,它仅仅是一个类(ApplicationContext,BeanFactory)的实例。web应用启动时加载一个WebApplicationContext实例,即我们所说的spring容器
追问
按你的意思理解 一个程序启动一个jvm实例,一个项目能保证在一个jvm里面吗 
另外 如果一个tomcat加载n各项目 他们之间彼此调用(比如通过http访问),是不是跨jvm?
谢谢
回答
同一个项目可以部署在多台机器上,通过代理服务器转发请求给不同机器处理。这样就是个简单地web集群了。同一个tomcat下部署地应用自然是在一个jvm里。至于你说地通过http访问,其实只通过客户端通过http协议发起地,并不是服务器之间地调用关系。相当于客户端地两个请求

 

 

我使用

posted @ 2013-05-02 12:16  javahuang  阅读(925)  评论(0编辑  收藏  举报