java开发中遇到bug是再正常不过了,所谓程序不是写出来的是调出来的,bug的调试是程序开发中重要的一部分也是必不可少的一部分。以下是我项目开发中遇到的bug整理,有一些可能比较低级,但是我还是把它记录下来。合格的程序员都是从bug堆里爬出来。
解决方法:增加、删除类文件或者在一个类中增加、删除方法时,是不能够热部署到服务上的。这时候需要停止服务器(Tomcat等等)重新部署后再启动,就不会出现上面的提示了。
3.org.apache.jasper.JasperException: java.lang.ClassCastException:org.apache.catalina.util.DefaultAnnotationProcessor cannot be cast to org.apache.AnnotationProcessor
at org.apache.jasper.servlet.JspServletWrapper.handleJspException(JspServletWrapper.java:522)
at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:356)
原因:修改了tomcat里的context.xml文件,在context 元素下添加 <Loader delegate="true" />
4.POI导出大数据问题
第一步:HSSF导出.xls文件时,行数不能超过65535行。改用XSSF导出.xlsx文件时行数可达100万条。但是在导出20万条数据时就很时间了。并且会报错:java.lang.OutOfMemoryError: Java heap space http://blog.sina.com.cn/s/blog_701c951f0100n1sp.html中的第二种情况发生这种问题的原因是java虚拟机创建的对象太多,在进行垃圾回收之间,虚拟机分配的到堆内存空间已经用满了,与Heap space有关。解决这类问题有两种思路:
1. 检查程序,看是否有死循环或不必要地重复创建大量对象。找到原因后,修改程序和算法。
我以前写一个使用K-Means文本聚类算法对几万条文本记录(每条记录的特征向量大约10来个)进行文本聚类时,由于程序细节上有问题,就导致了Java heap space的内存溢出问题,后来通过修改程序得到了解决。
2. 增加Java虚拟机中Xms(初始堆大小)和Xmx(最大堆大小)参数的大小。如:set JAVA_OPTS= -Xms256m -Xmx1024m
第二步:按照上面的方法将JVM的参数改为:-Xms256m -Xmx1024m 又报了下面的问题
java.lang.OutOfMemoryError: GC overheadlimit exceeded 这个是JDK6新添的错误类型。是发生在GC占用大量时间为释放很小空间的时候发生的,是一种保护机制。解决方案是,关闭该功能,使用—— -XX:-UseGCOverheadLimit
第三步:关闭该功能,使用—— -XX:-UseGCOverheadLimit 方式
还是报错:java.lang.OutOfMemoryError: Java heap space 效果不行
然后将参数调整为-Xms1024m -Xmx1024m 其中"-Xms128M"为最小内存,"-Xmx256M"为最大内存。 这样的效果不好。需要想其他方法
http://outofmemory.cn/c/java-outOfMemoryError
第四步:测试发现改用XSSF导出.xlsx文件时行数可达100万条,但是导出10万条只需要15秒,当超过12万时就会出现了内存溢出。修改jvm的参数效果不好,现在只有想其他方法
第五步:改用SXSSF模拟数据导出时100万条只要16-18秒,50万只要9秒。但是缺点就是只能导出xlsx文件,??但是我尝试导出xls文件也可以。可能我用的是3.11版本比较高了已经支持xls了吧。原因:可以到处xls文件,但是他实质还是xlsx文件。Xls文件只能有65535行。所有本质上还是不能到处大数据的xls文件。因为将这样一个文件导入时会被认为是xlsx文件。
http://blog.youkuaiyun.com/u010003835/article/details/51590101中的方案一是可以解决问题的OK
POI导入大数据问题
首先导入一个11M的xls文件,里面含有50万条数据。导入就报错了,Struts中文件上传不能超多2M
修改Struts的常量配置文件
<!--修改Struts2的文件上传限制大小 -->
<constantname="struts.multipart.maxSize" value="20000000"/>
但是还是出现问题:内存溢出 50万条太大了
ognl.MethodFailedException: Method"importExcel" failed for objectcn.itcast.nsfw.user.action.UserAction@d6f860e [java.lang.OutOfMemoryError: Javaheap space]
实际测试导入10万条大小为2.3M没有问题不到一分钟时间.超过15万条开始出现内存溢出这个导出一样的大小就会造成内存溢出并且这里的第一种方案是解决不了的,只可能考虑第二种方案压缩然后解压的方式
分几批导入数据库,总共为75万条数据.
select count(*) from table_ 查询总记录数
然后导出75万数据时还是报错ognl.MethodFailedException: Method"exportExcel" failed for objectcn.itcast.nsfw.user.action.UserAction@455f2645 [java.lang.OutOfMemoryError:Java heap space]内存溢出.所以大数据导出还是得用第二种方案来解决
先用DELETE FROM USER WHERE 1=1 LIMIT 100000; 删除表中前10万的数据到60万行.还是报错,到55万行时就可以,时间上只要不到一分钟.
通过第二种方案实现大数据导出:多个excel文件压缩文件
导出多个文件excel时数据量达到60万时还是会OOM,因为一次性读取那么大的数据量到内存可能会溢出的,读取50万的时候还好,所以还是必须分批读出来然后分批写到excel文件中去,所以现在就是首先要分批来做,以5万为单位,每次向数据库中读取5万的数据写到excel文件中去.
分页查询出数据库中的值
SELECT* FROM USER LIMIT 0,20;
SELECT* FROM USER LIMIT 21,40; 就是分页处理的查询
分页查询方式导出60万条,没有文件,然后将多个文件压缩为Zip文件,再删除源文件. 最大150万没有问题
@Test
/**
* 将用户列表分页导出多个excel文件,然后压缩为zip文件,然后将源文件删除(完整版)
*/
public void doZipExcel() {// 这样是OK 现在就是要将多个excel文件压缩就可以了----
// 以当前时间为文件名称
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd-hh-mm-ss");
String path = sdf.format(new Date());
// 得到服务器地址路径
// String serverPath = ServletActionContext.getServletContext()
// .getRealPath("upload/test/");
String serverPath = new String(
"D:\\apache-tomcat-6.0.39\\webapps\\itcastTax\\upload\\test\\");
// 在服务器端创建文件夹
File file = new File(serverPath + path);
if (!file.exists()) {
file.mkdir();
}
// 从容器中拿到userService对象
UserService ts = (UserService) ctx.getBean("userService");
// 查询总记录数
int resultCounts = ts.findCounts();
// 然后分页查询出数据来
// 每次设置导出数量
int NUM = 100000;
// 得出导出的excel文件数
int excelNumbers = 0;
if (resultCounts != 0) {
if (resultCounts % NUM == 0) {
excelNumbers = resultCounts / NUM;
} else {
excelNumbers = resultCounts / NUM + 1;
}
} else {
excelNumbers = 1;
}
System.out.println(excelNumbers);
for (int j = 0; j < excelNumbers; j++) {
List<User> userList1 = null;
// 切取每5000为一个导出单位,存储一个文件
// 对不足5000做处理;
if (resultCounts != 0) {
userList1 = ts.findCount(NUM, (j + 1));
}
System.out.println(userList1.size());
// 2、导出
try {
// 1、创建工作簿
Workbook workbook = new SXSSFWorkbook(500);
// 1.1、创建合并单元格对象
CellRangeAddress cellRangeAddress = new CellRangeAddress(0, 0,
0, 6);// 起始行号,结束行号,起始列号,结束列号
// 1.2、头标题样式
CellStyle style1 = createCellStyle(workbook, (short) 16);
// 1.3、列标题样式
CellStyle style2 = createCellStyle(workbook, (short) 13);
// 2、创建工作表
Sheet sheet = workbook.createSheet("用户列表");
// 2.1、加载合并单元格对象
sheet.addMergedRegion(cellRangeAddress);
// 设置默认列宽
sheet.setDefaultColumnWidth(12);
// 3、创建行
// 3.1、创建头标题行;并且设置头标题
Row row1 = sheet.createRow(0);
Cell cell1 = row1.createCell(0);
// 加载单元格样式
cell1.setCellStyle(style1);
cell1.setCellValue("用户列表");
// 3.2、创建列标题行;并且设置列标题
Row row2 = sheet.createRow(1);
String[] titles = { "用户名", "帐号", "所属部门", "性别", "手机号码", "电子邮箱",
"生日" };
for (int i = 0; i < titles.length; i++) {
Cell cell2 = row2.createCell(i);
// 加载单元格样式
cell2.setCellStyle(style2);
cell2.setCellValue(titles[i]);
}
// 4、操作单元格;将用户列表写入excel
if (userList1 != null) {
for (int x = 0; x < userList1.size(); x++) {
Row row = sheet.createRow(x + 2);
Cell cell11 = row.createCell(0);
cell11.setCellValue(userList1.get(x).getName());
Cell cell12 = row.createCell(1);
cell12.setCellValue(userList1.get(x).getAccount());
Cell cell13 = row.createCell(2);
cell13.setCellValue(userList1.get(x).getDept());
Cell cell14 = row.createCell(3);
cell14.setCellValue(userList1.get(x).isGender() ? "男"
: "女");
Cell cell15 = row.createCell(4);
cell15.setCellValue(userList1.get(x).getMobile());
Cell cell16 = row.createCell(5);
cell16.setCellValue(userList1.get(x).getEmail());
Cell cell17 = row.createCell(6);
cell17.setCellValue(userList1.get(x).getBirthday());
}
}
// 5、输出
FileOutputStream outputStream = new FileOutputStream(new File(
serverPath + path + "\\" + j + "用户列表大数据.xlsx"));
workbook.write(outputStream);
workbook.close();
} catch (Exception e) {
e.printStackTrace();
}
}
// 得到导出来的excel文件数组
File[] files = file.listFiles();
// List<String> filesList = new ArrayList<String>();
// if (files != null) {
// for (File file2 : files) {
// filesList.add(file2.getAbsolutePath());
// System.out.println(file2.getAbsolutePath());
// }
// }
// 通过工具类将文件数组压缩为zip文件
String fileZipName = serverPath + "用户列表大数据" + path + ".zip";
ZipFileUtil.compressFiles2Zip(files, fileZipName);
// 将文件夹删除
System.out.println(DeleteFolder(file.getAbsolutePath()));
}
/**
* 创建单元格样式
*
* @param workbook
* 工作簿
* @param fontSize
* 字体大小
* @return 单元格样式
*/
private static CellStyle createCellStyle(Workbook workbook, short fontSize) {
CellStyle style = workbook.createCellStyle();
style.setAlignment(CellStyle.ALIGN_CENTER);// 水平居中
style.setVerticalAlignment(CellStyle.VERTICAL_CENTER);// 垂直居中
// 创建字体
Font font = workbook.createFont();
font.setBoldweight(Font.BOLDWEIGHT_BOLD);// 加粗字体
font.setFontHeightInPoints(fontSize);
// 加载字体
style.setFont(font);
return style;
}
/**
* 根据路径删除指定的目录或文件,无论存在与否
*
* @param sPath
* 要删除的目录或文件
* @return 删除成功返回 true,否则返回 false。
*/
public boolean DeleteFolder(String sPath) {
boolean flag = false;
File file = new File(sPath);
// 判断目录或文件是否存在
if (!file.exists()) { // 不存在返回 false
return flag;
} else {
// 判断是否为文件
if (file.isFile()) { // 为文件时调用删除文件方法
return deleteFile(sPath);
} else { // 为目录时调用删除目录方法
return deleteDirectory(sPath);
}
}
}
/**
* 删除单个文件
*
* @param sPath
* 被删除文件的文件名
* @return 单个文件删除成功返回true,否则返回false
*/
public boolean deleteFile(String sPath) {
boolean flag = false;
File file = new File(sPath);
// 路径为文件且不为空则进行删除
if (file.isFile() && file.exists()) {
file.delete();
flag = true;
}
return flag;
}
/**
* 删除目录(文件夹)以及目录下的文件
*
* @param sPath
* 被删除目录的文件路径
* @return 目录删除成功返回true,否则返回false
*/
public boolean deleteDirectory(String sPath) {
// 如果sPath不以文件分隔符结尾,自动添加文件分隔符
if (!sPath.endsWith(File.separator)) {
sPath = sPath + File.separator;
}
System.out.println(File.separator);
File dirFile = new File(sPath);
// 如果dir对应的文件不存在,或者不是一个目录,则退出
if (!dirFile.exists() || !dirFile.isDirectory()) {
return false;
}
boolean flag = true;
// 删除文件夹下的所有文件(包括子目录)
File[] files = dirFile.listFiles();
for (int i = 0; i < files.length; i++) {
// 删除子文件
if (files[i].isFile()) {
flag = deleteFile(files[i].getAbsolutePath());
if (!flag)
break;
} // 删除子目录
else {
flag = deleteDirectory(files[i].getAbsolutePath());
if (!flag)
break;
}
}
if (!flag)
return false;
// 删除当前目录
if (dirFile.delete()) {
return true;
} else {
return false;
}
}
5.SQL [delete fromrole where role_id=?]; constraint [null]; nested exception is org.hibernate.exception.ConstraintViolationException:Could not execute JDBC batch update
原因:这个和数据库还是有区别
数据库外键检查。一般情况是,当你删除父键时,不让删除,因为有子键引用这个父建id,但是hibernate的级联不一样。删除子键也不行 ,所以取消级联
6.2016-6-13 23:50:57org.apache.catalina.core.StandardWrapperValve invoke
严重: Servlet.service() for servlet jsp threw exception
org.apache.jasper.JasperException: Unable to compile class for JSP:
An error occurred at line: 6 in the generated java file
Only a type can be imported. com.baidu.ueditor.ActionEnter resolves to apackage
An error occurred at line: 12 in the jsp file: /ueditor/jsp/controller.jsp
ActionEnter cannot be resolved to a type
9:
10: String rootPath = application.getRealPath( "/" );
11:
12: out.write( new ActionEnter( request, rootPath ).exec() );
13:
14: %>
Stacktrace:
at org.apache.jasper.compiler.DefaultErrorHandler.javacError(DefaultErrorHandler.java:92)
同出现此问题,我是因为直接把ueditor/jsp/lib下的包导入工程的.
将该包全部拷到web-inf/lib下导入解决此问题