我正在尝试修改现有的jar来更改用户凭据,因为我丢失了一些代码。
当我运行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);
}
}
所以我在一个jar中编译了这个类,并打开了类文件,并改变了#34; TEST"到" newTest"。我把类文件放回到jar中并运行它,并获得异常。现在我再次编辑了类文件,并更改了#34; TEST"到"成长",把它放回去运行它。这次它奏效了。我认为如果我通过编辑它来破坏类文件,那么第二次更改也会抛出异常,但它不会。它似乎与字符串长度
有关答案 0 :(得分:3)
“Java®虚拟机规范”的相关部分是§4.4.7, The CONSTANT_Utf8_info
Structure
CONSTANT_Utf8_info
结构用于表示常量字符串值:CONSTANT_Utf8_info { u1 tag; u2 length; u1 bytes[length]; }
标签
CONSTANT_Utf8_info
结构的项目如下:长度
tag
结构的CONSTANT_Utf8_info
项的值为CONSTANT_Utf8
(1)。字节[]
length
项的值给出bytes
数组中的字节数(不是结果字符串的长度)。
bytes
数组包含字符串的字节。
因此,如果您在没有专用类文件解析器的情况下查看它并识别字符串内容,则在第一个字符之前的两个字节确定字符串的长度(解释为大端无符号短路)。
如果用相同长度的字符串覆盖字符串内容(假设全ASCII字符),它可以工作,但是如果你将它改为不同长度的字符串而不调整length
信息,类文件解析器将尝试在旧位置查找下一个常量池项。在您第一次尝试将其更改为更长的字符串时,它会在原始字符串结束后的位置找到字节51
,换句话说字符'3'
。
如果您正确调整长度,类文件中确实没有其他信息,具体取决于这些项目的长度/位置。