我一直在玩ASM ,并且我相信我成功地将 final 修饰符添加到类的实例字段中;但是,然后我继续实例化所述类并在其上调用 setter,这成功地更改了 now-final 字段的值。我的字节码更改是否有问题,还是最终仅由 Java 编译器强制执行?
更新:(7 月 31 日)这里有一些代码供您引用。主要部分是
private int x 和 private final int y 的简单 POJO,换句话说,我们从一个具有一个 final (x) 和一个 non-final (y) 字段的类开始。我们使 x 最终。除了设置 x 之外,我们还让 setX() 设置 y。我们跑。 x 和 y 都设置没有错误。 code is on github .你可以克隆它:
git clone git://github.com/zzantozz/testbed.git tmp
cd tmp/asm-playground
需要注意的两点:我首先提出这个问题的原因是:我设置为 final 的字段和已经设置为 final 的字段都可以设置为我认为的是普通的字节码指令。
另一个更新:(8 月 1 日)使用 1.6.0_26-b03 和 1.7.0-b147 进行测试,结果相同。也就是说,JVM 在运行时会愉快地修改 final 字段。
最终(?)更新:(9 月 19 日) 我从这篇文章中删除了完整的源代码,因为它相当冗长,但它仍然可以在 github 上找到(见上文)。
我相信我已经最终证明 JDK7 JVM 违反了规范。 (参见 excerpt in Stephen's answer 。)在使用 ASM 修改字节码后,如前所述,我将其写回到类文件中。使用优秀的JD-GUI ,这个类文件反编译成如下代码:
package rds.asm;
import java.io.PrintStream;
public class TestPojo
{
private final int x;
private final int y;
public TestPojo(int x)
{
this.x = x;
this.y = 1;
}
public int getX() {
return this.x;
}
public void setX(int x) {
System.out.println("Inside setX()");
this.x = x; this.y = x;
}
public String toString()
{
return "TestPojo{x=" +
this.x +
", y=" + this.y +
'}';
}
public static void main(String[] args) {
TestPojo pojo = new TestPojo(10);
System.out.println(pojo);
pojo.setX(42);
System.out.println(pojo);
}
}
简单的看一下应该会告诉你,由于重新分配了 final 字段,类永远不会编译,但是在普通的 JDK 6 或 7 中运行该类看起来像这样:
$ java rds.asm.TestPojo
TestPojo{x=10, y=1}
Inside setX()
TestPojo{x=42, y=42}
最佳答案
Is “final” final at runtime?
不是你的意思。
AFAIK,final 的语义修饰符仅由字节码编译器强制执行。
没有用于初始化 final 的特殊字节码字段,并且字节码 validator (显然)也不检查“非法”分配。
但是,JIT 编译器可能会处理 final修饰符作为不需要重新获取事物的提示。因此,如果您的字节码修改标记为 final 的变量您有可能导致不可预知的行为。 (如果您使用反射来修改 final 变量,也会发生同样的事情。规范清楚地说明了......)
当然,您可以修改 final使用反射的字段。
更新
我查看了 Java 7 JVM 规范,它与我上面所说的部分矛盾。具体来说,PutField 操作码的描述是:
"Linking Exceptions ... Otherwise, if the field is final, it must be declared in the current class, and the instruction must occur in an instance initialization method (
<init>) of the current class. Otherwise, anIllegalAccessErroris thrown.".
所以,虽然您可以(理论上)分配给 final字段多次在对象的构造函数中,字节码 validator 应该阻止任何尝试加载包含分配给 final 的字节码的方法。 .哪个...当您想到 Java 安全沙箱时...是一件好事。
关于java - "final"在运行时是最终的吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6881288/
总的来说,我对ruby还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用
我需要在客户计算机上运行Ruby应用程序。通常需要几天才能完成(复制大备份文件)。问题是如果启用sleep,它会中断应用程序。否则,计算机将持续运行数周,直到我下次访问为止。有什么方法可以防止执行期间休眠并让Windows在执行后休眠吗?欢迎任何疯狂的想法;-) 最佳答案 Here建议使用SetThreadExecutionStateWinAPI函数,使应用程序能够通知系统它正在使用中,从而防止系统在应用程序运行时进入休眠状态或关闭显示。像这样的东西:require'Win32API'ES_AWAYMODE_REQUIRED=0x0
我正在尝试测试是否存在表单。我是Rails新手。我的new.html.erb_spec.rb文件的内容是:require'spec_helper'describe"messages/new.html.erb"doit"shouldrendertheform"dorender'/messages/new.html.erb'reponse.shouldhave_form_putting_to(@message)with_submit_buttonendendView本身,new.html.erb,有代码:当我运行rspec时,它失败了:1)messages/new.html.erbshou
我在从html页面生成PDF时遇到问题。我正在使用PDFkit。在安装它的过程中,我注意到我需要wkhtmltopdf。所以我也安装了它。我做了PDFkit的文档所说的一切......现在我在尝试加载PDF时遇到了这个错误。这里是错误:commandfailed:"/usr/local/bin/wkhtmltopdf""--margin-right""0.75in""--page-size""Letter""--margin-top""0.75in""--margin-bottom""0.75in""--encoding""UTF-8""--margin-left""0.75in""-
在选择我想要运行操作的频率时,唯一的选项是“每天”、“每小时”和“每10分钟”。谢谢!我想为我的Rails3.1应用程序运行调度程序。 最佳答案 这不是一个优雅的解决方案,但您可以安排它每天运行,并在实际开始工作之前检查日期是否为当月的第一天。 关于ruby-如何每月在Heroku运行一次Scheduler插件?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/8692687/
为了将Cucumber用于命令行脚本,我按照提供的说明安装了arubagem。它在我的Gemfile中,我可以验证是否安装了正确的版本并且我已经包含了require'aruba/cucumber'在'features/env.rb'中为了确保它能正常工作,我写了以下场景:@announceScenario:Testingcucumber/arubaGivenablankslateThentheoutputfrom"ls-la"shouldcontain"drw"假设事情应该失败。它确实失败了,但失败的原因是错误的:@announceScenario:Testingcucumber/ar
exe应该在我打开页面时运行。异步进程需要运行。有什么方法可以在ruby中使用两个参数异步运行exe吗?我已经尝试过ruby命令-system()、exec()但它正在等待过程完成。我需要用参数启动exe,无需等待进程完成是否有任何rubygems会支持我的问题? 最佳答案 您可以使用Process.spawn和Process.wait2:pid=Process.spawn'your.exe','--option'#Later...pid,status=Process.wait2pid您的程序将作为解释器的子进程执行。除
我尝试运行2.x应用程序。我使用rvm并为此应用程序设置其他版本的ruby:$rvmuseree-1.8.7-head我尝试运行服务器,然后出现很多错误:$script/serverNOTE:Gem.source_indexisdeprecated,useSpecification.Itwillberemovedonorafter2011-11-01.Gem.source_indexcalledfrom/Users/serg/rails_projects_terminal/work_proj/spohelp/config/../vendor/rails/railties/lib/r
Sinatra新手;我正在运行一些rspec测试,但在日志中收到了一堆不需要的噪音。如何消除日志中过多的噪音?我仔细检查了环境是否设置为:test,这意味着记录器级别应设置为WARN而不是DEBUG。spec_helper:require"./app"require"sinatra"require"rspec"require"rack/test"require"database_cleaner"require"factory_girl"set:environment,:testFactoryGirl.definition_file_paths=%w{./factories./test/
我真的很习惯使用Ruby编写以下代码:my_hash={}my_hash['test']=1Java中对应的数据结构是什么? 最佳答案 HashMapmap=newHashMap();map.put("test",1);我假设? 关于java-等价于Java中的RubyHash,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/22737685/