#vulnerable code 
                                public Object borrowObject() throws Exception {
        long starttime = System.currentTimeMillis();
        Latch latch = new Latch();
        synchronized (this) {
            _allocationQueue.add(latch);
            allocate();
        }

        for(;;) {
            synchronized (this) {
                assertOpen();
            }
                
            // If no object was allocated from the pool above
            if(latch._pair == null) {
                // check if we were allowed to create one
                if(latch._mayCreate) {
                    // allow new object to be created
                } else {
                    // the pool is exhausted
                    switch(_whenExhaustedAction) {
                        case WHEN_EXHAUSTED_GROW:
                            // allow new object to be created
                            break;
                        case WHEN_EXHAUSTED_FAIL:
                            synchronized (this) {
                                _allocationQueue.remove(latch);
                            }
                            throw new NoSuchElementException("Pool exhausted");
                        case WHEN_EXHAUSTED_BLOCK:
                            try {
                                synchronized (latch) {
                                    if(_maxWait <= 0) {
                                        latch.wait();
                                    } else {
                                        // this code may be executed again after a notify then continue cycle
                                        // so, need to calculate the amount of time to wait
                                        final long elapsed = (System.currentTimeMillis() - starttime);
                                        final long waitTime = _maxWait - elapsed;
                                        if (waitTime > 0)
                                        {
                                            latch.wait(waitTime);
                                        }
                                    }
                                }
                            } catch(InterruptedException e) {
                                Thread.currentThread().interrupt();
                                throw e; 
                            }
                            if(_maxWait > 0 && ((System.currentTimeMillis() - starttime) >= _maxWait)) {
                                throw new NoSuchElementException("Timeout waiting for idle object");
                            } else {
                                continue; // keep looping
                            }
                        default:
                            throw new IllegalArgumentException("WhenExhaustedAction property " + _whenExhaustedAction + " not recognized.");
                    }
                }
            }

            boolean newlyCreated = false;
            if(null == latch._pair) {
                try {
                    Object obj = _factory.makeObject();
                    latch._pair = new ObjectTimestampPair(obj);
                    newlyCreated = true;
                } finally {
                    if (!newlyCreated) {
                        // object cannot be created
                        synchronized (this) {
                            _numInternalProcessing--;
                            // No need to reset latch - about to throw exception
                            allocate();
                        }
                    }
                }
            }
            // activate & validate the object
            try {
                _factory.activateObject(latch._pair.value);
                if(_testOnBorrow && !_factory.validateObject(latch._pair.value)) {
                    throw new Exception("ValidateObject failed");
                }
                synchronized(this) {
                    _numInternalProcessing--;
                    _numActive++;
                }
                return latch._pair.value;
            }
            catch (Throwable e) {
                // object cannot be activated or is invalid
                try {
                    _factory.destroyObject(latch._pair.value);
                } catch (Throwable e2) {
                    // cannot destroy broken object
                }
                synchronized (this) {
                    _numInternalProcessing--;
                    latch.reset();
                    _allocationQueue.add(0, latch);
                    allocate();
                }
                if(newlyCreated) {
                    throw new NoSuchElementException("Could not create a validated object, cause: " + e.getMessage());
                }
                else {
                    continue; // keep looping
                }
            }
        }
    } 
                            #location 56 
                            #vulnerability type THREAD_SAFETY_VIOLATION
#fixed code
                                public Object borrowObject() throws Exception {
        long starttime = System.currentTimeMillis();
        Latch latch = new Latch();
        byte whenExhaustedAction;
        long maxWait;
        synchronized (this) {
            // Get local copy of current config. Can't sync when used later as
            // it can result in a deadlock. Has the added advantage that config
            // is consistent for entire method execution 
            whenExhaustedAction = _whenExhaustedAction;
            maxWait = _maxWait;
            
            // Add this request to the queue 
            _allocationQueue.add(latch);
            allocate();
        }

        for(;;) {
            synchronized (this) {
                assertOpen();
            }
                
            // If no object was allocated from the pool above
            if(latch._pair == null) {
                // check if we were allowed to create one
                if(latch._mayCreate) {
                    // allow new object to be created
                } else {
                    // the pool is exhausted
                    switch(whenExhaustedAction) {
                        case WHEN_EXHAUSTED_GROW:
                            // allow new object to be created
                            break;
                        case WHEN_EXHAUSTED_FAIL:
                            synchronized (this) {
                                _allocationQueue.remove(latch);
                            }
                            throw new NoSuchElementException("Pool exhausted");
                        case WHEN_EXHAUSTED_BLOCK:
                            try {
                                synchronized (latch) {
                                    if(maxWait <= 0) {
                                        latch.wait();
                                    } else {
                                        // this code may be executed again after a notify then continue cycle
                                        // so, need to calculate the amount of time to wait
                                        final long elapsed = (System.currentTimeMillis() - starttime);
                                        final long waitTime = maxWait - elapsed;
                                        if (waitTime > 0)
                                        {
                                            latch.wait(waitTime);
                                        }
                                    }
                                }
                            } catch(InterruptedException e) {
                                Thread.currentThread().interrupt();
                                throw e; 
                            }
                            if(maxWait > 0 && ((System.currentTimeMillis() - starttime) >= maxWait)) {
                                throw new NoSuchElementException("Timeout waiting for idle object");
                            } else {
                                continue; // keep looping
                            }
                        default:
                            throw new IllegalArgumentException("WhenExhaustedAction property " + whenExhaustedAction + " not recognized.");
                    }
                }
            }

            boolean newlyCreated = false;
            if(null == latch._pair) {
                try {
                    Object obj = _factory.makeObject();
                    latch._pair = new ObjectTimestampPair(obj);
                    newlyCreated = true;
                } finally {
                    if (!newlyCreated) {
                        // object cannot be created
                        synchronized (this) {
                            _numInternalProcessing--;
                            // No need to reset latch - about to throw exception
                            allocate();
                        }
                    }
                }
            }
            // activate & validate the object
            try {
                _factory.activateObject(latch._pair.value);
                if(_testOnBorrow && !_factory.validateObject(latch._pair.value)) {
                    throw new Exception("ValidateObject failed");
                }
                synchronized(this) {
                    _numInternalProcessing--;
                    _numActive++;
                }
                return latch._pair.value;
            }
            catch (Throwable e) {
                // object cannot be activated or is invalid
                try {
                    _factory.destroyObject(latch._pair.value);
                } catch (Throwable e2) {
                    // cannot destroy broken object
                }
                synchronized (this) {
                    _numInternalProcessing--;
                    latch.reset();
                    _allocationQueue.add(0, latch);
                    allocate();
                }
                if(newlyCreated) {
                    throw new NoSuchElementException("Could not create a validated object, cause: " + e.getMessage());
                }
                else {
                    continue; // keep looping
                }
            }
        }
    }