Тяжело сказать что такое Canadian Mind Products. Энциклопедия что-ли?
Зато вот о Roedy Green’s Java & Internet Glossary можно сказать лишь одно - просто замечательнейший reference/documentation по Java. Пользуюсь часто и всем советую. Почти каждая страница содержит описание книжек по теме.
Visual Studio по функциональности и удобству заставляет курить в сторонке все IDE для плюсов. Но, некоторых мелочей, все же, очень не хватает. А иногда они просто хорошо спрятаны...
Довольно часто приходится вставлять куски кода вида hr = GetLastError();, запускать Error Lookup чтобы
прочитать человеческим языком что же произошло. Я уже давно пользуюсь одним из более удобных способов:
HRESULT, то окошки дебаггера Visual Studio (Watch #, Autos,
Locals etc) автоматически отображают в колонке Value строку ошибки вместо кода.err или @err отображает текущее числовое значение
GetLastError(). А для отображения строки вместо числа нужно применить форматирование - добавить через
запятую hr. Пример: @err,hr.
Visual Studio поддерживает множество форматов. Подробнее - Visual Studio Debugger --> Format Specifiers in C++
@eax,hr
расскажет нам в чем беда.Есть и другие псевдопеременные -
$handles, $vframe, $TID, $ENV, $CMDLINE,
@registername или $registername, $clk, $user. Приятно, а?
Хостинг усправляемого кода в программных продуктах уже не редкость. Oracle поддерживает выполнение байткода JVM
еще с 8-й версии и периодически выполняет апгрейд виртуальной машины (11g поставляется с версией 1.5). Сравнительно
недавно добавили поддержку .NET 1.1 и .NET 2.0. Microsoft SQL Server 2005 имеет поддержку CLR 2.0 и, кстати,
внутренняя архитектура последнего была усовершенствована (скорее заточена
) под задачи хостинга. Дальше я
расскажу, как добавить возможность выполнять JVM-код в приложение, написанное на С++.
Первое, что необходимо сделать, - поставить Java Development Kit версии 6. Далее в настройках проекта прописать папку
поиска заголовочных файлов JDK -
"C:\Program Files\Java\jdk1.6.0_03\include\", папку с библиотечными
файлами - "C:\Program Files\Java\jdk1.6.0_03\lib" и добавить путь поиска jvm.dll -
C:\Program Files\Java\jdk1.6.0_03\jre\bin\client\ как написано здесь. Еще нужно закинуть файл
"c:\Program Files\Java\jdk1.6.0_03\include\win32\jni_md.h" в папку с проектом и включить его в проект.
Традиционно изменяем stdafx.h:
#include <jni.h> #pragma comment(lib, "jvm.lib")
Перед использованием, виртуальную машину Java необходимо загрузить и инициализировать. По-сути, она является песочницей (sandbox) для выполняемого байт-кода, другими словами, мини-операционной системой в пределах хост-процесса. Инициализация предполагает создание управляющих структур, выделение пулов памяти и других ресурсов ОС, связанных с конкретным екземпляром JVM (да, их можно создать несколько).
jint jRet;
JavaVMOption options[1];
options[0].optionString = "-verbose:class,gc,jni";
JavaVMInitArgs jvmInitArgs;
jvmInitArgs.version = JNI_VERSION_1_6;
jvmInitArgs.nOptions = _countof(options);
jvmInitArgs.options = options;
jvmInitArgs.ignoreUnrecognized = JNI_TRUE;
JavaVM *pJvm;
JNIEnv *pEnv;
jRet = JNI_CreateJavaVM(&pJvm, reinterpret_cast<LPVOID*>(&pEnv), &jvmInitArgs);
if (jRet != JNI_OK) {
// Это залет, солдат!
cout << "JNI_CreateJavaVM returned " << jRet << endl;
return(jRet);
}
Структура JavaVMInitArgs содержит настройки создания екземпляра JVM - запрашиваемую версию и различные
конфигурационные параметры. Функция JNI_CreateJavaVM, как нетрудно догадаться из ее названия, создает
виртуальную машину и возвращает указатель на управляющий интерфейс - JNIEnv. Любые дальнейшие манипуляции
выполняются посредством него.
Не буду оригинален. Вашему вниманию представляется вариант "Hello World" в исполнении C++/Java:
void printHelloWorld(JNIEnv *pEnv) {
jclass classSystem = pEnv->FindClass("java/lang/System");
jfieldID fieldId = pEnv->GetStaticFieldID(classSystem, "out", "Ljava/io/PrintStream;");
jobject system_out = pEnv->GetStaticObjectField(classSystem, fieldId);
jclass classPrintStream = pEnv->FindClass("java/io/PrintStream");
jmethodID methodId = pEnv->GetMethodID(classPrintStream, "println", "(Ljava/lang/String;)V");
jvalue v;
v.l = pEnv->NewStringUTF("Hello World!");
pEnv->CallVoidMethodA(system_out, methodId, &v);
if (jthrowable ex = pEnv->ExceptionOccurred()) {
pEnv->ExceptionDescribe();
pEnv->ExceptionClear();
}
}
По завершению работы с JVM рантайм нужно удалить:
jRet = pJvm->DestroyJavaVM();
if (jRet != JNI_OK) {
cout << "pJvm->DestroyJavaVM() returned " << jRet << endl;
return(jRet);
}