HP-UX: B.11.31 U ia64
Джава: 7 или 8
Весна-загрузка: 1.5.3.RELEASE
Кот: 8.5.14
Обновить: Похоже, проблема с Java JNI / JVM под HP-UX, поскольку мы не получаем эту ошибку под RHEL
org.apache.tomcat.util.net.NioEndpoint$Acceptor run
SEVERE: Socket accept failed
java.nio.channels.NotYetBoundException
У меня есть приложение весенней загрузки, которое использует встроенный сервер Tomcat. JAR был переупакован как myapp-exec.jar
используя spring-boot: repackage, чтобы его можно было выполнить из командной строки с помощью java -jar и успешно запустить в качестве автономного модуля только для целей тестирования. Тот же код, доступный в оригинальном JAR myapp.jar
без всех сведений о BOOT-INF и подпружиненной загрузке предназначен для выполнения в производстве с помощью JVM, встроенной в приложение C ++. Из-за процесса переупаковки это невозможно с помощью переупакованного JAR.
Таким образом, для правильной работы встроенной JVM C ++ все библиотеки, доступные в перепакованном JAR, также должны быть доступны по пути к классам для встроенной JVM C ++. Это достигается путем извлечения BOOT-INF / lib из перепакованного JAR с использованием jar -xvf myapp-exec.jar
и перемещение каталога BOOT-INF / lib в целевое расположение пути к классам. Файлы JAR включаются в определение CLASSPATH в том же порядке, в котором они отображаются в переупакованном JAR. Это работает просто отлично, и этот принцип применяется к ряду других проектов, использующих точно такую же инфраструктуру приложения C ++ без проблем.
Проблема здесь, кажется, со встроенным сервером Tomcat. У меня проблема в том, что сервер Tomcat, который работает нормально, когда выполняется перепакованный JAR, не инициализируется правильно при запуске встроенной JVM C ++.
Любая помощь с благодарностью получена!
Spring-boot приложение запускается так:
spring_application = new SpringApplication(IncidentConfiguration.class);
IncidentSubscribe subscriber = null;
try
{
spring_context = spring_application.run(args);
subscriber = (IncidentSubscribe) spring_context.getBean("incidentSubscribe");
synchronized (subscriber)
{
if (subscriber.start())
{
subscriber.wait();
}
else
{
log.warn("failed to start Web-Service platform!");
}
}
}
catch (InterruptedException ex)
{
log.info("thread interrupted");
}
Запустите встроенный Tomcat
Feb 08, 2018 6:06:05 PM org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainer initialize
INFO: Tomcat initialized with port(s): 8080 (http)
Feb 08, 2018 6:06:05 PM org.apache.catalina.core.StandardService startInternal
INFO: Starting service Tomcat
Feb 08, 2018 6:06:05 PM org.apache.catalina.core.StandardEngine startInternal
INFO: Starting Servlet Engine: Apache Tomcat/8.5.14
Инициализирует AbstractProtocol (не выполнено при успешном запуске)
Feb 08, 2018 6:06:12 PM org.springframework.jmx.export.MBeanExporter afterSingletonsInstantiated
INFO: Registering beans for JMX exposure on startup
Feb 08, 2018 6:06:12 PM org.apache.coyote.AbstractProtocol init
INFO: Initializing ProtocolHandler ["http-nio-8080"]
Feb 08, 2018 6:06:13 PM org.apache.coyote.AbstractProtocol start
INFO: Starting ProtocolHandler ["http-nio-8080"]
Feb 08, 2018 6:06:13 PM org.apache.tomcat.util.net.NioSelectorPool getSharedSelector
INFO: Using a shared selector for servlet write/read
SEVERE: ошибка повторяет 1000 раз …
Feb 08, 2018 6:06:13 PM org.apache.tomcat.util.net.NioEndpoint$Acceptor run
SEVERE: Socket accept failed
java.nio.channels.NotYetBoundException
at sun.nio.ch.ServerSocketChannelImpl.accept(ServerSocketChannelImpl.java:237)
at org.apache.tomcat.util.net.NioEndpoint$Acceptor.run(NioEndpoint.java:453)
at java.lang.Thread.run(Thread.java:745)
Здесь происходит нечто иное …
Feb 08, 2018 6:06:13 PM org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainer start
INFO: Tomcat started on port(s): -1 (http)
Feb 08, 2018 6:06:14 PM org.springframework.boot.StartupInfoLogger logStarted
INFO: Started application in 23.874 seconds (JVM running for 33.524)
Приложение C ++ обнаруживает сбой при запуске и завершает загрузку
08/02 18:06:15.127[26491][0:1:Thread-2] XXXAdapter.java:144 ***Warning: start() - stop the embeded TOMCAT server
Feb 08, 2018 6:06:15 PM org.springframework.context.support.AbstractApplicationContext doClose
INFO: Closing org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@545866ff: startup date [Thu Feb 08 18:05:55 GMT 2018]; root of context hierarchy
Feb 08, 2018 6:06:15 PM org.springframework.jmx.export.MBeanExporter destroy
INFO: Unregistering JMX-exposed beans on shutdown
Feb 08, 2018 6:06:15 PM org.apache.coyote.AbstractProtocol pause
INFO: Pausing ProtocolHandler ["http-nio-8080"]
Feb 08, 2018 6:06:15 PM org.apache.tomcat.util.net.AbstractEndpoint unlockAccept
WARNING: Failed to unlock acceptor for [http-nio-8080] because the local address was not available
Feb 08, 2018 6:06:15 PM org.apache.catalina.core.StandardService stopInternal
INFO: Stopping service Tomcat
Feb 08, 2018 6:06:15 PM org.apache.coyote.AbstractProtocol stop
INFO: Stopping ProtocolHandler ["http-nio-8080"]
Feb 08, 2018 6:06:15 PM org.apache.coyote.AbstractProtocol destroy
INFO: Destroying ProtocolHandler ["http-nio-8080"]
Запустите встроенный Tomcat
Feb 08, 2018 6:39:26 PM org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainer initialize
INFO: Tomcat initialized with port(s): 8080 (http)
Feb 08, 2018 6:39:26 PM org.apache.catalina.core.StandardService startInternal
INFO: Starting service Tomcat
Feb 08, 2018 6:39:26 PM org.apache.catalina.core.StandardEngine startInternal
INFO: Starting Servlet Engine: Apache Tomcat/8.5.14
Здесь происходит нечто иное …
Feb 08, 2018 6:39:33 PM org.springframework.jmx.export.MBeanExporter afterSingletonsInstantiated
INFO: Registering beans for JMX exposure on startup
Feb 08, 2018 6:39:33 PM org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainer start
INFO: Tomcat started on port(s): 8080 (http)
Feb 08, 2018 6:39:33 PM org.springframework.boot.StartupInfoLogger logStarted
INFO: Started XXXApplication in 19.691 seconds (JVM running for 26.538)
Затем он закрывается …
Feb 08, 2018 6:39:33 PM org.springframework.context.support.AbstractApplicationContext doClose
INFO: Closing org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@423419: startup date [Thu Feb 08 18:39:17 GMT 2018]; root of context hierarchy
Feb 08, 2018 6:39:33 PM org.springframework.jmx.export.MBeanExporter destroy
INFO: Unregistering JMX-exposed beans on shutdown
Feb 08, 2018 6:39:33 PM org.apache.catalina.core.StandardService stopInternal
INFO: Stopping service Tomcat
ОК, фреймворк C ++ содержит гораздо больше функций, чем просто start()
метод, так как это довольно сложно, я извлек соответствующие биты и убрал большинство кодов проверки ошибок и освобождения ресурсов для ясности.
Общая структура JVM
struct
{
JavaVM* handle; ///< Handle to Java Virtual Machine (JVM).
jclass adapterClass; ///< JNI jclass for user class.
jobject adapterObject; ///< JNI jobject for instance of user class.
jmethodID adapterStart; ///< JNI method ID of 'start' function for user class.
jclass XXXAdapterClass; ///< JNI jclass for class XXXAdapter.
jmethodID AdapterClassLoader; ///< JNI method ID for static method setClassLoader.
} JVM;
Конфигурация и инициализация JVM
JavaVMInitArgs vm_args;
vm_args.nOptions = count;
vm_args.options = options;
vm_args.version = JNI_VERSION_1_4;
vm_args.ignoreUnrecognized = JNI_FALSE;
// Create the Java Virtual Machine
JNIEnv* jni = NULL;
int success = (JNI_CreateJavaVM((JavaVM**)&JVM.handle, (void**)&jni, &vm_args) != JNI_ERR);
if (!success)
{
SM_Throw(AdapterException, "error creating Java Virtual Machine (JVM)");
}
// locate parent class and class loader for use later
//
JVM.XXXAdapterClass = jni->FindClass( "com/xxx/XXXAdapter" );
JVM.AdapterClassLoader = jni->GetStaticMethodID( JVM.XXXAdapterClass, "setClassLoader", "()V")) )jclass j_adapterClass = 0;
jobject j_adapterObject = 0;
jmethodID j_adapterInit = 0;
// locate the user specified AdapterClass
//
j_adapterClass = jni()->FindClass(adapter_class_path)) )
// check it is inherited from XXXAdapter class
//
jni->IsAssignableFrom(j_adapterClass, JVM.XXXAdapterClass) )
// locate the default class constructor
//
j_adapterInit = jni->GetMethodID( j_adapterClass, "<init>", "()V");
// create a new adapter object for this service
//
j_adapterObject = jni->NewObject( j_adapterClass, j_adapterInit );
// save service adapter instance as a Java global object
//
JVM.adapterObject = jni->NewGlobalRef(j_adapterObject);
// save user adapter class as a Java global reference
//
JVM.adapterClass = jni->NewGlobalRef(j_adapterClass);JVM.adapterStart = jni->GetMethodID( j_adapterClass, "start", "()V");
jni->DeleteLocalRef(j_adapterClass);
jni->DeleteLocalRef(j_adapterObject);
jni->ExceptionClear();
и, наконец, вызовите адаптер start()
функция
JNIEnv* jni;
// attach to current Java thread to get handle to JNI environment
//
if (JVM.handle->AttachCurrentThread((void**)&jni, NULL) < 0)
{
SM_Throw(AdapterException, "JAVAAdapter: error during AttachCurrentThread!");
}
// always use the parent class ClassLoader
//
jni->CallStaticVoidMethod(JVM.XXXAdapterClass, JVM.AdapterClassLoader, NULL);
if (jni->ExceptionCheck())
{
jni->ExceptionDescribe();
SM_Throw(WarningException, "JAVAAdapter: error during setClassLoader!" );
}
// *** DO THE CALL ***
//
jni->CallVoidMethod(JVM.adapterObject, JVM.adapterStart);// and detach from current Java thread
//
JVM.handle->DetachCurrentThread();
Задача ещё не решена.
Других решений пока нет …