2017-03-06 51 views
-1

我想修改一個現有的jar來更改用戶憑證,因爲我丟失了一些代碼。修改一個jar:ClassFormatError:未知的常量標記

當我運行該jar時,我得到一個sql異常,因爲它由於憑據不正確和服務器url不正確而無法連接。我試着提取負責數據庫連接的類文件,更改它中的字符串(它們是硬編碼的字符串常量),然後將修改後的類文件放回jar中,然後執行它。

當我將密碼更改爲恰好與原始密碼長度相同的密碼時,我仍然收到sql異常。但是,當我改變數據庫的URL,通過具有較大長度的字符串替換它,我得到

Exception in thread "main" java.lang.reflect.InvocationTargetException 
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) 
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) 
at java.lang.reflect.Method.invoke(Unknown Source) 
at org.eclipse.jdt.internal.jarinjarloader.JarRsrcLoader.main(JarRsrcLoader.java:58) 
Caused by: java.lang.ClassFormatError: Unknown constant tag 51 in class file 

我不明白是怎麼回事。從我所知道的,類文件大小不存儲在類文件中。此外,從搜索特定的異常,看起來其他人誰得到它已損壞的類文件,這是一個很好的答案,但在我的情況下,我希望得到異常時更改密碼,它不應該依賴在字符串長度。

有沒有人明白爲什麼會發生這種情況? 另外,有沒有一種方法可以有效地實現我的目標,即更改類文件中的硬編碼字符串並讓jar正常運行?

編輯

public class TestEdit { 
public static final String OUTPUT = "TEST"; 

public static void main(String[] args) { 
    System.out.println(OUTPUT); 
} 

}

所以我編這個類在一個罐子,打開了類文件,並改變 「TEST」 到 「newTest」。我把類文件放回到jar中,並運行它,並得到了異常。現在我再次編輯了類文件,並將「TEST」更改爲「增長」,並將其放回並運行。這一次它工作。我認爲如果我通過編輯破壞了類文件,那麼第二個更改也會拋出異常,但它不會。它似乎有什麼做的字符串長度

+0

看來你損壞了類文件中的[常量池]條目(https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html#jvms-4.4) ,而不是或者除了更改密碼字符串。 –

+0

我不認爲這是事實,因爲當我用「本地主機」,原始值替換服務器IP,並將類文件放回jar中,我再次得到sql異常 – yemista

+0

那麼,什麼'java.lang.ClassFormatError:未知類文件中的常量標籤51意味着什麼? –

回答

3

的「Java®的虛擬機規範」的相關部分是§4.4.7, The CONSTANT_Utf8_info Structure

The CONSTANT_Utf8_info structure is used to represent constant string values:

CONSTANT_Utf8_info { 
    u1 tag; 
    u2 length; 
    u1 bytes[length]; 
} 

The items of the CONSTANT_Utf8_info structure are as follows:

tag

The tag item of the CONSTANT_Utf8_info structure has the value CONSTANT_Utf8 (1).

length

The value of the length item gives the number of bytes in the bytes array (not the length of the resulting string).

bytes[]

The bytes array contains the bytes of the string.

所以,如果你正在尋找它沒有專門的類文件解析器和識別字符串內容,在第一個字符確定字符串的長度之前的兩個字節(解釋爲大端無符號短)。

如果用一個長度相同的字符串覆蓋字符串內容(假設爲全ASCII字符),它將起作用,但如果您在不修改length信息的情況下將其更改爲不同長度的字符串,則類文件解析器將嘗試在舊位置找到下一個常量池項目。在第一次嘗試中,如果將其更改爲更長的字符串,它會在原始字符串結束後的位置找到字節51,換句話說,字符爲'3'

如果您正確調整長度,則根據這些項目的長度/位置,類文件中確實沒有其他信息。