是否可以在 Tomcat 8 中禁用对 JSP 2.3 引用静态字段和方法的支持
Is it possible to disable support for referencing static fields and methods for JSP 2.3 in Tomcat 8
是否可以关闭作为统一表达式语言 3.0 的一部分添加的 Tomcat8 中对引用静态字段和方法的支持。
我们的应用程序中有 ~4K JSP,有许多 ${undefined}
(未指定范围)表达式,迁移到 Tomcat 8 导致性能显着下降,因为这些表达式的评估是合法的 'null' 值。我们不再对较新的页面使用 JSP 技术,但遗留技术不会很快消失。
有问题的代码在 javax.servlet.el.ScopedAttributeELResolver class 中,它试图解析来自 ImportHandler 的表达式,该表达式进行多次 Class.forName 查找,这失败主要是由于 ClassNotFoundException。
@Override
public Object getValue(ELContext context, Object base, Object property) {
if (context == null) {
throw new NullPointerException();
}
Object result = null;
if (base == null) {
context.setPropertyResolved(base, property);
if (property != null) {
String key = property.toString();
PageContext page = (PageContext) context
.getContext(JspContext.class);
result = page.findAttribute(key);
if (result == null) {
// This might be the name of an imported class
ImportHandler importHandler = context.getImportHandler();
if (importHandler != null) {
Class<?> clazz = importHandler.resolveClass(key);
if (clazz != null) {
result = new ELClass(clazz);
}
if (result == null) {
// This might be the name of an imported static field
clazz = importHandler.resolveStatic(key);
if (clazz != null) {
try {
result = clazz.getField(key).get(null);
} catch (IllegalArgumentException | IllegalAccessException |
NoSuchFieldException | SecurityException e) {
// Most (all?) of these should have been
// prevented by the checks when the import
// was defined.
}
}
}
}
}
}
}
return result;
}
更新
为 Tomcat 8 - performance problems when using scopeless optional attributes 打开了一个错误,该错误已关闭,因为不会修复。我认为他们可能会添加一些 属性 来禁用性能消耗代码,但现在他们不会,因为:
- 它将Tomcat具体
- 它必须是一个系统 属性 因为这是一个规范 class
- 它不能应用于每个应用程序 - 它会影响该实例上的所有应用程序 运行
请指教谢谢
禁用新行为的一种方法是利用 Tomcat 的 class 加载机制。通用 class 加载程序包含额外的 classes,它们对 Tomcat 内部 classes 和所有 Web 应用程序都是可见的。此 class 加载程序搜索的位置由 $CATALINA_BASE/conf/catalina.properties 中的 common.loader 属性 定义。默认设置将按照列出的顺序搜索以下位置:
- 在 $CATALINA_BASE/lib
中解压 classes 和资源
- $CATALINA_BASE/lib
中的 JAR 文件
- 在 $CATALINA_HOME/lib
中解压 classes 和资源
- $CATALINA_HOME/lib
中的 JAR 文件
我用一个 class 创建了一个新的 jar:javax.servlet.jsp.el.ScopedAttributeELResolver,这个 class 与原来的相同(来自 jsp-api.jar) 除了执行静态解析的 getValue 方法(tomcat 代码在 Apache 2 许可证下,因此补丁是合法的)。 jar 放在 $CATALINA_BASE/lib 文件夹下。
新方法:
@Override
public Object getValue(ELContext context, Object base, Object property) {
if (context == null) {
throw new NullPointerException();
}
Object result = null;
if (base == null) {
context.setPropertyResolved(base, property);
if (property != null) {
String key = property.toString();
PageContext page = (PageContext) context
.getContext(JspContext.class);
result = page.findAttribute(key);
// if (result == null) {
// // This might be the name of an imported class
// ImportHandler importHandler = context.getImportHandler();
// if (importHandler != null) {
// Class<?> clazz = importHandler.resolveClass(key);
// if (clazz != null) {
// result = new ELClass(clazz);
// }
// if (result == null) {
// // This might be the name of an imported static field
// clazz = importHandler.resolveStatic(key);
// if (clazz != null) {
// try {
// result = clazz.getField(key).get(null);
// } catch (IllegalArgumentException | IllegalAccessException |
// NoSuchFieldException | SecurityException e) {
// // Most (all?) of these should have been
// // prevented by the checks when the import
// // was defined.
// }
// }
// }
// }
// }
}
}
return result;
}
此 class 将加载而不是原来的加载并绕过性能问题。
优点:
- 通过简单的 jar 删除很容易回滚
缺点:
- 每次Tomcat升级都需要维护
似乎 Tomcat 8.0.33 解决了这个问题,性能提高了 10 倍
https://bz.apache.org/bugzilla/show_bug.cgi?id=57583
几年后,我们的系统 运行 在 Tomcat 8.5 上出现了巨大的内存分配问题,我们实施了与上面提到的类似的解决方法 ),但不是完全禁用 类 的解析,我们只为首字母大写的属性保留它(类 应该是)。
真正的中期解决方案当然是按照 Tomcat 迁移指南中的说明调整我们的页面属性范围...
是否可以关闭作为统一表达式语言 3.0 的一部分添加的 Tomcat8 中对引用静态字段和方法的支持。
我们的应用程序中有 ~4K JSP,有许多 ${undefined}
(未指定范围)表达式,迁移到 Tomcat 8 导致性能显着下降,因为这些表达式的评估是合法的 'null' 值。我们不再对较新的页面使用 JSP 技术,但遗留技术不会很快消失。
有问题的代码在 javax.servlet.el.ScopedAttributeELResolver class 中,它试图解析来自 ImportHandler 的表达式,该表达式进行多次 Class.forName 查找,这失败主要是由于 ClassNotFoundException。
@Override
public Object getValue(ELContext context, Object base, Object property) {
if (context == null) {
throw new NullPointerException();
}
Object result = null;
if (base == null) {
context.setPropertyResolved(base, property);
if (property != null) {
String key = property.toString();
PageContext page = (PageContext) context
.getContext(JspContext.class);
result = page.findAttribute(key);
if (result == null) {
// This might be the name of an imported class
ImportHandler importHandler = context.getImportHandler();
if (importHandler != null) {
Class<?> clazz = importHandler.resolveClass(key);
if (clazz != null) {
result = new ELClass(clazz);
}
if (result == null) {
// This might be the name of an imported static field
clazz = importHandler.resolveStatic(key);
if (clazz != null) {
try {
result = clazz.getField(key).get(null);
} catch (IllegalArgumentException | IllegalAccessException |
NoSuchFieldException | SecurityException e) {
// Most (all?) of these should have been
// prevented by the checks when the import
// was defined.
}
}
}
}
}
}
}
return result;
}
更新
为 Tomcat 8 - performance problems when using scopeless optional attributes 打开了一个错误,该错误已关闭,因为不会修复。我认为他们可能会添加一些 属性 来禁用性能消耗代码,但现在他们不会,因为:
- 它将Tomcat具体
- 它必须是一个系统 属性 因为这是一个规范 class
- 它不能应用于每个应用程序 - 它会影响该实例上的所有应用程序 运行
请指教谢谢
禁用新行为的一种方法是利用 Tomcat 的 class 加载机制。通用 class 加载程序包含额外的 classes,它们对 Tomcat 内部 classes 和所有 Web 应用程序都是可见的。此 class 加载程序搜索的位置由 $CATALINA_BASE/conf/catalina.properties 中的 common.loader 属性 定义。默认设置将按照列出的顺序搜索以下位置:
- 在 $CATALINA_BASE/lib 中解压 classes 和资源
- $CATALINA_BASE/lib 中的 JAR 文件
- 在 $CATALINA_HOME/lib 中解压 classes 和资源
- $CATALINA_HOME/lib 中的 JAR 文件
我用一个 class 创建了一个新的 jar:javax.servlet.jsp.el.ScopedAttributeELResolver,这个 class 与原来的相同(来自 jsp-api.jar) 除了执行静态解析的 getValue 方法(tomcat 代码在 Apache 2 许可证下,因此补丁是合法的)。 jar 放在 $CATALINA_BASE/lib 文件夹下。
新方法:
@Override
public Object getValue(ELContext context, Object base, Object property) {
if (context == null) {
throw new NullPointerException();
}
Object result = null;
if (base == null) {
context.setPropertyResolved(base, property);
if (property != null) {
String key = property.toString();
PageContext page = (PageContext) context
.getContext(JspContext.class);
result = page.findAttribute(key);
// if (result == null) {
// // This might be the name of an imported class
// ImportHandler importHandler = context.getImportHandler();
// if (importHandler != null) {
// Class<?> clazz = importHandler.resolveClass(key);
// if (clazz != null) {
// result = new ELClass(clazz);
// }
// if (result == null) {
// // This might be the name of an imported static field
// clazz = importHandler.resolveStatic(key);
// if (clazz != null) {
// try {
// result = clazz.getField(key).get(null);
// } catch (IllegalArgumentException | IllegalAccessException |
// NoSuchFieldException | SecurityException e) {
// // Most (all?) of these should have been
// // prevented by the checks when the import
// // was defined.
// }
// }
// }
// }
// }
}
}
return result;
}
此 class 将加载而不是原来的加载并绕过性能问题。
优点:
- 通过简单的 jar 删除很容易回滚
缺点:
- 每次Tomcat升级都需要维护
似乎 Tomcat 8.0.33 解决了这个问题,性能提高了 10 倍 https://bz.apache.org/bugzilla/show_bug.cgi?id=57583
几年后,我们的系统 运行 在 Tomcat 8.5 上出现了巨大的内存分配问题,我们实施了与上面提到的类似的解决方法
真正的中期解决方案当然是按照 Tomcat 迁移指南中的说明调整我们的页面属性范围...