Когда jvm загрузит импортированные классы для оператора instanceof?

Я провел обширные тесты и не смог сломать asio. Даже без блокировки каких-либо мьютексов.

Тем не менее я бы посоветовал вам использовать async_read и async_write с мьютексом вокруг каждого из этих вызовов.

Я считаю, что единственный обратный путь что ваши обработчики завершения могут быть вызваны одновременно, если у вас есть более одного потока, вызывающего io_service::run.

В моем случае это не было проблемой. Вот мой тестовый код:

#include <boost/thread.hpp>
#include <boost/date_time.hpp>
#include <boost/asio.hpp>
#include <vector>

using namespace std;
char databuffer[256];
vector<boost::asio::const_buffer> scatter_buffer;
boost::mutex my_test_mutex;
void my_test_func(boost::asio::ip::tcp::socket* socket, boost::asio::io_service *io) {
while(1) {
    boost::this_thread::sleep(boost::posix_time::microsec(rand()%1000));

    //my_test_mutex.lock(); // It would be safer 
    socket->async_send(scatter_buffer, boost::bind(&mycallback));
    //my_test_mutex.unlock(); // It would be safer
}
}
int main(int argc, char **argv) {

for(int i = 0; i < 256; ++i)
    databuffer[i] = i;

for(int i = 0; i < 4*90; ++i)
    scatter_buffer.push_back(boost::asio::buffer(databuffer));
boost::asio::io_service my_test_ioservice;
boost::asio::ip::tcp::socket my_test_socket(my_test_ioservice);
boost::asio::ip::tcp::resolver my_test_tcp_resolver(my_test_ioservice);
boost::asio::ip::tcp::resolver::query  my_test_tcp_query("192.168.1.10", "40000");
boost::asio::ip::tcp::resolver::iterator my_test_tcp_iterator = my_test_tcp_resolver.resolve(my_test_tcp_query);
boost::asio::connect(my_test_socket, my_test_tcp_iterator);
for (size_t i = 0; i < 8; ++i) {
    boost::shared_ptr<boost::thread> thread(
            new boost::thread(my_test_func, &my_test_socket, &my_test_ioservice));
}

while(1) {
    my_test_ioservice.run_one();
    boost::this_thread::sleep(boost::posix_time::microsec(rand()%1000));
}
return 0;

}

И вот мой временный сервер в python:

import socket
def main():
    mysocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    mysocket.bind((socket.gethostname(), 40000))
    mysocket.listen(1)

    while 1:
        (clientsocket, address) = mysocket.accept()
        print("Connection from: " + str(address))
        i = 0
        count = 0
        while i == ord(clientsocket.recv(1)):
            i += 1
            i %= 256

            count+=1
            if count % 1000 == 0:
                print(count/1000)
        print("Error!")
return 0

if __name__ == '__main__':
    main()

Обратите внимание, что запуск этого кода может заставьте ваш компьютер трэш.

0
задан T.J. Crowder 20 March 2019 в 07:57
поделиться

2 ответа

Вы можете проверить это следующим образом:

Main.java:

package test;

import test.sub.B;

public class Main {
   public static void main(String args[]) {
      System.out.println("Creating object");
      final B b = new B();
      System.out.println("instanceof check");
      if (b instanceof B) {
         // Do nothing
      }
   }
}

A.java:

package test;

public class A {
   static {
      System.out.println("Class A loaded");
   }
}

B.java:

[ 112]

Вывод:

Creating object
Class B loaded
instanceof check

Итак, ни импорт, ни объявление (A a;) не загружают класс.

Это соответствует утверждению из википедии: The Java Class Loader [...] dynamically loads Java classes [...]. [...] This loading is typically done "on demand", in that it does not occur until the class is called by the program. [...]

Когда вы изменяете A a; в классе B на A a = new A();, тогда класс A будет загружен.

0
ответ дан Marvin Klar 20 March 2019 в 07:57
поделиться

Следует отметить две вещи:

  1. Оператор import не влияет на поведение класса во время выполнения. Никакой код не генерируется для оператора импорта. И если вы просто импортируете класс A в класс B, то загрузка класса B не приводит к загрузке класса A.

  2. Время загрузки класса и время инициализации класса различаются.

Жизненный цикл класса заключается в том, что он загружается, связывается и инициализируется перед использованием (см. Глава 12 JLS ).

  • Загрузка выполняется загрузчиком классов и включает в себя поиск файла класса, чтение его в byte[] и вызов ClassLoader::defineClass.

  • Связывание выполняется с помощью основного кода JVM и состоит из проверки, подготовки и разрешения символических ссылок. В JLS 12.3 говорится следующее:

    Эта спецификация обеспечивает гибкость реализации в отношении того, когда происходит связывание действий (и, из-за рекурсии, загрузки), при условии, что семантика Язык программирования Java соблюдается, что класс или интерфейс полностью проверены и подготовлены перед его инициализацией, и что ошибки, обнаруженные во время связывания, генерируются в той точке программы, где программа предпринимает некоторые действия, которые могут потребовать связи с классом. или интерфейс, связанный с ошибкой.

    Это означает, что мы не можем определиться с тем, когда выполняются различные задачи.

  • Инициализация происходит после того, как все соответствующие классы были связаны. В соответствии с JLS 12.4.1 :

    Класс T или интерфейсный тип T будут инициализированы непосредственно перед первым появлением любого из следующего:

      [ 1145] T является классом, и создается экземпляр T.
    • Вызывается статический метод, объявленный T.
    • Статическое поле, объявленное T, присваивается.
    • Используется статическое поле, объявленное T, и поле не является постоянной переменной (§4.12.4).

Согласно JLS (см. Выше), мы не можем точно сказать, когда B будет загружен и связан. Все, что мы можем сказать, это то, что это происходит до инициализации B ... если она инициализирована. (Вы можете получить представление о порядке загрузки классов, включив некоторые журналы JVM. Однако, порядок может варьироваться в зависимости от поставщика и версии JVM.)

В соответствии с инициализацией JLS (см. Выше) [115 ] будет происходить (обычно), когда первый экземпляр B создается вашим методом main. Предполагая, что object в вашем Вопросе было инициализировано для экземпляра B, инициализация уже произошла до теста instanceof. Если нет, то B не будет инициализирован тестом instanceof.

На первый взгляд, нет необходимости загружать класс A. (Это зависит от того, действительно ли и как класс B использует класс A, и от того, как / как другие части вашей кодовой базы используют A.)

0
ответ дан Stephen C 20 March 2019 в 07:57
поделиться
Другие вопросы по тегам:

Похожие вопросы: