【问题标题】:When we create an object using new operator, does it use the actual .class file to create an object in java当我们使用 new 运算符创建对象时,它是否使用实际的 .class 文件在 java 中创建对象
【发布时间】:2018-06-09 01:00:39
【问题描述】:

我对某个主题感到困惑,无法在网上找到它。 据我了解,当程序启动时,类加载器会加载.class 文件并将它们作为Class 类型的对象存储在内存中。

我的问题是我们什么时候使用:

Test test = new Test();

是使用.class 文件创建的新对象,还是使用内存中的Class 对象?

【问题讨论】:

  • 我认为不清楚的部分是 据我了解,当程序启动时,类加载器会加载 .class 文件并将它们作为 Class 类型的对象存储在内存中。
  • 错了吗?如果是这样,你能指出我可以学习执行周期的方向吗@YCF_L

标签: java class classloader new-operator


【解决方案1】:

一旦一个类被加载到 JVM 中,同一个类将不会被同一个类加载器再次加载。新实例将从内存中的类对象创建(对于相同的类加载器)。

高级步骤(复制自https://www.ibm.com/developerworks/java/tutorials/j-classloader/j-classloader.html

  1. 调用 findLoadedClass 查看是否已经加载了类。
  2. 如果尚未加载类,请使用 findClass 获取字节(由类加载器实现覆盖)。
  3. 如果找到原始字节,则调用 defineClass 将它们转换为 Class 对象。 (AppClassLoader 中的示例)
  4. 如果类已解析,则调用 resolveClass 来解析 Class 对象。
  5. 如果仍然没有类,则抛出 ClassNotFoundException。

    protected synchronized Class<?> loadClass(String name, boolean resolve)
    throws ClassNotFoundException
    {
        // First, check if the class has already been loaded
      Class c = findLoadedClass(name);
         if (c == null) {
            try {
                if (parent != null) {
                  c = parent.loadClass(name, false);
                 } else {
                    c = findBootstrapClass0(name);
                }
            } catch (ClassNotFoundException e) {
                // If still not found, then invoke findClass in order
               // to find the class.
                 c = findClass(name);
             }
         }
        if (resolve) {
           resolveClass(c);
         }
        return c;
    }
    

以下所有示例将打印相同的 hashCode 并引用相同的 Test.class

    Test  test1 = new Test();
    Test test2 = new Test();
    System.out.println(test2.getClass().hashCode());
    System.out.println(test1.getClass().hashCode());
    System.out.println(Test.class.hashCode());

更多详情 http://www.onjava.com/pub/a/onjava/2005/01/26/classloading.html?page=1

【讨论】:

  • If raw bytes found, call defineClass to turn them into a Class object. 那么从这一点开始,将使用该 Class 对象创建新实例?在我的情况下,我可以使用 Test.class 访问它?
  • 是的,您甚至可以从 ClassLoader 创建自定义类加载并尝试查找类 docs.oracle.com/javase/1.5.0/docs/api/java/lang/…
  • 对于第二个new Test() 表达式,JVM 甚至不会调用loadClass,因为每个类只解析一次相同的符号引用。这确保了一个类中对 Test 的所有引用始终解析为同一个类,即使您实现了一个自定义类加载器,该类加载器使用一种奇怪的方法覆盖了 loadClass……
【解决方案2】:

一个类 (.class) 被加载到 方法区域(每个 JVM 1 个)。这也是堆的逻辑部分。

因此,在您的情况下,Test.class 在通过 main 方法或其他一些类作为以下结构中的依赖项加载时将出现在方法区域中:

方法区为每个加载的类存储以下数据:

  1. 运行时常量池
  2. 字段和方法数据
  3. 方法和构造函数的代码

当遇到new Test() 时,将在堆中创建一个Test 类的新实例,该实例表示Test 类型的Object。

Where does class, object, reference variable get stored in java. IN heap or stack? Where is heap or stack located?

上面的帖子更清楚地解释了JVM中的存储原理。

【讨论】:

  • 您好,感谢您的回答.. 只是为了避免混淆.. 方法区域是否包含 class object (test.getClass()) 或是否包含 compiled .class 文件,即 Test.class 文件?
猜你喜欢
  • 1970-01-01
  • 2015-03-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多