我最近将应用程序从 Java 1.8 升级到 Java 11,并开始看到此错误
com.pricemax.util.exceptions.IllegalUsageError: java.lang.ClassCastException: class [B cannot be cast to class [C ([B and [C are in module java.base of loader 'bootstrap')
at com.pricemax.util.helpers.CharHelper.toCharArray(CharHelper.java:77)
at com.pricemax.etl.steps.transform.price.PricePatternParser.parse(PricePatternParser.java:87)
at com.pricemax.etl.steps.transform.price.PatternPriceSelector.cleanPrice(PatternPriceSelector.java:227)
at com.pricemax.etl.steps.transform.price.PatternPriceSelector.cleanPrice(PatternPriceSelector.java:152)
at com.pricemax.etl.steps.transform.price.PatternPriceSelector.performTransform(PatternPriceSelector.java:99)
at com.pricemax.etl.steps.transform.BaseTransform.performTransformARC(BaseTransform.java:62)
at com.pricemax.etl.steps.transform.BaseTransform.transformARC(BaseTransform.java:49)
at com.pricemax.etl.process.parallel.TransformThread.doWork(TransformThread.java:99)
at com.pricemax.etl.process.parallel.BaseParallelThread.run(BaseParallelThread.java:57)
at java.base/java.lang.Thread.run(Thread.java:834)
Caused by: java.lang.ClassCastException: class [B cannot be cast to class [C ([B and [C are in module java.base of loader 'bootstrap')
at com.pricemax.util.helpers.CharHelper.toCharArray(CharHelper.java:73)
... 9 more
08/05/2022 17:46:47:0511 - [WARN] - Fatal error in parallel process
Run Code Online (Sandbox Code Playgroud)
当我到达 charHelper.java 类中的第 77 行时,我看到了这个函数 -
public static char[] toCharArray(String str) throws IllegalAccessException
{
try {
return (char[]) field.get(str); //line number 77
}
catch (Exception ex) {
throw new IllegalUsageError(ex);
}
}
Run Code Online (Sandbox Code Playgroud)
其中field是java.lang.reflect.Field类的实例,至少从错误中我可以解释的是错误正在将类类型 Byte (B) 转换为类类型 Character (C)。如果我理解错误,请纠正我,我该如何解决这个错误?注意 - 我注意到一些关于同样问题的 stackoverflow 文章,很少有人提到他们在从 java 1.8 迁移时遇到了同样的问题,但没有找到任何解决方案来解决这个问题。谢谢
您正在使用的某些代码使用了不受支持的黑客技术。正如不受支持的黑客攻击惯常做的那样,java 升级“破坏了它”。这不是java的错 - 文档的重点是“不要这样做 - 这是不支持的”(并且private
是“文档”大喊:不要这样做 - 这是不支持的),是未来的版本可能会更改这部分,并且不会特意说:危险!如果不采取这些步骤,请勿升级到此版本!
它滥用的具体黑客行为是,直到 java 8 左右,实例的内容java.lang.String
基本上只是一个东西:一个char[]
.
这是低效的;char 使用 16 位来存储单个字符。
如今,字符串由一个byte[]
和几个标志组成。这些标志在 64 位系统上是“自由”的(假设所有对象都对齐到可被 64 整除的边界上,并且大多数指针都被压缩)。一个标志告诉字符串字节代表什么。对于没有花哨的裤子字符的简单字符串,可能是简单的 ASCII,否则它将是 UTF;还有进一步计划的空间,但截至撰写本文时,这些是唯一的两个。
无论您使用什么代码都依赖于它是char[]
. 事实并非如此,使用反射来挖掘并获取它是一种失败的行为,而且从来没有真正的意义。我不知道为什么你使用的库要这样做(或者如果这是你的代码,为什么你这样做),但我怀疑这是正确的。就像,无论它试图解决什么问题,我敢打赌有更好的方法来做到这一点。
您不能只是简单地更新此代码并修复char[]
tobyte[]
部分:您还必须读取该标志才能了解字节的含义。无论执行此操作的代码是什么,都需要复杂得多。
从您的粘贴来看,您似乎编写了一个名为 的辅助方法toCharArray
,该方法与 执行完全相同的操作str.toCharArray()
,除了您不应该这样做的这种黑客方式。我无法理解这样做的意义或目的。也许是一场错误的“效率”运动,因为这个黑客避免了数组复制?一般来说,这不是获得高效代码的方法。鉴于对于绝大多数项目,不到 1% 的代码占用了 99% 的资源,因此您只需优化那 1%。通常,为了正确地做到这一点,您需要到处都有灵活的、高度抽象的代码,以便可以轻松地调整“围绕”这 1%“热路径”的内容,以精确地满足热路径必须运行的速度可能的。这些“微观优化”对性能的影响远大于其对性能的帮助。更不用说它使您的代码变得多么脆弱了。如果您需要证明 - 看看这个问题就不用再犹豫了:)