- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
我正在创建一个类似于 java.util.LinkedList
的类,但得到了一个完全出乎意料的 ClassFormatError
。我的 IDE 没有显示任何警告。仅供引用,我正在使用 Java 8u20。 更新:在 Java 8u60 中修复。
T̶h̶i̶s̶̶i̶n̶c̶l̶u̶d̶e̶s̶̶a̶l̶l̶̶r̶e̶l̶e̶v̶a̶n̶t̶̶m̶e̶t̶h̶o̶d̶s̶:̶更新示例为完全可编译:
import java.io.Serializable;
import java.util.*;
import java.util.function.Function;
public class Foo<E> implements Deque<E>, Serializable {
private static final long serialVersionUID = 0L;
private final Node sentinel = sentinelInit();
private final Iterable<Node> nodes = (Iterable<Node> & Serializable) () -> new Iterator<Node>() {
@SuppressWarnings("UnusedDeclaration")
private static final long serialVersionUID = 0L;
private Node next = sentinel.next;
@Override
public boolean hasNext() {
return next != sentinel;
}
@Override
public Node next() {
if (!hasNext()) {
throw new NoSuchElementException();
}
Node old = next;
next = next.next;
return old;
}
@Override
public void remove() {
if (next.previous == sentinel) {
throw new IllegalStateException();
}
removeNode(next.previous);
}
};
@Override
public boolean isEmpty() {
return false;
}
@Override
public Object[] toArray() {
return new Object[0];
}
@Override
public <T> T[] toArray(T[] a) {
return null;
}
@Override
public boolean containsAll(Collection<?> c) {
return false;
}
@Override
public boolean removeAll(Collection<?> c) {
return false;
}
@Override
public boolean retainAll(Collection<?> c) {
return false;
}
@Override
public void clear() {
}
@Override
public void addFirst(E e) {
}
@Override
public void addLast(E e) {
}
@Override
public boolean offerLast(E e) {
return false;
}
@Override
public E removeFirst() {
return null;
}
@Override
public E removeLast() {
return null;
}
@Override
public E pollFirst() {
return null;
}
@Override
public E getFirst() {
return null;
}
@Override
public E getLast() {
return null;
}
@Override
public E peekFirst() {
return null;
}
@Override
public boolean removeFirstOccurrence(Object o) {
return false;
}
@Override
public boolean removeLastOccurrence(Object o) {
return false;
}
@Override
public E remove() {
return null;
}
@Override
public E element() {
return null;
}
@Override
public void push(E e) {
}
@Override
public E pop() {
return null;
}
@Override
public boolean contains(Object o) {
return false;
}
@Override
public boolean offerFirst(E e) {
return false;
}
@Override
public E pollLast() {
return null;
}
@Override
public E peekLast() {
return null;
}
@Override
public boolean offer(E e) {
Node node = new Node(e);
sentinel.previous.next = node;
node.previous = sentinel.previous;
sentinel.previous = node;
node.next = sentinel;
return true;
}
@Override
public E poll() {
return null;
}
@Override
public E peek() {
return null;
}
@Override
public boolean remove(Object o) {
for (Node node : nodes) {
if (node.value.equals(o)) {
removeNode(node);
return true;
}
}
return false;
}
@Override
public int size() {
return 0;
}
@Override
public Iterator<E> descendingIterator() {
return null;
}
@Override
public Iterator<E> iterator() {
return new Iterator<E>() {
private final Iterator<Node> backingIter = nodes.iterator();
@Override
public boolean hasNext() {
return backingIter.hasNext();
}
@Override
public E next() {
return backingIter.next().value;
}
@Override
public void remove() {
backingIter.remove();
}
};
}
private Node sentinelInit() {
Node sentinel = new Node();
sentinel.next = sentinel;
sentinel.previous = sentinel;
return sentinel;
}
private void removeNode(Node node) {
node.previous.next = node.next;
node.next.previous = node.previous;
}
private class Node implements Serializable {
private static final long serialVersionUID = 0L;
public E value;
public Node next;
public Node previous;
public Node(E value) {
this.value = value;
}
public Node() {
this(null);
}
}
public static <I, O> List<O> map(Function<? super I, O> function, Iterable<I> objects) {
ArrayList<O> returned = new ArrayList<>();
for (I obj : objects) {
returned.add(function.apply(obj));
}
return returned;
}
@Override
public boolean addAll(Collection<? extends E> c) {
boolean ret = false;
for (boolean changed : map(this::add, c)) {
if (changed) {
ret = true;
}
}
return ret;
}
@Override
public boolean add(E e) {
if (!offer(e)) {
throw new IllegalStateException();
}
return true;
}
public static void main(String[] args) {
Foo<String> list = new Foo<>();
System.out.println("Constructed list");
list.addAll(Arrays.asList("a", "B", "c"));
System.out.println("Added a, B and c.");
list.forEach(System.out::println);
list.remove("B");
list.forEach(System.out::println);
}
}
这是输出:
Constructed list
Added a, B and c.
Exception in thread "main" java.lang.ClassFormatError: Duplicate field name&signature in class file uk/org/me/Foo$1
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClass(ClassLoader.java:760)
at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
at java.net.URLClassLoader.defineClass(URLClassLoader.java:455)
at java.net.URLClassLoader.access$100(URLClassLoader.java:73)
at java.net.URLClassLoader$1.run(URLClassLoader.java:367)
at java.net.URLClassLoader$1.run(URLClassLoader.java:361)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:360)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
at uk.org.me.Foo.lambda$new$c83cc381$1(Foo.java:18)
at uk.org.me.Foo$$Lambda$1/1392838282.iterator(Unknown Source)
at uk.org.me.Foo$2.<init>(Foo.java:222)
at uk.org.me.Foo.iterator(Foo.java:221)
at java.lang.Iterable.forEach(Iterable.java:74)
at uk.org.me.Foo.main(Foo.java:300)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:134)
最佳答案
您的代码是有效的,ClassFormatError
是由于 Java 8 编译器中的错误造成的。我认为您已经发现了一个边缘案例:加载为 lambda 表达式主体生成的类文件,其中包含一个与该主体中被覆盖的方法同名的变量可能会失败。
我将您的代码粘贴到最新版本的 Intellij Idea (13.1.5)、NetBeans (8.0.1) 和 Eclipse (Kepler SR2) 中。在所有情况下编译的代码。运行时,它在 NetBeans 和 Idea 中因 ClassFormatError
而失败,但在 Eclipse 中运行良好。
堆栈跟踪显示错误是由于尝试加载由分配给实例变量 Foo.nodes
的 lamba 表达式生成的类失败而引起的。根本原因是在分配给 Foo.nodes
的 lambda 主体中,您有一个变量 next
与覆盖方法 next()
同名>。
正如您已经注意到的,如果您将声明 private Node next = sentinel.next;
中的变量重命名为某个唯一值(例如 next2
),问题就来了离开。同样,将其重命名为不同的覆盖方法(即 remove
或 hasNext
)会导致问题再次出现。 ClassFormatError
(“Duplicate field name&signature”)附带的消息准确描述了问题,但根本没有解释为什么这应该是一个如此精确定义的运行时错误;编译的代码,并且方法和变量具有相同的名称是合法的(如果不明智的话)。在 next 前加前缀“this”。没有解决问题。
在失败的 Idea 类文件(在我的例子中是 foo/Foo$1
)上运行 javap 显示:
C:\Idea\Java8\Foo\out\production\Foo\foo>"C:\Program Files\Java\jdk1.8.0_20\bin\javap.exe" Foo$1.class
Compiled from "Foo.java"
class foo.Foo$1 implements java.util.Iterator<foo.Foo<E>.Node> {
final foo.Foo this$0;
foo.Foo$1(foo.Foo);
public boolean hasNext();
public foo.Foo<E>.Node next();
public void remove();
}
但是,在运行良好的相应 Eclipse 类上运行 javap 会显示一个额外的条目:
public java.lang.Object next();
如果 lambda 主体中的变量 next
被重命名为唯一的东西,那么额外的方法条目也会神奇地出现在 Idea 类文件中,从而允许代码运行。我建议您将此作为编译器错误报告给 JetBrains。
此外,作为一个不相关的问题,Iterator
接口(interface)将 remove()
实现为 Java 8 中的默认方法。因为您永远不会调用 Iterator.remove( )
你可以删除你的两个实现。
更新:我针对 Oracle 的这个问题提出了一个错误 ( JDK-8080842 ),并且将在 1.8.0_60 版本中修复它。
更新更新 (8/27/15):Oracle 已在 8u60 之后的所有版本中修复了此问题。我验证了针对 8u60 的修复。错误 JDK-8080842 引用。
关于java - Java 8 中的 ClassFormatError?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24580370/
从 Eclipse 运行程序时它工作正常。 在 Eclipse 之外运行它时,我得到了这个: java.lang.ClassFormatError: Duplicate method name&si
我尝试在我的网络应用程序中使用小程序。 小程序类: public class TestApplet extends JApplet { @Override public void in
使用 ASM,我将一个方法中的代码替换为另一个方法。该方法称为“checkIfShouldDisconnect”,使用BytecodeOutline插件,我获得了我想要转换的源代码的ASM代码。但是,
我的项目有问题,经过一些测试后我认为它与源代码无关。即使回到以前的工作修订版,我在尝试部署到 Tomcat 时仍然会收到错误消息。 错误是由 java.lang.ClassFormatError 引起
我需要开发一个示例应用程序并将其部署在 Linux 中并进行测试。 问题是我得到了 Exception in thread "main" java.lang.ClassFormatError: com
最近我遇到了这个错误 Caught: java.lang.ClassFormatError: Illegal field modifier in class **** : 0x3 java.lang.
我正在运行一个已部署并在诺基亚 S60 sdk 上运行的 midlet 应用程序。我想让我的应用程序在每个 java 和 symbian 设备上运行。我尝试在 Java_ME_platform_SDK
我正在尝试使用 EMMA 生成代码覆盖率报告使用一些测试 JMockit作为模拟框架。在大多数情况下,它是有效的,但我的一些测试因 ClassFormatError 而崩溃,如下所示: java.la
在研究 Java,特别是字节码编辑时,我偶然发现了 this tutorial ,它指导您完成使用十六进制编辑器编辑已编译的 Java .class 文件的步骤。出于好奇,我尝试了一下。 我确保我输入
我正在创建一个类似于 java.util.LinkedList 的类,但得到了一个完全出乎意料的 ClassFormatError。我的 IDE 没有显示任何警告。仅供引用,我正在使用 Java 8u
欢迎, 我写了简单的测试类形式示例a JavaMail API – Sending email - by mkyong工作完美,但如果我在没有主方法的情况下创建单独的类,如下所示: import co
我正在尝试使用 EMMA 来衡量一些使用 JMockit 的 JUnit 测试的覆盖率。但是当我在使用 EMMA 进行检测后尝试运行 JMockit 测试时,大约四分之一的测试失败并出现以下错误: c
感谢这里的一些帮助。 刚刚安装了Android Studio 1.5.1(使用1.2之后)。然后我创建了一个新项目来尝试并在事件日志中显示以下内容: 7:15:26 PM ClassFormatErr
当我尝试在已注释的 @Controller 方法中使用 @Secured 或 @PreAuthorize 时,抛出了一个奇怪的错误@RequestMapping。当我尝试启动应用程序时(在 win 7
我正在使用Equinox Transforms将一个类替换为类路径上该类的自定义版本。转换机制似乎工作正常,我从转换器类的 public InputStream getInputStream(Inpu
我正在玩《我的世界》,我玩的客户端有一个错误,导致我的《我的世界》在退出后崩溃,所以我想修复这个问题。我反编译客户端并在 NetBeans 中编辑 .java 文件(我编辑得很少),然后将该文件另存为
这个问题在这里已经有了答案: How to properly install and configure JSF libraries via Maven? (1 个回答) 关闭 7 年前。 在我的
我正在使用以下方法从 jar 条目(仅包含类文件)中读取字节。 jar里面没有jar文件。 private List readFromJarFile(File cp) { List cbyte
控制台错误:- Initial SessionFactory creation failed.java.lang.ClassFormatError: Absent Code attribute in
我正在使用 javassist 来更改方法体。当该方法在应用程序中定义时我可以做到这一点。但是,当我想更改应用程序使用的 jar 文件中定义的方法时,我会收到以下运行时错误: javassist.Ca
我是一名优秀的程序员,十分优秀!