一、war包中的文件的读取
在开发J2EEWeb应用时,在开发阶段通常采用目录的部署方式,而在正式运行时通常把web应用打包为单个的.war文件进行方便地部署。也就是在你的应用目录(比如WebLogic的DefaultWebApp)下,执行下面的命令:
这样,要部署到正式系统时就非常方便,只需要把这个.war文件拷贝到WebLogic的applications目录或Tomcat的webapps目录下即可自动进行部署。Tomcat会对部署的.war应用包进行自动监控、解包,所以不会出现下面提到的问题。而WebLogic并不会自动解包.war,所以如果在你的应用中,需要读取原来应用中的配置文件或其它资源文件时,就会发现,在解包部署时,正常运行的程序,在WebLogic中打包部署时,运行却出错,会报告找不到该文件。例如下面的应用:
[pre]|--DefaultWebApp
|--index.jsp
|--.....jsp
|--WEB-INF
|--web.xml
|--log4j.properties
|--classes
......[/pre]
其中使用到了Log4J作为日志输出工具,Log4J的配置文件log4j.propertes放在DefaultWebApp\WEB-INF目录下。Log4J通过一个自动加载的Servlet进行初始化,初始化代码如下:
-
ServletContextcontext=getServletContext();
-
org.apache.log4j.PropertyConfigurator.configure(context.getRealPath("/")+
- "/WEB-INF/log4j.properties");
其中,context.getRealPath("/")得到当前Web应用的真实根目录,比如,如果你的WebLogic安装在D:\bea下,在Windows下context.getRealPath("/")通常会返回:
D:\bea\wlserver6.1\config\mydomain\applications\DefaultWebApp
在UNIX下类似:
/bea/wlserver6.1/config/mydomain/applications/DefaultWebApp
这样,和"/WEB-INF/log4j.properties"拼接后,就得到了log4j.properties文件的真实路径,Log4J通过文件IO读取这个配置文件,完成初始化。
现在一切正常!测试通过后,将DefaultWebApp下的所有文件打为一个.war包,进行部署时,发现系统报告找不到“D:\bea\wlserver6.1\null\WEB-INF\log4j.properties”文件!如果你的应用中还需要读取其它已经被打包到war包中的文件,都会报告找不到文件。并且,系统并不会到D:\bea\wlserver6.1\config\mydomain\applications\DefaultWebApp目录下寻找,而会到D:\bea\wlserver6.1\null下寻找。这是因为context.getRealPath("/")返回了null。查看ServletContext的API文档,
publicStringgetRealPath(Stringpath)
……
Therealpathreturnedwillbeinaformappropriatetothecomputerandoperatingsystemon
whichtheservletcontainerisrunning,includingtheproperpathseparators.Thismethod
returnsnulliftheservletcontainercannottranslatethevirtualpathtoarealpathforany
reason
(suchaswhenthecontentisbeingmadeavailablefroma.wararchive).
原来,对一个打包的应用来说,是没有RealPath的概念的,调用getRealPath只会简单地返回null。其实,也很好理解,一个文件被打包入了.war文件,就不存在目录结构了(虽然包中仍然存在目录结构,但这不等同于文件系统中的目录结构)。所以,对war包中的资源是无法得到RealPath的。这样也就无从通过文件IO进行读取了。那么,如何读取war包中的资源呢?答案是使用ServletContext.getResourceAsStream(String)方法。
对于org.apache.log4j.PropertyConfigurator,有如下几种配置方法:
-
staticvoidconfigure(Propertiesproperties);
-
staticvoidconfigure(StringconfigFilename);
- staticvoidconfigure(URLconfigURL);
既然,现在不能得到war包中的Log4J的配置文件,那么可以通过读入InputStream,构造一个Properties,通过configure(Propertiesproperties)方法同样可以完成配置。示例代码如下:
-
InputStreamis=getServletContext().
-
getResourceAsStream("/WEB-INF/log4j.properties");
-
Propertiesprops=newProperties();
-
try{
-
props.load(is);
-
}catch(IOExceptione){
-
System.err.println("Loadlog4jconfigurationfailed");
-
}
- PropertyConfigurator.configure(props);
那么,现在对于war应用可以成功运行,但如果现在不通过war部署,直接通过目录结构部署应用会不会又出现找不到资源的错误呢?请来看看ServletContext.getResourceAsStream的API文档,
ReturnsaURLtotheresourcethatismappedtoaspecifiedpath.Thepathmustbeginwith
a"/"andisinterpretedasrelativetothecurrentcontextroot.
Thismethodallowstheservletcontainertomakearesourceavailabletoservletsfromany
source.
Resourcescanbelocatedonalocalorremotefilesystem,inadatabase,orin
a.warfile.可见,通过getResourceAsStream可以获取包括本地文件系统、远程文件系统、war包等资源。不会出现上面担心的问题。
结论:在开发J2EEWeb应用时,如果需要读取本应用中的文件,尽量使用ServletContext.getResourceAsStream进行,而不要使用文件IO。
二、Ant使用中的OutOfMemoryError解决
在开发大型项目时,类文件通常有数千个之多,这时都需要采用一些make工具来辅助开发。有时需要编译的类太多,使用Ant编译时,会出现OutOfMemoryError的错误,使编译进程中断。这时,通常通过先移出部分文件,分批编译。但Java编译过程的自动依赖编译,通常很难确定究竟应该先移出哪些文件、后移出哪些文件伤透脑筋。有没有简便的方法?有!
转到你的Ant的安装目录,在bin子目录中找到ant.bat,使用文字编辑器打开,修改:runAnt处的允许命令,添加如下参数:
:runAnt
"%_JAVACMD%"-Xms128m-Xmx512m-classpath……
如果你安装了Jike,使用Jike编译器,则需要修改:runAntWithJikes处的运行命令,同上。
结论:Java虚拟机默认分配64M内存,如果你的应用比较大,超出64M内存,Java虚拟机就会抛出OutOfMemoryError,并停止运行。不管是什么应用(Web应用、Application等),只需要修改你的机器上的运行Java命令,在javaxxx命令中添加-Xms(最小使用内存)、-Xmx(最大使用内存)即可解决。当然,这儿的内存容量都是指物理内存,不能超出你的机器的物理内存的总容量。
分享到:
相关推荐
在使用Apache Ant构建Java项目时,可能会遇到一个常见的问题,即`OutOfMemoryError`。这个错误通常发生在编译大量Java源文件时,由于资源耗尽,JVM无法分配足够的内存来执行任务。`OutOfMemoryError`是Java运行时...
本文介绍了在J2EE项目开发中遇到的war包中的文件的读取问题,Ant使用中的OutOfMemoryError解决方法。
总结,junrar的`OutOfMemoryError`问题是由于内存管理不当造成的,解决之道在于采用更高效的内存使用策略,如流式处理和内存映射文件。通过理解和应用这些技术,开发者可以提高junrar的性能,避免在处理大文件时出现...
概述:本文将讨论如何使用 Java 高效地读取大文件,解决读取大文件时可能遇到的 OutOfMemoryError 异常问题。同时,文章还将介绍使用 Guava 和 Apache Commons IO 库来读取大文件的不同方法,并对比它们的内存占用...
由于大文本文件一次性加载到内存可能导致`OutOfMemoryError`,因此通常采用逐行读取或分块读取的方式。以下是一个示例,展示了如何使用BufferedReader逐行读取: ```java BufferedReader reader = new ...
"Java.lang.OutOfMemoryError: Java heap space 解决方法" Java.lang.OutOfMemoryError: Java heap space 是 Java 中的一个常见错误,它发生时,Java 虚拟机 (JVM) 无法分配对象,因为堆空间不足。下面是解决该问题...
传统方式的读取文件方式会将整个文件读取到内存中,导致程序抛出OutOfMemoryError异常。但是,我们可以通过行迭代方式来读取大文件,从而避免内存溢出。 传统方式的问题:传统方式的问题是将整个文件读取到内存中,...
OutOfMemoryError解决办法.md
这个例子展示了如何使用SXSSFWorkbook来读取Excel文件,只保留100行数据在内存中,其他超出的行会被自动写入磁盘。处理完数据后,记得调用`dispose()`方法释放内存。 总结来说,解决Java读取Excel内存溢出问题,...
Java中的`java.lang.OutOfMemoryError`是一种常见的运行时错误,通常表示应用程序在尝试分配内存时遇到了问题。根据提供的信息,这个错误主要涉及到两个方面:`PermGen space`和`Java heap`,并且与Tomcat服务器相关...
Java 8 提供了更加简洁和高效的文件读取方式,使得开发者可以在一行代码内完成文件的读取。然而,需要注意的是,这些方法并不适合处理非常大的文件,因为它们可能会消耗大量内存,导致内存溢出(OutOfMemoryError)...
### 解决OutOfMemoryError内存溢出 在Java开发过程中,我们经常会遇到`java.lang.OutOfMemoryError`(简称OOM)的问题。这个问题的发生主要是由于JVM内存不足或程序中存在内存泄漏所引起的。本文将深入探讨OOM产生...
java.lang.OutOfMemoryError: Java heap space 解决方法
### 解决OutOfMemoryError: PermGen space 在Java应用程序运行过程中,可能会遇到“OutOfMemoryError: PermGen space”的错误提示。这种错误通常发生在永久代(PermGen space)内存不足的情况下,永久代主要用于...
### Tomcat 出现 OutOfMemoryError 的解决方法 #### 一、问题概述 在部署应用至 Tomcat 服务器时,经常会遇到一个常见的错误:`java.lang.OutOfMemoryError: PermGen space`。该错误表明 Java 虚拟机 (JVM) 的永久...
poi读取大量数据会造成gc内存溢出的报错,由于垃圾回收机制无法将大量的对象及时的回收,而这些对象又会保存在内存中,会导致内存不够用的情况,这时候我们就需要使用新的方法,读取为cvs即可.此解决方案可支持千万数据的...
### Myeclipse下java.lang.OutOfMemoryError: Java heap space的解决方案 在使用Myeclipse进行Java开发时,可能会遇到`java.lang.OutOfMemoryError: Java heap space`这个错误提示。这种异常通常发生在应用程序占用...
【系统稳定性——OutOfMemoryError常见原因及解决方法】 在Java应用程序中,系统稳定性的一个关键因素是避免出现`OutOfMemoryError`。这种错误通常表明JVM(Java虚拟机)的内存资源已经耗尽,无法继续正常运行。...
OutOfMemoryError如何解决.md