JVM 如何处理标记接口

发布于 2024-12-10 11:05:38 字数 73 浏览 0 评论 0原文

标记界面没有任何东西。它只包含接口声明,那么JVM如何处理实现这个标记接口的类呢?

我们可以创建任何新的标记接口吗?

Marker interface doesn't has any thing. It contains only interface declarations, then how it is handled by the JVM for the classes which implements this marker interface?

Can we create any new marker interfaces ?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

随风而去 2024-12-17 11:05:38

您的问题实际上应该是编译器如何处理标记接口,答案是:与任何其他接口没有什么不同。例如,假设我声明一个新的标记接口 Foo:

public interface Foo {
}

...,然后声明一个实现 Foo 的类 Bar

public class Bar implements Foo {
  private final int i;

  public Bar(int i) { this.i = i; }
}

我现在能够通过 Foo 类型的引用来引用 Bar 的实例:

Foo foo = new Bar(5);

... 并检查(在运行时)对象是否实现 Foo

if (o instanceof Foo) {
  System.err.println("It's a Foo!");
}

后一种情况通常是使用标记接口背后的驱动程序;前一种情况几乎没有什么好处,因为没有可以在 Foo 上调用的方法(无需首先尝试向下转型)。

Your question should really be how does the compiler handle marker interfaces, and the answer is: No differently from any other interface. For example, suppose I declare a new marker interface Foo:

public interface Foo {
}

... and then declare a class Bar that implements Foo:

public class Bar implements Foo {
  private final int i;

  public Bar(int i) { this.i = i; }
}

I am now able to refer to an instance of Bar through a reference of type Foo:

Foo foo = new Bar(5);

... and also check (at runtime) whether an object implements Foo:

if (o instanceof Foo) {
  System.err.println("It's a Foo!");
}

This latter case is typically the driver behind using marker interfaces; the former case offers little benefit as there are no methods that can be called on Foo (without first attempting a downcast).

红ご颜醉 2024-12-17 11:05:38

那么 JVM 如何处理实现的类
这个标记接口?

实现 Java 标记接口的类实例受益于特定行为,因为某些 JDK 类或 HotSpot JVM 为他们提供特定的行为。

Serialized 接口为例。
如果您深入研究 ObjectOutputStreamObjectInputStream,您可以看到序列化/反序列化行为的实现。

这是 ObjectOutputStream.writeObject0() 调用方式ObjectOutputStream.writeObject() 说明:

public class ObjectOutputStream extends OutputStream implements ObjectOutput, ObjectStreamConstants {

   ...
   private void writeObject0(Object obj, boolean unshared) throws IOException   {
            ...    
            if (obj instanceof String) {
                writeString((String) obj, unshared);
            } else if (cl.isArray()) {
                writeArray(obj, desc, unshared);
            } else if (obj instanceof Enum) {
                writeEnum((Enum<?>) obj, desc, unshared);
            } else if (obj instanceof Serializable) {
                writeOrdinaryObject(obj, desc, unshared);
            } else {
                if (extendedDebugInfo) {
                    throw new NotSerializableException(
                        cl.getName() + "\n" + debugInfoStack.toString());
                } else {
                    throw new NotSerializableException(cl.getName());
                }
            }
            ...
    }
}

对于 Cloneable 接口,查看 Object.clone() 方法,您将看到它指的是应用Cloneable规范的本机方法。

在 HotSpot 源代码中, src\share\vm\prims\jvm.cpp,可以找到Object.clone() 实现:

JVM_ENTRY(jobject, JVM_Clone(JNIEnv* env, jobject handle))
  JVMWrapper("JVM_Clone");
  Handle obj(THREAD, JNIHandles::resolve_non_null(handle));
  const KlassHandle klass (THREAD, obj->klass());
  JvmtiVMObjectAllocEventCollector oam;

  // I skip all the processing that you can read in the actual source file
  ...

  return JNIHandles::make_local(env, oop(new_obj));
JVM_END 

对于此标记接口,其行为不是直接在 JDK 类中实现,而是由 JVM 本身实现,但总体思路是相同的。

我们可以创建任何新的标记界面吗?

如果您创建自己的标记接口,则应该像 JVM 和 JDK 类那样处理实现 Java 标记接口的类的内置实例:即添加代码来专门处理标记接口的实例。
Adamski 的非常好的答案展示了这样做的总体思路。

then how it is handled by the JVM for the classes which implements
this marker interface?

Instances of class implementing a Java marker interface benefit from a specific behavior because some JDK classes or the HotSpot JVM provide a specific behavior for them.

For example take the Serializable interface.
If you dig into ObjectOutputStream and ObjectInputStream you can see that the serialization/unserialization behavior are implemented in.

Here is a snippet of ObjectOutputStream.writeObject0() invoking by ObjectOutputStream.writeObject() that illustrates that :

public class ObjectOutputStream extends OutputStream implements ObjectOutput, ObjectStreamConstants {

   ...
   private void writeObject0(Object obj, boolean unshared) throws IOException   {
            ...    
            if (obj instanceof String) {
                writeString((String) obj, unshared);
            } else if (cl.isArray()) {
                writeArray(obj, desc, unshared);
            } else if (obj instanceof Enum) {
                writeEnum((Enum<?>) obj, desc, unshared);
            } else if (obj instanceof Serializable) {
                writeOrdinaryObject(obj, desc, unshared);
            } else {
                if (extendedDebugInfo) {
                    throw new NotSerializableException(
                        cl.getName() + "\n" + debugInfoStack.toString());
                } else {
                    throw new NotSerializableException(cl.getName());
                }
            }
            ...
    }
}

For the Cloneable interface, look at the Object.clone() method and you will see that it refers a native method that applies the Cloneable specification.

In the HotSpot source code, the src\share\vm\prims\jvm.cpp, you can find the Object.clone() implementation :

JVM_ENTRY(jobject, JVM_Clone(JNIEnv* env, jobject handle))
  JVMWrapper("JVM_Clone");
  Handle obj(THREAD, JNIHandles::resolve_non_null(handle));
  const KlassHandle klass (THREAD, obj->klass());
  JvmtiVMObjectAllocEventCollector oam;

  // I skip all the processing that you can read in the actual source file
  ...

  return JNIHandles::make_local(env, oop(new_obj));
JVM_END 

For this marker interface the behavior is not directly implemented in a JDK class but by the JVM itself but the general idea is the same.

Can we create any new marker interfaces ?

If you create your own marker interfaces, you should do as the JVM and the JDK classes do to handle built-in instances of class implementing a Java marker interface : that is adding code to handle specifically the instances of your marker interfaces.
The very good answer of Adamski shows the general idea to do that.

萌酱 2024-12-17 11:05:38

就编译器和 JVM 而言,标记接口和任何其他接口之间绝对没有区别。

是的,您可以根据需要创建标记界面。

As far the compiler and the JVM are concerned, there is absolutely no difference between a marker interface and any other interface.

And yes, you can create marker interfaces as you please.

慕烟庭风 2024-12-17 11:05:38

我觉得这背后可能有一些逻辑。当尝试调用clone()而不实现Cloneable时,我们如何得到CloneNotSupportedException,除非编译器有一些指导方针来在看到clone()时检查一些事情!

http://javamagic .wordpress.com/2011/12/02/marker-interface-in-java-what-why-uses-etc/

根据此线程( 标记接口混乱),这些都是标记接口.........可序列化、Clonable、SingleThreadModel、EventListener、RandomAccess、Remote 等。

如果幕后没有逻辑,或者 JVM/编译器没有特殊指令来区别对待它们,那么它们为什么会表现得像预期的那样(& JVM/编译器理解 Clonable 和 Serialized 之间的区别)?

I feel that there might be some logic behind the scenes. How else we get the CloneNotSupportedException when try calling clone() without implementing Cloneable, unless the compiler has some guidelines to check on few things when it sees the clone()!

http://javamagic.wordpress.com/2011/12/02/marker-interface-in-java-what-why-uses-etc/

As per this thread( Confusion in marker interface ), these are all Marker Interfaces .......... Serializable, Clonable, SingleThreadModel, EventListener, RandomAccess, Remote etc.

If there is no logic behind the scene OR no special instructions for JVM/compiler to treat them differently, how come they behave as ONLY what is expected out of them (& JVM/compiler understands the difference between Clonable & Serializable)?

清风挽心 2024-12-17 11:05:38

标记接口有助于识别所检查的对象是否实际上是我们感兴趣的类型(实现的接口)。但是它与其他接口没有什么不同(除了它们没有任何行为义务)

例如, < code>ObjectOutputStream可以发现,如果一个类实现了Serialized,那么用户已经明确表示同意该对象可以被序列化。

The marker interface helps identify that whether the object under inspection is actually a type (implemented interface) we are interested in. However it is not different than the other interfaces (except that they don't have any behavior obligation)

For example, the ObjectOutputStream can find that if a class implements Serializable, then the user has explicitly shown his consent that the object can be serialized.

寂寞花火° 2024-12-17 11:05:38

在这种情况下,“可序列化”这个词很令人困惑,因为像我这样的许多新手程序员都认为它意味着“可序列化”接口执行序列化,即将抽象数据类型转换为字节的过程。但正如文献所示,可序列化接口只是一个“标记”,将 ADT 转换为字节的真正工作(我将其称为获取元数据的过程)是由 ObjectOutputStream 完成的。类似地,反序列化是由 ObjectInputStream 完成的。

The word "serializable" is confusing in this context, as many novice programmers like myself take it to mean that "serializable" interface does the serialization, i.e. the process of converting the abstract data type to bytes. But as the literature shows, serializable interface is just a "marker" and the real work of converting ADT to bytes (I will call this the process of getting metadata) is done by ObjectOutputStream. Similarly deserialization is done by ObjectInputStream.

陪你搞怪i 2024-12-17 11:05:38

clone() 为例。实际上clone()是在Object类中定义的。但它是受保护的。仅当您的类实现 Cloneable 接口时才可以使用它。因此,当您实现Cloneable时,您就获得了使用clone()的权利。接口不包含任何方法!知道了 ?

Take Exampe of clone(). Actually clone() is defined inside Object class. But it is protected. You can use it only if your class is implementing Cloneable interface. So what happens is, when you implement Cloneable, you get the right to use clone(). Interface doesn't contain any methods! Got it ?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文