2015-12-11 63 views
0

我想用檢測代碼生成一個隨機數。爲此我添加了以下表達式來生成一個隨機數。但它正在拋出一個驗證錯誤,如下所示。如何獲得周圍java.lang.verrifyError

method.addLocalVariable("instMethod_correlationId", CtClass.longType); 
beforeBuilder.append("instMethod_correlationId = Long.valueOf(String.valueOf(System.nanoTime()) + String.valueOf(Math.round(Math.random())));"); 

我已經添加了一個長變量並分配上面生成的值。但我在運行時遇到下面的異常。但是如果我在一個正常的項目中運行相同的數字生成,它不會拋出任何異常。

java.lang.VerifyError: Bad type on operand stack 
Exception Details: 
    Location: 
    org/h2/jdbc/JdbcConnection.prepareStatement(Ljava/lang/String;)Ljava/sql/PreparedStatement; @38: i2l 
    Reason: 
    Type 'java/lang/Long' (current frame, stack[0]) is not assignable to integer 
    Current Frame: 
    bci: @38 
    flags: { } 
    locals: { 'org/h2/jdbc/JdbcConnection', 'java/lang/String', top, long, long_2nd } 
    stack: { 'java/lang/Long' } 
    Bytecode: 
    0000000: b803 6c42 bb03 6e59 b703 6fb8 036c b803 
    0000010: 73b6 0376 b803 7cb8 0380 b803 73b6 0376 
    0000020: b603 81b8 0386 8537 05b8 038b b803 8e16 
    0000030: 0513 0390 b603 94bb 0396 59b7 0397 3a07 
    0000040: 1907 1303 992b b903 9d03 0057 b803 8bb8 
    0000050: 038e 1605 1303 9f19 07b6 03a2 2a06 b600 
    0000060: 113d 2ab6 002a 9900 272a 1237 061c bb00 
    0000070: 1659 b700 1712 38b6 0019 2a2b b600 1db6 
    0000080: 0019 1234 b600 19b6 0020 b600 2d2a b600 
    0000090: 2e2a 2bb7 0039 4cbb 003a 592a 2b1c 1103 
    00000a0: ebb2 0030 03b7 003b a700 0a4d 2a2c b600 
    00000b0: 28bf 3a09 bb03 9659 b703 973a 0a19 0a13 
    00000c0: 03a4 1303 a6b9 039d 0300 57b8 038b b803 
    00000d0: 8e16 05bb 036e 59b7 036f 1303 a8b6 0376 
    00000e0: b803 6c21 65b8 0373 b603 76b6 0381 190a 
    00000f0: b603 a219 09b0       
    Exception Handler Table: 
    bci [55, 168] => handler: 171 
    Stackmap Table: 
    full_frame(@141,{Object[#320],Object[#331],Integer,Long,Long,Object[#918]},{}) 
    full_frame(@171,{Object[#320],Object[#331],Top,Long,Long},{Object[#322]}) 
    full_frame(@178,{Object[#320],Object[#331],Integer,Long,Long,Object[#918]},{Object[#58]}) 

    at org.h2.Driver.connect(Driver.java:73) 
    at org.apache.tomcat.jdbc.pool.PooledConnection.connectUsingDriver(PooledConnection.java:278) 
    at org.apache.tomcat.jdbc.pool.PooledConnection.connect(PooledConnection.java:182) 
    at org.apache.tomcat.jdbc.pool.ConnectionPool.createConnection(ConnectionPool.java:701) 
    at org.apache.tomcat.jdbc.pool.ConnectionPool.borrowConnection(ConnectionPool.java:635) 
    at org.apache.tomcat.jdbc.pool.ConnectionPool.getConnection(ConnectionPool.java:188) 
    at org.apache.tomcat.jdbc.pool.DataSourceProxy.getConnection(DataSourceProxy.java:128) 
    at org.wso2.carbon.user.core.claim.dao.ClaimDAO.getDialectCount(ClaimDAO.java:158) 
    at org.wso2.carbon.user.core.common.DefaultRealm.populateProfileAndClaimMaps(DefaultRealm.java:429) 
    at org.wso2.carbon.user.core.common.DefaultRealm.init(DefaultRealm.java:105) 
    at org.wso2.carbon.user.core.common.DefaultRealmService.initializeRealm(DefaultRealmService.java:262) 
    at org.user.core.common.DefaultRealmService.<init>(DefaultRealmService.java:99) 
    at org.user.core.common.DefaultRealmService.<init>(DefaultRealmService.java:112) 
    at org.user.core.internal.Activator.startDeploy(Activator.java:68) 
    at org.user.core.internal.BundleCheckActivator.start(BundleCheckActivator.java:61) 
    at org.eclipse.osgi.framework.internal.core.BundleContextImpl$1.run(BundleContextImpl.java:711) 
    at java.security.AccessController.doPrivileged(Native Method) 
    at org.eclipse.osgi.framework.internal.core.BundleContextImpl.startActivator(BundleContextImpl.java:702) 
    at org.eclipse.osgi.framework.internal.core.BundleContextImpl.start(BundleContextImpl.java:683) 
    at org.eclipse.osgi.framework.internal.core.BundleHost.startWorker(BundleHost.java:381) 
    at org.eclipse.osgi.framework.internal.core.AbstractBundle.resume(AbstractBundle.java:390) 
    at org.eclipse.osgi.framework.internal.core.Framework.resumeBundle(Framework.java:1176) 
    at org.eclipse.osgi.framework.internal.core.StartLevelManager.resumeBundles(StartLevelManager.java:559) 
    at org.eclipse.osgi.framework.internal.core.StartLevelManager.resumeBundles(StartLevelManager.java:544) 
    at org.eclipse.osgi.framework.internal.core.StartLevelManager.incFWSL(StartLevelManager.java:457) 
    at org.eclipse.osgi.framework.internal.core.StartLevelManager.doSetStartLevel(StartLevelManager.java:243) 
    at org.eclipse.osgi.framework.internal.core.StartLevelManager.dispatchEvent(StartLevelManager.java:438) 
    at org.eclipse.osgi.framework.internal.core.StartLevelManager.dispatchEvent(StartLevelManager.java:1) 
    at org.eclipse.osgi.framework.eventmgr.EventManager.dispatchEvent(EventManager.java:230) 
    at org.eclipse.osgi.framework.eventmgr.EventManager$EventThread.run(EventManager.java:340) 

我該怎麼辦才能克服這個問題?我在這裏做錯了什麼?

+0

這是版本問題,你需要檢查你是否使用相同的版本或需要檢查庫也.. –

+0

版本和庫的什麼? h2或javassist或java? – udani

回答

2

看來您在Javassist的字節碼生成器中遇到了一個錯誤。以下是從VerifyError報告的反彙編代碼。需要注意的是由於沒有異常消息常量池中,實際目標的方法是從你的源代碼猜(但它看起來似是而非):

0 invokestatic [876] 
    3 lstore_3 
    4 new  [878]   guess: new StringBuilder 
    7 dup 
    8 invokespecial [879] guess: StringBuilder.<init> 
11 invokestatic [876] guess: System.nanoTime() 
14 invokestatic [883] guess: String.valueOf(long) 
17 invokevirtual [886] guess: StringBuilder.append(String) 
20 invokestatic [892] guess: Math.random() 
23 invokestatic [896] guess: Math.round(double) 
26 invokestatic [883] guess: String.valueOf(long) 
29 invokevirtual [886] guess: StringBuilder.append(String) 
32 invokevirtual [897] guess: StringBuilder.toString() 
35 invokestatic [902] guess: Long.valueOf(String) 
38 i2l 
39 lstore <5> 
… rest omitted 

注意,方法調用符合你的源代碼片段(是static或虛擬的如預期的那樣並且是相同的參考,應該是相同的),而位置38(被驗證者拒絕的那個)的指令是虛假的i2l指令(從intlong的轉換)。在這個地方,應該發生從Longlong的拆箱轉換。由於以下lstore指令會將long值存儲到局部變量中,所以似乎Javassist已獲得本地變量聲明。

請注意,前兩個指令表明還有另一個儀器正在發生;因爲它調用的方法與位置11(應該是System.nanoTime)中的指令的調用方式相同,所以其他工具似乎用於測量方法的總體執行時間。但是這不應該影響你的檢測代碼。

您可以聯繫Javassist的作者,瞭解Long拆箱是否可行。與此同時,您可以通過使用Long.parseLong而不是Long.valueOf來避免拳擊/拆箱。您也可以通過使用String.concat代替+操作的簡化從生成代碼的角度來看,操作這消除了需要處理StringBuilder內部:

更換

method.addLocalVariable("instMethod_correlationId", CtClass.longType); 
beforeBuilder.append("instMethod_correlationId = Long.valueOf(String.valueOf(System.nanoTime()) + String.valueOf(Math.round(Math.random())));"); 

method.addLocalVariable("instMethod_correlationId", CtClass.longType); 
beforeBuilder.append("instMethod_correlationId = Long.parseLong(String.valueOf(System.nanoTime()).concat(String.valueOf(Math.round(Math.random()))));"); 

這應該降低對Javassist編譯功能的要求,並解決由原始代碼片段觸發的錯誤。