今天遇到一个问题,首先是在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.HttpJspBase
implements 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 HttpServlet
implements 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. java jsp文件报错解决方法

    初次使用java开发 下载好代码之后,用maven编译都是ok的,第二天,打开项目一看,好的web项目的jsp文件提示错误,后面,查了下问题,是tomcat没有配置路径导致的问题,现在大致记录一下解决 ...

  2. 新建maven项目index.jsp文件报错处理

    最近用eclipse新建了一个maven项目,结果刚新建完成index.jsp页面就报错了,先把错误信息贴出来看看 后来就找资料,结果发现两种解决办法,希望可以帮助用得上的人! 第一种:直接在pom. ...

  3. SpringBoot 访问jsp文件报错Path with "WEB-INF" or "META-INF": [WEB-INF/jsp/welcome.jsp]的解决办法

    由于SpringBoot不在支持jsp,所以想使用jsp的情况下需要在pom.xml配置servlet依赖,jstl标签库和tomcat依赖.以下是我的pom.xml的配置: (ps:标记红色处为重点 ...

  4. MyEclipse打不开jsp文件 报错“Failed to create the part's controls"

    本来写好了一套网站html代码,需要移植到myeclipse的jsp页面中,当复制代码完毕后,也是可以运行的并不报错,但一直有弹框提示有空指针,当关闭页面后再次打开就歇菜了,提示 我预感到这可能是my ...

  5. eclipse中web工程新建jsp文件报错:The superclass "javax.servlet.http.HttpServlet" was not found on the Java Build Path

    web工程中新建jsp文件提示:The superclass "javax.servlet.http.HttpServlet" was not found on the Java ...

  6. Eclipse 新建jsp文件报错问题

    今天在web工程中新建一个index.jsp文件时,发现会报错,记录一下解决办法. 原因:缺少servlet-api.jar包 所以我们先去下载一个jar包,将它引入我们的工程中,即可. 工程右键-& ...

  7. 新建Maven项目Index.jsp文件报错解决方法

    The superclass "javax.servlet.http.HttpServlet" was not found on the Java Build Path    in ...

  8. Maven构建项目时index.jsp文件报错

    错误为:The superclass "javax.servlet.http.HttpServlet" was not found on the Java Build Path 原 ...

  9. 【问题】R文件报错原因及解决办法 (转)

    错误如图.下面是几种解决方法(网上搜集的). 1.如果是导入项目出现这个问题,一般是R文件没有更新造成(据说导入项目,R不会自动更新).可以Project——clean以下,R文件会重新生成. 2.选 ...

随机推荐

  1. python中的列表及numpy数组排序

    一.列表排序  # python中对列表排序有sort.sorted两种方法,其中sort是列表内置方法,其帮助文档如下:In [1]: help(sorted) Help on built-in f ...

  2. java 日志体系目录

    java 日志体系目录 1.1 java 日志体系(一)log4j1.log4j2.logback.jul.jcl.slf4j 1.2 java 日志体系(二)jcl 和 slf4j 2.1 java ...

  3. Linux iptables 安全配置(防Ddos)

    *filter:INPUT ACCEPT [0:0]:FORWARD ACCEPT [0:0]:OUTPUT ACCEPT [0:0]-N whitelist-A whitelist -s 58.60 ...

  4. [ES]elasticsearch章5 ES的分词(一)

    初次接触 Elasticsearch 的同学经常会遇到分词相关的难题,比如如下这些场景: 1.为什么明明有包含搜索关键词的文档,但结果里面就没有相关文档呢? 2.我存进去的文档到底被分成哪些词(ter ...

  5. java31

    1.包装类 基本数据类型包装成对象,使基本数据类型的功能更加强大, 基本数据类型 包装类 byte Byte short Short int Integer long Long float Float ...

  6. 20155312 张竞予 Exp9 Web安全基础

    Exp9 Web安全基础 目录 基础问题回答 (1)SQL注入攻击原理,如何防御 (2)XSS攻击的原理,如何防御 (3)CSRF攻击原理,如何防御 实践过程记录 WebGoat准备工作 1.XSS攻 ...

  7. Python Day 6

    阅读目录:   内容回顾:   深浅拷贝:   元组:   字典   集合 ##内容回顾 #1.数字类型 int | float | bool | complex #2.字符串 #常规操作: -- 索 ...

  8. C#中一些关联名词的含义归纳

    形参/实参:定义一个方法,方法中需要传输的参数为形参,实际调用方法时候传入的参数为实参. 方法/函数:两个没有本质上的区别,都是指类中的一些操作. 委托/事件:委托(delegate)是存有对某个方法 ...

  9. Promise实战AJAX封装

    一.利用Promise的知识,对最开始的ajax的例子进行一个简单的封装: var url = 'xxx'; // 封装一个get请求的方法 function request(url){ return ...

  10. 欧拉函数-gcd-快速幂(牛客寒假算法基础集训营1-D-小a与黄金街道)

    题目描述: 链接:https://ac.nowcoder.com/acm/contest/317/D来源:牛客网小a和小b来到了一条布满了黄金的街道上.它们想要带几块黄金回去,然而这里的城管担心他们拿 ...