我针对Java Google App Engine 1.6.4.1 API编写了一些代码,为了让我的代码能够编译,我必须处理很多异常,例如ConcurrentModificationException。我升级到1.6.5,现在我可以删除大多数异常处理程序,我的代码编译得很好。发生了什么事?
更新:不再抛出几类异常;因为不同的例外,这可能是由于不同的原因而发生的,这里是不再被抛出的异常
抛出:IllegalArgumentException
IllegalStateException异常
DatastoreFailureException
ConcurrentModificationException的
以下是有人在GAE中获取IllegalArgumentException的示例:Google App Engine - "java.lang.IllegalArgumentException: datastore transaction or write too big."这是否会再次发生?
事务接口文档说您在执行commit()时可以获得最后三个中的任何一个:https://developers.google.com/appengine/docs/java/javadoc/com/google/appengine/api/datastore/Transaction#commit()
抛出:
java.lang.IllegalStateException - 如果事务已经存在 已提交,回滚,提交或回滚正在进行中(通过 异步调用),或尝试提交或回滚已失败。 如果此方法有任何未完成的异步数据存储区调用 调用后,此方法将阻止完成那些调用 在继续之前。
DatastoreFailureException - 如果发生数据存储错误。
java.util.ConcurrentModificationException - 如果有其他事务 同时修改了相同的实体组。
然而我不再需要处理它们以便让我的代码进行编译。这看起来很奇怪。
答案 0 :(得分:2)
Google App Engine的最新版本需要在appengine-web.xml中设置<threadsafe>true</threadsafe>
属性。在此版本之前,这不是必需的。
当多个线程同时修改应用程序中对象的单个实例时,会发生ConcurrentModificationExceptions。这当然会导致数据和结果不一致,并且某些类将抛出此异常,而不是返回错误数据或对数据库进行不一致的更改。
如果threadsafe属性设置为true,则现在启用并发请求。
<强> Using Concurrent Requests 强>
默认情况下,App Engine会将请求串行发送到给定的Web服务器。您可以将App Engine配置为通过将元素添加到appengine-web.xml:
来并行发送多个请求
<threadsafe>true</threadsafe>
在1.6.5之前,线程安全指令是可选的,在1.4.3中引入:
Java applications can enable concurrent request support by setting <threadsafe>
to True in their appengine-web.xml. This flag indicates that request handlers
for your app are thread safe and multiple request handlers may safely run
at the same time in the same memory space for your application.
虽然现在需要这样做,但似乎没有立即可用的任何信息可以解释为什么您的ConcurrentModificationExceptions突然消失了。如果您没有对代码进行更改以使其线程安全,正如1.4.3发行说明中所述,那么这些线程安全问题很可能仍然存在。
以下是有关博文Announcing App Engine 1.4.3 Release的1.4.3版本的更多信息:
并发请求:到目前为止,Java应用程序依赖于启动其他实例来动态扩展以获得更高的流量级别。现在支持并发请求,每个应用程序实例可以同时提供多个用户请求。首先,确保应用程序的代码是线程安全的,然后通过将标志添加到appengine-web.xml来启用并发请求。
如果您报告的异常消失,您的代码可能仍然存在一些线程安全问题。您可能没有看到这些,因为您增加了实例数量或在应用程序中执行了其他操作来缓解ConcurrentModificationExceptions。
考虑到1.6.5已经发布不到一个月,我会非常犹豫从我的代码中删除我的异常处理程序。毕竟,他们的工作是检测和处理发生的问题,如果你将它们移除,那么你就会失去在移除之前可能存在的任何优雅降级。
此外,缺少某些内容(例如例外情况)并不能证明某些内容将来不会出现在某个未知点。
来自javadocs for ConcurrentModificationException:
当不允许进行此类修改时,检测到并发修改对象的方法可能抛出此异常。
例如,一个线程修改Collection而另一个线程迭代它时通常不允许这样做。通常,在这些情况下,迭代的结果是不确定的。如果检测到此行为,某些Iterator实现(包括JRE提供的所有集合实现的实现)可能会选择抛出此异常。执行此操作的迭代器称为失败快速迭代器,因为它们快速而干净地失败,而不是在未来的未确定时间冒着任意的,非确定性行为的风险。
答案 1 :(得分:0)
我针对Java Google App Engine 1.6.4.1 API编写了一些代码,为了让我的代码能够编译,我必须处理很多异常,例如ConcurrentModificationException。
这里有点奇怪:ConcurrentModificationException和你列出的其他异常是RuntimeException的子类。您永远不需要捕获它们来满足Java编译器。