alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Java example source code file (awt_GDIObject.cpp)

This example Java source code file (awt_GDIObject.cpp) is included in the alvinalexander.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Learn more about this Java project at its project page.

Java - Java tags/keywords

bool, criticalsection, dword, error_success, false, getmaxgdilimit, j2dtraceln, jnienv, max_gdi_objects, null, problem, regopenkeyex, safecreate, true

The awt_GDIObject.cpp Java example source code

/*
 * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

#include "awt_GDIObject.h"

/**
 * These methods work around a bug in Windows where allocating
 * the max number of GDI Objects (HDC, Pen, Brush, etc.) will cause the
 * application and desktop to become unusable.  The workaround
 * ensures we never reach this maximum, by refcounting
 * HDC, Pen, and Brush objects that are active.  We increment the refcount
 * when we create these objects and decrement the
 * refcount when we release them, so that our numCurrentObjects
 * counter should always equal the number of unreleased objects.
 * We only do this for HDC, Pen, and Brush because these are the only GDI
 * objects that may grow without bound in our implementation (we cache
 * these objects per thread, so a growing number of threads may have
 * unique HDC/Pen/Brush objects per thread and might approach the maximum).
 * Also, we do not count objects allocated on a temporary basis (such as
 * the many calls to GetDC() in our code, followed quickly by ReleaseDC());
 * we only care about long-lived GDI objects that might bloat our total
 * object usage.
 */

/**
 * Default GDI Object limit for win2k and XP is 10,000
 * Set our limit much lower than that to allow a buffer for objects
 * created beyond the per-thread HDC/Brush/Pen objects we are
 * counting here, including objects created by the overall process
 * (which could include the browser, in the case of applets)
 */
#define MAX_GDI_OBJECTS 9000

// Static initialization of these globals used in AwtGDIObject
int AwtGDIObject::numCurrentObjects = 0;
// this variable will never be deleted. initialized below with SafeCreate.
CriticalSection* AwtGDIObject::objectCounterLock = NULL;
int AwtGDIObject::maxGDIObjects = GetMaxGDILimit();

/**
 * Sets up max GDI limit; we query the registry key that
 * defines this value on WindowsXP and Windows2000.
 * If we fail here, we will use the default value
 * MAX_GDI_OBJECTS as a fallback value.  This is not unreasonable -
 * it seems unlikely that many people would change this
 * registry key setting.
 * NOTE: This function is called automatically at startup to
 * set the value of maxGDIObjects; it should not be necessary to
 * call this function from anywhere else.  Think of it like a static
 * block in Java.
 */
int AwtGDIObject::GetMaxGDILimit() {
    int limit = MAX_GDI_OBJECTS;
    HKEY hKey = NULL;
    DWORD ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
        L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Windows", 0,
        KEY_QUERY_VALUE, &hKey);
    if (ret == ERROR_SUCCESS) {
        DWORD valueLength = 4;
        DWORD regValue;
        ret = RegQueryValueEx(hKey, L"GDIProcessHandleQuota", NULL, NULL,
            (LPBYTE)®Value, &valueLength);
        if (ret == ERROR_SUCCESS) {
            // Set limit to 90% of the actual limit to account for other
            // GDI objects that the process might need
            limit = (int)(regValue * .9);
        } else {
            J2dTraceLn(J2D_TRACE_WARNING,
                "Problem with RegQueryValueEx in GetMaxGDILimit");
        }
        RegCloseKey(hKey);
    } else {
        J2dTraceLn(J2D_TRACE_WARNING,
            "Problem with RegOpenKeyEx in GetMaxGDILimit");
    }
    return limit;
}

/**
 * Increment the object counter to indicate that we are about to
 * create a new GDI object.  If the limit has been reached, skip the
 * increment and return FALSE to indicate that an object should
 * not be allocated.
 */
BOOL AwtGDIObject::IncrementIfAvailable() {
    BOOL available;
    CriticalSection* pLock = SafeCreate(objectCounterLock);
    pLock->Enter();
    if (numCurrentObjects < maxGDIObjects) {
        available = TRUE;
        ++numCurrentObjects;
    } else {
        // First, flush the cache; we may have run out simply because
        // we have unused colors still reserved in the cache
        GDIHashtable::flushAll();
        // Now check again to see if flushing helped.  If not, we really
        // have run out.
        if (numCurrentObjects < maxGDIObjects) {
            available = TRUE;
            ++numCurrentObjects;
        } else {
            available = FALSE;
        }
    }
    pLock->Leave();
    return available;
}

/**
 * Decrement the counter after releasing a GDI Object
 */
void AwtGDIObject::Decrement() {
    CriticalSection* pLock = SafeCreate(objectCounterLock);
    pLock->Enter();
    --numCurrentObjects;
    pLock->Leave();
}

/**
 * This utility method is called by subclasses of AwtGDIObject
 * to ensure capacity for an additional GDI object.  Failure
 * results in throwing an AWTException.
 */
BOOL AwtGDIObject::EnsureGDIObjectAvailability()
{
    if (!IncrementIfAvailable()) {
        // IncrementIfAvailable flushed the cache but still failed; must
        // have hit the limit.  Throw an exception to indicate the problem.
        if (jvm != NULL) {
            JNIEnv* env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
            if (env != NULL && !safe_ExceptionOccurred(env)) {
                JNU_ThrowByName(env, "java/awt/AWTError",
                    "Pen/Brush creation failure - " \
                    "exceeded maximum GDI resources");
            }
        }
        return FALSE;
    }
    return TRUE;
}

Other Java examples (source code examples)

Here is a short list of links related to this Java awt_GDIObject.cpp source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.