我一直在调查这个错误整整三天,但仍然没有进展.我希望我能从这里得到一些提示.
我想要做的是使用ASM库将MethodNode内联到MethodHandle调用站点(#5,#17和#30).为简化起见,#5处的MethodHandle引用静态方法static Functions.isFooString(String)boolen.
在呼叫站点,内联之前的指令就像
//Before
stack=3, locals=3, args_size=3
0: aload_0
1: getfield #15 // Field guard:Ljava/lang/invoke/MethodHandle;
4: aload_1
5: invokevirtual #29 // Method java/lang/invoke/MethodHandle.invokeExact:(Ljava/lang/String;)Z
8: ifeq 24
11: aload_0
12: getfield #17 // Field trueTarget:Ljava/lang/invoke/MethodHandle;
15: aload_1
16: aload_2
17: invokevirtual #31 // Method java/lang/invoke/MethodHandle.invokeExact:(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
20: checkcast #33 // class java/lang/String
23: areturn
24: aload_0
25: getfield #19 // Field falseTarget:Ljava/lang/invoke/MethodHandle;
28: aload_1
29: aload_2
30: invokevirtual #31 // Method java/lang/invoke/MethodHandle.invokeExact:(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
33: checkcast #33 // class java/lang/String
36: …Run Code Online (Sandbox Code Playgroud) 我正在开发一个小型Spring应用程序.我必须将学生信息的详细信息存储在数据库中.我开发了一个SimpleFormController.我使用过NetBeans + Hibernate映射+ Spring.部署项目时,会发生以下错误.
我的spring-config-db-applicationContext.xml如下所示:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
"http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<!-- Hibernate session factory -->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<constructor-arg index="0">
<value>${driverClassName}</value>
</constructor-arg>
<constructor-arg index="1">
<value>${url}</value>
</constructor-arg>
<constructor-arg index="2">
<value>${username}</value>
</constructor-arg>
<constructor-arg index="3">
<value>${password}</value>
</constructor-arg>
</bean>
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource">
<ref bean="dataSource"/>
</property>
<!-- <property name="configLocation">
<value>WEB-INF/classes/hibernate.cfg.xml</value>
</property> -->
<property name="mappingResources" >
<list>
<value>hibernate.cfg.xml</value>
</list>
</property>
<!-- <property name="configurationClass">
<value>org.hibernate.cfg.AnnotationConfiguration</value>
</property> -->
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">${dialect}</prop>
<prop key="hibernate.show_sql">true</prop>
<!--<prop key="hibernate.hbm2ddl.auto">create</prop>-->
</props>
</property>
</bean>
<bean …Run Code Online (Sandbox Code Playgroud) 有一些框架用于动态字节码生成,操作和编织(BCEL,CGLIB,javassist,ASM,MPS).我想了解它们,但由于我没有太多时间知道所有这些细节,我希望看到一种比较图表,说明一种与其他的优缺点,以及对为什么.
在SO中,我发现了许多类似问题的问题,答案通常说"你可以使用cglib或ASM",或者"javassist比cglib更好",或者"BCEL已经老了,正在死"或"ASM是最好的,因为它给出X和Y".这些答案很有用,但并没有完全回答我想要的范围内的问题,更深入地比较它们并给出每个问题的优点和缺点.
bytecode-manipulation cglib javassist java-bytecode-asm jvm-bytecode
我一直在玩ASM,我相信我成功地将final修饰符添加到了类的实例字段中; 然后我继续实例化所述类并在其上调用一个setter,它成功地改变了now-final字段的值.我的字节码更改有问题,还是仅由Java编译器最终强制执行?
更新:(7月31日)这里有一些代码供您使用.主要部分是
private int x和private final int y,换句话说,我们从一个具有一个final(x)和一个非final(y)字段的类开始.我们让x最终.除了设置x之外,我们使setX()设置为y.我们跑.x和y都设置为没有错误.该代码在GitHub上.你可以用以下方法克隆它:
git clone git://github.com/zzantozz/testbed.git tmp
cd tmp/asm-playground
Run Code Online (Sandbox Code Playgroud)
需要注意的两件事:我首先提出这个问题的原因是:我做了最后一个字段和一个已经是最终字段的字段都可以设置为我认为是正常的字节码指令.
另一个更新:(8月1日)使用1.6.0_26-b03和1.7.0-b147进行测试,结果相同.也就是说,JVM在运行时愉快地修改了最终字段.
最终(?)更新:(9月19日)我正在从这篇文章中删除完整的源代码,因为它相当冗长,但它仍然可以在github上看到(见上文).
我相信我已经最终证明JDK7 JVM违反了规范.(请参阅Stephen的回答摘录.)如前所述,在使用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) { …Run Code Online (Sandbox Code Playgroud) 在一个非常简单的HelloWorld应用程序上运行javap时,我对常量池周围的输出有些困惑.
测试代码
public class TestClass {
public static void main(String[] args) {
System.out.println("hello world");
}
}
Run Code Online (Sandbox Code Playgroud)
Javap -c -verbose输出(剪切)
// Header + consts 1..22 snipped
const #22 = String #23; // hello world
const #23 = Asciz hello world;
public static void main(java.lang.String[]);
Signature: ([Ljava/lang/String;)V
Code:
Stack=2, Locals=1, Args_size=1
0: getstatic #16; //Field java/lang/System.out:Ljava/io/PrintStream;
3: ldc #22; //String hello world
5: invokevirtual #24; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
8: return
// Debug info snipped
}
Run Code Online (Sandbox Code Playgroud)
好的,所以在第3行我们看到通过#22将"hello world"常量推送到堆栈上,但const#23似乎保持实际值.我想我对#(数字)在打印输出右侧出现时的含义有点困惑.
Oracle/Sun的javap手册页有很多不足之处.
在Java中,存储密码的旧方法(如密码)可以使用,char[]因为您可以在完成后覆盖其数据.然而,由于垃圾收集器在重新组织堆时会复制内容,因此这被证明是不安全的.在某些体系结构中,可能会释放页面,并且当其他程序分配同一页面时,秘密将保留.
这非常难看,但是如果秘密存储在Thread run方法的堆栈上呢?仍需要注意优雅地终止线程,以便它可以将其数据清零,但这个问题也以旧的方式出现.
我直接看到的一个主要问题是我无法想到一种安全的方法来获取数据进出容器.您可以通过使用具有非常小的内部缓冲区的流来最小化泄露秘密的可能性,但最终您最终会遇到与此相同的问题char[].[编辑:单个private static byte成员和国旗会有效吗?虽然这会限制每个ClassLoader一个秘密.这增加了更多的丑陋,但它可能很容易隐藏在一个写得很好的界面后面.]
所以我真的有很多问题.
堆栈比这些类型的攻击更安全吗?是否有任何纯Java机制以对这个问题有用的方式在两个不同的堆栈帧之间执行堆栈到堆栈的复制?如果没有,JVM是否甚至支持字节码中的这种类型的操作?
[编辑:在人们过分担心之前,这更像是一个思想实验而不是其他任何东西.我绝对没有打算"在生产中测试"或在任何当前项目中使用它.我意识到我所说的内容真的很难看,可能非常笨重,并且可以对抗整个JVM结构.我只是对它是否有可能感兴趣,它是否真正实现了我的目标,以及它需要什么样的英雄才能实现目标.
有人可以指向我的Java框架或别名分析实现.我查看了asm框架,但它只提供数据流分析和控制流分析.
更新:只是好奇,但有人知道Findbugs是否进行别名分析?
java compiler-construction optimization code-analysis java-bytecode-asm
我想避免在我正在开发的开源项目中反思.在这里,我有类似以下的课程.
public class PurchaseOrder {
@Property
private Customer customer;
@Property
private String name;
}
Run Code Online (Sandbox Code Playgroud)
我扫描@Property注释以确定我可以设置和反射性地从PurchaseOrder获取.有许多这样的类都使用java.lang.reflect.Field.get()和java.lang.reflect.Field.set().
理想情况下,我想为每个属性生成如下调用者.
public interface PropertyAccessor<S, V> {
public void set(S source, V value);
public V get(S source);
}
Run Code Online (Sandbox Code Playgroud)
现在,当我扫描类时,我可以创建一个PurchaseOrder类似的静态内部类.
static class customer_Field implements PropertyAccessor<PurchaseOrder, Customer> {
public void set(PurchaseOrder order, Customer customer) {
order.customer = customer;
}
public Customer get(PurchaseOrder order) {
return order.customer;
}
}
Run Code Online (Sandbox Code Playgroud)
有了这些,我完全避免了反思的代价.我现在可以使用原生性能设置并从我的实例中获取.任何人都可以告诉我如何做到这一点.代码示例会很棒.我在网上搜索了一个很好的例子但是却找不到这样的东西.ASM和Javasist的例子也很差.
这里的关键是我有一个可以传递的界面.所以我可以有各种各样的实现,也许有一个用Java反射作为默认,一个用ASM,一个用Javassist?
任何帮助将不胜感激.
user=> (def r (range 1))
user=> (for [a r, b r, c r, d r, e r, f r, g r, h r :when (and (= 0 a) (not= 1 b))]
(list a b c d e f g h))
((0 0 0 0 0 0 0 0))
user=> (doseq [a r, b r, c r, d r, e r, f r, g r, h r :when (and (= 0 a) (not= 1 b))]
(println (list a b c d …Run Code Online (Sandbox Code Playgroud) 随着ASMDEX(dex文件的ASM)和dexmaker的出现,不应该将Groovy移植到Android吗?两个框架都允许在运行时生成dex字节码.
据我了解,不可能在内存中修改APK中的dex类.但是不可能将这些类复制到可写内存,在运行时修改这些副本并使用它们吗?
还需要移植什么来处理dex类文件?CGLIB?