Заставьте JVM выращивать спрос на память по мере необходимости до размера предела VM?

Новые проекты Базы данных в Visual Studio обеспечивают управление исходным кодом и сценарии изменения.

у Них есть хороший инструмент, который сравнивает базы данных и может генерировать сценарий, который преобразовывает схему одной в другой или обновляет данные в одном для соответствия другому.

схема дб "измельчена" для создания многих, многих маленьких .sql файлов, один на команду DDL, которая описывает DB.

<час> +tom

Дополнительная информация 30.11.2008

я использовал его в качестве разработчика в течение прошлого года и действительно как он. Это облегчает сравнивать мою работу dev с производством и генерировать сценарий для использования для выпуска. Я не знаю, являются ли это недостающие возможности, в которых DBAs нуждаются для проектов "типа предприятия".

, поскольку схема "измельчена" в sql файлы, управление исходным кодом хорошо работает.

Один глюк - то, что у Вас должно быть различное мышление при использовании проекта дб. Инструмент имеет "проект дб" в VS, который является просто sql плюс автоматически сгенерированная локальная база данных, которая имеет схему и некоторые другие администраторские данные - но ни одни из Ваших данных приложения, плюс Ваш локальный dev дб, что Вы используете для данных приложения dev работу. Вы редко знаете об автоматически сгенерированном дб, но необходимо знать там, таким образом, можно оставить его в покое:). Этот специальный дб является явно распознаваемым, потому что он имеет Гуид на свое имя,

, Проект DB VS делает хорошее задание интегрирующихся изменений дб, которые другие члены команды превратили в Ваш локальный дб проекта/связанный. но необходимо сделать дополнительный шаг, чтобы сравнить схему проекта с локальной dev схемой дб и применить модификации. Это имеет смысл, но это кажется неловким сначала.

Проекты дБ являются очень мощным инструментом. Они не только генерируют сценарии, но и могут сразу применить их. Обязательно не уничтожьте Ваш производственный дб с ним.;)

мне действительно нравятся проекты DB VS, и я ожидаю использовать этот инструмент для всех своих проектов дб продвижение.

+tom

16
задан Ira Baxter 18 February 2010 в 16:31
поделиться

14 ответов

Это обсуждение является спорным, если вы считаете, что ваши клиенты могут обратиться за 2-3 Гбайт оперативной памяти на их 32-битной машине. Операционная система и другие приложения также будут загружать свою плоть.

Похоже, ваше приложение приближается к точке, когда ему требуется 64-разрядная операционная система и намного больше оперативной памяти.

-1
ответ дан 30 November 2019 в 16:00
поделиться

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

Предположим, что машина пользователя сконфигурирована с небольшой физической памятью и огромным пространством подкачки. Если вы запустите JVM с огромным размером виртуальной машины, это может вызвать серьезную "перебоя", поскольку JVM пытается получить доступ к данным на нерезидентных страницах. Напротив, если вы предоставите JVM нечто большее, чем требуется приложению, и меньше доступной физической памяти, вы сможете комфортно работать без перебоев.

0
ответ дан 30 November 2019 в 16:00
поделиться

Я не думаю, что вы можете делать то, что пытаетесь сделать; вместо этого вам придется отправить инструкции , относящиеся к вашим клиентам, их системам и их требованиям относительно того, как они могут изменить ваш файл .cmd , чтобы освободить больше памяти.

Конечно, если ваш продукт нацелен на очень нетехнических пользователей, вы можете спрятать это за более удобным для пользователя файлом конфигурации. Например,

# HIGH, MEDIUM, LOW - please change as appropriate. The guidelines are:
#                       * HIGH - users who generate 500 items per day
#                       * MEDIUM - 200-500 items etc
memoryUsage=MEDIUM

или, возможно, развертывание различных файлов конфигурации в зависимости от того, какой продукт параметр указывает пользователь при первом заказе продукта.

0
ответ дан 30 November 2019 в 16:00
поделиться

Я думаю, что самый простой способ сделать это - запустить JVM через какое-нибудь приложение-оболочку, которое будет проверять системные ресурсы для определения доступности памяти, а затем запустить JVM с соответствующим параметром -Xmx .

Тогда возникает вопрос, как будет написана эта оболочка. Возможно, приложение-оболочка даже само будет JVM, хотя я не думаю, что API или системные свойства предоставят необходимую информацию. Возможно, эту информацию сможет получить сценарий оболочки или ваш выбор.

4
ответ дан 30 November 2019 в 16:00
поделиться

В аргументах виртуальной машины можно использовать два параметра: -Xms для установки размера памяти при запуске и -Xmx для установки максимального размера памяти ...

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

0
ответ дан 30 November 2019 в 16:00
поделиться

Я не думаю, что Sun или IBM JVM могут это сделать (я знаю, что AS / 400 может, но это, скорее всего, не имеет отношения к вам).

Я бы хотел предложите использовать Java WebStart (и прежде, чем вы откажетесь от этого, обратите внимание, что он был обновлен с помощью Java 6 u 10 и намного лучше подходит для запуска «локальных» приложений и апплетов), поскольку он позволяет вам предоставить «небольшой экземпляр», более крупный экземпляр »,« гигантский экземпляр »в виде ссылок / значков.

Скорее всего, вы изучите параметры« внедрить приложение в кеш веб-запуска »и« автономный ».

0
ответ дан 30 November 2019 в 16:00
поделиться

Думаю, вам не повезло :-( Параметры -Xms и -Xmx не обеспечивают такой гибкости.

Поэтому я думаю, вам нужно будет обернуть вызов JVM сценарием, который может определить максимальный объем памяти, а затем соответствующим образом установить -Xmx (возможно, сценарий .vbs с использованием WMI на Windows). Или, может быть, он спрашивает пользователей при первом запуске?

Боюсь, это немного неудобно.

5
ответ дан 30 November 2019 в 16:00
поделиться

Еще один вариант ... Я работаю над программой запуска под названием WinRun4J , которая позволяет вам указать максимальный размер кучи в процентах от доступной памяти на машине, в которой находится выполняется (т. е. выполняет проверку объема доступной памяти и динамически устанавливает параметр -Xmx при запуске).

Параметр INI - "vm.heapsize.max.percent". Существует также еще одна опция «vm.heapsize.preferred», которая устанавливает параметр -Xmx как максимально доступную память на машине до этого количества.

Я полагаю, что некоторые другие программы запуска (например, Launch4J, Janel) предлагают та же функциональность.

7
ответ дан 30 November 2019 в 16:00
поделиться

Максимальные размеры виртуальной машины действительно отвечают этой потребности (она устанавливает максимальное значение, но виртуальная машина будет принимать только необходимое, шаг за шагом), но если вам нужно несколько конфигураций, помимо предоставления разных " cmd ", я действительно не вижу способа (хотя поищу еще немного)

[править] Как насчет использования первой программы / сценария (или даже другой Java-программы), которая будет проверять доступные ресурсы для системы, а затем вызывать вашу программу только с соответствующим -Xm, в зависимости от того, что она получила из системы? Таким образом, он будет адаптироваться к машинам, даже если вы не знали их раньше. Может быть идея ...

[второе редактирование] Хорошо, это уже было предложено скаффманом , моя ошибка.

8
ответ дан 30 November 2019 в 16:00
поделиться

если у вас много свободного времени, вы можете попробовать следующее:

Попытайтесь получить необходимую память по сравнению с набором входных данных. Благодаря этому вы можете разделить обработку на другой набор классов и создать новый процесс JVM для фактической обработки данных. В основном менеджер и рабочий. Менеджер проведет базовый анализ требуемого набора данных и создаст воркер с соответствующими требованиями к памяти.

1
ответ дан 30 November 2019 в 16:00
поделиться

У нас есть небольшое приложение на C, которое мы используем для запуска всех наших приложений Java через JNI. Это позволяет нам:

  1. Иметь значимое имя процесса (особенно важно для Windows)
  2. Иметь собственные значки (опять же, важно для Windows)
  3. Динамически создавать пути к классам (мы разбираем содержимое файла / lib для автоматического включения всех jar-файлов)

Для наших приложений мы просто жестко запрограммировали ограничение кучи, но вы можете легко динамически настроить максимальный размер кучи на основе доступной памяти.

Такое маленькое приложение на самом деле довольно легко сделать (это одна из самых простых вещей, которые можно сделать с JNI). Хорошей отправной точкой будет исходный код для JDK (есть подпапка для самого java.exe, которую вы можете использовать - это то, что мы сделали). Большинство людей очень удивлены, обнаружив, что java.exe - это крошечное приложение (< 200 строк кода), который просто вызывает JNI и передает аргументы командной строки (черт возьми, даже использование метода с именем main () довольно необязательно, если вы начинаете запускать вещи самостоятельно).

Вот код, который не только запускает JVM и т. Д., Но также определяет максимальное пространство кучи на основе доступной оперативной памяти компьютера. Это большой объем кода для сообщения SO, и он совсем не красивый - но это закаленный в битвах код - он использовался почти десять лет в ходе многих сотен установок и т.д. Наслаждайтесь:

#include <windows.h>
#include <jni.h>
#include <string>
#include <sstream>
using namespace std;

#define STARTUP_CLASS "some/path/to/YourStartupClass"

void vShowError(string sErrorMessage);
void vShowJREError(string sErrorMessage);
void vShowLastError(string sErrorMessage);
void vDestroyVM(JNIEnv *env, JavaVM *jvm);
void vAddOption(string& sName);
string GetClassPath(string root);
string GetJREPath();
int getMaxHeapAvailable(int permGenMB, int maxHeapMB);

JavaVMOption* vm_options;
int mctOptions = 0;
int mctOptionCapacity = 0;


boolean GetApplicationHome(char *buf, jint sz);


typedef jint (CALLBACK *CreateJavaVM)(JavaVM
**pvm, JNIEnv **penv, void *args);

boolean PathExists(string &path)
{
    DWORD dwAttr = GetFileAttributes(path.c_str());
    if (dwAttr == 0xffffffff)
        return FALSE;
    else 
        return TRUE;
}

// returns TRUE is there was an exception, FALSE otherwise
BOOL GetExceptionString(JNIEnv* jenv, string &result)
{
    jthrowable ex;


    if (NULL != (ex = jenv->ExceptionOccurred())) {
        // clear exception 
        jenv->ExceptionClear();

        jmethodID gmID = jenv->GetMethodID( 
                           jenv->FindClass("java/lang/Throwable"),
                           "getMessage",
                           "()Ljava/lang/String;");


        jstring jerrStr = (jstring)jenv->CallObjectMethod(ex,gmID);
        // now you can look at the error message string 

        if (jerrStr != NULL){ // make sure getMessage() didn't return null
            const char *errStr = jenv->GetStringUTFChars(jerrStr,0);
            result = errStr;
            jenv->ReleaseStringUTFChars(jerrStr, errStr);
        } else {
            result = "null";
        }

        return TRUE;
    } else {
        return FALSE;
    }
}

BOOL GetJRESystemProperty(JNIEnv *env, string propname, string &propval, string &errmessage)
{
    // now check for minimum JRE version requirement
    jclass cls = env->FindClass("java/lang/System");
    if (cls == NULL){
        errmessage = "Unable to interact with Java Virtual Machine - please visit www.java.com and confirm that your Java installation is valid.";
        return FALSE;
    }

    jmethodID mid = env->GetStaticMethodID(cls, "getProperty", "(Ljava/lang/String;)Ljava/lang/String;");
    if (mid == NULL){
        errmessage = "Unable to obtain Java runtime system properties - please visit www.java.net and confirm that your Java installation is valid.";
        return FALSE;
    }

    jstring propName = env->NewStringUTF( propname.c_str() );
    jstring result = (jstring) env->CallStaticObjectMethod(cls, mid, propName);
    const char* utfResult = env->GetStringUTFChars( result, NULL );

    if (utfResult == NULL){
        errmessage = "Unable to obtain Java runtime system property " + propname + " - please visit www.java.net and confirm that your Java installation is valid.";
        return FALSE;
    }

    propval = utfResult;
    env->ReleaseStringUTFChars( result, utfResult );

    return TRUE;
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow) {


    JNIEnv *env;
    JavaVM *jvm;
    jint jintVMStartupReturnValue;
    jclass jclassStartup;
    jmethodID midStartup;


    // Path Determination


    // --- application home
    char home[2000];
    if (!GetApplicationHome(home, sizeof(home))) {
        vShowError("Unable to determine application home.");
        return 0;
    }
    string sAppHome(home);
    string sOption_AppHome = "-Dapplication.home=" + sAppHome;


    string sJREPath = GetJREPath();


    // --- VM Path
    string sRuntimePath = sJREPath + "\\bin\\client\\"; // must contain jvm.dll
    string sJVMpath = sRuntimePath + "jvm.dll";

    // --- boot path
    string sBootPath = sJREPath + "\\lib";
    string sOption_BootPath = "-Dsun.boot.class.path=" + sBootPath;


    // --- class path
    //string sClassPath = sAppHome + "\\lib;" + sAppHome + "\\lib\\" + APP_JAR + ";" + sAppHome + "\\lib\\log4j-1.2.7.jar";

    string cpRoot = sAppHome + "\\";
    string sClassPath = GetClassPath(cpRoot);

    string sOption_ClassPath = "-Djava.class.path=" + sClassPath;

    string sOption_JavaLibraryPath = "-Djava.library.path=" + sAppHome + "\\lib";

    int maxHeapBM = 768;

    int argStart = 1; // the first argument passed in that should be passed along to the JVM
    if(__argc > 1){
        string maxheapstr = __argv[1];
        if (maxheapstr.substr(0, 9).compare("/maxheap=") == 0){
            maxheapstr = maxheapstr.substr(9);
            maxHeapBM = atoi(maxheapstr.c_str());
            argStart++;
        }
    }

    // we now use adaptive max heap size determination - we try for 768MB of heap, but if we don't get it, we can back off and use less instead of failing the launch
    // note: we had problems going for 1024 heap at TrueNorth - it would throttle back to 848 and fail with error -4 no matter what I did
    int maxHeapMB = getMaxHeapAvailable(62, maxHeapBM);
    stringstream ss;
    ss << "-Xmx";
    ss << maxHeapMB;
    ss << "m";
    string sOption_HeapSpace = ss.str();

    string sOption_PermSize = "-XX:MaxPermSize=62m";

    string sOption_HeapDump = "-XX:+HeapDumpOnOutOfMemoryError";

    if (strstr(szCmdLine, "/launcher_verbose") != NULL){
        string msg = "App Home = ";
        msg += sAppHome;
        msg += "\nJRE Path = ";
        msg += sJREPath;
        msg += "\nRuntime Path = ";
        msg += sRuntimePath;
        msg += "\nClass Path = ";
        msg += sClassPath;
        msg += "\nHeap argument = ";
        msg += sOption_HeapSpace;
        msg += "\nPermsize argument = ";
        msg += sOption_PermSize;
        msg += "\nHeap dump = ";
        msg += sOption_HeapDump;
        msg += "\njava.library.path = ";
        msg += sOption_JavaLibraryPath;
        msg += "\nCommand line = ";
        msg += szCmdLine;

        FILE *f = fopen("launcher.txt", "w");
        fprintf(f, "%s", msg.c_str());
        fclose(f);

        MessageBox(0, msg.c_str(), "Launcher Verbose Info", MB_OK);

    }

    // setup VM options
    // vAddOption(string("-verbose"));
    vAddOption(sOption_ClassPath);
    vAddOption(sOption_AppHome);

    vAddOption(sOption_HeapSpace);
    vAddOption(sOption_PermSize);
    vAddOption(sOption_HeapDump);
    vAddOption(sOption_JavaLibraryPath);

    // initialize args
    JavaVMInitArgs vm_args;
    vm_args.version = 0x00010002;
    vm_args.options = vm_options;
    vm_args.nOptions = mctOptions;
    vm_args.ignoreUnrecognized = JNI_TRUE;


    // need to diddle with paths to ensure that jvm can find correct libraries - see http://www.duckware.com/tech/java6msvcr71.html
    string sBinPath = sJREPath + "\\bin";
    char originalCurrentDirectory[4096];
    GetCurrentDirectory(4095, originalCurrentDirectory);

    SetCurrentDirectory(sBinPath.c_str());

    // Dynamic binding to SetDllDirectory()
    typedef BOOL (WINAPI *LPFNSDD)(LPCTSTR lpPathname);
    HINSTANCE hKernel32 = GetModuleHandle("kernel32");
    LPFNSDD lpfnSetDllDirectory = (LPFNSDD)GetProcAddress(hKernel32, "SetDllDirectoryA");
    if (lpfnSetDllDirectory){
        lpfnSetDllDirectory(sBinPath.c_str());
    }

    // load jvm library
    HINSTANCE hJVM = LoadLibrary(sJVMpath.c_str());

    SetCurrentDirectory(originalCurrentDirectory);
    if (lpfnSetDllDirectory){
        lpfnSetDllDirectory(NULL);
    }

    if( hJVM == NULL ){
        vShowJREError("Java does not appear to be installed on this machine.  Click OK to go to www.java.com where you can download and install Java");
        return 0;
    }


    // try to start 1.2/3/4 VM
    // uses handle above to locate entry point
    CreateJavaVM lpfnCreateJavaVM = (CreateJavaVM)
    GetProcAddress(hJVM, "JNI_CreateJavaVM");
    jintVMStartupReturnValue = (*lpfnCreateJavaVM)(&jvm, &env, &vm_args);

    // test for success
    if (jintVMStartupReturnValue < 0) {
        stringstream ss;
        ss << "There is a problem with the 32 bit Java installation on this computer (";
        ss << jintVMStartupReturnValue;
        ss << ").  Click OK to go to www.java.com where you can download and re-install 32 bit Java";

        vShowJREError(ss.str());
        // I don't think we should destroy the VM - it never was created...
        //vDestroyVM(env, jvm);
        return 0;
    }


    //now check for minimum jvm version 
    string version = "";
    string errormsg = "";
    if (!GetJRESystemProperty(env, "java.specification.version", version, errormsg)){
        vShowJREError(errormsg);
        vDestroyVM(env, jvm);
        return 0;
    }

    double verf = atof(version.c_str());
    if (verf < 1.599f){
        string sErrorMessage = "This application requires Java Runtime version 1.6 or above, but your runtime is version " + version + "\n\nClick OK to go to www.java.com and update to the latest Java Runtime Environment";
        vShowJREError(sErrorMessage);
        vDestroyVM(env, jvm);
        return 0;
    }


    // find startup class
    string sStartupClass = STARTUP_CLASS;
    // notice dots are translated to slashes
    jclassStartup = env->FindClass(sStartupClass.c_str());
    if (jclassStartup == NULL) {
        string sErrorMessage = "Unable to find startup class [" + sStartupClass + "]";
        vShowError(sErrorMessage);
        vDestroyVM(env, jvm);
        return 0;
    }


    // find startup method
    string sStartupMethod_Identifier = "main";
    string sStartupMethod_TypeDescriptor =
    "([Ljava/lang/String;)V";
    midStartup = 
    env->GetStaticMethodID(jclassStartup,
    sStartupMethod_Identifier.c_str(),
    sStartupMethod_TypeDescriptor.c_str());
    if (midStartup == NULL) {
        string sErrorMessage =
            "Unable to find startup method ["
            + sStartupClass + "."
            + sStartupMethod_Identifier
            + "] with type descriptor [" +
            sStartupMethod_TypeDescriptor + "]";
        vShowError(sErrorMessage);
        vDestroyVM(env, jvm);
        return 0;
    }


    // create array of args to startup method
    jstring jstringExampleArg;
    jclass jclassString;
    jobjectArray jobjectArray_args;


    jstringExampleArg = env->NewStringUTF("example string");
    if (jstringExampleArg == NULL){
        vDestroyVM(env, jvm);
        return 0;
    }
    jclassString = env->FindClass("java/lang/String");
    jobjectArray_args = env->NewObjectArray(__argc-argStart, jclassString, jstringExampleArg);
    if (jobjectArray_args == NULL){
        vDestroyVM(env, jvm);
        return 0;
    }

    int count;
    for (count = argStart; count < __argc; count++){
        env->SetObjectArrayElement(jobjectArray_args, count-1, env->NewStringUTF(__argv[count]));
    }

    // call the startup method -
    // this starts the Java program
    env->CallStaticVoidMethod(jclassStartup, midStartup, jobjectArray_args);

    string errstr;
    if (GetExceptionString(env, errstr)){
        vShowError(errstr);
    }

    // attempt to detach main thread before exiting
    if (jvm->DetachCurrentThread() != 0) {
        vShowError("Could not detach main thread.\n");
    }

    // this call will hang as long as there are
    // non-daemon threads remaining
    jvm->DestroyJavaVM();


    return 0;

}


void vDestroyVM(JNIEnv *env, JavaVM *jvm)
{
    if (env->ExceptionOccurred()) {
        env->ExceptionDescribe();
    }
    jvm->DestroyJavaVM();
}


void vShowError(string sError) {
    MessageBox(NULL, sError.c_str(), "Startup Error", MB_OK);
}

void vShowJREError(string sError) {
    MessageBox(NULL, sError.c_str(), "Startup Error", MB_OK);
    ShellExecute(NULL, "open", "http://www.java.com", NULL, NULL, SW_SHOWNORMAL);
}


/* Shows an error message in an OK box with the
system GetLastError appended in brackets */
void vShowLastError(string sLocalError) {
    LPVOID lpSystemMsgBuf;
    FormatMessage(  FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
                    NULL,
                    GetLastError(),
                    MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
                    (LPTSTR) &lpSystemMsgBuf, 0, NULL );
    string sSystemError = string((LPTSTR)lpSystemMsgBuf);
    vShowError(sLocalError + " [" + sSystemError + "]");
}


void vAddOption(string& sValue) {
    mctOptions++;
    if (mctOptions >= mctOptionCapacity) {
        if (mctOptionCapacity == 0) {
            mctOptionCapacity = 3;
            vm_options = (JavaVMOption*)malloc(mctOptionCapacity * sizeof(JavaVMOption));
        } else {
            JavaVMOption *tmp;
            mctOptionCapacity *= 2;
            tmp = (JavaVMOption*)malloc(mctOptionCapacity * sizeof(JavaVMOption));
            memcpy(tmp, vm_options, (mctOptions-1) * sizeof(JavaVMOption));
            free(vm_options);
            vm_options = tmp;
        }
    }
    vm_options[mctOptions-1].optionString = (char*)sValue.c_str();
}


/* If buffer is "c:\app\bin\java",
* then put "c:\app" into buf. */
jboolean GetApplicationHome(char *buf, jint sz) {
    char *cp;
    GetModuleFileName(0, buf, sz);
    *strrchr(buf, '\\') = '\0';
    if ((cp = strrchr(buf, '\\')) == 0) {
        // This happens if the application is in a
        // drive root, and there is no bin directory.
        buf[0] = '\0';
        return JNI_FALSE;
    }
    return JNI_TRUE;
}

string GetClassPath(string root){
    string rootWithBackslash = root;

    if (rootWithBackslash[rootWithBackslash.length()-1] != '\\')
        rootWithBackslash += "\\";

    string cp = rootWithBackslash + "classes\\"; //first entry in the cp

    string libPathWithBackslash = rootWithBackslash + "lib\\";

    // now find all jar files...
    string searchSpec = libPathWithBackslash;

    searchSpec = libPathWithBackslash + "*.jar";


    WIN32_FIND_DATA fd;
    HANDLE find = FindFirstFile(searchSpec.c_str(), &fd); 
    while (find != NULL){
        cp += ";";
        cp += libPathWithBackslash;
        cp += fd.cFileName;
        if (!FindNextFile(find, &fd)){
            FindClose(find);
            find = NULL;
        }
    }

    return cp;
}

string GetJREPath(){

    // first, check for JRE in application directory
    char home[2000];
    if (!GetApplicationHome(home, sizeof(home))) {
        vShowError("Unable to determine application home.");
        return 0;
    }
    string sJREPath(home);
    sJREPath += "\\jre";

    if (PathExists(sJREPath)){
        return sJREPath;
    }

/* - don't check JAVA_HOME - it may be incorrect...
    // next, check the JAVA_HOME environment variable
    GetEnvironmentVariable("JAVA_HOME", home, sizeof(home));
    sJREPath = home;

    if (PathExists(sJREPath)){
        return sJREPath;
    }

*/

    // next, check registry
    HKEY hKeyJRERoot;
    HKEY hKeyJREInstance;
    DWORD dwType;
    DWORD dwSize;
    BYTE *pData;
    string valueName;
    string value;
    LONG regRslt;

    sJREPath = "";

    regRslt = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\\JavaSoft\\Java Runtime Environment", 0, KEY_READ, &hKeyJRERoot);

    if (regRslt == ERROR_SUCCESS){

        valueName = "CurrentVersion";

        regRslt = RegQueryValueEx(hKeyJRERoot, valueName.c_str(), NULL, &dwType, NULL, &dwSize);

        if (regRslt == ERROR_SUCCESS){
            pData = (BYTE *)malloc(dwSize);

            value = "";
            regRslt = RegQueryValueEx(hKeyJRERoot, valueName.c_str(), NULL, &dwType, pData, &dwSize);

            if (regRslt == ERROR_SUCCESS){
                value = (LPCSTR)pData;
            }

            free(pData);

            if (value != ""){

                regRslt = RegOpenKeyEx(hKeyJRERoot, value.c_str(), 0, KEY_READ, &hKeyJREInstance);

                if (regRslt == ERROR_SUCCESS){
                    valueName = "JavaHome";
                    value = "";

                    regRslt = RegQueryValueEx(hKeyJREInstance, valueName.c_str(), NULL, &dwType, NULL, &dwSize);

                    if (regRslt == ERROR_SUCCESS){
                        pData = (BYTE *)malloc(dwSize);

                        regRslt = RegQueryValueEx(hKeyJREInstance, valueName.c_str(), NULL, &dwType, pData, &dwSize);

                        if (regRslt == ERROR_SUCCESS){
                            value = (LPCSTR)pData;
                            sJREPath = value;
                        }

                        free(pData);
                    }
                    RegCloseKey(hKeyJREInstance);
                }
            }
        }
        RegCloseKey(hKeyJRERoot);
    }

    return sJREPath;

}

static const DWORD NUM_BYTES_PER_MB = 1024 * 1024;

bool canAllocate(DWORD bytes)
{
    LPVOID lpvBase;

    lpvBase = VirtualAlloc(NULL, bytes, MEM_RESERVE, PAGE_READWRITE);
    if (lpvBase == NULL) return false;

    VirtualFree(lpvBase, 0, MEM_RELEASE);

    return true;
}

int getMaxHeapAvailable(int permGenMB, int maxHeapMB)
{
    DWORD       originalMaxHeapBytes = 0;
    DWORD       maxHeapBytes = 0;
    int         numMemChunks = 0;
    SYSTEM_INFO     sSysInfo;
    DWORD       maxPermBytes = permGenMB * NUM_BYTES_PER_MB;     // Perm space is in addition to the heap size
    DWORD       numBytesNeeded = 0;

    GetSystemInfo(&sSysInfo);

    // jvm aligns as follows: 
    // quoted from size_t GenCollectorPolicy::compute_max_alignment() of jdk 7 hotspot code:
    //      The card marking array and the offset arrays for old generations are
    //      committed in os pages as well. Make sure they are entirely full (to
    //      avoid partial page problems), e.g. if 512 bytes heap corresponds to 1
    //      byte entry and the os page size is 4096, the maximum heap size should
    //      be 512*4096 = 2MB aligned.

    // card_size computation from CardTableModRefBS::SomePublicConstants of jdk 7 hotspot code
    int card_shift  = 9;
    int card_size   = 1 << card_shift;

    DWORD alignmentBytes = sSysInfo.dwPageSize * card_size;

    maxHeapBytes = maxHeapMB * NUM_BYTES_PER_MB + 50*NUM_BYTES_PER_MB; // 50 is an overhead fudge factory per https://forums.oracle.com/forums/thread.jspa?messageID=6463655 (they had 28, I'm bumping it 'just in case')

    // make it fit in the alignment structure
    maxHeapBytes = maxHeapBytes + (maxHeapBytes % alignmentBytes);
    numMemChunks = maxHeapBytes / alignmentBytes;
    originalMaxHeapBytes = maxHeapBytes;

    // loop and decrement requested amount by one chunk
    // until the available amount is found
    numBytesNeeded = maxHeapBytes + maxPermBytes; 
    while (!canAllocate(numBytesNeeded) && numMemChunks > 0) 
    {
        numMemChunks --;
        maxHeapBytes = numMemChunks * alignmentBytes;
        numBytesNeeded = maxHeapBytes + maxPermBytes;
    }

    if (numMemChunks == 0) return 0;

    // we can allocate the requested size, return it now
    if (maxHeapBytes == originalMaxHeapBytes) return maxHeapMB;

    // calculate the new MaxHeapSize in megabytes
    return maxHeapBytes / NUM_BYTES_PER_MB;
}
8
ответ дан 30 November 2019 в 16:00
поделиться

Вы также можете использовать опцию: -XX: + AggressiveHeap

Согласно [документации] [1]:

Параметр -XX: + AggressiveHeap проверяет ресурсы машины (размер памяти и количество процессоров) и пытается установить различные параметры чтобы быть оптимальным для длительной работы, память Работа с интенсивным распределением ресурсов. это было изначально предназначался для машин с большой объем памяти и большой количество процессоров, но в J2SE платформа, версия 1.4.1 и выше показал себя полезным даже на четыре процессорных машины. С этим опция сборщик пропускной способности (-XX: + UseParallelGC) используется вместе с адаптивной калибровкой (-XX: + UseAdaptiveSizePolicy). В физическая память на машинах должна быть не менее 256 МБ до AggressiveHeap можно использовать. Размер исходной кучи вычисляется в зависимости от размера физического память и попытки сделать максимальную использование физической памяти для куча (т. е. алгоритмы пытаются использовать кучи почти столько же, сколько общая физическая память).

[1]: http://java.sun.com/docs/hotspot/gc1.4.2/#4.2.2 . AggressiveHeap | наброски

13
ответ дан 30 November 2019 в 16:00
поделиться

Я прочитал цепочку сообщений, но не нашел ничего, что указывало бы на то, что приложение подверглось некоторому профилированию. Обычно я профилирую приложения при определенных условиях, чтобы найти «горячие» точки в производительности или использовании памяти. Вероятно, в большинстве случаев есть вещи, которые можно улучшить.

Если бы вы могли установить ограничения и понять поведение приложения, вы могли бы лучше рассказать своим клиентам, что они могут или не могут делать с приложением, тем самым уменьшая количество обращений в службу поддержки и давая вам лучшее представление о какой минимальный или максимальный размер кучи для отправки продукта.

Может быть, вы могли бы начать с этого: http://www.eclipse.org/mat/

0
ответ дан 30 November 2019 в 16:00
поделиться

Не пробовали ли вы запустить jps, чтобы получить PID вашего процесса, а затем вызвать jinfo, чтобы изменить параметр mx? Не уверен, что это сработает, но возможно.

[Edit] Это означает, что когда вы думаете, что у вас большой набор данных, вы каким-то образом считываете общий объем памяти (я думаю, это зависит от ОС. См. http://forums.sun.com/thread.jspa?messageID=10306570) или просто увеличиваете размер до тех пор, пока он не перестанет казаться вам маленьким (если он взорвется первым, попытайтесь захватить и отобразить полезное сообщение, например, "ваша машина неадекватна, пора бежать в Frys").

0
ответ дан 30 November 2019 в 16:00
поделиться
Другие вопросы по тегам:

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