servlet的以下代码每分钟接收一次巨大的JSON字符串,大约在2小时后,我总是收到OutOfMemoryError: Java Heap Space
public class GetScanAlertServlet extends HttpServlet {
private String scanType = "";
private static final String path = "D:\\Mobile_scan_alerts8180";
private static final String stockFileName = "stock.txt";
private static final String foFileName = "fo.txt";
private static Logger logger = null;
private String currDate = "";
private DateFormat dateFormat;
private StringBuffer stockData;
private StringBuffer foData;
StringBuffer data = new StringBuffer("");
// For average time of received data
private static float sum = 0;
private static float count = 0;
private static float s_sum = 0;
private static float s_count = 0;
private static float fo_sum = 0;
private static float fo_count = 0;
private static final File dir = new File(path);
private static final File stockFile = new File(path + "\\" + stockFileName);
private static final File foFile = new File(path + "\\" + foFileName);
public void init() {
logger = MyLogger.getScanAlertLogger();
if(logger == null) {
MyLogger.createLog();
logger = MyLogger.getScanAlertLogger();
}
}
/**
* Processes requests for both HTTP <code>GET</code> and <code>POST</code>
* methods.
*
* @param request servlet request
* @param response servlet response
* @throws ServletException if a servlet-specific error occurs
* @throws IOException if an I/O error occurs
*/
protected void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
PrintWriter out = response.getWriter();
response.setContentType("text/plain");
String strScan = "";
try {
String asof = null;
scanType = request.getParameter("type");
scanType = scanType == null ? "" : scanType;
if(scanType.length() > 0){
if(scanType.equalsIgnoreCase("s")) {
stockData = null;
stockData = new StringBuffer(request.getParameter("scanData"));
stockData = stockData == null ? new StringBuffer("") : stockData;
} else {
foData = null;
foData = new StringBuffer(request.getParameter("scanData"));
foData = foData == null ? new StringBuffer("") : foData;
}
}
asof = request.getParameter("asof");
asof = asof == null ? "" : asof.trim();
// Date format without seconds
DateFormat formatWithoutSec = new SimpleDateFormat("yyyy/MM/dd HH:mm");
dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
Date tmp = new Date();
// format: yyyy/MM/dd HH:mm:ss
currDate = dateFormat.format(tmp);
//format: yyyy/MM/dd HH:mm
Date asofDate = formatWithoutSec.parse(asof);
Date cDate = formatWithoutSec.parse(currDate);
cDate.setSeconds(0);
System.out.println(asofDate.toString()+" || "+cDate.toString());
int isDataExpired = asofDate.toString().compareTo(cDate.toString());
if(isDataExpired > 0 || isDataExpired == 0) {
if(scanType != null && scanType.length() > 0) {
checkAndCreateDir();
strScan = scanType.equalsIgnoreCase("s") ? "Stock Data Recieved at "+currDate
: "FO Data Recieved at "+currDate;
//System.out.println(strScan);
} else {
strScan = "JSON of scan data not received properly at "+currDate;
//System.out.println("GSAS: received null or empty");
}
} else {
strScan = "GSAS: " + scanType + ": Received Expired Data of "+asofDate.toString()+" at "+cDate.toString();
System.out.println(strScan);
}
scanType = null;
} catch (Exception ex) {
strScan = "Mobile server issue for receiving scan data";
System.out.println("GSAS: Exception-1: "+ex);
logger.error("GetScanAlertServlet: processRequest(): Exception: "+ex.toString());
} finally {
logger.info("GetScanAlertServlet: "+strScan);
out.println(strScan);
}
}
private void checkAndCreateDir() {
try {
boolean isStock = false;
Date ddate = new Date();
currDate = dateFormat.format(ddate);
sum += ddate.getSeconds();
count++;
logger.info("Total Average Time: "+(sum/count));
if(scanType.equalsIgnoreCase("s")){ //For Stock
setStockData(stockData);
Date date1 = new Date();
currDate = dateFormat.format(date1);
s_sum += date1.getSeconds();
s_count++;
logger.info("Stock Average Time: "+(s_sum/s_count));
//file = new File(path + "\\" + stockFileName);
isStock = true;
} else if (scanType.equalsIgnoreCase("fo")) { //For FO
setFOData(foData);
Date date2 = new Date();
currDate = dateFormat.format(date2);
fo_sum += date2.getSeconds();
fo_count++;
logger.info("FO Average Time: "+(fo_sum/fo_count));
//file = new File(path + "\\" +foFileName);
isStock = false;
}
if(!dir.exists()) { // Directory not exists
if(dir.mkdir()) {
if(isStock)
checkAndCreateFile(stockFile);
else
checkAndCreateFile(foFile);
}
} else { // Directory already exists
if(isStock)
checkAndCreateFile(stockFile);
else
checkAndCreateFile(foFile);
}
} catch (Exception e) {
System.out.println("GSAS: Exception-2: "+e);
logger.error("GetScanAlertServlet: checkAndCreateDir(): Exception: "+e);
}
}
private void checkAndCreateFile(File file) {
try{
if(!file.exists()){ // File not exists
if(file.createNewFile()){
writeToFile(file);
}
} else { // File already exists
writeToFile(file);
}
} catch (Exception e) {
System.out.println("GSAS: Exception-3: "+e);
logger.error("GetScanAlertServlet: checkAndCreateFile(): Exception: "+e.toString());
}
}
private void writeToFile(File file) {
FileOutputStream fop = null;
try{
if(scanType.equalsIgnoreCase("s")){ //For Stock
data = getStockData();
} else if (scanType.equalsIgnoreCase("fo")) { //For FO
data = getFOData();
}
if(data != null && data.length() > 0 && file != null){
fop = new FileOutputStream(file);
byte[] contentBytes = data.toString().getBytes();
for(byte b : contentBytes){
fop.write(b);
}
//fop.write(contentBytes);
fop.flush();
} else {
System.out.println("GSAS: Data is null/empty string");
logger.info("GSAS: Data is null or empty string");
}
data = null;
} catch (Exception e) {
System.out.println("GSAS: Exception-4: "+e);
logger.info("GetScanAlertServlet: writeToFile(): Exception: "+e.toString());
} finally {
try {
if(fop != null)
fop.close();
} catch (IOException ex) {
java.util.logging.Logger.getLogger(GetScanAlertServlet.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
private String readFromFile(String fileName){
String fileContent = "";
try{
String temp = "";
File file = new File(fileName);
if(file.exists()){
FileReader fr = new FileReader(file);
BufferedReader br = new BufferedReader(fr);
while((temp = br.readLine()) != null)
{
fileContent += temp;
}
br.close();
} else {
System.out.println("GSAS: File not exists to read");
logger.info("GetScanAlertServlet: File not exists to read");
}
temp = null;
file = null;
} catch (Exception e) {
System.out.println("GSAS: Exception-5: "+e);
logger.error("GetScanAlertServlet: readFromFile(): Exception: "+e.toString());
}
return fileContent;
}
public StringBuffer getStockData() {
//String temp="";
//StringBuffer temp = (StringBuffer)scanDataSession.getAttribute("stock");
//if(temp != null && temp.length() > 0) {
// return temp;
//}
if(stockData != null && stockData.length() > 0){
return stockData;
} else {
stockData = null;
stockData = new StringBuffer(readFromFile(path + "\\"+ stockFileName));
return stockData;
}
}
public StringBuffer getFOData(){
//String temp="";
//StringBuffer temp = (StringBuffer)scanDataSession.getAttribute("fo");
//if(temp != null && temp.length() > 0) {
// return temp;
//}
if(foData != null && foData.length() > 0) {
return foData;
} else {
foData = null;
foData = new StringBuffer(readFromFile(path + "\\" + foFileName));
return foData;
}
}}
每2小时重启一次jboss服务器后,我总是会收到以下异常,作为解决方案,我也增加了堆大小,但同样的问题仍然存在
ERROR [[GetScanAlertServlet]] Servlet.service() for servlet GetScan
AlertServlet threw exception
java.lang.OutOfMemoryError: Java heap space
at sun.nio.cs.StreamEncoder.write(Unknown Source)
at java.io.OutputStreamWriter.write(Unknown Source)
at java.io.Writer.write(Unknown Source)
at GetScanAlertServlet.writeToFile(GetScanAlertServlet.java:256)
at GetScanAlertServlet.checkAndCreateFile(GetScanAlertServlet.java:236)
at GetScanAlertServlet.checkAndCreateDir(GetScanAlertServlet.java:202)
at GetScanAlertServlet.processRequest(GetScanAlertServlet.java:135)
at GetScanAlertServlet.doPost(GetScanAlertServlet.java:377)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:707)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:790)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(Appl
icationFilterChain.java:252)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationF
ilterChain.java:173)
at org.jboss.web.tomcat.filters.ReplyHeaderFilter.doFilter(ReplyHeaderFi
lter.java:81)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(Appl
icationFilterChain.java:202)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationF
ilterChain.java:173)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperV
alve.java:213)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextV
alve.java:178)
at org.jboss.web.tomcat.security.CustomPrincipalValve.invoke(CustomPrinc
ipalValve.java:39)
at org.jboss.web.tomcat.security.SecurityAssociationValve.invoke(Securit
yAssociationValve.java:153)
at org.jboss.web.tomcat.security.JaccContextValve.invoke(JaccContextValv
e.java:59)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.j
ava:126)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.j
ava:105)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineVal
ve.java:107)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.jav
a:148)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java
:856)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.proce
ssConnection(Http11Protocol.java:744)
at org.apache.tomcat.util.net.PoolTcpEndpoint.processSocket(PoolTcpEndpo
int.java:527)
at org.apache.tomcat.util.net.MasterSlaveWorkerThread.run(MasterSlaveWor
kerThread.java:112)
at java.lang.Thread.run(Unknown Source)发布于 2016-03-21 20:57:29
虽然我没有立即看到问题,但您的代码没有正确处理资源分配/释放。这些问题不一定是由操作大型JSON blob引起的。
我只是注意到您没有释放资源(您打开文件,但不在最终块中关闭它们--有什么理由不这样做吗?),您可能会更好地使用StringBuilder进行字符串操作,或者只使用某种现有的库(apache commons (io,string))来为您做这件事。
应该适当地关闭预定的executor服务(也许使用您的容器提供的东西:Jboss thread pool)。
发布于 2016-03-22 21:59:36
一开始,我不得不重写大部分代码。我知道这是不好的做法,所以这样做,我们在这里教导和帮助。不做别人的工作。但我真的可以忍受阅读代码,让它很难理解。
以下是我发现的问题要点
FileWriter“”FileReader, andBufferedReader`“”永远不会关闭。static,路径和文件名永远不会更改。而且,您的DateFormat从未发生如此更改,以至于staticnull的原因,并且无论如何都将其更改为空字符串。无论如何,以下是代码,希望它能有所帮助
public class GetScanAlertServlet extends HttpServlet
{
private static final String PATH = "D:\\Mobile_scan_alerts";
private static final String STOCK_FILE_NAME = "stock.txt";
private static final String FO_FILE_NAME = "fo.txt";
private static final String EMPTY = "";
private static final DateFormat FORMAT_WITHOUT_SEC = new SimpleDateFormat("yyyy/MM/dd HH:mm");
// For average time of received data
private static float SUM = 0;
private static float S_SUM = 0;
private static float FO_SUM = 0;
private static float COUNT = 0;
private static float S_COUNT = 0;
private static float FO_COUNT = 0;
private static Logger LOGGER = null;
private String scanType;
private String stockData;
private String foData;
@Override
public void init()
{
LOGGER = MyLogger.getScanAlertLogger();
if (LOGGER == null)
{
MyLogger.createLog();
LOGGER = MyLogger.getScanAlertLogger();
}
}
/**
* Returns a short description of the servlet.
*
* @return a String containing servlet description
*/
@Override
public String getServletInfo()
{
return "Short description";
}
/**
* Handles the HTTP <code>GET</code> method.
*
* @param request servlet request
* @param response servlet response
* @throws ServletException if a servlet-specific error occurs
* @throws IOException if an I/O error occurs
*/
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
{
processRequest(request, response);
}
/**
* Handles the HTTP <code>POST</code> method.
*
* @param request servlet request
* @param response servlet response
* @throws ServletException if a servlet-specific error occurs
* @throws IOException if an I/O error occurs
*/
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
{
processRequest(request, response);
}
/**
* Processes requests for both HTTP <code>GET</code> and <code>POST</code>
* methods.
*
* @param request servlet request
* @param response servlet response
* @throws ServletException if a servlet-specific error occurs
* @throws IOException if an I/O error occurs
*/
protected void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
{
PrintWriter out = response.getWriter();
response.setContentType("text/plain");
String strScan = EMPTY;
try
{
scanType = getRequestParameter(request, "type");
if (scanType.length() > 0)
{
if (scanType.equalsIgnoreCase("s"))
{
stockData = getRequestParameter(request, "scanData");
}
else
{
foData = getRequestParameter(request, "scanData");
}
}
//format: yyyy/MM/dd HH:mm
Date asofDate = FORMAT_WITHOUT_SEC.parse(getRequestParameter(request, "asof"));
Date currDate = new Date();
currDate.setSeconds(0);
System.out.println(asofDate.toString() + " || " + currDate.toString());
if (asofDate.compareTo(currDate) >= 0)
{
if (scanType != null && scanType.length() > 0)
{
checkAndCreateDir();
strScan =
scanType.equalsIgnoreCase("s") ? "Stock Data Recieved at " + currDate :
"FO Data Recieved at " + currDate;
}
else
{
strScan = "JSON of scan data not received properly at " + currDate;
}
}
else
{
strScan = "GSAS: " + scanType + ": Received Expired Data of " + asofDate.toString()
+ " at " + currDate.toString();
System.out.println(strScan);
}
}
catch (Exception ex)
{
strScan = "Mobile server issue for receiving scan data";
LOGGER.error("GetScanAlertServlet: processRequest(): Exception: " + ex.toString());
}
finally
{
LOGGER.info("GetScanAlertServlet: " + strScan);
out.println(strScan);
out.close();
}
}
private void checkAndCreateDir()
{
try
{
File dir = new File(PATH);
if (!dir.exists())
{
dir.mkdir();
}
File file = null;
SUM += new Date().getSeconds();
COUNT++;
LOGGER.info("Total Average Time: " + (SUM / COUNT));
if (scanType.equalsIgnoreCase("s"))
{ //For Stock
S_SUM += new Date().getSeconds();
S_COUNT++;
LOGGER.info("Stock Average Time: " + (S_SUM / S_COUNT));
file = new File(PATH + System.lineSeparator() + STOCK_FILE_NAME);
}
else if (scanType.equalsIgnoreCase("fo"))
{ //For FO
FO_SUM += new Date().getSeconds();
FO_COUNT++;
LOGGER.info("FO Average Time: " + (FO_SUM / FO_COUNT));
file = new File(PATH + System.lineSeparator() + FO_FILE_NAME);
}
checkAndCreateFile(file);
}
catch (Exception e)
{
//System.out.println("GSAS: Exception-2: "+e);
LOGGER.error("GetScanAlertServlet: checkAndCreateDir(): Exception: " + e.toString());
}
}
private void checkAndCreateFile(File file)
{
try
{
if(!file.exists())
{
file.createNewFile();
}
writeToFile(file);
}
catch (Exception e)
{
LOGGER.error("GetScanAlertServlet: checkAndCreateFile(): Exception: " + e.toString());
}
}
private void writeToFile(File file) throws IOException
{
String data = EMPTY;
if (scanType.equalsIgnoreCase("s"))
{ //For Stock
if (stockData == null)
{
stockData = readFromFile(PATH + System.lineSeparator() + STOCK_FILE_NAME);
}
data = stockData;
}
else if (scanType.equalsIgnoreCase("fo"))
{ //For FO
if (foData == null)
{
foData = readFromFile(PATH + System.lineSeparator() + FO_FILE_NAME);
}
data = foData;
}
FileWriter fileWriter = null;
try
{
if (data != null && data.length() > 0)
{
fileWriter = new FileWriter(file);
fileWriter.write(data.toString());
}
else
{
System.out.println("GSAS: Data is null/empty string");
LOGGER.info("GSAS: Data is null or empty string");
}
}
catch (Exception e)
{
LOGGER.info("GetScanAlertServlet: writeToFile(): Exception: " + e.toString());
}
finally
{
if (fileWriter != null)
{
fileWriter.flush();
fileWriter.close();
}
}
}
private String readFromFile(String fileName) throws IOException
{
String fileContent = EMPTY;
FileReader fr = null;
BufferedReader br = null;
try
{
File file = new File(fileName);
if (file.exists())
{
fr = new FileReader(file);
br = new BufferedReader(fr);
String temp;
while ((temp = br.readLine()) != null)
{
fileContent += temp;
}
}
else
{
System.out.println("GSAS: File not exists to read");
LOGGER.info("GetScanAlertServlet: File not exists to read");
}
}
catch (Exception e)
{
LOGGER.error("GetScanAlertServlet: readFromFile(): Exception: " + e.toString());
}
finally
{
if (fr != null)
{
fr.close();
}
if (br != null)
{
br.close();
}
}
return fileContent;
}
private String getRequestParameter(HttpServletRequest request, String parameter)
{
String str = request.getParameter(parameter);
return str == null ? EMPTY : str.trim();
}
}https://stackoverflow.com/questions/36131221
复制相似问题