今天遇到一个问题,首先是在tomcat中间件上跑的web项目,一个jsp文件,因为代码行数实在是太多了,更新了几个版本之后编译报错了,页面打开都是报500的错误,500的报错,知道http协议返回码的都知道,这是服务端的报错。

jsp编译过程是先编译为servlet,然后再通过类加载器编译为.class文件,再执行为Servlet实例。这就是jsp的编译过程。所以jsp报500错误也可以理解,属于服务端的报错没什么好怀疑的。

服务端报错,肯定就是去console拿日志了。从CONSOLE拿到日志关键信息:

The code of method _jspService(HttpServletRequest, HttpServletResponse) is exceeding the 65535 bytes limit

这个报错意思大概是超过字节限制。通过网上资料搜索,很多地方都是给出了一个解决方法,不过大部分都没说明为什么。
网上一大堆差不多的博客,都是这样说的,在tomcat的conf文件夹里,找到web.xml,然后在JspServlet的servlet配置里,加上mappedfile参数
修改后的代码

<servlet><servlet-name>jsp</servlet-name><servlet-class>org.apache.jasper.servlet.JspServlet</servlet-class><init-param><param-name>fork</param-name><param-value>false</param-value></init-param><init-param><param-name>xpoweredBy</param-name><param-value>false</param-value></init-param><init-param>  <param-name>mappedfile</param-name>  <param-value>false</param-value>  </init-param> <load-on-startup>3</load-on-startup></servlet>

其实也就是加上

<init-param>  <param-name>mappedfile</param-name>  <param-value>false</param-value>  </init-param>

大部分博客并没有给出原因。不过还是可以解决问题的。不过网上所说的这种方法并不是很好的方法,只能说是暂缓之策。

首先要从jsp的编译说起,jsp经过tomcat编译后,文件会保存在哪里?
下面介绍一下,一般路径都会在${TOMCAT_HOME}\work\Catalina\localhost\项目名称\org\apache\jsp文件夹下面。
假如新建了一个index.jsp,经过编译之后,都会在该路径下面生成index_jsp.java文件和index_jsp.class文件,index_jsp.java文件是什么?其实可以理解为tomcat编译生成的servlet类,index_jsp.class呢?当然就是servlet类编译之后生成的.class文件了。
随便找个index_jsp.java文件,拿代码来看看:

/** Generated by the Jasper component of Apache Tomcat* Version: Apache Tomcat/7.0.32* Generated at: 2016-11-19 03:26:12 UTC* Note: The last modified time of this file was set to*       the last modified time of the source file after*       generation to assist with modification tracking.*/
package org.apache.jsp;import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.jsp.*;
import java.util.*;public final class index_jsp extends org.apache.jasper.runtime.HttpJspBaseimplements org.apache.jasper.runtime.JspSourceDependent {private static final javax.servlet.jsp.JspFactory _jspxFactory =javax.servlet.jsp.JspFactory.getDefaultFactory();private static java.util.Map<java.lang.String,java.lang.Long> _jspx_dependants;private javax.el.ExpressionFactory _el_expressionfactory;private org.apache.tomcat.InstanceManager _jsp_instancemanager;public java.util.Map<java.lang.String,java.lang.Long> getDependants() {return _jspx_dependants;}public void _jspInit() {_el_expressionfactory = _jspxFactory.getJspApplicationContext(getServletConfig().getServletContext()).getExpressionFactory();_jsp_instancemanager = org.apache.jasper.runtime.InstanceManagerFactory.getInstanceManager(getServletConfig());}public void _jspDestroy() {}public void _jspService(final javax.servlet.http.HttpServletRequest request, final javax.servlet.http.HttpServletResponse response)throws java.io.IOException, javax.servlet.ServletException {final javax.servlet.jsp.PageContext pageContext;javax.servlet.http.HttpSession session = null;final javax.servlet.ServletContext application;final javax.servlet.ServletConfig config;javax.servlet.jsp.JspWriter out = null;final java.lang.Object page = this;javax.servlet.jsp.JspWriter _jspx_out = null;javax.servlet.jsp.PageContext _jspx_page_context = null;try {response.setContentType("text/html;charset=UTF-8");pageContext = _jspxFactory.getPageContext(this, request, response,null, true, 8192, true);_jspx_page_context = pageContext;application = pageContext.getServletContext();config = pageContext.getServletConfig();session = pageContext.getSession();out = pageContext.getOut();_jspx_out = out;out.write('\r');out.write('\n');if (true) {_jspx_page_context.forward("/login_toLogin");return;}out.write('\r');out.write('\n');} catch (java.lang.Throwable t) {if (!(t instanceof javax.servlet.jsp.SkipPageException)){out = _jspx_out;if (out != null && out.getBufferSize() != 0)try { out.clearBuffer(); } catch (java.io.IOException e) {}if (_jspx_page_context != null) _jspx_page_context.handlePageException(t);else throw new ServletException(t);}} finally {_jspxFactory.releasePageContext(_jspx_page_context);}}
}

从代码可以看出,类继承于HttpJspBase类实现JspSourceDependent接口,先看一下HttpJspBase类,这个类从哪来的呢?HttpJspBase是tomcat库提供的,所以拿tomcat库的源码来看看,在${TOMCAT_HOME}/lib里找到价包jasper.jar,反编译代码,找到HttpJspBase类

package org.apache.jasper.runtime;import java.io.IOException;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.jsp.HttpJspPage;
import org.apache.jasper.compiler.Localizer;public abstract class HttpJspBase extends HttpServletimplements HttpJspPage
{private static final long serialVersionUID = 1L;public final void init(ServletConfig config)throws ServletException{super.init(config);jspInit();_jspInit();}public String getServletInfo(){return Localizer.getMessage("jsp.engine.info");}public final void destroy(){jspDestroy();_jspDestroy();}public final void service(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException{_jspService(request, response);}public void jspInit(){}public void _jspInit(){}public void jspDestroy(){}protected void _jspDestroy(){}public abstract void _jspService(HttpServletRequest paramHttpServletRequest, HttpServletResponse paramHttpServletResponse)throws ServletException, IOException;
}

代码并不是说多复杂,HttpJspBase类继承HttpServlet类,实现HttpJspPage接口,也就是说HttpJspBase重写了HttpServlet的service(),init()等等方法,HttpServlet,我们就很熟悉了。HttpJspPage又是什么?看它的包名,马上知道它是jdk提供的接口,马上找到它的代码:

/** The contents of this file are subject to the terms* of the Common Development and Distribution License* (the "License").  You may not use this file except* in compliance with the License.** You can obtain a copy of the license at* glassfish/bootstrap/legal/CDDLv1.0.txt or* https://glassfish.dev.java.net/public/CDDLv1.0.html.* See the License for the specific language governing* permissions and limitations under the License.** When distributing Covered Code, include this CDDL* HEADER in each file and include the License file at* glassfish/bootstrap/legal/CDDLv1.0.txt.  If applicable,* add the following below this CDDL HEADER, with the* fields enclosed by brackets "[]" replaced with your* own identifying information: Portions Copyright [yyyy]* [name of copyright owner]** Copyright 2005 Sun Microsystems, Inc. All rights reserved.** Portions Copyright Apache Software Foundation.*/package javax.servlet.jsp;import javax.servlet.*;
import javax.servlet.http.*;
import java.io.IOException;/*** The HttpJspPage interface describes the interaction that a JSP Page* Implementation Class must satisfy when using the HTTP protocol.** <p>* The behaviour is identical to that of the JspPage, except for the signature* of the _jspService method, which is now expressible in the Java type* system and included explicitly in the interface.* * @see JspPage*/public interface HttpJspPage extends JspPage {/** The _jspService()method corresponds to the body of the JSP page. This* method is defined automatically by the JSP container and should never* be defined by the JSP page author.* <p>* If a superclass is specified using the extends attribute, that* superclass may choose to perform some actions in its service() method* before or after calling the _jspService() method.  See using the extends* attribute in the JSP_Engine chapter of the JSP specification.** @param request Provides client request information to the JSP.* @param response Assists the JSP in sending a response to the client.* @throws ServletException Thrown if an error occurred during the *     processing of the JSP and that the container should take *     appropriate action to clean up the request.* @throws IOException Thrown if an error occurred while writing the*     response for this page.*/public void _jspService(HttpServletRequest request,HttpServletResponse response)throws ServletException, IOException;
}

很关键的方法名:_jspService,不就是刚才CONSOLE报错提示的方法名?
也就是说jdk提供接口,然后tomcat对接口进行实现,我们知道Java内存模型(JMM)规定了一个方法的大小只能是64k,所以,从刚才的报错,我们简单从源码分析了一下,报错的原因其实就是jsp反编译为Servlet之后,代码要经过_jspService这个方法,这个方法超过了64k,导致报错。

查看一下tomcat7官方给出的文档:http://tomcat.apache.org/tomcat-7.0-doc/jasper-howto.html#Configuration
找到mappedfile属性的意思

mappedfile - 我们是否应该为每个输入行生成一个print语句的静态内容,以便于调试? true或者false,默认true。

现在分析一下具体原因。代码报错的原因就是因为jsp编译为Servlet之后,经过_jspService这个方法,方法超过64k导致报错。然后通过设置mappedfile参数的原因是尽量减少print代码,暂时使代码不超过,也就是说只是一种暂缓的方法。网上资料说通过jsp:include方法或许可以,我并没有实践过,所以不讨论。

tomcat系列之编译超过64k大小的jsp文件报错原因相关推荐

  1. tomcat work目录的作用就是编译每个项目里的jsp文件为java文件如果项目没有jsp页面则这个项目文件夹为空...

    最近发现,很多网友喜欢把tomcat的work目录里的东西叫做缓存,其实那不是很恰当,work目录只是tomcat的工作目录,也就是tomcat把jsp转换为class文件的工作目录,这也正是为什么它 ...

  2. cmake编译安装完成后 执行cmake --version报错 bash: /usr/bin/cmake: 没有那个文件或目录

    cmake编译安装完成后 执行cmake --version报错 bash: /usr/bin/cmake: 没有那个文件或目录 cmake 没有那个目录 - 未完代码 - 博客园 因为直接使用cma ...

  3. linux下编译make文件报错“/bin/bash^M: 坏的解释器,使用grep快速定位代码位置

    一.linux下编译make文件报错"/bin/bash^M: 坏的解释器 参考文章:http://blog.csdn.net/liuqiyao_01/article/details/415 ...

  4. 【错误记录】记录 Android 命令行执行 Java 程序中出现的错误 ( dx 打包 PC 可执行文件报错 | dalvik 命令执行 kotlin 编译的 dex 文件报错 )

    文章目录 前言 一.Android 命令行与 PC 可执行 JAR 文件不兼容 二.Android 命令行使用 dalvik 命令不能直接执行 Kotlin 编译的 dex 文件 前言 尝试在 And ...

  5. 启动Tomcat服务时,出现org.apache.catalina.startup.VersionLoggerListener报错

    启动Tomcat服务时,出现org.apache.catalina.startup.VersionLoggerListener报错 解决办法: 打开Tomcat安装后目录,进入conf文件夹,找到配置 ...

  6. 深度学习自学(十六):caffe-sphereface识别代码编译问题-caffe sudo make test报错

    一.caffe-sphereface编译错误 caffe sudo make test报错 sudo make runtest -j33 CXX src/caffe/test/test_benchma ...

  7. Maven项目中pox.xml文件报错以及项目编译错误

    我用Eclipse开发Maven项目,本来好好的,但是后来莫名其妙的其中pom.xml文件报错,后来执行install命令时又编译不通过报错.我痛苦地摸索了一整天,最后才把问题解决了.虽然问题解决了, ...

  8. win10解决koala编译sass文件报错

    ## win10解决koala编译sass文件报错 使用koala编译sass文件时报错invalid byte sequence in utf-8 use --trace for backtrace ...

  9. 打印log4j日志 : 超过一定大小新建日志文件 每天新建一个日志文件

    # Settings dir=. file=opc-client.log target=${dir}/${file} #target=${file}# Set root logger level to ...

最新文章

  1. LEGv8指令集中分支和跳转的地址范围
  2. 某大学校园网设计方案大学校园拓扑图 全解
  3. pygame交换式拼图设计
  4. Just some wierd thoughts
  5. Latex改变页边距
  6. 注册中国移动物联网平台账号
  7. 老男孩网络安全 | 从小白到月薪13k,仅仅只用了三个多月的时间!
  8. GitHub标星90K,这份持续霸榜的Leetcode刷题手册到底有多强?
  9. 美团:后端开发工程师(实习生)面试
  10. 一个爆款小程序的复盘
  11. 《士兵突击》哪些最精彩的话语
  12. 软考初级程序员上午单选题(13)
  13. Web APIs 简介、DOM
  14. python:大球吃小球
  15. win10系统更新后图片查看器的恢复方法
  16. 乡村振兴战略下传统村落文化旅游设计 | 年度图书,踔厉奋发,勇毅前行
  17. struts2漏洞监测_全版本struts2漏洞练习
  18. Nginx总结(2)—Nginx的反向代理
  19. jffs2挂载Nand Flash分区失败问题
  20. 7-6 个税查询 (15 分)

热门文章

  1. 苏宁“J-10%”抢下618开局,比主场虚名更重要的是什么?
  2. 微信公众账号后台怎么解除小程序_公众号与微信解除关联 微信公众号小程序怎么做...
  3. 客户端与服务端长连接的几种方式
  4. Ebook电子书下载
  5. C#连接OleDbConnection操作数据库
  6. layer.confirm 用法
  7. kvm技术:kvm虚拟化的安装和应用
  8. 礼品平台网站对于商家有什么用处
  9. ThinkPHP6.0伪静态使用
  10. JS cssText(二十一)