&引用;java.lang.OutOfMemoryError:java堆空间;在xml文件上调用FileUtils.readFileToString时
我的程序在一个目录上迭代,并使用我的Recoder类中的以下函数,在一个编码上使用&引用;java.lang.OutOfMemoryError:java堆空间;在xml文件上调用FileUtils.readFileToString时,java,xml,encoding,heap,fileutils,Java,Xml,Encoding,Heap,Fileutils,我的程序在一个目录上迭代,并使用我的Recoder类中的以下函数,在一个编码上使用FileUtils.readFileToString读取一个文件,并在另一个编码上使用FileUtils.write覆盖它 但是,当它尝试对xml文件执行此操作时,我在标题处遇到异常,否则,它可以正常工作(我已经用.java、.js、.css、.html、.jsp…)在dir上进行了测试 CharsetDetector的内容来自ICU4J,由于某种原因,它在调用cd.detect()时会挂起,因此,现在,我只是将其
FileUtils.readFileToString
读取一个文件,并在另一个编码上使用FileUtils.write
覆盖它
但是,当它尝试对xml文件执行此操作时,我在标题处遇到异常,否则,它可以正常工作(我已经用.java、.js、.css、.html、.jsp…)在dir上进行了测试
CharsetDetector的内容来自ICU4J,由于某种原因,它在调用cd.detect()时会挂起,因此,现在,我只是将其保留在注释中
这就是所谓的主要原因:
public static void main( String[] args ){
DecoderArguments decArgs = new DecoderArguments();
JCommander jc = new JCommander(decArgs, args);
try {
if(args.length>0){
for(String s : decArgs.files){
File file;
if (decArgs.recursive){
System.out.println("Executando Recursivamente em: "+ s);
file = new File(s);
if(file.isDirectory()){
Collection<File> files = FileUtils.listFiles(file,FileFileFilter.FILE, DirectoryFileFilter.DIRECTORY);
for (File f : files){
boolean exec=true;
for(String excl : decArgs.excludes){
if (f.getAbsolutePath().contains(excl)) exec=false;
}
if (file.exists() && exec){
if("".equals(decArgs.fromEncoding)){
Recoder.recodeToUTF(f, decArgs.verbose);
}else {
Recoder.recodeFile(f, decArgs.fromEncoding, decArgs.toEncoding, decArgs.verbose);
}
System.gc();
}
}
}else{
System.out.println("Por favor, informe um diretorio para ler recursivamente.\n"
+ "Uso: java -jar decoder.jar <-r> Caminho|Arquivo");
}
}else{
System.out.println("Convertendo arquivo: "+ s);
file = new File(s);
boolean exec=true;
for(String excl : decArgs.excludes){
if (file.getAbsolutePath().contains(excl)) exec=false;
}
if (file.exists() && exec){
if("".equals(decArgs.fromEncoding)){
Recoder.recodeToUTF(file, decArgs.verbose);
}else {
Recoder.recodeFile(file, decArgs.fromEncoding, decArgs.toEncoding, decArgs.verbose);
}
}
}
}
}else if (args.length==0){
System.out.println("Sintaxe incorreta.\n");
jc.usage();
}
} catch (Exception e) {
e.printStackTrace();
}
}
publicstaticvoidmain(字符串[]args){
DecoderArguments decArgs=新的DecoderArguments();
JCommander jc=新的JCommander(十格,args);
试一试{
如果(参数长度>0){
用于(字符串s:decArgs.files){
文件;
if(十次递归){
System.out.println(“executanto Recursivamente em:+s”);
文件=新文件;
if(file.isDirectory()){
集合文件=FileUtils.listFiles(文件,filefilter.file,DirectoryFileFilter.DIRECTORY);
用于(文件f:文件){
布尔值exec=true;
for(字符串不包括:decArgs.excludes){
如果(f.getAbsolutePath().contains(exc))exec=false;
}
if(file.exists()&&exec){
如果(“.equals(decArgs.fromEncoding)){
Recoder.recodetoff(f,decArgs.verbose);
}否则{
Recoder.RECODIBLE(f,decArgs.fromEncoding,decArgs.toEncoding,decArgs.verbose);
}
gc();
}
}
}否则{
System.out.println(“支持,信息和方向参数递归。\n”
+“Uso:java-jar decoder.jar Caminho | Arquivo”);
}
}否则{
System.out.println(“Convertendo arquivo:+s”);
文件=新文件;
布尔值exec=true;
for(字符串不包括:decArgs.excludes){
如果(file.getAbsolutePath().contains(exc))exec=false;
}
if(file.exists()&&exec){
如果(“.equals(decArgs.fromEncoding)){
Recoder.recodetoff(文件,decArgs.verbose);
}否则{
Recoder.recondile(文件,decArgs.fromEncoding,decArgs.toEncoding,decArgs.verbose);
}
}
}
}
}else if(args.length==0){
System.out.println(“Sintaxe不正确。\n”);
jc.usage();
}
}捕获(例外e){
e、 printStackTrace();
}
}
注意事项:
- 我在Eclipse-Xms1024m-Xmx2048m上使用以下VM参数
- JDK版本1.7.0_75
- 我尝试了一些System.gc(),但没有效果
- 它仅在main递归运行时发生(
),当decArgs.recursive=true
- 已经在bash上检查了文件编码并对其进行了硬编码以供测试,但也没有运气
Recoder.recodetoff
方法代替Recoder.recodeFile
不会引发OutOfMemory。可能试图用错误的编码打开会导致内存泄漏
通过分析生成的.hprof,(混乱的)300Mb xml文件使用了大约500Mb的堆。但是,堆的最大大小设置为2Gb,您的内存正在泄漏,因此为了检查问题,您可以 使用以下参数配置JVM
-XX:+HeapDumpOnOutOfMemoryError-XX:HeapDumpPath=/path/to/dump
。当抛出OutOfMemoryError
时,将在/path/to/dump
中创建转储。然后你可以分析它,寻找那些让你记忆模糊的东西。
不错的教程文件有多大?千字节?兆字节?千兆字节?为什么您需要完整地阅读它们,这似乎非常浪费,您是否可以尝试将它们作为流进行处理(即,读一点,写一点,…)。最后但并非最不重要的一点是:如果您只是“重新编码”一个XML文件而不修复标头,那么很容易导致格式错误:如果标头提到的编码与实际使用的编码不同,则确认XML解析器必须将其报告为错误(如果它能够检测到)。大多数以Kb为单位,一些以Mb为单位,但出于某种原因,有一个300Mb的pom.xml,非常奇怪。我一次阅读整个文件只是为了方便,还没有找到一个可以使用编码的文件流,有什么建议吗?我目前正在替换eclipse上XML文件的编码,但我计划很快将其放入代码中。谢谢
public static void main( String[] args ){
DecoderArguments decArgs = new DecoderArguments();
JCommander jc = new JCommander(decArgs, args);
try {
if(args.length>0){
for(String s : decArgs.files){
File file;
if (decArgs.recursive){
System.out.println("Executando Recursivamente em: "+ s);
file = new File(s);
if(file.isDirectory()){
Collection<File> files = FileUtils.listFiles(file,FileFileFilter.FILE, DirectoryFileFilter.DIRECTORY);
for (File f : files){
boolean exec=true;
for(String excl : decArgs.excludes){
if (f.getAbsolutePath().contains(excl)) exec=false;
}
if (file.exists() && exec){
if("".equals(decArgs.fromEncoding)){
Recoder.recodeToUTF(f, decArgs.verbose);
}else {
Recoder.recodeFile(f, decArgs.fromEncoding, decArgs.toEncoding, decArgs.verbose);
}
System.gc();
}
}
}else{
System.out.println("Por favor, informe um diretorio para ler recursivamente.\n"
+ "Uso: java -jar decoder.jar <-r> Caminho|Arquivo");
}
}else{
System.out.println("Convertendo arquivo: "+ s);
file = new File(s);
boolean exec=true;
for(String excl : decArgs.excludes){
if (file.getAbsolutePath().contains(excl)) exec=false;
}
if (file.exists() && exec){
if("".equals(decArgs.fromEncoding)){
Recoder.recodeToUTF(file, decArgs.verbose);
}else {
Recoder.recodeFile(file, decArgs.fromEncoding, decArgs.toEncoding, decArgs.verbose);
}
}
}
}
}else if (args.length==0){
System.out.println("Sintaxe incorreta.\n");
jc.usage();
}
} catch (Exception e) {
e.printStackTrace();
}
}