在我的应用程序中,我每秒都会收到消息,其中包含高度、速度和航向。每次收到消息时,我都需要生成一个符号 (jpg) 并将其显示在桌面应用程序的 UI 中。下面是我使用的代码。由于某种原因,一旦将以下代码集成到应用程序中,我就会不断收到 OutOfMemory 错误。
为了摆脱它,我将下面类的实例创建和调用 createSymbol 放在单独的线程中,并将 svg 到 jpg 的转换放入单独的线程中。即使这样,问题也没有得到解决。我在想,由于该代码每秒执行一次,因此在内存中加载 javascript 库 milsymbol.js 会导致此问题。
针对我的问题,我的理解正确吗?或者您认为可能是什么问题?
如果我的理解是正确的,有没有办法,我可以在内存中加载一次库,并且每次都可以引用已经加载的库来调用它的函数?
您认为以下代码有什么改进吗?
public class SymbolCreation {
private static final Logger log =
Logger.getLogger( UAVSymbolCreation.class );
int altitude;
int heading;
int speed;
public SymbolCreation(int altitude, int speed, int heading) {
this.altitude = altitude;
this.heading = heading;
this.speed = speed;
}
public void createSymbol() {
synchronized(this) {
File milSymbolLib = new File("config/4586controller/milsymbol.js");
if(milSymbolLib.exists()) {
try {
Reader libraryReader = new FileReader(milSymbolLib);
ScriptEngine scriptEngine = new ScriptEngineManager().getEngineByName("JavaScript");
scriptEngine.eval(libraryReader);
SymbolCreation symbolCreation = this;
scriptEngine.put("symbolCreation",symbolCreation);
scriptEngine.eval("function run(symbolCreation){var altitude = symbolCreation.getAltitude(); "
+ "var speedVal = symbolCreation.getSpeed(); "
+ "var heading = symbolCreation.getHeading();"
+ "symbolCreation.createSymbolSVG(new ms.Symbol('SFA-MFQ--------',{size:20, altitudeDepth:altitude, speed: speedVal , direction: heading}).asSVG());} run(symbolCreation);");
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ScriptException se) {
se.printStackTrace();
}
}
}
}
public void createSymbolSVG(String svgStr) {
synchronized(this) {
boolean fileCreated = false;
File svgFile = new File("config/4586controller/symbol.svg");
if(!svgFile.exists()) {
try {
fileCreated = svgFile.createNewFile();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} else {
fileCreated = true;
}
try {
if(fileCreated) {
List<String> lines = Arrays.asList(svgStr);
Path svgFilePath = Paths.get(svgFile.getPath());
Files.write(svgFilePath, lines, Charset.forName("UTF-8"));
//Conversion will happen on an individual thread - COMMENTED OUT
convertSVGToJPEG(svgFile);
}
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
}
public void convertSVGToJPEG(final File svgFile) {
synchronized(this) {
Runnable svgToJPEGConversion = new Runnable() {
public void run() {
try {
// TODO Auto-generated method stub
//NOw convert svg to jpg
String svg_URI_input = svgFile.toURI().toString();
TranscoderInput input_svg_image = new TranscoderInput(svg_URI_input);
//Step-2: Define OutputStream to JPG file and attach to TranscoderOutput
File jpgFile = new File("config/4586controller/uav.jpg");
if(jpgFile.exists()) {
jpgFile.createNewFile();
}
OutputStream jpg_ostream = new FileOutputStream(jpgFile);
TranscoderOutput output_jpg_image = new TranscoderOutput(jpg_ostream);
// Step-3: Create JPEGTranscoder and define hints
JPEGTranscoder my_converter = new JPEGTranscoder();
my_converter.addTranscodingHint(JPEGTranscoder.KEY_QUALITY,new Float(.9));
// Step-4: Write output
my_converter.transcode(input_svg_image, output_jpg_image);
// Step 5- close / flush Output Stream
jpg_ostream.flush();
jpg_ostream.close();
} catch (IOException ioe) {
ioe.printStackTrace();
} catch (TranscoderException te) {
te.printStackTrace();
}
}
};
Thread imageConversionThread = new Thread(svgToJPEGConversion);
imageConversionThread.start();
}
}
public int getAltitude() {
return altitude;
}
public int getHeading() {
return heading;
}
public int getSpeed() {
return speed;
}
}
最佳答案
java.io.FileReader
类使用流来读取文件。
您的代码永远不会调用 close()
从 libraryReader
对象上的 InputStreamReader
类继承的方法。
您可以添加 finally
block 以关闭阅读器或使用 try-with-resources
语句 - 从 Java8 可用 - 因为 FileReader
类实现 AutoCloseable
界面。
最好检查同时有多少线程处于 Activity 状态,因为每次调用 convertSVGToJPEG
方法都会创建一个新线程。
关于javascript - Java UI 线程被阻止 - 内存不足错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46194157/