From 6f5991fa38f314220a67b01f07ab500aa62c4446 Mon Sep 17 00:00:00 2001 From: Jon Masamitsu Date: Thu, 3 Jan 2013 15:03:27 -0800 Subject: [PATCH 001/210] 8004895: NPG: JMapPermCore test failure caused by warnings about missing field Reviewed-by: johnc --- .../compactibleFreeListSpace.cpp | 14 +++++++++----- .../compactibleFreeListSpace.hpp | 2 +- .../concurrentMarkSweep/vmStructs_cms.hpp | 8 +++----- .../src/share/vm/memory/binaryTreeDictionary.cpp | 6 +++--- .../src/share/vm/memory/binaryTreeDictionary.hpp | 4 ++++ hotspot/src/share/vm/runtime/vmStructs.cpp | 3 +-- 6 files changed, 21 insertions(+), 16 deletions(-) diff --git a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp index 45e53170859..c2a9cbe330b 100644 --- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp +++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp @@ -102,7 +102,7 @@ CompactibleFreeListSpace::CompactibleFreeListSpace(BlockOffsetSharedArray* bs, // temporarily disabled). switch (dictionaryChoice) { case FreeBlockDictionary::dictionaryBinaryTree: - _dictionary = new BinaryTreeDictionary(mr); + _dictionary = new AFLBinaryTreeDictionary(mr); break; case FreeBlockDictionary::dictionarySplayTree: case FreeBlockDictionary::dictionarySkipList: @@ -122,7 +122,8 @@ CompactibleFreeListSpace::CompactibleFreeListSpace(BlockOffsetSharedArray* bs, // moved to its new location before the klass is moved. // Set the _refillSize for the linear allocation blocks if (!use_adaptive_freelists) { - FreeChunk* fc = _dictionary->get_chunk(mr.word_size()); + FreeChunk* fc = _dictionary->get_chunk(mr.word_size(), + FreeBlockDictionary::atLeast); // The small linAB initially has all the space and will allocate // a chunk of any size. HeapWord* addr = (HeapWord*) fc; @@ -1647,7 +1648,8 @@ CompactibleFreeListSpace::getChunkFromIndexedFreeListHelper(size_t size, FreeChunk* CompactibleFreeListSpace::getChunkFromDictionary(size_t size) { assert_locked(); - FreeChunk* fc = _dictionary->get_chunk(size); + FreeChunk* fc = _dictionary->get_chunk(size, + FreeBlockDictionary::atLeast); if (fc == NULL) { return NULL; } @@ -1664,7 +1666,8 @@ CompactibleFreeListSpace::getChunkFromDictionary(size_t size) { FreeChunk* CompactibleFreeListSpace::getChunkFromDictionaryExact(size_t size) { assert_locked(); - FreeChunk* fc = _dictionary->get_chunk(size); + FreeChunk* fc = _dictionary->get_chunk(size, + FreeBlockDictionary::atLeast); if (fc == NULL) { return fc; } @@ -1677,7 +1680,8 @@ CompactibleFreeListSpace::getChunkFromDictionaryExact(size_t size) { if (fc->size() < size + MinChunkSize) { // Return the chunk to the dictionary and go get a bigger one. returnChunkToDictionary(fc); - fc = _dictionary->get_chunk(size + MinChunkSize); + fc = _dictionary->get_chunk(size + MinChunkSize, + FreeBlockDictionary::atLeast); if (fc == NULL) { return NULL; } diff --git a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.hpp b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.hpp index 1b3d93ed248..23c95897cfa 100644 --- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.hpp +++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.hpp @@ -131,7 +131,7 @@ class CompactibleFreeListSpace: public CompactibleSpace { LinearAllocBlock _smallLinearAllocBlock; FreeBlockDictionary::DictionaryChoice _dictionaryChoice; - FreeBlockDictionary* _dictionary; // ptr to dictionary for large size blocks + AFLBinaryTreeDictionary* _dictionary; // ptr to dictionary for large size blocks AdaptiveFreeList _indexedFreeList[IndexSetSize]; // indexed array for small size blocks diff --git a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/vmStructs_cms.hpp b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/vmStructs_cms.hpp index a67e19d89d2..3a8499b27e3 100644 --- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/vmStructs_cms.hpp +++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/vmStructs_cms.hpp @@ -25,8 +25,6 @@ #ifndef SHARE_VM_GC_IMPLEMENTATION_CONCURRENTMARKSWEEP_VMSTRUCTS_CMS_HPP #define SHARE_VM_GC_IMPLEMENTATION_CONCURRENTMARKSWEEP_VMSTRUCTS_CMS_HPP -typedef BinaryTreeDictionary AFLBinaryTreeDictionary; - #define VM_STRUCTS_CMS(nonstatic_field, \ volatile_nonstatic_field, \ static_field) \ @@ -42,6 +40,7 @@ typedef BinaryTreeDictionary AFLBinaryTreeDictionar static_field(ConcurrentMarkSweepThread, _collector, CMSCollector*) \ nonstatic_field(LinearAllocBlock, _word_size, size_t) \ nonstatic_field(AFLBinaryTreeDictionary, _total_size, size_t) \ + nonstatic_field(CompactibleFreeListSpace, _dictionary, AFLBinaryTreeDictionary*) \ nonstatic_field(CompactibleFreeListSpace, _indexedFreeList[0], FreeList) \ nonstatic_field(CompactibleFreeListSpace, _smallLinearAllocBlock, LinearAllocBlock) @@ -62,10 +61,9 @@ typedef BinaryTreeDictionary AFLBinaryTreeDictionar declare_toplevel_type(SurrogateLockerThread*) \ declare_toplevel_type(CompactibleFreeListSpace*) \ declare_toplevel_type(CMSCollector*) \ - declare_toplevel_type(AFLBinaryTreeDictionary*) \ + declare_toplevel_type(AFLBinaryTreeDictionary) \ declare_toplevel_type(LinearAllocBlock) \ - declare_toplevel_type(FreeBlockDictionary) \ - declare_type(AFLBinaryTreeDictionary, FreeBlockDictionary) + declare_toplevel_type(FreeBlockDictionary) #define VM_INT_CONSTANTS_CMS(declare_constant) \ declare_constant(Generation::ConcurrentMarkSweep) \ diff --git a/hotspot/src/share/vm/memory/binaryTreeDictionary.cpp b/hotspot/src/share/vm/memory/binaryTreeDictionary.cpp index 725a71925dc..1bb78ca99fd 100644 --- a/hotspot/src/share/vm/memory/binaryTreeDictionary.cpp +++ b/hotspot/src/share/vm/memory/binaryTreeDictionary.cpp @@ -873,7 +873,7 @@ void BinaryTreeDictionary::dict_census_update(size_t size, #ifndef SERIALGC template <> -void BinaryTreeDictionary::dict_census_update(size_t size, bool split, bool birth){ +void AFLBinaryTreeDictionary::dict_census_update(size_t size, bool split, bool birth){ TreeList* nd = find_list(size); if (nd) { if (split) { @@ -911,7 +911,7 @@ bool BinaryTreeDictionary::coal_dict_over_populated(size_t #ifndef SERIALGC template <> -bool BinaryTreeDictionary::coal_dict_over_populated(size_t size) { +bool AFLBinaryTreeDictionary::coal_dict_over_populated(size_t size) { if (FLSAlwaysCoalesceLarge) return true; TreeList* list_of_size = find_list(size); @@ -1288,7 +1288,7 @@ void BinaryTreeDictionary::print_dict_census(void) const { #ifndef SERIALGC template <> -void BinaryTreeDictionary::print_dict_census(void) const { +void AFLBinaryTreeDictionary::print_dict_census(void) const { gclog_or_tty->print("\nBinaryTree\n"); AdaptiveFreeList::print_labels_on(gclog_or_tty, "size"); diff --git a/hotspot/src/share/vm/memory/binaryTreeDictionary.hpp b/hotspot/src/share/vm/memory/binaryTreeDictionary.hpp index 757eb4fdac9..460a4ea29e1 100644 --- a/hotspot/src/share/vm/memory/binaryTreeDictionary.hpp +++ b/hotspot/src/share/vm/memory/binaryTreeDictionary.hpp @@ -43,6 +43,10 @@ template class FreeList_t> class AscendTreeCens template class FreeList_t> class DescendTreeCensusClosure; template class FreeList_t> class DescendTreeSearchClosure; +class FreeChunk; +template class AdaptiveFreeList; +typedef BinaryTreeDictionary AFLBinaryTreeDictionary; + template class FreeList_t> class TreeList : public FreeList_t { friend class TreeChunk; diff --git a/hotspot/src/share/vm/runtime/vmStructs.cpp b/hotspot/src/share/vm/runtime/vmStructs.cpp index e180f7d449f..70e5d2b9281 100644 --- a/hotspot/src/share/vm/runtime/vmStructs.cpp +++ b/hotspot/src/share/vm/runtime/vmStructs.cpp @@ -2087,8 +2087,7 @@ typedef BinaryTreeDictionary MetablockTreeDictionary; declare_toplevel_type(FreeBlockDictionary*) \ declare_toplevel_type(FreeList*) \ declare_toplevel_type(FreeList) \ - declare_toplevel_type(MetablockTreeDictionary*) \ - declare_type(MetablockTreeDictionary, FreeBlockDictionary) + declare_type(MetablockTreeDictionary, FreeBlockDictionary) //-------------------------------------------------------------------------------- From 8762d54e63d2f6c3609a254e44be070f8c612903 Mon Sep 17 00:00:00 2001 From: Bharadwaj Yadavalli Date: Wed, 9 Jan 2013 11:39:30 -0500 Subject: [PATCH 002/210] 8005689: InterfaceAccessFlagsTest failures in Lambda-JDK tests Fix verifier for new interface access flags Reviewed-by: acorn, kvn --- .../share/vm/classfile/classFileParser.cpp | 40 +++++++++++++++---- 1 file changed, 33 insertions(+), 7 deletions(-) diff --git a/hotspot/src/share/vm/classfile/classFileParser.cpp b/hotspot/src/share/vm/classfile/classFileParser.cpp index 9dd0640de06..efb6138e583 100644 --- a/hotspot/src/share/vm/classfile/classFileParser.cpp +++ b/hotspot/src/share/vm/classfile/classFileParser.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, 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 @@ -3912,7 +3912,10 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name, // check that if this class is an interface then it doesn't have static methods if (this_klass->is_interface()) { - check_illegal_static_method(this_klass, CHECK_(nullHandle)); + /* An interface in a JAVA 8 classfile can be static */ + if (_major_version < JAVA_8_VERSION) { + check_illegal_static_method(this_klass, CHECK_(nullHandle)); + } } @@ -4466,6 +4469,7 @@ void ClassFileParser::verify_legal_method_modifiers( const bool is_bridge = (flags & JVM_ACC_BRIDGE) != 0; const bool is_strict = (flags & JVM_ACC_STRICT) != 0; const bool is_synchronized = (flags & JVM_ACC_SYNCHRONIZED) != 0; + const bool is_protected = (flags & JVM_ACC_PROTECTED) != 0; const bool major_gte_15 = _major_version >= JAVA_1_5_VERSION; const bool major_gte_8 = _major_version >= JAVA_8_VERSION; const bool is_initializer = (name == vmSymbols::object_initializer_name()); @@ -4473,11 +4477,33 @@ void ClassFileParser::verify_legal_method_modifiers( bool is_illegal = false; if (is_interface) { - if (!is_public || is_static || is_final || is_native || - ((is_synchronized || is_strict) && major_gte_15 && - (!major_gte_8 || is_abstract)) || - (!major_gte_8 && !is_abstract)) { - is_illegal = true; + if (major_gte_8) { + // Class file version is JAVA_8_VERSION or later Methods of + // interfaces may set any of the flags except ACC_PROTECTED, + // ACC_FINAL, ACC_NATIVE, and ACC_SYNCHRONIZED; they must + // have exactly one of the ACC_PUBLIC or ACC_PRIVATE flags set. + if ((is_public == is_private) || /* Only one of private and public should be true - XNOR */ + (is_native || is_protected || is_final || is_synchronized) || + // If a specific method of a class or interface has its + // ACC_ABSTRACT flag set, it must not have any of its + // ACC_FINAL, ACC_NATIVE, ACC_PRIVATE, ACC_STATIC, + // ACC_STRICT, or ACC_SYNCHRONIZED flags set. No need to + // check for ACC_FINAL, ACC_NATIVE or ACC_SYNCHRONIZED as + // those flags are illegal irrespective of ACC_ABSTRACT being set or not. + (is_abstract && (is_private || is_static || is_strict))) { + is_illegal = true; + } + } else if (major_gte_15) { + // Class file version in the interval [JAVA_1_5_VERSION, JAVA_8_VERSION) + if (!is_public || is_static || is_final || is_synchronized || + is_native || !is_abstract || is_strict) { + is_illegal = true; + } + } else { + // Class file version is pre-JAVA_1_5_VERSION + if (!is_public || is_static || is_final || is_native || !is_abstract) { + is_illegal = true; + } } } else { // not interface if (is_initializer) { From 030fa5107d44b37dce7a61306b186bd9eb6ceb28 Mon Sep 17 00:00:00 2001 From: Zhengyu Gu Date: Wed, 9 Jan 2013 14:46:55 -0500 Subject: [PATCH 003/210] 7152671: RFE: Windows decoder should add some std dirs to the symbol search path Added JRE/JDK bin directories to decoder's symbol search path Reviewed-by: dcubed, sla --- hotspot/src/os/windows/vm/decoder_windows.cpp | 78 ++++++++++++++++++- hotspot/src/os/windows/vm/decoder_windows.hpp | 2 + 2 files changed, 77 insertions(+), 3 deletions(-) diff --git a/hotspot/src/os/windows/vm/decoder_windows.cpp b/hotspot/src/os/windows/vm/decoder_windows.cpp index 82ba909bc5c..2b4682728a2 100644 --- a/hotspot/src/os/windows/vm/decoder_windows.cpp +++ b/hotspot/src/os/windows/vm/decoder_windows.cpp @@ -49,7 +49,7 @@ void WindowsDecoder::initialize() { pfn_SymSetOptions _pfnSymSetOptions = (pfn_SymSetOptions)::GetProcAddress(handle, "SymSetOptions"); pfn_SymInitialize _pfnSymInitialize = (pfn_SymInitialize)::GetProcAddress(handle, "SymInitialize"); _pfnSymGetSymFromAddr64 = (pfn_SymGetSymFromAddr64)::GetProcAddress(handle, "SymGetSymFromAddr64"); - _pfnUndecorateSymbolName = (pfn_UndecorateSymbolName)GetProcAddress(handle, "UnDecorateSymbolName"); + _pfnUndecorateSymbolName = (pfn_UndecorateSymbolName)::GetProcAddress(handle, "UnDecorateSymbolName"); if (_pfnSymSetOptions == NULL || _pfnSymInitialize == NULL || _pfnSymGetSymFromAddr64 == NULL) { _pfnSymGetSymFromAddr64 = NULL; @@ -60,8 +60,9 @@ void WindowsDecoder::initialize() { return; } - _pfnSymSetOptions(SYMOPT_UNDNAME | SYMOPT_DEFERRED_LOADS); - if (!_pfnSymInitialize(GetCurrentProcess(), NULL, TRUE)) { + HANDLE hProcess = ::GetCurrentProcess(); + _pfnSymSetOptions(SYMOPT_UNDNAME | SYMOPT_DEFERRED_LOADS | SYMOPT_EXACT_SYMBOLS); + if (!_pfnSymInitialize(hProcess, NULL, TRUE)) { _pfnSymGetSymFromAddr64 = NULL; _pfnUndecorateSymbolName = NULL; ::FreeLibrary(handle); @@ -70,6 +71,77 @@ void WindowsDecoder::initialize() { return; } + // set pdb search paths + pfn_SymSetSearchPath _pfn_SymSetSearchPath = + (pfn_SymSetSearchPath)::GetProcAddress(handle, "SymSetSearchPath"); + pfn_SymGetSearchPath _pfn_SymGetSearchPath = + (pfn_SymGetSearchPath)::GetProcAddress(handle, "SymGetSearchPath"); + if (_pfn_SymSetSearchPath != NULL && _pfn_SymGetSearchPath != NULL) { + char paths[MAX_PATH]; + int len = sizeof(paths); + if (!_pfn_SymGetSearchPath(hProcess, paths, len)) { + paths[0] = '\0'; + } else { + // available spaces in path buffer + len -= (int)strlen(paths); + } + + char tmp_path[MAX_PATH]; + DWORD dwSize; + HMODULE hJVM = ::GetModuleHandle("jvm.dll"); + tmp_path[0] = '\0'; + // append the path where jvm.dll is located + if (hJVM != NULL && (dwSize = ::GetModuleFileName(hJVM, tmp_path, sizeof(tmp_path))) > 0) { + while (dwSize > 0 && tmp_path[dwSize] != '\\') { + dwSize --; + } + + tmp_path[dwSize] = '\0'; + + if (dwSize > 0 && len > (int)dwSize + 1) { + strncat(paths, os::path_separator(), 1); + strncat(paths, tmp_path, dwSize); + len -= dwSize + 1; + } + } + + // append $JRE/bin. Arguments::get_java_home actually returns $JRE + // path + char *p = Arguments::get_java_home(); + assert(p != NULL, "empty java home"); + size_t java_home_len = strlen(p); + if (len > (int)java_home_len + 5) { + strncat(paths, os::path_separator(), 1); + strncat(paths, p, java_home_len); + strncat(paths, "\\bin", 4); + len -= (int)(java_home_len + 5); + } + + // append $JDK/bin path if it exists + assert(java_home_len < MAX_PATH, "Invalid path length"); + // assume $JRE is under $JDK, construct $JDK/bin path and + // see if it exists or not + if (strncmp(&p[java_home_len - 3], "jre", 3) == 0) { + strncpy(tmp_path, p, java_home_len - 3); + tmp_path[java_home_len - 3] = '\0'; + strncat(tmp_path, "bin", 3); + + // if the directory exists + DWORD dwAttrib = GetFileAttributes(tmp_path); + if (dwAttrib != INVALID_FILE_ATTRIBUTES && + (dwAttrib & FILE_ATTRIBUTE_DIRECTORY)) { + // tmp_path should have the same length as java_home_len, since we only + // replaced 'jre' with 'bin' + if (len > (int)java_home_len + 1) { + strncat(paths, os::path_separator(), 1); + strncat(paths, tmp_path, java_home_len); + } + } + } + + _pfn_SymSetSearchPath(hProcess, paths); + } + // find out if jvm.dll contains private symbols, by decoding // current function and comparing the result address addr = (address)Decoder::demangle; diff --git a/hotspot/src/os/windows/vm/decoder_windows.hpp b/hotspot/src/os/windows/vm/decoder_windows.hpp index b2c2638d8ab..3008ee79136 100644 --- a/hotspot/src/os/windows/vm/decoder_windows.hpp +++ b/hotspot/src/os/windows/vm/decoder_windows.hpp @@ -35,6 +35,8 @@ typedef DWORD (WINAPI *pfn_SymSetOptions)(DWORD); typedef BOOL (WINAPI *pfn_SymInitialize)(HANDLE, PCTSTR, BOOL); typedef BOOL (WINAPI *pfn_SymGetSymFromAddr64)(HANDLE, DWORD64, PDWORD64, PIMAGEHLP_SYMBOL64); typedef DWORD (WINAPI *pfn_UndecorateSymbolName)(const char*, char*, DWORD, DWORD); +typedef BOOL (WINAPI *pfn_SymSetSearchPath)(HANDLE, PCTSTR); +typedef BOOL (WINAPI *pfn_SymGetSearchPath)(HANDLE, PTSTR, int); class WindowsDecoder : public AbstractDecoder { From 472004ca58f6c7189b23d1298adec5550e991fad Mon Sep 17 00:00:00 2001 From: Karen Kinnear Date: Thu, 10 Jan 2013 17:38:20 -0500 Subject: [PATCH 004/210] 7199207: NPG: Crash in PlaceholderTable::verify after StackOverflow Reduce scope of placeholder table entries to improve cleanup Reviewed-by: dholmes, coleenp --- .../src/share/vm/classfile/placeholders.cpp | 12 +- .../src/share/vm/classfile/placeholders.hpp | 10 +- .../share/vm/classfile/systemDictionary.cpp | 174 ++++++------------ hotspot/src/share/vm/utilities/exceptions.hpp | 3 +- 4 files changed, 72 insertions(+), 127 deletions(-) diff --git a/hotspot/src/share/vm/classfile/placeholders.cpp b/hotspot/src/share/vm/classfile/placeholders.cpp index 1babaaf978c..10d7650db58 100644 --- a/hotspot/src/share/vm/classfile/placeholders.cpp +++ b/hotspot/src/share/vm/classfile/placeholders.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2013, 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 @@ -142,7 +142,7 @@ PlaceholderEntry* PlaceholderTable::find_and_add(int index, unsigned int hash, } -// placeholder used to track class loading internal states +// placeholder is used to track class loading internal states // placeholder existence now for loading superclass/superinterface // superthreadQ tracks class circularity, while loading superclass/superinterface // loadInstanceThreadQ tracks load_instance_class calls @@ -153,15 +153,17 @@ PlaceholderEntry* PlaceholderTable::find_and_add(int index, unsigned int hash, // All claimants remove SeenThread after completing action // On removal: if definer and all queues empty, remove entry // Note: you can be in both placeholders and systemDictionary -// see parse_stream for redefine classes // Therefore - must always check SD first // Ignores the case where entry is not found void PlaceholderTable::find_and_remove(int index, unsigned int hash, - Symbol* name, ClassLoaderData* loader_data, Thread* thread) { + Symbol* name, ClassLoaderData* loader_data, + classloadAction action, + Thread* thread) { assert_locked_or_safepoint(SystemDictionary_lock); PlaceholderEntry *probe = get_entry(index, hash, name, loader_data); if (probe != NULL) { - // No other threads using this entry + probe->remove_seen_thread(thread, action); + // If no other threads using this entry, and this thread is not using this entry for other states if ((probe->superThreadQ() == NULL) && (probe->loadInstanceThreadQ() == NULL) && (probe->defineThreadQ() == NULL) && (probe->definer() == NULL)) { remove_entry(index, hash, name, loader_data); diff --git a/hotspot/src/share/vm/classfile/placeholders.hpp b/hotspot/src/share/vm/classfile/placeholders.hpp index af4518a462f..ca0d85af0fb 100644 --- a/hotspot/src/share/vm/classfile/placeholders.hpp +++ b/hotspot/src/share/vm/classfile/placeholders.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2013, 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 @@ -82,7 +82,7 @@ public: }; // find_and_add returns probe pointer - old or new - // If no entry exists, add a placeholder entry and push SeenThread + // If no entry exists, add a placeholder entry and push SeenThread for classloadAction // If entry exists, reuse entry and push SeenThread for classloadAction PlaceholderEntry* find_and_add(int index, unsigned int hash, Symbol* name, ClassLoaderData* loader_data, @@ -92,9 +92,11 @@ public: void remove_entry(int index, unsigned int hash, Symbol* name, ClassLoaderData* loader_data); -// Remove placeholder information + // find_and_remove first removes SeenThread for classloadAction + // If all queues are empty and definer is null, remove the PlacheholderEntry completely void find_and_remove(int index, unsigned int hash, - Symbol* name, ClassLoaderData* loader_data, Thread* thread); + Symbol* name, ClassLoaderData* loader_data, + classloadAction action, Thread* thread); // GC support. void classes_do(KlassClosure* f); diff --git a/hotspot/src/share/vm/classfile/systemDictionary.cpp b/hotspot/src/share/vm/classfile/systemDictionary.cpp index a493e73d84d..54601625056 100644 --- a/hotspot/src/share/vm/classfile/systemDictionary.cpp +++ b/hotspot/src/share/vm/classfile/systemDictionary.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, 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 @@ -172,7 +172,7 @@ Klass* SystemDictionary::handle_resolution_exception(Symbol* class_name, Handle assert(klass_h() == NULL, "Should not have result with exception pending"); Handle e(THREAD, PENDING_EXCEPTION); CLEAR_PENDING_EXCEPTION; - THROW_MSG_CAUSE_0(vmSymbols::java_lang_NoClassDefFoundError(), class_name->as_C_string(), e); + THROW_MSG_CAUSE_NULL(vmSymbols::java_lang_NoClassDefFoundError(), class_name->as_C_string(), e); } else { return NULL; } @@ -181,9 +181,9 @@ Klass* SystemDictionary::handle_resolution_exception(Symbol* class_name, Handle if (klass_h() == NULL) { ResourceMark rm(THREAD); if (throw_error) { - THROW_MSG_0(vmSymbols::java_lang_NoClassDefFoundError(), class_name->as_C_string()); + THROW_MSG_NULL(vmSymbols::java_lang_NoClassDefFoundError(), class_name->as_C_string()); } else { - THROW_MSG_0(vmSymbols::java_lang_ClassNotFoundException(), class_name->as_C_string()); + THROW_MSG_NULL(vmSymbols::java_lang_ClassNotFoundException(), class_name->as_C_string()); } } return (Klass*)klass_h(); @@ -343,29 +343,29 @@ Klass* SystemDictionary::resolve_super_or_fail(Symbol* child_name, } if (throw_circularity_error) { ResourceMark rm(THREAD); - THROW_MSG_0(vmSymbols::java_lang_ClassCircularityError(), child_name->as_C_string()); + THROW_MSG_NULL(vmSymbols::java_lang_ClassCircularityError(), child_name->as_C_string()); } // java.lang.Object should have been found above assert(class_name != NULL, "null super class for resolving"); // Resolve the super class or interface, check results on return - Klass* superk = NULL; - superk = SystemDictionary::resolve_or_null(class_name, + Klass* superk = SystemDictionary::resolve_or_null(class_name, class_loader, protection_domain, THREAD); KlassHandle superk_h(THREAD, superk); - // Note: clean up of placeholders currently in callers of - // resolve_super_or_fail - either at update_dictionary time - // or on error + // Clean up of placeholders moved so that each classloadAction registrar self-cleans up + // It is no longer necessary to keep the placeholder table alive until update_dictionary + // or error. GC used to walk the placeholder table as strong roots. + // The instanceKlass is kept alive because the class loader is on the stack, + // which keeps the loader_data alive, as well as all instanceKlasses in + // the loader_data. parseClassFile adds the instanceKlass to loader_data. { - MutexLocker mu(SystemDictionary_lock, THREAD); - PlaceholderEntry* probe = placeholders()->get_entry(p_index, p_hash, child_name, loader_data); - if (probe != NULL) { - probe->remove_seen_thread(THREAD, PlaceholderTable::LOAD_SUPER); - } + MutexLocker mu(SystemDictionary_lock, THREAD); + placeholders()->find_and_remove(p_index, p_hash, child_name, loader_data, PlaceholderTable::LOAD_SUPER, THREAD); + SystemDictionary_lock->notify_all(); } if (HAS_PENDING_EXCEPTION || superk_h() == NULL) { // can null superk @@ -430,8 +430,8 @@ void SystemDictionary::validate_protection_domain(instanceKlassHandle klass, // We're using a No_Safepoint_Verifier to catch any place where we // might potentially do a GC at all. - // SystemDictionary::do_unloading() asserts that classes are only - // unloaded at a safepoint. + // Dictionary::do_unloading() asserts that classes in SD are only + // unloaded at a safepoint. Anonymous classes are not in SD. No_Safepoint_Verifier nosafepoint; dictionary()->add_protection_domain(d_index, d_hash, klass, loader_data, protection_domain, THREAD); @@ -486,7 +486,6 @@ void SystemDictionary::double_lock_wait(Handle lockObject, TRAPS) { // super class loading here. // This also is critical in cases where the original thread gets stalled // even in non-circularity situations. -// Note: only one thread can define the class, but multiple can resolve // Note: must call resolve_super_or_fail even if null super - // to force placeholder entry creation for this class for circularity detection // Caller must check for pending exception @@ -518,14 +517,6 @@ instanceKlassHandle SystemDictionary::handle_parallel_super_load( protection_domain, true, CHECK_(nh)); - // We don't redefine the class, so we just need to clean up if there - // was not an error (don't want to modify any system dictionary - // data structures). - { - MutexLocker mu(SystemDictionary_lock, THREAD); - placeholders()->find_and_remove(p_index, p_hash, name, loader_data, THREAD); - SystemDictionary_lock->notify_all(); - } // parallelCapable class loaders do NOT wait for parallel superclass loads to complete // Serial class loaders and bootstrap classloader do wait for superclass loads @@ -595,6 +586,10 @@ Klass* SystemDictionary::resolve_instance_class_or_null(Symbol* name, Handle cla // Do lookup to see if class already exist and the protection domain // has the right access + // This call uses find which checks protection domain already matches + // All subsequent calls use find_class, and set has_loaded_class so that + // before we return a result we call out to java to check for valid protection domain + // to allow returning the Klass* and add it to the pd_set if it is valid unsigned int d_hash = dictionary()->compute_hash(name, loader_data); int d_index = dictionary()->hash_to_index(d_hash); Klass* probe = dictionary()->find(d_index, d_hash, name, loader_data, @@ -652,7 +647,7 @@ Klass* SystemDictionary::resolve_instance_class_or_null(Symbol* name, Handle cla } } - // If the class in is in the placeholder table, class loading is in progress + // If the class is in the placeholder table, class loading is in progress if (super_load_in_progress && havesupername==true) { k = SystemDictionary::handle_parallel_super_load(name, superclassname, class_loader, protection_domain, lockObject, THREAD); @@ -664,7 +659,9 @@ Klass* SystemDictionary::resolve_instance_class_or_null(Symbol* name, Handle cla } } + bool throw_circularity_error = false; if (!class_has_been_loaded) { + bool load_instance_added = false; // add placeholder entry to record loading instance class // Five cases: @@ -690,7 +687,7 @@ Klass* SystemDictionary::resolve_instance_class_or_null(Symbol* name, Handle cla // No performance benefit and no deadlock issues. // case 5. parallelCapable user level classloaders - without objectLocker // Allow parallel classloading of a class/classloader pair - bool throw_circularity_error = false; + { MutexLocker mu(SystemDictionary_lock, THREAD); if (class_loader.is_null() || !is_parallelCapable(class_loader)) { @@ -726,12 +723,13 @@ Klass* SystemDictionary::resolve_instance_class_or_null(Symbol* name, Handle cla } } } - // All cases: add LOAD_INSTANCE + // All cases: add LOAD_INSTANCE holding SystemDictionary_lock // case 3: UnsyncloadClass || case 5: parallelCapable: allow competing threads to try // LOAD_INSTANCE in parallel - // add placeholder entry even if error - callers will remove on error + if (!throw_circularity_error && !class_has_been_loaded) { PlaceholderEntry* newprobe = placeholders()->find_and_add(p_index, p_hash, name, loader_data, PlaceholderTable::LOAD_INSTANCE, NULL, THREAD); + load_instance_added = true; // For class loaders that do not acquire the classloader object lock, // if they did not catch another thread holding LOAD_INSTANCE, // need a check analogous to the acquire ObjectLocker/find_class @@ -740,19 +738,18 @@ Klass* SystemDictionary::resolve_instance_class_or_null(Symbol* name, Handle cla // class loaders holding the ObjectLock shouldn't find the class here Klass* check = find_class(d_index, d_hash, name, loader_data); if (check != NULL) { - // Klass is already loaded, so just return it + // Klass is already loaded, so return it after checking/adding protection domain k = instanceKlassHandle(THREAD, check); class_has_been_loaded = true; - newprobe->remove_seen_thread(THREAD, PlaceholderTable::LOAD_INSTANCE); - placeholders()->find_and_remove(p_index, p_hash, name, loader_data, THREAD); - SystemDictionary_lock->notify_all(); } } } + // must throw error outside of owning lock if (throw_circularity_error) { + assert(!HAS_PENDING_EXCEPTION && load_instance_added == false,"circularity error cleanup"); ResourceMark rm(THREAD); - THROW_MSG_0(vmSymbols::java_lang_ClassCircularityError(), name->as_C_string()); + THROW_MSG_NULL(vmSymbols::java_lang_ClassCircularityError(), name->as_C_string()); } if (!class_has_been_loaded) { @@ -782,20 +779,6 @@ Klass* SystemDictionary::resolve_instance_class_or_null(Symbol* name, Handle cla } } - // clean up placeholder entries for success or error - // This cleans up LOAD_INSTANCE entries - // It also cleans up LOAD_SUPER entries on errors from - // calling load_instance_class - { - MutexLocker mu(SystemDictionary_lock, THREAD); - PlaceholderEntry* probe = placeholders()->get_entry(p_index, p_hash, name, loader_data); - if (probe != NULL) { - probe->remove_seen_thread(THREAD, PlaceholderTable::LOAD_INSTANCE); - placeholders()->find_and_remove(p_index, p_hash, name, loader_data, THREAD); - SystemDictionary_lock->notify_all(); - } - } - // If everything was OK (no exceptions, no null return value), and // class_loader is NOT the defining loader, do a little more bookkeeping. if (!HAS_PENDING_EXCEPTION && !k.is_null() && @@ -819,18 +802,22 @@ Klass* SystemDictionary::resolve_instance_class_or_null(Symbol* name, Handle cla } } } - if (HAS_PENDING_EXCEPTION || k.is_null()) { - // On error, clean up placeholders - { - MutexLocker mu(SystemDictionary_lock, THREAD); - placeholders()->find_and_remove(p_index, p_hash, name, loader_data, THREAD); - SystemDictionary_lock->notify_all(); - } - return NULL; - } + } // load_instance_class loop + + if (load_instance_added == true) { + // clean up placeholder entries for LOAD_INSTANCE success or error + // This brackets the SystemDictionary updates for both defining + // and initiating loaders + MutexLocker mu(SystemDictionary_lock, THREAD); + placeholders()->find_and_remove(p_index, p_hash, name, loader_data, PlaceholderTable::LOAD_INSTANCE, THREAD); + SystemDictionary_lock->notify_all(); } } + if (HAS_PENDING_EXCEPTION || k.is_null()) { + return NULL; + } + #ifdef ASSERT { ClassLoaderData* loader_data = k->class_loader_data(); @@ -850,8 +837,8 @@ Klass* SystemDictionary::resolve_instance_class_or_null(Symbol* name, Handle cla // so we cannot allow GC to occur while we're holding this entry. // We're using a No_Safepoint_Verifier to catch any place where we // might potentially do a GC at all. - // SystemDictionary::do_unloading() asserts that classes are only - // unloaded at a safepoint. + // Dictionary::do_unloading() asserts that classes in SD are only + // unloaded at a safepoint. Anonymous classes are not in SD. No_Safepoint_Verifier nosafepoint; if (dictionary()->is_valid_protection_domain(d_index, d_hash, name, loader_data, @@ -898,8 +885,8 @@ Klass* SystemDictionary::find(Symbol* class_name, // so we cannot allow GC to occur while we're holding this entry. // We're using a No_Safepoint_Verifier to catch any place where we // might potentially do a GC at all. - // SystemDictionary::do_unloading() asserts that classes are only - // unloaded at a safepoint. + // Dictionary::do_unloading() asserts that classes in SD are only + // unloaded at a safepoint. Anonymous classes are not in SD. No_Safepoint_Verifier nosafepoint; return dictionary()->find(d_index, d_hash, class_name, loader_data, protection_domain, THREAD); @@ -965,10 +952,6 @@ Klass* SystemDictionary::parse_stream(Symbol* class_name, // throw potential ClassFormatErrors. // // Note: "name" is updated. - // Further note: a placeholder will be added for this class when - // super classes are loaded (resolve_super_or_fail). We expect this - // to be called for all classes but java.lang.Object; and we preload - // java.lang.Object through resolve_or_fail, not this path. instanceKlassHandle k = ClassFileParser(st).parseClassFile(class_name, loader_data, @@ -979,21 +962,6 @@ Klass* SystemDictionary::parse_stream(Symbol* class_name, true, THREAD); - // We don't redefine the class, so we just need to clean up whether there - // was an error or not (don't want to modify any system dictionary - // data structures). - // Parsed name could be null if we threw an error before we got far - // enough along to parse it -- in that case, there is nothing to clean up. - if (parsed_name != NULL) { - unsigned int p_hash = placeholders()->compute_hash(parsed_name, - loader_data); - int p_index = placeholders()->hash_to_index(p_hash); - { - MutexLocker mu(SystemDictionary_lock, THREAD); - placeholders()->find_and_remove(p_index, p_hash, parsed_name, loader_data, THREAD); - SystemDictionary_lock->notify_all(); - } - } if (host_klass.not_null() && k.not_null()) { assert(EnableInvokeDynamic, ""); @@ -1062,10 +1030,6 @@ Klass* SystemDictionary::resolve_from_stream(Symbol* class_name, // throw potential ClassFormatErrors. // // Note: "name" is updated. - // Further note: a placeholder will be added for this class when - // super classes are loaded (resolve_super_or_fail). We expect this - // to be called for all classes but java.lang.Object; and we preload - // java.lang.Object through resolve_or_fail, not this path. instanceKlassHandle k = ClassFileParser(st).parseClassFile(class_name, loader_data, @@ -1114,25 +1078,7 @@ Klass* SystemDictionary::resolve_from_stream(Symbol* class_name, } } - // If parsing the class file or define_instance_class failed, we - // need to remove the placeholder added on our behalf. But we - // must make sure parsed_name is valid first (it won't be if we had - // a format error before the class was parsed far enough to - // find the name). - if (HAS_PENDING_EXCEPTION && parsed_name != NULL) { - unsigned int p_hash = placeholders()->compute_hash(parsed_name, - loader_data); - int p_index = placeholders()->hash_to_index(p_hash); - { - MutexLocker mu(SystemDictionary_lock, THREAD); - placeholders()->find_and_remove(p_index, p_hash, parsed_name, loader_data, THREAD); - SystemDictionary_lock->notify_all(); - } - return NULL; - } - - // Make sure that we didn't leave a place holder in the - // SystemDictionary; this is only done on success + // Make sure we have an entry in the SystemDictionary on success debug_only( { if (!HAS_PENDING_EXCEPTION) { assert(parsed_name != NULL, "parsed_name is still null?"); @@ -1547,8 +1493,7 @@ instanceKlassHandle SystemDictionary::find_or_define_instance_class(Symbol* clas // Other cases fall through, and may run into duplicate defines // caught by finding an entry in the SystemDictionary if ((UnsyncloadClass || is_parallelDefine(class_loader)) && (probe->instance_klass() != NULL)) { - probe->remove_seen_thread(THREAD, PlaceholderTable::DEFINE_CLASS); - placeholders()->find_and_remove(p_index, p_hash, name_h, loader_data, THREAD); + placeholders()->find_and_remove(p_index, p_hash, name_h, loader_data, PlaceholderTable::DEFINE_CLASS, THREAD); SystemDictionary_lock->notify_all(); #ifdef ASSERT Klass* check = find_class(d_index, d_hash, name_h, loader_data); @@ -1578,8 +1523,7 @@ instanceKlassHandle SystemDictionary::find_or_define_instance_class(Symbol* clas probe->set_instance_klass(k()); } probe->set_definer(NULL); - probe->remove_seen_thread(THREAD, PlaceholderTable::DEFINE_CLASS); - placeholders()->find_and_remove(p_index, p_hash, name_h, loader_data, THREAD); + placeholders()->find_and_remove(p_index, p_hash, name_h, loader_data, PlaceholderTable::DEFINE_CLASS, THREAD); SystemDictionary_lock->notify_all(); } } @@ -1736,6 +1680,8 @@ int SystemDictionary::calculate_systemdictionary_size(int classcount) { } return newsize; } +// Assumes classes in the SystemDictionary are only unloaded at a safepoint +// Note: anonymous classes are not in the SD. bool SystemDictionary::do_unloading(BoolObjectClosure* is_alive) { // First, mark for unload all ClassLoaderData referencing a dead class loader. bool has_dead_loaders = ClassLoaderDataGraph::do_unloading(is_alive); @@ -2105,9 +2051,7 @@ void SystemDictionary::update_dictionary(int d_index, unsigned int d_hash, // All loaded classes get a unique ID. TRACE_INIT_ID(k); - // Check for a placeholder. If there, remove it and make a - // new system dictionary entry. - placeholders()->find_and_remove(p_index, p_hash, name, loader_data, THREAD); + // Make a new system dictionary entry. Klass* sd_check = find_class(d_index, d_hash, name, loader_data); if (sd_check == NULL) { dictionary()->add_klass(name, loader_data, k); @@ -2116,12 +2060,8 @@ void SystemDictionary::update_dictionary(int d_index, unsigned int d_hash, #ifdef ASSERT sd_check = find_class(d_index, d_hash, name, loader_data); assert (sd_check != NULL, "should have entry in system dictionary"); -// Changed to allow PH to remain to complete class circularity checking -// while only one thread can define a class at one time, multiple -// classes can resolve the superclass for a class at one time, -// and the placeholder is used to track that -// Symbol* ph_check = find_placeholder(name, class_loader); -// assert (ph_check == NULL, "should not have a placeholder entry"); + // Note: there may be a placeholder entry: for circularity testing + // or for parallel defines #endif SystemDictionary_lock->notify_all(); } diff --git a/hotspot/src/share/vm/utilities/exceptions.hpp b/hotspot/src/share/vm/utilities/exceptions.hpp index 740912d3909..089cd3e0811 100644 --- a/hotspot/src/share/vm/utilities/exceptions.hpp +++ b/hotspot/src/share/vm/utilities/exceptions.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2013, 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 @@ -267,6 +267,7 @@ class Exceptions { #define THROW_WRAPPED_0(name, oop_to_wrap) THROW_WRAPPED_(name, oop_to_wrap, 0) #define THROW_ARG_0(name, signature, arg) THROW_ARG_(name, signature, arg, 0) #define THROW_MSG_CAUSE_0(name, message, cause) THROW_MSG_CAUSE_(name, message, cause, 0) +#define THROW_MSG_CAUSE_NULL(name, message, cause) THROW_MSG_CAUSE_(name, message, cause, NULL) #define THROW_NULL(name) THROW_(name, NULL) #define THROW_MSG_NULL(name, message) THROW_MSG_(name, message, NULL) From e7e6443c6d3c1e98d289306b38c5d2a101cc8e51 Mon Sep 17 00:00:00 2001 From: Mikael Vidstedt Date: Thu, 10 Jan 2013 17:06:26 -0800 Subject: [PATCH 005/210] 8004747: Remove last_entry from VM_STRUCT macros Instead of passing in last_entry to all the VM_ macros just expand it in the main vmStructs.cpp file. Reviewed-by: dholmes, sspitsyn, minqi --- hotspot/src/cpu/sparc/vm/vmStructs_sparc.hpp | 29 +- hotspot/src/cpu/x86/vm/vmStructs_x86.hpp | 27 +- hotspot/src/cpu/zero/vm/vmStructs_zero.hpp | 24 +- .../os_cpu/bsd_x86/vm/vmStructs_bsd_x86.hpp | 23 +- .../os_cpu/bsd_zero/vm/vmStructs_bsd_zero.hpp | 16 +- .../linux_sparc/vm/vmStructs_linux_sparc.hpp | 25 +- .../linux_x86/vm/vmStructs_linux_x86.hpp | 23 +- .../linux_zero/vm/vmStructs_linux_zero.hpp | 17 +- .../vm/vmStructs_solaris_sparc.hpp | 26 +- .../solaris_x86/vm/vmStructs_solaris_x86.hpp | 24 +- .../windows_x86/vm/vmStructs_windows_x86.hpp | 23 +- hotspot/src/share/vm/runtime/vmStructs.cpp | 248 +++++++++--------- 12 files changed, 179 insertions(+), 326 deletions(-) diff --git a/hotspot/src/cpu/sparc/vm/vmStructs_sparc.hpp b/hotspot/src/cpu/sparc/vm/vmStructs_sparc.hpp index 8103a6395b7..11f829385b8 100644 --- a/hotspot/src/cpu/sparc/vm/vmStructs_sparc.hpp +++ b/hotspot/src/cpu/sparc/vm/vmStructs_sparc.hpp @@ -29,7 +29,7 @@ // constants required by the Serviceability Agent. This file is // referenced by vmStructs.cpp. -#define VM_STRUCTS_CPU(nonstatic_field, static_field, unchecked_nonstatic_field, volatile_nonstatic_field, nonproduct_nonstatic_field, c2_nonstatic_field, unchecked_c1_static_field, unchecked_c2_static_field, last_entry) \ +#define VM_STRUCTS_CPU(nonstatic_field, static_field, unchecked_nonstatic_field, volatile_nonstatic_field, nonproduct_nonstatic_field, c2_nonstatic_field, unchecked_c1_static_field, unchecked_c2_static_field) \ \ /******************************/ \ /* JavaCallWrapper */ \ @@ -37,22 +37,12 @@ /******************************/ \ /* JavaFrameAnchor */ \ /******************************/ \ - volatile_nonstatic_field(JavaFrameAnchor, _flags, int) \ - \ + volatile_nonstatic_field(JavaFrameAnchor, _flags, int) - /* NOTE that we do not use the last_entry() macro here; it is used */ - /* in vmStructs__.hpp's VM_STRUCTS_OS_CPU macro (and must */ - /* be present there) */ +#define VM_TYPES_CPU(declare_type, declare_toplevel_type, declare_oop_type, declare_integer_type, declare_unsigned_integer_type, declare_c1_toplevel_type, declare_c2_type, declare_c2_toplevel_type) -#define VM_TYPES_CPU(declare_type, declare_toplevel_type, declare_oop_type, declare_integer_type, declare_unsigned_integer_type, declare_c1_toplevel_type, declare_c2_type, declare_c2_toplevel_type, last_entry) \ - - /* NOTE that we do not use the last_entry() macro here; it is used */ - /* in vmStructs__.hpp's VM_TYPES_OS_CPU macro (and must */ - /* be present there) */ - - -#define VM_INT_CONSTANTS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant, last_entry) \ +#define VM_INT_CONSTANTS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) \ /******************************/ \ /* Register numbers (C2 only) */ \ /******************************/ \ @@ -90,15 +80,6 @@ declare_c2_constant(R_G6_num) \ declare_c2_constant(R_G7_num) - - /* NOTE that we do not use the last_entry() macro here; it is used */ - /* in vmStructs__.hpp's VM_INT_CONSTANTS_OS_CPU macro (and must */ - /* be present there) */ - -#define VM_LONG_CONSTANTS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant, last_entry) \ - - /* NOTE that we do not use the last_entry() macro here; it is used */ - /* in vmStructs__.hpp's VM_LONG_CONSTANTS_OS_CPU macro (and must */ - /* be present there) */ +#define VM_LONG_CONSTANTS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) #endif // CPU_SPARC_VM_VMSTRUCTS_SPARC_HPP diff --git a/hotspot/src/cpu/x86/vm/vmStructs_x86.hpp b/hotspot/src/cpu/x86/vm/vmStructs_x86.hpp index 8dddc9c3e1d..847d08ed207 100644 --- a/hotspot/src/cpu/x86/vm/vmStructs_x86.hpp +++ b/hotspot/src/cpu/x86/vm/vmStructs_x86.hpp @@ -29,7 +29,7 @@ // constants required by the Serviceability Agent. This file is // referenced by vmStructs.cpp. -#define VM_STRUCTS_CPU(nonstatic_field, static_field, unchecked_nonstatic_field, volatile_nonstatic_field, nonproduct_nonstatic_field, c2_nonstatic_field, unchecked_c1_static_field, unchecked_c2_static_field, last_entry) \ +#define VM_STRUCTS_CPU(nonstatic_field, static_field, unchecked_nonstatic_field, volatile_nonstatic_field, nonproduct_nonstatic_field, c2_nonstatic_field, unchecked_c1_static_field, unchecked_c2_static_field) \ \ /******************************/ \ /* JavaCallWrapper */ \ @@ -37,31 +37,14 @@ /******************************/ \ /* JavaFrameAnchor */ \ /******************************/ \ - volatile_nonstatic_field(JavaFrameAnchor, _last_Java_fp, intptr_t*) \ - \ - - /* NOTE that we do not use the last_entry() macro here; it is used */ - /* in vmStructs__.hpp's VM_STRUCTS_OS_CPU macro (and must */ - /* be present there) */ + volatile_nonstatic_field(JavaFrameAnchor, _last_Java_fp, intptr_t*) -#define VM_TYPES_CPU(declare_type, declare_toplevel_type, declare_oop_type, declare_integer_type, declare_unsigned_integer_type, declare_c1_toplevel_type, declare_c2_type, declare_c2_toplevel_type, last_entry) \ - /* NOTE that we do not use the last_entry() macro here; it is used */ - /* in vmStructs__.hpp's VM_TYPES_OS_CPU macro (and must */ - /* be present there) */ +#define VM_TYPES_CPU(declare_type, declare_toplevel_type, declare_oop_type, declare_integer_type, declare_unsigned_integer_type, declare_c1_toplevel_type, declare_c2_type, declare_c2_toplevel_type) +#define VM_INT_CONSTANTS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) -#define VM_INT_CONSTANTS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant, last_entry) \ - - /* NOTE that we do not use the last_entry() macro here; it is used */ - /* in vmStructs__.hpp's VM_INT_CONSTANTS_OS_CPU macro (and must */ - /* be present there) */ - -#define VM_LONG_CONSTANTS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant, last_entry) \ - - /* NOTE that we do not use the last_entry() macro here; it is used */ - /* in vmStructs__.hpp's VM_LONG_CONSTANTS_OS_CPU macro (and must */ - /* be present there) */ +#define VM_LONG_CONSTANTS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) #endif // CPU_X86_VM_VMSTRUCTS_X86_HPP diff --git a/hotspot/src/cpu/zero/vm/vmStructs_zero.hpp b/hotspot/src/cpu/zero/vm/vmStructs_zero.hpp index 1b3815a0a2c..0bbc1f40f45 100644 --- a/hotspot/src/cpu/zero/vm/vmStructs_zero.hpp +++ b/hotspot/src/cpu/zero/vm/vmStructs_zero.hpp @@ -30,28 +30,12 @@ // constants required by the Serviceability Agent. This file is // referenced by vmStructs.cpp. -#define VM_STRUCTS_CPU(nonstatic_field, static_field, unchecked_nonstatic_field, volatile_nonstatic_field, nonproduct_nonstatic_field, c2_nonstatic_field, unchecked_c1_static_field, unchecked_c2_static_field, last_entry) \ +#define VM_STRUCTS_CPU(nonstatic_field, static_field, unchecked_nonstatic_field, volatile_nonstatic_field, nonproduct_nonstatic_field, c2_nonstatic_field, unchecked_c1_static_field, unchecked_c2_static_field) - /* NOTE that we do not use the last_entry() macro here; it is used */ - /* in vmStructs__.hpp's VM_STRUCTS_OS_CPU macro (and must */ - /* be present there) */ +#define VM_TYPES_CPU(declare_type, declare_toplevel_type, declare_oop_type, declare_integer_type, declare_unsigned_integer_type, declare_c1_toplevel_type, declare_c2_type, declare_c2_toplevel_type) -#define VM_TYPES_CPU(declare_type, declare_toplevel_type, declare_oop_type, declare_integer_type, declare_unsigned_integer_type, declare_c1_toplevel_type, declare_c2_type, declare_c2_toplevel_type, last_entry) \ +#define VM_INT_CONSTANTS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) - /* NOTE that we do not use the last_entry() macro here; it is used */ - /* in vmStructs__.hpp's VM_TYPES_OS_CPU macro (and must */ - /* be present there) */ - -#define VM_INT_CONSTANTS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant, last_entry) \ - - /* NOTE that we do not use the last_entry() macro here; it is used */ - /* in vmStructs__.hpp's VM_INT_CONSTANTS_OS_CPU macro (and must */ - /* be present there) */ - -#define VM_LONG_CONSTANTS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant, last_entry) \ - - /* NOTE that we do not use the last_entry() macro here; it is used */ - /* in vmStructs__.hpp's VM_LONG_CONSTANTS_OS_CPU macro (and must */ - /* be present there) */ +#define VM_LONG_CONSTANTS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) #endif // CPU_ZERO_VM_VMSTRUCTS_ZERO_HPP diff --git a/hotspot/src/os_cpu/bsd_x86/vm/vmStructs_bsd_x86.hpp b/hotspot/src/os_cpu/bsd_x86/vm/vmStructs_bsd_x86.hpp index b98d975408a..edfbcfa9a54 100644 --- a/hotspot/src/os_cpu/bsd_x86/vm/vmStructs_bsd_x86.hpp +++ b/hotspot/src/os_cpu/bsd_x86/vm/vmStructs_bsd_x86.hpp @@ -29,37 +29,26 @@ // constants required by the Serviceability Agent. This file is // referenced by vmStructs.cpp. -#define VM_STRUCTS_OS_CPU(nonstatic_field, static_field, unchecked_nonstatic_field, volatile_nonstatic_field, nonproduct_nonstatic_field, c2_nonstatic_field, unchecked_c1_static_field, unchecked_c2_static_field, last_entry) \ +#define VM_STRUCTS_OS_CPU(nonstatic_field, static_field, unchecked_nonstatic_field, volatile_nonstatic_field, nonproduct_nonstatic_field, c2_nonstatic_field, unchecked_c1_static_field, unchecked_c2_static_field) \ \ /******************************/ \ /* Threads (NOTE: incomplete) */ \ /******************************/ \ nonstatic_field(OSThread, _thread_id, OSThread::thread_id_t) \ - nonstatic_field(OSThread, _pthread_id, pthread_t) \ - /* This must be the last entry, and must be present */ \ - last_entry() + nonstatic_field(OSThread, _pthread_id, pthread_t) -#define VM_TYPES_OS_CPU(declare_type, declare_toplevel_type, declare_oop_type, declare_integer_type, declare_unsigned_integer_type, declare_c1_toplevel_type, declare_c2_type, declare_c2_toplevel_type, last_entry) \ +#define VM_TYPES_OS_CPU(declare_type, declare_toplevel_type, declare_oop_type, declare_integer_type, declare_unsigned_integer_type, declare_c1_toplevel_type, declare_c2_type, declare_c2_toplevel_type) \ \ /**********************/ \ /* Posix Thread IDs */ \ /**********************/ \ \ declare_unsigned_integer_type(OSThread::thread_id_t) \ - declare_unsigned_integer_type(pthread_t) \ - \ - /* This must be the last entry, and must be present */ \ - last_entry() + declare_unsigned_integer_type(pthread_t) -#define VM_INT_CONSTANTS_OS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant, last_entry) \ - \ - /* This must be the last entry, and must be present */ \ - last_entry() +#define VM_INT_CONSTANTS_OS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) -#define VM_LONG_CONSTANTS_OS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant, last_entry) \ - \ - /* This must be the last entry, and must be present */ \ - last_entry() +#define VM_LONG_CONSTANTS_OS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) #endif // OS_CPU_BSD_X86_VM_VMSTRUCTS_BSD_X86_HPP diff --git a/hotspot/src/os_cpu/bsd_zero/vm/vmStructs_bsd_zero.hpp b/hotspot/src/os_cpu/bsd_zero/vm/vmStructs_bsd_zero.hpp index 17165cc9d13..6673f448f81 100644 --- a/hotspot/src/os_cpu/bsd_zero/vm/vmStructs_bsd_zero.hpp +++ b/hotspot/src/os_cpu/bsd_zero/vm/vmStructs_bsd_zero.hpp @@ -30,21 +30,13 @@ // constants required by the Serviceability Agent. This file is // referenced by vmStructs.cpp. -#define VM_STRUCTS_OS_CPU(nonstatic_field, static_field, unchecked_nonstatic_field, volatile_nonstatic_field, nonproduct_nonstatic_field, c2_nonstatic_field, unchecked_c1_static_field, unchecked_c2_static_field, last_entry) \ - /* This must be the last entry, and must be present */ \ - last_entry() +#define VM_STRUCTS_OS_CPU(nonstatic_field, static_field, unchecked_nonstatic_field, volatile_nonstatic_field, nonproduct_nonstatic_field, c2_nonstatic_field, unchecked_c1_static_field, unchecked_c2_static_field) -#define VM_TYPES_OS_CPU(declare_type, declare_toplevel_type, declare_oop_type, declare_integer_type, declare_unsigned_integer_type, declare_c1_toplevel_type, declare_c2_type, declare_c2_toplevel_type, last_entry) \ - /* This must be the last entry, and must be present */ \ - last_entry() +#define VM_TYPES_OS_CPU(declare_type, declare_toplevel_type, declare_oop_type, declare_integer_type, declare_unsigned_integer_type, declare_c1_toplevel_type, declare_c2_type, declare_c2_toplevel_type) -#define VM_INT_CONSTANTS_OS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant, last_entry) \ - /* This must be the last entry, and must be present */ \ - last_entry() +#define VM_INT_CONSTANTS_OS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) -#define VM_LONG_CONSTANTS_OS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant, last_entry) \ - /* This must be the last entry, and must be present */ \ - last_entry() +#define VM_LONG_CONSTANTS_OS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) #endif // OS_CPU_BSD_ZERO_VM_VMSTRUCTS_BSD_ZERO_HPP diff --git a/hotspot/src/os_cpu/linux_sparc/vm/vmStructs_linux_sparc.hpp b/hotspot/src/os_cpu/linux_sparc/vm/vmStructs_linux_sparc.hpp index 58fc94bbc38..38bc63e6496 100644 --- a/hotspot/src/os_cpu/linux_sparc/vm/vmStructs_linux_sparc.hpp +++ b/hotspot/src/os_cpu/linux_sparc/vm/vmStructs_linux_sparc.hpp @@ -29,7 +29,7 @@ // constants required by the Serviceability Agent. This file is // referenced by vmStructs.cpp. -#define VM_STRUCTS_OS_CPU(nonstatic_field, static_field, unchecked_nonstatic_field, volatile_nonstatic_field, nonproduct_nonstatic_field, c2_nonstatic_field, unchecked_c1_static_field, unchecked_c2_static_field, last_entry) \ +#define VM_STRUCTS_OS_CPU(nonstatic_field, static_field, unchecked_nonstatic_field, volatile_nonstatic_field, nonproduct_nonstatic_field, c2_nonstatic_field, unchecked_c1_static_field, unchecked_c2_static_field) \ \ /******************************/ \ /* Threads (NOTE: incomplete) */ \ @@ -37,38 +37,27 @@ \ nonstatic_field(JavaThread, _base_of_stack_pointer, intptr_t*) \ nonstatic_field(OSThread, _thread_id, OSThread::thread_id_t) \ - nonstatic_field(OSThread, _pthread_id, pthread_t) \ - /* This must be the last entry, and must be present */ \ - last_entry() + nonstatic_field(OSThread, _pthread_id, pthread_t) -#define VM_TYPES_OS_CPU(declare_type, declare_toplevel_type, declare_oop_type, declare_integer_type, declare_unsigned_integer_type, declare_c1_toplevel_type, declare_c2_type, declare_c2_toplevel_type, last_entry) \ +#define VM_TYPES_OS_CPU(declare_type, declare_toplevel_type, declare_oop_type, declare_integer_type, declare_unsigned_integer_type, declare_c1_toplevel_type, declare_c2_type, declare_c2_toplevel_type) \ \ /**********************/ \ /* POSIX Thread IDs */ \ /**********************/ \ \ declare_integer_type(OSThread::thread_id_t) \ - declare_unsigned_integer_type(pthread_t) \ - \ - /* This must be the last entry, and must be present */ \ - last_entry() + declare_unsigned_integer_type(pthread_t) -#define VM_INT_CONSTANTS_OS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant, last_entry) \ +#define VM_INT_CONSTANTS_OS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) \ \ /************************/ \ /* JavaThread constants */ \ /************************/ \ \ - declare_constant(JavaFrameAnchor::flushed) \ - \ - /* This must be the last entry, and must be present */ \ - last_entry() + declare_constant(JavaFrameAnchor::flushed) -#define VM_LONG_CONSTANTS_OS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant, last_entry) \ - \ - /* This must be the last entry, and must be present */ \ - last_entry() +#define VM_LONG_CONSTANTS_OS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) #endif // OS_CPU_LINUX_SPARC_VM_VMSTRUCTS_LINUX_SPARC_HPP diff --git a/hotspot/src/os_cpu/linux_x86/vm/vmStructs_linux_x86.hpp b/hotspot/src/os_cpu/linux_x86/vm/vmStructs_linux_x86.hpp index c01e6c91c2a..828f992d8ba 100644 --- a/hotspot/src/os_cpu/linux_x86/vm/vmStructs_linux_x86.hpp +++ b/hotspot/src/os_cpu/linux_x86/vm/vmStructs_linux_x86.hpp @@ -29,37 +29,26 @@ // constants required by the Serviceability Agent. This file is // referenced by vmStructs.cpp. -#define VM_STRUCTS_OS_CPU(nonstatic_field, static_field, unchecked_nonstatic_field, volatile_nonstatic_field, nonproduct_nonstatic_field, c2_nonstatic_field, unchecked_c1_static_field, unchecked_c2_static_field, last_entry) \ +#define VM_STRUCTS_OS_CPU(nonstatic_field, static_field, unchecked_nonstatic_field, volatile_nonstatic_field, nonproduct_nonstatic_field, c2_nonstatic_field, unchecked_c1_static_field, unchecked_c2_static_field) \ \ /******************************/ \ /* Threads (NOTE: incomplete) */ \ /******************************/ \ nonstatic_field(OSThread, _thread_id, OSThread::thread_id_t) \ - nonstatic_field(OSThread, _pthread_id, pthread_t) \ - /* This must be the last entry, and must be present */ \ - last_entry() + nonstatic_field(OSThread, _pthread_id, pthread_t) -#define VM_TYPES_OS_CPU(declare_type, declare_toplevel_type, declare_oop_type, declare_integer_type, declare_unsigned_integer_type, declare_c1_toplevel_type, declare_c2_type, declare_c2_toplevel_type, last_entry) \ +#define VM_TYPES_OS_CPU(declare_type, declare_toplevel_type, declare_oop_type, declare_integer_type, declare_unsigned_integer_type, declare_c1_toplevel_type, declare_c2_type, declare_c2_toplevel_type) \ \ /**********************/ \ /* Posix Thread IDs */ \ /**********************/ \ \ declare_integer_type(OSThread::thread_id_t) \ - declare_unsigned_integer_type(pthread_t) \ - \ - /* This must be the last entry, and must be present */ \ - last_entry() + declare_unsigned_integer_type(pthread_t) -#define VM_INT_CONSTANTS_OS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant, last_entry) \ - \ - /* This must be the last entry, and must be present */ \ - last_entry() +#define VM_INT_CONSTANTS_OS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) -#define VM_LONG_CONSTANTS_OS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant, last_entry) \ - \ - /* This must be the last entry, and must be present */ \ - last_entry() +#define VM_LONG_CONSTANTS_OS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) #endif // OS_CPU_LINUX_X86_VM_VMSTRUCTS_LINUX_X86_HPP diff --git a/hotspot/src/os_cpu/linux_zero/vm/vmStructs_linux_zero.hpp b/hotspot/src/os_cpu/linux_zero/vm/vmStructs_linux_zero.hpp index 46c7912c372..34b82a96d79 100644 --- a/hotspot/src/os_cpu/linux_zero/vm/vmStructs_linux_zero.hpp +++ b/hotspot/src/os_cpu/linux_zero/vm/vmStructs_linux_zero.hpp @@ -30,21 +30,12 @@ // constants required by the Serviceability Agent. This file is // referenced by vmStructs.cpp. -#define VM_STRUCTS_OS_CPU(nonstatic_field, static_field, unchecked_nonstatic_field, volatile_nonstatic_field, nonproduct_nonstatic_field, c2_nonstatic_field, unchecked_c1_static_field, unchecked_c2_static_field, last_entry) \ - /* This must be the last entry, and must be present */ \ - last_entry() +#define VM_STRUCTS_OS_CPU(nonstatic_field, static_field, unchecked_nonstatic_field, volatile_nonstatic_field, nonproduct_nonstatic_field, c2_nonstatic_field, unchecked_c1_static_field, unchecked_c2_static_field) +#define VM_TYPES_OS_CPU(declare_type, declare_toplevel_type, declare_oop_type, declare_integer_type, declare_unsigned_integer_type, declare_c1_toplevel_type, declare_c2_type, declare_c2_toplevel_type) -#define VM_TYPES_OS_CPU(declare_type, declare_toplevel_type, declare_oop_type, declare_integer_type, declare_unsigned_integer_type, declare_c1_toplevel_type, declare_c2_type, declare_c2_toplevel_type, last_entry) \ - /* This must be the last entry, and must be present */ \ - last_entry() +#define VM_INT_CONSTANTS_OS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) -#define VM_INT_CONSTANTS_OS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant, last_entry) \ - /* This must be the last entry, and must be present */ \ - last_entry() - -#define VM_LONG_CONSTANTS_OS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant, last_entry) \ - /* This must be the last entry, and must be present */ \ - last_entry() +#define VM_LONG_CONSTANTS_OS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) #endif // OS_CPU_LINUX_ZERO_VM_VMSTRUCTS_LINUX_ZERO_HPP diff --git a/hotspot/src/os_cpu/solaris_sparc/vm/vmStructs_solaris_sparc.hpp b/hotspot/src/os_cpu/solaris_sparc/vm/vmStructs_solaris_sparc.hpp index 58113a9ea49..40d6ae735aa 100644 --- a/hotspot/src/os_cpu/solaris_sparc/vm/vmStructs_solaris_sparc.hpp +++ b/hotspot/src/os_cpu/solaris_sparc/vm/vmStructs_solaris_sparc.hpp @@ -29,44 +29,32 @@ // constants required by the Serviceability Agent. This file is // referenced by vmStructs.cpp. -#define VM_STRUCTS_OS_CPU(nonstatic_field, static_field, unchecked_nonstatic_field, volatile_nonstatic_field, nonproduct_nonstatic_field, c2_nonstatic_field, unchecked_c1_static_field, unchecked_c2_static_field, last_entry) \ +#define VM_STRUCTS_OS_CPU(nonstatic_field, static_field, unchecked_nonstatic_field, volatile_nonstatic_field, nonproduct_nonstatic_field, c2_nonstatic_field, unchecked_c1_static_field, unchecked_c2_static_field) \ \ /******************************/ \ /* Threads (NOTE: incomplete) */ \ /******************************/ \ \ nonstatic_field(JavaThread, _base_of_stack_pointer, intptr_t*) \ - nonstatic_field(OSThread, _thread_id, OSThread::thread_id_t) \ - /* This must be the last entry, and must be present */ \ - last_entry() + nonstatic_field(OSThread, _thread_id, OSThread::thread_id_t) - -#define VM_TYPES_OS_CPU(declare_type, declare_toplevel_type, declare_oop_type, declare_integer_type, declare_unsigned_integer_type, declare_c1_toplevel_type, declare_c2_type, declare_c2_toplevel_type, last_entry) \ +#define VM_TYPES_OS_CPU(declare_type, declare_toplevel_type, declare_oop_type, declare_integer_type, declare_unsigned_integer_type, declare_c1_toplevel_type, declare_c2_type, declare_c2_toplevel_type) \ \ /**********************/ \ /* Solaris Thread IDs */ \ /**********************/ \ \ - declare_unsigned_integer_type(OSThread::thread_id_t) \ - \ - /* This must be the last entry, and must be present */ \ - last_entry() + declare_unsigned_integer_type(OSThread::thread_id_t) -#define VM_INT_CONSTANTS_OS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant, last_entry) \ +#define VM_INT_CONSTANTS_OS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) \ \ /************************/ \ /* JavaThread constants */ \ /************************/ \ \ - declare_constant(JavaFrameAnchor::flushed) \ - \ - /* This must be the last entry, and must be present */ \ - last_entry() + declare_constant(JavaFrameAnchor::flushed) -#define VM_LONG_CONSTANTS_OS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant, last_entry) \ - \ - /* This must be the last entry, and must be present */ \ - last_entry() +#define VM_LONG_CONSTANTS_OS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) #endif // OS_CPU_SOLARIS_SPARC_VM_VMSTRUCTS_SOLARIS_SPARC_HPP diff --git a/hotspot/src/os_cpu/solaris_x86/vm/vmStructs_solaris_x86.hpp b/hotspot/src/os_cpu/solaris_x86/vm/vmStructs_solaris_x86.hpp index a2a4f7c60b7..523fdc7cc42 100644 --- a/hotspot/src/os_cpu/solaris_x86/vm/vmStructs_solaris_x86.hpp +++ b/hotspot/src/os_cpu/solaris_x86/vm/vmStructs_solaris_x86.hpp @@ -29,36 +29,24 @@ // constants required by the Serviceability Agent. This file is // referenced by vmStructs.cpp. -#define VM_STRUCTS_OS_CPU(nonstatic_field, static_field, unchecked_nonstatic_field, volatile_nonstatic_field, nonproduct_nonstatic_field, c2_nonstatic_field, unchecked_c1_static_field, unchecked_c2_static_field, last_entry) \ +#define VM_STRUCTS_OS_CPU(nonstatic_field, static_field, unchecked_nonstatic_field, volatile_nonstatic_field, nonproduct_nonstatic_field, c2_nonstatic_field, unchecked_c1_static_field, unchecked_c2_static_field) \ \ /******************************/ \ /* Threads (NOTE: incomplete) */ \ /******************************/ \ \ - nonstatic_field(OSThread, _thread_id, OSThread::thread_id_t) \ - \ - /* This must be the last entry, and must be present */ \ - last_entry() + nonstatic_field(OSThread, _thread_id, OSThread::thread_id_t) -#define VM_TYPES_OS_CPU(declare_type, declare_toplevel_type, declare_oop_type, declare_integer_type, declare_unsigned_integer_type, declare_c1_toplevel_type, declare_c2_type, declare_c2_toplevel_type, last_entry) \ +#define VM_TYPES_OS_CPU(declare_type, declare_toplevel_type, declare_oop_type, declare_integer_type, declare_unsigned_integer_type, declare_c1_toplevel_type, declare_c2_type, declare_c2_toplevel_type) \ \ /**********************/ \ /* Solaris Thread IDs */ \ /**********************/ \ \ - declare_unsigned_integer_type(OSThread::thread_id_t) \ - \ - /* This must be the last entry, and must be present */ \ - last_entry() + declare_unsigned_integer_type(OSThread::thread_id_t) -#define VM_INT_CONSTANTS_OS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant, last_entry) \ - \ - /* This must be the last entry, and must be present */ \ - last_entry() +#define VM_INT_CONSTANTS_OS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) -#define VM_LONG_CONSTANTS_OS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant, last_entry) \ - \ - /* This must be the last entry, and must be present */ \ - last_entry() +#define VM_LONG_CONSTANTS_OS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) #endif // OS_CPU_SOLARIS_X86_VM_VMSTRUCTS_SOLARIS_X86_HPP diff --git a/hotspot/src/os_cpu/windows_x86/vm/vmStructs_windows_x86.hpp b/hotspot/src/os_cpu/windows_x86/vm/vmStructs_windows_x86.hpp index 69d25c93186..a392b63632c 100644 --- a/hotspot/src/os_cpu/windows_x86/vm/vmStructs_windows_x86.hpp +++ b/hotspot/src/os_cpu/windows_x86/vm/vmStructs_windows_x86.hpp @@ -29,32 +29,21 @@ // constants required by the Serviceability Agent. This file is // referenced by vmStructs.cpp. -#define VM_STRUCTS_OS_CPU(nonstatic_field, static_field, unchecked_nonstatic_field, volatile_nonstatic_field, nonproduct_nonstatic_field, c2_nonstatic_field, unchecked_c1_static_field, unchecked_c2_static_field, last_entry) \ +#define VM_STRUCTS_OS_CPU(nonstatic_field, static_field, unchecked_nonstatic_field, volatile_nonstatic_field, nonproduct_nonstatic_field, c2_nonstatic_field, unchecked_c1_static_field, unchecked_c2_static_field) \ \ /******************************/ \ /* Threads (NOTE: incomplete) */ \ /******************************/ \ \ nonstatic_field(OSThread, _thread_id, OSThread::thread_id_t) \ - unchecked_nonstatic_field(OSThread, _thread_handle, sizeof(HANDLE)) /* NOTE: no type */ \ - \ - /* This must be the last entry, and must be present */ \ - last_entry() + unchecked_nonstatic_field(OSThread, _thread_handle, sizeof(HANDLE)) /* NOTE: no type */ -#define VM_TYPES_OS_CPU(declare_type, declare_toplevel_type, declare_oop_type, declare_integer_type, declare_unsigned_integer_type, declare_c1_toplevel_type, declare_c2_type, declare_c2_toplevel_type, last_entry) \ +#define VM_TYPES_OS_CPU(declare_type, declare_toplevel_type, declare_oop_type, declare_integer_type, declare_unsigned_integer_type, declare_c1_toplevel_type, declare_c2_type, declare_c2_toplevel_type) \ \ - declare_unsigned_integer_type(OSThread::thread_id_t) \ - /* This must be the last entry, and must be present */ \ - last_entry() + declare_unsigned_integer_type(OSThread::thread_id_t) -#define VM_INT_CONSTANTS_OS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant, last_entry) \ - \ - /* This must be the last entry, and must be present */ \ - last_entry() +#define VM_INT_CONSTANTS_OS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) -#define VM_LONG_CONSTANTS_OS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant, last_entry) \ - \ - /* This must be the last entry, and must be present */ \ - last_entry() +#define VM_LONG_CONSTANTS_OS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) #endif // OS_CPU_WINDOWS_X86_VM_VMSTRUCTS_WINDOWS_X86_HPP diff --git a/hotspot/src/share/vm/runtime/vmStructs.cpp b/hotspot/src/share/vm/runtime/vmStructs.cpp index 9ac10e26d4c..958298bf994 100644 --- a/hotspot/src/share/vm/runtime/vmStructs.cpp +++ b/hotspot/src/share/vm/runtime/vmStructs.cpp @@ -257,8 +257,7 @@ typedef BinaryTreeDictionary MetablockTreeDictionary; c1_nonstatic_field, \ c2_nonstatic_field, \ unchecked_c1_static_field, \ - unchecked_c2_static_field, \ - last_entry) \ + unchecked_c2_static_field) \ \ /******************************************************************/ \ /* OopDesc and Klass hierarchies (NOTE: MethodData* incomplete) */ \ @@ -1238,9 +1237,6 @@ typedef BinaryTreeDictionary MetablockTreeDictionary; nonstatic_field(FreeList, _count, ssize_t) \ nonstatic_field(MetablockTreeDictionary, _total_size, size_t) - /* NOTE that we do not use the last_entry() macro here; it is used */ - /* in vmStructs__.hpp's VM_STRUCTS_OS_CPU macro (and must */ - /* be present there) */ //-------------------------------------------------------------------------------- // VM_TYPES @@ -1280,8 +1276,7 @@ typedef BinaryTreeDictionary MetablockTreeDictionary; declare_unsigned_integer_type, \ declare_c1_toplevel_type, \ declare_c2_type, \ - declare_c2_toplevel_type, \ - last_entry) \ + declare_c2_toplevel_type) \ \ /*************************************************************/ \ /* Java primitive types -- required by the SA implementation */ \ @@ -2098,10 +2093,6 @@ typedef BinaryTreeDictionary MetablockTreeDictionary; declare_type(MetablockTreeDictionary, FreeBlockDictionary) - /* NOTE that we do not use the last_entry() macro here; it is used */ - /* in vmStructs__.hpp's VM_TYPES_OS_CPU macro (and must be */ - /* present there) */ - //-------------------------------------------------------------------------------- // VM_INT_CONSTANTS // @@ -2114,8 +2105,7 @@ typedef BinaryTreeDictionary MetablockTreeDictionary; declare_preprocessor_constant, \ declare_c1_constant, \ declare_c2_constant, \ - declare_c2_preprocessor_constant, \ - last_entry) \ + declare_c2_preprocessor_constant) \ \ /******************/ \ /* Useful globals */ \ @@ -2483,9 +2473,6 @@ typedef BinaryTreeDictionary MetablockTreeDictionary; declare_c2_preprocessor_constant("SAVED_ON_ENTRY_REG_COUNT", SAVED_ON_ENTRY_REG_COUNT) \ declare_c2_preprocessor_constant("C_SAVED_ON_ENTRY_REG_COUNT", C_SAVED_ON_ENTRY_REG_COUNT) - /* NOTE that we do not use the last_entry() macro here; it is used */ - /* in vmStructs__.hpp's VM_INT_CONSTANTS_OS_CPU macro (and */ - /* must be present there) */ //-------------------------------------------------------------------------------- // VM_LONG_CONSTANTS @@ -2495,7 +2482,7 @@ typedef BinaryTreeDictionary MetablockTreeDictionary; // enums, etc., while "declare_preprocessor_constant" must be used for // all #defined constants. -#define VM_LONG_CONSTANTS(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant, last_entry) \ +#define VM_LONG_CONSTANTS(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) \ \ /*********************/ \ /* MarkOop constants */ \ @@ -2541,11 +2528,7 @@ typedef BinaryTreeDictionary MetablockTreeDictionary; /* Constants in markOop used by CMS. */ \ declare_constant(markOopDesc::cms_shift) \ declare_constant(markOopDesc::cms_mask) \ - declare_constant(markOopDesc::size_shift) \ - - /* NOTE that we do not use the last_entry() macro here; it is used */ - /* in vmStructs__.hpp's VM_LONG_CONSTANTS_OS_CPU macro (and */ - /* must be present there) */ + declare_constant(markOopDesc::size_shift) //-------------------------------------------------------------------------------- @@ -2608,9 +2591,6 @@ typedef BinaryTreeDictionary MetablockTreeDictionary; // This is a no-op macro for unchecked fields #define CHECK_NO_OP(a, b, c) -// This is a no-op macro for the sentinel value -#define CHECK_SENTINEL() - // // Build-specific macros: // @@ -2789,48 +2769,47 @@ typedef BinaryTreeDictionary MetablockTreeDictionary; // as long as class VMStructs is a friend VMStructEntry VMStructs::localHotSpotVMStructs[] = { - VM_STRUCTS(GENERATE_NONSTATIC_VM_STRUCT_ENTRY, \ - GENERATE_STATIC_VM_STRUCT_ENTRY, \ - GENERATE_UNCHECKED_NONSTATIC_VM_STRUCT_ENTRY, \ - GENERATE_NONSTATIC_VM_STRUCT_ENTRY, \ - GENERATE_NONPRODUCT_NONSTATIC_VM_STRUCT_ENTRY, \ - GENERATE_C1_NONSTATIC_VM_STRUCT_ENTRY, \ - GENERATE_C2_NONSTATIC_VM_STRUCT_ENTRY, \ - GENERATE_C1_UNCHECKED_STATIC_VM_STRUCT_ENTRY, \ - GENERATE_C2_UNCHECKED_STATIC_VM_STRUCT_ENTRY, \ - GENERATE_VM_STRUCT_LAST_ENTRY) + VM_STRUCTS(GENERATE_NONSTATIC_VM_STRUCT_ENTRY, + GENERATE_STATIC_VM_STRUCT_ENTRY, + GENERATE_UNCHECKED_NONSTATIC_VM_STRUCT_ENTRY, + GENERATE_NONSTATIC_VM_STRUCT_ENTRY, + GENERATE_NONPRODUCT_NONSTATIC_VM_STRUCT_ENTRY, + GENERATE_C1_NONSTATIC_VM_STRUCT_ENTRY, + GENERATE_C2_NONSTATIC_VM_STRUCT_ENTRY, + GENERATE_C1_UNCHECKED_STATIC_VM_STRUCT_ENTRY, + GENERATE_C2_UNCHECKED_STATIC_VM_STRUCT_ENTRY) #ifndef SERIALGC - VM_STRUCTS_PARALLELGC(GENERATE_NONSTATIC_VM_STRUCT_ENTRY, \ + VM_STRUCTS_PARALLELGC(GENERATE_NONSTATIC_VM_STRUCT_ENTRY, GENERATE_STATIC_VM_STRUCT_ENTRY) - VM_STRUCTS_CMS(GENERATE_NONSTATIC_VM_STRUCT_ENTRY, \ - GENERATE_NONSTATIC_VM_STRUCT_ENTRY, \ + VM_STRUCTS_CMS(GENERATE_NONSTATIC_VM_STRUCT_ENTRY, + GENERATE_NONSTATIC_VM_STRUCT_ENTRY, GENERATE_STATIC_VM_STRUCT_ENTRY) - VM_STRUCTS_G1(GENERATE_NONSTATIC_VM_STRUCT_ENTRY, \ + VM_STRUCTS_G1(GENERATE_NONSTATIC_VM_STRUCT_ENTRY, GENERATE_STATIC_VM_STRUCT_ENTRY) #endif // SERIALGC - VM_STRUCTS_CPU(GENERATE_NONSTATIC_VM_STRUCT_ENTRY, \ - GENERATE_STATIC_VM_STRUCT_ENTRY, \ - GENERATE_UNCHECKED_NONSTATIC_VM_STRUCT_ENTRY, \ - GENERATE_NONSTATIC_VM_STRUCT_ENTRY, \ - GENERATE_NONPRODUCT_NONSTATIC_VM_STRUCT_ENTRY, \ - GENERATE_C2_NONSTATIC_VM_STRUCT_ENTRY, \ - GENERATE_C1_UNCHECKED_STATIC_VM_STRUCT_ENTRY, \ - GENERATE_C2_UNCHECKED_STATIC_VM_STRUCT_ENTRY, \ - GENERATE_VM_STRUCT_LAST_ENTRY) + VM_STRUCTS_CPU(GENERATE_NONSTATIC_VM_STRUCT_ENTRY, + GENERATE_STATIC_VM_STRUCT_ENTRY, + GENERATE_UNCHECKED_NONSTATIC_VM_STRUCT_ENTRY, + GENERATE_NONSTATIC_VM_STRUCT_ENTRY, + GENERATE_NONPRODUCT_NONSTATIC_VM_STRUCT_ENTRY, + GENERATE_C2_NONSTATIC_VM_STRUCT_ENTRY, + GENERATE_C1_UNCHECKED_STATIC_VM_STRUCT_ENTRY, + GENERATE_C2_UNCHECKED_STATIC_VM_STRUCT_ENTRY) - VM_STRUCTS_OS_CPU(GENERATE_NONSTATIC_VM_STRUCT_ENTRY, \ - GENERATE_STATIC_VM_STRUCT_ENTRY, \ - GENERATE_UNCHECKED_NONSTATIC_VM_STRUCT_ENTRY, \ - GENERATE_NONSTATIC_VM_STRUCT_ENTRY, \ - GENERATE_NONPRODUCT_NONSTATIC_VM_STRUCT_ENTRY, \ - GENERATE_C2_NONSTATIC_VM_STRUCT_ENTRY, \ - GENERATE_C1_UNCHECKED_STATIC_VM_STRUCT_ENTRY, \ - GENERATE_C2_UNCHECKED_STATIC_VM_STRUCT_ENTRY, \ - GENERATE_VM_STRUCT_LAST_ENTRY) + VM_STRUCTS_OS_CPU(GENERATE_NONSTATIC_VM_STRUCT_ENTRY, + GENERATE_STATIC_VM_STRUCT_ENTRY, + GENERATE_UNCHECKED_NONSTATIC_VM_STRUCT_ENTRY, + GENERATE_NONSTATIC_VM_STRUCT_ENTRY, + GENERATE_NONPRODUCT_NONSTATIC_VM_STRUCT_ENTRY, + GENERATE_C2_NONSTATIC_VM_STRUCT_ENTRY, + GENERATE_C1_UNCHECKED_STATIC_VM_STRUCT_ENTRY, + GENERATE_C2_UNCHECKED_STATIC_VM_STRUCT_ENTRY) + + GENERATE_VM_STRUCT_LAST_ENTRY() }; VMTypeEntry VMStructs::localHotSpotVMTypes[] = { @@ -2842,8 +2821,7 @@ VMTypeEntry VMStructs::localHotSpotVMTypes[] = { GENERATE_UNSIGNED_INTEGER_VM_TYPE_ENTRY, GENERATE_C1_TOPLEVEL_VM_TYPE_ENTRY, GENERATE_C2_VM_TYPE_ENTRY, - GENERATE_C2_TOPLEVEL_VM_TYPE_ENTRY, - GENERATE_VM_TYPE_LAST_ENTRY) + GENERATE_C2_TOPLEVEL_VM_TYPE_ENTRY) #ifndef SERIALGC VM_TYPES_PARALLELGC(GENERATE_VM_TYPE_ENTRY, @@ -2865,8 +2843,7 @@ VMTypeEntry VMStructs::localHotSpotVMTypes[] = { GENERATE_UNSIGNED_INTEGER_VM_TYPE_ENTRY, GENERATE_C1_TOPLEVEL_VM_TYPE_ENTRY, GENERATE_C2_VM_TYPE_ENTRY, - GENERATE_C2_TOPLEVEL_VM_TYPE_ENTRY, - GENERATE_VM_TYPE_LAST_ENTRY) + GENERATE_C2_TOPLEVEL_VM_TYPE_ENTRY) VM_TYPES_OS_CPU(GENERATE_VM_TYPE_ENTRY, GENERATE_TOPLEVEL_VM_TYPE_ENTRY, @@ -2875,8 +2852,9 @@ VMTypeEntry VMStructs::localHotSpotVMTypes[] = { GENERATE_UNSIGNED_INTEGER_VM_TYPE_ENTRY, GENERATE_C1_TOPLEVEL_VM_TYPE_ENTRY, GENERATE_C2_VM_TYPE_ENTRY, - GENERATE_C2_TOPLEVEL_VM_TYPE_ENTRY, - GENERATE_VM_TYPE_LAST_ENTRY) + GENERATE_C2_TOPLEVEL_VM_TYPE_ENTRY) + + GENERATE_VM_TYPE_LAST_ENTRY() }; VMIntConstantEntry VMStructs::localHotSpotVMIntConstants[] = { @@ -2885,8 +2863,7 @@ VMIntConstantEntry VMStructs::localHotSpotVMIntConstants[] = { GENERATE_PREPROCESSOR_VM_INT_CONSTANT_ENTRY, GENERATE_C1_VM_INT_CONSTANT_ENTRY, GENERATE_C2_VM_INT_CONSTANT_ENTRY, - GENERATE_C2_PREPROCESSOR_VM_INT_CONSTANT_ENTRY, - GENERATE_VM_INT_CONSTANT_LAST_ENTRY) + GENERATE_C2_PREPROCESSOR_VM_INT_CONSTANT_ENTRY) #ifndef SERIALGC VM_INT_CONSTANTS_CMS(GENERATE_VM_INT_CONSTANT_ENTRY) @@ -2898,15 +2875,15 @@ VMIntConstantEntry VMStructs::localHotSpotVMIntConstants[] = { GENERATE_PREPROCESSOR_VM_INT_CONSTANT_ENTRY, GENERATE_C1_VM_INT_CONSTANT_ENTRY, GENERATE_C2_VM_INT_CONSTANT_ENTRY, - GENERATE_C2_PREPROCESSOR_VM_INT_CONSTANT_ENTRY, - GENERATE_VM_INT_CONSTANT_LAST_ENTRY) + GENERATE_C2_PREPROCESSOR_VM_INT_CONSTANT_ENTRY) VM_INT_CONSTANTS_OS_CPU(GENERATE_VM_INT_CONSTANT_ENTRY, GENERATE_PREPROCESSOR_VM_INT_CONSTANT_ENTRY, GENERATE_C1_VM_INT_CONSTANT_ENTRY, GENERATE_C2_VM_INT_CONSTANT_ENTRY, - GENERATE_C2_PREPROCESSOR_VM_INT_CONSTANT_ENTRY, - GENERATE_VM_INT_CONSTANT_LAST_ENTRY) + GENERATE_C2_PREPROCESSOR_VM_INT_CONSTANT_ENTRY) + + GENERATE_VM_INT_CONSTANT_LAST_ENTRY() }; VMLongConstantEntry VMStructs::localHotSpotVMLongConstants[] = { @@ -2915,22 +2892,21 @@ VMLongConstantEntry VMStructs::localHotSpotVMLongConstants[] = { GENERATE_PREPROCESSOR_VM_LONG_CONSTANT_ENTRY, GENERATE_C1_VM_LONG_CONSTANT_ENTRY, GENERATE_C2_VM_LONG_CONSTANT_ENTRY, - GENERATE_C2_PREPROCESSOR_VM_LONG_CONSTANT_ENTRY, - GENERATE_VM_LONG_CONSTANT_LAST_ENTRY) + GENERATE_C2_PREPROCESSOR_VM_LONG_CONSTANT_ENTRY) VM_LONG_CONSTANTS_CPU(GENERATE_VM_LONG_CONSTANT_ENTRY, GENERATE_PREPROCESSOR_VM_LONG_CONSTANT_ENTRY, GENERATE_C1_VM_LONG_CONSTANT_ENTRY, GENERATE_C2_VM_LONG_CONSTANT_ENTRY, - GENERATE_C2_PREPROCESSOR_VM_LONG_CONSTANT_ENTRY, - GENERATE_VM_LONG_CONSTANT_LAST_ENTRY) + GENERATE_C2_PREPROCESSOR_VM_LONG_CONSTANT_ENTRY) VM_LONG_CONSTANTS_OS_CPU(GENERATE_VM_LONG_CONSTANT_ENTRY, GENERATE_PREPROCESSOR_VM_LONG_CONSTANT_ENTRY, GENERATE_C1_VM_LONG_CONSTANT_ENTRY, GENERATE_C2_VM_LONG_CONSTANT_ENTRY, - GENERATE_C2_PREPROCESSOR_VM_LONG_CONSTANT_ENTRY, - GENERATE_VM_LONG_CONSTANT_LAST_ENTRY) + GENERATE_C2_PREPROCESSOR_VM_LONG_CONSTANT_ENTRY) + + GENERATE_VM_LONG_CONSTANT_LAST_ENTRY() }; // This is used both to check the types of referenced fields and, in @@ -2945,8 +2921,7 @@ VMStructs::init() { CHECK_C1_NONSTATIC_VM_STRUCT_ENTRY, CHECK_C2_NONSTATIC_VM_STRUCT_ENTRY, CHECK_NO_OP, - CHECK_NO_OP, - CHECK_SENTINEL); + CHECK_NO_OP); #ifndef SERIALGC VM_STRUCTS_PARALLELGC(CHECK_NONSTATIC_VM_STRUCT_ENTRY, @@ -2967,8 +2942,7 @@ VMStructs::init() { CHECK_NONPRODUCT_NONSTATIC_VM_STRUCT_ENTRY, CHECK_C2_NONSTATIC_VM_STRUCT_ENTRY, CHECK_NO_OP, - CHECK_NO_OP, - CHECK_SENTINEL); + CHECK_NO_OP); VM_STRUCTS_OS_CPU(CHECK_NONSTATIC_VM_STRUCT_ENTRY, CHECK_STATIC_VM_STRUCT_ENTRY, @@ -2977,8 +2951,7 @@ VMStructs::init() { CHECK_NONPRODUCT_NONSTATIC_VM_STRUCT_ENTRY, CHECK_C2_NONSTATIC_VM_STRUCT_ENTRY, CHECK_NO_OP, - CHECK_NO_OP, - CHECK_SENTINEL); + CHECK_NO_OP); VM_TYPES(CHECK_VM_TYPE_ENTRY, CHECK_SINGLE_ARG_VM_TYPE_NO_OP, @@ -2987,8 +2960,7 @@ VMStructs::init() { CHECK_SINGLE_ARG_VM_TYPE_NO_OP, CHECK_C1_TOPLEVEL_VM_TYPE_ENTRY, CHECK_C2_VM_TYPE_ENTRY, - CHECK_C2_TOPLEVEL_VM_TYPE_ENTRY, - CHECK_SENTINEL); + CHECK_C2_TOPLEVEL_VM_TYPE_ENTRY); #ifndef SERIALGC VM_TYPES_PARALLELGC(CHECK_VM_TYPE_ENTRY, @@ -3010,8 +2982,7 @@ VMStructs::init() { CHECK_SINGLE_ARG_VM_TYPE_NO_OP, CHECK_C1_TOPLEVEL_VM_TYPE_ENTRY, CHECK_C2_VM_TYPE_ENTRY, - CHECK_C2_TOPLEVEL_VM_TYPE_ENTRY, - CHECK_SENTINEL); + CHECK_C2_TOPLEVEL_VM_TYPE_ENTRY); VM_TYPES_OS_CPU(CHECK_VM_TYPE_ENTRY, CHECK_SINGLE_ARG_VM_TYPE_NO_OP, @@ -3020,8 +2991,7 @@ VMStructs::init() { CHECK_SINGLE_ARG_VM_TYPE_NO_OP, CHECK_C1_TOPLEVEL_VM_TYPE_ENTRY, CHECK_C2_VM_TYPE_ENTRY, - CHECK_C2_TOPLEVEL_VM_TYPE_ENTRY, - CHECK_SENTINEL); + CHECK_C2_TOPLEVEL_VM_TYPE_ENTRY); // // Split VM_STRUCTS() invocation into two parts to allow MS VC++ 6.0 @@ -3040,53 +3010,49 @@ VMStructs::init() { // Solstice NFS setup. If everyone switches to local workspaces on // Win32, we can put this back in. #ifndef _WINDOWS - debug_only(VM_STRUCTS(ENSURE_FIELD_TYPE_PRESENT, \ - CHECK_NO_OP, \ - CHECK_NO_OP, \ - CHECK_NO_OP, \ - CHECK_NO_OP, \ - CHECK_NO_OP, \ - CHECK_NO_OP, \ - CHECK_NO_OP, \ - CHECK_NO_OP, \ - CHECK_SENTINEL)); - debug_only(VM_STRUCTS(CHECK_NO_OP, \ - ENSURE_FIELD_TYPE_PRESENT, \ - CHECK_NO_OP, \ - ENSURE_FIELD_TYPE_PRESENT, \ - ENSURE_NONPRODUCT_FIELD_TYPE_PRESENT, \ - ENSURE_C1_FIELD_TYPE_PRESENT, \ - ENSURE_C2_FIELD_TYPE_PRESENT, \ - CHECK_NO_OP, \ - CHECK_NO_OP, \ - CHECK_SENTINEL)); + debug_only(VM_STRUCTS(ENSURE_FIELD_TYPE_PRESENT, + CHECK_NO_OP, + CHECK_NO_OP, + CHECK_NO_OP, + CHECK_NO_OP, + CHECK_NO_OP, + CHECK_NO_OP, + CHECK_NO_OP, + CHECK_NO_OP)); + debug_only(VM_STRUCTS(CHECK_NO_OP, + ENSURE_FIELD_TYPE_PRESENT, + CHECK_NO_OP, + ENSURE_FIELD_TYPE_PRESENT, + ENSURE_NONPRODUCT_FIELD_TYPE_PRESENT, + ENSURE_C1_FIELD_TYPE_PRESENT, + ENSURE_C2_FIELD_TYPE_PRESENT, + CHECK_NO_OP, + CHECK_NO_OP)); #ifndef SERIALGC - debug_only(VM_STRUCTS_PARALLELGC(ENSURE_FIELD_TYPE_PRESENT, \ + debug_only(VM_STRUCTS_PARALLELGC(ENSURE_FIELD_TYPE_PRESENT, ENSURE_FIELD_TYPE_PRESENT)); - debug_only(VM_STRUCTS_CMS(ENSURE_FIELD_TYPE_PRESENT, \ - ENSURE_FIELD_TYPE_PRESENT, \ + debug_only(VM_STRUCTS_CMS(ENSURE_FIELD_TYPE_PRESENT, + ENSURE_FIELD_TYPE_PRESENT, ENSURE_FIELD_TYPE_PRESENT)); - debug_only(VM_STRUCTS_G1(ENSURE_FIELD_TYPE_PRESENT, \ + debug_only(VM_STRUCTS_G1(ENSURE_FIELD_TYPE_PRESENT, ENSURE_FIELD_TYPE_PRESENT)); #endif // SERIALGC - debug_only(VM_STRUCTS_CPU(ENSURE_FIELD_TYPE_PRESENT, \ - ENSURE_FIELD_TYPE_PRESENT, \ - CHECK_NO_OP, \ - ENSURE_FIELD_TYPE_PRESENT, \ - ENSURE_NONPRODUCT_FIELD_TYPE_PRESENT, \ - ENSURE_C2_FIELD_TYPE_PRESENT, \ - CHECK_NO_OP, \ - CHECK_NO_OP, \ - CHECK_SENTINEL)); - debug_only(VM_STRUCTS_OS_CPU(ENSURE_FIELD_TYPE_PRESENT, \ - ENSURE_FIELD_TYPE_PRESENT, \ - CHECK_NO_OP, \ - ENSURE_FIELD_TYPE_PRESENT, \ - ENSURE_NONPRODUCT_FIELD_TYPE_PRESENT, \ - ENSURE_C2_FIELD_TYPE_PRESENT, \ - CHECK_NO_OP, \ - CHECK_NO_OP, \ - CHECK_SENTINEL)); + debug_only(VM_STRUCTS_CPU(ENSURE_FIELD_TYPE_PRESENT, + ENSURE_FIELD_TYPE_PRESENT, + CHECK_NO_OP, + ENSURE_FIELD_TYPE_PRESENT, + ENSURE_NONPRODUCT_FIELD_TYPE_PRESENT, + ENSURE_C2_FIELD_TYPE_PRESENT, + CHECK_NO_OP, + CHECK_NO_OP)); + debug_only(VM_STRUCTS_OS_CPU(ENSURE_FIELD_TYPE_PRESENT, + ENSURE_FIELD_TYPE_PRESENT, + CHECK_NO_OP, + ENSURE_FIELD_TYPE_PRESENT, + ENSURE_NONPRODUCT_FIELD_TYPE_PRESENT, + ENSURE_C2_FIELD_TYPE_PRESENT, + CHECK_NO_OP, + CHECK_NO_OP)); #endif } @@ -3206,6 +3172,30 @@ void vmStructs_init() { #ifndef PRODUCT void VMStructs::test() { + // Make sure last entry in the each array is indeed the correct end marker. + // The reason why these are static is to make sure they are zero initialized. + // Putting them on the stack will leave some garbage in the padding of some fields. + static VMStructEntry struct_last_entry = GENERATE_VM_STRUCT_LAST_ENTRY(); + assert(memcmp(&localHotSpotVMStructs[(sizeof(localHotSpotVMStructs) / sizeof(VMStructEntry)) - 1], + &struct_last_entry, + sizeof(VMStructEntry)) == 0, "Incorrect last entry in localHotSpotVMStructs"); + + static VMTypeEntry type_last_entry = GENERATE_VM_TYPE_LAST_ENTRY(); + assert(memcmp(&localHotSpotVMTypes[sizeof(localHotSpotVMTypes) / sizeof(VMTypeEntry) - 1], + &type_last_entry, + sizeof(VMTypeEntry)) == 0, "Incorrect last entry in localHotSpotVMTypes"); + + static VMIntConstantEntry int_last_entry = GENERATE_VM_INT_CONSTANT_LAST_ENTRY(); + assert(memcmp(&localHotSpotVMIntConstants[sizeof(localHotSpotVMIntConstants) / sizeof(VMIntConstantEntry) - 1], + &int_last_entry, + sizeof(VMIntConstantEntry)) == 0, "Incorrect last entry in localHotSpotVMIntConstants"); + + static VMLongConstantEntry long_last_entry = GENERATE_VM_LONG_CONSTANT_LAST_ENTRY(); + assert(memcmp(&localHotSpotVMLongConstants[sizeof(localHotSpotVMLongConstants) / sizeof(VMLongConstantEntry) - 1], + &long_last_entry, + sizeof(VMLongConstantEntry)) == 0, "Incorrect last entry in localHotSpotVMLongConstants"); + + // Check for duplicate entries in type array for (int i = 0; localHotSpotVMTypes[i].typeName != NULL; i++) { for (int j = i + 1; localHotSpotVMTypes[j].typeName != NULL; j++) { From cac8a55fb2a9eb6c53253cd0daf0223977371f17 Mon Sep 17 00:00:00 2001 From: Jeremy Manson Date: Thu, 10 Jan 2013 21:00:11 -0500 Subject: [PATCH 006/210] 8005921: Memory leaks in vmStructs.cpp Reviewed-by: dholmes, mikael, rasbold --- hotspot/src/share/vm/runtime/vmStructs.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/hotspot/src/share/vm/runtime/vmStructs.cpp b/hotspot/src/share/vm/runtime/vmStructs.cpp index 958298bf994..09d557cdbf9 100644 --- a/hotspot/src/share/vm/runtime/vmStructs.cpp +++ b/hotspot/src/share/vm/runtime/vmStructs.cpp @@ -3112,10 +3112,10 @@ static int recursiveFindType(VMTypeEntry* origtypes, const char* typeName, bool s[len-1] = '\0'; // tty->print_cr("checking \"%s\" for \"%s\"", s, typeName); if (recursiveFindType(origtypes, s, true) == 1) { - delete s; + delete [] s; return 1; } - delete s; + delete [] s; } const char* start = NULL; if (strstr(typeName, "GrowableArray<") == typeName) { @@ -3131,10 +3131,10 @@ static int recursiveFindType(VMTypeEntry* origtypes, const char* typeName, bool s[len-1] = '\0'; // tty->print_cr("checking \"%s\" for \"%s\"", s, typeName); if (recursiveFindType(origtypes, s, true) == 1) { - delete s; + delete [] s; return 1; } - delete s; + delete [] s; } if (strstr(typeName, "const ") == typeName) { const char * s = typeName + strlen("const "); @@ -3148,8 +3148,10 @@ static int recursiveFindType(VMTypeEntry* origtypes, const char* typeName, bool s[len - 6] = '\0'; // tty->print_cr("checking \"%s\" for \"%s\"", s, typeName); if (recursiveFindType(origtypes, s, true) == 1) { + free(s); return 1; } + free(s); } if (!isRecurse) { tty->print_cr("type \"%s\" not found", typeName); From ce51b6ebee9ab3b0051243e8cb9be689b99f65a8 Mon Sep 17 00:00:00 2001 From: Jonathan Gibbons Date: Thu, 10 Jan 2013 19:36:13 -0800 Subject: [PATCH 007/210] 8004834: Add doclint support into javadoc Reviewed-by: erikj, tbell --- common/makefiles/javadoc/Javadoc.gmk | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/common/makefiles/javadoc/Javadoc.gmk b/common/makefiles/javadoc/Javadoc.gmk index 84f0b5f8494..2d919c05462 100644 --- a/common/makefiles/javadoc/Javadoc.gmk +++ b/common/makefiles/javadoc/Javadoc.gmk @@ -1,4 +1,4 @@ -# Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 1997, 2013, 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 @@ -271,6 +271,7 @@ COMMON_JAVADOCFLAGS = \ -quiet \ -use \ -keywords \ + -Xdoclint:none \ $(ADDITIONAL_JAVADOCFLAGS) ifdef OPENJDK From 7518dede81f02eeff80f686d7e5784935b5bc3fd Mon Sep 17 00:00:00 2001 From: Jonathan Gibbons Date: Thu, 10 Jan 2013 19:38:57 -0800 Subject: [PATCH 008/210] 8004834: Add doclint support into javadoc Reviewed-by: darcy --- .../formats/html/ConfigurationImpl.java | 47 +++- .../internal/toolkit/Configuration.java | 4 +- .../toolkit/resources/doclets.properties | 2 + .../toolkit/util/MessageRetriever.java | 11 +- .../com/sun/tools/javac/comp/Enter.java | 8 +- .../classes/com/sun/tools/javadoc/DocEnv.java | 43 ++- .../com/sun/tools/javadoc/DocImpl.java | 10 +- .../sun/tools/javadoc/JavadocMemberEnter.java | 6 +- .../com/sun/tools/javadoc/RootDocImpl.java | 13 +- .../com/sun/javadoc/5093723/T5093723.java | 2 +- .../testBadSourceFile/TestBadSourceFile.java | 4 +- .../TestHtmlDefinitionListTag.java | 10 +- .../TestNewLanguageFeatures.java | 4 +- .../javadoc/testReturnTag/TestReturnTag.java | 4 +- .../TestTagInheritence.java | 4 +- .../javadoc/testTagMisuse/TestTagMisuse.java | 4 +- .../javadoc/testValueTag/TestValueTag.java | 3 +- .../TestWarnBadParamNames.java | 4 +- .../javadoc/testWarnings/TestWarnings.java | 6 +- .../test/tools/javadoc/6958836/Test.java | 3 +- .../test/tools/javadoc/6964914/Test.java | 3 +- .../tools/javadoc/6964914/TestStdDoclet.java | 3 +- langtools/test/tools/javadoc/MaxWarns.java | 2 +- langtools/test/tools/javadoc/T6551367.java | 4 +- .../tools/javadoc/doclint/DocLintTest.java | 251 ++++++++++++++++++ 25 files changed, 401 insertions(+), 54 deletions(-) create mode 100644 langtools/test/tools/javadoc/doclint/DocLintTest.java diff --git a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/ConfigurationImpl.java b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/ConfigurationImpl.java index a6244a0335f..e74c73835d9 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/ConfigurationImpl.java +++ b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/ConfigurationImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2013, 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 @@ -33,8 +33,10 @@ import javax.tools.JavaFileManager; import com.sun.javadoc.*; import com.sun.tools.doclets.internal.toolkit.*; import com.sun.tools.doclets.internal.toolkit.util.*; +import com.sun.tools.doclint.DocLint; import com.sun.tools.javac.file.JavacFileManager; import com.sun.tools.javac.util.Context; +import com.sun.tools.javadoc.RootDocImpl; /** * Configure the output based on the command line options. @@ -171,6 +173,11 @@ public class ConfigurationImpl extends Configuration { */ public boolean createoverview = false; + /** + * Collected set of doclint options + */ + public Set doclintOpts = new LinkedHashSet(); + /** * Unique Resource Handler for this package. */ @@ -255,6 +262,10 @@ public class ConfigurationImpl extends Configuration { nooverview = true; } else if (opt.equals("-overview")) { overview = true; + } else if (opt.equals("-xdoclint")) { + doclintOpts.add(null); + } else if (opt.startsWith("-xdoclint:")) { + doclintOpts.add(opt.substring(opt.indexOf(":") + 1)); } } if (root.specifiedClasses().length > 0) { @@ -270,6 +281,10 @@ public class ConfigurationImpl extends Configuration { } setCreateOverview(); setTopFile(root); + + if (root instanceof RootDocImpl) { + ((RootDocImpl) root).initDocLint(doclintOpts); + } } /** @@ -303,7 +318,9 @@ public class ConfigurationImpl extends Configuration { option.equals("-serialwarn") || option.equals("-use") || option.equals("-nonavbar") || - option.equals("-nooverview")) { + option.equals("-nooverview") || + option.equals("-xdoclint") || + option.startsWith("-xdoclint:")) { return 1; } else if (option.equals("-help")) { System.out.println(getText("doclet.usage")); @@ -410,6 +427,16 @@ public class ConfigurationImpl extends Configuration { return false; } noindex = true; + } else if (opt.startsWith("-xdoclint:")) { + if (opt.contains("/")) { + reporter.printError(getText("doclet.Option_doclint_no_qualifiers")); + return false; + } + if (!DocLint.isValidOption( + opt.replace("-xdoclint:", DocLint.XMSGS_CUSTOM_PREFIX))) { + reporter.printError(getText("doclet.Option_doclint_invalid_arg")); + return false; + } } } return true; @@ -506,8 +533,8 @@ public class ConfigurationImpl extends Configuration { */ @Override public Locale getLocale() { - if (root instanceof com.sun.tools.javadoc.RootDocImpl) - return ((com.sun.tools.javadoc.RootDocImpl)root).getLocale(); + if (root instanceof RootDocImpl) + return ((RootDocImpl)root).getLocale(); else return Locale.getDefault(); } @@ -518,8 +545,8 @@ public class ConfigurationImpl extends Configuration { @Override public JavaFileManager getFileManager() { if (fileManager == null) { - if (root instanceof com.sun.tools.javadoc.RootDocImpl) - fileManager = ((com.sun.tools.javadoc.RootDocImpl)root).getFileManager(); + if (root instanceof RootDocImpl) + fileManager = ((RootDocImpl) root).getFileManager(); else fileManager = new JavacFileManager(new Context(), false, null); } @@ -527,4 +554,12 @@ public class ConfigurationImpl extends Configuration { } private JavaFileManager fileManager; + + @Override + public boolean showMessage(SourcePosition pos, String key) { + if (root instanceof RootDocImpl) { + return pos == null || ((RootDocImpl) root).showTagMessages(); + } + return true; + } } diff --git a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/Configuration.java b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/Configuration.java index 13099d24be9..2d869df9556 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/Configuration.java +++ b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/Configuration.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, 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 @@ -781,4 +781,6 @@ public abstract class Configuration { sourcetab = n; tabSpaces = String.format("%" + n + "s", ""); } + + public abstract boolean showMessage(SourcePosition pos, String key); } diff --git a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/resources/doclets.properties b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/resources/doclets.properties index f476b1b861f..93223311754 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/resources/doclets.properties +++ b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/resources/doclets.properties @@ -11,6 +11,8 @@ doclet.Class_0_implements_serializable=Class {0} implements Serializable doclet.Class_0_extends_implements_serializable=Class {0} extends {1} implements Serializable doclet.Option_conflict=Option {0} conflicts with {1} doclet.Option_reuse=Option reused: {0} +doclet.Option_doclint_no_qualifiers=Access qualifiers not permitted for -Xdoclint arguments +doclet.Option_doclint_invalid_arg=Invalid argument for -Xdoclint option doclet.exception_encountered= {0} encountered \n\ \twhile attempting to create file: {1} doclet.perform_copy_exception_encountered= {0} encountered while \n\ diff --git a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/util/MessageRetriever.java b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/util/MessageRetriever.java index d761cfebc69..75129c20a3e 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/util/MessageRetriever.java +++ b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/util/MessageRetriever.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2013, 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 @@ -60,9 +60,9 @@ public class MessageRetriever { private ResourceBundle messageRB; /** - * Initilize the ResourceBundle with the given resource. + * Initialize the ResourceBundle with the given resource. * - * @param rb the esource bundle to read. + * @param rb the resource bundle to read. */ public MessageRetriever(ResourceBundle rb) { this.configuration = null; @@ -71,7 +71,7 @@ public class MessageRetriever { } /** - * Initilize the ResourceBundle with the given resource. + * Initialize the ResourceBundle with the given resource. * * @param configuration the configuration * @param resourcelocation Resource. @@ -189,7 +189,8 @@ public class MessageRetriever { * @param args arguments to be replaced in the message. */ public void warning(SourcePosition pos, String key, Object... args) { - printWarning(pos, getText(key, args)); + if (configuration.showMessage(pos, key)) + printWarning(pos, getText(key, args)); } /** diff --git a/langtools/src/share/classes/com/sun/tools/javac/comp/Enter.java b/langtools/src/share/classes/com/sun/tools/javac/comp/Enter.java index ccf7a82badd..1165a151aa2 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/comp/Enter.java +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Enter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2013, 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 @@ -131,7 +131,11 @@ public class Enter extends JCTree.Visitor { predefClassDef = make.ClassDef( make.Modifiers(PUBLIC), - syms.predefClass.name, null, null, null, null); + syms.predefClass.name, + List.nil(), + null, + List.nil(), + List.nil()); predefClassDef.sym = syms.predefClass; todo = Todo.instance(context); fileManager = context.get(JavaFileManager.class); diff --git a/langtools/src/share/classes/com/sun/tools/javadoc/DocEnv.java b/langtools/src/share/classes/com/sun/tools/javadoc/DocEnv.java index ba08ae47eaa..0cac65c422a 100644 --- a/langtools/src/share/classes/com/sun/tools/javadoc/DocEnv.java +++ b/langtools/src/share/classes/com/sun/tools/javadoc/DocEnv.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2013, 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 @@ -31,8 +31,10 @@ import java.util.*; import javax.tools.JavaFileManager; import com.sun.javadoc.*; +import com.sun.source.util.JavacTask; import com.sun.source.util.TreePath; -import com.sun.tools.javac.api.JavacTrees; +import com.sun.tools.doclint.DocLint; +import com.sun.tools.javac.api.BasicJavacTask; import com.sun.tools.javac.code.*; import com.sun.tools.javac.code.Symbol.*; import com.sun.tools.javac.code.Type.ClassType; @@ -105,6 +107,7 @@ public class DocEnv { Types types; JavaFileManager fileManager; Context context; + DocLint doclint; WeakHashMap treePaths = new WeakHashMap(); @@ -400,6 +403,9 @@ public class DocEnv { public void warning(DocImpl doc, String key, String a1) { if (silent) return; + // suppress messages that have (probably) been covered by doclint + if (doclint != null && doc != null && key.startsWith("tag")) + return; messager.warning(doc==null ? null : doc.position(), key, a1); } @@ -732,9 +738,15 @@ public class DocEnv { return p; } - TreePath getTreePath(JCCompilationUnit toplevel, JCTree tree) { - // don't bother to cache paths for classes and members - return new TreePath(getTreePath(toplevel), tree); + TreePath getTreePath(JCCompilationUnit toplevel, JCClassDecl tree) { + TreePath p = treePaths.get(tree); + if (p == null) + treePaths.put(tree, p = new TreePath(getTreePath(toplevel), tree)); + return p; + } + + TreePath getTreePath(JCCompilationUnit toplevel, JCClassDecl cdecl, JCTree tree) { + return new TreePath(getTreePath(toplevel, cdecl), tree); } /** @@ -781,4 +793,25 @@ public class DocEnv { result |= Modifier.VOLATILE; return result; } + + void initDoclint(Collection opts) { + ArrayList doclintOpts = new ArrayList(); + + for (String opt: opts) { + doclintOpts.add(opt == null ? DocLint.XMSGS_OPTION : DocLint.XMSGS_CUSTOM_PREFIX + opt); + } + + if (doclintOpts.size() == 1 + && doclintOpts.get(0).equals(DocLint.XMSGS_CUSTOM_PREFIX + "none")) { + return; + } + + JavacTask t = BasicJavacTask.instance(context); + doclint = new DocLint(); + doclint.init(t, doclintOpts.toArray(new String[doclintOpts.size()]), false); + } + + boolean showTagMessages() { + return (doclint == null); + } } diff --git a/langtools/src/share/classes/com/sun/tools/javadoc/DocImpl.java b/langtools/src/share/classes/com/sun/tools/javadoc/DocImpl.java index 12451293c9a..e5b3f6c9980 100644 --- a/langtools/src/share/classes/com/sun/tools/javadoc/DocImpl.java +++ b/langtools/src/share/classes/com/sun/tools/javadoc/DocImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, 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 @@ -126,7 +126,13 @@ public abstract class DocImpl implements Doc, Comparable { */ Comment comment() { if (comment == null) { - comment = new Comment(this, documentation()); + String d = documentation(); + if (env.doclint != null + && treePath != null + && d.equals(getCommentText(treePath))) { + env.doclint.scan(treePath); + } + comment = new Comment(this, d); } return comment; } diff --git a/langtools/src/share/classes/com/sun/tools/javadoc/JavadocMemberEnter.java b/langtools/src/share/classes/com/sun/tools/javadoc/JavadocMemberEnter.java index 76e93a34367..058d173ebe7 100644 --- a/langtools/src/share/classes/com/sun/tools/javadoc/JavadocMemberEnter.java +++ b/langtools/src/share/classes/com/sun/tools/javadoc/JavadocMemberEnter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2013, 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 @@ -72,7 +72,7 @@ public class JavadocMemberEnter extends MemberEnter { super.visitMethodDef(tree); MethodSymbol meth = tree.sym; if (meth == null || meth.kind != Kinds.MTH) return; - TreePath treePath = docenv.getTreePath(env.toplevel, tree); + TreePath treePath = docenv.getTreePath(env.toplevel, env.enclClass, tree); if (meth.isConstructor()) docenv.makeConstructorDoc(meth, treePath); else if (isAnnotationTypeElement(meth)) @@ -90,7 +90,7 @@ public class JavadocMemberEnter extends MemberEnter { if (tree.sym != null && tree.sym.kind == Kinds.VAR && !isParameter(tree.sym)) { - docenv.makeFieldDoc(tree.sym, docenv.getTreePath(env.toplevel, tree)); + docenv.makeFieldDoc(tree.sym, docenv.getTreePath(env.toplevel, env.enclClass, tree)); } } diff --git a/langtools/src/share/classes/com/sun/tools/javadoc/RootDocImpl.java b/langtools/src/share/classes/com/sun/tools/javadoc/RootDocImpl.java index f662dd749db..89a086aa8f8 100644 --- a/langtools/src/share/classes/com/sun/tools/javadoc/RootDocImpl.java +++ b/langtools/src/share/classes/com/sun/tools/javadoc/RootDocImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, 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 @@ -26,13 +26,14 @@ package com.sun.tools.javadoc; import java.io.IOException; +import java.util.Collection; import java.util.Locale; + import javax.tools.JavaFileManager; import javax.tools.JavaFileObject; import javax.tools.StandardJavaFileManager; import com.sun.javadoc.*; - import com.sun.tools.javac.tree.JCTree.JCClassDecl; import com.sun.tools.javac.util.List; import com.sun.tools.javac.util.ListBuffer; @@ -375,4 +376,12 @@ public class RootDocImpl extends DocImpl implements RootDoc { public JavaFileManager getFileManager() { return env.fileManager; } + + public void initDocLint(Collection opts) { + env.initDoclint(opts); + } + + public boolean showTagMessages() { + return env.showTagMessages(); + } } diff --git a/langtools/test/com/sun/javadoc/5093723/T5093723.java b/langtools/test/com/sun/javadoc/5093723/T5093723.java index cab8c1d53d6..4fb3f90a821 100644 --- a/langtools/test/com/sun/javadoc/5093723/T5093723.java +++ b/langtools/test/com/sun/javadoc/5093723/T5093723.java @@ -36,7 +36,7 @@ public class T5093723 extends JavadocTester { private static final String BUG_ID = "5093723"; private static final String[] ARGS = new String[] { - "-d", BUG_ID + ".out", "-source", "5", + "-d", BUG_ID + ".out", "-source", "5", "-Xdoclint:none", SRC_DIR + "/DocumentedClass.java", SRC_DIR + "/UndocumentedClass.java" }; diff --git a/langtools/test/com/sun/javadoc/testBadSourceFile/TestBadSourceFile.java b/langtools/test/com/sun/javadoc/testBadSourceFile/TestBadSourceFile.java index 9f928543957..266aafdde1f 100644 --- a/langtools/test/com/sun/javadoc/testBadSourceFile/TestBadSourceFile.java +++ b/langtools/test/com/sun/javadoc/testBadSourceFile/TestBadSourceFile.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2013, 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 @@ -40,7 +40,7 @@ public class TestBadSourceFile extends JavadocTester { //Javadoc arguments. private static final String[] ARGS = new String[] { - "-d", BUG_ID, SRC_DIR + FS + "C2.java" + "-Xdoclint:none", "-d", BUG_ID, SRC_DIR + FS + "C2.java" }; //Input for string search tests. diff --git a/langtools/test/com/sun/javadoc/testHtmlDefinitionListTag/TestHtmlDefinitionListTag.java b/langtools/test/com/sun/javadoc/testHtmlDefinitionListTag/TestHtmlDefinitionListTag.java index 508175a1949..7c403e5b5b0 100644 --- a/langtools/test/com/sun/javadoc/testHtmlDefinitionListTag/TestHtmlDefinitionListTag.java +++ b/langtools/test/com/sun/javadoc/testHtmlDefinitionListTag/TestHtmlDefinitionListTag.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2013, 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 @@ -222,19 +222,19 @@ public class TestHtmlDefinitionListTag extends JavadocTester { private static final String[] ARGS1 = new String[] { - "-d", BUG_ID, "-sourcepath", SRC_DIR, "pkg1"}; + "-Xdoclint:none", "-d", BUG_ID, "-sourcepath", SRC_DIR, "pkg1"}; private static final String[] ARGS2 = new String[] { - "-d", BUG_ID, "-nocomment", "-sourcepath", SRC_DIR, "pkg1"}; + "-Xdoclint:none", "-d", BUG_ID, "-nocomment", "-sourcepath", SRC_DIR, "pkg1"}; private static final String[] ARGS3 = new String[] { - "-d", BUG_ID, "-nodeprecated", "-sourcepath", SRC_DIR, "pkg1"}; + "-Xdoclint:none", "-d", BUG_ID, "-nodeprecated", "-sourcepath", SRC_DIR, "pkg1"}; private static final String[] ARGS4 = new String[] { - "-d", BUG_ID, "-nocomment", "-nodeprecated", "-sourcepath", SRC_DIR, "pkg1"}; + "-Xdoclint:none", "-d", BUG_ID, "-nocomment", "-nodeprecated", "-sourcepath", SRC_DIR, "pkg1"}; /** * The entry point of the test. diff --git a/langtools/test/com/sun/javadoc/testNewLanguageFeatures/TestNewLanguageFeatures.java b/langtools/test/com/sun/javadoc/testNewLanguageFeatures/TestNewLanguageFeatures.java index 0ad0d86e84e..cc6694594e4 100644 --- a/langtools/test/com/sun/javadoc/testNewLanguageFeatures/TestNewLanguageFeatures.java +++ b/langtools/test/com/sun/javadoc/testNewLanguageFeatures/TestNewLanguageFeatures.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2013, 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 @@ -40,7 +40,7 @@ public class TestNewLanguageFeatures extends JavadocTester { //Javadoc arguments. private static final String[] ARGS = new String[] { - "-d", BUG_ID, "-use", "-source", "1.5", "-sourcepath", SRC_DIR, "pkg", "pkg1", "pkg2" + "-Xdoclint:none", "-d", BUG_ID, "-use", "-source", "1.5", "-sourcepath", SRC_DIR, "pkg", "pkg1", "pkg2" }; //Input for string search tests. diff --git a/langtools/test/com/sun/javadoc/testReturnTag/TestReturnTag.java b/langtools/test/com/sun/javadoc/testReturnTag/TestReturnTag.java index eab8f02acd6..b7319746af3 100644 --- a/langtools/test/com/sun/javadoc/testReturnTag/TestReturnTag.java +++ b/langtools/test/com/sun/javadoc/testReturnTag/TestReturnTag.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2013, 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 @@ -39,7 +39,7 @@ public class TestReturnTag extends JavadocTester { //Javadoc arguments. private static final String[] ARGS = new String[] { - "-d", BUG_ID, "-sourcepath", SRC_DIR, SRC_DIR + FS + "TestReturnTag.java" + "-Xdoclint:none", "-d", BUG_ID, "-sourcepath", SRC_DIR, SRC_DIR + FS + "TestReturnTag.java" }; //Input for string search tests. diff --git a/langtools/test/com/sun/javadoc/testTagInheritence/TestTagInheritence.java b/langtools/test/com/sun/javadoc/testTagInheritence/TestTagInheritence.java index ca6f4c0f108..194d10ef118 100644 --- a/langtools/test/com/sun/javadoc/testTagInheritence/TestTagInheritence.java +++ b/langtools/test/com/sun/javadoc/testTagInheritence/TestTagInheritence.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2013, 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 @@ -36,7 +36,7 @@ public class TestTagInheritence extends JavadocTester { private static final String BUG_ID = "4496223-4496270-4618686-4720974-4812240-6253614-6253604"; private static final String[] ARGS = new String[] { - "-d", BUG_ID, "-sourcepath", SRC_DIR, "pkg", "firstSentence", "firstSentence2" + "-Xdoclint:none", "-d", BUG_ID, "-sourcepath", SRC_DIR, "pkg", "firstSentence", "firstSentence2" }; /** diff --git a/langtools/test/com/sun/javadoc/testTagMisuse/TestTagMisuse.java b/langtools/test/com/sun/javadoc/testTagMisuse/TestTagMisuse.java index b80c4ca3141..d5f67301b60 100644 --- a/langtools/test/com/sun/javadoc/testTagMisuse/TestTagMisuse.java +++ b/langtools/test/com/sun/javadoc/testTagMisuse/TestTagMisuse.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2002, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2013, 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 @@ -42,7 +42,7 @@ public class TestTagMisuse extends JavadocTester { }; private static final String[][] NEGATED_TEST = NO_TEST; private static final String[] ARGS = new String[] { - "-d", BUG_ID, SRC_DIR + FS + "TestTagMisuse.java" + "-Xdoclint:none", "-d", BUG_ID, SRC_DIR + FS + "TestTagMisuse.java" }; /** diff --git a/langtools/test/com/sun/javadoc/testValueTag/TestValueTag.java b/langtools/test/com/sun/javadoc/testValueTag/TestValueTag.java index 08780aa6acb..f53e6f4f1a5 100644 --- a/langtools/test/com/sun/javadoc/testValueTag/TestValueTag.java +++ b/langtools/test/com/sun/javadoc/testValueTag/TestValueTag.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2013, 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 @@ -41,6 +41,7 @@ public class TestValueTag extends JavadocTester { //Javadoc arguments. private static final String[] ARGS = new String[] { + "-Xdoclint:none", "-d", BUG_ID, "-sourcepath", SRC_DIR, "-tag", "todo", "pkg1", "pkg2" }; diff --git a/langtools/test/com/sun/javadoc/testWarnBadParamNames/TestWarnBadParamNames.java b/langtools/test/com/sun/javadoc/testWarnBadParamNames/TestWarnBadParamNames.java index de23e99862f..1d58351cff0 100644 --- a/langtools/test/com/sun/javadoc/testWarnBadParamNames/TestWarnBadParamNames.java +++ b/langtools/test/com/sun/javadoc/testWarnBadParamNames/TestWarnBadParamNames.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2013, 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 @@ -43,7 +43,7 @@ public class TestWarnBadParamNames extends JavadocTester { }; private static final String[][] NEGATED_TEST = NO_TEST; private static final String[] ARGS = new String[] { - "-d", BUG_ID, SRC_DIR + FS + "C.java" + "-Xdoclint:none", "-d", BUG_ID, SRC_DIR + FS + "C.java" }; /** diff --git a/langtools/test/com/sun/javadoc/testWarnings/TestWarnings.java b/langtools/test/com/sun/javadoc/testWarnings/TestWarnings.java index bf21f3f0d8f..d5f697a213e 100644 --- a/langtools/test/com/sun/javadoc/testWarnings/TestWarnings.java +++ b/langtools/test/com/sun/javadoc/testWarnings/TestWarnings.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2013, 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 @@ -43,11 +43,11 @@ public class TestWarnings extends JavadocTester { //Javadoc arguments. private static final String[] ARGS = new String[] { - "-d", BUG_ID, "-sourcepath", SRC_DIR, "pkg" + "-Xdoclint:none", "-d", BUG_ID, "-sourcepath", SRC_DIR, "pkg" }; private static final String[] ARGS2 = new String[] { - "-d", BUG_ID, "-private", "-sourcepath", SRC_DIR, "pkg" + "-Xdoclint:none", "-d", BUG_ID, "-private", "-sourcepath", SRC_DIR, "pkg" }; //Input for string search tests. diff --git a/langtools/test/tools/javadoc/6958836/Test.java b/langtools/test/tools/javadoc/6958836/Test.java index 75222700a98..41746f71347 100644 --- a/langtools/test/tools/javadoc/6958836/Test.java +++ b/langtools/test/tools/javadoc/6958836/Test.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2013, 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 @@ -61,6 +61,7 @@ public class Test { // Force en_US locale in lieu of something like -XDrawDiagnostics. // For some reason, this must be the first option when used. opts.addAll(list("-locale", "en_US")); + opts.add("-Xdoclint:none"); opts.addAll(list("-classpath", System.getProperty("test.src"))); opts.addAll(list("-d", testOutDir.getPath())); opts.addAll(testOpts); diff --git a/langtools/test/tools/javadoc/6964914/Test.java b/langtools/test/tools/javadoc/6964914/Test.java index 92362afc1f7..751f29572e9 100644 --- a/langtools/test/tools/javadoc/6964914/Test.java +++ b/langtools/test/tools/javadoc/6964914/Test.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2013, 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 @@ -45,6 +45,7 @@ public class Test { void javadoc(String path, String expect) { File testSrc = new File(System.getProperty("test.src")); String[] args = { + "-Xdoclint:none", "-source", "1.4", // enables certain Parser warnings "-bootclasspath", System.getProperty("sun.boot.class.path"), "-classpath", ".", diff --git a/langtools/test/tools/javadoc/6964914/TestStdDoclet.java b/langtools/test/tools/javadoc/6964914/TestStdDoclet.java index 9714557571c..ce6a39f77c9 100644 --- a/langtools/test/tools/javadoc/6964914/TestStdDoclet.java +++ b/langtools/test/tools/javadoc/6964914/TestStdDoclet.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2013, 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 @@ -57,6 +57,7 @@ public class TestStdDoclet { Process p = new ProcessBuilder() .command(javadoc.getPath(), "-J-Xbootclasspath:" + System.getProperty("sun.boot.class.path"), + "-Xdoclint:none", "-package", new File(testSrc, thisClassName + ".java").getPath()) .redirectErrorStream(true) diff --git a/langtools/test/tools/javadoc/MaxWarns.java b/langtools/test/tools/javadoc/MaxWarns.java index 9cd3b381c01..93b870f62d3 100644 --- a/langtools/test/tools/javadoc/MaxWarns.java +++ b/langtools/test/tools/javadoc/MaxWarns.java @@ -74,7 +74,7 @@ public class MaxWarns { String javadoc(File f) { StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter(sw); - String[] args = { "-d", "api", f.getPath() }; + String[] args = { "-Xdoclint:none", "-d", "api", f.getPath() }; int rc = com.sun.tools.javadoc.Main.execute("javadoc", pw, pw, pw, com.sun.tools.doclets.standard.Standard.class.getName(), args); pw.flush(); diff --git a/langtools/test/tools/javadoc/T6551367.java b/langtools/test/tools/javadoc/T6551367.java index 04e6bdc1bde..f82e7caa633 100644 --- a/langtools/test/tools/javadoc/T6551367.java +++ b/langtools/test/tools/javadoc/T6551367.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2013, 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 @@ -46,7 +46,7 @@ public class T6551367 extends com.sun.tools.doclets.standard.Standard { File source = new File(testSrc, file); int rc = execute("javadoc", "T6551367", T6551367.class.getClassLoader(), - new String[]{source.getPath(), "-d", destDir.getAbsolutePath()}); + new String[]{"-Xdoclint:none", source.getPath(), "-d", destDir.getAbsolutePath()}); if (rc != 0) throw new Error("unexpected exit from javadoc: " + rc); } diff --git a/langtools/test/tools/javadoc/doclint/DocLintTest.java b/langtools/test/tools/javadoc/doclint/DocLintTest.java new file mode 100644 index 00000000000..22557fa1f1f --- /dev/null +++ b/langtools/test/tools/javadoc/doclint/DocLintTest.java @@ -0,0 +1,251 @@ +/* + * Copyright (c) 2012, 2013, 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. + * + * 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. + */ + +/* + * @test + * @bug 8004834 + * @summary Add doclint support into javadoc + */ + +import java.io.File; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.net.URI; +import java.util.Arrays; +import java.util.Collections; +import java.util.EnumSet; +import java.util.List; +import java.util.Set; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import javax.tools.Diagnostic; +import javax.tools.DocumentationTool; +import javax.tools.DocumentationTool.DocumentationTask; +import javax.tools.JavaFileObject; +import javax.tools.SimpleJavaFileObject; +import javax.tools.StandardJavaFileManager; +import javax.tools.StandardLocation; +import javax.tools.ToolProvider; +import static javax.tools.Diagnostic.Kind.*; + +import com.sun.tools.javac.main.Main; + +public class DocLintTest { + public static void main(String... args) throws Exception { + new DocLintTest().run(); + } + + DocumentationTool javadoc; + StandardJavaFileManager fm; + JavaFileObject file; + + final String code = + /* 01 */ "/** Class comment. */\n" + + /* 02 */ "public class Test {\n" + + /* 03 */ " /** Method comment. */\n" + + /* 04 */ " public void method() { }\n" + + /* 05 */ "\n" + + /* 06 */ " /** Syntax < error. */\n" + + /* 07 */ " private void syntaxError() { }\n" + + /* 08 */ "\n" + + /* 09 */ " /** @see DoesNotExist */\n" + + /* 10 */ " protected void referenceError() { }\n" + + /* 11 */ "\n" + + /* 12 */ " /** @return */\n" + + /* 13 */ " public int emptyReturn() { return 0; }\n" + + /* 14 */ "}\n"; + + private final String rawDiags = "-XDrawDiagnostics"; + + private enum Message { + // doclint messages + DL_ERR6(ERROR, "Test.java:6:16: compiler.err.proc.messager: malformed HTML"), + DL_ERR9(ERROR, "Test.java:9:14: compiler.err.proc.messager: reference not found"), + DL_WRN12(WARNING, "Test.java:12:9: compiler.warn.proc.messager: no description for @return"), + + // doclint messages when -XDrawDiagnostics is not in effect + DL_ERR9A(ERROR, "Test.java:9: error: reference not found"), + DL_WRN12A(WARNING, "Test.java:12: warning: no description for @return"), + + // javadoc messages about bad content: these should only appear when doclint is disabled + JD_WRN10(WARNING, "Test.java:10: warning - Tag @see: reference not found: DoesNotExist"), + JD_WRN13(WARNING, "Test.java:13: warning - @return tag has no arguments."), + + // javadoc messages for bad options + OPT_BADARG(ERROR, "javadoc: error - Invalid argument for -Xdoclint option"), + OPT_BADQUAL(ERROR, "javadoc: error - Access qualifiers not permitted for -Xdoclint arguments"); + + final Diagnostic.Kind kind; + final String text; + + static Message get(String text) { + for (Message m: values()) { + if (m.text.equals(text)) + return m; + } + return null; + } + + Message(Diagnostic.Kind kind, String text) { + this.kind = kind; + this.text = text; + } + + @Override + public String toString() { + return "[" + kind + ",\"" + text + "\"]"; + } + } + + void run() throws Exception { + javadoc = ToolProvider.getSystemDocumentationTool(); + fm = javadoc.getStandardFileManager(null, null, null); + fm.setLocation(StandardLocation.CLASS_OUTPUT, Arrays.asList(new File("."))); + file = new SimpleJavaFileObject(URI.create("Test.java"), JavaFileObject.Kind.SOURCE) { + @Override + public CharSequence getCharContent(boolean ignoreEncoding) { + return code; + } + }; + + test(Collections.emptyList(), + Main.Result.ERROR, + EnumSet.of(Message.DL_ERR9A, Message.DL_WRN12A)); + + test(Arrays.asList(rawDiags), + Main.Result.ERROR, + EnumSet.of(Message.DL_ERR9, Message.DL_WRN12)); + + test(Arrays.asList("-Xdoclint:none"), + Main.Result.OK, + EnumSet.of(Message.JD_WRN10, Message.JD_WRN13)); + + test(Arrays.asList(rawDiags, "-Xdoclint"), + Main.Result.ERROR, + EnumSet.of(Message.DL_ERR9, Message.DL_WRN12)); + + test(Arrays.asList(rawDiags, "-Xdoclint:all/public"), + Main.Result.ERROR, + EnumSet.of(Message.OPT_BADQUAL)); + + test(Arrays.asList(rawDiags, "-Xdoclint:all", "-public"), + Main.Result.OK, + EnumSet.of(Message.DL_WRN12)); + + test(Arrays.asList(rawDiags, "-Xdoclint:syntax"), + Main.Result.OK, + EnumSet.of(Message.DL_WRN12)); + + test(Arrays.asList(rawDiags, "-Xdoclint:syntax", "-private"), + Main.Result.ERROR, + EnumSet.of(Message.DL_ERR6, Message.DL_WRN12)); + + test(Arrays.asList(rawDiags, "-Xdoclint:reference"), + Main.Result.ERROR, + EnumSet.of(Message.DL_ERR9)); + + test(Arrays.asList(rawDiags, "-Xdoclint:badarg"), + Main.Result.ERROR, + EnumSet.of(Message.OPT_BADARG)); + + if (errors > 0) + throw new Exception(errors + " errors occurred"); + } + + void test(List opts, Main.Result expectResult, Set expectMessages) { + System.err.println("test: " + opts); + StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter(sw); + List files = Arrays.asList(file); + try { + DocumentationTask t = javadoc.getTask(pw, fm, null, null, opts, files); + boolean ok = t.call(); + pw.close(); + String out = sw.toString().replaceAll("[\r\n]+", "\n"); + if (!out.isEmpty()) + System.err.println(out); + if (ok && expectResult != Main.Result.OK) { + error("Compilation succeeded unexpectedly"); + } else if (!ok && expectResult != Main.Result.ERROR) { + error("Compilation failed unexpectedly"); + } else + check(out, expectMessages); + } catch (IllegalArgumentException e) { + System.err.println(e); + String expectOut = expectMessages.iterator().next().text; + if (expectResult != Main.Result.CMDERR) + error("unexpected exception caught"); + else if (!e.getMessage().equals(expectOut)) { + error("unexpected exception message: " + + e.getMessage() + + " expected: " + expectOut); + } + } + +// if (errors > 0) +// throw new Error("stop"); + } + + private void check(String out, Set expect) { + Pattern ignore = Pattern.compile("^(Building|Constructing|Generating|Loading|Standard|Starting| ) .*"); + Pattern stats = Pattern.compile("^([1-9]+) (error|warning)(s?)"); + Set found = EnumSet.noneOf(Message.class); + int e = 0, w = 0; + for (String line: out.split("[\r\n]+")) { + if (ignore.matcher(line).matches()) + continue; + + Matcher s = stats.matcher(line); + if (s.matches()) { + int i = Integer.valueOf(s.group(1)); + if (s.group(2).equals("error")) + e++; + else + w++; + continue; + } + + Message m = Message.get(line); + if (m == null) + error("Unexpected line: " + line); + else + found.add(m); + } + for (Message m: expect) { + if (!found.contains(m)) + error("expected message not found: " + m.text); + } + for (Message m: found) { + if (!expect.contains(m)) + error("unexpected message found: " + m.text); + } + } + + void error(String msg) { + System.err.println("Error: " + msg); + errors++; + } + + int errors; +} From 8f7055008085deffd407ec4d004097498cc1ca52 Mon Sep 17 00:00:00 2001 From: David Buck Date: Thu, 10 Jan 2013 20:26:00 -0800 Subject: [PATCH 009/210] 8003147: port fix for BCEL bug 39695 Added support for Local Variable Type Table so that BCEL library can be used to modify methods with generics-related debug data without violating class file format Reviewed-by: lancea --- .../org/apache/bcel/internal/Constants.java | 32 ++-- .../bcel/internal/classfile/Attribute.java | 3 + .../internal/classfile/DescendingVisitor.java | 6 + .../bcel/internal/classfile/EmptyVisitor.java | 1 + .../classfile/LocalVariableTypeTable.java | 146 ++++++++++++++++++ .../bcel/internal/classfile/Visitor.java | 1 + .../bcel/internal/generic/MethodGen.java | 17 ++ 7 files changed, 191 insertions(+), 15 deletions(-) create mode 100644 jaxp/src/com/sun/org/apache/bcel/internal/classfile/LocalVariableTypeTable.java diff --git a/jaxp/src/com/sun/org/apache/bcel/internal/Constants.java b/jaxp/src/com/sun/org/apache/bcel/internal/Constants.java index ac4ae3e3e37..d7fc6bcedf0 100644 --- a/jaxp/src/com/sun/org/apache/bcel/internal/Constants.java +++ b/jaxp/src/com/sun/org/apache/bcel/internal/Constants.java @@ -746,27 +746,29 @@ public interface Constants { /** Attributes and their corresponding names. */ - public static final byte ATTR_UNKNOWN = -1; - public static final byte ATTR_SOURCE_FILE = 0; - public static final byte ATTR_CONSTANT_VALUE = 1; - public static final byte ATTR_CODE = 2; - public static final byte ATTR_EXCEPTIONS = 3; - public static final byte ATTR_LINE_NUMBER_TABLE = 4; - public static final byte ATTR_LOCAL_VARIABLE_TABLE = 5; - public static final byte ATTR_INNER_CLASSES = 6; - public static final byte ATTR_SYNTHETIC = 7; - public static final byte ATTR_DEPRECATED = 8; - public static final byte ATTR_PMG = 9; - public static final byte ATTR_SIGNATURE = 10; - public static final byte ATTR_STACK_MAP = 11; + public static final byte ATTR_UNKNOWN = -1; + public static final byte ATTR_SOURCE_FILE = 0; + public static final byte ATTR_CONSTANT_VALUE = 1; + public static final byte ATTR_CODE = 2; + public static final byte ATTR_EXCEPTIONS = 3; + public static final byte ATTR_LINE_NUMBER_TABLE = 4; + public static final byte ATTR_LOCAL_VARIABLE_TABLE = 5; + public static final byte ATTR_INNER_CLASSES = 6; + public static final byte ATTR_SYNTHETIC = 7; + public static final byte ATTR_DEPRECATED = 8; + public static final byte ATTR_PMG = 9; + public static final byte ATTR_SIGNATURE = 10; + public static final byte ATTR_STACK_MAP = 11; + public static final byte ATTR_LOCAL_VARIABLE_TYPE_TABLE = 12; - public static final short KNOWN_ATTRIBUTES = 12; + public static final short KNOWN_ATTRIBUTES = 13; public static final String[] ATTRIBUTE_NAMES = { "SourceFile", "ConstantValue", "Code", "Exceptions", "LineNumberTable", "LocalVariableTable", "InnerClasses", "Synthetic", "Deprecated", - "PMGClass", "Signature", "StackMap" + "PMGClass", "Signature", "StackMap", + "LocalVariableTypeTable" }; /** Constants used in the StackMap attribute. diff --git a/jaxp/src/com/sun/org/apache/bcel/internal/classfile/Attribute.java b/jaxp/src/com/sun/org/apache/bcel/internal/classfile/Attribute.java index a391d4d639a..204bb2506bb 100644 --- a/jaxp/src/com/sun/org/apache/bcel/internal/classfile/Attribute.java +++ b/jaxp/src/com/sun/org/apache/bcel/internal/classfile/Attribute.java @@ -206,6 +206,9 @@ public abstract class Attribute implements Cloneable, Node, Serializable { case Constants.ATTR_LOCAL_VARIABLE_TABLE: return new LocalVariableTable(name_index, length, file, constant_pool); + case Constants.ATTR_LOCAL_VARIABLE_TYPE_TABLE: + return new LocalVariableTypeTable(name_index, length, file, constant_pool); + case Constants.ATTR_INNER_CLASSES: return new InnerClasses(name_index, length, file, constant_pool); diff --git a/jaxp/src/com/sun/org/apache/bcel/internal/classfile/DescendingVisitor.java b/jaxp/src/com/sun/org/apache/bcel/internal/classfile/DescendingVisitor.java index c25cce0555b..fe35197652d 100644 --- a/jaxp/src/com/sun/org/apache/bcel/internal/classfile/DescendingVisitor.java +++ b/jaxp/src/com/sun/org/apache/bcel/internal/classfile/DescendingVisitor.java @@ -210,6 +210,12 @@ public class DescendingVisitor implements Visitor { stack.pop(); } + public void visitLocalVariableTypeTable(LocalVariableTypeTable obj) { + stack.push(obj); + obj.accept(visitor); + stack.pop(); + } + public void visitStackMap(StackMap table) { stack.push(table); table.accept(visitor); diff --git a/jaxp/src/com/sun/org/apache/bcel/internal/classfile/EmptyVisitor.java b/jaxp/src/com/sun/org/apache/bcel/internal/classfile/EmptyVisitor.java index 88fe11e6a8a..32a1cc144cf 100644 --- a/jaxp/src/com/sun/org/apache/bcel/internal/classfile/EmptyVisitor.java +++ b/jaxp/src/com/sun/org/apache/bcel/internal/classfile/EmptyVisitor.java @@ -98,6 +98,7 @@ public class EmptyVisitor implements Visitor { public void visitLineNumberTable(LineNumberTable obj) {} public void visitLocalVariable(LocalVariable obj) {} public void visitLocalVariableTable(LocalVariableTable obj) {} + public void visitLocalVariableTypeTable(LocalVariableTypeTable obj) {} public void visitMethod(Method obj) {} public void visitSignature(Signature obj) {} public void visitSourceFile(SourceFile obj) {} diff --git a/jaxp/src/com/sun/org/apache/bcel/internal/classfile/LocalVariableTypeTable.java b/jaxp/src/com/sun/org/apache/bcel/internal/classfile/LocalVariableTypeTable.java new file mode 100644 index 00000000000..472f53a2b6f --- /dev/null +++ b/jaxp/src/com/sun/org/apache/bcel/internal/classfile/LocalVariableTypeTable.java @@ -0,0 +1,146 @@ +/* + * reserved comment block + * DO NOT REMOVE OR ALTER! + */ +package com.sun.org.apache.bcel.internal.classfile; +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import com.sun.org.apache.bcel.internal.Constants; +import java.io.*; + +// The new table is used when generic types are about... + +//LocalVariableTable_attribute { +// u2 attribute_name_index; +// u4 attribute_length; +// u2 local_variable_table_length; +// { u2 start_pc; +// u2 length; +// u2 name_index; +// u2 descriptor_index; +// u2 index; +// } local_variable_table[local_variable_table_length]; +// } + +//LocalVariableTypeTable_attribute { +// u2 attribute_name_index; +// u4 attribute_length; +// u2 local_variable_type_table_length; +// { +// u2 start_pc; +// u2 length; +// u2 name_index; +// u2 signature_index; +// u2 index; +// } local_variable_type_table[local_variable_type_table_length]; +// } +// J5TODO: Needs some testing ! +public class LocalVariableTypeTable extends Attribute { + private static final long serialVersionUID = -1082157891095177114L; +private int local_variable_type_table_length; // Table of local + private LocalVariable[] local_variable_type_table; // variables + + public LocalVariableTypeTable(LocalVariableTypeTable c) { + this(c.getNameIndex(), c.getLength(), c.getLocalVariableTypeTable(), + c.getConstantPool()); + } + + public LocalVariableTypeTable(int name_index, int length, + LocalVariable[] local_variable_table, + ConstantPool constant_pool) + { + super(Constants.ATTR_LOCAL_VARIABLE_TYPE_TABLE, name_index, length, constant_pool); + setLocalVariableTable(local_variable_table); + } + + LocalVariableTypeTable(int nameIdx, int len, DataInputStream dis,ConstantPool cpool) throws IOException { + this(nameIdx, len, (LocalVariable[])null, cpool); + + local_variable_type_table_length = (dis.readUnsignedShort()); + local_variable_type_table = new LocalVariable[local_variable_type_table_length]; + + for(int i=0; i < local_variable_type_table_length; i++) + local_variable_type_table[i] = new LocalVariable(dis, cpool); + } + + @Override +public void accept(Visitor v) { + v.visitLocalVariableTypeTable(this); + } + + @Override +public final void dump(DataOutputStream file) throws IOException + { + super.dump(file); + file.writeShort(local_variable_type_table_length); + for(int i=0; i < local_variable_type_table_length; i++) + local_variable_type_table[i].dump(file); + } + + public final LocalVariable[] getLocalVariableTypeTable() { + return local_variable_type_table; + } + + public final LocalVariable getLocalVariable(int index) { + for(int i=0; i < local_variable_type_table_length; i++) + if(local_variable_type_table[i].getIndex() == index) + return local_variable_type_table[i]; + + return null; + } + + public final void setLocalVariableTable(LocalVariable[] local_variable_table) + { + this.local_variable_type_table = local_variable_table; + local_variable_type_table_length = (local_variable_table == null)? 0 : + local_variable_table.length; + } + + /** + * @return String representation. + */ + @Override +public final String toString() { + StringBuilder buf = new StringBuilder(); + + for(int i=0; i < local_variable_type_table_length; i++) { + buf.append(local_variable_type_table[i].toString()); + + if(i < local_variable_type_table_length - 1) buf.append('\n'); + } + + return buf.toString(); + } + + /** + * @return deep copy of this attribute + */ + @Override +public Attribute copy(ConstantPool constant_pool) { + LocalVariableTypeTable c = (LocalVariableTypeTable)clone(); + + c.local_variable_type_table = new LocalVariable[local_variable_type_table_length]; + for(int i=0; i < local_variable_type_table_length; i++) + c.local_variable_type_table[i] = local_variable_type_table[i].copy(); + + c.constant_pool = constant_pool; + return c; + } + + public final int getTableLength() { return local_variable_type_table_length; } +} diff --git a/jaxp/src/com/sun/org/apache/bcel/internal/classfile/Visitor.java b/jaxp/src/com/sun/org/apache/bcel/internal/classfile/Visitor.java index a66c7ad2927..a076768700c 100644 --- a/jaxp/src/com/sun/org/apache/bcel/internal/classfile/Visitor.java +++ b/jaxp/src/com/sun/org/apache/bcel/internal/classfile/Visitor.java @@ -94,6 +94,7 @@ public interface Visitor { public void visitLineNumberTable(LineNumberTable obj); public void visitLocalVariable(LocalVariable obj); public void visitLocalVariableTable(LocalVariableTable obj); + public void visitLocalVariableTypeTable(LocalVariableTypeTable obj); public void visitMethod(Method obj); public void visitSignature(Signature obj); public void visitSourceFile(SourceFile obj); diff --git a/jaxp/src/com/sun/org/apache/bcel/internal/generic/MethodGen.java b/jaxp/src/com/sun/org/apache/bcel/internal/generic/MethodGen.java index a58172a9114..34da00768cd 100644 --- a/jaxp/src/com/sun/org/apache/bcel/internal/generic/MethodGen.java +++ b/jaxp/src/com/sun/org/apache/bcel/internal/generic/MethodGen.java @@ -258,6 +258,23 @@ public class MethodGen extends FieldGenOrMethodGen { addLocalVariable(l.getName(), Type.getType(l.getSignature()), l.getIndex(), start, end); } + } else if (a instanceof LocalVariableTypeTable) { + LocalVariable[] lv = ((LocalVariableTypeTable) a).getLocalVariableTypeTable(); + removeLocalVariables(); + for (int k = 0; k < lv.length; k++) { + LocalVariable l = lv[k]; + InstructionHandle start = il.findHandle(l.getStartPC()); + InstructionHandle end = il.findHandle(l.getStartPC() + l.getLength()); + // Repair malformed handles + if (null == start) { + start = il.getStart(); + } + if (null == end) { + end = il.getEnd(); + } + addLocalVariable(l.getName(), Type.getType(l.getSignature()), l + .getIndex(), start, end); + } } else addCodeAttribute(a); } From d06c06026ac94ec811ac7b1d4825f9be5a0a9c0b Mon Sep 17 00:00:00 2001 From: Alejandro Murillo Date: Fri, 11 Jan 2013 02:02:51 -0800 Subject: [PATCH 010/210] 8006034: new hotspot build - hs25-b16 Reviewed-by: jcoomes --- hotspot/make/hotspot_version | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/hotspot/make/hotspot_version b/hotspot/make/hotspot_version index d6959b3b86c..946cb5c1aa8 100644 --- a/hotspot/make/hotspot_version +++ b/hotspot/make/hotspot_version @@ -1,5 +1,5 @@ # -# Copyright (c) 2006, 2012, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2006, 2013, 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 @@ -31,11 +31,11 @@ # # Don't put quotes (fail windows build). -HOTSPOT_VM_COPYRIGHT=Copyright 2012 +HOTSPOT_VM_COPYRIGHT=Copyright 2013 HS_MAJOR_VER=25 HS_MINOR_VER=0 -HS_BUILD_NUMBER=15 +HS_BUILD_NUMBER=16 JDK_MAJOR_VER=1 JDK_MINOR_VER=8 From 93d2366337fae6b1607a4c6368bc3fa9e872dfca Mon Sep 17 00:00:00 2001 From: Zhengyu Gu Date: Fri, 11 Jan 2013 12:30:54 -0500 Subject: [PATCH 011/210] 8005936: PrintNMTStatistics doesn't work for normal JVM exit Moved NMT shutdown code to JVM exit handler to ensure NMT statistics is printed when PrintNMTStatistics is enabled Reviewed-by: acorn, dholmes, coleenp --- hotspot/src/share/vm/runtime/java.cpp | 4 ++++ hotspot/src/share/vm/runtime/thread.cpp | 4 ---- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/hotspot/src/share/vm/runtime/java.cpp b/hotspot/src/share/vm/runtime/java.cpp index ad6399495b0..fb26ad9ddfc 100644 --- a/hotspot/src/share/vm/runtime/java.cpp +++ b/hotspot/src/share/vm/runtime/java.cpp @@ -542,6 +542,10 @@ void before_exit(JavaThread * thread) { BeforeExit_lock->notify_all(); } + // Shutdown NMT before exit. Otherwise, + // it will run into trouble when system destroys static variables. + MemTracker::shutdown(MemTracker::NMT_normal); + #undef BEFORE_EXIT_NOT_RUN #undef BEFORE_EXIT_RUNNING #undef BEFORE_EXIT_DONE diff --git a/hotspot/src/share/vm/runtime/thread.cpp b/hotspot/src/share/vm/runtime/thread.cpp index db3cace3d64..971f4f8dad1 100644 --- a/hotspot/src/share/vm/runtime/thread.cpp +++ b/hotspot/src/share/vm/runtime/thread.cpp @@ -4011,10 +4011,6 @@ bool Threads::destroy_vm() { Mutex::_as_suspend_equivalent_flag); } - // Shutdown NMT before exit. Otherwise, - // it will run into trouble when system destroys static variables. - MemTracker::shutdown(MemTracker::NMT_normal); - // Hang forever on exit if we are reporting an error. if (ShowMessageBoxOnError && is_error_reported()) { os::infinite_sleep(); From 2cbabcea4a6e675bd498173a64f1f061c3ac5199 Mon Sep 17 00:00:00 2001 From: Jiangli Zhou Date: Fri, 11 Jan 2013 16:55:07 -0500 Subject: [PATCH 012/210] 8005895: Inefficient InstanceKlass field packing wasts memory Pack _misc_has_default_methods into the _misc_flags, move _idnum_allocated_count. Reviewed-by: coleenp, shade --- hotspot/src/share/vm/oops/instanceKlass.hpp | 24 +++++++++++++++------ 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/hotspot/src/share/vm/oops/instanceKlass.hpp b/hotspot/src/share/vm/oops/instanceKlass.hpp index 0d173faa510..9793dd77d82 100644 --- a/hotspot/src/share/vm/oops/instanceKlass.hpp +++ b/hotspot/src/share/vm/oops/instanceKlass.hpp @@ -225,12 +225,16 @@ class InstanceKlass: public Klass { u2 _java_fields_count; // The number of declared Java fields int _nonstatic_oop_map_size;// size in words of nonstatic oop map blocks + // _is_marked_dependent can be set concurrently, thus cannot be part of the + // _misc_flags. bool _is_marked_dependent; // used for marking during flushing and deoptimization + enum { _misc_rewritten = 1 << 0, // methods rewritten. _misc_has_nonstatic_fields = 1 << 1, // for sizing with UseCompressedOops _misc_should_verify_class = 1 << 2, // allow caching of preverification - _misc_is_anonymous = 1 << 3 // has embedded _inner_classes field + _misc_is_anonymous = 1 << 3, // has embedded _inner_classes field + _misc_has_default_methods = 1 << 4 // class/superclass/implemented interfaces has default methods }; u2 _misc_flags; u2 _minor_version; // minor version number of class file @@ -253,10 +257,6 @@ class InstanceKlass: public Klass { jint _cached_class_file_len; // JVMTI: length of above JvmtiCachedClassFieldMap* _jvmti_cached_class_field_map; // JVMTI: used during heap iteration - // true if class, superclass, or implemented interfaces have default methods - bool _has_default_methods; - - volatile u2 _idnum_allocated_count; // JNI/JVMTI: increments with the addition of methods, old ids don't change // Method array. Array* _methods; // Interface (Klass*s) this class declares locally to implement. @@ -280,6 +280,8 @@ class InstanceKlass: public Klass { // ... Array* _fields; + volatile u2 _idnum_allocated_count; // JNI/JVMTI: increments with the addition of methods, old ids don't change + // Class states are defined as ClassState (see above). // Place the _init_state here to utilize the unused 2-byte after // _idnum_allocated_count. @@ -616,8 +618,16 @@ class InstanceKlass: public Klass { return _jvmti_cached_class_field_map; } - bool has_default_methods() const { return _has_default_methods; } - void set_has_default_methods(bool b) { _has_default_methods = b; } + bool has_default_methods() const { + return (_misc_flags & _misc_has_default_methods) != 0; + } + void set_has_default_methods(bool b) { + if (b) { + _misc_flags |= _misc_has_default_methods; + } else { + _misc_flags &= ~_misc_has_default_methods; + } + } // for adding methods, ConstMethod::UNSET_IDNUM means no more ids available inline u2 next_method_idnum(); From 6c57a4b9f8978dfa88f586d7dc109d95f6a62f96 Mon Sep 17 00:00:00 2001 From: Christian Thalinger Date: Fri, 11 Jan 2013 14:07:09 -0800 Subject: [PATCH 013/210] 8006031: LibraryCallKit::inline_array_copyOf disabled unintentionally with 7172640 Reviewed-by: kvn --- hotspot/src/share/vm/opto/library_call.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hotspot/src/share/vm/opto/library_call.cpp b/hotspot/src/share/vm/opto/library_call.cpp index 313339edfde..b2138abe931 100644 --- a/hotspot/src/share/vm/opto/library_call.cpp +++ b/hotspot/src/share/vm/opto/library_call.cpp @@ -3559,7 +3559,7 @@ bool LibraryCallKit::inline_native_getLength() { // public static T[] java.util.Arrays.copyOf( U[] original, int newLength, Class newType); // public static T[] java.util.Arrays.copyOfRange(U[] original, int from, int to, Class newType); bool LibraryCallKit::inline_array_copyOf(bool is_copyOfRange) { - return false; + tty->print_cr("LibraryCallKit::inline_array_copyOf: %d", is_copyOfRange); if (too_many_traps(Deoptimization::Reason_intrinsic)) return false; // Get the arguments. From a42478ecf417902fbb5dd100ffbe44d5dc38c1d6 Mon Sep 17 00:00:00 2001 From: Roman Kennke Date: Fri, 11 Jan 2013 16:47:23 -0800 Subject: [PATCH 014/210] 8005816: Shark: fix volatile float field access Reviewed-by: twisti --- hotspot/src/share/vm/shark/sharkBlock.cpp | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/hotspot/src/share/vm/shark/sharkBlock.cpp b/hotspot/src/share/vm/shark/sharkBlock.cpp index b4e98365efc..723b2d1dbc6 100644 --- a/hotspot/src/share/vm/shark/sharkBlock.cpp +++ b/hotspot/src/share/vm/shark/sharkBlock.cpp @@ -1044,10 +1044,17 @@ void SharkBlock::do_field_access(bool is_get, bool is_field) { BasicType basic_type = field->type()->basic_type(); Type *stack_type = SharkType::to_stackType(basic_type); Type *field_type = SharkType::to_arrayType(basic_type); - + Type *type = field_type; + if (field->is_volatile()) { + if (field_type == SharkType::jfloat_type()) { + type = SharkType::jint_type(); + } else if (field_type == SharkType::jdouble_type()) { + type = SharkType::jlong_type(); + } + } Value *addr = builder()->CreateAddressOfStructEntry( object, in_ByteSize(field->offset_in_bytes()), - PointerType::getUnqual(field_type), + PointerType::getUnqual(type), "addr"); // Do the access @@ -1055,6 +1062,7 @@ void SharkBlock::do_field_access(bool is_get, bool is_field) { Value* field_value; if (field->is_volatile()) { field_value = builder()->CreateAtomicLoad(addr); + field_value = builder()->CreateBitCast(field_value, field_type); } else { field_value = builder()->CreateLoad(addr); } @@ -1074,6 +1082,7 @@ void SharkBlock::do_field_access(bool is_get, bool is_field) { } if (field->is_volatile()) { + field_value = builder()->CreateBitCast(field_value, type); builder()->CreateAtomicStore(field_value, addr); } else { builder()->CreateStore(field_value, addr); From a0a0d0b65ef0dc2a055fac34fbad0b44e0a4067a Mon Sep 17 00:00:00 2001 From: Roman Kennke Date: Fri, 11 Jan 2013 16:47:23 -0800 Subject: [PATCH 015/210] 8005817: Shark: implement deoptimization support Reviewed-by: twisti --- hotspot/src/cpu/zero/vm/frame_zero.cpp | 18 ++++++++++++++---- hotspot/src/cpu/zero/vm/frame_zero.inline.hpp | 15 ++++++++++++--- hotspot/src/cpu/zero/vm/sharkFrame_zero.hpp | 4 ++++ hotspot/src/share/vm/shark/sharkInvariants.hpp | 8 +++++--- .../src/share/vm/shark/sharkTopLevelBlock.cpp | 7 ++++--- 5 files changed, 39 insertions(+), 13 deletions(-) diff --git a/hotspot/src/cpu/zero/vm/frame_zero.cpp b/hotspot/src/cpu/zero/vm/frame_zero.cpp index 8643af5953f..56f2a7a1c71 100644 --- a/hotspot/src/cpu/zero/vm/frame_zero.cpp +++ b/hotspot/src/cpu/zero/vm/frame_zero.cpp @@ -98,10 +98,20 @@ BasicObjectLock* frame::interpreter_frame_monitor_end() const { #endif // CC_INTERP void frame::patch_pc(Thread* thread, address pc) { - // We borrow this call to set the thread pointer in the interpreter - // state; the hook to set up deoptimized frames isn't supplied it. - assert(pc == NULL, "should be"); - get_interpreterState()->set_thread((JavaThread *) thread); + + if (pc != NULL) { + _cb = CodeCache::find_blob(pc); + SharkFrame* sharkframe = zeroframe()->as_shark_frame(); + sharkframe->set_pc(pc); + _pc = pc; + _deopt_state = is_deoptimized; + + } else { + // We borrow this call to set the thread pointer in the interpreter + // state; the hook to set up deoptimized frames isn't supplied it. + assert(pc == NULL, "should be"); + get_interpreterState()->set_thread((JavaThread *) thread); + } } bool frame::safe_for_sender(JavaThread *thread) { diff --git a/hotspot/src/cpu/zero/vm/frame_zero.inline.hpp b/hotspot/src/cpu/zero/vm/frame_zero.inline.hpp index 2bc703ae032..f6bd6d3c6be 100644 --- a/hotspot/src/cpu/zero/vm/frame_zero.inline.hpp +++ b/hotspot/src/cpu/zero/vm/frame_zero.inline.hpp @@ -45,27 +45,36 @@ inline frame::frame(ZeroFrame* zf, intptr_t* sp) { case ZeroFrame::ENTRY_FRAME: _pc = StubRoutines::call_stub_return_pc(); _cb = NULL; + _deopt_state = not_deoptimized; break; case ZeroFrame::INTERPRETER_FRAME: _pc = NULL; _cb = NULL; + _deopt_state = not_deoptimized; break; - case ZeroFrame::SHARK_FRAME: + case ZeroFrame::SHARK_FRAME: { _pc = zero_sharkframe()->pc(); _cb = CodeCache::find_blob_unsafe(pc()); + address original_pc = nmethod::get_deopt_original_pc(this); + if (original_pc != NULL) { + _pc = original_pc; + _deopt_state = is_deoptimized; + } else { + _deopt_state = not_deoptimized; + } break; - + } case ZeroFrame::FAKE_STUB_FRAME: _pc = NULL; _cb = NULL; + _deopt_state = not_deoptimized; break; default: ShouldNotReachHere(); } - _deopt_state = not_deoptimized; } // Accessors diff --git a/hotspot/src/cpu/zero/vm/sharkFrame_zero.hpp b/hotspot/src/cpu/zero/vm/sharkFrame_zero.hpp index 6c67d0eb1d8..505241b147f 100644 --- a/hotspot/src/cpu/zero/vm/sharkFrame_zero.hpp +++ b/hotspot/src/cpu/zero/vm/sharkFrame_zero.hpp @@ -68,6 +68,10 @@ class SharkFrame : public ZeroFrame { return (address) value_of_word(pc_off); } + void set_pc(address pc) const { + *((address*) addr_of_word(pc_off)) = pc; + } + intptr_t* unextended_sp() const { return (intptr_t *) value_of_word(unextended_sp_off); } diff --git a/hotspot/src/share/vm/shark/sharkInvariants.hpp b/hotspot/src/share/vm/shark/sharkInvariants.hpp index 50e1be8ea6d..8e9d0aec062 100644 --- a/hotspot/src/share/vm/shark/sharkInvariants.hpp +++ b/hotspot/src/share/vm/shark/sharkInvariants.hpp @@ -99,13 +99,15 @@ class SharkCompileInvariants : public ResourceObj { DebugInformationRecorder* debug_info() const { return env()->debug_info(); } - Dependencies* dependencies() const { - return env()->dependencies(); - } SharkCodeBuffer* code_buffer() const { return builder()->code_buffer(); } + public: + Dependencies* dependencies() const { + return env()->dependencies(); + } + // Commonly used classes protected: ciInstanceKlass* java_lang_Object_klass() const { diff --git a/hotspot/src/share/vm/shark/sharkTopLevelBlock.cpp b/hotspot/src/share/vm/shark/sharkTopLevelBlock.cpp index fcd6906caad..a3f90b058bf 100644 --- a/hotspot/src/share/vm/shark/sharkTopLevelBlock.cpp +++ b/hotspot/src/share/vm/shark/sharkTopLevelBlock.cpp @@ -1030,7 +1030,6 @@ ciMethod* SharkTopLevelBlock::improve_virtual_call(ciMethod* caller, dest_method->holder() == java_lang_Object_klass()) return dest_method; -#ifdef SHARK_CAN_DEOPTIMIZE_ANYWHERE // This code can replace a virtual call with a direct call if this // class is the only one in the entire set of loaded classes that // implements this method. This makes the compiled code dependent @@ -1064,6 +1063,8 @@ ciMethod* SharkTopLevelBlock::improve_virtual_call(ciMethod* caller, if (monomorphic_target != NULL) { assert(!monomorphic_target->is_abstract(), "shouldn't be"); + function()->dependencies()->assert_unique_concrete_method(actual_receiver, monomorphic_target); + // Opto has a bunch of type checking here that I don't // understand. It's to inhibit casting in one direction, // possibly because objects in Opto can have inexact @@ -1097,7 +1098,6 @@ ciMethod* SharkTopLevelBlock::improve_virtual_call(ciMethod* caller, // with non-monomorphic targets if the receiver has an exact // type. We don't mark types this way, so we can't do this. -#endif // SHARK_CAN_DEOPTIMIZE_ANYWHERE return NULL; } @@ -1298,8 +1298,9 @@ void SharkTopLevelBlock::do_call() { // Try to inline the call if (!call_is_virtual) { - if (SharkInliner::attempt_inline(call_method, current_state())) + if (SharkInliner::attempt_inline(call_method, current_state())) { return; + } } // Find the method we are calling From ba649f4203f5d53ce5f0475156c87dc741a7869d Mon Sep 17 00:00:00 2001 From: Roman Kennke Date: Fri, 11 Jan 2013 16:47:23 -0800 Subject: [PATCH 016/210] 8005818: Shark: fix OSR for non-empty incoming stack Reviewed-by: twisti --- hotspot/src/share/vm/shark/sharkCompiler.cpp | 3 +++ hotspot/src/share/vm/shark/sharkFunction.cpp | 4 ++++ hotspot/src/share/vm/shark/sharkInvariants.hpp | 2 +- 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/hotspot/src/share/vm/shark/sharkCompiler.cpp b/hotspot/src/share/vm/shark/sharkCompiler.cpp index 3438240ad00..cde6bc23e76 100644 --- a/hotspot/src/share/vm/shark/sharkCompiler.cpp +++ b/hotspot/src/share/vm/shark/sharkCompiler.cpp @@ -185,6 +185,9 @@ void SharkCompiler::compile_method(ciEnv* env, // Build the LLVM IR for the method Function *function = SharkFunction::build(env, &builder, flow, name); + if (env->failing()) { + return; + } // Generate native code. It's unpleasant that we have to drop into // the VM to do this -- it blocks safepoints -- but I can't see any diff --git a/hotspot/src/share/vm/shark/sharkFunction.cpp b/hotspot/src/share/vm/shark/sharkFunction.cpp index 917ed0109ac..1ec7a371fb4 100644 --- a/hotspot/src/share/vm/shark/sharkFunction.cpp +++ b/hotspot/src/share/vm/shark/sharkFunction.cpp @@ -77,6 +77,10 @@ void SharkFunction::initialize(const char *name) { // Walk the tree from the start block to determine which // blocks are entered and which blocks require phis SharkTopLevelBlock *start_block = block(flow()->start_block_num()); + if (is_osr() && start_block->stack_depth_at_entry() != 0) { + env()->record_method_not_compilable("can't compile OSR block with incoming stack-depth > 0"); + return; + } assert(start_block->start() == flow()->start_bci(), "blocks out of order"); start_block->enter(); diff --git a/hotspot/src/share/vm/shark/sharkInvariants.hpp b/hotspot/src/share/vm/shark/sharkInvariants.hpp index 8e9d0aec062..e6b6399fe26 100644 --- a/hotspot/src/share/vm/shark/sharkInvariants.hpp +++ b/hotspot/src/share/vm/shark/sharkInvariants.hpp @@ -68,7 +68,7 @@ class SharkCompileInvariants : public ResourceObj { // // Accessing this directly is kind of ugly, so it's private. Add // new accessors below if you need something from it. - private: + protected: ciEnv* env() const { assert(_env != NULL, "env not available"); return _env; From b17ebac5b54b3e1be6199cd71c63843c771836dc Mon Sep 17 00:00:00 2001 From: Roman Kennke Date: Fri, 11 Jan 2013 16:47:23 -0800 Subject: [PATCH 017/210] 8005820: Shark: enable JSR292 support Reviewed-by: twisti --- .../share/vm/compiler/abstractCompiler.hpp | 1 + .../src/share/vm/compiler/compileBroker.cpp | 2 +- hotspot/src/share/vm/shark/sharkBlock.cpp | 2 +- hotspot/src/share/vm/shark/sharkCompiler.hpp | 3 +++ hotspot/src/share/vm/shark/sharkConstant.cpp | 7 +++++- hotspot/src/share/vm/shark/sharkInliner.cpp | 2 +- .../src/share/vm/shark/sharkTopLevelBlock.cpp | 24 ++++++++++++++++++- 7 files changed, 36 insertions(+), 5 deletions(-) diff --git a/hotspot/src/share/vm/compiler/abstractCompiler.hpp b/hotspot/src/share/vm/compiler/abstractCompiler.hpp index 9007a82fc49..96453e7d9ba 100644 --- a/hotspot/src/share/vm/compiler/abstractCompiler.hpp +++ b/hotspot/src/share/vm/compiler/abstractCompiler.hpp @@ -50,6 +50,7 @@ class AbstractCompiler : public CHeapObj { // Missing feature tests virtual bool supports_native() { return true; } virtual bool supports_osr () { return true; } + virtual bool can_compile_method(methodHandle method) { return true; } #if defined(TIERED) || ( !defined(COMPILER1) && !defined(COMPILER2) && !defined(SHARK)) virtual bool is_c1 () { return false; } virtual bool is_c2 () { return false; } diff --git a/hotspot/src/share/vm/compiler/compileBroker.cpp b/hotspot/src/share/vm/compiler/compileBroker.cpp index 73ab865dc74..57389701d82 100644 --- a/hotspot/src/share/vm/compiler/compileBroker.cpp +++ b/hotspot/src/share/vm/compiler/compileBroker.cpp @@ -1218,7 +1218,7 @@ nmethod* CompileBroker::compile_method(methodHandle method, int osr_bci, // lock, make sure that the compilation // isn't prohibited in a straightforward way. - if (compiler(comp_level) == NULL || compilation_is_prohibited(method, osr_bci, comp_level)) { + if (compiler(comp_level) == NULL || !compiler(comp_level)->can_compile_method(method) || compilation_is_prohibited(method, osr_bci, comp_level)) { return NULL; } diff --git a/hotspot/src/share/vm/shark/sharkBlock.cpp b/hotspot/src/share/vm/shark/sharkBlock.cpp index 723b2d1dbc6..6b1b5fbe89c 100644 --- a/hotspot/src/share/vm/shark/sharkBlock.cpp +++ b/hotspot/src/share/vm/shark/sharkBlock.cpp @@ -1032,7 +1032,7 @@ void SharkBlock::do_field_access(bool is_get, bool is_field) { check_null(value); object = value->generic_value(); } - if (is_get && field->is_constant()) { + if (is_get && field->is_constant() && field->is_static()) { SharkConstant *constant = SharkConstant::for_field(iter()); if (constant->is_loaded()) value = constant->value(builder()); diff --git a/hotspot/src/share/vm/shark/sharkCompiler.hpp b/hotspot/src/share/vm/shark/sharkCompiler.hpp index 828a783a80d..7e530c142aa 100644 --- a/hotspot/src/share/vm/shark/sharkCompiler.hpp +++ b/hotspot/src/share/vm/shark/sharkCompiler.hpp @@ -46,6 +46,9 @@ class SharkCompiler : public AbstractCompiler { // Missing feature tests bool supports_native() { return true; } bool supports_osr() { return true; } + bool can_compile_method(methodHandle method) { + return ! (method->is_method_handle_intrinsic() || method->is_compiled_lambda_form()); + } // Customization bool needs_adapters() { return false; } diff --git a/hotspot/src/share/vm/shark/sharkConstant.cpp b/hotspot/src/share/vm/shark/sharkConstant.cpp index b45ec136e77..cd6e1152d0f 100644 --- a/hotspot/src/share/vm/shark/sharkConstant.cpp +++ b/hotspot/src/share/vm/shark/sharkConstant.cpp @@ -37,7 +37,12 @@ SharkConstant* SharkConstant::for_ldc(ciBytecodeStream *iter) { ciType *type = NULL; if (constant.basic_type() == T_OBJECT) { ciEnv *env = ciEnv::current(); - assert(constant.as_object()->klass() == env->String_klass() || constant.as_object()->klass() == env->Class_klass(), "should be"); + + assert(constant.as_object()->klass() == env->String_klass() + || constant.as_object()->klass() == env->Class_klass() + || constant.as_object()->klass()->is_subtype_of(env->MethodType_klass()) + || constant.as_object()->klass()->is_subtype_of(env->MethodHandle_klass()), "should be"); + type = constant.as_object()->klass(); } return new SharkConstant(constant, type); diff --git a/hotspot/src/share/vm/shark/sharkInliner.cpp b/hotspot/src/share/vm/shark/sharkInliner.cpp index c9e895a9c9b..1f4ea829fb3 100644 --- a/hotspot/src/share/vm/shark/sharkInliner.cpp +++ b/hotspot/src/share/vm/shark/sharkInliner.cpp @@ -725,7 +725,7 @@ bool SharkInlinerHelper::do_field_access(bool is_get, bool is_field) { // Push the result if necessary if (is_get) { bool result_pushed = false; - if (field->is_constant()) { + if (field->is_constant() && field->is_static()) { SharkConstant *sc = SharkConstant::for_field(iter()); if (sc->is_loaded()) { push(sc->is_nonzero()); diff --git a/hotspot/src/share/vm/shark/sharkTopLevelBlock.cpp b/hotspot/src/share/vm/shark/sharkTopLevelBlock.cpp index a3f90b058bf..6614146bb42 100644 --- a/hotspot/src/share/vm/shark/sharkTopLevelBlock.cpp +++ b/hotspot/src/share/vm/shark/sharkTopLevelBlock.cpp @@ -113,7 +113,19 @@ void SharkTopLevelBlock::scan_for_traps() { ciSignature* sig; method = iter()->get_method(will_link, &sig); assert(will_link, "typeflow responsibility"); - + // We can't compile calls to method handle intrinsics, because we use + // the interpreter entry points and they expect the top frame to be an + // interpreter frame. We need to implement the intrinsics for Shark. + if (method->is_method_handle_intrinsic() || method->is_compiled_lambda_form()) { + if (SharkPerformanceWarnings) { + warning("JSR292 optimization not yet implemented in Shark"); + } + set_trap( + Deoptimization::make_trap_request( + Deoptimization::Reason_unhandled, + Deoptimization::Action_make_not_compilable), bci()); + return; + } if (!method->holder()->is_linked()) { set_trap( Deoptimization::make_trap_request( @@ -158,6 +170,16 @@ void SharkTopLevelBlock::scan_for_traps() { return; } break; + case Bytecodes::_invokedynamic: + case Bytecodes::_invokehandle: + if (SharkPerformanceWarnings) { + warning("JSR292 optimization not yet implemented in Shark"); + } + set_trap( + Deoptimization::make_trap_request( + Deoptimization::Reason_unhandled, + Deoptimization::Action_make_not_compilable), bci()); + return; } } From 827930b510dd8ae13b0dd42f97f499c4772384f6 Mon Sep 17 00:00:00 2001 From: Christian Thalinger Date: Fri, 11 Jan 2013 20:01:16 -0800 Subject: [PATCH 018/210] 8006127: remove printing code added with 8006031 Reviewed-by: kvn --- hotspot/src/share/vm/opto/library_call.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/hotspot/src/share/vm/opto/library_call.cpp b/hotspot/src/share/vm/opto/library_call.cpp index b2138abe931..406f605853d 100644 --- a/hotspot/src/share/vm/opto/library_call.cpp +++ b/hotspot/src/share/vm/opto/library_call.cpp @@ -3559,7 +3559,6 @@ bool LibraryCallKit::inline_native_getLength() { // public static T[] java.util.Arrays.copyOf( U[] original, int newLength, Class newType); // public static T[] java.util.Arrays.copyOfRange(U[] original, int from, int to, Class newType); bool LibraryCallKit::inline_array_copyOf(bool is_copyOfRange) { - tty->print_cr("LibraryCallKit::inline_array_copyOf: %d", is_copyOfRange); if (too_many_traps(Deoptimization::Reason_intrinsic)) return false; // Get the arguments. From a3639fdea176da5d87615a58ef294d5f5cb0bc5c Mon Sep 17 00:00:00 2001 From: Erik Helin Date: Mon, 14 Jan 2013 09:58:52 +0100 Subject: [PATCH 019/210] 8004018: Remove old initialization flags Reviewed-by: dholmes, stefank --- hotspot/src/share/vm/runtime/globals.hpp | 12 ---- hotspot/src/share/vm/runtime/thread.cpp | 77 +++++++++--------------- 2 files changed, 29 insertions(+), 60 deletions(-) diff --git a/hotspot/src/share/vm/runtime/globals.hpp b/hotspot/src/share/vm/runtime/globals.hpp index 7ea96627e82..61aee4a9060 100644 --- a/hotspot/src/share/vm/runtime/globals.hpp +++ b/hotspot/src/share/vm/runtime/globals.hpp @@ -969,18 +969,6 @@ class CommandLineFlags { notproduct(uintx, WarnOnStalledSpinLock, 0, \ "Prints warnings for stalled SpinLocks") \ \ - develop(bool, InitializeJavaLangSystem, true, \ - "Initialize java.lang.System - turn off for individual " \ - "method debugging") \ - \ - develop(bool, InitializeJavaLangString, true, \ - "Initialize java.lang.String - turn off for individual " \ - "method debugging") \ - \ - develop(bool, InitializeJavaLangExceptionsErrors, true, \ - "Initialize various error and exception classes - turn off for " \ - "individual method debugging") \ - \ product(bool, RegisterFinalizersAtInit, true, \ "Register finalizable objects at end of Object. or " \ "after allocation") \ diff --git a/hotspot/src/share/vm/runtime/thread.cpp b/hotspot/src/share/vm/runtime/thread.cpp index db3cace3d64..5be1615e1be 100644 --- a/hotspot/src/share/vm/runtime/thread.cpp +++ b/hotspot/src/share/vm/runtime/thread.cpp @@ -1716,7 +1716,6 @@ static void ensure_join(JavaThread* thread) { // cleanup_failed_attach_current_thread as well. void JavaThread::exit(bool destroy_vm, ExitType exit_type) { assert(this == JavaThread::current(), "thread consistency check"); - if (!InitializeJavaLangSystem) return; HandleMark hm(this); Handle uncaught_exception(this, this->pending_exception()); @@ -3469,11 +3468,7 @@ jint Threads::create_vm(JavaVMInitArgs* args, bool* canTryAgain) { create_vm_init_libraries(); } - if (InitializeJavaLangString) { - initialize_class(vmSymbols::java_lang_String(), CHECK_0); - } else { - warning("java.lang.String not initialized"); - } + initialize_class(vmSymbols::java_lang_String(), CHECK_0); if (AggressiveOpts) { { @@ -3514,53 +3509,39 @@ jint Threads::create_vm(JavaVMInitArgs* args, bool* canTryAgain) { } // Initialize java_lang.System (needed before creating the thread) - if (InitializeJavaLangSystem) { - initialize_class(vmSymbols::java_lang_System(), CHECK_0); - initialize_class(vmSymbols::java_lang_ThreadGroup(), CHECK_0); - Handle thread_group = create_initial_thread_group(CHECK_0); - Universe::set_main_thread_group(thread_group()); - initialize_class(vmSymbols::java_lang_Thread(), CHECK_0); - oop thread_object = create_initial_thread(thread_group, main_thread, CHECK_0); - main_thread->set_threadObj(thread_object); - // Set thread status to running since main thread has - // been started and running. - java_lang_Thread::set_thread_status(thread_object, - java_lang_Thread::RUNNABLE); + initialize_class(vmSymbols::java_lang_System(), CHECK_0); + initialize_class(vmSymbols::java_lang_ThreadGroup(), CHECK_0); + Handle thread_group = create_initial_thread_group(CHECK_0); + Universe::set_main_thread_group(thread_group()); + initialize_class(vmSymbols::java_lang_Thread(), CHECK_0); + oop thread_object = create_initial_thread(thread_group, main_thread, CHECK_0); + main_thread->set_threadObj(thread_object); + // Set thread status to running since main thread has + // been started and running. + java_lang_Thread::set_thread_status(thread_object, + java_lang_Thread::RUNNABLE); - // The VM creates & returns objects of this class. Make sure it's initialized. - initialize_class(vmSymbols::java_lang_Class(), CHECK_0); + // The VM creates & returns objects of this class. Make sure it's initialized. + initialize_class(vmSymbols::java_lang_Class(), CHECK_0); - // The VM preresolves methods to these classes. Make sure that they get initialized - initialize_class(vmSymbols::java_lang_reflect_Method(), CHECK_0); - initialize_class(vmSymbols::java_lang_ref_Finalizer(), CHECK_0); - call_initializeSystemClass(CHECK_0); + // The VM preresolves methods to these classes. Make sure that they get initialized + initialize_class(vmSymbols::java_lang_reflect_Method(), CHECK_0); + initialize_class(vmSymbols::java_lang_ref_Finalizer(), CHECK_0); + call_initializeSystemClass(CHECK_0); - // get the Java runtime name after java.lang.System is initialized - JDK_Version::set_runtime_name(get_java_runtime_name(THREAD)); - JDK_Version::set_runtime_version(get_java_runtime_version(THREAD)); - } else { - warning("java.lang.System not initialized"); - } + // get the Java runtime name after java.lang.System is initialized + JDK_Version::set_runtime_name(get_java_runtime_name(THREAD)); + JDK_Version::set_runtime_version(get_java_runtime_version(THREAD)); // an instance of OutOfMemory exception has been allocated earlier - if (InitializeJavaLangExceptionsErrors) { - initialize_class(vmSymbols::java_lang_OutOfMemoryError(), CHECK_0); - initialize_class(vmSymbols::java_lang_NullPointerException(), CHECK_0); - initialize_class(vmSymbols::java_lang_ClassCastException(), CHECK_0); - initialize_class(vmSymbols::java_lang_ArrayStoreException(), CHECK_0); - initialize_class(vmSymbols::java_lang_ArithmeticException(), CHECK_0); - initialize_class(vmSymbols::java_lang_StackOverflowError(), CHECK_0); - initialize_class(vmSymbols::java_lang_IllegalMonitorStateException(), CHECK_0); - initialize_class(vmSymbols::java_lang_IllegalArgumentException(), CHECK_0); - } else { - warning("java.lang.OutOfMemoryError has not been initialized"); - warning("java.lang.NullPointerException has not been initialized"); - warning("java.lang.ClassCastException has not been initialized"); - warning("java.lang.ArrayStoreException has not been initialized"); - warning("java.lang.ArithmeticException has not been initialized"); - warning("java.lang.StackOverflowError has not been initialized"); - warning("java.lang.IllegalArgumentException has not been initialized"); - } + initialize_class(vmSymbols::java_lang_OutOfMemoryError(), CHECK_0); + initialize_class(vmSymbols::java_lang_NullPointerException(), CHECK_0); + initialize_class(vmSymbols::java_lang_ClassCastException(), CHECK_0); + initialize_class(vmSymbols::java_lang_ArrayStoreException(), CHECK_0); + initialize_class(vmSymbols::java_lang_ArithmeticException(), CHECK_0); + initialize_class(vmSymbols::java_lang_StackOverflowError(), CHECK_0); + initialize_class(vmSymbols::java_lang_IllegalMonitorStateException(), CHECK_0); + initialize_class(vmSymbols::java_lang_IllegalArgumentException(), CHECK_0); } // See : bugid 4211085. From 0614ed6542613326b7f46121e3ef1be8e7a01c59 Mon Sep 17 00:00:00 2001 From: Aleksey Shipilev Date: Mon, 14 Jan 2013 15:17:47 +0100 Subject: [PATCH 020/210] 8003985: Support @Contended Annotation - JEP 142 HotSpot changes to support @Contended annotation. Reviewed-by: coleenp, kvn, jrose --- .../sun/jvm/hotspot/oops/InstanceKlass.java | 17 +- hotspot/src/cpu/sparc/vm/vm_version_sparc.cpp | 7 + hotspot/src/cpu/x86/vm/vm_version_x86.cpp | 7 + .../share/vm/classfile/classFileParser.cpp | 451 +++++++++++++++--- .../share/vm/classfile/classFileParser.hpp | 22 +- hotspot/src/share/vm/classfile/vmSymbols.hpp | 5 +- hotspot/src/share/vm/oops/fieldInfo.hpp | 144 +++++- hotspot/src/share/vm/oops/fieldStreams.hpp | 17 + hotspot/src/share/vm/oops/instanceKlass.hpp | 14 +- hotspot/src/share/vm/runtime/globals.hpp | 14 +- hotspot/src/share/vm/runtime/vmStructs.cpp | 11 +- 11 files changed, 617 insertions(+), 92 deletions(-) diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/InstanceKlass.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/InstanceKlass.java index ba07fa34800..7052f8a2d18 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/InstanceKlass.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/InstanceKlass.java @@ -52,6 +52,8 @@ public class InstanceKlass extends Klass { private static int LOW_OFFSET; private static int HIGH_OFFSET; private static int FIELD_SLOTS; + private static short FIELDINFO_TAG_SIZE; + private static short FIELDINFO_TAG_OFFSET; // ClassState constants private static int CLASS_STATE_ALLOCATED; @@ -96,9 +98,12 @@ public class InstanceKlass extends Klass { NAME_INDEX_OFFSET = db.lookupIntConstant("FieldInfo::name_index_offset").intValue(); SIGNATURE_INDEX_OFFSET = db.lookupIntConstant("FieldInfo::signature_index_offset").intValue(); INITVAL_INDEX_OFFSET = db.lookupIntConstant("FieldInfo::initval_index_offset").intValue(); - LOW_OFFSET = db.lookupIntConstant("FieldInfo::low_offset").intValue(); - HIGH_OFFSET = db.lookupIntConstant("FieldInfo::high_offset").intValue(); + LOW_OFFSET = db.lookupIntConstant("FieldInfo::low_packed_offset").intValue(); + HIGH_OFFSET = db.lookupIntConstant("FieldInfo::high_packed_offset").intValue(); FIELD_SLOTS = db.lookupIntConstant("FieldInfo::field_slots").intValue(); + FIELDINFO_TAG_SIZE = db.lookupIntConstant("FIELDINFO_TAG_SIZE").shortValue(); + FIELDINFO_TAG_OFFSET = db.lookupIntConstant("FIELDINFO_TAG_OFFSET").shortValue(); + // read ClassState constants CLASS_STATE_ALLOCATED = db.lookupIntConstant("InstanceKlass::allocated").intValue(); CLASS_STATE_LOADED = db.lookupIntConstant("InstanceKlass::loaded").intValue(); @@ -314,8 +319,12 @@ public class InstanceKlass extends Klass { public int getFieldOffset(int index) { U2Array fields = getFields(); - return VM.getVM().buildIntFromShorts(fields.at(index * FIELD_SLOTS + LOW_OFFSET), - fields.at(index * FIELD_SLOTS + HIGH_OFFSET)); + short lo = fields.at(index * FIELD_SLOTS + LOW_OFFSET); + short hi = fields.at(index * FIELD_SLOTS + HIGH_OFFSET); + if ((lo & FIELDINFO_TAG_SIZE) == FIELDINFO_TAG_OFFSET) { + return VM.getVM().buildIntFromShorts(lo, hi) >> FIELDINFO_TAG_SIZE; + } + throw new RuntimeException("should not reach here"); } // Accessors for declared fields diff --git a/hotspot/src/cpu/sparc/vm/vm_version_sparc.cpp b/hotspot/src/cpu/sparc/vm/vm_version_sparc.cpp index 7d3becef336..03670106924 100644 --- a/hotspot/src/cpu/sparc/vm/vm_version_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/vm_version_sparc.cpp @@ -259,6 +259,10 @@ void VM_Version::initialize() { if (!has_vis1()) // Drop to 0 if no VIS1 support UseVIS = 0; + if (FLAG_IS_DEFAULT(ContendedPaddingWidth) && + (cache_line_size > ContendedPaddingWidth)) + ContendedPaddingWidth = cache_line_size; + #ifndef PRODUCT if (PrintMiscellaneous && Verbose) { tty->print("Allocation"); @@ -286,6 +290,9 @@ void VM_Version::initialize() { if (PrefetchFieldsAhead > 0) { tty->print_cr("PrefetchFieldsAhead %d", PrefetchFieldsAhead); } + if (ContendedPaddingWidth > 0) { + tty->print_cr("ContendedPaddingWidth %d", ContendedPaddingWidth); + } } #endif // PRODUCT } diff --git a/hotspot/src/cpu/x86/vm/vm_version_x86.cpp b/hotspot/src/cpu/x86/vm/vm_version_x86.cpp index fc046676739..41f5ec2cdc7 100644 --- a/hotspot/src/cpu/x86/vm/vm_version_x86.cpp +++ b/hotspot/src/cpu/x86/vm/vm_version_x86.cpp @@ -734,6 +734,10 @@ void VM_Version::get_processor_features() { PrefetchFieldsAhead = prefetch_fields_ahead(); #endif + if (FLAG_IS_DEFAULT(ContendedPaddingWidth) && + (cache_line_size > ContendedPaddingWidth)) + ContendedPaddingWidth = cache_line_size; + #ifndef PRODUCT if (PrintMiscellaneous && Verbose) { tty->print_cr("Logical CPUs per core: %u", @@ -780,6 +784,9 @@ void VM_Version::get_processor_features() { if (PrefetchFieldsAhead > 0) { tty->print_cr("PrefetchFieldsAhead %d", PrefetchFieldsAhead); } + if (ContendedPaddingWidth > 0) { + tty->print_cr("ContendedPaddingWidth %d", ContendedPaddingWidth); + } } #endif // !PRODUCT } diff --git a/hotspot/src/share/vm/classfile/classFileParser.cpp b/hotspot/src/share/vm/classfile/classFileParser.cpp index efb6138e583..af9700f25cb 100644 --- a/hotspot/src/share/vm/classfile/classFileParser.cpp +++ b/hotspot/src/share/vm/classfile/classFileParser.cpp @@ -970,6 +970,12 @@ void ClassFileParser::parse_field_attributes(ClassLoaderData* loader_data, runtime_visible_annotations_length = attribute_length; runtime_visible_annotations = cfs->get_u1_buffer(); assert(runtime_visible_annotations != NULL, "null visible annotations"); + parse_annotations(loader_data, + runtime_visible_annotations, + runtime_visible_annotations_length, + cp, + parsed_annotations, + CHECK); cfs->skip_u1(runtime_visible_annotations_length, CHECK); } else if (PreserveAllAnnotations && attribute_name == vmSymbols::tag_runtime_invisible_annotations()) { runtime_invisible_annotations_length = attribute_length; @@ -1216,19 +1222,16 @@ Array* ClassFileParser::parse_fields(ClassLoaderData* loader_data, field->initialize(access_flags.as_short(), name_index, signature_index, - constantvalue_index, - 0); - if (parsed_annotations.has_any_annotations()) - parsed_annotations.apply_to(field); - + constantvalue_index); BasicType type = cp->basic_type_for_signature_at(signature_index); // Remember how many oops we encountered and compute allocation type FieldAllocationType atype = fac->update(is_static, type); + field->set_allocation_type(atype); - // The correct offset is computed later (all oop fields will be located together) - // We temporarily store the allocation type in the offset field - field->set_offset(atype); + // After field is initialized with type, we can augment it with aux info + if (parsed_annotations.has_any_annotations()) + parsed_annotations.apply_to(field); } int index = length; @@ -1259,17 +1262,13 @@ Array* ClassFileParser::parse_fields(ClassLoaderData* loader_data, field->initialize(JVM_ACC_FIELD_INTERNAL, injected[n].name_index, injected[n].signature_index, - 0, 0); BasicType type = FieldType::basic_type(injected[n].signature()); // Remember how many oops we encountered and compute allocation type FieldAllocationType atype = fac->update(false, type); - - // The correct offset is computed later (all oop fields will be located together) - // We temporarily store the allocation type in the offset field - field->set_offset(atype); + field->set_allocation_type(atype); index++; } } @@ -1735,7 +1734,8 @@ int ClassFileParser::skip_annotation_value(u1* buffer, int limit, int index) { } // Sift through annotations, looking for those significant to the VM: -void ClassFileParser::parse_annotations(u1* buffer, int limit, +void ClassFileParser::parse_annotations(ClassLoaderData* loader_data, + u1* buffer, int limit, constantPoolHandle cp, ClassFileParser::AnnotationCollector* coll, TRAPS) { @@ -1752,9 +1752,12 @@ void ClassFileParser::parse_annotations(u1* buffer, int limit, e_type_off = 7, // utf8 such as 'Ljava/lang/annotation/RetentionPolicy;' e_con_off = 9, // utf8 payload, such as 'SOURCE', 'CLASS', 'RUNTIME' e_size = 11, // end of 'e' annotation - c_tag_val = 'c', - c_con_off = 7, // utf8 payload, such as 'I' or 'Ljava/lang/String;' + c_tag_val = 'c', // payload is type + c_con_off = 7, // utf8 payload, such as 'I' c_size = 9, // end of 'c' annotation + s_tag_val = 's', // payload is String + s_con_off = 7, // utf8 payload, such as 'Ljava/lang/String;' + s_size = 9, min_size = 6 // smallest possible size (zero members) }; while ((--nann) >= 0 && (index-2 + min_size <= limit)) { @@ -1773,57 +1776,65 @@ void ClassFileParser::parse_annotations(u1* buffer, int limit, } // Here is where parsing particular annotations will take place. - AnnotationCollector::ID id = coll->annotation_index(aname); + AnnotationCollector::ID id = coll->annotation_index(loader_data, aname); if (id == AnnotationCollector::_unknown) continue; coll->set_annotation(id); - // If there are no values, just set the bit and move on: - if (count == 0) continue; - // For the record, here is how annotation payloads can be collected. - // Suppose we want to capture @Retention.value. Here is how: - //if (id == AnnotationCollector::_class_Retention) { - // Symbol* payload = NULL; - // if (count == 1 - // && e_size == (index0 - index) // match size - // && e_tag_val == *(abase + tag_off) - // && (check_symbol_at(cp, Bytes::get_Java_u2(abase + e_type_off)) - // == vmSymbols::RetentionPolicy_signature()) - // && member == vmSymbols::value_name()) { - // payload = check_symbol_at(cp, Bytes::get_Java_u2(abase + e_con_off)); - // } - // check_property(payload != NULL, - // "Invalid @Retention annotation at offset %u in class file %s", - // index0, CHECK); - // if (payload != NULL) { - // payload->increment_refcount(); - // coll->_class_RetentionPolicy = payload; - // } - //} + if (id == AnnotationCollector::_sun_misc_Contended) { + if (count == 1 + && s_size == (index - index0) // match size + && s_tag_val == *(abase + tag_off) + && member == vmSymbols::value_name()) { + u2 group_index = Bytes::get_Java_u2(abase + s_con_off); + coll->set_contended_group(group_index); + } else { + coll->set_contended_group(0); // default contended group + } + coll->set_contended(true); + } else { + coll->set_contended(false); + } } } -ClassFileParser::AnnotationCollector::ID ClassFileParser::AnnotationCollector::annotation_index(Symbol* name) { +ClassFileParser::AnnotationCollector::ID +ClassFileParser::AnnotationCollector::annotation_index(ClassLoaderData* loader_data, + Symbol* name) { vmSymbols::SID sid = vmSymbols::find_sid(name); + bool privileged = false; + if (loader_data->is_the_null_class_loader_data()) { + // Privileged code can use all annotations. Other code silently drops some. + privileged = true; + } switch (sid) { case vmSymbols::VM_SYMBOL_ENUM_NAME(java_lang_invoke_ForceInline_signature): if (_location != _in_method) break; // only allow for methods + if (!privileged) break; // only allow in privileged code return _method_ForceInline; case vmSymbols::VM_SYMBOL_ENUM_NAME(java_lang_invoke_DontInline_signature): if (_location != _in_method) break; // only allow for methods + if (!privileged) break; // only allow in privileged code return _method_DontInline; case vmSymbols::VM_SYMBOL_ENUM_NAME(java_lang_invoke_LambdaForm_Compiled_signature): if (_location != _in_method) break; // only allow for methods + if (!privileged) break; // only allow in privileged code return _method_LambdaForm_Compiled; case vmSymbols::VM_SYMBOL_ENUM_NAME(java_lang_invoke_LambdaForm_Hidden_signature): if (_location != _in_method) break; // only allow for methods + if (!privileged) break; // only allow in privileged code return _method_LambdaForm_Hidden; + case vmSymbols::VM_SYMBOL_ENUM_NAME(sun_misc_Contended_signature): + if (_location != _in_field && _location != _in_class) break; // only allow for fields and classes + if (!EnableContended || (RestrictContended && !privileged)) break; // honor privileges + return _sun_misc_Contended; default: break; } return AnnotationCollector::_unknown; } void ClassFileParser::FieldAnnotationCollector::apply_to(FieldInfo* f) { - fatal("no field annotations yet"); + if (is_contended()) + f->set_contended_group(contended_group()); } void ClassFileParser::MethodAnnotationCollector::apply_to(methodHandle m) { @@ -1838,7 +1849,7 @@ void ClassFileParser::MethodAnnotationCollector::apply_to(methodHandle m) { } void ClassFileParser::ClassAnnotationCollector::apply_to(instanceKlassHandle k) { - fatal("no class annotations yet"); + k->set_is_contended(is_contended()); } @@ -2181,7 +2192,8 @@ methodHandle ClassFileParser::parse_method(ClassLoaderData* loader_data, runtime_visible_annotations_length = method_attribute_length; runtime_visible_annotations = cfs->get_u1_buffer(); assert(runtime_visible_annotations != NULL, "null visible annotations"); - parse_annotations(runtime_visible_annotations, + parse_annotations(loader_data, + runtime_visible_annotations, runtime_visible_annotations_length, cp, &parsed_annotations, CHECK_(nullHandle)); cfs->skip_u1(runtime_visible_annotations_length, CHECK_(nullHandle)); @@ -2886,7 +2898,8 @@ void ClassFileParser::parse_classfile_attributes(ClassLoaderData* loader_data, runtime_visible_annotations_length = attribute_length; runtime_visible_annotations = cfs->get_u1_buffer(); assert(runtime_visible_annotations != NULL, "null visible annotations"); - parse_annotations(runtime_visible_annotations, + parse_annotations(loader_data, + runtime_visible_annotations, runtime_visible_annotations_length, cp, parsed_annotations, @@ -3405,18 +3418,21 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name, // Size of Java itable (in words) itable_size = access_flags.is_interface() ? 0 : klassItable::compute_itable_size(transitive_interfaces); + // get the padding width from the option + // TODO: Ask VM about specific CPU we are running on + int pad_size = ContendedPaddingWidth; + // Field size and offset computation int nonstatic_field_size = super_klass() == NULL ? 0 : super_klass->nonstatic_field_size(); #ifndef PRODUCT int orig_nonstatic_field_size = 0; #endif - int static_field_size = 0; int next_static_oop_offset; int next_static_double_offset; int next_static_word_offset; int next_static_short_offset; int next_static_byte_offset; - int next_static_type_offset; + int next_static_padded_offset; int next_nonstatic_oop_offset; int next_nonstatic_double_offset; int next_nonstatic_word_offset; @@ -3426,11 +3442,36 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name, int first_nonstatic_oop_offset; int first_nonstatic_field_offset; int next_nonstatic_field_offset; + int next_nonstatic_padded_offset; + + // Count the contended fields by type. + int static_contended_count = 0; + int nonstatic_contended_count = 0; + FieldAllocationCount fac_contended; + for (AllFieldStream fs(fields, cp); !fs.done(); fs.next()) { + FieldAllocationType atype = (FieldAllocationType) fs.allocation_type(); + if (fs.is_contended()) { + fac_contended.count[atype]++; + if (fs.access_flags().is_static()) { + static_contended_count++; + } else { + nonstatic_contended_count++; + } + } + } + int contended_count = static_contended_count + nonstatic_contended_count; + // Calculate the starting byte offsets next_static_oop_offset = InstanceMirrorKlass::offset_of_static_fields(); + + // class is contended, pad before all the fields + if (parsed_annotations.is_contended()) { + next_static_oop_offset += pad_size; + } + next_static_double_offset = next_static_oop_offset + - (fac.count[STATIC_OOP] * heapOopSize); + ((fac.count[STATIC_OOP] - fac_contended.count[STATIC_OOP]) * heapOopSize); if ( fac.count[STATIC_DOUBLE] && (Universe::field_type_should_be_aligned(T_DOUBLE) || Universe::field_type_should_be_aligned(T_LONG)) ) { @@ -3438,25 +3479,29 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name, } next_static_word_offset = next_static_double_offset + - (fac.count[STATIC_DOUBLE] * BytesPerLong); + ((fac.count[STATIC_DOUBLE] - fac_contended.count[STATIC_DOUBLE]) * BytesPerLong); next_static_short_offset = next_static_word_offset + - (fac.count[STATIC_WORD] * BytesPerInt); + ((fac.count[STATIC_WORD] - fac_contended.count[STATIC_WORD]) * BytesPerInt); next_static_byte_offset = next_static_short_offset + - (fac.count[STATIC_SHORT] * BytesPerShort); - next_static_type_offset = align_size_up((next_static_byte_offset + - fac.count[STATIC_BYTE] ), wordSize ); - static_field_size = (next_static_type_offset - - next_static_oop_offset) / wordSize; + ((fac.count[STATIC_SHORT] - fac_contended.count[STATIC_SHORT]) * BytesPerShort); + next_static_padded_offset = next_static_byte_offset + + ((fac.count[STATIC_BYTE] - fac_contended.count[STATIC_BYTE]) * 1); first_nonstatic_field_offset = instanceOopDesc::base_offset_in_bytes() + nonstatic_field_size * heapOopSize; + + // class is contended, pad before all the fields + if (parsed_annotations.is_contended()) { + first_nonstatic_field_offset += pad_size; + } + next_nonstatic_field_offset = first_nonstatic_field_offset; - unsigned int nonstatic_double_count = fac.count[NONSTATIC_DOUBLE]; - unsigned int nonstatic_word_count = fac.count[NONSTATIC_WORD]; - unsigned int nonstatic_short_count = fac.count[NONSTATIC_SHORT]; - unsigned int nonstatic_byte_count = fac.count[NONSTATIC_BYTE]; - unsigned int nonstatic_oop_count = fac.count[NONSTATIC_OOP]; + unsigned int nonstatic_double_count = fac.count[NONSTATIC_DOUBLE] - fac_contended.count[NONSTATIC_DOUBLE]; + unsigned int nonstatic_word_count = fac.count[NONSTATIC_WORD] - fac_contended.count[NONSTATIC_WORD]; + unsigned int nonstatic_short_count = fac.count[NONSTATIC_SHORT] - fac_contended.count[NONSTATIC_SHORT]; + unsigned int nonstatic_byte_count = fac.count[NONSTATIC_BYTE] - fac_contended.count[NONSTATIC_BYTE]; + unsigned int nonstatic_oop_count = fac.count[NONSTATIC_OOP] - fac_contended.count[NONSTATIC_OOP]; bool super_has_nonstatic_fields = (super_klass() != NULL && super_klass->has_nonstatic_fields()); @@ -3529,12 +3574,12 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name, } if( allocation_style == 0 ) { - // Fields order: oops, longs/doubles, ints, shorts/chars, bytes + // Fields order: oops, longs/doubles, ints, shorts/chars, bytes, padded fields next_nonstatic_oop_offset = next_nonstatic_field_offset; next_nonstatic_double_offset = next_nonstatic_oop_offset + (nonstatic_oop_count * heapOopSize); } else if( allocation_style == 1 ) { - // Fields order: longs/doubles, ints, shorts/chars, bytes, oops + // Fields order: longs/doubles, ints, shorts/chars, bytes, oops, padded fields next_nonstatic_double_offset = next_nonstatic_field_offset; } else if( allocation_style == 2 ) { // Fields allocation: oops fields in super and sub classes are together. @@ -3613,27 +3658,33 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name, (nonstatic_word_count * BytesPerInt); next_nonstatic_byte_offset = next_nonstatic_short_offset + (nonstatic_short_count * BytesPerShort); + next_nonstatic_padded_offset = next_nonstatic_byte_offset + + nonstatic_byte_count; - int notaligned_offset; - if( allocation_style == 0 ) { - notaligned_offset = next_nonstatic_byte_offset + nonstatic_byte_count; - } else { // allocation_style == 1 - next_nonstatic_oop_offset = next_nonstatic_byte_offset + nonstatic_byte_count; + // let oops jump before padding with this allocation style + if( allocation_style == 1 ) { + next_nonstatic_oop_offset = next_nonstatic_padded_offset; if( nonstatic_oop_count > 0 ) { next_nonstatic_oop_offset = align_size_up(next_nonstatic_oop_offset, heapOopSize); } - notaligned_offset = next_nonstatic_oop_offset + (nonstatic_oop_count * heapOopSize); + next_nonstatic_padded_offset = next_nonstatic_oop_offset + (nonstatic_oop_count * heapOopSize); } - next_nonstatic_type_offset = align_size_up(notaligned_offset, heapOopSize ); - nonstatic_field_size = nonstatic_field_size + ((next_nonstatic_type_offset - - first_nonstatic_field_offset)/heapOopSize); // Iterate over fields again and compute correct offsets. // The field allocation type was temporarily stored in the offset slot. // oop fields are located before non-oop fields (static and non-static). for (AllFieldStream fs(fields, cp); !fs.done(); fs.next()) { + + // skip already laid out fields + if (fs.is_offset_set()) continue; + + // contended fields are handled below + if (fs.is_contended()) continue; + int real_offset; - FieldAllocationType atype = (FieldAllocationType) fs.offset(); + FieldAllocationType atype = (FieldAllocationType) fs.allocation_type(); + + // pack the rest of the fields switch (atype) { case STATIC_OOP: real_offset = next_static_oop_offset; @@ -3722,13 +3773,225 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name, fs.set_offset(real_offset); } + + // Handle the contended cases. + // + // Each contended field should not intersect the cache line with another contended field. + // In the absence of alignment information, we end up with pessimistically separating + // the fields with full-width padding. + // + // Additionally, this should not break alignment for the fields, so we round the alignment up + // for each field. + if (contended_count > 0) { + + // if there is at least one contended field, we need to have pre-padding for them + if (nonstatic_contended_count > 0) { + next_nonstatic_padded_offset += pad_size; + } + + // collect all contended groups + BitMap bm(cp->size()); + for (AllFieldStream fs(fields, cp); !fs.done(); fs.next()) { + // skip already laid out fields + if (fs.is_offset_set()) continue; + + if (fs.is_contended()) { + bm.set_bit(fs.contended_group()); + } + } + + int current_group = -1; + while ((current_group = (int)bm.get_next_one_offset(current_group + 1)) != (int)bm.size()) { + + for (AllFieldStream fs(fields, cp); !fs.done(); fs.next()) { + + // skip already laid out fields + if (fs.is_offset_set()) continue; + + // skip non-contended fields and fields from different group + if (!fs.is_contended() || (fs.contended_group() != current_group)) continue; + + // handle statics below + if (fs.access_flags().is_static()) continue; + + int real_offset; + FieldAllocationType atype = (FieldAllocationType) fs.allocation_type(); + + switch (atype) { + case NONSTATIC_BYTE: + next_nonstatic_padded_offset = align_size_up(next_nonstatic_padded_offset, 1); + real_offset = next_nonstatic_padded_offset; + next_nonstatic_padded_offset += 1; + break; + + case NONSTATIC_SHORT: + next_nonstatic_padded_offset = align_size_up(next_nonstatic_padded_offset, BytesPerShort); + real_offset = next_nonstatic_padded_offset; + next_nonstatic_padded_offset += BytesPerShort; + break; + + case NONSTATIC_WORD: + next_nonstatic_padded_offset = align_size_up(next_nonstatic_padded_offset, BytesPerInt); + real_offset = next_nonstatic_padded_offset; + next_nonstatic_padded_offset += BytesPerInt; + break; + + case NONSTATIC_DOUBLE: + next_nonstatic_padded_offset = align_size_up(next_nonstatic_padded_offset, BytesPerLong); + real_offset = next_nonstatic_padded_offset; + next_nonstatic_padded_offset += BytesPerLong; + break; + + case NONSTATIC_OOP: + next_nonstatic_padded_offset = align_size_up(next_nonstatic_padded_offset, heapOopSize); + real_offset = next_nonstatic_padded_offset; + next_nonstatic_padded_offset += heapOopSize; + + // Create new oop map + nonstatic_oop_offsets[nonstatic_oop_map_count] = real_offset; + nonstatic_oop_counts [nonstatic_oop_map_count] = 1; + nonstatic_oop_map_count += 1; + if( first_nonstatic_oop_offset == 0 ) { // Undefined + first_nonstatic_oop_offset = real_offset; + } + break; + + default: + ShouldNotReachHere(); + } + + if (fs.contended_group() == 0) { + // Contended group defines the equivalence class over the fields: + // the fields within the same contended group are not inter-padded. + // The only exception is default group, which does not incur the + // equivalence, and so requires intra-padding. + next_nonstatic_padded_offset += pad_size; + } + + fs.set_offset(real_offset); + } // for + + // Start laying out the next group. + // Note that this will effectively pad the last group in the back; + // this is expected to alleviate memory contention effects for + // subclass fields and/or adjacent object. + // If this was the default group, the padding is already in place. + if (current_group != 0) { + next_nonstatic_padded_offset += pad_size; + } + } + + // handle static fields + + // if there is at least one contended field, we need to have pre-padding for them + if (static_contended_count > 0) { + next_static_padded_offset += pad_size; + } + + current_group = -1; + while ((current_group = (int)bm.get_next_one_offset(current_group + 1)) != (int)bm.size()) { + + for (AllFieldStream fs(fields, cp); !fs.done(); fs.next()) { + + // skip already laid out fields + if (fs.is_offset_set()) continue; + + // skip non-contended fields and fields from different group + if (!fs.is_contended() || (fs.contended_group() != current_group)) continue; + + // non-statics already handled above + if (!fs.access_flags().is_static()) continue; + + int real_offset; + FieldAllocationType atype = (FieldAllocationType) fs.allocation_type(); + + switch (atype) { + + case STATIC_BYTE: + next_static_padded_offset = align_size_up(next_static_padded_offset, 1); + real_offset = next_static_padded_offset; + next_static_padded_offset += 1; + break; + + case STATIC_SHORT: + next_static_padded_offset = align_size_up(next_static_padded_offset, BytesPerShort); + real_offset = next_static_padded_offset; + next_static_padded_offset += BytesPerShort; + break; + + case STATIC_WORD: + next_static_padded_offset = align_size_up(next_static_padded_offset, BytesPerInt); + real_offset = next_static_padded_offset; + next_static_padded_offset += BytesPerInt; + break; + + case STATIC_DOUBLE: + next_static_padded_offset = align_size_up(next_static_padded_offset, BytesPerLong); + real_offset = next_static_padded_offset; + next_static_padded_offset += BytesPerLong; + break; + + case STATIC_OOP: + next_static_padded_offset = align_size_up(next_static_padded_offset, heapOopSize); + real_offset = next_static_padded_offset; + next_static_padded_offset += heapOopSize; + break; + + default: + ShouldNotReachHere(); + } + + if (fs.contended_group() == 0) { + // Contended group defines the equivalence class over the fields: + // the fields within the same contended group are not inter-padded. + // The only exception is default group, which does not incur the + // equivalence, and so requires intra-padding. + next_static_padded_offset += pad_size; + } + + fs.set_offset(real_offset); + } // for + + // Start laying out the next group. + // Note that this will effectively pad the last group in the back; + // this is expected to alleviate memory contention effects for + // subclass fields and/or adjacent object. + // If this was the default group, the padding is already in place. + if (current_group != 0) { + next_static_padded_offset += pad_size; + } + + } + + } // handle contended + // Size of instances int instance_size; + int notaligned_offset = next_nonstatic_padded_offset; + + // Entire class is contended, pad in the back. + // This helps to alleviate memory contention effects for subclass fields + // and/or adjacent object. + if (parsed_annotations.is_contended()) { + notaligned_offset += pad_size; + next_static_padded_offset += pad_size; + } + + int next_static_type_offset = align_size_up(next_static_padded_offset, wordSize); + int static_field_size = (next_static_type_offset - + InstanceMirrorKlass::offset_of_static_fields()) / wordSize; + + next_nonstatic_type_offset = align_size_up(notaligned_offset, heapOopSize ); + nonstatic_field_size = nonstatic_field_size + ((next_nonstatic_type_offset + - first_nonstatic_field_offset)/heapOopSize); + next_nonstatic_type_offset = align_size_up(notaligned_offset, wordSize ); instance_size = align_object_size(next_nonstatic_type_offset / wordSize); - assert(instance_size == align_object_size(align_size_up((instanceOopDesc::base_offset_in_bytes() + nonstatic_field_size*heapOopSize), wordSize) / wordSize), "consistent layout helper value"); + assert(instance_size == align_object_size(align_size_up( + (instanceOopDesc::base_offset_in_bytes() + nonstatic_field_size*heapOopSize + ((parsed_annotations.is_contended()) ? pad_size : 0)), + wordSize) / wordSize), "consistent layout helper value"); // Number of non-static oop map blocks allocated at end of klass. const unsigned int total_oop_map_count = @@ -4008,6 +4271,18 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name, } #endif +#ifndef PRODUCT + if (PrintFieldLayout) { + print_field_layout(name, + fields, + cp, + instance_size, + first_nonstatic_field_offset, + next_nonstatic_field_offset, + next_static_type_offset); + } +#endif + // preserve result across HandleMark preserve_this_klass = this_klass(); } @@ -4020,6 +4295,38 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name, return this_klass; } +void ClassFileParser::print_field_layout(Symbol* name, + Array* fields, + constantPoolHandle cp, + int instance_size, + int instance_fields_start, + int instance_fields_end, + int static_fields_end) { + tty->print("%s: field layout\n", name->as_klass_external_name()); + tty->print(" @%3d %s\n", instance_fields_start, "--- instance fields start ---"); + for (AllFieldStream fs(fields, cp); !fs.done(); fs.next()) { + if (!fs.access_flags().is_static()) { + tty->print(" @%3d \"%s\" %s\n", + fs.offset(), + fs.name()->as_klass_external_name(), + fs.signature()->as_klass_external_name()); + } + } + tty->print(" @%3d %s\n", instance_fields_end, "--- instance fields end ---"); + tty->print(" @%3d %s\n", instance_size * wordSize, "--- instance ends ---"); + tty->print(" @%3d %s\n", InstanceMirrorKlass::offset_of_static_fields(), "--- static fields start ---"); + for (AllFieldStream fs(fields, cp); !fs.done(); fs.next()) { + if (fs.access_flags().is_static()) { + tty->print(" @%3d \"%s\" %s\n", + fs.offset(), + fs.name()->as_klass_external_name(), + fs.signature()->as_klass_external_name()); + } + } + tty->print(" @%3d %s\n", static_fields_end, "--- static fields end ---"); + tty->print("\n"); +} + unsigned int ClassFileParser::compute_oop_map_count(instanceKlassHandle super, unsigned int nonstatic_oop_map_count, diff --git a/hotspot/src/share/vm/classfile/classFileParser.hpp b/hotspot/src/share/vm/classfile/classFileParser.hpp index 5a5d3fc397a..cc0193a15f5 100644 --- a/hotspot/src/share/vm/classfile/classFileParser.hpp +++ b/hotspot/src/share/vm/classfile/classFileParser.hpp @@ -95,17 +95,20 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC { _method_DontInline, _method_LambdaForm_Compiled, _method_LambdaForm_Hidden, + _sun_misc_Contended, _annotation_LIMIT }; const Location _location; int _annotations_present; + u2 _contended_group; + AnnotationCollector(Location location) : _location(location), _annotations_present(0) { assert((int)_annotation_LIMIT <= (int)sizeof(_annotations_present) * BitsPerByte, ""); } // If this annotation name has an ID, report it (or _none). - ID annotation_index(Symbol* name); + ID annotation_index(ClassLoaderData* loader_data, Symbol* name); // Set the annotation name: void set_annotation(ID id) { assert((int)id >= 0 && (int)id < (int)_annotation_LIMIT, "oob"); @@ -114,6 +117,12 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC { // Report if the annotation is present. bool has_any_annotations() { return _annotations_present != 0; } bool has_annotation(ID id) { return (nth_bit((int)id) & _annotations_present) != 0; } + + void set_contended_group(u2 group) { _contended_group = group; } + u2 contended_group() { return _contended_group; } + + void set_contended(bool contended) { set_annotation(_sun_misc_Contended); } + bool is_contended() { return has_annotation(_sun_misc_Contended); } }; class FieldAnnotationCollector: public AnnotationCollector { public: @@ -177,6 +186,14 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC { Array** fields_type_annotations, u2* java_fields_count_ptr, TRAPS); + void print_field_layout(Symbol* name, + Array* fields, + constantPoolHandle cp, + int instance_size, + int instance_fields_start, + int instance_fields_end, + int static_fields_end); + // Method parsing methodHandle parse_method(ClassLoaderData* loader_data, constantPoolHandle cp, @@ -247,7 +264,8 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC { int runtime_invisible_annotations_length, TRAPS); int skip_annotation(u1* buffer, int limit, int index); int skip_annotation_value(u1* buffer, int limit, int index); - void parse_annotations(u1* buffer, int limit, constantPoolHandle cp, + void parse_annotations(ClassLoaderData* loader_data, + u1* buffer, int limit, constantPoolHandle cp, /* Results (currently, only one result is supported): */ AnnotationCollector* result, TRAPS); diff --git a/hotspot/src/share/vm/classfile/vmSymbols.hpp b/hotspot/src/share/vm/classfile/vmSymbols.hpp index e6168ceba2c..e77e5cea2db 100644 --- a/hotspot/src/share/vm/classfile/vmSymbols.hpp +++ b/hotspot/src/share/vm/classfile/vmSymbols.hpp @@ -194,7 +194,10 @@ template(java_lang_VirtualMachineError, "java/lang/VirtualMachineError") \ template(java_lang_StackOverflowError, "java/lang/StackOverflowError") \ template(java_lang_StackTraceElement, "java/lang/StackTraceElement") \ + \ + /* Concurrency support */ \ template(java_util_concurrent_locks_AbstractOwnableSynchronizer, "java/util/concurrent/locks/AbstractOwnableSynchronizer") \ + template(sun_misc_Contended_signature, "Lsun/misc/Contended;") \ \ /* class symbols needed by intrinsics */ \ VM_INTRINSICS_DO(VM_INTRINSIC_IGNORE, template, VM_SYMBOL_IGNORE, VM_SYMBOL_IGNORE, VM_ALIAS_IGNORE) \ @@ -284,7 +287,7 @@ NOT_LP64( do_alias(intptr_signature, int_signature) ) \ LP64_ONLY( do_alias(intptr_signature, long_signature) ) \ template(selectAlternative_signature, "(ZLjava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodHandle;)Ljava/lang/invoke/MethodHandle;") \ - \ + \ /* common method and field names */ \ template(object_initializer_name, "") \ template(class_initializer_name, "") \ diff --git a/hotspot/src/share/vm/oops/fieldInfo.hpp b/hotspot/src/share/vm/oops/fieldInfo.hpp index ee4af47204d..331dc05f37c 100644 --- a/hotspot/src/share/vm/oops/fieldInfo.hpp +++ b/hotspot/src/share/vm/oops/fieldInfo.hpp @@ -43,14 +43,29 @@ class FieldInfo VALUE_OBJ_CLASS_SPEC { public: // fields // Field info extracted from the class file and stored - // as an array of 7 shorts + // as an array of 6 shorts. + +#define FIELDINFO_TAG_SIZE 2 +#define FIELDINFO_TAG_BLANK 0 +#define FIELDINFO_TAG_OFFSET 1 +#define FIELDINFO_TAG_TYPE_PLAIN 2 +#define FIELDINFO_TAG_TYPE_CONTENDED 3 +#define FIELDINFO_TAG_MASK 3 + + // Packed field has the tag, and can be either of: + // hi bits <--------------------------- lo bits + // |---------high---------|---------low---------| + // ..........................................00 - blank + // [------------------offset----------------]01 - real field offset + // ......................[-------type-------]10 - plain field with type + // [--contention_group--][-------type-------]11 - contended field with type and contention group enum FieldOffset { access_flags_offset = 0, name_index_offset = 1, signature_index_offset = 2, initval_index_offset = 3, - low_offset = 4, - high_offset = 5, + low_packed_offset = 4, + high_packed_offset = 5, field_slots = 6 }; @@ -76,17 +91,90 @@ class FieldInfo VALUE_OBJ_CLASS_SPEC { void initialize(u2 access_flags, u2 name_index, u2 signature_index, - u2 initval_index, - u4 offset) { + u2 initval_index) { _shorts[access_flags_offset] = access_flags; _shorts[name_index_offset] = name_index; _shorts[signature_index_offset] = signature_index; _shorts[initval_index_offset] = initval_index; - set_offset(offset); + _shorts[low_packed_offset] = 0; + _shorts[high_packed_offset] = 0; } u2 access_flags() const { return _shorts[access_flags_offset]; } - u4 offset() const { return build_int_from_shorts(_shorts[low_offset], _shorts[high_offset]); } + u4 offset() const { + u2 lo = _shorts[low_packed_offset]; + switch(lo & FIELDINFO_TAG_MASK) { + case FIELDINFO_TAG_OFFSET: + return build_int_from_shorts(_shorts[low_packed_offset], _shorts[high_packed_offset]) >> FIELDINFO_TAG_SIZE; +#ifndef PRODUCT + case FIELDINFO_TAG_TYPE_PLAIN: + ShouldNotReachHere2("Asking offset for the plain type field"); + case FIELDINFO_TAG_TYPE_CONTENDED: + ShouldNotReachHere2("Asking offset for the contended type field"); + case FIELDINFO_TAG_BLANK: + ShouldNotReachHere2("Asking offset for the blank field"); +#endif + } + ShouldNotReachHere(); + return 0; + } + + bool is_contended() const { + u2 lo = _shorts[low_packed_offset]; + switch(lo & FIELDINFO_TAG_MASK) { + case FIELDINFO_TAG_TYPE_PLAIN: + return false; + case FIELDINFO_TAG_TYPE_CONTENDED: + return true; +#ifndef PRODUCT + case FIELDINFO_TAG_OFFSET: + ShouldNotReachHere2("Asking contended flag for the field with offset"); + case FIELDINFO_TAG_BLANK: + ShouldNotReachHere2("Asking contended flag for the blank field"); +#endif + } + ShouldNotReachHere(); + return false; + } + + u2 contended_group() const { + u2 lo = _shorts[low_packed_offset]; + switch(lo & FIELDINFO_TAG_MASK) { + case FIELDINFO_TAG_TYPE_PLAIN: + return 0; + case FIELDINFO_TAG_TYPE_CONTENDED: + return _shorts[high_packed_offset]; +#ifndef PRODUCT + case FIELDINFO_TAG_OFFSET: + ShouldNotReachHere2("Asking the contended group for the field with offset"); + case FIELDINFO_TAG_BLANK: + ShouldNotReachHere2("Asking the contended group for the blank field"); +#endif + } + ShouldNotReachHere(); + return 0; + } + + u2 allocation_type() const { + u2 lo = _shorts[low_packed_offset]; + switch(lo & FIELDINFO_TAG_MASK) { + case FIELDINFO_TAG_TYPE_PLAIN: + case FIELDINFO_TAG_TYPE_CONTENDED: + return (lo >> FIELDINFO_TAG_SIZE); +#ifndef PRODUCT + case FIELDINFO_TAG_OFFSET: + ShouldNotReachHere2("Asking the field type for field with offset"); + case FIELDINFO_TAG_BLANK: + ShouldNotReachHere2("Asking the field type for the blank field"); +#endif + } + ShouldNotReachHere(); + return 0; + } + + bool is_offset_set() const { + return (_shorts[low_packed_offset] & FIELDINFO_TAG_MASK) == FIELDINFO_TAG_OFFSET; + } Symbol* name(constantPoolHandle cp) const { int index = name_index(); @@ -106,8 +194,46 @@ class FieldInfo VALUE_OBJ_CLASS_SPEC { void set_access_flags(u2 val) { _shorts[access_flags_offset] = val; } void set_offset(u4 val) { - _shorts[low_offset] = extract_low_short_from_int(val); - _shorts[high_offset] = extract_high_short_from_int(val); + val = val << FIELDINFO_TAG_SIZE; // make room for tag + _shorts[low_packed_offset] = extract_low_short_from_int(val) | FIELDINFO_TAG_OFFSET; + _shorts[high_packed_offset] = extract_high_short_from_int(val); + } + + void set_allocation_type(int type) { + u2 lo = _shorts[low_packed_offset]; + switch(lo & FIELDINFO_TAG_MASK) { + case FIELDINFO_TAG_BLANK: + _shorts[low_packed_offset] = ((type << FIELDINFO_TAG_SIZE)) & 0xFFFF; + _shorts[low_packed_offset] &= ~FIELDINFO_TAG_MASK; + _shorts[low_packed_offset] |= FIELDINFO_TAG_TYPE_PLAIN; + return; +#ifndef PRODUCT + case FIELDINFO_TAG_TYPE_PLAIN: + case FIELDINFO_TAG_TYPE_CONTENDED: + case FIELDINFO_TAG_OFFSET: + ShouldNotReachHere2("Setting the field type with overwriting"); +#endif + } + ShouldNotReachHere(); + } + + void set_contended_group(u2 val) { + u2 lo = _shorts[low_packed_offset]; + switch(lo & FIELDINFO_TAG_MASK) { + case FIELDINFO_TAG_TYPE_PLAIN: + _shorts[low_packed_offset] |= FIELDINFO_TAG_TYPE_CONTENDED; + _shorts[high_packed_offset] = val; + return; +#ifndef PRODUCT + case FIELDINFO_TAG_TYPE_CONTENDED: + ShouldNotReachHere2("Overwriting contended group"); + case FIELDINFO_TAG_BLANK: + ShouldNotReachHere2("Setting contended group for the blank field"); + case FIELDINFO_TAG_OFFSET: + ShouldNotReachHere2("Setting contended group for field with offset"); +#endif + } + ShouldNotReachHere(); } bool is_internal() const { diff --git a/hotspot/src/share/vm/oops/fieldStreams.hpp b/hotspot/src/share/vm/oops/fieldStreams.hpp index adde764127b..acc590c970c 100644 --- a/hotspot/src/share/vm/oops/fieldStreams.hpp +++ b/hotspot/src/share/vm/oops/fieldStreams.hpp @@ -160,9 +160,26 @@ class FieldStreamBase : public StackObj { return field()->offset(); } + int allocation_type() const { + return field()->allocation_type(); + } + void set_offset(int offset) { field()->set_offset(offset); } + + bool is_offset_set() const { + return field()->is_offset_set(); + } + + bool is_contended() const { + return field()->is_contended(); + } + + int contended_group() const { + return field()->contended_group(); + } + }; // Iterate over only the internal fields diff --git a/hotspot/src/share/vm/oops/instanceKlass.hpp b/hotspot/src/share/vm/oops/instanceKlass.hpp index 0d173faa510..31ba745c19d 100644 --- a/hotspot/src/share/vm/oops/instanceKlass.hpp +++ b/hotspot/src/share/vm/oops/instanceKlass.hpp @@ -230,7 +230,8 @@ class InstanceKlass: public Klass { _misc_rewritten = 1 << 0, // methods rewritten. _misc_has_nonstatic_fields = 1 << 1, // for sizing with UseCompressedOops _misc_should_verify_class = 1 << 2, // allow caching of preverification - _misc_is_anonymous = 1 << 3 // has embedded _inner_classes field + _misc_is_anonymous = 1 << 3, // has embedded _inner_classes field + _misc_is_contended = 1 << 4 // marked with contended annotation }; u2 _misc_flags; u2 _minor_version; // minor version number of class file @@ -550,6 +551,17 @@ class InstanceKlass: public Klass { return is_anonymous() ? java_mirror() : class_loader(); } + bool is_contended() const { + return (_misc_flags & _misc_is_contended) != 0; + } + void set_is_contended(bool value) { + if (value) { + _misc_flags |= _misc_is_contended; + } else { + _misc_flags &= ~_misc_is_contended; + } + } + // signers objArrayOop signers() const { return _signers; } void set_signers(objArrayOop s) { klass_oop_store((oop*)&_signers, s); } diff --git a/hotspot/src/share/vm/runtime/globals.hpp b/hotspot/src/share/vm/runtime/globals.hpp index abdb42a51e2..52c9e7afad5 100644 --- a/hotspot/src/share/vm/runtime/globals.hpp +++ b/hotspot/src/share/vm/runtime/globals.hpp @@ -1075,7 +1075,7 @@ class CommandLineFlags { \ product(intx, ClearFPUAtPark, 0, "(Unsafe,Unstable)" ) \ \ - product(intx, hashCode, 0, \ + product(intx, hashCode, 5, \ "(Unstable) select hashCode generation algorithm" ) \ \ product(intx, WorkAroundNPTLTimedWaitHang, 1, \ @@ -1173,6 +1173,18 @@ class CommandLineFlags { notproduct(bool, PrintCompactFieldsSavings, false, \ "Print how many words were saved with CompactFields") \ \ + notproduct(bool, PrintFieldLayout, false, \ + "Print field layout for each class") \ + \ + product(intx, ContendedPaddingWidth, 128, \ + "How many bytes to pad the fields/classes marked @Contended with")\ + \ + product(bool, EnableContended, true, \ + "Enable @Contended annotation support") \ + \ + product(bool, RestrictContended, true, \ + "Restrict @Contended to trusted classes") \ + \ product(bool, UseBiasedLocking, true, \ "Enable biased locking in JVM") \ \ diff --git a/hotspot/src/share/vm/runtime/vmStructs.cpp b/hotspot/src/share/vm/runtime/vmStructs.cpp index 09d557cdbf9..e4f9cbb3ee0 100644 --- a/hotspot/src/share/vm/runtime/vmStructs.cpp +++ b/hotspot/src/share/vm/runtime/vmStructs.cpp @@ -2284,10 +2284,17 @@ typedef BinaryTreeDictionary MetablockTreeDictionary; declare_constant(FieldInfo::name_index_offset) \ declare_constant(FieldInfo::signature_index_offset) \ declare_constant(FieldInfo::initval_index_offset) \ - declare_constant(FieldInfo::low_offset) \ - declare_constant(FieldInfo::high_offset) \ + declare_constant(FieldInfo::low_packed_offset) \ + declare_constant(FieldInfo::high_packed_offset) \ declare_constant(FieldInfo::field_slots) \ \ + /*************************************/ \ + /* FieldInfo tag constants */ \ + /*************************************/ \ + \ + declare_preprocessor_constant("FIELDINFO_TAG_SIZE", FIELDINFO_TAG_SIZE) \ + declare_preprocessor_constant("FIELDINFO_TAG_OFFSET", FIELDINFO_TAG_OFFSET) \ + \ /************************************************/ \ /* InstanceKlass InnerClassAttributeOffset enum */ \ /************************************************/ \ From be0c8e9f08c42bcd5543214f5c2868bf036d469b Mon Sep 17 00:00:00 2001 From: Eric Mccorkle Date: Mon, 14 Jan 2013 11:01:39 -0500 Subject: [PATCH 021/210] 8006005: Fix constant pool index validation and alignment trap for method parameter reflection This patch addresses an alignment trap due to the storage format of method parameters data in constMethod. It also adds code to validate constant pool indexes for method parameters data. Reviewed-by: jrose, dholmes --- .../share/vm/classfile/classFileParser.cpp | 18 ++++++++- hotspot/src/share/vm/oops/constMethod.hpp | 7 +++- hotspot/src/share/vm/prims/jvm.cpp | 38 +++++++++++++------ hotspot/src/share/vm/runtime/reflection.cpp | 10 ++++- 4 files changed, 58 insertions(+), 15 deletions(-) diff --git a/hotspot/src/share/vm/classfile/classFileParser.cpp b/hotspot/src/share/vm/classfile/classFileParser.cpp index efb6138e583..a2fec400d94 100644 --- a/hotspot/src/share/vm/classfile/classFileParser.cpp +++ b/hotspot/src/share/vm/classfile/classFileParser.cpp @@ -59,6 +59,7 @@ #include "services/classLoadingService.hpp" #include "services/threadService.hpp" #include "utilities/array.hpp" +#include "utilities/globalDefinitions.hpp" // We generally try to create the oops directly when parsing, rather than // allocating temporary data structures and copying the bytes twice. A @@ -2148,9 +2149,21 @@ methodHandle ClassFileParser::parse_method(ClassLoaderData* loader_data, cp, CHECK_(nullHandle)); } else if (method_attribute_name == vmSymbols::tag_method_parameters()) { method_parameters_length = cfs->get_u1_fast(); + // Track the actual size (note: this is written for clarity; a + // decent compiler will CSE and constant-fold this into a single + // expression) + u2 actual_size = 1; method_parameters_data = cfs->get_u1_buffer(); + actual_size += 2 * method_parameters_length; cfs->skip_u2_fast(method_parameters_length); + actual_size += 4 * method_parameters_length; cfs->skip_u4_fast(method_parameters_length); + // Enforce attribute length + if (method_attribute_length != actual_size) { + classfile_parse_error( + "Invalid MethodParameters method attribute length %u in class file %s", + method_attribute_length, CHECK_(nullHandle)); + } // ignore this attribute if it cannot be reflected if (!SystemDictionary::Parameter_klass_loaded()) method_parameters_length = 0; @@ -2297,7 +2310,10 @@ methodHandle ClassFileParser::parse_method(ClassLoaderData* loader_data, elem[i].name_cp_index = Bytes::get_Java_u2(method_parameters_data); method_parameters_data += 2; - elem[i].flags = Bytes::get_Java_u4(method_parameters_data); + u4 flags = Bytes::get_Java_u4(method_parameters_data); + // This caused an alignment fault on Sparc, if flags was a u4 + elem[i].flags_lo = extract_low_short_from_int(flags); + elem[i].flags_hi = extract_high_short_from_int(flags); method_parameters_data += 4; } } diff --git a/hotspot/src/share/vm/oops/constMethod.hpp b/hotspot/src/share/vm/oops/constMethod.hpp index 08c650278e6..8b593982140 100644 --- a/hotspot/src/share/vm/oops/constMethod.hpp +++ b/hotspot/src/share/vm/oops/constMethod.hpp @@ -122,7 +122,12 @@ class ExceptionTableElement VALUE_OBJ_CLASS_SPEC { class MethodParametersElement VALUE_OBJ_CLASS_SPEC { public: u2 name_cp_index; - u4 flags; + // This has to happen, otherwise it will cause SIGBUS from a + // misaligned u4 on some architectures (ie SPARC) + // because MethodParametersElements are only aligned mod 2 + // within the ConstMethod container u2 flags_hi; + u2 flags_hi; + u2 flags_lo; }; diff --git a/hotspot/src/share/vm/prims/jvm.cpp b/hotspot/src/share/vm/prims/jvm.cpp index f899aac02e7..8b7b2583c5f 100644 --- a/hotspot/src/share/vm/prims/jvm.cpp +++ b/hotspot/src/share/vm/prims/jvm.cpp @@ -1589,6 +1589,12 @@ JVM_ENTRY(jbyteArray, JVM_GetClassTypeAnnotations(JNIEnv *env, jclass cls)) return NULL; JVM_END +static void bounds_check(constantPoolHandle cp, jint index, TRAPS) { + if (!cp->is_within_bounds(index)) { + THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), "Constant pool index out of bounds"); + } +} + JVM_ENTRY(jobjectArray, JVM_GetMethodParameters(JNIEnv *env, jobject method)) { JVMWrapper("JVM_GetMethodParameters"); @@ -1598,15 +1604,31 @@ JVM_ENTRY(jobjectArray, JVM_GetMethodParameters(JNIEnv *env, jobject method)) Handle reflected_method (THREAD, JNIHandles::resolve_non_null(method)); const int num_params = mh->method_parameters_length(); - if(0 != num_params) { + if (0 != num_params) { + // make sure all the symbols are properly formatted + for (int i = 0; i < num_params; i++) { + MethodParametersElement* params = mh->method_parameters_start(); + int index = params[i].name_cp_index; + bounds_check(mh->constants(), index, CHECK_NULL); + + if (0 != index && !mh->constants()->tag_at(index).is_utf8()) { + THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), + "Wrong type at constant pool index"); + } + + } + objArrayOop result_oop = oopFactory::new_objArray(SystemDictionary::reflect_Parameter_klass(), num_params, CHECK_NULL); objArrayHandle result (THREAD, result_oop); - for(int i = 0; i < num_params; i++) { + for (int i = 0; i < num_params; i++) { MethodParametersElement* params = mh->method_parameters_start(); - Symbol* const sym = mh->constants()->symbol_at(params[i].name_cp_index); + // For a 0 index, give a NULL symbol + Symbol* const sym = 0 != params[i].name_cp_index ? + mh->constants()->symbol_at(params[i].name_cp_index) : NULL; + int flags = build_int_from_shorts(params[i].flags_lo, params[i].flags_hi); oop param = Reflection::new_parameter(reflected_method, i, sym, - params[i].flags, CHECK_NULL); + flags, CHECK_NULL); result->obj_at_put(i, param); } return (jobjectArray)JNIHandles::make_local(env, result()); @@ -1830,13 +1852,6 @@ JVM_ENTRY(jint, JVM_ConstantPoolGetSize(JNIEnv *env, jobject obj, jobject unused JVM_END -static void bounds_check(constantPoolHandle cp, jint index, TRAPS) { - if (!cp->is_within_bounds(index)) { - THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), "Constant pool index out of bounds"); - } -} - - JVM_ENTRY(jclass, JVM_ConstantPoolGetClassAt(JNIEnv *env, jobject obj, jobject unused, jint index)) { JVMWrapper("JVM_ConstantPoolGetClassAt"); @@ -1851,7 +1866,6 @@ JVM_ENTRY(jclass, JVM_ConstantPoolGetClassAt(JNIEnv *env, jobject obj, jobject u } JVM_END - JVM_ENTRY(jclass, JVM_ConstantPoolGetClassAtIfLoaded(JNIEnv *env, jobject obj, jobject unused, jint index)) { JVMWrapper("JVM_ConstantPoolGetClassAtIfLoaded"); diff --git a/hotspot/src/share/vm/runtime/reflection.cpp b/hotspot/src/share/vm/runtime/reflection.cpp index 76a72e4e9b7..8d0cab2a441 100644 --- a/hotspot/src/share/vm/runtime/reflection.cpp +++ b/hotspot/src/share/vm/runtime/reflection.cpp @@ -862,7 +862,15 @@ oop Reflection::new_field(fieldDescriptor* fd, bool intern_name, TRAPS) { oop Reflection::new_parameter(Handle method, int index, Symbol* sym, int flags, TRAPS) { - Handle name = java_lang_String::create_from_symbol(sym, CHECK_NULL); + Handle name; + + // A null symbol here translates to the empty string + if(NULL != sym) { + name = java_lang_String::create_from_symbol(sym, CHECK_NULL); + } else { + name = java_lang_String::create_from_str("", CHECK_NULL); + } + Handle rh = java_lang_reflect_Parameter::create(CHECK_NULL); java_lang_reflect_Parameter::set_name(rh(), name()); java_lang_reflect_Parameter::set_modifiers(rh(), flags); From f8b9f3900cadebd35e5fc1082c069cd94e6436c0 Mon Sep 17 00:00:00 2001 From: Vladimir Ivanov Date: Mon, 14 Jan 2013 08:22:32 -0800 Subject: [PATCH 022/210] 8006095: C1: SIGSEGV w/ -XX:+LogCompilation Avoid printing inlining decision when compilation fails Reviewed-by: kvn, roland --- hotspot/src/share/vm/c1/c1_GraphBuilder.cpp | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp b/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp index 85c3aa1c9a9..cbaf83b8fea 100644 --- a/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp +++ b/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp @@ -3223,7 +3223,12 @@ bool GraphBuilder::try_inline(ciMethod* callee, bool holder_known, Bytecodes::Co } if (try_inline_full(callee, holder_known, bc, receiver)) return true; - print_inlining(callee, _inline_bailout_msg, /*success*/ false); + + // Entire compilation could fail during try_inline_full call. + // In that case printing inlining decision info is useless. + if (!bailed_out()) + print_inlining(callee, _inline_bailout_msg, /*success*/ false); + return false; } @@ -3753,7 +3758,8 @@ bool GraphBuilder::try_inline_full(ciMethod* callee, bool holder_known, Bytecode push_scope(callee, cont); // the BlockListBuilder for the callee could have bailed out - CHECK_BAILOUT_(false); + if (bailed_out()) + return false; // Temporarily set up bytecode stream so we can append instructions // (only using the bci of this stream) @@ -3819,7 +3825,8 @@ bool GraphBuilder::try_inline_full(ciMethod* callee, bool holder_known, Bytecode iterate_all_blocks(callee_start_block == NULL); // If we bailed out during parsing, return immediately (this is bad news) - if (bailed_out()) return false; + if (bailed_out()) + return false; // iterate_all_blocks theoretically traverses in random order; in // practice, we have only traversed the continuation if we are @@ -3828,9 +3835,6 @@ bool GraphBuilder::try_inline_full(ciMethod* callee, bool holder_known, Bytecode !continuation()->is_set(BlockBegin::was_visited_flag), "continuation should not have been parsed yet if we created it"); - // If we bailed out during parsing, return immediately (this is bad news) - CHECK_BAILOUT_(false); - // At this point we are almost ready to return and resume parsing of // the caller back in the GraphBuilder. The only thing we want to do // first is an optimization: during parsing of the callee we @@ -4171,7 +4175,10 @@ void GraphBuilder::print_inlining(ciMethod* callee, const char* msg, bool succes else log->inline_success("receiver is statically known"); } else { - log->inline_fail(msg); + if (msg != NULL) + log->inline_fail(msg); + else + log->inline_fail("reason unknown"); } } From 561384762672523b6d9757401803dacbbffef2dc Mon Sep 17 00:00:00 2001 From: Alexander Harlap Date: Mon, 14 Jan 2013 13:44:49 -0500 Subject: [PATCH 023/210] 8005639: Move InlineSynchronizedMethods flag from develop to product Move InlineSynchronizedMethods flag from develop to product Reviewed-by: kvn, vladidan --- hotspot/src/share/vm/c1/c1_globals.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hotspot/src/share/vm/c1/c1_globals.hpp b/hotspot/src/share/vm/c1/c1_globals.hpp index e81636c524a..16451f6d526 100644 --- a/hotspot/src/share/vm/c1/c1_globals.hpp +++ b/hotspot/src/share/vm/c1/c1_globals.hpp @@ -147,7 +147,7 @@ "Inline methods containing exception handlers " \ "(NOTE: does not work with current backend)") \ \ - develop(bool, InlineSynchronizedMethods, true, \ + product(bool, InlineSynchronizedMethods, true, \ "Inline synchronized methods") \ \ develop(bool, InlineNIOCheckIndex, true, \ From 95cbed6639bff77ca7b1b5c8233e4e5fa87f0909 Mon Sep 17 00:00:00 2001 From: Alexander Harlap Date: Mon, 14 Jan 2013 13:52:08 -0500 Subject: [PATCH 024/210] 8005204: Code Cache Reduction: command line options implementation Adding more detailed output on CodeCache usage Reviewed-by: kvn, vladidan --- hotspot/src/share/vm/code/codeCache.cpp | 47 ++++++++++++++----- hotspot/src/share/vm/code/codeCache.hpp | 4 +- .../src/share/vm/compiler/compileBroker.cpp | 21 ++++++++- hotspot/src/share/vm/runtime/globals.hpp | 9 ++-- hotspot/src/share/vm/runtime/java.cpp | 6 +++ hotspot/src/share/vm/utilities/vmError.cpp | 2 +- 6 files changed, 70 insertions(+), 19 deletions(-) diff --git a/hotspot/src/share/vm/code/codeCache.cpp b/hotspot/src/share/vm/code/codeCache.cpp index c40a377ebb3..d5b8f8f9a78 100644 --- a/hotspot/src/share/vm/code/codeCache.cpp +++ b/hotspot/src/share/vm/code/codeCache.cpp @@ -30,6 +30,7 @@ #include "code/icBuffer.hpp" #include "code/nmethod.hpp" #include "code/pcDesc.hpp" +#include "compiler/compileBroker.hpp" #include "gc_implementation/shared/markSweep.hpp" #include "memory/allocation.inline.hpp" #include "memory/gcLocker.hpp" @@ -39,6 +40,7 @@ #include "oops/objArrayOop.hpp" #include "oops/oop.inline.hpp" #include "runtime/handles.inline.hpp" +#include "runtime/arguments.hpp" #include "runtime/icache.hpp" #include "runtime/java.hpp" #include "runtime/mutexLocker.hpp" @@ -168,6 +170,8 @@ nmethod* CodeCache::next_nmethod (CodeBlob* cb) { return (nmethod*)cb; } +static size_t maxCodeCacheUsed = 0; + CodeBlob* CodeCache::allocate(int size) { // Do not seize the CodeCache lock here--if the caller has not // already done so, we are going to lose bigtime, since the code @@ -192,6 +196,8 @@ CodeBlob* CodeCache::allocate(int size) { (address)_heap->end() - (address)_heap->begin()); } } + maxCodeCacheUsed = MAX2(maxCodeCacheUsed, ((address)_heap->high_boundary() - + (address)_heap->low_boundary()) - unallocated_capacity()); verify_if_often(); print_trace("allocation", cb, size); return cb; @@ -928,7 +934,14 @@ void CodeCache::print_internals() { FREE_C_HEAP_ARRAY(int, buckets, mtCode); } +#endif // !PRODUCT + void CodeCache::print() { + print_summary(tty); + +#ifndef PRODUCT + if (!Verbose) return; + CodeBlob_sizes live; CodeBlob_sizes dead; @@ -953,7 +966,7 @@ void CodeCache::print() { } - if (Verbose) { + if (WizardMode) { // print the oop_map usage int code_size = 0; int number_of_blobs = 0; @@ -977,20 +990,30 @@ void CodeCache::print() { tty->print_cr(" map size = %d", map_size); } +#endif // !PRODUCT } -#endif // PRODUCT +void CodeCache::print_summary(outputStream* st, bool detailed) { + size_t total = (_heap->high_boundary() - _heap->low_boundary()); + st->print_cr("CodeCache: size=" SIZE_FORMAT "Kb used=" SIZE_FORMAT + "Kb max_used=" SIZE_FORMAT "Kb free=" SIZE_FORMAT + "Kb max_free_chunk=" SIZE_FORMAT "Kb", + total/K, (total - unallocated_capacity())/K, + maxCodeCacheUsed/K, unallocated_capacity()/K, largest_free_block()/K); -void CodeCache::print_bounds(outputStream* st) { - st->print_cr("Code Cache [" INTPTR_FORMAT ", " INTPTR_FORMAT ", " INTPTR_FORMAT ")", - _heap->low_boundary(), - _heap->high(), - _heap->high_boundary()); - st->print_cr(" total_blobs=" UINT32_FORMAT " nmethods=" UINT32_FORMAT - " adapters=" UINT32_FORMAT " free_code_cache=" SIZE_FORMAT "Kb" - " largest_free_block=" SIZE_FORMAT, - nof_blobs(), nof_nmethods(), nof_adapters(), - unallocated_capacity()/K, largest_free_block()); + if (detailed) { + st->print_cr(" bounds [" INTPTR_FORMAT ", " INTPTR_FORMAT ", " INTPTR_FORMAT "]", + _heap->low_boundary(), + _heap->high(), + _heap->high_boundary()); + st->print_cr(" total_blobs=" UINT32_FORMAT " nmethods=" UINT32_FORMAT + " adapters=" UINT32_FORMAT, + nof_blobs(), nof_nmethods(), nof_adapters()); + st->print_cr(" compilation: %s", CompileBroker::should_compile_new_jobs() ? + "enabled" : Arguments::mode() == Arguments::_int ? + "disabled (interpreter mode)" : + "disabled (not enough contiguous free space left)"); + } } void CodeCache::log_state(outputStream* st) { diff --git a/hotspot/src/share/vm/code/codeCache.hpp b/hotspot/src/share/vm/code/codeCache.hpp index 6187ba9a2a7..92ce241b938 100644 --- a/hotspot/src/share/vm/code/codeCache.hpp +++ b/hotspot/src/share/vm/code/codeCache.hpp @@ -145,11 +145,11 @@ class CodeCache : AllStatic { static void prune_scavenge_root_nmethods(); // Printing/debugging - static void print() PRODUCT_RETURN; // prints summary + static void print(); // prints summary static void print_internals(); static void verify(); // verifies the code cache static void print_trace(const char* event, CodeBlob* cb, int size = 0) PRODUCT_RETURN; - static void print_bounds(outputStream* st); // Prints a summary of the bounds of the code cache + static void print_summary(outputStream* st, bool detailed = true); // Prints a summary of the code cache usage static void log_state(outputStream* st); // The full limits of the codeCache diff --git a/hotspot/src/share/vm/compiler/compileBroker.cpp b/hotspot/src/share/vm/compiler/compileBroker.cpp index 73ab865dc74..94c042d32e3 100644 --- a/hotspot/src/share/vm/compiler/compileBroker.cpp +++ b/hotspot/src/share/vm/compiler/compileBroker.cpp @@ -1714,6 +1714,20 @@ void CompileBroker::maybe_block() { } } +// wrapper for CodeCache::print_summary() +static void codecache_print(bool detailed) +{ + ResourceMark rm; + stringStream s; + // Dump code cache into a buffer before locking the tty, + { + MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag); + CodeCache::print_summary(&s, detailed); + } + ttyLocker ttyl; + tty->print_cr(s.as_string()); +} + // ------------------------------------------------------------------ // CompileBroker::invoke_compiler_on_method // @@ -1841,6 +1855,9 @@ void CompileBroker::invoke_compiler_on_method(CompileTask* task) { tty->print_cr("size: %d time: %d inlined: %d bytes", code_size, (int)time.milliseconds(), task->num_inlined_bytecodes()); } + if (PrintCodeCacheOnCompilation) + codecache_print(/* detailed= */ false); + // Disable compilation, if required. switch (compilable) { case ciEnv::MethodCompilable_never: @@ -1885,6 +1902,7 @@ void CompileBroker::handle_full_code_cache() { UseInterpreter = true; if (UseCompiler || AlwaysCompileLoopMethods ) { if (xtty != NULL) { + ResourceMark rm; stringStream s; // Dump code cache state into a buffer before locking the tty, // because log_state() will use locks causing lock conflicts. @@ -1898,9 +1916,9 @@ void CompileBroker::handle_full_code_cache() { } warning("CodeCache is full. Compiler has been disabled."); warning("Try increasing the code cache size using -XX:ReservedCodeCacheSize="); - CodeCache::print_bounds(tty); #ifndef PRODUCT if (CompileTheWorld || ExitOnFullCodeCache) { + codecache_print(/* detailed= */ true); before_exit(JavaThread::current()); exit_globals(); // will delete tty vm_direct_exit(CompileTheWorld ? 0 : 1); @@ -1913,6 +1931,7 @@ void CompileBroker::handle_full_code_cache() { AlwaysCompileLoopMethods = false; } } + codecache_print(/* detailed= */ true); } // ------------------------------------------------------------------ diff --git a/hotspot/src/share/vm/runtime/globals.hpp b/hotspot/src/share/vm/runtime/globals.hpp index 7ea96627e82..0856bd30367 100644 --- a/hotspot/src/share/vm/runtime/globals.hpp +++ b/hotspot/src/share/vm/runtime/globals.hpp @@ -929,11 +929,14 @@ class CommandLineFlags { "Starts debugger when an implicit OS (e.g., NULL) " \ "exception happens") \ \ - notproduct(bool, PrintCodeCache, false, \ - "Print the compiled_code cache when exiting") \ + product(bool, PrintCodeCache, false, \ + "Print the code cache memory usage when exiting") \ \ develop(bool, PrintCodeCache2, false, \ - "Print detailed info on the compiled_code cache when exiting") \ + "Print detailed usage info on the code cache when exiting") \ + \ + product(bool, PrintCodeCacheOnCompilation, false, \ + "Print the code cache memory usage each time a method is compiled") \ \ diagnostic(bool, PrintStubCode, false, \ "Print generated stub code") \ diff --git a/hotspot/src/share/vm/runtime/java.cpp b/hotspot/src/share/vm/runtime/java.cpp index ad6399495b0..61ad935018c 100644 --- a/hotspot/src/share/vm/runtime/java.cpp +++ b/hotspot/src/share/vm/runtime/java.cpp @@ -368,6 +368,12 @@ void print_statistics() { if (CITime) { CompileBroker::print_times(); } + + if (PrintCodeCache) { + MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag); + CodeCache::print(); + } + #ifdef COMPILER2 if (PrintPreciseBiasedLockingStatistics) { OptoRuntime::print_named_counters(); diff --git a/hotspot/src/share/vm/utilities/vmError.cpp b/hotspot/src/share/vm/utilities/vmError.cpp index ddb6e1cf882..d8fe93b64f3 100644 --- a/hotspot/src/share/vm/utilities/vmError.cpp +++ b/hotspot/src/share/vm/utilities/vmError.cpp @@ -702,7 +702,7 @@ void VMError::report(outputStream* st) { if (_verbose && Universe::is_fully_initialized()) { // print code cache information before vm abort - CodeCache::print_bounds(st); + CodeCache::print_summary(st); st->cr(); } From 9e3a1213576a299b599b884b0821b80799659d6d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joel=20Borggr=C3=A9n-Franck?= Date: Mon, 14 Jan 2013 19:52:36 +0100 Subject: [PATCH 025/210] 7193719: Support repeating annotations in javax.lang.model Reviewed-by: jjg --- .../com/sun/tools/javac/code/Symbol.java | 9 +- .../sun/tools/javac/model/JavacElements.java | 242 ++++++++++++++++-- .../javax/lang/model/element/Element.java | 52 +++- 3 files changed, 276 insertions(+), 27 deletions(-) diff --git a/langtools/src/share/classes/com/sun/tools/javac/code/Symbol.java b/langtools/src/share/classes/com/sun/tools/javac/code/Symbol.java index 6f2e19985a4..134b0c1e890 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/code/Symbol.java +++ b/langtools/src/share/classes/com/sun/tools/javac/code/Symbol.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2013, 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 @@ -450,7 +450,7 @@ public abstract class Symbol implements Element { * This is the implementation for {@code * javax.lang.model.element.Element.getAnnotationMirrors()}. */ - public final List getAnnotationMirrors() { + public final List getAnnotationMirrors() { return getRawAttributes(); } @@ -462,6 +462,11 @@ public abstract class Symbol implements Element { return JavacElements.getAnnotation(this, annoType); } + // This method is part of the javax.lang.model API, do not use this in javac code. + public A[] getAnnotations(Class annoType) { + return JavacElements.getAnnotations(this, annoType); + } + // TODO: getEnclosedElements should return a javac List, fix in FilteredMemberList public java.util.List getEnclosedElements() { return List.nil(); diff --git a/langtools/src/share/classes/com/sun/tools/javac/model/JavacElements.java b/langtools/src/share/classes/com/sun/tools/javac/model/JavacElements.java index 168cef93e72..517ec5b4703 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/model/JavacElements.java +++ b/langtools/src/share/classes/com/sun/tools/javac/model/JavacElements.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2013, 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 @@ -27,6 +27,8 @@ package com.sun.tools.javac.model; import java.lang.annotation.Annotation; import java.lang.annotation.Inherited; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; import java.util.Map; import javax.lang.model.SourceVersion; @@ -96,32 +98,43 @@ public class JavacElements implements Elements { enter = Enter.instance(context); } - /** - * An internal-use utility that creates a reified annotation. + * An internal-use utility that creates a runtime view of an + * annotation. This is the implementation of + * Element.getAnnotation(Class). */ public static A getAnnotation(Symbol annotated, Class annoType) { if (!annoType.isAnnotation()) throw new IllegalArgumentException("Not an annotation type: " + annoType); - String name = annoType.getName(); - for (Attribute.Compound anno : annotated.getAnnotationMirrors()) - if (name.equals(anno.type.tsym.flatName().toString())) - return AnnotationProxyMaker.generateAnnotation(anno, annoType); - return null; + Attribute.Compound c; + if (annotated.kind == Kinds.TYP && annotated instanceof ClassSymbol) { + c = getAttributeOnClass((ClassSymbol)annotated, annoType); + } else { + c = getAttribute(annotated, annoType); + } + return c == null ? null : AnnotationProxyMaker.generateAnnotation(c, annoType); } - /** - * An internal-use utility that creates a reified annotation. - * This overloaded version take annotation inheritance into account. - */ - public static A getAnnotation(ClassSymbol annotated, - Class annoType) { + // Helper to getAnnotation[s] + private static Attribute.Compound getAttribute(Symbol annotated, + Class annoType) { + String name = annoType.getName(); + + for (Attribute.Compound anno : annotated.getRawAttributes()) + if (name.equals(anno.type.tsym.flatName().toString())) + return anno; + + return null; + } + // Helper to getAnnotation[s] + private static Attribute.Compound getAttributeOnClass(ClassSymbol annotated, + Class annoType) { boolean inherited = annoType.isAnnotationPresent(Inherited.class); - A result = null; + Attribute.Compound result = null; while (annotated.name != annotated.name.table.names.java_lang_Object) { - result = getAnnotation((Symbol)annotated, annoType); + result = getAttribute(annotated, annoType); if (result != null || !inherited) break; Type sup = annotated.getSuperclass(); @@ -132,6 +145,188 @@ public class JavacElements implements Elements { return result; } + /** + * An internal-use utility that creates a runtime view of + * annotations. This is the implementation of + * Element.getAnnotations(Class). + */ + public static A[] getAnnotations(Symbol annotated, + Class annoType) { + if (!annoType.isAnnotation()) + throw new IllegalArgumentException("Not an annotation type: " + + annoType); + // If annoType does not declare a container this is equivalent to wrapping + // getAnnotation(...) in an array. + Class containerType = getContainer(annoType); + if (containerType == null) { + A res = getAnnotation(annotated, annoType); + int size; + if (res == null) { + size = 0; + } else { + size = 1; + } + @SuppressWarnings("unchecked") // annoType is the Class for A + A[] arr = (A[])java.lang.reflect.Array.newInstance(annoType, size); + if (res != null) + arr[0] = res; + return arr; + } + + // So we have a containing type + String name = annoType.getName(); + String annoTypeName = annoType.getSimpleName(); + String containerTypeName = containerType.getSimpleName(); + int directIndex = -1, containerIndex = -1; + Attribute.Compound direct = null, container = null; + Attribute.Compound[] rawAttributes = annotated.getRawAttributes().toArray(new Attribute.Compound[0]); + + // Find directly present annotations + for (int i = 0; i < rawAttributes.length; i++) { + if (annoTypeName.equals(rawAttributes[i].type.tsym.flatName().toString())) { + directIndex = i; + direct = rawAttributes[i]; + } else if(containerTypeName != null && + containerTypeName.equals(rawAttributes[i].type.tsym.flatName().toString())) { + containerIndex = i; + container = rawAttributes[i]; + } + } + // Deal with inherited annotations + if (annotated.kind == Kinds.TYP && + (annotated instanceof ClassSymbol)) { + ClassSymbol s = (ClassSymbol)annotated; + if (direct == null && container == null) { + direct = getAttributeOnClass(s, annoType); + container = getAttributeOnClass(s, containerType); + + // both are inherited and found, put container last + if (direct != null && container != null) { + directIndex = 0; + containerIndex = 1; + } else if (direct != null) { + directIndex = 0; + } else { + containerIndex = 0; + } + } else if (direct == null) { + direct = getAttributeOnClass(s, annoType); + if (direct != null) + directIndex = containerIndex + 1; + } else if (container == null) { + container = getAttributeOnClass(s, containerType); + if (container != null) + containerIndex = directIndex + 1; + } + } + + // Pack them in an array + Attribute[] contained0 = new Attribute[0]; + if (container != null) + contained0 = unpackAttributes(container); + ListBuffer compounds = ListBuffer.lb(); + for (Attribute a : contained0) + if (a instanceof Attribute.Compound) + compounds = compounds.append((Attribute.Compound)a); + Attribute.Compound[] contained = compounds.toArray(new Attribute.Compound[0]); + + int size = (direct == null ? 0 : 1) + contained.length; + @SuppressWarnings("unchecked") // annoType is the Class for A + A[] arr = (A[])java.lang.reflect.Array.newInstance(annoType, size); + + // if direct && container, which is first? + int insert = -1; + int length = arr.length; + if (directIndex >= 0 && containerIndex >= 0) { + if (directIndex < containerIndex) { + arr[0] = AnnotationProxyMaker.generateAnnotation(direct, annoType); + insert = 1; + } else { + arr[arr.length - 1] = AnnotationProxyMaker.generateAnnotation(direct, annoType); + insert = 0; + length--; + } + } else if (directIndex >= 0) { + arr[0] = AnnotationProxyMaker.generateAnnotation(direct, annoType); + return arr; + } else { + // Only container + insert = 0; + } + + for (int i = 0; i + insert < length; i++) + arr[insert + i] = AnnotationProxyMaker.generateAnnotation(contained[i], annoType); + + return arr; + } + + // Needed to unpack the runtime view of containing annotations + private static final Class CONTAINED_BY_CLASS = initContainedBy(); + private static final Method VALUE_ELEMENT_METHOD = initValueElementMethod(); + + private static Class initContainedBy() { + try { + @SuppressWarnings("unchecked") // java.lang.annotation.ContainedBy extends Annotation by being an annotation type + Class c = (Class)Class.forName("java.lang.annotation.ContainedBy"); + return c; + } catch (ClassNotFoundException e) { + return null; + } catch (SecurityException e) { + return null; + } + } + private static Method initValueElementMethod() { + if (CONTAINED_BY_CLASS == null) + return null; + + Method m = null; + try { + m = CONTAINED_BY_CLASS.getMethod("value"); + if (m != null) + m.setAccessible(true); + return m; + } catch (NoSuchMethodException e) { + return null; + } + } + + // Helper to getAnnotations + private static Class getContainer(Class annoType) { + // Since we can not refer to java.lang.annotation.ContainedBy until we are + // bootstrapping with java 8 we need to get the ContainedBy annotation using + // reflective invocations instead of just using its type and element method. + if (CONTAINED_BY_CLASS != null && + VALUE_ELEMENT_METHOD != null) { + // Get the ContainedBy instance on the annotations declaration + Annotation containedBy = (Annotation)annoType.getAnnotation(CONTAINED_BY_CLASS); + if (containedBy != null) { + try { + // Get the value element, it should be a class + // indicating the containing annotation type + @SuppressWarnings("unchecked") + Class containerType = (Class)VALUE_ELEMENT_METHOD.invoke(containedBy); + if (containerType == null) + return null; + + return containerType; + } catch (ClassCastException e) { + return null; + } catch (IllegalAccessException e) { + return null; + } catch (InvocationTargetException e ) { + return null; + } + } + } + return null; + } + // Helper to getAnnotations + private static Attribute[] unpackAttributes(Attribute.Compound container) { + // We now have an instance of the container, + // unpack it returning an instance of the + // contained type or null + return ((Attribute.Array)container.member(container.type.tsym.name.table.names.value)).values; + } public PackageSymbol getPackageElement(CharSequence name) { String strName = name.toString(); @@ -238,8 +433,10 @@ public class JavacElements implements Elements { tree.accept(vis); if (vis.result == null) return null; + + List annos = sym.getRawAttributes(); return matchAnnoToTree(cast(Attribute.Compound.class, findme), - sym.getAnnotationMirrors(), + annos, vis.result); } @@ -442,7 +639,7 @@ public class JavacElements implements Elements { */ public List getAllAnnotationMirrors(Element e) { Symbol sym = cast(Symbol.class, e); - List annos = sym.getAnnotationMirrors(); + List annos = sym.getRawAttributes(); while (sym.getKind() == ElementKind.CLASS) { Type sup = ((ClassSymbol) sym).getSuperclass(); if (!sup.hasTag(CLASS) || sup.isErroneous() || @@ -451,7 +648,8 @@ public class JavacElements implements Elements { } sym = sup.tsym; List oldAnnos = annos; - for (Attribute.Compound anno : sym.getAnnotationMirrors()) { + List newAnnos = sym.getRawAttributes(); + for (Attribute.Compound anno : newAnnos) { if (isInherited(anno.type) && !containsAnnoOfType(oldAnnos, anno.type)) { annos = annos.prepend(anno); @@ -465,11 +663,7 @@ public class JavacElements implements Elements { * Tests whether an annotation type is @Inherited. */ private boolean isInherited(Type annotype) { - for (Attribute.Compound anno : annotype.tsym.getAnnotationMirrors()) { - if (anno.type.tsym == syms.inheritedType.tsym) - return true; - } - return false; + return annotype.tsym.attribute(syms.inheritedType.tsym) != null; } /** diff --git a/langtools/src/share/classes/javax/lang/model/element/Element.java b/langtools/src/share/classes/javax/lang/model/element/Element.java index 505525865c5..b0b463df13f 100644 --- a/langtools/src/share/classes/javax/lang/model/element/Element.java +++ b/langtools/src/share/classes/javax/lang/model/element/Element.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2013, 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 @@ -148,6 +148,56 @@ public interface Element { */ A getAnnotation(Class annotationType); + /** + * Returns an array of all of this element's annotation for the + * specified type if such annotations are present, else an empty + * array. The annotation may be either inherited or directly + * present on this element. This method will look through a container + * annotation (if present) if the supplied annotation type is + * repeatable. + * + *

The annotations returned by this method could contain an element + * whose value is of type {@code Class}. + * This value cannot be returned directly: information necessary to + * locate and load a class (such as the class loader to use) is + * not available, and the class might not be loadable at all. + * Attempting to read a {@code Class} object by invoking the relevant + * method on the returned annotation + * will result in a {@link MirroredTypeException}, + * from which the corresponding {@link TypeMirror} may be extracted. + * Similarly, attempting to read a {@code Class[]}-valued element + * will result in a {@link MirroredTypesException}. + * + *

+ * Note: This method is unlike others in this and related + * interfaces. It operates on runtime reflective information — + * representations of annotation types currently loaded into the + * VM — rather than on the representations defined by and used + * throughout these interfaces. Consequently, calling methods on + * the returned annotation object can throw many of the exceptions + * that can be thrown when calling methods on an annotation object + * returned by core reflection. This method is intended for + * callers that are written to operate on a known, fixed set of + * annotation types. + *
+ * + * @param
the annotation type + * @param annotationType the {@code Class} object corresponding to + * the annotation type + * @return this element's annotations for the specified annotation + * type if present on this element, else an empty array + * + * @see #getAnnotationMirrors() + * @see #getAnnotation() + * @see java.lang.reflect.AnnotatedElement#getAnnotations + * @see EnumConstantNotPresentException + * @see AnnotationTypeMismatchException + * @see IncompleteAnnotationException + * @see MirroredTypeException + * @see MirroredTypesException + */ + A[] getAnnotations(Class annotationType); + /** * Returns the modifiers of this element, excluding annotations. * Implicit modifiers, such as the {@code public} and {@code static} From b4546eb428eeecd4c764029150a24b2edea7e429 Mon Sep 17 00:00:00 2001 From: Mikael Vidstedt Date: Mon, 14 Jan 2013 11:00:56 -0800 Subject: [PATCH 026/210] 8005592: ClassLoaderDataGraph::_unloading incorrectly defined as nonstatic in vmStructs Added assertion to catch problem earlier and removed the unused field Reviewed-by: dholmes, acorn --- hotspot/src/share/vm/runtime/vmStructs.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hotspot/src/share/vm/runtime/vmStructs.cpp b/hotspot/src/share/vm/runtime/vmStructs.cpp index e4f9cbb3ee0..8d454992cf8 100644 --- a/hotspot/src/share/vm/runtime/vmStructs.cpp +++ b/hotspot/src/share/vm/runtime/vmStructs.cpp @@ -717,7 +717,6 @@ typedef BinaryTreeDictionary MetablockTreeDictionary; nonstatic_field(ClassLoaderData, _next, ClassLoaderData*) \ \ static_field(ClassLoaderDataGraph, _head, ClassLoaderData*) \ - nonstatic_field(ClassLoaderDataGraph, _unloading, ClassLoaderData*) \ \ /*******************/ \ /* GrowableArrays */ \ @@ -2575,7 +2574,8 @@ typedef BinaryTreeDictionary MetablockTreeDictionary; // This macro checks the type of a VMStructEntry by comparing pointer types #define CHECK_NONSTATIC_VM_STRUCT_ENTRY(typeName, fieldName, type) \ - {typeName *dummyObj = NULL; type* dummy = &dummyObj->fieldName; } + {typeName *dummyObj = NULL; type* dummy = &dummyObj->fieldName; \ + assert(offset_of(typeName, fieldName) < sizeof(typeName), "Illegal nonstatic struct entry, field offset too large"); } // This macro checks the type of a volatile VMStructEntry by comparing pointer types #define CHECK_VOLATILE_NONSTATIC_VM_STRUCT_ENTRY(typeName, fieldName, type) \ From 33b7cd7cae2d7a22bf107e1e746d3be133bedcdb Mon Sep 17 00:00:00 2001 From: Bengt Rutisson Date: Mon, 14 Jan 2013 21:30:45 +0100 Subject: [PATCH 027/210] 8005972: ParNew should not update the tenuring threshold when promotion failed has occurred Reviewed-by: ysr, johnc, jwilhelm --- .../vm/gc_implementation/parNew/parNewGeneration.cpp | 9 ++------- .../vm/gc_implementation/parNew/parNewGeneration.hpp | 4 ---- hotspot/src/share/vm/memory/defNewGeneration.cpp | 9 ++++++--- hotspot/src/share/vm/memory/defNewGeneration.hpp | 4 +++- 4 files changed, 11 insertions(+), 15 deletions(-) diff --git a/hotspot/src/share/vm/gc_implementation/parNew/parNewGeneration.cpp b/hotspot/src/share/vm/gc_implementation/parNew/parNewGeneration.cpp index 273322436ba..e868d870990 100644 --- a/hotspot/src/share/vm/gc_implementation/parNew/parNewGeneration.cpp +++ b/hotspot/src/share/vm/gc_implementation/parNew/parNewGeneration.cpp @@ -878,12 +878,6 @@ void EvacuateFollowersClosureGeneral::do_void() { bool ParNewGeneration::_avoid_promotion_undo = false; -void ParNewGeneration::adjust_desired_tenuring_threshold() { - // Set the desired survivor size to half the real survivor space - _tenuring_threshold = - age_table()->compute_tenuring_threshold(to()->capacity()/HeapWordSize); -} - // A Generation that does parallel young-gen collection. void ParNewGeneration::collect(bool full, @@ -1013,6 +1007,8 @@ void ParNewGeneration::collect(bool full, size_policy->reset_gc_overhead_limit_count(); assert(to()->is_empty(), "to space should be empty now"); + + adjust_desired_tenuring_threshold(); } else { assert(_promo_failure_scan_stack.is_empty(), "post condition"); _promo_failure_scan_stack.clear(true); // Clear cached segments. @@ -1035,7 +1031,6 @@ void ParNewGeneration::collect(bool full, from()->set_concurrent_iteration_safe_limit(from()->top()); to()->set_concurrent_iteration_safe_limit(to()->top()); - adjust_desired_tenuring_threshold(); if (ResizePLAB) { plab_stats()->adjust_desired_plab_sz(n_workers); } diff --git a/hotspot/src/share/vm/gc_implementation/parNew/parNewGeneration.hpp b/hotspot/src/share/vm/gc_implementation/parNew/parNewGeneration.hpp index bbb6176fd08..487552bfba9 100644 --- a/hotspot/src/share/vm/gc_implementation/parNew/parNewGeneration.hpp +++ b/hotspot/src/share/vm/gc_implementation/parNew/parNewGeneration.hpp @@ -347,10 +347,6 @@ class ParNewGeneration: public DefNewGeneration { bool survivor_overflow() { return _survivor_overflow; } void set_survivor_overflow(bool v) { _survivor_overflow = v; } - // Adjust the tenuring threshold. See the implementation for - // the details of the policy. - virtual void adjust_desired_tenuring_threshold(); - public: ParNewGeneration(ReservedSpace rs, size_t initial_byte_size, int level); diff --git a/hotspot/src/share/vm/memory/defNewGeneration.cpp b/hotspot/src/share/vm/memory/defNewGeneration.cpp index cca7cd0e704..689ce7b8bbf 100644 --- a/hotspot/src/share/vm/memory/defNewGeneration.cpp +++ b/hotspot/src/share/vm/memory/defNewGeneration.cpp @@ -550,6 +550,11 @@ HeapWord* DefNewGeneration::expand_and_allocate(size_t size, return allocate(size, is_tlab); } +void DefNewGeneration::adjust_desired_tenuring_threshold() { + // Set the desired survivor size to half the real survivor space + _tenuring_threshold = + age_table()->compute_tenuring_threshold(to()->capacity()/HeapWordSize); +} void DefNewGeneration::collect(bool full, bool clear_all_soft_refs, @@ -649,9 +654,7 @@ void DefNewGeneration::collect(bool full, assert(to()->is_empty(), "to space should be empty now"); - // Set the desired survivor size to half the real survivor space - _tenuring_threshold = - age_table()->compute_tenuring_threshold(to()->capacity()/HeapWordSize); + adjust_desired_tenuring_threshold(); // A successful scavenge should restart the GC time limit count which is // for full GC's. diff --git a/hotspot/src/share/vm/memory/defNewGeneration.hpp b/hotspot/src/share/vm/memory/defNewGeneration.hpp index b7c794d86c2..38ea742b38a 100644 --- a/hotspot/src/share/vm/memory/defNewGeneration.hpp +++ b/hotspot/src/share/vm/memory/defNewGeneration.hpp @@ -124,7 +124,9 @@ protected: _should_allocate_from_space = true; } - protected: + // Tenuring + void adjust_desired_tenuring_threshold(); + // Spaces EdenSpace* _eden_space; ContiguousSpace* _from_space; From a2f594bf745112b1662d7aaf732f23a69cc29215 Mon Sep 17 00:00:00 2001 From: Jonathan Gibbons Date: Mon, 14 Jan 2013 13:50:01 -0800 Subject: [PATCH 028/210] 8006119: update javac to follow latest spec for repeatable annotations Reviewed-by: darcy --- .../com/sun/tools/javac/code/Annotations.java | 8 +- .../com/sun/tools/javac/code/Symtab.java | 8 +- .../com/sun/tools/javac/comp/Annotate.java | 35 +++--- .../com/sun/tools/javac/comp/Attr.java | 24 ++-- .../com/sun/tools/javac/comp/Check.java | 113 ++++-------------- .../sun/tools/javac/model/JavacElements.java | 26 ++-- .../tools/javac/resources/compiler.properties | 50 +++----- .../pkg/ContaineeSynthDoc.java | 4 +- .../pkg/ContainerSynthDoc.java | 3 +- .../pkg1/ContaineeSynthDoc.java | 4 +- .../pkg1/ContainerSynthNotDoc.java | 3 +- .../BaseAnnoAsContainerAnno.java | 6 +- .../BaseAnnoAsContainerAnno.out | 2 +- .../BasicRepeatingAnnotations.java | 5 +- .../repeatingAnnotations/CheckTargets.java | 11 +- .../ClassReaderDefault.java | 8 +- .../ContainerHasRepeatedContained.java | 8 +- .../CyclicAnnotation.java | 9 +- .../repeatingAnnotations/CyclicAnnotation.out | 8 +- .../DefaultCasePresent.java | 8 +- .../DelayRepeatedContainer.java | 5 +- .../DocumentedContainerAnno.java | 6 +- .../DocumentedContainerAnno.out | 2 +- .../InheritedContainerAnno.java | 6 +- .../InheritedContainerAnno.out | 2 +- .../repeatingAnnotations/InvalidTarget.java | 5 +- .../MissingContainer.java | 6 +- .../repeatingAnnotations/MissingContainer.out | 9 +- .../MissingContainerFor.java | 38 ------ .../MissingDefaultCase1.java | 6 +- .../MissingDefaultCase1.out | 4 +- .../MissingDefaultCase2.java | 6 +- .../MissingDefaultCase2.out | 4 +- .../MissingValueMethod.java | 6 +- .../MissingValueMethod.out | 6 +- .../MultiLevelRepeatableAnno.java | 11 +- .../MultipleAnnoMixedOrder.java | 11 +- .../NestedContainers.java | 8 +- .../repeatingAnnotations/NoRepeatableAnno.out | 4 +- .../repeatingAnnotations/RepMemberAnno.java | 8 +- .../RepSelfMemberAnno.java | 8 +- .../RepeatingAndContainerPresent.java | 4 +- .../RepeatingTargetNotAllowed.java | 5 +- .../RepeatingTargetNotAllowed.out | 2 +- .../SelfRepeatingAnnotations.java | 5 +- .../SingleRepeatingAndContainer.java | 5 +- .../UseWrongContainedBy.java | 42 ------- .../UseWrongContainerFor.java | 42 ------- ...ntainedBy.java => UseWrongRepeatable.java} | 14 ++- .../WrongContainedBy.java | 39 ------ .../WrongContainerFor.java | 39 ------ .../WrongReturnTypeForValue.java | 6 +- .../WrongReturnTypeForValue.out | 7 +- .../combo/BasicSyntaxCombo.java | 5 +- .../combo/DeprecatedAnnoCombo.java | 13 +- .../combo/DocumentedAnnoCombo.java | 8 +- .../repeatingAnnotations/combo/Helper.java | 8 +- .../combo/InheritedAnnoCombo.java | 8 +- .../combo/RetentionAnnoCombo.java | 7 +- .../tools/javac/diags/examples.not-yet.txt | 6 +- .../examples/InvalidDuplicateAnnotation.java | 9 +- ...java => RepeatableDocumentedMismatch.java} | 9 +- ....java => RepeatableInheritedMismatch.java} | 9 +- ...dByNoValue.java => RepeatableNoValue.java} | 9 +- ...Default.java => RepeatableNonDefault.java} | 9 +- ....java => RepeatableRetentionMismatch.java} | 9 +- ...tch.java => RepeatableTargetMismatch.java} | 9 +- ...ype.java => RepeatableWrongValueType.java} | 9 +- .../RepeatingAnnotationAndContainer.java | 7 +- .../diags/examples/WrongContainedBy.java | 35 ------ .../diags/examples/WrongContainerFor.java | 35 ------ 71 files changed, 243 insertions(+), 675 deletions(-) delete mode 100644 langtools/test/tools/javac/annotations/repeatingAnnotations/MissingContainerFor.java delete mode 100644 langtools/test/tools/javac/annotations/repeatingAnnotations/UseWrongContainedBy.java delete mode 100644 langtools/test/tools/javac/annotations/repeatingAnnotations/UseWrongContainerFor.java rename langtools/test/tools/javac/annotations/repeatingAnnotations/{MissingContainedBy.java => UseWrongRepeatable.java} (79%) delete mode 100644 langtools/test/tools/javac/annotations/repeatingAnnotations/WrongContainedBy.java delete mode 100644 langtools/test/tools/javac/annotations/repeatingAnnotations/WrongContainerFor.java rename langtools/test/tools/javac/diags/examples/{ContainedByDocumentedMismatch.java => RepeatableDocumentedMismatch.java} (82%) rename langtools/test/tools/javac/diags/examples/{ContainedByInheritedMismatch.java => RepeatableInheritedMismatch.java} (82%) rename langtools/test/tools/javac/diags/examples/{ContainedByNoValue.java => RepeatableNoValue.java} (83%) rename langtools/test/tools/javac/diags/examples/{ContainedByNonDefault.java => RepeatableNonDefault.java} (82%) rename langtools/test/tools/javac/diags/examples/{ContainedByRetentionMismatch.java => RepeatableRetentionMismatch.java} (83%) rename langtools/test/tools/javac/diags/examples/{ContainedByTargetMismatch.java => RepeatableTargetMismatch.java} (82%) rename langtools/test/tools/javac/diags/examples/{ContainedByWrongValueType.java => RepeatableWrongValueType.java} (82%) delete mode 100644 langtools/test/tools/javac/diags/examples/WrongContainedBy.java delete mode 100644 langtools/test/tools/javac/diags/examples/WrongContainerFor.java diff --git a/langtools/src/share/classes/com/sun/tools/javac/code/Annotations.java b/langtools/src/share/classes/com/sun/tools/javac/code/Annotations.java index 29c88c9d90e..f9c3e76ae74 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/code/Annotations.java +++ b/langtools/src/share/classes/com/sun/tools/javac/code/Annotations.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2013, 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 @@ -126,12 +126,12 @@ public class Annotations { // // We need to do this in two passes because when creating // a container for a repeating annotation we must - // guarantee that the @ContainedBy on the + // guarantee that the @Repeatable on the // contained annotation is fully annotated // // The way we force this order is to do all repeating // annotations in a pass after all non-repeating are - // finished. This will work because @ContainedBy + // finished. This will work because @Repeatable // is non-repeating and therefore will be annotated in the // fist pass. @@ -261,7 +261,7 @@ public class Annotations { // its contained annotation. ListBuffer manualContainer = ctx.annotated.get(validRepeated.type.tsym); if (manualContainer != null) { - log.error(ctx.pos.get(manualContainer.first()), "invalid.containedby.annotation.repeated.and.container.present", + log.error(ctx.pos.get(manualContainer.first()), "invalid.repeatable.annotation.repeated.and.container.present", manualContainer.first().type.tsym); } } diff --git a/langtools/src/share/classes/com/sun/tools/javac/code/Symtab.java b/langtools/src/share/classes/com/sun/tools/javac/code/Symtab.java index 00d6b69db94..17535be2053 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/code/Symtab.java +++ b/langtools/src/share/classes/com/sun/tools/javac/code/Symtab.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2013, 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 @@ -161,8 +161,7 @@ public class Symtab { public final Type autoCloseableType; public final Type trustMeType; public final Type lambdaMetafactory; - public final Type containedByType; - public final Type containerForType; + public final Type repeatableType; public final Type documentedType; public final Type elementTypeType; @@ -494,8 +493,7 @@ public class Symtab { deprecatedType = enterClass("java.lang.Deprecated"); suppressWarningsType = enterClass("java.lang.SuppressWarnings"); inheritedType = enterClass("java.lang.annotation.Inherited"); - containedByType = enterClass("java.lang.annotation.ContainedBy"); - containerForType = enterClass("java.lang.annotation.ContainerFor"); + repeatableType = enterClass("java.lang.annotation.Repeatable"); documentedType = enterClass("java.lang.annotation.Documented"); elementTypeType = enterClass("java.lang.annotation.ElementType"); systemType = enterClass("java.lang.System"); diff --git a/langtools/src/share/classes/com/sun/tools/javac/comp/Annotate.java b/langtools/src/share/classes/com/sun/tools/javac/comp/Annotate.java index b9807d9180c..a2cd3851742 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/comp/Annotate.java +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Annotate.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2013, 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 @@ -392,7 +392,7 @@ public class Annotate { List.of(p))); if (!chk.annotationApplicable(annoTree, on)) - log.error(annoTree.pos(), "invalid.containedby.annotation.incompatible.target", targetContainerType, origAnnoType); + log.error(annoTree.pos(), "invalid.repeatable.annotation.incompatible.target", targetContainerType, origAnnoType); if (!chk.validateAnnotationDeferErrors(annoTree)) log.error(annoTree.pos(), "duplicate.annotation.invalid.repeated", origAnnoType); @@ -414,11 +414,11 @@ public class Annotate { Type origAnnoType = currentAnno.type; TypeSymbol origAnnoDecl = origAnnoType.tsym; - // Fetch the ContainedBy annotation from the current + // Fetch the Repeatable annotation from the current // annotation's declaration, or null if it has none - Attribute.Compound ca = origAnnoDecl.attribute(syms.containedByType.tsym); - if (ca == null) { // has no ContainedBy annotation - log.error(pos, "duplicate.annotation.missing.container", origAnnoType, syms.containedByType); + Attribute.Compound ca = origAnnoDecl.attribute(syms.repeatableType.tsym); + if (ca == null) { // has no Repeatable annotation + log.error(pos, "duplicate.annotation.missing.container", origAnnoType, syms.repeatableType); return null; } @@ -440,23 +440,23 @@ public class Annotate { DiagnosticPosition pos, TypeSymbol annoDecl) { - // The next three checks check that the ContainedBy annotation + // The next three checks check that the Repeatable annotation // on the declaration of the annotation type that is repeating is // valid. - // ContainedBy must have at least one element + // Repeatable must have at least one element if (ca.values.isEmpty()) { - log.error(pos, "invalid.containedby.annotation", annoDecl); + log.error(pos, "invalid.repeatable.annotation", annoDecl); return null; } Pair p = ca.values.head; Name name = p.fst.name; if (name != names.value) { // should contain only one element, named "value" - log.error(pos, "invalid.containedby.annotation", annoDecl); + log.error(pos, "invalid.repeatable.annotation", annoDecl); return null; } if (!(p.snd instanceof Attribute.Class)) { // check that the value of "value" is an Attribute.Class - log.error(pos, "invalid.containedby.annotation", annoDecl); + log.error(pos, "invalid.repeatable.annotation", annoDecl); return null; } @@ -491,13 +491,13 @@ public class Annotate { } if (error) { log.error(pos, - "invalid.containedby.annotation.multiple.values", + "invalid.repeatable.annotation.multiple.values", targetContainerType, nr_value_elems); return null; } else if (nr_value_elems == 0) { log.error(pos, - "invalid.containedby.annotation.no.value", + "invalid.repeatable.annotation.no.value", targetContainerType); return null; } @@ -506,7 +506,7 @@ public class Annotate { // probably "impossible" to fail this if (containerValueSymbol.kind != Kinds.MTH) { log.error(pos, - "invalid.containedby.annotation.invalid.value", + "invalid.repeatable.annotation.invalid.value", targetContainerType); fatalError = true; } @@ -518,7 +518,7 @@ public class Annotate { if (!(types.isArray(valueRetType) && types.isSameType(expectedType, valueRetType))) { log.error(pos, - "invalid.containedby.annotation.value.return", + "invalid.repeatable.annotation.value.return", targetContainerType, valueRetType, expectedType); @@ -528,10 +528,7 @@ public class Annotate { fatalError = true; } - // Explicitly no check for/validity of @ContainerFor. That is - // done on declaration of the container, and at reflect time. - - // The rest of the conditions for a valid containing annotation are made + // The conditions for a valid containing annotation are made // in Check.validateRepeatedAnnotaton(); return fatalError ? null : containerValueSymbol; diff --git a/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java b/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java index da982534deb..a787b4845a1 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2013, 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 @@ -3844,24 +3844,14 @@ public class Attr extends JCTree.Visitor { log.error(tree.typarams.head.pos(), "intf.annotation.cant.have.type.params"); - // If this annotation has a @ContainedBy, validate - Attribute.Compound containedBy = c.attribute(syms.containedByType.tsym); - if (containedBy != null) { - // get diagnositc position for error reporting - DiagnosticPosition cbPos = getDiagnosticPosition(tree, containedBy.type); + // If this annotation has a @Repeatable, validate + Attribute.Compound repeatable = c.attribute(syms.repeatableType.tsym); + if (repeatable != null) { + // get diagnostic position for error reporting + DiagnosticPosition cbPos = getDiagnosticPosition(tree, repeatable.type); Assert.checkNonNull(cbPos); - chk.validateContainedBy(c, containedBy, cbPos); - } - - // If this annotation has a @ContainerFor, validate - Attribute.Compound containerFor = c.attribute(syms.containerForType.tsym); - if (containerFor != null) { - // get diagnositc position for error reporting - DiagnosticPosition cfPos = getDiagnosticPosition(tree, containerFor.type); - Assert.checkNonNull(cfPos); - - chk.validateContainerFor(c, containerFor, cfPos); + chk.validateRepeatable(c, repeatable, cbPos); } } else { // Check that all extended classes and interfaces diff --git a/langtools/src/share/classes/com/sun/tools/javac/comp/Check.java b/langtools/src/share/classes/com/sun/tools/javac/comp/Check.java index 7db55b62c02..bcc9aa32bcb 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/comp/Check.java +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Check.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2013, 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 @@ -2592,30 +2592,30 @@ public class Check { } /** - * Validate the proposed container 'containedBy' on the + * Validate the proposed container 'repeatable' on the * annotation type symbol 's'. Report errors at position * 'pos'. * - * @param s The (annotation)type declaration annotated with a @ContainedBy - * @param containedBy the @ContainedBy on 's' + * @param s The (annotation)type declaration annotated with a @Repeatable + * @param repeatable the @Repeatable on 's' * @param pos where to report errors */ - public void validateContainedBy(TypeSymbol s, Attribute.Compound containedBy, DiagnosticPosition pos) { - Assert.check(types.isSameType(containedBy.type, syms.containedByType)); + public void validateRepeatable(TypeSymbol s, Attribute.Compound repeatable, DiagnosticPosition pos) { + Assert.check(types.isSameType(repeatable.type, syms.repeatableType)); Type t = null; - List> l = containedBy.values; + List> l = repeatable.values; if (!l.isEmpty()) { Assert.check(l.head.fst.name == names.value); t = ((Attribute.Class)l.head.snd).getValue(); } if (t == null) { - log.error(pos, "invalid.container.wrong.containedby", s, containedBy); + // errors should already have been reported during Annotate return; } - validateHasContainerFor(t.tsym, s, pos); + validateValue(t.tsym, s, pos); validateRetention(t.tsym, s, pos); validateDocumented(t.tsym, s, pos); validateInherited(t.tsym, s, pos); @@ -2623,79 +2623,18 @@ public class Check { validateDefault(t.tsym, s, pos); } - /** - * Validate the proposed container 'containerFor' on the - * annotation type symbol 's'. Report errors at position - * 'pos'. - * - * @param s The (annotation)type declaration annotated with a @ContainerFor - * @param containerFor the @ContainedFor on 's' - * @param pos where to report errors - */ - public void validateContainerFor(TypeSymbol s, Attribute.Compound containerFor, DiagnosticPosition pos) { - Assert.check(types.isSameType(containerFor.type, syms.containerForType)); - - Type t = null; - List> l = containerFor.values; - if (!l.isEmpty()) { - Assert.check(l.head.fst.name == names.value); - t = ((Attribute.Class)l.head.snd).getValue(); + private void validateValue(TypeSymbol container, TypeSymbol contained, DiagnosticPosition pos) { + Scope.Entry e = container.members().lookup(names.value); + if (e.scope != null && e.sym.kind == MTH) { + MethodSymbol m = (MethodSymbol) e.sym; + Type ret = m.getReturnType(); + if (!(ret.hasTag(ARRAY) && types.isSameType(((ArrayType)ret).elemtype, contained.type))) { + log.error(pos, "invalid.repeatable.annotation.value.return", + container, ret, types.makeArrayType(contained.type)); + } + } else { + log.error(pos, "invalid.repeatable.annotation.no.value", container); } - - if (t == null) { - log.error(pos, "invalid.container.wrong.containerfor", s, containerFor); - return; - } - - validateHasContainedBy(t.tsym, s, pos); - } - - private void validateHasContainedBy(TypeSymbol container, TypeSymbol contained, DiagnosticPosition pos) { - Attribute.Compound containedBy = container.attribute(syms.containedByType.tsym); - - if (containedBy == null) { - log.error(pos, "invalid.container.no.containedby", container, syms.containedByType.tsym); - return; - } - - Type t = null; - List> l = containedBy.values; - if (!l.isEmpty()) { - Assert.check(l.head.fst.name == names.value); - t = ((Attribute.Class)l.head.snd).getValue(); - } - - if (t == null) { - log.error(pos, "invalid.container.wrong.containedby", container, contained); - return; - } - - if (!types.isSameType(t, contained.type)) - log.error(pos, "invalid.container.wrong.containedby", t.tsym, contained); - } - - private void validateHasContainerFor(TypeSymbol container, TypeSymbol contained, DiagnosticPosition pos) { - Attribute.Compound containerFor = container.attribute(syms.containerForType.tsym); - - if (containerFor == null) { - log.error(pos, "invalid.container.no.containerfor", container, syms.containerForType.tsym); - return; - } - - Type t = null; - List> l = containerFor.values; - if (!l.isEmpty()) { - Assert.check(l.head.fst.name == names.value); - t = ((Attribute.Class)l.head.snd).getValue(); - } - - if (t == null) { - log.error(pos, "invalid.container.wrong.containerfor", container, contained); - return; - } - - if (!types.isSameType(t, contained.type)) - log.error(pos, "invalid.container.wrong.containerfor", t.tsym, contained); } private void validateRetention(Symbol container, Symbol contained, DiagnosticPosition pos) { @@ -2715,7 +2654,7 @@ public class Check { } } if (error ) { - log.error(pos, "invalid.containedby.annotation.retention", + log.error(pos, "invalid.repeatable.annotation.retention", container, containerRetention, contained, containedRetention); } @@ -2724,7 +2663,7 @@ public class Check { private void validateDocumented(Symbol container, Symbol contained, DiagnosticPosition pos) { if (contained.attribute(syms.documentedType.tsym) != null) { if (container.attribute(syms.documentedType.tsym) == null) { - log.error(pos, "invalid.containedby.annotation.not.documented", container, contained); + log.error(pos, "invalid.repeatable.annotation.not.documented", container, contained); } } } @@ -2732,7 +2671,7 @@ public class Check { private void validateInherited(Symbol container, Symbol contained, DiagnosticPosition pos) { if (contained.attribute(syms.inheritedType.tsym) != null) { if (container.attribute(syms.inheritedType.tsym) == null) { - log.error(pos, "invalid.containedby.annotation.not.inherited", container, contained); + log.error(pos, "invalid.repeatable.annotation.not.inherited", container, contained); } } } @@ -2752,7 +2691,7 @@ public class Check { // contained has target, but container has not, error Attribute.Array containerTarget = getAttributeTargetAttribute(container); if (containerTarget == null) { - log.error(pos, "invalid.containedby.annotation.incompatible.target", container, contained); + log.error(pos, "invalid.repeatable.annotation.incompatible.target", container, contained); return; } @@ -2775,7 +2714,7 @@ public class Check { } if (!isTargetSubset(containedTargets, containerTargets)) { - log.error(pos, "invalid.containedby.annotation.incompatible.target", container, contained); + log.error(pos, "invalid.repeatable.annotation.incompatible.target", container, contained); } } @@ -2809,7 +2748,7 @@ public class Check { elm.kind == Kinds.MTH && ((MethodSymbol)elm).defaultValue == null) { log.error(pos, - "invalid.containedby.annotation.elem.nondefault", + "invalid.repeatable.annotation.elem.nondefault", container, elm); } diff --git a/langtools/src/share/classes/com/sun/tools/javac/model/JavacElements.java b/langtools/src/share/classes/com/sun/tools/javac/model/JavacElements.java index 517ec5b4703..14f6e366ddb 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/model/JavacElements.java +++ b/langtools/src/share/classes/com/sun/tools/javac/model/JavacElements.java @@ -261,13 +261,13 @@ public class JavacElements implements Elements { } // Needed to unpack the runtime view of containing annotations - private static final Class CONTAINED_BY_CLASS = initContainedBy(); + private static final Class REPEATABLE_CLASS = initRepeatable(); private static final Method VALUE_ELEMENT_METHOD = initValueElementMethod(); - private static Class initContainedBy() { + private static Class initRepeatable() { try { - @SuppressWarnings("unchecked") // java.lang.annotation.ContainedBy extends Annotation by being an annotation type - Class c = (Class)Class.forName("java.lang.annotation.ContainedBy"); + @SuppressWarnings("unchecked") // java.lang.annotation.Repeatable extends Annotation by being an annotation type + Class c = (Class)Class.forName("java.lang.annotation.Repeatable"); return c; } catch (ClassNotFoundException e) { return null; @@ -276,12 +276,12 @@ public class JavacElements implements Elements { } } private static Method initValueElementMethod() { - if (CONTAINED_BY_CLASS == null) + if (REPEATABLE_CLASS == null) return null; Method m = null; try { - m = CONTAINED_BY_CLASS.getMethod("value"); + m = REPEATABLE_CLASS.getMethod("value"); if (m != null) m.setAccessible(true); return m; @@ -292,19 +292,19 @@ public class JavacElements implements Elements { // Helper to getAnnotations private static Class getContainer(Class annoType) { - // Since we can not refer to java.lang.annotation.ContainedBy until we are - // bootstrapping with java 8 we need to get the ContainedBy annotation using + // Since we can not refer to java.lang.annotation.Repeatable until we are + // bootstrapping with java 8 we need to get the Repeatable annotation using // reflective invocations instead of just using its type and element method. - if (CONTAINED_BY_CLASS != null && + if (REPEATABLE_CLASS != null && VALUE_ELEMENT_METHOD != null) { - // Get the ContainedBy instance on the annotations declaration - Annotation containedBy = (Annotation)annoType.getAnnotation(CONTAINED_BY_CLASS); - if (containedBy != null) { + // Get the Repeatable instance on the annotations declaration + Annotation repeatable = (Annotation)annoType.getAnnotation(REPEATABLE_CLASS); + if (repeatable != null) { try { // Get the value element, it should be a class // indicating the containing annotation type @SuppressWarnings("unchecked") - Class containerType = (Class)VALUE_ELEMENT_METHOD.invoke(containedBy); + Class containerType = (Class)VALUE_ELEMENT_METHOD.invoke(repeatable); if (containerType == null) return null; diff --git a/langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties b/langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties index 1f36e636ccc..41c89491c63 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties +++ b/langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 1999, 2013, 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 @@ -319,64 +319,48 @@ compiler.err.duplicate.annotation.member.value=\ compiler.err.duplicate.annotation.missing.container=\ duplicate annotation, the declaration of {0} does not have a valid {1} annotation -# 0: type, 1: type -compiler.err.invalid.container.no.containedby=\ - invalid contained repeatable annotation, {0} is not annotated with {1} - -# 0: type, 1: type -compiler.err.invalid.container.wrong.containedby=\ - invalid contained repeatable annotation, {0} does not match {1} - -# 0: type, 1: type -compiler.err.invalid.container.no.containerfor=\ - invalid container for repeating annotations, {0} is not annotated with {1} - -# 0: type, 1: type -compiler.err.invalid.container.wrong.containerfor=\ - invalid container for repeating annotations, {0} does not match {1} +# 0: type +compiler.err.invalid.repeatable.annotation=\ + duplicate annotation, {0} is annotated with an invalid Repeatable annotation # 0: type -compiler.err.invalid.containedby.annotation=\ - duplicate annotation, {0} is annotated with an invalid ContainedBy annotation - -# 0: type -compiler.err.invalid.containedby.annotation.no.value=\ - duplicate annotation, {0} is not a valid ContainedBy, no value element method declared +compiler.err.invalid.repeatable.annotation.no.value=\ + duplicate annotation, {0} is not a valid Repeatable, no value element method declared # 0: type, 1: number -compiler.err.invalid.containedby.annotation.multiple.values=\ - duplicate annotation, {0} is not a valid ContainedBy, {1} value element methods declared +compiler.err.invalid.repeatable.annotation.multiple.values=\ + duplicate annotation, {0} is not a valid Repeatable, {1} value element methods declared # 0: type -compiler.err.invalid.containedby.annotation.invalid.value=\ - duplicate annotation, {0} is not a valid ContainedBy, invalid value element, need a method +compiler.err.invalid.repeatable.annotation.invalid.value=\ + duplicate annotation, {0} is not a valid Repeatable, invalid value element, need a method # 0: type, 1: type, 2: type -compiler.err.invalid.containedby.annotation.value.return=\ +compiler.err.invalid.repeatable.annotation.value.return=\ duplicate annotation, value element of containing annotation {0} should have type {2}, found {1} # 0: type, 1: symbol -compiler.err.invalid.containedby.annotation.elem.nondefault=\ +compiler.err.invalid.repeatable.annotation.elem.nondefault=\ containing annotation {0} does not have a default value for element {1} # 0: symbol, 1: type, 2: symbol, 3: type -compiler.err.invalid.containedby.annotation.retention=\ +compiler.err.invalid.repeatable.annotation.retention=\ containing annotation {0} has shorter retention ({1}) than the contained annotation {2} with retention {3} # 0: symbol, 1: symbol -compiler.err.invalid.containedby.annotation.not.documented=\ +compiler.err.invalid.repeatable.annotation.not.documented=\ containing annotation type, {0}, is not @Documented while repeated annotation type, {1}, is # 0: symbol, 1: symbol -compiler.err.invalid.containedby.annotation.not.inherited=\ +compiler.err.invalid.repeatable.annotation.not.inherited=\ containing annotation type, {0}, is not @Inherited while repeated annotation type, {1}, is # 0: symbol, 1: symbol -compiler.err.invalid.containedby.annotation.incompatible.target=\ +compiler.err.invalid.repeatable.annotation.incompatible.target=\ target of container annotation {0} is not a subset of target of repeated annotation {1} # 0: symbol -compiler.err.invalid.containedby.annotation.repeated.and.container.present=\ +compiler.err.invalid.repeatable.annotation.repeated.and.container.present=\ container {0} must not be present at the same time as the element it contains # 0: name diff --git a/langtools/test/com/sun/javadoc/testRepeatedAnnotations/pkg/ContaineeSynthDoc.java b/langtools/test/com/sun/javadoc/testRepeatedAnnotations/pkg/ContaineeSynthDoc.java index 8499ffb5e8b..a0208e201b3 100644 --- a/langtools/test/com/sun/javadoc/testRepeatedAnnotations/pkg/ContaineeSynthDoc.java +++ b/langtools/test/com/sun/javadoc/testRepeatedAnnotations/pkg/ContaineeSynthDoc.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2013, 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 @@ -32,6 +32,6 @@ import java.lang.annotation.*; * @author Bhavesh Patel */ @Documented -@ContainedBy(ContainerSynthDoc.class) +@Repeatable(ContainerSynthDoc.class) public @interface ContaineeSynthDoc { } diff --git a/langtools/test/com/sun/javadoc/testRepeatedAnnotations/pkg/ContainerSynthDoc.java b/langtools/test/com/sun/javadoc/testRepeatedAnnotations/pkg/ContainerSynthDoc.java index 950b923d357..bdf86ee8537 100644 --- a/langtools/test/com/sun/javadoc/testRepeatedAnnotations/pkg/ContainerSynthDoc.java +++ b/langtools/test/com/sun/javadoc/testRepeatedAnnotations/pkg/ContainerSynthDoc.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2013, 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 @@ -32,7 +32,6 @@ import java.lang.annotation.*; * @author Bhavesh Patel */ @Documented -@ContainerFor(ContaineeSynthDoc.class) public @interface ContainerSynthDoc { ContaineeSynthDoc[] value(); diff --git a/langtools/test/com/sun/javadoc/testRepeatedAnnotations/pkg1/ContaineeSynthDoc.java b/langtools/test/com/sun/javadoc/testRepeatedAnnotations/pkg1/ContaineeSynthDoc.java index 15722e3324e..a3211095282 100644 --- a/langtools/test/com/sun/javadoc/testRepeatedAnnotations/pkg1/ContaineeSynthDoc.java +++ b/langtools/test/com/sun/javadoc/testRepeatedAnnotations/pkg1/ContaineeSynthDoc.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2013, 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 @@ -32,6 +32,6 @@ import java.lang.annotation.*; * @author Bhavesh Patel */ @Documented -@ContainedBy(ContainerSynthNotDoc.class) +@Repeatable(ContainerSynthNotDoc.class) public @interface ContaineeSynthDoc { } diff --git a/langtools/test/com/sun/javadoc/testRepeatedAnnotations/pkg1/ContainerSynthNotDoc.java b/langtools/test/com/sun/javadoc/testRepeatedAnnotations/pkg1/ContainerSynthNotDoc.java index fbdfc272b18..247dd1edd2e 100644 --- a/langtools/test/com/sun/javadoc/testRepeatedAnnotations/pkg1/ContainerSynthNotDoc.java +++ b/langtools/test/com/sun/javadoc/testRepeatedAnnotations/pkg1/ContainerSynthNotDoc.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2013, 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 @@ -31,7 +31,6 @@ import java.lang.annotation.*; * * @author Bhavesh Patel */ -@ContainerFor(ContaineeSynthDoc.class) public @interface ContainerSynthNotDoc { ContaineeSynthDoc[] value(); diff --git a/langtools/test/tools/javac/annotations/repeatingAnnotations/BaseAnnoAsContainerAnno.java b/langtools/test/tools/javac/annotations/repeatingAnnotations/BaseAnnoAsContainerAnno.java index d508fea04c7..baf8b14363a 100644 --- a/langtools/test/tools/javac/annotations/repeatingAnnotations/BaseAnnoAsContainerAnno.java +++ b/langtools/test/tools/javac/annotations/repeatingAnnotations/BaseAnnoAsContainerAnno.java @@ -6,11 +6,9 @@ * @compile/fail/ref=BaseAnnoAsContainerAnno.out -XDrawDiagnostics BaseAnnoAsContainerAnno.java */ -import java.lang.annotation.ContainedBy; -import java.lang.annotation.ContainerFor; +import java.lang.annotation.Repeatable; -@ContainedBy(Foo.class) -@ContainerFor(Foo.class) +@Repeatable(Foo.class) @interface Foo { Foo[] value() default {}; } diff --git a/langtools/test/tools/javac/annotations/repeatingAnnotations/BaseAnnoAsContainerAnno.out b/langtools/test/tools/javac/annotations/repeatingAnnotations/BaseAnnoAsContainerAnno.out index 8f2419f297b..0d6975ac424 100644 --- a/langtools/test/tools/javac/annotations/repeatingAnnotations/BaseAnnoAsContainerAnno.out +++ b/langtools/test/tools/javac/annotations/repeatingAnnotations/BaseAnnoAsContainerAnno.out @@ -1,2 +1,2 @@ -BaseAnnoAsContainerAnno.java:15:11: compiler.err.cyclic.annotation.element +BaseAnnoAsContainerAnno.java:13:11: compiler.err.cyclic.annotation.element 1 error diff --git a/langtools/test/tools/javac/annotations/repeatingAnnotations/BasicRepeatingAnnotations.java b/langtools/test/tools/javac/annotations/repeatingAnnotations/BasicRepeatingAnnotations.java index 9d9e59c1fc4..848cd18cc39 100644 --- a/langtools/test/tools/javac/annotations/repeatingAnnotations/BasicRepeatingAnnotations.java +++ b/langtools/test/tools/javac/annotations/repeatingAnnotations/BasicRepeatingAnnotations.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2013, 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 @@ -34,10 +34,9 @@ import java.lang.annotation.*; @Retention(RetentionPolicy.RUNTIME) -@ContainedBy(Foos.class) +@Repeatable(Foos.class) @interface Foo {} -@ContainerFor(Foo.class) @Retention(RetentionPolicy.RUNTIME) @interface Foos { Foo[] value(); diff --git a/langtools/test/tools/javac/annotations/repeatingAnnotations/CheckTargets.java b/langtools/test/tools/javac/annotations/repeatingAnnotations/CheckTargets.java index 1489cea562d..bdcfb1e51dc 100644 --- a/langtools/test/tools/javac/annotations/repeatingAnnotations/CheckTargets.java +++ b/langtools/test/tools/javac/annotations/repeatingAnnotations/CheckTargets.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2013, 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 @@ -32,32 +32,29 @@ import java.lang.annotation.*; -@ContainedBy(Foos.class) +@Repeatable(Foos.class) @Target(ElementType.TYPE) @interface Foo {} -@ContainerFor(Foo.class) @Target(ElementType.ANNOTATION_TYPE) @interface Foos { Foo[] value(); } -@ContainedBy(Bars.class) +@Repeatable(Bars.class) @Target(ElementType.TYPE) @interface Bar {} -@ContainerFor(Bar.class) @Target({ ElementType.ANNOTATION_TYPE, ElementType.TYPE }) @interface Bars { Bar[] value(); } -@ContainedBy(Bazs.class) +@Repeatable(Bazs.class) @Target({ ElementType.TYPE, ElementType.ANNOTATION_TYPE }) @interface Baz {} -@ContainerFor(Baz.class) @Target({ ElementType.ANNOTATION_TYPE, ElementType.TYPE }) @interface Bazs { Baz[] value(); diff --git a/langtools/test/tools/javac/annotations/repeatingAnnotations/ClassReaderDefault.java b/langtools/test/tools/javac/annotations/repeatingAnnotations/ClassReaderDefault.java index 18d9d7c6a41..f441f5b046c 100644 --- a/langtools/test/tools/javac/annotations/repeatingAnnotations/ClassReaderDefault.java +++ b/langtools/test/tools/javac/annotations/repeatingAnnotations/ClassReaderDefault.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2013, 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 @@ -30,17 +30,15 @@ * @compile ClassReaderDefault.java * @compile SeparateCompile.java */ -import java.lang.annotation.ContainedBy; -import java.lang.annotation.ContainerFor; +import java.lang.annotation.Repeatable; public class ClassReaderDefault { } -@ContainerFor(Foo.class) @interface FooContainer { Foo[] value(); int f() default 0; } -@ContainedBy(FooContainer.class) +@Repeatable(FooContainer.class) @interface Foo {} diff --git a/langtools/test/tools/javac/annotations/repeatingAnnotations/ContainerHasRepeatedContained.java b/langtools/test/tools/javac/annotations/repeatingAnnotations/ContainerHasRepeatedContained.java index ca2345d6b16..86cb6a071bd 100644 --- a/langtools/test/tools/javac/annotations/repeatingAnnotations/ContainerHasRepeatedContained.java +++ b/langtools/test/tools/javac/annotations/repeatingAnnotations/ContainerHasRepeatedContained.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2013, 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 @@ -30,15 +30,13 @@ * @run compile ContainerHasRepeatedContained.java */ -import java.lang.annotation.ContainedBy; -import java.lang.annotation.ContainerFor; +import java.lang.annotation.Repeatable; -@ContainedBy(BarContainer.class) +@Repeatable(BarContainer.class) @interface Bar {} @Bar @Bar -@ContainerFor(Bar.class) @interface BarContainer { Bar[] value(); } diff --git a/langtools/test/tools/javac/annotations/repeatingAnnotations/CyclicAnnotation.java b/langtools/test/tools/javac/annotations/repeatingAnnotations/CyclicAnnotation.java index 7549d464d5f..82d52700459 100644 --- a/langtools/test/tools/javac/annotations/repeatingAnnotations/CyclicAnnotation.java +++ b/langtools/test/tools/javac/annotations/repeatingAnnotations/CyclicAnnotation.java @@ -6,17 +6,14 @@ * @compile/fail/ref=CyclicAnnotation.out -XDrawDiagnostics CyclicAnnotation.java */ -import java.lang.annotation.ContainedBy; -import java.lang.annotation.ContainerFor; +import java.lang.annotation.Repeatable; -@ContainedBy(Foo.class) -@ContainerFor(Baz.class) +@Repeatable(Foo.class) @interface Baz { Foo[] value() default {}; } -@ContainedBy(Baz.class) -@ContainerFor(Foo.class) +@Repeatable(Baz.class) @interface Foo{ Baz[] value() default {}; } diff --git a/langtools/test/tools/javac/annotations/repeatingAnnotations/CyclicAnnotation.out b/langtools/test/tools/javac/annotations/repeatingAnnotations/CyclicAnnotation.out index 070b8ca0883..84079dd77b4 100644 --- a/langtools/test/tools/javac/annotations/repeatingAnnotations/CyclicAnnotation.out +++ b/langtools/test/tools/javac/annotations/repeatingAnnotations/CyclicAnnotation.out @@ -1,6 +1,2 @@ -CyclicAnnotation.java:12:1: compiler.err.invalid.container.wrong.containerfor: Foo, Baz -CyclicAnnotation.java:13:1: compiler.err.invalid.container.wrong.containedby: Foo, Baz -CyclicAnnotation.java:15:11: compiler.err.cyclic.annotation.element -CyclicAnnotation.java:18:1: compiler.err.invalid.container.wrong.containerfor: Baz, Foo -CyclicAnnotation.java:19:1: compiler.err.invalid.container.wrong.containedby: Baz, Foo -5 errors +CyclicAnnotation.java:13:11: compiler.err.cyclic.annotation.element +1 error diff --git a/langtools/test/tools/javac/annotations/repeatingAnnotations/DefaultCasePresent.java b/langtools/test/tools/javac/annotations/repeatingAnnotations/DefaultCasePresent.java index 7352a622119..4f8778d4488 100644 --- a/langtools/test/tools/javac/annotations/repeatingAnnotations/DefaultCasePresent.java +++ b/langtools/test/tools/javac/annotations/repeatingAnnotations/DefaultCasePresent.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2013, 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 @@ -29,13 +29,11 @@ * @compile DefaultCasePresent.java */ -import java.lang.annotation.ContainedBy; -import java.lang.annotation.ContainerFor; +import java.lang.annotation.Repeatable; -@ContainedBy(FooContainer.class) +@Repeatable(FooContainer.class) @interface Foo {} -@ContainerFor(Foo.class) @interface FooContainer { Foo[] value(); String other() default "other-method"; diff --git a/langtools/test/tools/javac/annotations/repeatingAnnotations/DelayRepeatedContainer.java b/langtools/test/tools/javac/annotations/repeatingAnnotations/DelayRepeatedContainer.java index ffceb9c3707..939ce4a3266 100644 --- a/langtools/test/tools/javac/annotations/repeatingAnnotations/DelayRepeatedContainer.java +++ b/langtools/test/tools/javac/annotations/repeatingAnnotations/DelayRepeatedContainer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2013, 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 @@ -39,12 +39,11 @@ public class DelayRepeatedContainer { @Bar("katt") @Bar("lol") -@ContainedBy(BarContainer.class) +@Repeatable(BarContainer.class) @interface Bar { String value(); } -@ContainerFor(Bar.class) @interface BarContainer { Bar[] value(); } diff --git a/langtools/test/tools/javac/annotations/repeatingAnnotations/DocumentedContainerAnno.java b/langtools/test/tools/javac/annotations/repeatingAnnotations/DocumentedContainerAnno.java index 96d86f7a368..95fd96ceda2 100644 --- a/langtools/test/tools/javac/annotations/repeatingAnnotations/DocumentedContainerAnno.java +++ b/langtools/test/tools/javac/annotations/repeatingAnnotations/DocumentedContainerAnno.java @@ -6,15 +6,13 @@ * @compile/fail/ref=DocumentedContainerAnno.out -XDrawDiagnostics DocumentedContainerAnno.java */ -import java.lang.annotation.ContainedBy; -import java.lang.annotation.ContainerFor; +import java.lang.annotation.Repeatable; import java.lang.annotation.Documented; @Documented -@ContainedBy(FooContainer.class) +@Repeatable(FooContainer.class) @interface Foo {} -@ContainerFor(Foo.class) @interface FooContainer{ Foo[] value(); } diff --git a/langtools/test/tools/javac/annotations/repeatingAnnotations/DocumentedContainerAnno.out b/langtools/test/tools/javac/annotations/repeatingAnnotations/DocumentedContainerAnno.out index 409d0414e77..bb267c47af3 100644 --- a/langtools/test/tools/javac/annotations/repeatingAnnotations/DocumentedContainerAnno.out +++ b/langtools/test/tools/javac/annotations/repeatingAnnotations/DocumentedContainerAnno.out @@ -1,2 +1,2 @@ -DocumentedContainerAnno.java:14:1: compiler.err.invalid.containedby.annotation.not.documented: FooContainer, Foo +DocumentedContainerAnno.java:13:1: compiler.err.invalid.repeatable.annotation.not.documented: FooContainer, Foo 1 error diff --git a/langtools/test/tools/javac/annotations/repeatingAnnotations/InheritedContainerAnno.java b/langtools/test/tools/javac/annotations/repeatingAnnotations/InheritedContainerAnno.java index 2d2a9c63894..20f8ad25224 100644 --- a/langtools/test/tools/javac/annotations/repeatingAnnotations/InheritedContainerAnno.java +++ b/langtools/test/tools/javac/annotations/repeatingAnnotations/InheritedContainerAnno.java @@ -6,15 +6,13 @@ * @compile/fail/ref=InheritedContainerAnno.out -XDrawDiagnostics InheritedContainerAnno.java */ -import java.lang.annotation.ContainedBy; -import java.lang.annotation.ContainerFor; +import java.lang.annotation.Repeatable; import java.lang.annotation.Inherited; @Inherited -@ContainedBy(FooContainer.class) +@Repeatable(FooContainer.class) @interface Foo {} -@ContainerFor(Foo.class) @interface FooContainer{ Foo[] value(); } diff --git a/langtools/test/tools/javac/annotations/repeatingAnnotations/InheritedContainerAnno.out b/langtools/test/tools/javac/annotations/repeatingAnnotations/InheritedContainerAnno.out index 10fcc772581..43736227f0d 100644 --- a/langtools/test/tools/javac/annotations/repeatingAnnotations/InheritedContainerAnno.out +++ b/langtools/test/tools/javac/annotations/repeatingAnnotations/InheritedContainerAnno.out @@ -1,2 +1,2 @@ -InheritedContainerAnno.java:14:1: compiler.err.invalid.containedby.annotation.not.inherited: FooContainer, Foo +InheritedContainerAnno.java:13:1: compiler.err.invalid.repeatable.annotation.not.inherited: FooContainer, Foo 1 error diff --git a/langtools/test/tools/javac/annotations/repeatingAnnotations/InvalidTarget.java b/langtools/test/tools/javac/annotations/repeatingAnnotations/InvalidTarget.java index 24c23386033..f85924a5d4c 100644 --- a/langtools/test/tools/javac/annotations/repeatingAnnotations/InvalidTarget.java +++ b/langtools/test/tools/javac/annotations/repeatingAnnotations/InvalidTarget.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2013, 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 @@ -32,11 +32,10 @@ import java.lang.annotation.*; -@ContainedBy(Foos.class) +@Repeatable(Foos.class) @Target(ElementType.ANNOTATION_TYPE) @interface Foo {} -@ContainerFor(Foo.class) @Target(ElementType.TYPE) @interface Foos { Foo[] value(); diff --git a/langtools/test/tools/javac/annotations/repeatingAnnotations/MissingContainer.java b/langtools/test/tools/javac/annotations/repeatingAnnotations/MissingContainer.java index 8e5650442dc..e35273e0f4a 100644 --- a/langtools/test/tools/javac/annotations/repeatingAnnotations/MissingContainer.java +++ b/langtools/test/tools/javac/annotations/repeatingAnnotations/MissingContainer.java @@ -6,13 +6,11 @@ * @compile/fail/ref=MissingContainer.out -XDrawDiagnostics MissingContainer.java */ -import java.lang.annotation.ContainedBy; -import java.lang.annotation.ContainerFor; +import java.lang.annotation.Repeatable; -@ContainedBy() +@Repeatable() @interface Foo {} -@ContainerFor(Foo.class) @interface FooContainer { Foo[] value(); } diff --git a/langtools/test/tools/javac/annotations/repeatingAnnotations/MissingContainer.out b/langtools/test/tools/javac/annotations/repeatingAnnotations/MissingContainer.out index 76986a76769..5a0e89df1ee 100644 --- a/langtools/test/tools/javac/annotations/repeatingAnnotations/MissingContainer.out +++ b/langtools/test/tools/javac/annotations/repeatingAnnotations/MissingContainer.out @@ -1,5 +1,4 @@ -MissingContainer.java:20:1: compiler.err.invalid.containedby.annotation: Foo -MissingContainer.java:20:6: compiler.err.invalid.containedby.annotation: Foo -MissingContainer.java:12:1: compiler.err.annotation.missing.default.value: java.lang.annotation.ContainedBy, value -MissingContainer.java:15:1: compiler.err.invalid.container.wrong.containedby: Foo, FooContainer -4 errors +MissingContainer.java:18:1: compiler.err.invalid.repeatable.annotation: Foo +MissingContainer.java:18:6: compiler.err.invalid.repeatable.annotation: Foo +MissingContainer.java:11:1: compiler.err.annotation.missing.default.value: java.lang.annotation.Repeatable, value +3 errors diff --git a/langtools/test/tools/javac/annotations/repeatingAnnotations/MissingContainerFor.java b/langtools/test/tools/javac/annotations/repeatingAnnotations/MissingContainerFor.java deleted file mode 100644 index 7d22aebf9b3..00000000000 --- a/langtools/test/tools/javac/annotations/repeatingAnnotations/MissingContainerFor.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (c) 2012, 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. - * - * 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. - */ - -/** - * @test - * @summary Smoke test for repeating annotations - * @compile/fail MissingContainerFor.java - * @bug 7151010 - */ - -import java.lang.annotation.*; - -@interface Foos { - MissingContainerFor[] value(); -} - -@ContainedBy(Foos.class) -public @interface MissingContainerFor {} diff --git a/langtools/test/tools/javac/annotations/repeatingAnnotations/MissingDefaultCase1.java b/langtools/test/tools/javac/annotations/repeatingAnnotations/MissingDefaultCase1.java index c29d0e8afa7..478154738c6 100644 --- a/langtools/test/tools/javac/annotations/repeatingAnnotations/MissingDefaultCase1.java +++ b/langtools/test/tools/javac/annotations/repeatingAnnotations/MissingDefaultCase1.java @@ -6,13 +6,11 @@ * @compile/fail/ref=MissingDefaultCase1.out -XDrawDiagnostics MissingDefaultCase1.java */ -import java.lang.annotation.ContainedBy; -import java.lang.annotation.ContainerFor; +import java.lang.annotation.Repeatable; -@ContainedBy(FooContainer.class) +@Repeatable(FooContainer.class) @interface Foo {} -@ContainerFor(Foo.class) @interface FooContainer { Foo[] value(); String other(); // missing default clause diff --git a/langtools/test/tools/javac/annotations/repeatingAnnotations/MissingDefaultCase1.out b/langtools/test/tools/javac/annotations/repeatingAnnotations/MissingDefaultCase1.out index ae188503866..474b6c16451 100644 --- a/langtools/test/tools/javac/annotations/repeatingAnnotations/MissingDefaultCase1.out +++ b/langtools/test/tools/javac/annotations/repeatingAnnotations/MissingDefaultCase1.out @@ -1,3 +1,3 @@ -MissingDefaultCase1.java:21:1: compiler.err.duplicate.annotation.invalid.repeated: Foo -MissingDefaultCase1.java:12:1: compiler.err.invalid.containedby.annotation.elem.nondefault: FooContainer, other() +MissingDefaultCase1.java:19:1: compiler.err.duplicate.annotation.invalid.repeated: Foo +MissingDefaultCase1.java:11:1: compiler.err.invalid.repeatable.annotation.elem.nondefault: FooContainer, other() 2 errors diff --git a/langtools/test/tools/javac/annotations/repeatingAnnotations/MissingDefaultCase2.java b/langtools/test/tools/javac/annotations/repeatingAnnotations/MissingDefaultCase2.java index b0b42b40cfc..73f2cfe6500 100644 --- a/langtools/test/tools/javac/annotations/repeatingAnnotations/MissingDefaultCase2.java +++ b/langtools/test/tools/javac/annotations/repeatingAnnotations/MissingDefaultCase2.java @@ -6,13 +6,11 @@ * @compile/fail/ref=MissingDefaultCase2.out -XDrawDiagnostics MissingDefaultCase2.java */ -import java.lang.annotation.ContainedBy; -import java.lang.annotation.ContainerFor; +import java.lang.annotation.Repeatable; -@ContainedBy(FooContainer.class) +@Repeatable(FooContainer.class) @interface Foo {} -@ContainerFor(Foo.class) @interface FooContainer { Foo[] value(); Foo other(); // missing default clause and return type is an annotation diff --git a/langtools/test/tools/javac/annotations/repeatingAnnotations/MissingDefaultCase2.out b/langtools/test/tools/javac/annotations/repeatingAnnotations/MissingDefaultCase2.out index 7e3a4229587..de467107770 100644 --- a/langtools/test/tools/javac/annotations/repeatingAnnotations/MissingDefaultCase2.out +++ b/langtools/test/tools/javac/annotations/repeatingAnnotations/MissingDefaultCase2.out @@ -1,3 +1,3 @@ -MissingDefaultCase2.java:21:1: compiler.err.duplicate.annotation.invalid.repeated: Foo -MissingDefaultCase2.java:12:1: compiler.err.invalid.containedby.annotation.elem.nondefault: FooContainer, other() +MissingDefaultCase2.java:19:1: compiler.err.duplicate.annotation.invalid.repeated: Foo +MissingDefaultCase2.java:11:1: compiler.err.invalid.repeatable.annotation.elem.nondefault: FooContainer, other() 2 errors diff --git a/langtools/test/tools/javac/annotations/repeatingAnnotations/MissingValueMethod.java b/langtools/test/tools/javac/annotations/repeatingAnnotations/MissingValueMethod.java index 36333b75cb2..a539a94c59a 100644 --- a/langtools/test/tools/javac/annotations/repeatingAnnotations/MissingValueMethod.java +++ b/langtools/test/tools/javac/annotations/repeatingAnnotations/MissingValueMethod.java @@ -6,13 +6,11 @@ * @compile/fail/ref=MissingValueMethod.out -XDrawDiagnostics MissingValueMethod.java */ -import java.lang.annotation.ContainedBy; -import java.lang.annotation.ContainerFor; +import java.lang.annotation.Repeatable; -@ContainedBy(FooContainer.class) +@Repeatable(FooContainer.class) @interface Foo {} -@ContainerFor(Foo.class) @interface FooContainer{ Foo[] values(); // wrong method name } diff --git a/langtools/test/tools/javac/annotations/repeatingAnnotations/MissingValueMethod.out b/langtools/test/tools/javac/annotations/repeatingAnnotations/MissingValueMethod.out index a712b5fa798..bb1e8888d61 100644 --- a/langtools/test/tools/javac/annotations/repeatingAnnotations/MissingValueMethod.out +++ b/langtools/test/tools/javac/annotations/repeatingAnnotations/MissingValueMethod.out @@ -1,4 +1,4 @@ -MissingValueMethod.java:20:1: compiler.err.invalid.containedby.annotation.no.value: FooContainer -MissingValueMethod.java:20:6: compiler.err.invalid.containedby.annotation.no.value: FooContainer -MissingValueMethod.java:12:1: compiler.err.invalid.containedby.annotation.elem.nondefault: FooContainer, values() +MissingValueMethod.java:18:1: compiler.err.invalid.repeatable.annotation.no.value: FooContainer +MissingValueMethod.java:18:6: compiler.err.invalid.repeatable.annotation.no.value: FooContainer +MissingValueMethod.java:11:1: compiler.err.invalid.repeatable.annotation.no.value: FooContainer 3 errors diff --git a/langtools/test/tools/javac/annotations/repeatingAnnotations/MultiLevelRepeatableAnno.java b/langtools/test/tools/javac/annotations/repeatingAnnotations/MultiLevelRepeatableAnno.java index 62b0089e0a4..8459f863329 100644 --- a/langtools/test/tools/javac/annotations/repeatingAnnotations/MultiLevelRepeatableAnno.java +++ b/langtools/test/tools/javac/annotations/repeatingAnnotations/MultiLevelRepeatableAnno.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2013, 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 @@ -29,19 +29,16 @@ * @compile MultiLevelRepeatableAnno.java */ -import java.lang.annotation.ContainedBy; -import java.lang.annotation.ContainerFor; +import java.lang.annotation.Repeatable; -@ContainedBy(FooContainer.class) +@Repeatable(FooContainer.class) @interface Foo {} -@ContainedBy(FooContainerContainer.class) -@ContainerFor(Foo.class) +@Repeatable(FooContainerContainer.class) @interface FooContainer { Foo[] value(); } -@ContainerFor(FooContainer.class) @interface FooContainerContainer { FooContainer[] value(); } diff --git a/langtools/test/tools/javac/annotations/repeatingAnnotations/MultipleAnnoMixedOrder.java b/langtools/test/tools/javac/annotations/repeatingAnnotations/MultipleAnnoMixedOrder.java index 0de0c3221a0..5992dfc8ee7 100644 --- a/langtools/test/tools/javac/annotations/repeatingAnnotations/MultipleAnnoMixedOrder.java +++ b/langtools/test/tools/javac/annotations/repeatingAnnotations/MultipleAnnoMixedOrder.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2013, 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 @@ -29,25 +29,22 @@ * @compile MultipleAnnoMixedOrder.java */ -import java.lang.annotation.ContainedBy; -import java.lang.annotation.ContainerFor; +import java.lang.annotation.Repeatable; -@ContainedBy(FooContainer.class) +@Repeatable(FooContainer.class) @interface Foo { int getNumbers(); } -@ContainerFor(Foo.class) @interface FooContainer { Foo[] value(); } -@ContainedBy(BazContainer.class) +@Repeatable(BazContainer.class) @interface Baz { String getStr(); } -@ContainerFor(Baz.class) @interface BazContainer { Baz[] value(); } diff --git a/langtools/test/tools/javac/annotations/repeatingAnnotations/NestedContainers.java b/langtools/test/tools/javac/annotations/repeatingAnnotations/NestedContainers.java index c492258801a..4694989e821 100644 --- a/langtools/test/tools/javac/annotations/repeatingAnnotations/NestedContainers.java +++ b/langtools/test/tools/javac/annotations/repeatingAnnotations/NestedContainers.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2013, 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 @@ -34,17 +34,15 @@ import java.lang.annotation.*; @Retention(RetentionPolicy.RUNTIME) -@ContainedBy(Foos.class) +@Repeatable(Foos.class) @interface Foo {} @Retention(RetentionPolicy.RUNTIME) -@ContainedBy(FoosFoos.class) -@ContainerFor(Foo.class) +@Repeatable(FoosFoos.class) @interface Foos { Foo[] value(); } -@ContainerFor(Foos.class) @Retention(RetentionPolicy.RUNTIME) @interface FoosFoos { Foos[] value(); diff --git a/langtools/test/tools/javac/annotations/repeatingAnnotations/NoRepeatableAnno.out b/langtools/test/tools/javac/annotations/repeatingAnnotations/NoRepeatableAnno.out index 42a8105b79d..1af160338c3 100644 --- a/langtools/test/tools/javac/annotations/repeatingAnnotations/NoRepeatableAnno.out +++ b/langtools/test/tools/javac/annotations/repeatingAnnotations/NoRepeatableAnno.out @@ -1,3 +1,3 @@ -NoRepeatableAnno.java:11:1: compiler.err.duplicate.annotation.missing.container: Foo, java.lang.annotation.ContainedBy -NoRepeatableAnno.java:11:6: compiler.err.duplicate.annotation.missing.container: Foo, java.lang.annotation.ContainedBy +NoRepeatableAnno.java:11:1: compiler.err.duplicate.annotation.missing.container: Foo, java.lang.annotation.Repeatable +NoRepeatableAnno.java:11:6: compiler.err.duplicate.annotation.missing.container: Foo, java.lang.annotation.Repeatable 2 errors diff --git a/langtools/test/tools/javac/annotations/repeatingAnnotations/RepMemberAnno.java b/langtools/test/tools/javac/annotations/repeatingAnnotations/RepMemberAnno.java index bb67c91cee0..2a6fc880f3f 100644 --- a/langtools/test/tools/javac/annotations/repeatingAnnotations/RepMemberAnno.java +++ b/langtools/test/tools/javac/annotations/repeatingAnnotations/RepMemberAnno.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2013, 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 @@ -30,20 +30,18 @@ * @run compile RepMemberAnno.java */ -import java.lang.annotation.ContainedBy; -import java.lang.annotation.ContainerFor; +import java.lang.annotation.Repeatable; public class RepMemberAnno { @Bar("Apa") @Bar("Banan") public void meh() {} } -@ContainedBy(BarContainer.class) +@Repeatable(BarContainer.class) @interface Bar { String value(); } -@ContainerFor(Bar.class) @interface BarContainer { Bar[] value(); } diff --git a/langtools/test/tools/javac/annotations/repeatingAnnotations/RepSelfMemberAnno.java b/langtools/test/tools/javac/annotations/repeatingAnnotations/RepSelfMemberAnno.java index bc11c69c1f0..79fdf213863 100644 --- a/langtools/test/tools/javac/annotations/repeatingAnnotations/RepSelfMemberAnno.java +++ b/langtools/test/tools/javac/annotations/repeatingAnnotations/RepSelfMemberAnno.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2013, 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 @@ -34,21 +34,19 @@ import java.lang.annotation.*; @Retention(RetentionPolicy.RUNTIME) -@ContainedBy(BarContainer.class) +@Repeatable(BarContainer.class) public @interface RepSelfMemberAnno { @RepSelfMemberAnno @RepSelfMemberAnno String meh() default "banan"; } -@ContainedBy(BarContainerContainer.class) +@Repeatable(BarContainerContainer.class) @Retention(RetentionPolicy.RUNTIME) -@ContainerFor(RepSelfMemberAnno.class) @interface BarContainer { RepSelfMemberAnno[] value(); } -@ContainerFor(BarContainer.class) @Retention(RetentionPolicy.RUNTIME) @interface BarContainerContainer { BarContainer[] value(); diff --git a/langtools/test/tools/javac/annotations/repeatingAnnotations/RepeatingAndContainerPresent.java b/langtools/test/tools/javac/annotations/repeatingAnnotations/RepeatingAndContainerPresent.java index 26d98513502..62bc29f10bc 100644 --- a/langtools/test/tools/javac/annotations/repeatingAnnotations/RepeatingAndContainerPresent.java +++ b/langtools/test/tools/javac/annotations/repeatingAnnotations/RepeatingAndContainerPresent.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2013, 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 @@ -30,7 +30,7 @@ import java.lang.annotation.*; -@ContainedBy(Foos.class) +@Repeatable(Foos.class) @interface Foo {} @interface Foos { diff --git a/langtools/test/tools/javac/annotations/repeatingAnnotations/RepeatingTargetNotAllowed.java b/langtools/test/tools/javac/annotations/repeatingAnnotations/RepeatingTargetNotAllowed.java index 7210b3f573b..7d2ba5e7673 100644 --- a/langtools/test/tools/javac/annotations/repeatingAnnotations/RepeatingTargetNotAllowed.java +++ b/langtools/test/tools/javac/annotations/repeatingAnnotations/RepeatingTargetNotAllowed.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2013, 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 @@ -31,10 +31,9 @@ import java.lang.annotation.*; -@ContainedBy(Foos.class) +@Repeatable(Foos.class) @interface Foo {} -@ContainerFor(Foo.class) @Target(ElementType.ANNOTATION_TYPE) @interface Foos { Foo[] value(); diff --git a/langtools/test/tools/javac/annotations/repeatingAnnotations/RepeatingTargetNotAllowed.out b/langtools/test/tools/javac/annotations/repeatingAnnotations/RepeatingTargetNotAllowed.out index fd4b6acc4cc..7979c8213b9 100644 --- a/langtools/test/tools/javac/annotations/repeatingAnnotations/RepeatingTargetNotAllowed.out +++ b/langtools/test/tools/javac/annotations/repeatingAnnotations/RepeatingTargetNotAllowed.out @@ -1,2 +1,2 @@ -RepeatingTargetNotAllowed.java:44:5: compiler.err.invalid.containedby.annotation.incompatible.target: Foos, Foo +RepeatingTargetNotAllowed.java:43:5: compiler.err.invalid.repeatable.annotation.incompatible.target: Foos, Foo 1 error diff --git a/langtools/test/tools/javac/annotations/repeatingAnnotations/SelfRepeatingAnnotations.java b/langtools/test/tools/javac/annotations/repeatingAnnotations/SelfRepeatingAnnotations.java index b0eb87d876b..7a70c90562d 100644 --- a/langtools/test/tools/javac/annotations/repeatingAnnotations/SelfRepeatingAnnotations.java +++ b/langtools/test/tools/javac/annotations/repeatingAnnotations/SelfRepeatingAnnotations.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2013, 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 @@ -33,7 +33,6 @@ import java.lang.annotation.*; -@ContainerFor(SelfRepeatingAnno.class) @Retention(RetentionPolicy.RUNTIME) @interface Foos { SelfRepeatingAnno[] value(); @@ -42,7 +41,7 @@ import java.lang.annotation.*; @SelfRepeatingAnno @Retention(RetentionPolicy.RUNTIME) @SelfRepeatingAnno -@ContainedBy(Foos.class) +@Repeatable(Foos.class) @interface SelfRepeatingAnno {} public class SelfRepeatingAnnotations { diff --git a/langtools/test/tools/javac/annotations/repeatingAnnotations/SingleRepeatingAndContainer.java b/langtools/test/tools/javac/annotations/repeatingAnnotations/SingleRepeatingAndContainer.java index b18d259670f..56cc83ca5d6 100644 --- a/langtools/test/tools/javac/annotations/repeatingAnnotations/SingleRepeatingAndContainer.java +++ b/langtools/test/tools/javac/annotations/repeatingAnnotations/SingleRepeatingAndContainer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2013, 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 @@ -30,10 +30,9 @@ import java.lang.annotation.*; -@ContainedBy(Foos.class) +@Repeatable(Foos.class) @interface Foo {} -@ContainerFor(Foo.class) @interface Foos { Foo[] value(); } diff --git a/langtools/test/tools/javac/annotations/repeatingAnnotations/UseWrongContainedBy.java b/langtools/test/tools/javac/annotations/repeatingAnnotations/UseWrongContainedBy.java deleted file mode 100644 index a8a8a633d6b..00000000000 --- a/langtools/test/tools/javac/annotations/repeatingAnnotations/UseWrongContainedBy.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (c) 2012, 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. - * - * 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. - */ - -/** - * @test - * @summary Smoke test for repeating annotations - * @compile/fail UseWrongContainedBy.java - * @bug 7151010 - */ - -import java.lang.annotation.*; - -@ContainerFor(UseWrongContainedBy.class) -@interface Foos { - UseWrongContainedBy[] value(); -} - -@ContainedBy(Target.class) -public @interface UseWrongContainedBy {} - -@UseWrongContainedBy @UseWrongContainedBy -@interface Foo {} diff --git a/langtools/test/tools/javac/annotations/repeatingAnnotations/UseWrongContainerFor.java b/langtools/test/tools/javac/annotations/repeatingAnnotations/UseWrongContainerFor.java deleted file mode 100644 index 5067ef20625..00000000000 --- a/langtools/test/tools/javac/annotations/repeatingAnnotations/UseWrongContainerFor.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (c) 2012, 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. - * - * 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. - */ - -/** - * @test - * @summary Smoke test for repeating annotations - * @compile/fail UseWrongContainerFor.java - * @bug 7151010 - */ - -import java.lang.annotation.*; - -@ContainerFor(Retention.class) -@interface Foos { - UseWrongContainerFor[] value(); -} - -@ContainedBy(Foos.class) -public @interface UseWrongContainerFor {} - -@UseWrongContainerFor @UseWrongContainerFor -@interface Foo {} diff --git a/langtools/test/tools/javac/annotations/repeatingAnnotations/MissingContainedBy.java b/langtools/test/tools/javac/annotations/repeatingAnnotations/UseWrongRepeatable.java similarity index 79% rename from langtools/test/tools/javac/annotations/repeatingAnnotations/MissingContainedBy.java rename to langtools/test/tools/javac/annotations/repeatingAnnotations/UseWrongRepeatable.java index 0a141a9e129..8d4b37f4c31 100644 --- a/langtools/test/tools/javac/annotations/repeatingAnnotations/MissingContainedBy.java +++ b/langtools/test/tools/javac/annotations/repeatingAnnotations/UseWrongRepeatable.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2013, 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 @@ -24,16 +24,18 @@ /** * @test * @summary Smoke test for repeating annotations - * @compile/fail MissingContainedBy.java + * @compile/fail UseWrongRepeatable.java * @bug 7151010 */ import java.lang.annotation.*; - -@ContainerFor(MissingContainedBy.class) @interface Foos { - MissingContainedBy[] value(); + UseWrongRepeatable[] value(); } -public @interface MissingContainedBy {} +@Repeatable(Target.class) +public @interface UseWrongRepeatable {} + +@UseWrongRepeatable @UseWrongRepeatable +@interface Foo {} diff --git a/langtools/test/tools/javac/annotations/repeatingAnnotations/WrongContainedBy.java b/langtools/test/tools/javac/annotations/repeatingAnnotations/WrongContainedBy.java deleted file mode 100644 index 182acf0534d..00000000000 --- a/langtools/test/tools/javac/annotations/repeatingAnnotations/WrongContainedBy.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (c) 2012, 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. - * - * 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. - */ - -/** - * @test - * @summary Smoke test for repeating annotations - * @compile/fail WrongContainedBy.java - * @bug 7151010 - */ - -import java.lang.annotation.*; - -@ContainerFor(WrongContainedBy.class) -@interface Foos { - WrongContainedBy[] value(); -} - -@ContainedBy(Target.class) -public @interface WrongContainedBy {} diff --git a/langtools/test/tools/javac/annotations/repeatingAnnotations/WrongContainerFor.java b/langtools/test/tools/javac/annotations/repeatingAnnotations/WrongContainerFor.java deleted file mode 100644 index c87bdbcc40b..00000000000 --- a/langtools/test/tools/javac/annotations/repeatingAnnotations/WrongContainerFor.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (c) 2012, 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. - * - * 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. - */ - -/** - * @test - * @summary Smoke test for repeating annotations - * @compile/fail WrongContainerFor.java - * @bug 7151010 - */ - -import java.lang.annotation.*; - -@ContainerFor(Retention.class) -@interface Foos { - WrongContainerFor[] value(); -} - -@ContainedBy(Foos.class) -public @interface WrongContainerFor {} diff --git a/langtools/test/tools/javac/annotations/repeatingAnnotations/WrongReturnTypeForValue.java b/langtools/test/tools/javac/annotations/repeatingAnnotations/WrongReturnTypeForValue.java index 6573f2f86e7..69f25b6985a 100644 --- a/langtools/test/tools/javac/annotations/repeatingAnnotations/WrongReturnTypeForValue.java +++ b/langtools/test/tools/javac/annotations/repeatingAnnotations/WrongReturnTypeForValue.java @@ -6,15 +6,13 @@ * @compile/fail/ref=WrongReturnTypeForValue.out -XDrawDiagnostics WrongReturnTypeForValue.java */ -import java.lang.annotation.ContainedBy; -import java.lang.annotation.ContainerFor; +import java.lang.annotation.Repeatable; -@ContainedBy(FooContainer.class) +@Repeatable(FooContainer.class) @interface Foo { int getNumbers(); } -@ContainerFor(Foo.class) @interface FooContainer{ Foo value(); // wrong return type } diff --git a/langtools/test/tools/javac/annotations/repeatingAnnotations/WrongReturnTypeForValue.out b/langtools/test/tools/javac/annotations/repeatingAnnotations/WrongReturnTypeForValue.out index aa2c6384851..add7bbaa3ae 100644 --- a/langtools/test/tools/javac/annotations/repeatingAnnotations/WrongReturnTypeForValue.out +++ b/langtools/test/tools/javac/annotations/repeatingAnnotations/WrongReturnTypeForValue.out @@ -1,3 +1,4 @@ -WrongReturnTypeForValue.java:22:1: compiler.err.invalid.containedby.annotation.value.return: FooContainer, Foo, Foo[] -WrongReturnTypeForValue.java:22:6: compiler.err.invalid.containedby.annotation.value.return: FooContainer, Foo, Foo[] -2 errors +WrongReturnTypeForValue.java:20:1: compiler.err.invalid.repeatable.annotation.value.return: FooContainer, Foo, Foo[] +WrongReturnTypeForValue.java:20:6: compiler.err.invalid.repeatable.annotation.value.return: FooContainer, Foo, Foo[] +WrongReturnTypeForValue.java:11:1: compiler.err.invalid.repeatable.annotation.value.return: FooContainer, Foo, Foo[] +3 errors diff --git a/langtools/test/tools/javac/annotations/repeatingAnnotations/combo/BasicSyntaxCombo.java b/langtools/test/tools/javac/annotations/repeatingAnnotations/combo/BasicSyntaxCombo.java index 802f631f5b1..03e9dbe8e37 100644 --- a/langtools/test/tools/javac/annotations/repeatingAnnotations/combo/BasicSyntaxCombo.java +++ b/langtools/test/tools/javac/annotations/repeatingAnnotations/combo/BasicSyntaxCombo.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2013, 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 @@ -163,9 +163,8 @@ public class BasicSyntaxCombo extends Helper{ String replaceStr = "/*"+type+"*/"; StringBuilder annoData = new StringBuilder(); annoData.append(Helper.ContentVars.IMPORTCONTAINERSTMTS.getVal()) - .append(Helper.ContentVars.CONTAINERFOR.getVal()) .append(Helper.ContentVars.CONTAINER.getVal()) - .append(Helper.ContentVars.CONTAINEDBY.getVal()) + .append(Helper.ContentVars.REPEATABLE.getVal()) .append(Helper.ContentVars.BASE.getVal()); JavaFileObject pkgInfoFile = null; diff --git a/langtools/test/tools/javac/annotations/repeatingAnnotations/combo/DeprecatedAnnoCombo.java b/langtools/test/tools/javac/annotations/repeatingAnnotations/combo/DeprecatedAnnoCombo.java index ba4e1652a03..8a2bcca1f30 100644 --- a/langtools/test/tools/javac/annotations/repeatingAnnotations/combo/DeprecatedAnnoCombo.java +++ b/langtools/test/tools/javac/annotations/repeatingAnnotations/combo/DeprecatedAnnoCombo.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2013, 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 @@ -115,24 +115,21 @@ public class DeprecatedAnnoCombo extends Helper { switch(className) { case "DeprecatedonBoth": annoData.append(Helper.ContentVars.DEPRECATED.getVal()) - .append(Helper.ContentVars.CONTAINERFOR.getVal()) .append(Helper.ContentVars.CONTAINER.getVal()) .append(Helper.ContentVars.DEPRECATED.getVal()) - .append(Helper.ContentVars.CONTAINEDBY.getVal()) + .append(Helper.ContentVars.REPEATABLE.getVal()) .append(Helper.ContentVars.BASE.getVal()); break; case "DeprecatedonBase": - annoData.append(Helper.ContentVars.CONTAINERFOR.getVal()) - .append(Helper.ContentVars.CONTAINER.getVal()) + annoData.append(Helper.ContentVars.CONTAINER.getVal()) .append(Helper.ContentVars.DEPRECATED.getVal()) - .append(Helper.ContentVars.CONTAINEDBY.getVal()) + .append(Helper.ContentVars.REPEATABLE.getVal()) .append(Helper.ContentVars.BASE.getVal()); break; case "DeprecatedonContainer": annoData.append(Helper.ContentVars.DEPRECATED.getVal()) - .append(Helper.ContentVars.CONTAINERFOR.getVal()) .append(Helper.ContentVars.CONTAINER.getVal()) - .append(Helper.ContentVars.CONTAINEDBY.getVal()) + .append(Helper.ContentVars.REPEATABLE.getVal()) .append(Helper.ContentVars.BASE.getVal()); break; } diff --git a/langtools/test/tools/javac/annotations/repeatingAnnotations/combo/DocumentedAnnoCombo.java b/langtools/test/tools/javac/annotations/repeatingAnnotations/combo/DocumentedAnnoCombo.java index dbe38afd768..4bb3728dda0 100644 --- a/langtools/test/tools/javac/annotations/repeatingAnnotations/combo/DocumentedAnnoCombo.java +++ b/langtools/test/tools/javac/annotations/repeatingAnnotations/combo/DocumentedAnnoCombo.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2013, 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 @@ -93,17 +93,15 @@ public class DocumentedAnnoCombo extends Helper { switch(className) { case "DocumentedonBothAnno": annoData.append(Helper.ContentVars.DOCUMENTED.getVal()) - .append(Helper.ContentVars.CONTAINERFOR.getVal()) .append(Helper.ContentVars.CONTAINER.getVal()) .append(Helper.ContentVars.DOCUMENTED.getVal()) - .append(Helper.ContentVars.CONTAINEDBY.getVal()) + .append(Helper.ContentVars.REPEATABLE.getVal()) .append(Helper.ContentVars.BASE.getVal()); break; case "DocumentedonContainer": annoData.append(Helper.ContentVars.DOCUMENTED.getVal()) - .append(Helper.ContentVars.CONTAINERFOR.getVal()) .append(Helper.ContentVars.CONTAINER.getVal()) - .append(Helper.ContentVars.CONTAINEDBY.getVal()) + .append(Helper.ContentVars.REPEATABLE.getVal()) .append(Helper.ContentVars.BASE.getVal()); break; } diff --git a/langtools/test/tools/javac/annotations/repeatingAnnotations/combo/Helper.java b/langtools/test/tools/javac/annotations/repeatingAnnotations/combo/Helper.java index 653c2f5ce0a..8a0109578c1 100644 --- a/langtools/test/tools/javac/annotations/repeatingAnnotations/combo/Helper.java +++ b/langtools/test/tools/javac/annotations/repeatingAnnotations/combo/Helper.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2013, 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 @@ -34,15 +34,13 @@ import javax.tools.JavaCompiler.CompilationTask; public class Helper { enum ContentVars { - IMPORTCONTAINERSTMTS("\nimport java.lang.annotation.ContainedBy;\n" + - "\nimport java.lang.annotation.ContainerFor;\n"), + IMPORTCONTAINERSTMTS("\nimport java.lang.annotation.Repeatable;\n"), IMPORTDEPRECATED("import java.lang.Deprecated;\n"), IMPORTDOCUMENTED("import java.lang.annotation.Documented;\n"), IMPORTINHERITED("import java.lang.annotation.Inherited;\n"), IMPORTRETENTION("import java.lang.annotation.Retention;\n" + "\nimport java.lang.annotation.RetentionPolicy;\n"), - CONTAINEDBY("\n@ContainedBy(FooContainer.class)\n"), - CONTAINERFOR("@ContainerFor(Foo.class)\n"), + REPEATABLE("\n@Repeatable(FooContainer.class)\n"), CONTAINER("@interface FooContainer {\n" +" Foo[] value();\n}\n"), BASE("@interface Foo {}\n"), REPEATABLEANNO("\n@Foo() @Foo()"), diff --git a/langtools/test/tools/javac/annotations/repeatingAnnotations/combo/InheritedAnnoCombo.java b/langtools/test/tools/javac/annotations/repeatingAnnotations/combo/InheritedAnnoCombo.java index b0b019f065d..cb49350f6fd 100644 --- a/langtools/test/tools/javac/annotations/repeatingAnnotations/combo/InheritedAnnoCombo.java +++ b/langtools/test/tools/javac/annotations/repeatingAnnotations/combo/InheritedAnnoCombo.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2013, 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 @@ -94,17 +94,15 @@ public class InheritedAnnoCombo extends Helper { switch(className) { case "InheritedonBothAnno": annoData.append(Helper.ContentVars.INHERITED.getVal()) - .append(Helper.ContentVars.CONTAINERFOR.getVal()) .append(Helper.ContentVars.CONTAINER.getVal()) .append(Helper.ContentVars.INHERITED.getVal()) - .append(Helper.ContentVars.CONTAINEDBY.getVal()) + .append(Helper.ContentVars.REPEATABLE.getVal()) .append(Helper.ContentVars.BASE.getVal()); break; case "InheritedonBase": annoData.append(Helper.ContentVars.INHERITED.getVal()) - .append(Helper.ContentVars.CONTAINERFOR.getVal()) .append(Helper.ContentVars.CONTAINER.getVal()) - .append(Helper.ContentVars.CONTAINEDBY.getVal()) + .append(Helper.ContentVars.REPEATABLE.getVal()) .append(Helper.ContentVars.BASE.getVal()); break; } diff --git a/langtools/test/tools/javac/annotations/repeatingAnnotations/combo/RetentionAnnoCombo.java b/langtools/test/tools/javac/annotations/repeatingAnnotations/combo/RetentionAnnoCombo.java index 99c5c5eb0ce..3a5ebaf142b 100644 --- a/langtools/test/tools/javac/annotations/repeatingAnnotations/combo/RetentionAnnoCombo.java +++ b/langtools/test/tools/javac/annotations/repeatingAnnotations/combo/RetentionAnnoCombo.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2013, 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 @@ -120,7 +120,7 @@ public class RetentionAnnoCombo extends Helper { new DiagnosticCollector(); boolean ok = compileCode(className, contents, diagnostics); - String expectedErrKey = "compiler.err.invalid.containedby" + + String expectedErrKey = "compiler.err.invalid.repeatable" + ".annotation.retention"; if (!shouldCompile && !ok) { for (Diagnostic d : diagnostics.getDiagnostics()) { @@ -175,10 +175,9 @@ public class RetentionAnnoCombo extends Helper { StringBuilder annoData = new StringBuilder(); annoData.append(Helper.ContentVars.IMPORTCONTAINERSTMTS.getVal()) .append(Helper.ContentVars.IMPORTRETENTION.getVal()) - .append(Helper.ContentVars.CONTAINERFOR.getVal()) .append(replacedRetCAVal) .append(Helper.ContentVars.CONTAINER.getVal()) - .append(Helper.ContentVars.CONTAINEDBY.getVal()) + .append(Helper.ContentVars.REPEATABLE.getVal()) .append(replacedRetBaseVal) .append(Helper.ContentVars.BASE.getVal()); diff --git a/langtools/test/tools/javac/diags/examples.not-yet.txt b/langtools/test/tools/javac/diags/examples.not-yet.txt index 061825ac0d2..ef2b5c84e5a 100644 --- a/langtools/test/tools/javac/diags/examples.not-yet.txt +++ b/langtools/test/tools/javac/diags/examples.not-yet.txt @@ -5,9 +5,9 @@ compiler.err.cant.read.file # (apt.JavaCompiler?) compiler.err.cant.select.static.class.from.param.type compiler.err.dc.unterminated.string # cannot happen compiler.err.illegal.char.for.encoding -compiler.err.invalid.containedby.annotation # should not happen -compiler.err.invalid.containedby.annotation.invalid.value # "can't" happen -compiler.err.invalid.containedby.annotation.multiple.values # can't happen +compiler.err.invalid.repeatable.annotation # should not happen +compiler.err.invalid.repeatable.annotation.invalid.value # "can't" happen +compiler.err.invalid.repeatable.annotation.multiple.values # can't happen compiler.err.io.exception # (javah.JavahTask?) compiler.err.limit.code # Code compiler.err.limit.code.too.large.for.try.stmt # Gen diff --git a/langtools/test/tools/javac/diags/examples/InvalidDuplicateAnnotation.java b/langtools/test/tools/javac/diags/examples/InvalidDuplicateAnnotation.java index 1dcc0997961..4d2cf299b00 100644 --- a/langtools/test/tools/javac/diags/examples/InvalidDuplicateAnnotation.java +++ b/langtools/test/tools/javac/diags/examples/InvalidDuplicateAnnotation.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2013, 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 @@ -22,17 +22,16 @@ */ // key: compiler.err.duplicate.annotation.invalid.repeated -// key: compiler.err.invalid.containedby.annotation.elem.nondefault -// +// key: compiler.err.invalid.repeatable.annotation.elem.nondefault + // We need an almost valid containing annotation. The easiest way to get // one close enough to valid is by forgetting a default. import java.lang.annotation.*; -@ContainedBy(Annos.class) +@Repeatable(Annos.class) @interface Anno { } -@ContainerFor(Anno.class) @interface Annos { Anno[] value(); String foo(); } @Anno diff --git a/langtools/test/tools/javac/diags/examples/ContainedByDocumentedMismatch.java b/langtools/test/tools/javac/diags/examples/RepeatableDocumentedMismatch.java similarity index 82% rename from langtools/test/tools/javac/diags/examples/ContainedByDocumentedMismatch.java rename to langtools/test/tools/javac/diags/examples/RepeatableDocumentedMismatch.java index a5077c7b825..0329acfc476 100644 --- a/langtools/test/tools/javac/diags/examples/ContainedByDocumentedMismatch.java +++ b/langtools/test/tools/javac/diags/examples/RepeatableDocumentedMismatch.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2013, 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 @@ -21,17 +21,16 @@ * questions. */ -// key: compiler.err.invalid.containedby.annotation.not.documented +// key: compiler.err.invalid.repeatable.annotation.not.documented import java.lang.annotation.*; @Documented -@ContainedBy(Annos.class) +@Repeatable(Annos.class) @interface Anno { } -@ContainerFor(Anno.class) @interface Annos { Anno[] value(); } @Anno @Anno -class ContainedByDocumentedMismatch { } +class RepeatableDocumentedMismatch { } diff --git a/langtools/test/tools/javac/diags/examples/ContainedByInheritedMismatch.java b/langtools/test/tools/javac/diags/examples/RepeatableInheritedMismatch.java similarity index 82% rename from langtools/test/tools/javac/diags/examples/ContainedByInheritedMismatch.java rename to langtools/test/tools/javac/diags/examples/RepeatableInheritedMismatch.java index d7723bad61c..57ad1705859 100644 --- a/langtools/test/tools/javac/diags/examples/ContainedByInheritedMismatch.java +++ b/langtools/test/tools/javac/diags/examples/RepeatableInheritedMismatch.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2013, 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 @@ -21,17 +21,16 @@ * questions. */ -// key: compiler.err.invalid.containedby.annotation.not.inherited +// key: compiler.err.invalid.repeatable.annotation.not.inherited import java.lang.annotation.*; @Inherited -@ContainedBy(Annos.class) +@Repeatable(Annos.class) @interface Anno { } -@ContainerFor(Anno.class) @interface Annos { Anno[] value(); } @Anno @Anno -class ContainedByInheritedMismatch { } +class RepeatableInheritedMismatch { } diff --git a/langtools/test/tools/javac/diags/examples/ContainedByNoValue.java b/langtools/test/tools/javac/diags/examples/RepeatableNoValue.java similarity index 83% rename from langtools/test/tools/javac/diags/examples/ContainedByNoValue.java rename to langtools/test/tools/javac/diags/examples/RepeatableNoValue.java index 8cb612808f9..01f88717bca 100644 --- a/langtools/test/tools/javac/diags/examples/ContainedByNoValue.java +++ b/langtools/test/tools/javac/diags/examples/RepeatableNoValue.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2013, 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 @@ -21,16 +21,15 @@ * questions. */ -// key: compiler.err.invalid.containedby.annotation.no.value +// key: compiler.err.invalid.repeatable.annotation.no.value import java.lang.annotation.*; -@ContainedBy(Annos.class) +@Repeatable(Annos.class) @interface Anno { } -@ContainerFor(Anno.class) @interface Annos {} @Anno @Anno -class ContainedByNoValue { } +class RepeatableNoValue { } diff --git a/langtools/test/tools/javac/diags/examples/ContainedByNonDefault.java b/langtools/test/tools/javac/diags/examples/RepeatableNonDefault.java similarity index 82% rename from langtools/test/tools/javac/diags/examples/ContainedByNonDefault.java rename to langtools/test/tools/javac/diags/examples/RepeatableNonDefault.java index d6006dedfe3..bbf2ce57211 100644 --- a/langtools/test/tools/javac/diags/examples/ContainedByNonDefault.java +++ b/langtools/test/tools/javac/diags/examples/RepeatableNonDefault.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2013, 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 @@ -21,14 +21,13 @@ * questions. */ -// key: compiler.err.invalid.containedby.annotation.elem.nondefault +// key: compiler.err.invalid.repeatable.annotation.elem.nondefault import java.lang.annotation.*; -@ContainedBy(Annos.class) +@Repeatable(Annos.class) @interface Anno { } -@ContainerFor(Anno.class) @interface Annos { Anno[] value(); String foo(); } -class ContainedByNonDefault { } +class RepeatableNonDefault { } diff --git a/langtools/test/tools/javac/diags/examples/ContainedByRetentionMismatch.java b/langtools/test/tools/javac/diags/examples/RepeatableRetentionMismatch.java similarity index 83% rename from langtools/test/tools/javac/diags/examples/ContainedByRetentionMismatch.java rename to langtools/test/tools/javac/diags/examples/RepeatableRetentionMismatch.java index 22680f5b644..47a19e2696f 100644 --- a/langtools/test/tools/javac/diags/examples/ContainedByRetentionMismatch.java +++ b/langtools/test/tools/javac/diags/examples/RepeatableRetentionMismatch.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2013, 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 @@ -21,17 +21,16 @@ * questions. */ -// key: compiler.err.invalid.containedby.annotation.retention +// key: compiler.err.invalid.repeatable.annotation.retention import java.lang.annotation.*; @Retention(RetentionPolicy.RUNTIME) -@ContainedBy(Annos.class) +@Repeatable(Annos.class) @interface Anno { } -@ContainerFor(Anno.class) @interface Annos { Anno[] value(); } @Anno @Anno -class ContainedByRetentionMismatch { } +class RepeatableRetentionMismatch { } diff --git a/langtools/test/tools/javac/diags/examples/ContainedByTargetMismatch.java b/langtools/test/tools/javac/diags/examples/RepeatableTargetMismatch.java similarity index 82% rename from langtools/test/tools/javac/diags/examples/ContainedByTargetMismatch.java rename to langtools/test/tools/javac/diags/examples/RepeatableTargetMismatch.java index 3fcd4fb3f5d..d16cad28f70 100644 --- a/langtools/test/tools/javac/diags/examples/ContainedByTargetMismatch.java +++ b/langtools/test/tools/javac/diags/examples/RepeatableTargetMismatch.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2013, 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 @@ -21,15 +21,14 @@ * questions. */ -// key: compiler.err.invalid.containedby.annotation.incompatible.target +// key: compiler.err.invalid.repeatable.annotation.incompatible.target import java.lang.annotation.*; -@ContainedBy(Annos.class) +@Repeatable(Annos.class) @Target(ElementType.METHOD) @interface Anno { } -@ContainerFor(Anno.class) @interface Annos { Anno[] value(); } -class ContainedByTargetMismatch { } +class RepeatableTargetMismatch { } diff --git a/langtools/test/tools/javac/diags/examples/ContainedByWrongValueType.java b/langtools/test/tools/javac/diags/examples/RepeatableWrongValueType.java similarity index 82% rename from langtools/test/tools/javac/diags/examples/ContainedByWrongValueType.java rename to langtools/test/tools/javac/diags/examples/RepeatableWrongValueType.java index 9b963bd3f6e..583e01532b1 100644 --- a/langtools/test/tools/javac/diags/examples/ContainedByWrongValueType.java +++ b/langtools/test/tools/javac/diags/examples/RepeatableWrongValueType.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2013, 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 @@ -21,16 +21,15 @@ * questions. */ -// key: compiler.err.invalid.containedby.annotation.value.return +// key: compiler.err.invalid.repeatable.annotation.value.return import java.lang.annotation.*; -@ContainedBy(Annos.class) +@Repeatable(Annos.class) @interface Anno { } -@ContainerFor(Anno.class) @interface Annos { String value(); } @Anno @Anno -class ContainedByWrongValueType { } +class RepeatableWrongValueType { } diff --git a/langtools/test/tools/javac/diags/examples/RepeatingAnnotationAndContainer.java b/langtools/test/tools/javac/diags/examples/RepeatingAnnotationAndContainer.java index 07a9bfddefb..dec4b59649a 100644 --- a/langtools/test/tools/javac/diags/examples/RepeatingAnnotationAndContainer.java +++ b/langtools/test/tools/javac/diags/examples/RepeatingAnnotationAndContainer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2013, 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 @@ -21,14 +21,13 @@ * questions. */ -// key: compiler.err.invalid.containedby.annotation.repeated.and.container.present +// key: compiler.err.invalid.repeatable.annotation.repeated.and.container.present import java.lang.annotation.*; -@ContainedBy(Annos.class) +@Repeatable(Annos.class) @interface Anno { } -@ContainerFor(Anno.class) @interface Annos { Anno[] value(); } @Anno diff --git a/langtools/test/tools/javac/diags/examples/WrongContainedBy.java b/langtools/test/tools/javac/diags/examples/WrongContainedBy.java deleted file mode 100644 index 6914c4bd64e..00000000000 --- a/langtools/test/tools/javac/diags/examples/WrongContainedBy.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (c) 2012, 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. - * - * 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. - */ - -// key: compiler.err.invalid.container.no.containerfor -// key: compiler.err.invalid.container.wrong.containedby - -import java.lang.annotation.*; - -@ContainerFor(WrongContainedBy.class) -@interface Foos { - WrongContainedBy[] value(); -} - -@ContainedBy(Target.class) -public @interface WrongContainedBy {} diff --git a/langtools/test/tools/javac/diags/examples/WrongContainerFor.java b/langtools/test/tools/javac/diags/examples/WrongContainerFor.java deleted file mode 100644 index e439b780fbe..00000000000 --- a/langtools/test/tools/javac/diags/examples/WrongContainerFor.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (c) 2012, 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. - * - * 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. - */ - -// key: compiler.err.invalid.container.wrong.containerfor -// key: compiler.err.invalid.container.no.containedby - -import java.lang.annotation.*; - -@ContainerFor(Retention.class) -@interface Foos { - WrongContainerFor[] value(); -} - -@ContainedBy(Foos.class) -public @interface WrongContainerFor {} From f92bbd33111f87b51ffb94f6e677300a7aa4281b Mon Sep 17 00:00:00 2001 From: Jonathan Gibbons Date: Mon, 14 Jan 2013 14:17:25 -0800 Subject: [PATCH 029/210] 8006241: Test DocRootSlash.java fails Reviewed-by: darcy --- langtools/test/com/sun/javadoc/DocRootSlash/DocRootSlash.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/langtools/test/com/sun/javadoc/DocRootSlash/DocRootSlash.java b/langtools/test/com/sun/javadoc/DocRootSlash/DocRootSlash.java index 032481764d8..75562bdee08 100644 --- a/langtools/test/com/sun/javadoc/DocRootSlash/DocRootSlash.java +++ b/langtools/test/com/sun/javadoc/DocRootSlash/DocRootSlash.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2013, 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 @@ -60,6 +60,7 @@ public class DocRootSlash String srcdir = System.getProperty("test.src", "."); runJavadoc(new String[] {"-d", TMPDIR_STRING1, + "-Xdoclint:none", "-overview", (srcdir + FS + "overview.html"), "-header", "{@docroot} {@docRoot}", "-sourcepath", srcdir, From 67fc68ea7f815c3c6b23fc29ce3f60998e9ad0a7 Mon Sep 17 00:00:00 2001 From: Stefan Karlsson Date: Tue, 15 Jan 2013 13:32:13 +0100 Subject: [PATCH 030/210] 8005590: java_lang_Class injected field resolved_constructor appears unused Reviewed-by: coleenp, dholmes --- hotspot/src/share/vm/classfile/javaClasses.cpp | 15 --------------- hotspot/src/share/vm/classfile/javaClasses.hpp | 6 ------ hotspot/src/share/vm/classfile/vmSymbols.hpp | 1 - hotspot/src/share/vm/oops/instanceKlass.cpp | 4 ---- hotspot/src/share/vm/runtime/vmStructs.cpp | 1 - 5 files changed, 27 deletions(-) diff --git a/hotspot/src/share/vm/classfile/javaClasses.cpp b/hotspot/src/share/vm/classfile/javaClasses.cpp index cb30a83d455..1c46188b728 100644 --- a/hotspot/src/share/vm/classfile/javaClasses.cpp +++ b/hotspot/src/share/vm/classfile/javaClasses.cpp @@ -687,19 +687,6 @@ void java_lang_Class::set_array_klass(oop java_class, Klass* klass) { } -Method* java_lang_Class::resolved_constructor(oop java_class) { - Metadata* constructor = java_class->metadata_field(_resolved_constructor_offset); - assert(constructor == NULL || constructor->is_method(), "should be method"); - return ((Method*)constructor); -} - - -void java_lang_Class::set_resolved_constructor(oop java_class, Method* constructor) { - assert(constructor->is_method(), "should be method"); - java_class->metadata_field_put(_resolved_constructor_offset, constructor); -} - - bool java_lang_Class::is_primitive(oop java_class) { // should assert: //assert(java_lang_Class::is_instance(java_class), "must be a Class object"); @@ -2949,7 +2936,6 @@ int java_lang_System::err_offset_in_bytes() { int java_lang_Class::_klass_offset; int java_lang_Class::_array_klass_offset; -int java_lang_Class::_resolved_constructor_offset; int java_lang_Class::_oop_size_offset; int java_lang_Class::_static_oop_field_count_offset; GrowableArray* java_lang_Class::_fixup_mirror_list = NULL; @@ -3303,7 +3289,6 @@ void JavaClasses::check_offsets() { // Fake fields // CHECK_OFFSET("java/lang/Class", java_lang_Class, klass); // %%% this needs to be checked // CHECK_OFFSET("java/lang/Class", java_lang_Class, array_klass); // %%% this needs to be checked - // CHECK_OFFSET("java/lang/Class", java_lang_Class, resolved_constructor); // %%% this needs to be checked // java.lang.Throwable diff --git a/hotspot/src/share/vm/classfile/javaClasses.hpp b/hotspot/src/share/vm/classfile/javaClasses.hpp index 5ab16251c10..fe48e0f614d 100644 --- a/hotspot/src/share/vm/classfile/javaClasses.hpp +++ b/hotspot/src/share/vm/classfile/javaClasses.hpp @@ -206,7 +206,6 @@ class java_lang_String : AllStatic { #define CLASS_INJECTED_FIELDS(macro) \ macro(java_lang_Class, klass, intptr_signature, false) \ - macro(java_lang_Class, resolved_constructor, intptr_signature, false) \ macro(java_lang_Class, array_klass, intptr_signature, false) \ macro(java_lang_Class, oop_size, int_signature, false) \ macro(java_lang_Class, static_oop_field_count, int_signature, false) @@ -218,7 +217,6 @@ class java_lang_Class : AllStatic { // The fake offsets are added by the class loader when java.lang.Class is loaded static int _klass_offset; - static int _resolved_constructor_offset; static int _array_klass_offset; static int _oop_size_offset; @@ -254,15 +252,11 @@ class java_lang_Class : AllStatic { static bool is_primitive(oop java_class); static BasicType primitive_type(oop java_class); static oop primitive_mirror(BasicType t); - // JVM_NewInstance support - static Method* resolved_constructor(oop java_class); - static void set_resolved_constructor(oop java_class, Method* constructor); // JVM_NewArray support static Klass* array_klass(oop java_class); static void set_array_klass(oop java_class, Klass* klass); // compiler support for class operations static int klass_offset_in_bytes() { return _klass_offset; } - static int resolved_constructor_offset_in_bytes() { return _resolved_constructor_offset; } static int array_klass_offset_in_bytes() { return _array_klass_offset; } // Support for classRedefinedCount field static int classRedefinedCount(oop the_class_mirror); diff --git a/hotspot/src/share/vm/classfile/vmSymbols.hpp b/hotspot/src/share/vm/classfile/vmSymbols.hpp index e6168ceba2c..9829e834875 100644 --- a/hotspot/src/share/vm/classfile/vmSymbols.hpp +++ b/hotspot/src/share/vm/classfile/vmSymbols.hpp @@ -383,7 +383,6 @@ template(basicType_name, "basicType") \ template(append_name, "append") \ template(klass_name, "klass") \ - template(resolved_constructor_name, "resolved_constructor") \ template(array_klass_name, "array_klass") \ template(oop_size_name, "oop_size") \ template(static_oop_field_count_name, "static_oop_field_count") \ diff --git a/hotspot/src/share/vm/oops/instanceKlass.cpp b/hotspot/src/share/vm/oops/instanceKlass.cpp index d123641a0c7..b0b7038e35b 100644 --- a/hotspot/src/share/vm/oops/instanceKlass.cpp +++ b/hotspot/src/share/vm/oops/instanceKlass.cpp @@ -2890,11 +2890,7 @@ void InstanceKlass::oop_print_on(oop obj, outputStream* st) { st->print(BULLET"fake entry for mirror: "); mirrored_klass->print_value_on_maybe_null(st); st->cr(); - st->print(BULLET"fake entry resolved_constructor: "); - Method* ctor = java_lang_Class::resolved_constructor(obj); - ctor->print_value_on_maybe_null(st); Klass* array_klass = java_lang_Class::array_klass(obj); - st->cr(); st->print(BULLET"fake entry for array: "); array_klass->print_value_on_maybe_null(st); st->cr(); diff --git a/hotspot/src/share/vm/runtime/vmStructs.cpp b/hotspot/src/share/vm/runtime/vmStructs.cpp index 9ac10e26d4c..c4172c18212 100644 --- a/hotspot/src/share/vm/runtime/vmStructs.cpp +++ b/hotspot/src/share/vm/runtime/vmStructs.cpp @@ -1200,7 +1200,6 @@ typedef BinaryTreeDictionary MetablockTreeDictionary; /*********************************/ \ \ static_field(java_lang_Class, _klass_offset, int) \ - static_field(java_lang_Class, _resolved_constructor_offset, int) \ static_field(java_lang_Class, _array_klass_offset, int) \ static_field(java_lang_Class, _oop_size_offset, int) \ static_field(java_lang_Class, _static_oop_field_count_offset, int) \ From 9d65c6d24f2326b52541e9ae6820d8a6ad2e8448 Mon Sep 17 00:00:00 2001 From: Stefan Karlsson Date: Tue, 15 Jan 2013 10:09:45 +0100 Subject: [PATCH 031/210] 8005994: Method annotations are allocated unnecessarily during class file parsing Also reviewed by: vitalyd@gmail.com Reviewed-by: coleenp, acorn --- .../share/vm/classfile/classFileParser.cpp | 47 ++++++++++++------- hotspot/src/share/vm/prims/jvm.cpp | 7 ++- 2 files changed, 34 insertions(+), 20 deletions(-) diff --git a/hotspot/src/share/vm/classfile/classFileParser.cpp b/hotspot/src/share/vm/classfile/classFileParser.cpp index 9dd0640de06..102d551f00b 100644 --- a/hotspot/src/share/vm/classfile/classFileParser.cpp +++ b/hotspot/src/share/vm/classfile/classFileParser.cpp @@ -2475,26 +2475,38 @@ Array* ClassFileParser::parse_methods(ClassLoaderData* loader_data, *has_default_methods = true; } methods->at_put(index, method()); - if (*methods_annotations == NULL) { - *methods_annotations = - MetadataFactory::new_array(loader_data, length, NULL, CHECK_NULL); + + if (method_annotations != NULL) { + if (*methods_annotations == NULL) { + *methods_annotations = + MetadataFactory::new_array(loader_data, length, NULL, CHECK_NULL); + } + (*methods_annotations)->at_put(index, method_annotations); } - (*methods_annotations)->at_put(index, method_annotations); - if (*methods_parameter_annotations == NULL) { - *methods_parameter_annotations = - MetadataFactory::new_array(loader_data, length, NULL, CHECK_NULL); + + if (method_parameter_annotations != NULL) { + if (*methods_parameter_annotations == NULL) { + *methods_parameter_annotations = + MetadataFactory::new_array(loader_data, length, NULL, CHECK_NULL); + } + (*methods_parameter_annotations)->at_put(index, method_parameter_annotations); } - (*methods_parameter_annotations)->at_put(index, method_parameter_annotations); - if (*methods_default_annotations == NULL) { - *methods_default_annotations = - MetadataFactory::new_array(loader_data, length, NULL, CHECK_NULL); + + if (method_default_annotations != NULL) { + if (*methods_default_annotations == NULL) { + *methods_default_annotations = + MetadataFactory::new_array(loader_data, length, NULL, CHECK_NULL); + } + (*methods_default_annotations)->at_put(index, method_default_annotations); } - (*methods_default_annotations)->at_put(index, method_default_annotations); - if (*methods_type_annotations == NULL) { - *methods_type_annotations = - MetadataFactory::new_array(loader_data, length, NULL, CHECK_NULL); + + if (method_type_annotations != NULL) { + if (*methods_type_annotations == NULL) { + *methods_type_annotations = + MetadataFactory::new_array(loader_data, length, NULL, CHECK_NULL); + } + (*methods_type_annotations)->at_put(index, method_type_annotations); } - (*methods_type_annotations)->at_put(index, method_type_annotations); } if (_need_verify && length > 1) { @@ -3309,8 +3321,7 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name, bool has_final_method = false; AccessFlags promoted_flags; promoted_flags.set_flags(0); - // These need to be oop pointers because they are allocated lazily - // inside parse_methods inside a nested HandleMark + Array* methods_annotations = NULL; Array* methods_parameter_annotations = NULL; Array* methods_default_annotations = NULL; diff --git a/hotspot/src/share/vm/prims/jvm.cpp b/hotspot/src/share/vm/prims/jvm.cpp index f899aac02e7..0bf74c44bb7 100644 --- a/hotspot/src/share/vm/prims/jvm.cpp +++ b/hotspot/src/share/vm/prims/jvm.cpp @@ -1582,8 +1582,11 @@ JVM_ENTRY(jbyteArray, JVM_GetClassTypeAnnotations(JNIEnv *env, jclass cls)) if (!java_lang_Class::is_primitive(JNIHandles::resolve(cls))) { Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve(cls)); if (k->oop_is_instance()) { - typeArrayOop a = Annotations::make_java_array(InstanceKlass::cast(k)->type_annotations()->class_annotations(), CHECK_NULL); - return (jbyteArray) JNIHandles::make_local(env, a); + Annotations* type_annotations = InstanceKlass::cast(k)->type_annotations(); + if (type_annotations != NULL) { + typeArrayOop a = Annotations::make_java_array(type_annotations->class_annotations(), CHECK_NULL); + return (jbyteArray) JNIHandles::make_local(env, a); + } } } return NULL; From 5dda34f79842cfe079f94fcd169517a71621d87b Mon Sep 17 00:00:00 2001 From: Christian Thalinger Date: Tue, 15 Jan 2013 12:06:18 -0800 Subject: [PATCH 032/210] 8006109: test/java/util/AbstractSequentialList/AddAll.java fails: assert(rtype == ctype) failed: mismatched return types Reviewed-by: kvn --- hotspot/src/share/vm/ci/ciType.cpp | 16 +++++++++++++++- hotspot/src/share/vm/ci/ciType.hpp | 1 + hotspot/src/share/vm/opto/doCall.cpp | 8 +++++++- 3 files changed, 23 insertions(+), 2 deletions(-) diff --git a/hotspot/src/share/vm/ci/ciType.cpp b/hotspot/src/share/vm/ci/ciType.cpp index 47412130f04..e74dd921804 100644 --- a/hotspot/src/share/vm/ci/ciType.cpp +++ b/hotspot/src/share/vm/ci/ciType.cpp @@ -59,6 +59,19 @@ bool ciType::is_subtype_of(ciType* type) { return false; } +// ------------------------------------------------------------------ +// ciType::name +// +// Return the name of this type +const char* ciType::name() { + if (is_primitive_type()) { + return type2name(basic_type()); + } else { + assert(is_klass(), "must be"); + return as_klass()->name()->as_utf8(); + } +} + // ------------------------------------------------------------------ // ciType::print_impl // @@ -73,7 +86,8 @@ void ciType::print_impl(outputStream* st) { // // Print the name of this type void ciType::print_name_on(outputStream* st) { - st->print(type2name(basic_type())); + ResourceMark rm; + st->print(name()); } diff --git a/hotspot/src/share/vm/ci/ciType.hpp b/hotspot/src/share/vm/ci/ciType.hpp index 807ae1bec92..25f79e01263 100644 --- a/hotspot/src/share/vm/ci/ciType.hpp +++ b/hotspot/src/share/vm/ci/ciType.hpp @@ -77,6 +77,7 @@ public: bool is_type() const { return true; } bool is_classless() const { return is_primitive_type(); } + const char* name(); virtual void print_name_on(outputStream* st); void print_name() { print_name_on(tty); diff --git a/hotspot/src/share/vm/opto/doCall.cpp b/hotspot/src/share/vm/opto/doCall.cpp index 5d094c99afc..9a7562d01fb 100644 --- a/hotspot/src/share/vm/opto/doCall.cpp +++ b/hotspot/src/share/vm/opto/doCall.cpp @@ -553,7 +553,13 @@ void Parse::do_call() { rtype = ctype; } } else { - assert(rtype == ctype, "mismatched return types"); // symbolic resolution enforces this + // Symbolic resolution enforces the types to be the same. + // NOTE: We must relax the assert for unloaded types because two + // different ciType instances of the same unloaded class type + // can appear to be "loaded" by different loaders (depending on + // the accessing class). + assert(!rtype->is_loaded() || !ctype->is_loaded() || rtype == ctype, + err_msg_res("mismatched return types: rtype=%s, ctype=%s", rtype->name(), ctype->name())); } // If the return type of the method is not loaded, assert that the From b3b1b412b1e94f437b9b5bcda4d5cbb2713470f4 Mon Sep 17 00:00:00 2001 From: John Cuthbertson Date: Tue, 15 Jan 2013 12:32:26 -0800 Subject: [PATCH 033/210] 8001425: G1: Change the default values for certain G1 specific flags Changes to default and ergonomic flag values recommended by performance team. Changes were also reviewed by Monica Beckwith . Reviewed-by: brutisso, huntch --- .../src/share/vm/gc_implementation/g1/g1_globals.hpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1_globals.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1_globals.hpp index 92b1cb3fc49..d362956ea80 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1_globals.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1_globals.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2013, 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 @@ -287,24 +287,24 @@ "The number of times we'll force an overflow during " \ "concurrent marking") \ \ - experimental(uintx, G1NewSizePercent, 20, \ + experimental(uintx, G1NewSizePercent, 5, \ "Percentage (0-100) of the heap size to use as default " \ "minimum young gen size.") \ \ - experimental(uintx, G1MaxNewSizePercent, 80, \ + experimental(uintx, G1MaxNewSizePercent, 60, \ "Percentage (0-100) of the heap size to use as default " \ " maximum young gen size.") \ \ - experimental(uintx, G1MixedGCLiveThresholdPercent, 90, \ + experimental(uintx, G1MixedGCLiveThresholdPercent, 65, \ "Threshold for regions to be considered for inclusion in the " \ "collection set of mixed GCs. " \ "Regions with live bytes exceeding this will not be collected.") \ \ - product(uintx, G1HeapWastePercent, 5, \ + product(uintx, G1HeapWastePercent, 10, \ "Amount of space, expressed as a percentage of the heap size, " \ "that G1 is willing not to collect to avoid expensive GCs.") \ \ - product(uintx, G1MixedGCCountTarget, 4, \ + product(uintx, G1MixedGCCountTarget, 8, \ "The target number of mixed GCs after a marking cycle.") \ \ experimental(uintx, G1OldCSetRegionThresholdPercent, 10, \ From b60eabe8132255357077d228e597ca5d57681b02 Mon Sep 17 00:00:00 2001 From: Chris Hegarty Date: Tue, 15 Jan 2013 20:38:39 +0000 Subject: [PATCH 034/210] 8006344: Broken javadoc link in javax.lang.model.element.Element Reviewed-by: lancea, alanb, jfranck --- .../src/share/classes/javax/lang/model/element/Element.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/langtools/src/share/classes/javax/lang/model/element/Element.java b/langtools/src/share/classes/javax/lang/model/element/Element.java index b0b463df13f..a95cbe0ca95 100644 --- a/langtools/src/share/classes/javax/lang/model/element/Element.java +++ b/langtools/src/share/classes/javax/lang/model/element/Element.java @@ -188,7 +188,7 @@ public interface Element { * type if present on this element, else an empty array * * @see #getAnnotationMirrors() - * @see #getAnnotation() + * @see #getAnnotation(java.lang.Class) * @see java.lang.reflect.AnnotatedElement#getAnnotations * @see EnumConstantNotPresentException * @see AnnotationTypeMismatchException From f8b61f9b0cf65849167dda0c12c89fb5c251f5d2 Mon Sep 17 00:00:00 2001 From: Jonathan Gibbons Date: Tue, 15 Jan 2013 13:03:11 -0800 Subject: [PATCH 035/210] 8006224: Doclint NPE for attribute with no value Reviewed-by: darcy --- .../com/sun/tools/doclint/Checker.java | 18 ++-- .../doclint/resources/doclint.properties | 3 +- langtools/test/tools/doclint/AnchorTest.java | 93 +++++++++++++++++++ langtools/test/tools/doclint/AnchorTest.out | 37 ++++++++ 4 files changed, 143 insertions(+), 8 deletions(-) create mode 100644 langtools/test/tools/doclint/AnchorTest.java create mode 100644 langtools/test/tools/doclint/AnchorTest.out diff --git a/langtools/src/share/classes/com/sun/tools/doclint/Checker.java b/langtools/src/share/classes/com/sun/tools/doclint/Checker.java index 26a9cf1904d..0664838936d 100644 --- a/langtools/src/share/classes/com/sun/tools/doclint/Checker.java +++ b/langtools/src/share/classes/com/sun/tools/doclint/Checker.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2013, 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 @@ -447,14 +447,18 @@ public class Checker extends DocTreeScanner { if (currTag != HtmlTag.A) { break; } - // fallthrough + // fallthrough case ID: String value = getAttrValue(tree); - if (!validName.matcher(value).matches()) { - env.messages.error(HTML, tree, "dc.invalid.anchor", value); - } - if (!foundAnchors.add(value)) { - env.messages.error(HTML, tree, "dc.anchor.already.defined", value); + if (value == null) { + env.messages.error(HTML, tree, "dc.anchor.value.missing"); + } else { + if (!validName.matcher(value).matches()) { + env.messages.error(HTML, tree, "dc.invalid.anchor", value); + } + if (!foundAnchors.add(value)) { + env.messages.error(HTML, tree, "dc.anchor.already.defined", value); + } } break; diff --git a/langtools/src/share/classes/com/sun/tools/doclint/resources/doclint.properties b/langtools/src/share/classes/com/sun/tools/doclint/resources/doclint.properties index e85afc92d7c..33b0d7d1151 100644 --- a/langtools/src/share/classes/com/sun/tools/doclint/resources/doclint.properties +++ b/langtools/src/share/classes/com/sun/tools/doclint/resources/doclint.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2012, 2013, 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 @@ -24,6 +24,7 @@ # dc.anchor.already.defined = anchor already defined: {0} +dc.anchor.value.missing = no value given for anchor dc.attr.lacks.value = attribute lacks value dc.attr.obsolete = attribute obsolete: {0} dc.attr.obsolete.use.css = attribute obsolete, use CSS instead: {0} diff --git a/langtools/test/tools/doclint/AnchorTest.java b/langtools/test/tools/doclint/AnchorTest.java new file mode 100644 index 00000000000..08e19031b4a --- /dev/null +++ b/langtools/test/tools/doclint/AnchorTest.java @@ -0,0 +1,93 @@ +/* + * @test /nodynamiccopyright/ + * @bug 8004832 + * @summary Add new doclint package + * @build DocLintTester + * @run main DocLintTester -ref AnchorTest.out AnchorTest.java + */ + +/** */ +public class AnchorTest { + // tests for + + /** + * + */ + public void a_name_foo() { } + + /** + * + */ + public void a_name_already_defined() { } + + /** + * + */ + public void a_name_empty() { } + + /** + * + */ + public void a_name_invalid() { } + + /** + * + */ + public void a_name_missing() { } + + // tests for + + /** + * + */ + public void a_id_foo() { } + + /** + * + */ + public void a_id_already_defined() { } + + /** + * + */ + public void a_id_empty() { } + + /** + * + */ + public void a_id_invalid() { } + + /** + * + */ + public void a_id_missing() { } + + // tests for id=value on non- tags + + /** + *

text

+ */ + public void p_id_foo() { } + + /** + *

text

+ */ + public void p_id_already_defined() { } + + /** + *

text

+ */ + public void p_id_empty() { } + + /** + *

text

+ */ + public void p_id_invalid() { } + + /** + *

text

+ */ + public void p_id_missing() { } + + +} diff --git a/langtools/test/tools/doclint/AnchorTest.out b/langtools/test/tools/doclint/AnchorTest.out new file mode 100644 index 00000000000..562be5ba96c --- /dev/null +++ b/langtools/test/tools/doclint/AnchorTest.out @@ -0,0 +1,37 @@ +AnchorTest.java:19: error: anchor already defined: foo + *
+ ^ +AnchorTest.java:24: error: invalid name for anchor: "" + * + ^ +AnchorTest.java:29: error: invalid name for anchor: "123" + * + ^ +AnchorTest.java:34: error: no value given for anchor + * + ^ +AnchorTest.java:46: error: anchor already defined: foo + * + ^ +AnchorTest.java:51: error: invalid name for anchor: "" + * + ^ +AnchorTest.java:56: error: invalid name for anchor: "123" + * + ^ +AnchorTest.java:61: error: no value given for anchor + * + ^ +AnchorTest.java:73: error: anchor already defined: foo + *

text

+ ^ +AnchorTest.java:78: error: invalid name for anchor: "" + *

text

+ ^ +AnchorTest.java:83: error: invalid name for anchor: "123" + *

text

+ ^ +AnchorTest.java:88: error: no value given for anchor + *

text

+ ^ +12 errors From 84fce989ddf522c4b558064b9e6afa9aad404951 Mon Sep 17 00:00:00 2001 From: Ioi Lam Date: Tue, 15 Jan 2013 17:05:53 -0500 Subject: [PATCH 036/210] 8005467: CDS size information is incorrect and unfriendly Changed words to bytes, and added usage percentage information Reviewed-by: coleenp, twisti --- .../src/share/vm/memory/metaspaceShared.cpp | 47 +++++++++++++++---- 1 file changed, 37 insertions(+), 10 deletions(-) diff --git a/hotspot/src/share/vm/memory/metaspaceShared.cpp b/hotspot/src/share/vm/memory/metaspaceShared.cpp index 5954e43d05a..4f53114c6cd 100644 --- a/hotspot/src/share/vm/memory/metaspaceShared.cpp +++ b/hotspot/src/share/vm/memory/metaspaceShared.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2013, 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 @@ -373,17 +373,44 @@ void VM_PopulateDumpSharedSpace::doit() { md_top = wc.get_top(); // Print shared spaces all the time - const char* fmt = "%s space: " PTR_FORMAT " out of " PTR_FORMAT " words allocated at " PTR_FORMAT "."; + const char* fmt = "%s space: %9d [ %4.1f%% of total] out of %9d bytes [%4.1f%% used] at " PTR_FORMAT; Metaspace* ro_space = _loader_data->ro_metaspace(); Metaspace* rw_space = _loader_data->rw_metaspace(); - tty->print_cr(fmt, "ro", ro_space->used_words(Metaspace::NonClassType), - ro_space->capacity_words(Metaspace::NonClassType), - ro_space->bottom()); - tty->print_cr(fmt, "rw", rw_space->used_words(Metaspace::NonClassType), - rw_space->capacity_words(Metaspace::NonClassType), - rw_space->bottom()); - tty->print_cr(fmt, "md", md_top - md_low, md_end-md_low, md_low); - tty->print_cr(fmt, "mc", mc_top - mc_low, mc_end-mc_low, mc_low); + const size_t BPW = BytesPerWord; + + // Allocated size of each space (may not be all occupied) + const size_t ro_alloced = ro_space->capacity_words(Metaspace::NonClassType) * BPW; + const size_t rw_alloced = rw_space->capacity_words(Metaspace::NonClassType) * BPW; + const size_t md_alloced = md_end-md_low; + const size_t mc_alloced = mc_end-mc_low; + const size_t total_alloced = ro_alloced + rw_alloced + md_alloced + mc_alloced; + + // Occupied size of each space. + const size_t ro_bytes = ro_space->used_words(Metaspace::NonClassType) * BPW; + const size_t rw_bytes = rw_space->used_words(Metaspace::NonClassType) * BPW; + const size_t md_bytes = size_t(md_top - md_low); + const size_t mc_bytes = size_t(mc_top - mc_low); + + // Percent of total size + const size_t total_bytes = ro_bytes + rw_bytes + md_bytes + mc_bytes; + const double ro_t_perc = ro_bytes / double(total_bytes) * 100.0; + const double rw_t_perc = rw_bytes / double(total_bytes) * 100.0; + const double md_t_perc = md_bytes / double(total_bytes) * 100.0; + const double mc_t_perc = mc_bytes / double(total_bytes) * 100.0; + + // Percent of fullness of each space + const double ro_u_perc = ro_bytes / double(ro_alloced) * 100.0; + const double rw_u_perc = rw_bytes / double(rw_alloced) * 100.0; + const double md_u_perc = md_bytes / double(md_alloced) * 100.0; + const double mc_u_perc = mc_bytes / double(mc_alloced) * 100.0; + const double total_u_perc = total_bytes / double(total_alloced) * 100.0; + + tty->print_cr(fmt, "ro", ro_bytes, ro_t_perc, ro_alloced, ro_u_perc, ro_space->bottom()); + tty->print_cr(fmt, "rw", rw_bytes, rw_t_perc, rw_alloced, rw_u_perc, rw_space->bottom()); + tty->print_cr(fmt, "md", md_bytes, md_t_perc, md_alloced, md_u_perc, md_low); + tty->print_cr(fmt, "mc", mc_bytes, mc_t_perc, mc_alloced, mc_u_perc, mc_low); + tty->print_cr("total : %9d [100.0%% of total] out of %9d bytes [%4.1f%% used]", + total_bytes, total_alloced, total_u_perc); // Update the vtable pointers in all of the Klass objects in the // heap. They should point to newly generated vtable. From cc15237ca514c501a2e9ffff0386d4d890634d83 Mon Sep 17 00:00:00 2001 From: David Chase Date: Tue, 15 Jan 2013 14:45:12 -0800 Subject: [PATCH 037/210] 8005821: C2: -XX:+PrintIntrinsics is broken Check all print inlining flags when processing inlining list. Reviewed-by: kvn, twisti --- hotspot/src/share/vm/opto/compile.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/hotspot/src/share/vm/opto/compile.cpp b/hotspot/src/share/vm/opto/compile.cpp index f090939186d..ae9d6996a9c 100644 --- a/hotspot/src/share/vm/opto/compile.cpp +++ b/hotspot/src/share/vm/opto/compile.cpp @@ -692,7 +692,7 @@ Compile::Compile( ciEnv* ci_env, C2Compiler* compiler, ciMethod* target, int osr PhaseGVN gvn(node_arena(), estimated_size); set_initial_gvn(&gvn); - if (PrintInlining) { + if (PrintInlining || PrintIntrinsics NOT_PRODUCT( || PrintOptoInlining)) { _print_inlining_list = new (comp_arena())GrowableArray(comp_arena(), 1, 1, PrintInliningBuffer()); } { // Scope for timing the parser @@ -2049,7 +2049,7 @@ void Compile::Optimize() { } // (End scope of igvn; run destructor if necessary for asserts.) - dump_inlining(); + dump_inlining(); // A method with only infinite loops has no edges entering loops from root { NOT_PRODUCT( TracePhase t2("graphReshape", &_t_graphReshaping, TimeCompiler); ) @@ -3497,7 +3497,7 @@ void Compile::ConstantTable::fill_jump_table(CodeBuffer& cb, MachConstantNode* n } void Compile::dump_inlining() { - if (PrintInlining) { + if (PrintInlining || PrintIntrinsics NOT_PRODUCT( || PrintOptoInlining)) { // Print inlining message for candidates that we couldn't inline // for lack of space or non constant receiver for (int i = 0; i < _late_inlines.length(); i++) { From 38f6de7a0c6a19c03261545c3bdd8875632310de Mon Sep 17 00:00:00 2001 From: Bengt Rutisson Date: Wed, 16 Jan 2013 12:46:27 +0100 Subject: [PATCH 038/210] 8006242: G1: WorkerDataArray::verify() too strict for double calculations Also reviewed by vitalyd@gmail.com. Reviewed-by: johnc, mgerdin --- .../gc_implementation/g1/g1GCPhaseTimes.cpp | 34 +++++++++++-------- .../gc_implementation/g1/g1GCPhaseTimes.hpp | 2 ++ 2 files changed, 22 insertions(+), 14 deletions(-) diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1GCPhaseTimes.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1GCPhaseTimes.cpp index 7a102cf43d7..9782b67c007 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1GCPhaseTimes.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1GCPhaseTimes.cpp @@ -131,17 +131,23 @@ void WorkerDataArray::print(int level, const char* title) { #ifndef PRODUCT +template <> const int WorkerDataArray::_uninitialized = -1; +template <> const double WorkerDataArray::_uninitialized = -1.0; +template <> const size_t WorkerDataArray::_uninitialized = (size_t)-1; + template void WorkerDataArray::reset() { for (uint i = 0; i < _length; i++) { - _data[i] = (T)-1; + _data[i] = (T)_uninitialized; } } template void WorkerDataArray::verify() { for (uint i = 0; i < _length; i++) { - assert(_data[i] >= (T)0, err_msg("Invalid data for worker %d", i)); + assert(_data[i] != _uninitialized, + err_msg("Invalid data for worker " UINT32_FORMAT ", data: %lf, uninitialized: %lf", + i, (double)_data[i], (double)_uninitialized)); } } @@ -201,20 +207,20 @@ void G1GCPhaseTimes::note_gc_end() { _last_termination_attempts.verify(); _last_gc_worker_end_times_ms.verify(); - for (uint i = 0; i < _active_gc_threads; i++) { - double worker_time = _last_gc_worker_end_times_ms.get(i) - _last_gc_worker_start_times_ms.get(i); - _last_gc_worker_times_ms.set(i, worker_time); + for (uint i = 0; i < _active_gc_threads; i++) { + double worker_time = _last_gc_worker_end_times_ms.get(i) - _last_gc_worker_start_times_ms.get(i); + _last_gc_worker_times_ms.set(i, worker_time); - double worker_known_time = _last_ext_root_scan_times_ms.get(i) + - _last_satb_filtering_times_ms.get(i) + - _last_update_rs_times_ms.get(i) + - _last_scan_rs_times_ms.get(i) + - _last_obj_copy_times_ms.get(i) + - _last_termination_times_ms.get(i); + double worker_known_time = _last_ext_root_scan_times_ms.get(i) + + _last_satb_filtering_times_ms.get(i) + + _last_update_rs_times_ms.get(i) + + _last_scan_rs_times_ms.get(i) + + _last_obj_copy_times_ms.get(i) + + _last_termination_times_ms.get(i); - double worker_other_time = worker_time - worker_known_time; - _last_gc_worker_other_times_ms.set(i, worker_other_time); - } + double worker_other_time = worker_time - worker_known_time; + _last_gc_worker_other_times_ms.set(i, worker_other_time); + } _last_gc_worker_times_ms.verify(); _last_gc_worker_other_times_ms.verify(); diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1GCPhaseTimes.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1GCPhaseTimes.hpp index 99e35c63d43..b6e289ed22a 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1GCPhaseTimes.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1GCPhaseTimes.hpp @@ -35,6 +35,8 @@ class WorkerDataArray : public CHeapObj { const char* _print_format; bool _print_sum; + NOT_PRODUCT(static const T _uninitialized;) + // We are caching the sum and average to only have to calculate them once. // This is not done in an MT-safe way. It is intetened to allow single // threaded code to call sum() and average() multiple times in any order From 07e2e8803a15230e63049d07beaa1c639a86cb70 Mon Sep 17 00:00:00 2001 From: Aleksey Shipilev Date: Wed, 16 Jan 2013 16:30:04 +0100 Subject: [PATCH 039/210] 8006403: Regression: jstack failed due to the FieldInfo regression in SA Reviewed-by: sla, dholmes --- .../src/share/classes/sun/jvm/hotspot/oops/InstanceKlass.java | 4 +++- hotspot/src/share/vm/runtime/vmStructs.cpp | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/InstanceKlass.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/InstanceKlass.java index 7052f8a2d18..cfa26eacdbd 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/InstanceKlass.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/InstanceKlass.java @@ -53,6 +53,7 @@ public class InstanceKlass extends Klass { private static int HIGH_OFFSET; private static int FIELD_SLOTS; private static short FIELDINFO_TAG_SIZE; + private static short FIELDINFO_TAG_MASK; private static short FIELDINFO_TAG_OFFSET; // ClassState constants @@ -102,6 +103,7 @@ public class InstanceKlass extends Klass { HIGH_OFFSET = db.lookupIntConstant("FieldInfo::high_packed_offset").intValue(); FIELD_SLOTS = db.lookupIntConstant("FieldInfo::field_slots").intValue(); FIELDINFO_TAG_SIZE = db.lookupIntConstant("FIELDINFO_TAG_SIZE").shortValue(); + FIELDINFO_TAG_MASK = db.lookupIntConstant("FIELDINFO_TAG_MASK").shortValue(); FIELDINFO_TAG_OFFSET = db.lookupIntConstant("FIELDINFO_TAG_OFFSET").shortValue(); // read ClassState constants @@ -321,7 +323,7 @@ public class InstanceKlass extends Klass { U2Array fields = getFields(); short lo = fields.at(index * FIELD_SLOTS + LOW_OFFSET); short hi = fields.at(index * FIELD_SLOTS + HIGH_OFFSET); - if ((lo & FIELDINFO_TAG_SIZE) == FIELDINFO_TAG_OFFSET) { + if ((lo & FIELDINFO_TAG_MASK) == FIELDINFO_TAG_OFFSET) { return VM.getVM().buildIntFromShorts(lo, hi) >> FIELDINFO_TAG_SIZE; } throw new RuntimeException("should not reach here"); diff --git a/hotspot/src/share/vm/runtime/vmStructs.cpp b/hotspot/src/share/vm/runtime/vmStructs.cpp index 8d454992cf8..791a317af17 100644 --- a/hotspot/src/share/vm/runtime/vmStructs.cpp +++ b/hotspot/src/share/vm/runtime/vmStructs.cpp @@ -2292,6 +2292,7 @@ typedef BinaryTreeDictionary MetablockTreeDictionary; /*************************************/ \ \ declare_preprocessor_constant("FIELDINFO_TAG_SIZE", FIELDINFO_TAG_SIZE) \ + declare_preprocessor_constant("FIELDINFO_TAG_MASK", FIELDINFO_TAG_MASK) \ declare_preprocessor_constant("FIELDINFO_TAG_OFFSET", FIELDINFO_TAG_OFFSET) \ \ /************************************************/ \ From d19bc80ca1d894550267d873414eb382bebb4bc4 Mon Sep 17 00:00:00 2001 From: Maurizio Cimadamore Date: Wed, 16 Jan 2013 16:27:01 +0000 Subject: [PATCH 040/210] 8005854: Add support for array constructor references Support constructor references of the kind int[]::new Reviewed-by: jjg --- .../com/sun/tools/javac/comp/Check.java | 34 ++++++++---- .../sun/tools/javac/comp/LambdaToMethod.java | 44 +++++++++------ .../com/sun/tools/javac/comp/Resolve.java | 46 +++++++++++++++- .../com/sun/tools/javac/tree/JCTree.java | 4 +- .../tools/javac/lambda/MethodReference59.java | 52 ++++++++++++++++++ .../tools/javac/lambda/MethodReference60.java | 55 +++++++++++++++++++ .../tools/javac/lambda/MethodReference60.out | 6 ++ 7 files changed, 209 insertions(+), 32 deletions(-) create mode 100644 langtools/test/tools/javac/lambda/MethodReference59.java create mode 100644 langtools/test/tools/javac/lambda/MethodReference60.java create mode 100644 langtools/test/tools/javac/lambda/MethodReference60.out diff --git a/langtools/src/share/classes/com/sun/tools/javac/comp/Check.java b/langtools/src/share/classes/com/sun/tools/javac/comp/Check.java index bcc9aa32bcb..16bf5e43cfa 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/comp/Check.java +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Check.java @@ -634,25 +634,40 @@ public class Check { } } + Type checkClassOrArrayType(DiagnosticPosition pos, Type t) { + if (!t.hasTag(CLASS) && !t.hasTag(ARRAY) && !t.hasTag(ERROR)) { + return typeTagError(pos, + diags.fragment("type.req.class.array"), + asTypeParam(t)); + } else { + return t; + } + } + /** Check that type is a class or interface type. * @param pos Position to be used for error reporting. * @param t The type to be checked. */ Type checkClassType(DiagnosticPosition pos, Type t) { - if (!t.hasTag(CLASS) && !t.hasTag(ERROR)) + if (!t.hasTag(CLASS) && !t.hasTag(ERROR)) { return typeTagError(pos, diags.fragment("type.req.class"), - (t.hasTag(TYPEVAR)) - ? diags.fragment("type.parameter", t) - : t); - else + asTypeParam(t)); + } else { return t; + } } + //where + private Object asTypeParam(Type t) { + return (t.hasTag(TYPEVAR)) + ? diags.fragment("type.parameter", t) + : t; + } /** Check that type is a valid qualifier for a constructor reference expression */ Type checkConstructorRefType(DiagnosticPosition pos, Type t) { - t = checkClassType(pos, t); + t = checkClassOrArrayType(pos, t); if (t.hasTag(CLASS)) { if ((t.tsym.flags() & (ABSTRACT | INTERFACE)) != 0) { log.error(pos, "abstract.cant.be.instantiated"); @@ -690,11 +705,8 @@ public class Check { * @param t The type to be checked. */ Type checkReifiableReferenceType(DiagnosticPosition pos, Type t) { - if (!t.hasTag(CLASS) && !t.hasTag(ARRAY) && !t.hasTag(ERROR)) { - return typeTagError(pos, - diags.fragment("type.req.class.array"), - t); - } else if (!types.isReifiable(t)) { + t = checkClassOrArrayType(pos, t); + if (!t.isErroneous() && !types.isReifiable(t)) { log.error(pos, "illegal.generic.type.for.instof"); return types.createErrorType(t); } else { diff --git a/langtools/src/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java b/langtools/src/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java index 6ad3da8ddae..f7af35aaed3 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java @@ -302,6 +302,7 @@ public class LambdaToMethod extends TreeTranslator { case UNBOUND: /** Type :: instMethod */ case STATIC: /** Type :: staticMethod */ case TOPLEVEL: /** Top level :: new */ + case ARRAY_CTOR: /** ArrayType :: new */ init = null; break; @@ -645,24 +646,33 @@ public class LambdaToMethod extends TreeTranslator { * to the first bridge synthetic parameter */ private JCExpression bridgeExpressionNew() { - JCExpression encl = null; - switch (tree.kind) { - case UNBOUND: - case IMPLICIT_INNER: - encl = make.Ident(params.first()); - } + if (tree.kind == ReferenceKind.ARRAY_CTOR) { + //create the array creation expression + JCNewArray newArr = make.NewArray(make.Type(types.elemtype(tree.getQualifierExpression().type)), + List.of(make.Ident(params.first())), + null); + newArr.type = tree.getQualifierExpression().type; + return newArr; + } else { + JCExpression encl = null; + switch (tree.kind) { + case UNBOUND: + case IMPLICIT_INNER: + encl = make.Ident(params.first()); + } - //create the instance creation expression - JCNewClass newClass = make.NewClass(encl, - List.nil(), - make.Type(tree.getQualifierExpression().type), - convertArgs(tree.sym, args.toList(), tree.varargsElement), - null); - newClass.constructor = tree.sym; - newClass.constructorType = tree.sym.erasure(types); - newClass.type = tree.getQualifierExpression().type; - setVarargsIfNeeded(newClass, tree.varargsElement); - return newClass; + //create the instance creation expression + JCNewClass newClass = make.NewClass(encl, + List.nil(), + make.Type(tree.getQualifierExpression().type), + convertArgs(tree.sym, args.toList(), tree.varargsElement), + null); + newClass.constructor = tree.sym; + newClass.constructorType = tree.sym.erasure(types); + newClass.type = tree.getQualifierExpression().type; + setVarargsIfNeeded(newClass, tree.varargsElement); + return newClass; + } } private VarSymbol addParameter(String name, Type p, boolean genArg) { diff --git a/langtools/src/share/classes/com/sun/tools/javac/comp/Resolve.java b/langtools/src/share/classes/com/sun/tools/javac/comp/Resolve.java index 4b6cab1bf0e..d5adb408242 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/comp/Resolve.java +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Resolve.java @@ -2386,10 +2386,23 @@ public class Resolve { List typeargtypes, boolean boxingAllowed) { MethodResolutionPhase maxPhase = boxingAllowed ? VARARITY : BASIC; + + ReferenceLookupHelper boundLookupHelper; + if (!name.equals(names.init)) { + //method reference + boundLookupHelper = + new MethodReferenceLookupHelper(referenceTree, name, site, argtypes, typeargtypes, maxPhase); + } else if (site.hasTag(ARRAY)) { + //array constructor reference + boundLookupHelper = + new ArrayConstructorReferenceLookupHelper(referenceTree, site, argtypes, typeargtypes, maxPhase); + } else { + //class constructor reference + boundLookupHelper = + new ConstructorReferenceLookupHelper(referenceTree, site, argtypes, typeargtypes, maxPhase); + } + //step 1 - bound lookup - ReferenceLookupHelper boundLookupHelper = name.equals(names.init) ? - new ConstructorReferenceLookupHelper(referenceTree, site, argtypes, typeargtypes, maxPhase) : - new MethodReferenceLookupHelper(referenceTree, name, site, argtypes, typeargtypes, maxPhase); Env boundEnv = env.dup(env.tree, env.info.dup()); Symbol boundSym = lookupMethod(boundEnv, env.tree.pos(), site.tsym, boundLookupHelper); @@ -2626,6 +2639,33 @@ public class Resolve { } } + /** + * Helper class for array constructor lookup; an array constructor lookup + * is simulated by looking up a method that returns the array type specified + * as qualifier, and that accepts a single int parameter (size of the array). + */ + class ArrayConstructorReferenceLookupHelper extends ReferenceLookupHelper { + + ArrayConstructorReferenceLookupHelper(JCMemberReference referenceTree, Type site, List argtypes, + List typeargtypes, MethodResolutionPhase maxPhase) { + super(referenceTree, names.init, site, argtypes, typeargtypes, maxPhase); + } + + @Override + protected Symbol lookup(Env env, MethodResolutionPhase phase) { + Scope sc = new Scope(syms.arrayClass); + MethodSymbol arrayConstr = new MethodSymbol(PUBLIC, name, null, site.tsym); + arrayConstr.type = new MethodType(List.of(syms.intType), site, List.nil(), syms.methodClass); + sc.enter(arrayConstr); + return findMethodInScope(env, site, name, argtypes, typeargtypes, sc, methodNotFound, phase.isBoxingRequired(), phase.isVarargsRequired(), false, false); + } + + @Override + ReferenceKind referenceKind(Symbol sym) { + return ReferenceKind.ARRAY_CTOR; + } + } + /** * Helper class for constructor reference lookup. The lookup logic is based * upon either Resolve.findMethod or Resolve.findDiamond - depending on diff --git a/langtools/src/share/classes/com/sun/tools/javac/tree/JCTree.java b/langtools/src/share/classes/com/sun/tools/javac/tree/JCTree.java index 269890eeb2b..f28a8cf4a52 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/tree/JCTree.java +++ b/langtools/src/share/classes/com/sun/tools/javac/tree/JCTree.java @@ -1838,7 +1838,9 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition { /** Inner # new */ IMPLICIT_INNER(ReferenceMode.NEW, false), /** Toplevel # new */ - TOPLEVEL(ReferenceMode.NEW, false); + TOPLEVEL(ReferenceMode.NEW, false), + /** ArrayType # new */ + ARRAY_CTOR(ReferenceMode.NEW, false); final ReferenceMode mode; final boolean unbound; diff --git a/langtools/test/tools/javac/lambda/MethodReference59.java b/langtools/test/tools/javac/lambda/MethodReference59.java new file mode 100644 index 00000000000..76b6669e313 --- /dev/null +++ b/langtools/test/tools/javac/lambda/MethodReference59.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2012, 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. + * + * 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. + */ + +/* + * @test + * @bug 8004102 + * @summary Add support for array constructor references + */ +public class MethodReference59 { + + static int assertionCount = 0; + + static void assertTrue(boolean cond) { + assertionCount++; + if (!cond) + throw new AssertionError(); + } + + interface ArrayFactory { + X make(int size); + } + + public static void main(String[] args) { + ArrayFactory factory1 = int[]::new; + int[] i1 = factory1.make(5); + assertTrue(i1.length == 5); + ArrayFactory factory2 = int[][]::new; + int[][] i2 = factory2.make(5); + assertTrue(i2.length == 5); + assertTrue(assertionCount == 2); + } +} diff --git a/langtools/test/tools/javac/lambda/MethodReference60.java b/langtools/test/tools/javac/lambda/MethodReference60.java new file mode 100644 index 00000000000..f8317af36e2 --- /dev/null +++ b/langtools/test/tools/javac/lambda/MethodReference60.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2012, 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. + * + * 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. + */ + +/* + * @test + * @bug 8004102 + * @summary Add support for array constructor references + * @compile/fail/ref=MethodReference60.out -XDrawDiagnostics MethodReference60.java + */ +public class MethodReference60 { + + interface ArrayFactory { + X make(int size); + } + + interface BadArrayFactory1 { + X make(); + } + + interface BadArrayFactory2 { + X make(int i1, int i2); + } + + interface BadArrayFactory3 { + X make(String s); + } + + public static void main(String[] args) { + BadArrayFactory1 factory1 = int[]::new; //param mismatch + BadArrayFactory2 factory2 = int[]::new; //param mismatch + BadArrayFactory3 factory3 = int[]::new; //param mismatch + ArrayFactory factory4 = int[]::new; //return type mismatch + ArrayFactory factory5 = int[]::new; //return type mismatch + } +} diff --git a/langtools/test/tools/javac/lambda/MethodReference60.out b/langtools/test/tools/javac/lambda/MethodReference60.out new file mode 100644 index 00000000000..5aa973cf2ad --- /dev/null +++ b/langtools/test/tools/javac/lambda/MethodReference60.out @@ -0,0 +1,6 @@ +MethodReference60.java:49:44: compiler.err.prob.found.req: (compiler.misc.invalid.mref: kindname.constructor, (compiler.misc.cant.apply.symbol: kindname.constructor, Array, int, compiler.misc.no.args, kindname.class, Array, (compiler.misc.arg.length.mismatch))) +MethodReference60.java:50:44: compiler.err.prob.found.req: (compiler.misc.invalid.mref: kindname.constructor, (compiler.misc.cant.apply.symbol: kindname.constructor, Array, int, int,int, kindname.class, Array, (compiler.misc.arg.length.mismatch))) +MethodReference60.java:51:44: compiler.err.prob.found.req: (compiler.misc.invalid.mref: kindname.constructor, (compiler.misc.cant.apply.symbol: kindname.constructor, Array, int, java.lang.String, kindname.class, Array, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.inconvertible.types: java.lang.String, int)))) +MethodReference60.java:52:42: compiler.err.prob.found.req: (compiler.misc.incompatible.ret.type.in.mref: (compiler.misc.inconvertible.types: int[], java.lang.Integer)) +MethodReference60.java:53:44: compiler.err.prob.found.req: (compiler.misc.incompatible.ret.type.in.mref: (compiler.misc.inconvertible.types: int[], java.lang.Integer[])) +5 errors From 3b3feb3853f5bc44a5c3b62049a2d4c9789ccf41 Mon Sep 17 00:00:00 2001 From: Maurizio Cimadamore Date: Wed, 16 Jan 2013 16:30:11 +0000 Subject: [PATCH 041/210] 8005299: Add FunctionalInterface checking to javac Javac should check that types annotated with @FunctionalInterface are indeed functional interfaces Reviewed-by: jjg --- .../com/sun/tools/javac/code/Symtab.java | 2 ++ .../com/sun/tools/javac/code/Types.java | 8 ++--- .../com/sun/tools/javac/comp/Check.java | 12 +++++++ .../tools/javac/resources/compiler.properties | 17 +++++++--- .../javac/util/RichDiagnosticFormatter.java | 2 +- .../tools/javac/diags/examples.not-yet.txt | 1 + .../diags/examples/BadFunctionalIntfAnno.java | 28 ++++++++++++++++ .../test/tools/javac/lambda/BadConv03.out | 2 +- .../test/tools/javac/lambda/BadLambdaPos.out | 4 +-- .../test/tools/javac/lambda/BadTargetType.out | 8 ++--- .../javac/lambda/FunctionalInterfaceAnno.java | 33 +++++++++++++++++++ .../javac/lambda/FunctionalInterfaceAnno.out | 9 +++++ .../tools/javac/lambda/Intersection01.out | 4 +-- .../test/tools/javac/lambda/LambdaConv09.out | 8 ++--- .../test/tools/javac/lambda/LambdaExpr10.out | 12 +++---- .../tools/javac/lambda/MethodReference04.out | 2 +- .../test/tools/javac/lambda/TargetType17.out | 16 ++++----- .../test/tools/javac/lambda/TargetType43.out | 4 +-- .../funcInterfaces/LambdaTest2_neg1.out | 2 +- .../javac/lambda/funcInterfaces/NonSAM1.out | 2 +- .../javac/lambda/funcInterfaces/NonSAM3.out | 16 ++++----- .../lambdaExpression/AbstractClass_neg.out | 2 +- .../lambdaExpression/InvalidExpression5.out | 2 +- 23 files changed, 145 insertions(+), 51 deletions(-) create mode 100644 langtools/test/tools/javac/diags/examples/BadFunctionalIntfAnno.java create mode 100644 langtools/test/tools/javac/lambda/FunctionalInterfaceAnno.java create mode 100644 langtools/test/tools/javac/lambda/FunctionalInterfaceAnno.out diff --git a/langtools/src/share/classes/com/sun/tools/javac/code/Symtab.java b/langtools/src/share/classes/com/sun/tools/javac/code/Symtab.java index 17535be2053..2ec60dbf432 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/code/Symtab.java +++ b/langtools/src/share/classes/com/sun/tools/javac/code/Symtab.java @@ -164,6 +164,7 @@ public class Symtab { public final Type repeatableType; public final Type documentedType; public final Type elementTypeType; + public final Type functionalInterfaceType; /** The symbol representing the length field of an array. */ @@ -507,6 +508,7 @@ public class Symtab { nativeHeaderType = enterClass("java.lang.annotation.Native"); nativeHeaderType_old = enterClass("javax.tools.annotation.GenerateNativeHeader"); lambdaMetafactory = enterClass("java.lang.invoke.LambdaMetafactory"); + functionalInterfaceType = enterClass("java.lang.FunctionalInterface"); synthesizeEmptyInterfaceIfMissing(autoCloseableType); synthesizeEmptyInterfaceIfMissing(cloneableType); diff --git a/langtools/src/share/classes/com/sun/tools/javac/code/Types.java b/langtools/src/share/classes/com/sun/tools/javac/code/Types.java index a7378f8acfe..2a3946716d4 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/code/Types.java +++ b/langtools/src/share/classes/com/sun/tools/javac/code/Types.java @@ -392,9 +392,9 @@ public class Types { * Compute the function descriptor associated with a given functional interface */ public FunctionDescriptor findDescriptorInternal(TypeSymbol origin, CompoundScope membersCache) throws FunctionDescriptorLookupError { - if (!origin.isInterface()) { + if (!origin.isInterface() || (origin.flags() & ANNOTATION) != 0) { //t must be an interface - throw failure("not.a.functional.intf"); + throw failure("not.a.functional.intf", origin); } final ListBuffer abstracts = ListBuffer.lb(); @@ -406,13 +406,13 @@ public class Types { abstracts.append(sym); } else { //the target method(s) should be the only abstract members of t - throw failure("not.a.functional.intf.1", + throw failure("not.a.functional.intf.1", origin, diags.fragment("incompatible.abstracts", Kinds.kindName(origin), origin)); } } if (abstracts.isEmpty()) { //t must define a suitable non-generic method - throw failure("not.a.functional.intf.1", + throw failure("not.a.functional.intf.1", origin, diags.fragment("no.abstracts", Kinds.kindName(origin), origin)); } else if (abstracts.size() == 1) { return new FunctionDescriptor(abstracts.first()); diff --git a/langtools/src/share/classes/com/sun/tools/javac/comp/Check.java b/langtools/src/share/classes/com/sun/tools/javac/comp/Check.java index 16bf5e43cfa..0ad9c099199 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/comp/Check.java +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Check.java @@ -2601,6 +2601,18 @@ public class Check { if (!isOverrider(s)) log.error(a.pos(), "method.does.not.override.superclass"); } + + if (a.annotationType.type.tsym == syms.functionalInterfaceType.tsym) { + if (s.kind != TYP) { + log.error(a.pos(), "bad.functional.intf.anno"); + } else { + try { + types.findDescriptorSymbol((TypeSymbol)s); + } catch (Types.FunctionDescriptorLookupError ex) { + log.error(a.pos(), "bad.functional.intf.anno.1", ex.getDiagnostic()); + } + } + } } /** diff --git a/langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties b/langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties index 41c89491c63..f04abc7c42a 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties +++ b/langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties @@ -178,14 +178,23 @@ compiler.misc.no.abstracts=\ compiler.misc.incompatible.abstracts=\ multiple non-overriding abstract methods found in {0} {1} -compiler.misc.not.a.functional.intf=\ - the target type must be a functional interface +compiler.err.bad.functional.intf.anno=\ + Unexpected @FunctionalInterface annotation # 0: message segment -compiler.misc.not.a.functional.intf.1=\ - the target type must be a functional interface\n\ +compiler.err.bad.functional.intf.anno.1=\ + Unexpected @FunctionalInterface annotation\n\ {0} +# 0: symbol +compiler.misc.not.a.functional.intf=\ + {0} is not a functional interface + +# 0: symbol, 1: message segment +compiler.misc.not.a.functional.intf.1=\ + {0} is not a functional interface\n\ + {1} + # 0: symbol, 1: symbol kind, 2: symbol compiler.misc.invalid.generic.lambda.target=\ invalid functional descriptor for lambda expression\n\ diff --git a/langtools/src/share/classes/com/sun/tools/javac/util/RichDiagnosticFormatter.java b/langtools/src/share/classes/com/sun/tools/javac/util/RichDiagnosticFormatter.java index 46867d5fa75..7c5849d2758 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/util/RichDiagnosticFormatter.java +++ b/langtools/src/share/classes/com/sun/tools/javac/util/RichDiagnosticFormatter.java @@ -288,7 +288,7 @@ public class RichDiagnosticFormatter extends public String simplify(Symbol s) { String name = s.getQualifiedName().toString(); - if (!s.type.isCompound()) { + if (!s.type.isCompound() && !s.type.isPrimitive()) { List conflicts = nameClashes.get(s.getSimpleName()); if (conflicts == null || (conflicts.size() == 1 && diff --git a/langtools/test/tools/javac/diags/examples.not-yet.txt b/langtools/test/tools/javac/diags/examples.not-yet.txt index ef2b5c84e5a..1cc337e69fa 100644 --- a/langtools/test/tools/javac/diags/examples.not-yet.txt +++ b/langtools/test/tools/javac/diags/examples.not-yet.txt @@ -1,6 +1,7 @@ compiler.err.already.annotated # internal compiler error? compiler.err.already.defined.this.unit # seems to be masked by compiler.err.duplicate.class compiler.err.annotation.value.not.allowable.type # cannot happen: precluded by complete type-specific tests +compiler.err.bad.functional.intf.anno # seems to be masked by compiler.err.annotation.type.not.applicable compiler.err.cant.read.file # (apt.JavaCompiler?) compiler.err.cant.select.static.class.from.param.type compiler.err.dc.unterminated.string # cannot happen diff --git a/langtools/test/tools/javac/diags/examples/BadFunctionalIntfAnno.java b/langtools/test/tools/javac/diags/examples/BadFunctionalIntfAnno.java new file mode 100644 index 00000000000..87090505bd2 --- /dev/null +++ b/langtools/test/tools/javac/diags/examples/BadFunctionalIntfAnno.java @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2013, 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. + * + * 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. + */ + +// key: compiler.err.bad.functional.intf.anno.1 +// key: compiler.misc.not.a.functional.intf + +@FunctionalInterface +class BadFunctionalIntfAnno { } diff --git a/langtools/test/tools/javac/lambda/BadConv03.out b/langtools/test/tools/javac/lambda/BadConv03.out index 078f304f413..210148069a8 100644 --- a/langtools/test/tools/javac/lambda/BadConv03.out +++ b/langtools/test/tools/javac/lambda/BadConv03.out @@ -1,2 +1,2 @@ -BadConv03.java:19:11: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf.1: (compiler.misc.incompatible.abstracts: kindname.interface, BadConv03.B)) +BadConv03.java:19:11: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf.1: BadConv03.B, (compiler.misc.incompatible.abstracts: kindname.interface, BadConv03.B)) 1 error diff --git a/langtools/test/tools/javac/lambda/BadLambdaPos.out b/langtools/test/tools/javac/lambda/BadLambdaPos.out index b2436d9ca1a..d192495c9c6 100644 --- a/langtools/test/tools/javac/lambda/BadLambdaPos.out +++ b/langtools/test/tools/javac/lambda/BadLambdaPos.out @@ -4,6 +4,6 @@ BadLambdaPos.java:19:14: compiler.err.unexpected.lambda BadLambdaPos.java:23:18: compiler.err.unexpected.lambda BadLambdaPos.java:23:34: compiler.err.unexpected.lambda BadLambdaPos.java:24:21: compiler.err.unexpected.lambda -BadLambdaPos.java:28:22: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf) -BadLambdaPos.java:29:28: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf) +BadLambdaPos.java:28:22: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf: java.lang.Object) +BadLambdaPos.java:29:28: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf: java.lang.Object) 8 errors diff --git a/langtools/test/tools/javac/lambda/BadTargetType.out b/langtools/test/tools/javac/lambda/BadTargetType.out index 8979631251b..122b4c833e4 100644 --- a/langtools/test/tools/javac/lambda/BadTargetType.out +++ b/langtools/test/tools/javac/lambda/BadTargetType.out @@ -1,5 +1,5 @@ -BadTargetType.java:16:24: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf) -BadTargetType.java:17:17: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf) -BadTargetType.java:20:9: compiler.err.cant.apply.symbol: kindname.method, m1, java.lang.Object, @460, kindname.class, BadTargetType, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.not.a.functional.intf)) -BadTargetType.java:21:9: compiler.err.cant.apply.symbol: kindname.method, m2, java.lang.Object, @489, kindname.class, BadTargetType, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.not.a.functional.intf)) +BadTargetType.java:16:24: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf: java.lang.Object) +BadTargetType.java:17:17: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf: java.lang.Object) +BadTargetType.java:20:9: compiler.err.cant.apply.symbol: kindname.method, m1, java.lang.Object, @460, kindname.class, BadTargetType, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.not.a.functional.intf: java.lang.Object)) +BadTargetType.java:21:9: compiler.err.cant.apply.symbol: kindname.method, m2, java.lang.Object, @489, kindname.class, BadTargetType, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.not.a.functional.intf: java.lang.Object)) 4 errors diff --git a/langtools/test/tools/javac/lambda/FunctionalInterfaceAnno.java b/langtools/test/tools/javac/lambda/FunctionalInterfaceAnno.java new file mode 100644 index 00000000000..49248a0e378 --- /dev/null +++ b/langtools/test/tools/javac/lambda/FunctionalInterfaceAnno.java @@ -0,0 +1,33 @@ +/* + * @test /nodynamiccopyright/ + * @summary smoke test for functional interface annotation + * @compile/fail/ref=FunctionalInterfaceAnno.out -XDrawDiagnostics FunctionalInterfaceAnno.java + */ +class FunctionalInterfaceAnno { + @FunctionalInterface + static class A { } //not an interface + + @FunctionalInterface + static abstract class B { } //not an interface + + @FunctionalInterface + enum C { } //not an interface + + @FunctionalInterface + @interface D { } //not an interface + + @FunctionalInterface + interface E { } //no abstracts + + @FunctionalInterface + interface F { default void m() { } } //no abstracts + + @FunctionalInterface + interface G { String toString(); } //no abstracts + + @FunctionalInterface + interface H { void m(); void n(); } //incompatible abstracts + + @FunctionalInterface + interface I { void m(); } //ok +} diff --git a/langtools/test/tools/javac/lambda/FunctionalInterfaceAnno.out b/langtools/test/tools/javac/lambda/FunctionalInterfaceAnno.out new file mode 100644 index 00000000000..d6b8c398bc6 --- /dev/null +++ b/langtools/test/tools/javac/lambda/FunctionalInterfaceAnno.out @@ -0,0 +1,9 @@ +FunctionalInterfaceAnno.java:7:5: compiler.err.bad.functional.intf.anno.1: (compiler.misc.not.a.functional.intf: FunctionalInterfaceAnno.A) +FunctionalInterfaceAnno.java:10:5: compiler.err.bad.functional.intf.anno.1: (compiler.misc.not.a.functional.intf: FunctionalInterfaceAnno.B) +FunctionalInterfaceAnno.java:13:5: compiler.err.bad.functional.intf.anno.1: (compiler.misc.not.a.functional.intf: FunctionalInterfaceAnno.C) +FunctionalInterfaceAnno.java:16:5: compiler.err.bad.functional.intf.anno.1: (compiler.misc.not.a.functional.intf: FunctionalInterfaceAnno.D) +FunctionalInterfaceAnno.java:19:5: compiler.err.bad.functional.intf.anno.1: (compiler.misc.not.a.functional.intf.1: FunctionalInterfaceAnno.E, (compiler.misc.no.abstracts: kindname.interface, FunctionalInterfaceAnno.E)) +FunctionalInterfaceAnno.java:22:5: compiler.err.bad.functional.intf.anno.1: (compiler.misc.not.a.functional.intf.1: FunctionalInterfaceAnno.F, (compiler.misc.no.abstracts: kindname.interface, FunctionalInterfaceAnno.F)) +FunctionalInterfaceAnno.java:25:5: compiler.err.bad.functional.intf.anno.1: (compiler.misc.not.a.functional.intf.1: FunctionalInterfaceAnno.G, (compiler.misc.no.abstracts: kindname.interface, FunctionalInterfaceAnno.G)) +FunctionalInterfaceAnno.java:28:5: compiler.err.bad.functional.intf.anno.1: (compiler.misc.not.a.functional.intf.1: FunctionalInterfaceAnno.H, (compiler.misc.incompatible.abstracts: kindname.interface, FunctionalInterfaceAnno.H)) +8 errors diff --git a/langtools/test/tools/javac/lambda/Intersection01.out b/langtools/test/tools/javac/lambda/Intersection01.out index 122935b0913..75debb49693 100644 --- a/langtools/test/tools/javac/lambda/Intersection01.out +++ b/langtools/test/tools/javac/lambda/Intersection01.out @@ -1,3 +1,3 @@ -Intersection01.java:36:45: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf.1: (compiler.misc.no.abstracts: kindname.interface, java.io.Serializable)) -Intersection01.java:38:45: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf.1: (compiler.misc.no.abstracts: kindname.interface, java.io.Serializable)) +Intersection01.java:36:45: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf.1: java.io.Serializable, (compiler.misc.no.abstracts: kindname.interface, java.io.Serializable)) +Intersection01.java:38:45: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf.1: java.io.Serializable, (compiler.misc.no.abstracts: kindname.interface, java.io.Serializable)) 2 errors diff --git a/langtools/test/tools/javac/lambda/LambdaConv09.out b/langtools/test/tools/javac/lambda/LambdaConv09.out index 1f99986794c..5265879d881 100644 --- a/langtools/test/tools/javac/lambda/LambdaConv09.out +++ b/langtools/test/tools/javac/lambda/LambdaConv09.out @@ -1,5 +1,5 @@ -LambdaConv09.java:42:19: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf.1: (compiler.misc.no.abstracts: kindname.interface, LambdaConv09.Foo1)) -LambdaConv09.java:43:19: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf.1: (compiler.misc.no.abstracts: kindname.interface, LambdaConv09.Foo2)) -LambdaConv09.java:44:19: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf.1: (compiler.misc.no.abstracts: kindname.interface, LambdaConv09.Foo3)) -LambdaConv09.java:46:19: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf.1: (compiler.misc.no.abstracts: kindname.interface, LambdaConv09.Foo5)) +LambdaConv09.java:42:19: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf.1: LambdaConv09.Foo1, (compiler.misc.no.abstracts: kindname.interface, LambdaConv09.Foo1)) +LambdaConv09.java:43:19: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf.1: LambdaConv09.Foo2, (compiler.misc.no.abstracts: kindname.interface, LambdaConv09.Foo2)) +LambdaConv09.java:44:19: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf.1: LambdaConv09.Foo3, (compiler.misc.no.abstracts: kindname.interface, LambdaConv09.Foo3)) +LambdaConv09.java:46:19: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf.1: LambdaConv09.Foo5, (compiler.misc.no.abstracts: kindname.interface, LambdaConv09.Foo5)) 4 errors diff --git a/langtools/test/tools/javac/lambda/LambdaExpr10.out b/langtools/test/tools/javac/lambda/LambdaExpr10.out index adcba0ad43e..9270b144671 100644 --- a/langtools/test/tools/javac/lambda/LambdaExpr10.out +++ b/langtools/test/tools/javac/lambda/LambdaExpr10.out @@ -1,9 +1,9 @@ -LambdaExpr10.java:18:28: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf) -LambdaExpr10.java:19:32: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf) -LambdaExpr10.java:23:40: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf) -LambdaExpr10.java:24:46: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf) -LambdaExpr10.java:28:29: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf) -LambdaExpr10.java:29:33: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf) +LambdaExpr10.java:18:28: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf: java.lang.Object) +LambdaExpr10.java:19:32: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf: java.lang.Object) +LambdaExpr10.java:23:40: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf: java.lang.Object) +LambdaExpr10.java:24:46: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf: java.lang.Object) +LambdaExpr10.java:28:29: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf: java.lang.Object) +LambdaExpr10.java:29:33: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf: java.lang.Object) LambdaExpr10.java:33:35: compiler.err.prob.found.req: (compiler.misc.incompatible.ret.type.in.lambda: (compiler.misc.inconvertible.types: java.lang.Object, void)) LambdaExpr10.java:34:49: compiler.err.prob.found.req: (compiler.misc.incompatible.ret.type.in.lambda: (compiler.misc.inconvertible.types: java.lang.Object, void)) 8 errors diff --git a/langtools/test/tools/javac/lambda/MethodReference04.out b/langtools/test/tools/javac/lambda/MethodReference04.out index 789804b78d5..46c933a12c2 100644 --- a/langtools/test/tools/javac/lambda/MethodReference04.out +++ b/langtools/test/tools/javac/lambda/MethodReference04.out @@ -1,2 +1,2 @@ -MethodReference04.java:13:16: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf) +MethodReference04.java:13:16: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf: java.lang.Object) 1 error diff --git a/langtools/test/tools/javac/lambda/TargetType17.out b/langtools/test/tools/javac/lambda/TargetType17.out index 0bb985f699b..2bdf33ce266 100644 --- a/langtools/test/tools/javac/lambda/TargetType17.out +++ b/langtools/test/tools/javac/lambda/TargetType17.out @@ -1,9 +1,9 @@ -TargetType17.java:14:21: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf) -TargetType17.java:15:23: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf) -TargetType17.java:16:19: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf) -TargetType17.java:17:21: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf) -TargetType17.java:18:23: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf) -TargetType17.java:19:25: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf) -TargetType17.java:20:21: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf) -TargetType17.java:21:27: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf) +TargetType17.java:14:21: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf: byte) +TargetType17.java:15:23: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf: short) +TargetType17.java:16:19: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf: int) +TargetType17.java:17:21: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf: long) +TargetType17.java:18:23: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf: float) +TargetType17.java:19:25: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf: double) +TargetType17.java:20:21: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf: char) +TargetType17.java:21:27: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf: boolean) 8 errors diff --git a/langtools/test/tools/javac/lambda/TargetType43.out b/langtools/test/tools/javac/lambda/TargetType43.out index b7b8766c516..7d50949d9a0 100644 --- a/langtools/test/tools/javac/lambda/TargetType43.out +++ b/langtools/test/tools/javac/lambda/TargetType43.out @@ -1,5 +1,5 @@ -TargetType43.java:13:20: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf) +TargetType43.java:13:20: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf: java.lang.Object) TargetType43.java:13:30: compiler.err.cant.resolve.location: kindname.class, NonExistentClass, , , (compiler.misc.location: kindname.class, TargetType43, null) -TargetType43.java:14:9: compiler.err.cant.apply.symbol: kindname.method, m, java.lang.Object, @359, kindname.class, TargetType43, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.not.a.functional.intf)) +TargetType43.java:14:9: compiler.err.cant.apply.symbol: kindname.method, m, java.lang.Object, @359, kindname.class, TargetType43, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.not.a.functional.intf: java.lang.Object)) TargetType43.java:14:21: compiler.err.cant.resolve.location: kindname.class, NonExistentClass, , , (compiler.misc.location: kindname.class, TargetType43, null) 4 errors diff --git a/langtools/test/tools/javac/lambda/funcInterfaces/LambdaTest2_neg1.out b/langtools/test/tools/javac/lambda/funcInterfaces/LambdaTest2_neg1.out index 4780e80fec6..0a96b7ded8d 100644 --- a/langtools/test/tools/javac/lambda/funcInterfaces/LambdaTest2_neg1.out +++ b/langtools/test/tools/javac/lambda/funcInterfaces/LambdaTest2_neg1.out @@ -1,2 +1,2 @@ -LambdaTest2_neg1.java:15:13: compiler.err.cant.apply.symbol: kindname.method, methodQooRoo, QooRoo, @531, kindname.class, LambdaTest2_neg1, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.not.a.functional.intf.1: (compiler.misc.incompatible.abstracts: kindname.interface, QooRoo))) +LambdaTest2_neg1.java:15:13: compiler.err.cant.apply.symbol: kindname.method, methodQooRoo, QooRoo, @531, kindname.class, LambdaTest2_neg1, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.not.a.functional.intf.1: QooRoo, (compiler.misc.incompatible.abstracts: kindname.interface, QooRoo))) 1 error diff --git a/langtools/test/tools/javac/lambda/funcInterfaces/NonSAM1.out b/langtools/test/tools/javac/lambda/funcInterfaces/NonSAM1.out index c2472263c0a..abfaf967caa 100644 --- a/langtools/test/tools/javac/lambda/funcInterfaces/NonSAM1.out +++ b/langtools/test/tools/javac/lambda/funcInterfaces/NonSAM1.out @@ -1,2 +1,2 @@ -NonSAM1.java:11:20: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf.1: (compiler.misc.no.abstracts: kindname.interface, Planet)) +NonSAM1.java:11:20: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf.1: Planet, (compiler.misc.no.abstracts: kindname.interface, Planet)) 1 error diff --git a/langtools/test/tools/javac/lambda/funcInterfaces/NonSAM3.out b/langtools/test/tools/javac/lambda/funcInterfaces/NonSAM3.out index 8c9ff08b5ae..9f52ba5f767 100644 --- a/langtools/test/tools/javac/lambda/funcInterfaces/NonSAM3.out +++ b/langtools/test/tools/javac/lambda/funcInterfaces/NonSAM3.out @@ -1,9 +1,9 @@ -NonSAM3.java:15:21: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf.1: (compiler.misc.incompatible.abstracts: kindname.interface, FooBar)) -NonSAM3.java:16:22: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf.1: (compiler.misc.incompatible.abstracts: kindname.interface, FooBar)) -NonSAM3.java:17:17: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf.1: (compiler.misc.incompatible.abstracts: kindname.interface, DE)) -NonSAM3.java:18:18: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf.1: (compiler.misc.incompatible.abstracts: kindname.interface, DE)) -NonSAM3.java:19:18: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf.1: (compiler.misc.incompatible.abstracts: kindname.interface, DE)) -NonSAM3.java:20:18: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf.1: (compiler.misc.incompatible.abstracts: kindname.interface, DE)) -NonSAM3.java:21:18: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf.1: (compiler.misc.incompatible.abstracts: kindname.interface, DE)) -NonSAM3.java:22:18: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf.1: (compiler.misc.incompatible.abstracts: kindname.interface, DE)) +NonSAM3.java:15:21: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf.1: FooBar, (compiler.misc.incompatible.abstracts: kindname.interface, FooBar)) +NonSAM3.java:16:22: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf.1: FooBar, (compiler.misc.incompatible.abstracts: kindname.interface, FooBar)) +NonSAM3.java:17:17: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf.1: DE, (compiler.misc.incompatible.abstracts: kindname.interface, DE)) +NonSAM3.java:18:18: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf.1: DE, (compiler.misc.incompatible.abstracts: kindname.interface, DE)) +NonSAM3.java:19:18: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf.1: DE, (compiler.misc.incompatible.abstracts: kindname.interface, DE)) +NonSAM3.java:20:18: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf.1: DE, (compiler.misc.incompatible.abstracts: kindname.interface, DE)) +NonSAM3.java:21:18: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf.1: DE, (compiler.misc.incompatible.abstracts: kindname.interface, DE)) +NonSAM3.java:22:18: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf.1: DE, (compiler.misc.incompatible.abstracts: kindname.interface, DE)) 8 errors diff --git a/langtools/test/tools/javac/lambda/lambdaExpression/AbstractClass_neg.out b/langtools/test/tools/javac/lambda/lambdaExpression/AbstractClass_neg.out index 2fc5555b1e6..cfe68383937 100644 --- a/langtools/test/tools/javac/lambda/lambdaExpression/AbstractClass_neg.out +++ b/langtools/test/tools/javac/lambda/lambdaExpression/AbstractClass_neg.out @@ -1,2 +1,2 @@ -AbstractClass_neg.java:16:17: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf) +AbstractClass_neg.java:16:17: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf: AbstractClass_neg.SAM) 1 error diff --git a/langtools/test/tools/javac/lambda/lambdaExpression/InvalidExpression5.out b/langtools/test/tools/javac/lambda/lambdaExpression/InvalidExpression5.out index 251425e6675..f9c70cddcb8 100644 --- a/langtools/test/tools/javac/lambda/lambdaExpression/InvalidExpression5.out +++ b/langtools/test/tools/javac/lambda/lambdaExpression/InvalidExpression5.out @@ -1,2 +1,2 @@ -InvalidExpression5.java:12:20: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf) +InvalidExpression5.java:12:20: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf: java.lang.Object) 1 error From 5a60f56dbe32ba268524d68a7ce8df2c40cf9e53 Mon Sep 17 00:00:00 2001 From: Maurizio Cimadamore Date: Wed, 16 Jan 2013 17:40:28 +0000 Subject: [PATCH 042/210] 8005964: Regression: difference in error recovery after ambiguity causes JCK test failure Wrong implementation of ResolveError.access in AmbiguityError Reviewed-by: jjh --- .../src/share/classes/com/sun/tools/javac/comp/Resolve.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/langtools/src/share/classes/com/sun/tools/javac/comp/Resolve.java b/langtools/src/share/classes/com/sun/tools/javac/comp/Resolve.java index d5adb408242..2847ff1bfe8 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/comp/Resolve.java +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Resolve.java @@ -3421,7 +3421,10 @@ public class Resolve { @Override protected Symbol access(Name name, TypeSymbol location) { - return ambiguousSyms.last(); + Symbol firstAmbiguity = ambiguousSyms.last(); + return firstAmbiguity.kind == TYP ? + types.createErrorType(name, location, firstAmbiguity.type).tsym : + firstAmbiguity; } } From 17ebfc350d1c0fea959a96bda36778c8f78a5bf2 Mon Sep 17 00:00:00 2001 From: Jonathan Gibbons Date: Wed, 16 Jan 2013 10:29:52 -0800 Subject: [PATCH 043/210] 8006236: doclint: structural issue hidden Reviewed-by: darcy --- .../com/sun/tools/doclint/Checker.java | 23 ++++++++++- langtools/test/tools/doclint/EndTagsTest.java | 39 +++++++++++++++++++ langtools/test/tools/doclint/EndTagsTest.out | 25 ++++++++++++ 3 files changed, 85 insertions(+), 2 deletions(-) create mode 100644 langtools/test/tools/doclint/EndTagsTest.java create mode 100644 langtools/test/tools/doclint/EndTagsTest.out diff --git a/langtools/src/share/classes/com/sun/tools/doclint/Checker.java b/langtools/src/share/classes/com/sun/tools/doclint/Checker.java index 0664838936d..b0d8d06f127 100644 --- a/langtools/src/share/classes/com/sun/tools/doclint/Checker.java +++ b/langtools/src/share/classes/com/sun/tools/doclint/Checker.java @@ -25,6 +25,7 @@ package com.sun.tools.doclint; +import com.sun.source.doctree.LiteralTree; import java.util.regex.Matcher; import com.sun.source.doctree.LinkTree; import java.net.URI; @@ -359,9 +360,8 @@ public class Checker extends DocTreeScanner { env.messages.error(HTML, tree, "dc.tag.unknown", treeName); } else if (t.endKind == HtmlTag.EndKind.NONE) { env.messages.error(HTML, tree, "dc.tag.end.not.permitted", treeName); - } else if (tagStack.isEmpty()) { - env.messages.error(HTML, tree, "dc.tag.end.unexpected", treeName); } else { + boolean done = false; while (!tagStack.isEmpty()) { TagStackItem top = tagStack.peek(); if (t == top.tag) { @@ -383,6 +383,7 @@ public class Checker extends DocTreeScanner { env.messages.error(HTML, tree, "dc.text.not.allowed", treeName); } tagStack.pop(); + done = true; break; } else if (top.tag == null || top.tag.endKind != HtmlTag.EndKind.REQUIRED) { tagStack.pop(); @@ -400,10 +401,15 @@ public class Checker extends DocTreeScanner { tagStack.pop(); } else { env.messages.error(HTML, tree, "dc.tag.end.unexpected", treeName); + done = true; break; } } } + + if (!done && tagStack.isEmpty()) { + env.messages.error(HTML, tree, "dc.tag.end.unexpected", treeName); + } } return super.visitEndElement(tree, ignore); @@ -545,6 +551,19 @@ public class Checker extends DocTreeScanner { } } + @Override + public Void visitLiteral(LiteralTree tree, Void ignore) { + if (tree.getKind() == DocTree.Kind.CODE) { + for (TagStackItem tsi: tagStack) { + if (tsi.tag == HtmlTag.CODE) { + env.messages.warning(HTML, tree, "dc.tag.nested.not.allowed", "code"); + break; + } + } + } + return super.visitLiteral(tree, ignore); + } + @Override public Void visitParam(ParamTree tree, Void ignore) { boolean typaram = tree.isTypeParameter(); diff --git a/langtools/test/tools/doclint/EndTagsTest.java b/langtools/test/tools/doclint/EndTagsTest.java new file mode 100644 index 00000000000..154f516324a --- /dev/null +++ b/langtools/test/tools/doclint/EndTagsTest.java @@ -0,0 +1,39 @@ +/* + * @test /nodynamiccopyright/ + * @bug 8006236 + * @summary doclint: structural issue hidden + * @build DocLintTester + * @run main DocLintTester -Xmsgs:-html EndTagsTest.java + * @run main DocLintTester -ref EndTagsTest.out EndTagsTest.java + */ + +/** */ +public class EndTagsTest { + /**

text image

*/ + public void valid_all() { } + + /**

text image */ + public void valid_omit_optional_close() { } + + /** */ + public void invalid_missing_start() { } + + /**

*/ + public void invalid_missing_start_2() { } + + /**

text

*/ + public void invalid_missing_start_3() { } + + /** image */ + public void invalid_end() { } + + /** */ + public void unknown_start_end() { } + + /** */ + public void unknown_start() { } + + /** */ + public void unknown_end() { } +} + diff --git a/langtools/test/tools/doclint/EndTagsTest.out b/langtools/test/tools/doclint/EndTagsTest.out new file mode 100644 index 00000000000..61af632535c --- /dev/null +++ b/langtools/test/tools/doclint/EndTagsTest.out @@ -0,0 +1,25 @@ +EndTagsTest.java:18: error: unexpected end tag: + /** */ + ^ +EndTagsTest.java:21: error: unexpected end tag: + /**

*/ + ^ +EndTagsTest.java:24: error: unexpected end tag: + /**

text

*/ + ^ +EndTagsTest.java:27: error: invalid end tag: + /** image */ + ^ +EndTagsTest.java:30: error: unknown tag: invalid + /** */ + ^ +EndTagsTest.java:30: error: unknown tag: invalid + /** */ + ^ +EndTagsTest.java:33: error: unknown tag: invalid + /** */ + ^ +EndTagsTest.java:36: error: unknown tag: invalid + /** */ + ^ +8 errors From e942cdde819b76892eb060c6b25f10f0cf7b29bb Mon Sep 17 00:00:00 2001 From: Joe Darcy Date: Wed, 16 Jan 2013 13:22:09 -0800 Subject: [PATCH 044/210] 8006283: Change to Class.cast() in javax.lang.model implementation for repeating annotations Reviewed-by: jjg --- .../classes/com/sun/tools/javac/model/JavacElements.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/langtools/src/share/classes/com/sun/tools/javac/model/JavacElements.java b/langtools/src/share/classes/com/sun/tools/javac/model/JavacElements.java index 14f6e366ddb..5861e70f7f3 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/model/JavacElements.java +++ b/langtools/src/share/classes/com/sun/tools/javac/model/JavacElements.java @@ -266,9 +266,10 @@ public class JavacElements implements Elements { private static Class initRepeatable() { try { - @SuppressWarnings("unchecked") // java.lang.annotation.Repeatable extends Annotation by being an annotation type - Class c = (Class)Class.forName("java.lang.annotation.Repeatable"); - return c; + // Repeatable will not be available when bootstrapping on + // JDK 7 so use a reflective lookup instead of a class + // literal for Repeatable.class. + return Class.forName("java.lang.annotation.Repeatable").asSubclass(Annotation.class); } catch (ClassNotFoundException e) { return null; } catch (SecurityException e) { From c803a77fa8f02c256f2436c31f9b9352d9cacaa5 Mon Sep 17 00:00:00 2001 From: David Chase Date: Wed, 16 Jan 2013 14:55:18 -0800 Subject: [PATCH 045/210] 8006204: please JTREGify test/compiler/7190310/Test7190310.java Add proper jtreg annotations in the preceding comment, including an explicit timeout. Reviewed-by: kvn, twisti --- hotspot/test/compiler/7190310/Test7190310.java | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/hotspot/test/compiler/7190310/Test7190310.java b/hotspot/test/compiler/7190310/Test7190310.java index 57a89b93b39..b45c60bf196 100644 --- a/hotspot/test/compiler/7190310/Test7190310.java +++ b/hotspot/test/compiler/7190310/Test7190310.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2013, 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 @@ -23,7 +23,16 @@ */ /* - * Manual test + * @test + * @bug 7190310 + * @summary Inlining WeakReference.get(), and hoisting $referent may lead to non-terminating loops + * @run main/othervm/timeout=600 -Xbatch Test7190310 + */ + +/* + * Note bug exhibits as infinite loop, timeout is helpful. + * It should normally finish pretty quickly, but on some especially slow machines + * it may not. The companion _unsafe test lacks a timeout, but that is okay. */ import java.lang.ref.*; From 7b493a180e406771500a247a01a07f0cbc656de7 Mon Sep 17 00:00:00 2001 From: Jonathan Gibbons Date: Wed, 16 Jan 2013 20:41:14 -0800 Subject: [PATCH 046/210] 8006228: Doclint doesn't detect {@code nested inline} Reviewed-by: darcy --- .../classes/com/sun/tools/doclint/Checker.java | 2 +- .../tools/doclint/resources/doclint.properties | 1 + langtools/test/tools/doclint/LiteralTest.java | 16 ++++++++++++++++ langtools/test/tools/doclint/LiteralTest.out | 4 ++++ 4 files changed, 22 insertions(+), 1 deletion(-) create mode 100644 langtools/test/tools/doclint/LiteralTest.java create mode 100644 langtools/test/tools/doclint/LiteralTest.out diff --git a/langtools/src/share/classes/com/sun/tools/doclint/Checker.java b/langtools/src/share/classes/com/sun/tools/doclint/Checker.java index b0d8d06f127..8b4697c8e49 100644 --- a/langtools/src/share/classes/com/sun/tools/doclint/Checker.java +++ b/langtools/src/share/classes/com/sun/tools/doclint/Checker.java @@ -556,7 +556,7 @@ public class Checker extends DocTreeScanner { if (tree.getKind() == DocTree.Kind.CODE) { for (TagStackItem tsi: tagStack) { if (tsi.tag == HtmlTag.CODE) { - env.messages.warning(HTML, tree, "dc.tag.nested.not.allowed", "code"); + env.messages.warning(HTML, tree, "dc.tag.code.within.code"); break; } } diff --git a/langtools/src/share/classes/com/sun/tools/doclint/resources/doclint.properties b/langtools/src/share/classes/com/sun/tools/doclint/resources/doclint.properties index 33b0d7d1151..a1a3a02c7bb 100644 --- a/langtools/src/share/classes/com/sun/tools/doclint/resources/doclint.properties +++ b/langtools/src/share/classes/com/sun/tools/doclint/resources/doclint.properties @@ -48,6 +48,7 @@ dc.no.alt.attr.for.image = no "alt" attribute for image dc.no.summary.or.caption.for.table=no summary or caption for table dc.param.name.not.found = @param name not found dc.ref.not.found = reference not found +dc.tag.code.within.code = '{@code'} within dc.tag.empty = empty <{0}> tag dc.tag.end.not.permitted = invalid end tag: dc.tag.end.unexpected = unexpected end tag: diff --git a/langtools/test/tools/doclint/LiteralTest.java b/langtools/test/tools/doclint/LiteralTest.java new file mode 100644 index 00000000000..008246edee6 --- /dev/null +++ b/langtools/test/tools/doclint/LiteralTest.java @@ -0,0 +1,16 @@ +/* + * @test /nodynamiccopyright/ + * @bug 8006228 + * @summary Doclint doesn't detect {@code nested inline} + * @build DocLintTester + * @run main DocLintTester -ref LiteralTest.out LiteralTest.java + */ + +/** */ +public class LiteralTest { + /** abc {@literal < & > } def */ + public void ok_literal_in_code() { } + + /** abc {@code < & > } def */ + public void bad_code_in_code() { } +} diff --git a/langtools/test/tools/doclint/LiteralTest.out b/langtools/test/tools/doclint/LiteralTest.out new file mode 100644 index 00000000000..4cb41d9d7bb --- /dev/null +++ b/langtools/test/tools/doclint/LiteralTest.out @@ -0,0 +1,4 @@ +LiteralTest.java:14: warning: {@code} within + /** abc {@code < & > } def */ + ^ +1 warning From 6799149f7d1bc04933b07466043f471892808a7b Mon Sep 17 00:00:00 2001 From: Stefan Karlsson Date: Thu, 17 Jan 2013 11:39:48 +0100 Subject: [PATCH 047/210] 8006513: Null pointer in DefaultMethods::generate_default_methods when merging annotations Reviewed-by: brutisso, jfranck --- .../src/share/vm/classfile/defaultMethods.cpp | 22 +++++++++++++------ 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/hotspot/src/share/vm/classfile/defaultMethods.cpp b/hotspot/src/share/vm/classfile/defaultMethods.cpp index ac593a7ef24..ce516b84bc1 100644 --- a/hotspot/src/share/vm/classfile/defaultMethods.cpp +++ b/hotspot/src/share/vm/classfile/defaultMethods.cpp @@ -1285,13 +1285,15 @@ static void merge_in_new_methods(InstanceKlass* klass, enum { ANNOTATIONS, PARAMETERS, DEFAULTS, NUM_ARRAYS }; - Array* original_annots[NUM_ARRAYS]; + Array* original_annots[NUM_ARRAYS] = { NULL }; Array* original_methods = klass->methods(); Annotations* annots = klass->annotations(); - original_annots[ANNOTATIONS] = annots->methods_annotations(); - original_annots[PARAMETERS] = annots->methods_parameter_annotations(); - original_annots[DEFAULTS] = annots->methods_default_annotations(); + if (annots != NULL) { + original_annots[ANNOTATIONS] = annots->methods_annotations(); + original_annots[PARAMETERS] = annots->methods_parameter_annotations(); + original_annots[DEFAULTS] = annots->methods_default_annotations(); + } Array* original_ordering = klass->method_ordering(); Array* merged_ordering = Universe::the_empty_int_array(); @@ -1370,9 +1372,15 @@ static void merge_in_new_methods(InstanceKlass* klass, // Replace klass methods with new merged lists klass->set_methods(merged_methods); - annots->set_methods_annotations(merged_annots[ANNOTATIONS]); - annots->set_methods_parameter_annotations(merged_annots[PARAMETERS]); - annots->set_methods_default_annotations(merged_annots[DEFAULTS]); + if (annots != NULL) { + annots->set_methods_annotations(merged_annots[ANNOTATIONS]); + annots->set_methods_parameter_annotations(merged_annots[PARAMETERS]); + annots->set_methods_default_annotations(merged_annots[DEFAULTS]); + } else { + assert(merged_annots[ANNOTATIONS] == NULL, "Must be"); + assert(merged_annots[PARAMETERS] == NULL, "Must be"); + assert(merged_annots[DEFAULTS] == NULL, "Must be"); + } ClassLoaderData* cld = klass->class_loader_data(); MetadataFactory::free_array(cld, original_methods); From 68f3dd76c92ce3b0219ac2cc346718dd865645d9 Mon Sep 17 00:00:00 2001 From: Harold Seigel Date: Thu, 17 Jan 2013 10:25:16 -0500 Subject: [PATCH 048/210] 7102489: RFE: cleanup jlong typedef on __APPLE__and _LLP64 systems Define jlong as long on all LP64 platforms and add JLONG_FORMAT macro. Reviewed-by: dholmes, coleenp, mikael, kvn --- hotspot/src/cpu/x86/vm/jni_x86.h | 9 ++------- hotspot/src/os/bsd/vm/os_bsd.inline.hpp | 10 +--------- hotspot/src/os/linux/vm/os_linux.inline.hpp | 10 +--------- hotspot/src/os/posix/launcher/java_md.c | 7 +------ hotspot/src/os/posix/launcher/java_md.h | 8 +++++++- hotspot/src/os/solaris/vm/os_solaris.inline.hpp | 5 +---- hotspot/src/os/windows/launcher/java_md.c | 7 +------ hotspot/src/os/windows/launcher/java_md.h | 4 +++- hotspot/src/os/windows/vm/os_windows.cpp | 8 ++++---- hotspot/src/os/windows/vm/os_windows.inline.hpp | 5 +---- hotspot/src/share/tools/launcher/java.c | 4 ++-- hotspot/src/share/tools/launcher/java.h | 3 +-- hotspot/src/share/vm/c1/c1_InstructionPrinter.cpp | 4 ++-- hotspot/src/share/vm/c1/c1_LIR.cpp | 4 ++-- hotspot/src/share/vm/ci/ciReplay.cpp | 4 ++-- .../concurrentMarkSweep/compactibleFreeListSpace.cpp | 4 ++-- .../concurrentMarkSweepGeneration.cpp | 6 +++--- .../parallelScavenge/psScavenge.cpp | 4 ++-- .../share/vm/gc_implementation/shared/ageTable.cpp | 4 ++-- hotspot/src/share/vm/memory/universe.cpp | 4 ++-- hotspot/src/share/vm/opto/idealGraphPrinter.cpp | 4 ++-- hotspot/src/share/vm/opto/type.cpp | 12 ++++++------ hotspot/src/share/vm/runtime/aprofiler.cpp | 4 ++-- hotspot/src/share/vm/runtime/arguments.cpp | 4 ++-- hotspot/src/share/vm/runtime/os.hpp | 6 +----- hotspot/src/share/vm/runtime/perfData.cpp | 4 ++-- hotspot/src/share/vm/runtime/virtualspace.cpp | 6 +++--- hotspot/src/share/vm/services/diagnosticArgument.cpp | 6 +++--- hotspot/src/share/vm/services/heapDumper.cpp | 4 ++-- hotspot/src/share/vm/services/lowMemoryDetector.cpp | 4 ++-- hotspot/src/share/vm/utilities/globalDefinitions.hpp | 10 +++++++++- .../src/share/vm/utilities/globalDefinitions_gcc.hpp | 6 +++++- hotspot/src/share/vm/utilities/ostream.cpp | 8 +++----- hotspot/src/share/vm/utilities/taskqueue.cpp | 6 +++--- 34 files changed, 87 insertions(+), 111 deletions(-) diff --git a/hotspot/src/cpu/x86/vm/jni_x86.h b/hotspot/src/cpu/x86/vm/jni_x86.h index d724c86007a..2cd7abd304e 100644 --- a/hotspot/src/cpu/x86/vm/jni_x86.h +++ b/hotspot/src/cpu/x86/vm/jni_x86.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, 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 @@ -38,14 +38,9 @@ #define JNICALL typedef int jint; -#if defined(_LP64) && !defined(__APPLE__) +#if defined(_LP64) typedef long jlong; #else - /* - * On _LP64 __APPLE__ "long" and "long long" are both 64 bits, - * but we use the "long long" typedef to avoid complaints from - * the __APPLE__ compiler about fprintf formats. - */ typedef long long jlong; #endif diff --git a/hotspot/src/os/bsd/vm/os_bsd.inline.hpp b/hotspot/src/os/bsd/vm/os_bsd.inline.hpp index 6a7cdc08b5f..8fc3c2b0878 100644 --- a/hotspot/src/os/bsd/vm/os_bsd.inline.hpp +++ b/hotspot/src/os/bsd/vm/os_bsd.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2013, 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 @@ -59,14 +59,6 @@ inline const char* os::path_separator() { return ":"; } -inline const char* os::jlong_format_specifier() { - return "%lld"; -} - -inline const char* os::julong_format_specifier() { - return "%llu"; -} - // File names are case-sensitive on windows only inline int os::file_name_strcmp(const char* s1, const char* s2) { return strcmp(s1, s2); diff --git a/hotspot/src/os/linux/vm/os_linux.inline.hpp b/hotspot/src/os/linux/vm/os_linux.inline.hpp index c779f8a6aa5..3a8d8d97d9b 100644 --- a/hotspot/src/os/linux/vm/os_linux.inline.hpp +++ b/hotspot/src/os/linux/vm/os_linux.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2013, 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 @@ -68,14 +68,6 @@ inline const char* os::path_separator() { return ":"; } -inline const char* os::jlong_format_specifier() { - return "%lld"; -} - -inline const char* os::julong_format_specifier() { - return "%llu"; -} - // File names are case-sensitive on windows only inline int os::file_name_strcmp(const char* s1, const char* s2) { return strcmp(s1, s2); diff --git a/hotspot/src/os/posix/launcher/java_md.c b/hotspot/src/os/posix/launcher/java_md.c index 970222c4fd3..b5fc949813c 100644 --- a/hotspot/src/os/posix/launcher/java_md.c +++ b/hotspot/src/os/posix/launcher/java_md.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2013, 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 @@ -1876,11 +1876,6 @@ void SplashFreeLibrary() { } } -const char * -jlong_format_specifier() { - return "%lld"; -} - /* * Block current thread and continue execution in a new thread */ diff --git a/hotspot/src/os/posix/launcher/java_md.h b/hotspot/src/os/posix/launcher/java_md.h index ed36fd1af67..63c449a2926 100644 --- a/hotspot/src/os/posix/launcher/java_md.h +++ b/hotspot/src/os/posix/launcher/java_md.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2013, 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 @@ -64,6 +64,12 @@ #define Counter2Micros(counts) (1) #endif /* HAVE_GETHRTIME */ +#ifdef _LP64 +#define JLONG_FORMAT "%ld" +#else +#define JLONG_FORMAT "%lld" +#endif + /* * Function prototypes. */ diff --git a/hotspot/src/os/solaris/vm/os_solaris.inline.hpp b/hotspot/src/os/solaris/vm/os_solaris.inline.hpp index a3f09d01d32..61691fd384a 100644 --- a/hotspot/src/os/solaris/vm/os_solaris.inline.hpp +++ b/hotspot/src/os/solaris/vm/os_solaris.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, 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 @@ -50,9 +50,6 @@ inline const char* os::file_separator() { return "/"; } inline const char* os::line_separator() { return "\n"; } inline const char* os::path_separator() { return ":"; } -inline const char* os::jlong_format_specifier() { return "%lld"; } -inline const char* os::julong_format_specifier() { return "%llu"; } - // File names are case-sensitive on windows only inline int os::file_name_strcmp(const char* s1, const char* s2) { return strcmp(s1, s2); diff --git a/hotspot/src/os/windows/launcher/java_md.c b/hotspot/src/os/windows/launcher/java_md.c index 2fde40ad205..3e28755009c 100644 --- a/hotspot/src/os/windows/launcher/java_md.c +++ b/hotspot/src/os/windows/launcher/java_md.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2013, 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 @@ -1323,11 +1323,6 @@ void SplashFreeLibrary() { } } -const char * -jlong_format_specifier() { - return "%I64d"; -} - /* * Block current thread and continue execution in a new thread */ diff --git a/hotspot/src/os/windows/launcher/java_md.h b/hotspot/src/os/windows/launcher/java_md.h index 111be1ee13a..763e2457644 100644 --- a/hotspot/src/os/windows/launcher/java_md.h +++ b/hotspot/src/os/windows/launcher/java_md.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2013, 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 @@ -69,6 +69,8 @@ extern jlong Counter2Micros(jlong counts); extern int _main(int argc, char **argv); #endif +#define JLONG_FORMAT "%I64d" + /* * Function prototypes. */ diff --git a/hotspot/src/os/windows/vm/os_windows.cpp b/hotspot/src/os/windows/vm/os_windows.cpp index b8498d5a1e2..a10b83f8940 100644 --- a/hotspot/src/os/windows/vm/os_windows.cpp +++ b/hotspot/src/os/windows/vm/os_windows.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, 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 @@ -2946,7 +2946,7 @@ char* os::pd_reserve_memory(size_t bytes, char* addr, size_t alignment_hint) { } if( Verbose && PrintMiscellaneous ) { reserveTimer.stop(); - tty->print_cr("reserve_memory of %Ix bytes took %ld ms (%ld ticks)", bytes, + tty->print_cr("reserve_memory of %Ix bytes took " JLONG_FORMAT " ms (" JLONG_FORMAT " ticks)", bytes, reserveTimer.milliseconds(), reserveTimer.ticks()); } } @@ -4305,7 +4305,7 @@ char* os::pd_map_memory(int fd, const char* file_name, size_t file_offset, if (hFile == NULL) { if (PrintMiscellaneous && Verbose) { DWORD err = GetLastError(); - tty->print_cr("CreateFile() failed: GetLastError->%ld."); + tty->print_cr("CreateFile() failed: GetLastError->%ld.", err); } return NULL; } @@ -4355,7 +4355,7 @@ char* os::pd_map_memory(int fd, const char* file_name, size_t file_offset, if (hMap == NULL) { if (PrintMiscellaneous && Verbose) { DWORD err = GetLastError(); - tty->print_cr("CreateFileMapping() failed: GetLastError->%ld."); + tty->print_cr("CreateFileMapping() failed: GetLastError->%ld.", err); } CloseHandle(hFile); return NULL; diff --git a/hotspot/src/os/windows/vm/os_windows.inline.hpp b/hotspot/src/os/windows/vm/os_windows.inline.hpp index 8f8c3c72fd2..1df8694d9dd 100644 --- a/hotspot/src/os/windows/vm/os_windows.inline.hpp +++ b/hotspot/src/os/windows/vm/os_windows.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, 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 @@ -38,9 +38,6 @@ inline const char* os::line_separator() { return "\r\n"; } inline const char* os::path_separator() { return ";"; } inline const char* os::dll_file_extension() { return ".dll"; } -inline const char* os::jlong_format_specifier() { return "%I64d"; } -inline const char* os::julong_format_specifier() { return "%I64u"; } - inline const int os::default_file_open_flags() { return O_BINARY | O_NOINHERIT;} // File names are case-insensitive on windows only diff --git a/hotspot/src/share/tools/launcher/java.c b/hotspot/src/share/tools/launcher/java.c index 5ebfb9a8dc3..63f11d77c86 100644 --- a/hotspot/src/share/tools/launcher/java.c +++ b/hotspot/src/share/tools/launcher/java.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2013, 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 @@ -808,7 +808,7 @@ CheckJvmType(int *pargc, char ***argv, jboolean speculative) { static int parse_stack_size(const char *s, jlong *result) { jlong n = 0; - int args_read = sscanf(s, jlong_format_specifier(), &n); + int args_read = sscanf(s, JLONG_FORMAT, &n); if (args_read != 1) { return 0; } diff --git a/hotspot/src/share/tools/launcher/java.h b/hotspot/src/share/tools/launcher/java.h index 97fba2184f7..1dd79618c84 100644 --- a/hotspot/src/share/tools/launcher/java.h +++ b/hotspot/src/share/tools/launcher/java.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2013, 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 @@ -86,7 +86,6 @@ void ReportExceptionDescription(JNIEnv * env); jboolean RemovableMachineDependentOption(char * option); void PrintMachineDependentOptions(); -const char *jlong_format_specifier(); /* * Block current thread and continue execution in new thread */ diff --git a/hotspot/src/share/vm/c1/c1_InstructionPrinter.cpp b/hotspot/src/share/vm/c1/c1_InstructionPrinter.cpp index a2f6f86fd85..68e0feb5b83 100644 --- a/hotspot/src/share/vm/c1/c1_InstructionPrinter.cpp +++ b/hotspot/src/share/vm/c1/c1_InstructionPrinter.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2013, 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 @@ -360,7 +360,7 @@ void InstructionPrinter::do_Constant(Constant* x) { ValueType* t = x->type(); switch (t->tag()) { case intTag : output()->print("%d" , t->as_IntConstant ()->value()); break; - case longTag : output()->print(os::jlong_format_specifier(), t->as_LongConstant()->value()); output()->print("L"); break; + case longTag : output()->print(JLONG_FORMAT, t->as_LongConstant()->value()); output()->print("L"); break; case floatTag : output()->print("%g" , t->as_FloatConstant ()->value()); break; case doubleTag : output()->print("%gD" , t->as_DoubleConstant()->value()); break; case objectTag : print_object(x); break; diff --git a/hotspot/src/share/vm/c1/c1_LIR.cpp b/hotspot/src/share/vm/c1/c1_LIR.cpp index 178d1867179..7a0563c6a20 100644 --- a/hotspot/src/share/vm/c1/c1_LIR.cpp +++ b/hotspot/src/share/vm/c1/c1_LIR.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2013, 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 @@ -1563,7 +1563,7 @@ void LIR_Const::print_value_on(outputStream* out) const { switch (type()) { case T_ADDRESS:out->print("address:%d",as_jint()); break; case T_INT: out->print("int:%d", as_jint()); break; - case T_LONG: out->print("lng:%lld", as_jlong()); break; + case T_LONG: out->print("lng:" JLONG_FORMAT, as_jlong()); break; case T_FLOAT: out->print("flt:%f", as_jfloat()); break; case T_DOUBLE: out->print("dbl:%f", as_jdouble()); break; case T_OBJECT: out->print("obj:0x%x", as_jobject()); break; diff --git a/hotspot/src/share/vm/ci/ciReplay.cpp b/hotspot/src/share/vm/ci/ciReplay.cpp index f2e77241960..9b532b8e26b 100644 --- a/hotspot/src/share/vm/ci/ciReplay.cpp +++ b/hotspot/src/share/vm/ci/ciReplay.cpp @@ -1,4 +1,4 @@ -/* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2013, 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 @@ -645,7 +645,7 @@ class CompileReplay : public StackObj { java_mirror->bool_field_put(fd.offset(), value); } else if (strcmp(field_signature, "J") == 0) { jlong value; - if (sscanf(string_value, INT64_FORMAT, &value) != 1) { + if (sscanf(string_value, JLONG_FORMAT, &value) != 1) { fprintf(stderr, "Error parsing long: %s\n", string_value); return; } diff --git a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp index 2f43c987669..9fb347a05c5 100644 --- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp +++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2013, 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 @@ -555,7 +555,7 @@ void CompactibleFreeListSpace::reportFreeListStatistics() const { reportIndexedFreeListStatistics(); size_t total_size = totalSizeInIndexedFreeLists() + _dictionary->total_chunk_size(DEBUG_ONLY(freelistLock())); - gclog_or_tty->print(" free=%ld frag=%1.4f\n", total_size, flsFrag()); + gclog_or_tty->print(" free=" SIZE_FORMAT " frag=%1.4f\n", total_size, flsFrag()); } } diff --git a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp index 475f2b8fee1..2ed7e465ad0 100644 --- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp +++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2013, 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 @@ -3338,7 +3338,7 @@ bool ConcurrentMarkSweepGeneration::grow_by(size_t bytes) { if (Verbose && PrintGC) { size_t new_mem_size = _virtual_space.committed_size(); size_t old_mem_size = new_mem_size - bytes; - gclog_or_tty->print_cr("Expanding %s from %ldK by %ldK to %ldK", + gclog_or_tty->print_cr("Expanding %s from " SIZE_FORMAT "K by " SIZE_FORMAT "K to " SIZE_FORMAT "K", name(), old_mem_size/K, bytes/K, new_mem_size/K); } } @@ -9203,7 +9203,7 @@ void ASConcurrentMarkSweepGeneration::shrink_by(size_t desired_bytes) { if (Verbose && PrintGCDetails) { size_t new_mem_size = _virtual_space.committed_size(); size_t old_mem_size = new_mem_size + bytes; - gclog_or_tty->print_cr("Shrinking %s from %ldK by %ldK to %ldK", + gclog_or_tty->print_cr("Shrinking %s from " SIZE_FORMAT "K by " SIZE_FORMAT "K to " SIZE_FORMAT "K", name(), old_mem_size/K, bytes/K, new_mem_size/K); } } diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psScavenge.cpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psScavenge.cpp index f68b1b5a446..078bd62aff7 100644 --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psScavenge.cpp +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psScavenge.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2013, 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 @@ -529,7 +529,7 @@ bool PSScavenge::invoke_no_policy() { if (PrintTenuringDistribution) { gclog_or_tty->cr(); - gclog_or_tty->print_cr("Desired survivor size %ld bytes, new threshold %u (max %u)", + gclog_or_tty->print_cr("Desired survivor size " SIZE_FORMAT " bytes, new threshold %u (max %u)", size_policy->calculated_survivor_size_in_bytes(), _tenuring_threshold, MaxTenuringThreshold); } diff --git a/hotspot/src/share/vm/gc_implementation/shared/ageTable.cpp b/hotspot/src/share/vm/gc_implementation/shared/ageTable.cpp index 50162a0adb1..311fd7771dd 100644 --- a/hotspot/src/share/vm/gc_implementation/shared/ageTable.cpp +++ b/hotspot/src/share/vm/gc_implementation/shared/ageTable.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, 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 @@ -96,7 +96,7 @@ uint ageTable::compute_tenuring_threshold(size_t survivor_capacity) { if (PrintTenuringDistribution) { gclog_or_tty->cr(); - gclog_or_tty->print_cr("Desired survivor size %ld bytes, new threshold %u (max %u)", + gclog_or_tty->print_cr("Desired survivor size " SIZE_FORMAT " bytes, new threshold %u (max %u)", desired_survivor_size*oopSize, result, MaxTenuringThreshold); } diff --git a/hotspot/src/share/vm/memory/universe.cpp b/hotspot/src/share/vm/memory/universe.cpp index c528d270c64..c9199228cb9 100644 --- a/hotspot/src/share/vm/memory/universe.cpp +++ b/hotspot/src/share/vm/memory/universe.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, 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 @@ -228,7 +228,7 @@ void Universe::check_alignment(uintx size, uintx alignment, const char* name) { if (size < alignment || size % alignment != 0) { ResourceMark rm; stringStream st; - st.print("Size of %s (%ld bytes) must be aligned to %ld bytes", name, size, alignment); + st.print("Size of %s (" UINTX_FORMAT " bytes) must be aligned to " UINTX_FORMAT " bytes", name, size, alignment); char* error = st.as_string(); vm_exit_during_initialization(error); } diff --git a/hotspot/src/share/vm/opto/idealGraphPrinter.cpp b/hotspot/src/share/vm/opto/idealGraphPrinter.cpp index 0928704d9cb..1f811b8f4b8 100644 --- a/hotspot/src/share/vm/opto/idealGraphPrinter.cpp +++ b/hotspot/src/share/vm/opto/idealGraphPrinter.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2013, 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 @@ -547,7 +547,7 @@ void IdealGraphPrinter::visit_node(Node *n, bool edges, VectorSet* temp_set) { // max. 2 chars allowed if (value >= -9 && value <= 99) { - sprintf(buffer, INT64_FORMAT, value); + sprintf(buffer, JLONG_FORMAT, value); print_prop(short_name, buffer); } else { print_prop(short_name, "L"); diff --git a/hotspot/src/share/vm/opto/type.cpp b/hotspot/src/share/vm/opto/type.cpp index 1a8ee2597dd..3928c23aff3 100644 --- a/hotspot/src/share/vm/opto/type.cpp +++ b/hotspot/src/share/vm/opto/type.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, 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 @@ -1542,10 +1542,10 @@ bool TypeLong::is_finite() const { static const char* longnamenear(jlong x, const char* xname, char* buf, jlong n) { if (n > x) { if (n >= x + 10000) return NULL; - sprintf(buf, "%s+" INT64_FORMAT, xname, n - x); + sprintf(buf, "%s+" JLONG_FORMAT, xname, n - x); } else if (n < x) { if (n <= x - 10000) return NULL; - sprintf(buf, "%s-" INT64_FORMAT, xname, x - n); + sprintf(buf, "%s-" JLONG_FORMAT, xname, x - n); } else { return xname; } @@ -1557,11 +1557,11 @@ static const char* longname(char* buf, jlong n) { if (n == min_jlong) return "min"; else if (n < min_jlong + 10000) - sprintf(buf, "min+" INT64_FORMAT, n - min_jlong); + sprintf(buf, "min+" JLONG_FORMAT, n - min_jlong); else if (n == max_jlong) return "max"; else if (n > max_jlong - 10000) - sprintf(buf, "max-" INT64_FORMAT, max_jlong - n); + sprintf(buf, "max-" JLONG_FORMAT, max_jlong - n); else if ((str = longnamenear(max_juint, "maxuint", buf, n)) != NULL) return str; else if ((str = longnamenear(max_jint, "maxint", buf, n)) != NULL) @@ -1569,7 +1569,7 @@ static const char* longname(char* buf, jlong n) { else if ((str = longnamenear(min_jint, "minint", buf, n)) != NULL) return str; else - sprintf(buf, INT64_FORMAT, n); + sprintf(buf, JLONG_FORMAT, n); return buf; } diff --git a/hotspot/src/share/vm/runtime/aprofiler.cpp b/hotspot/src/share/vm/runtime/aprofiler.cpp index 6c4e9cc428d..e71bfb587ef 100644 --- a/hotspot/src/share/vm/runtime/aprofiler.cpp +++ b/hotspot/src/share/vm/runtime/aprofiler.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, 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 @@ -129,7 +129,7 @@ void AllocationProfiler::print(size_t cutoff) { assert(!is_active(), "AllocationProfiler cannot be active while printing profile"); tty->cr(); - tty->print_cr("Allocation profile (sizes in bytes, cutoff = %ld bytes):", cutoff * BytesPerWord); + tty->print_cr("Allocation profile (sizes in bytes, cutoff = " SIZE_FORMAT " bytes):", cutoff * BytesPerWord); tty->cr(); // Print regular instance klasses and basic type array klasses diff --git a/hotspot/src/share/vm/runtime/arguments.cpp b/hotspot/src/share/vm/runtime/arguments.cpp index 65f6e03b7ff..d5d700441df 100644 --- a/hotspot/src/share/vm/runtime/arguments.cpp +++ b/hotspot/src/share/vm/runtime/arguments.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, 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 @@ -532,7 +532,7 @@ char* SysClassPath::add_jars_to_path(char* path, const char* directory) { // Parses a memory size specification string. static bool atomull(const char *s, julong* result) { julong n = 0; - int args_read = sscanf(s, os::julong_format_specifier(), &n); + int args_read = sscanf(s, JULONG_FORMAT, &n); if (args_read != 1) { return false; } diff --git a/hotspot/src/share/vm/runtime/os.hpp b/hotspot/src/share/vm/runtime/os.hpp index 235005f9890..d061a0848c6 100644 --- a/hotspot/src/share/vm/runtime/os.hpp +++ b/hotspot/src/share/vm/runtime/os.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, 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 @@ -641,10 +641,6 @@ class os: AllStatic { static struct hostent* get_host_by_name(char* name); - // Printing 64 bit integers - static const char* jlong_format_specifier(); - static const char* julong_format_specifier(); - // Support for signals (see JVM_RaiseSignal, JVM_RegisterSignal) static void signal_init(); static void signal_init_pd(); diff --git a/hotspot/src/share/vm/runtime/perfData.cpp b/hotspot/src/share/vm/runtime/perfData.cpp index ddb565b074c..777ea27f906 100644 --- a/hotspot/src/share/vm/runtime/perfData.cpp +++ b/hotspot/src/share/vm/runtime/perfData.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2013, 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 @@ -192,7 +192,7 @@ PerfLong::PerfLong(CounterNS ns, const char* namep, Units u, Variability v) } int PerfLong::format(char* buffer, int length) { - return jio_snprintf(buffer, length,"%lld", *(jlong*)_valuep); + return jio_snprintf(buffer, length, JLONG_FORMAT, *(jlong*)_valuep); } PerfLongVariant::PerfLongVariant(CounterNS ns, const char* namep, Units u, diff --git a/hotspot/src/share/vm/runtime/virtualspace.cpp b/hotspot/src/share/vm/runtime/virtualspace.cpp index f33c1995e34..dffb588dbae 100644 --- a/hotspot/src/share/vm/runtime/virtualspace.cpp +++ b/hotspot/src/share/vm/runtime/virtualspace.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, 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 @@ -868,8 +868,8 @@ void VirtualSpace::print() { tty->print ("Virtual space:"); if (special()) tty->print(" (pinned in memory)"); tty->cr(); - tty->print_cr(" - committed: %ld", committed_size()); - tty->print_cr(" - reserved: %ld", reserved_size()); + tty->print_cr(" - committed: " SIZE_FORMAT, committed_size()); + tty->print_cr(" - reserved: " SIZE_FORMAT, reserved_size()); tty->print_cr(" - [low, high]: [" INTPTR_FORMAT ", " INTPTR_FORMAT "]", low(), high()); tty->print_cr(" - [low_b, high_b]: [" INTPTR_FORMAT ", " INTPTR_FORMAT "]", low_boundary(), high_boundary()); } diff --git a/hotspot/src/share/vm/services/diagnosticArgument.cpp b/hotspot/src/share/vm/services/diagnosticArgument.cpp index 23267fae520..5d0eb756b28 100644 --- a/hotspot/src/share/vm/services/diagnosticArgument.cpp +++ b/hotspot/src/share/vm/services/diagnosticArgument.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2012 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2013 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 @@ -86,7 +86,7 @@ void GenDCmdArgument::to_string(StringArrayArgument* f, char* buf, size_t len) { template <> void DCmdArgument::parse_value(const char* str, size_t len, TRAPS) { - if (str == NULL || sscanf(str, INT64_FORMAT, &_value) != 1) { + if (str == NULL || sscanf(str, JLONG_FORMAT, &_value) != 1) { THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), "Integer parsing error in diagnostic command arguments\n"); } @@ -171,7 +171,7 @@ template <> void DCmdArgument::parse_value(const char* str, "Integer parsing error nanotime value: syntax error"); } - int argc = sscanf(str, INT64_FORMAT , &_value._time); + int argc = sscanf(str, JLONG_FORMAT, &_value._time); if (argc != 1) { THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), "Integer parsing error nanotime value: syntax error"); diff --git a/hotspot/src/share/vm/services/heapDumper.cpp b/hotspot/src/share/vm/services/heapDumper.cpp index 0dbe2e86589..65ee27f457a 100644 --- a/hotspot/src/share/vm/services/heapDumper.cpp +++ b/hotspot/src/share/vm/services/heapDumper.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2013, 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 @@ -1866,7 +1866,7 @@ int HeapDumper::dump(const char* path) { if (error() == NULL) { char msg[256]; sprintf(msg, "Heap dump file created [%s bytes in %3.3f secs]", - os::jlong_format_specifier(), timer()->seconds()); + JLONG_FORMAT, timer()->seconds()); tty->print_cr(msg, writer.bytes_written()); } else { tty->print_cr("Dump file is incomplete: %s", writer.error()); diff --git a/hotspot/src/share/vm/services/lowMemoryDetector.cpp b/hotspot/src/share/vm/services/lowMemoryDetector.cpp index babd93ac85b..199a342dd77 100644 --- a/hotspot/src/share/vm/services/lowMemoryDetector.cpp +++ b/hotspot/src/share/vm/services/lowMemoryDetector.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2013, 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 @@ -353,7 +353,7 @@ void SensorInfo::clear(int count, TRAPS) { #ifndef PRODUCT void SensorInfo::print() { - tty->print_cr("%s count = %ld pending_triggers = %ld pending_clears = %ld", + tty->print_cr("%s count = " SIZE_FORMAT " pending_triggers = %ld pending_clears = %ld", (_sensor_on ? "on" : "off"), _sensor_count, _pending_trigger_count, _pending_clear_count); } diff --git a/hotspot/src/share/vm/utilities/globalDefinitions.hpp b/hotspot/src/share/vm/utilities/globalDefinitions.hpp index e00be90320e..5c10cf018be 100644 --- a/hotspot/src/share/vm/utilities/globalDefinitions.hpp +++ b/hotspot/src/share/vm/utilities/globalDefinitions.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, 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 @@ -1250,6 +1250,14 @@ inline int build_int_from_shorts( jushort low, jushort high ) { #define PTR64_FORMAT "0x%016" PRIx64 +// Format jlong, if necessary +#ifndef JLONG_FORMAT +#define JLONG_FORMAT INT64_FORMAT +#endif +#ifndef JULONG_FORMAT +#define JULONG_FORMAT UINT64_FORMAT +#endif + // Format pointers which change size between 32- and 64-bit. #ifdef _LP64 #define INTPTR_FORMAT "0x%016" PRIxPTR diff --git a/hotspot/src/share/vm/utilities/globalDefinitions_gcc.hpp b/hotspot/src/share/vm/utilities/globalDefinitions_gcc.hpp index e103816de93..a69708f8c8f 100644 --- a/hotspot/src/share/vm/utilities/globalDefinitions_gcc.hpp +++ b/hotspot/src/share/vm/utilities/globalDefinitions_gcc.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2013, 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 @@ -306,4 +306,8 @@ inline int wcslen(const jchar* x) { return wcslen((const wchar_t*)x); } #endif #define offsetof(klass,field) offset_of(klass,field) +#if defined(_LP64) && defined(__APPLE__) +#define JLONG_FORMAT "%ld" +#endif // _LP64 && __APPLE__ + #endif // SHARE_VM_UTILITIES_GLOBALDEFINITIONS_GCC_HPP diff --git a/hotspot/src/share/vm/utilities/ostream.cpp b/hotspot/src/share/vm/utilities/ostream.cpp index 2b6e2eeb853..ea0a0c25bec 100644 --- a/hotspot/src/share/vm/utilities/ostream.cpp +++ b/hotspot/src/share/vm/utilities/ostream.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, 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 @@ -243,13 +243,11 @@ outputStream& outputStream::indent() { } void outputStream::print_jlong(jlong value) { - // N.B. Same as INT64_FORMAT - print(os::jlong_format_specifier(), value); + print(JLONG_FORMAT, value); } void outputStream::print_julong(julong value) { - // N.B. Same as UINT64_FORMAT - print(os::julong_format_specifier(), value); + print(JULONG_FORMAT, value); } /** diff --git a/hotspot/src/share/vm/utilities/taskqueue.cpp b/hotspot/src/share/vm/utilities/taskqueue.cpp index fbb035adf0c..862c9b304fb 100644 --- a/hotspot/src/share/vm/utilities/taskqueue.cpp +++ b/hotspot/src/share/vm/utilities/taskqueue.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2013, 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 @@ -239,8 +239,8 @@ ParallelTaskTerminator::offer_termination(TerminatorTerminator* terminator) { #ifdef TRACESPINNING void ParallelTaskTerminator::print_termination_counts() { - gclog_or_tty->print_cr("ParallelTaskTerminator Total yields: %lld " - "Total spins: %lld Total peeks: %lld", + gclog_or_tty->print_cr("ParallelTaskTerminator Total yields: " UINT32_FORMAT + " Total spins: " UINT32_FORMAT " Total peeks: " UINT32_FORMAT, total_yields(), total_spins(), total_peeks()); From 0a95b1d28c920504ef3323e356a6338e388575b2 Mon Sep 17 00:00:00 2001 From: Maurizio Cimadamore Date: Thu, 17 Jan 2013 18:15:20 +0000 Subject: [PATCH 049/210] 8005852: Treatment of '_' as identifier Warn when '_' is found in an identifier position Reviewed-by: jjg --- .../sun/tools/javac/parser/JavacParser.java | 137 ++++++++++-------- .../com/sun/tools/javac/parser/Tokens.java | 10 +- .../tools/javac/resources/compiler.properties | 4 + .../tools/javac/lambda/LambdaParserTest.java | 78 ++++++---- 4 files changed, 137 insertions(+), 92 deletions(-) diff --git a/langtools/src/share/classes/com/sun/tools/javac/parser/JavacParser.java b/langtools/src/share/classes/com/sun/tools/javac/parser/JavacParser.java index 28f6d8a29eb..a44f9c310bf 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/parser/JavacParser.java +++ b/langtools/src/share/classes/com/sun/tools/javac/parser/JavacParser.java @@ -245,40 +245,42 @@ public class JavacParser implements Parser { token = S.token(); } - protected boolean peekToken(TokenKind tk) { + protected boolean peekToken(Filter tk) { return peekToken(0, tk); } - protected boolean peekToken(int lookahead, TokenKind tk) { - return S.token(lookahead + 1).kind == tk; + protected boolean peekToken(int lookahead, Filter tk) { + return tk.accepts(S.token(lookahead + 1).kind); } - protected boolean peekToken(TokenKind tk1, TokenKind tk2) { + protected boolean peekToken(Filter tk1, Filter tk2) { return peekToken(0, tk1, tk2); } - protected boolean peekToken(int lookahead, TokenKind tk1, TokenKind tk2) { - return S.token(lookahead + 1).kind == tk1 && - S.token(lookahead + 2).kind == tk2; + protected boolean peekToken(int lookahead, Filter tk1, Filter tk2) { + return tk1.accepts(S.token(lookahead + 1).kind) && + tk2.accepts(S.token(lookahead + 2).kind); } - protected boolean peekToken(TokenKind tk1, TokenKind tk2, TokenKind tk3) { + protected boolean peekToken(Filter tk1, Filter tk2, Filter tk3) { return peekToken(0, tk1, tk2, tk3); } - protected boolean peekToken(int lookahead, TokenKind tk1, TokenKind tk2, TokenKind tk3) { - return S.token(lookahead + 1).kind == tk1 && - S.token(lookahead + 2).kind == tk2 && - S.token(lookahead + 3).kind == tk3; + protected boolean peekToken(int lookahead, Filter tk1, Filter tk2, Filter tk3) { + return tk1.accepts(S.token(lookahead + 1).kind) && + tk2.accepts(S.token(lookahead + 2).kind) && + tk3.accepts(S.token(lookahead + 3).kind); } - protected boolean peekToken(TokenKind... kinds) { + @SuppressWarnings("unchecked") + protected boolean peekToken(Filter... kinds) { return peekToken(0, kinds); } - protected boolean peekToken(int lookahead, TokenKind... kinds) { + @SuppressWarnings("unchecked") + protected boolean peekToken(int lookahead, Filter... kinds) { for (; lookahead < kinds.length ; lookahead++) { - if (S.token(lookahead + 1).kind != kinds[lookahead]) { + if (!kinds[lookahead].accepts(S.token(lookahead + 1).kind)) { return false; } } @@ -333,6 +335,7 @@ public class JavacParser implements Parser { if (stopAtMemberDecl) return; break; + case UNDERSCORE: case IDENTIFIER: if (stopAtIdentifier) return; @@ -552,11 +555,16 @@ public class JavacParser implements Parser { nextToken(); return name; } + } else if (token.kind == UNDERSCORE) { + warning(token.pos, "underscore.as.identifier"); + Name name = token.name(); + nextToken(); + return name; } else { accept(IDENTIFIER); return names.error; } -} + } /** * Qualident = Ident { DOT Ident } @@ -1056,7 +1064,7 @@ public class JavacParser implements Parser { typeArgs = null; } else return illegal(); break; - case IDENTIFIER: case ASSERT: case ENUM: + case UNDERSCORE: case IDENTIFIER: case ASSERT: case ENUM: if (typeArgs != null) return illegal(); if ((mode & EXPR) != 0 && peekToken(ARROW)) { t = lambdaExpressionOrStatement(false, false, pos); @@ -1274,7 +1282,7 @@ public class JavacParser implements Parser { int pos = 0, depth = 0; for (Token t = S.token(pos) ; ; t = S.token(++pos)) { switch (t.kind) { - case IDENTIFIER: case QUES: case EXTENDS: case SUPER: + case IDENTIFIER: case UNDERSCORE: case QUES: case EXTENDS: case SUPER: case DOT: case RBRACKET: case LBRACKET: case COMMA: case BYTE: case SHORT: case INT: case LONG: case FLOAT: case DOUBLE: case BOOLEAN: case CHAR: @@ -1323,8 +1331,8 @@ public class JavacParser implements Parser { if (peekToken(lookahead, RPAREN)) { //Type, ')' -> cast return ParensResult.CAST; - } else if (peekToken(lookahead, IDENTIFIER)) { - //Type, 'Identifier -> explicit lambda + } else if (peekToken(lookahead, LAX_IDENTIFIER)) { + //Type, Identifier/'_'/'assert'/'enum' -> explicit lambda return ParensResult.EXPLICIT_LAMBDA; } break; @@ -1350,16 +1358,19 @@ public class JavacParser implements Parser { case INTLITERAL: case LONGLITERAL: case FLOATLITERAL: case DOUBLELITERAL: case CHARLITERAL: case STRINGLITERAL: case TRUE: case FALSE: case NULL: - case NEW: case IDENTIFIER: case ASSERT: case ENUM: + case NEW: case IDENTIFIER: case ASSERT: case ENUM: case UNDERSCORE: case BYTE: case SHORT: case CHAR: case INT: case LONG: case FLOAT: case DOUBLE: case BOOLEAN: case VOID: return ParensResult.CAST; default: return ParensResult.PARENS; } + case UNDERSCORE: + case ASSERT: + case ENUM: case IDENTIFIER: - if (peekToken(lookahead, IDENTIFIER)) { - // Identifier, Identifier -> explicit lambda + if (peekToken(lookahead, LAX_IDENTIFIER)) { + // Identifier, Identifier/'_'/'assert'/'enum' -> explicit lambda return ParensResult.EXPLICIT_LAMBDA; } else if (peekToken(lookahead, RPAREN, ARROW)) { // Identifier, ')' '->' -> implicit lambda @@ -1372,8 +1383,8 @@ public class JavacParser implements Parser { //those can only appear in explicit lambdas return ParensResult.EXPLICIT_LAMBDA; case LBRACKET: - if (peekToken(lookahead, RBRACKET, IDENTIFIER)) { - // '[', ']', Identifier -> explicit lambda + if (peekToken(lookahead, RBRACKET, LAX_IDENTIFIER)) { + // '[', ']', Identifier/'_'/'assert'/'enum' -> explicit lambda return ParensResult.EXPLICIT_LAMBDA; } else if (peekToken(lookahead, RBRACKET, RPAREN) || peekToken(lookahead, RBRACKET, AMP)) { @@ -1402,11 +1413,11 @@ public class JavacParser implements Parser { // '>', ')' -> cast // '>', '&' -> cast return ParensResult.CAST; - } else if (peekToken(lookahead, IDENTIFIER, COMMA) || - peekToken(lookahead, IDENTIFIER, RPAREN, ARROW) || + } else if (peekToken(lookahead, LAX_IDENTIFIER, COMMA) || + peekToken(lookahead, LAX_IDENTIFIER, RPAREN, ARROW) || peekToken(lookahead, ELLIPSIS)) { - // '>', Identifier, ',' -> explicit lambda - // '>', Identifier, ')', '->' -> explicit lambda + // '>', Identifier/'_'/'assert'/'enum', ',' -> explicit lambda + // '>', Identifier/'_'/'assert'/'enum', ')', '->' -> explicit lambda // '>', '...' -> explicit lambda return ParensResult.EXPLICIT_LAMBDA; } @@ -1426,6 +1437,13 @@ public class JavacParser implements Parser { } } + /** Accepts all identifier-like tokens */ + Filter LAX_IDENTIFIER = new Filter() { + public boolean accepts(TokenKind t) { + return t == IDENTIFIER || t == UNDERSCORE || t == ASSERT || t == ENUM; + } + }; + enum ParensResult { CAST, EXPLICIT_LAMBDA, @@ -1433,21 +1451,9 @@ public class JavacParser implements Parser { PARENS; } - JCExpression lambdaExpressionOrStatement(JCVariableDecl firstParam, int pos) { - ListBuffer params = new ListBuffer(); - params.append(firstParam); - JCVariableDecl lastParam = firstParam; - while ((lastParam.mods.flags & Flags.VARARGS) == 0 && token.kind == COMMA) { - nextToken(); - params.append(lastParam = formalParameter()); - } - accept(RPAREN); - return lambdaExpressionOrStatementRest(params.toList(), pos); - } - JCExpression lambdaExpressionOrStatement(boolean hasParens, boolean explicitParams, int pos) { List params = explicitParams ? - formalParameters() : + formalParameters(true) : implicitParameters(hasParens); return lambdaExpressionOrStatementRest(params, pos); @@ -1628,7 +1634,7 @@ public class JavacParser implements Parser { nextToken(); JCExpression bound = parseType(); return F.at(pos).Wildcard(t, bound); - } else if (token.kind == IDENTIFIER) { + } else if (LAX_IDENTIFIER.accepts(token.kind)) { //error recovery TypeBoundKind t = F.at(Position.NOPOS).TypeBoundKind(BoundKind.UNBOUND); JCExpression wc = toP(F.at(pos).Wildcard(t, null)); @@ -1678,7 +1684,7 @@ public class JavacParser implements Parser { if (token.pos == endPosTable.errorEndPos) { // error recovery Name name = null; - if (token.kind == IDENTIFIER) { + if (LAX_IDENTIFIER.accepts(token.kind)) { name = token.name(); nextToken(); } else { @@ -2026,10 +2032,7 @@ public class JavacParser implements Parser { nextToken(); JCStatement stat = parseStatement(); return List.of(F.at(pos).Labelled(prevToken.name(), stat)); - } else if ((lastmode & TYPE) != 0 && - (token.kind == IDENTIFIER || - token.kind == ASSERT || - token.kind == ENUM)) { + } else if ((lastmode & TYPE) != 0 && LAX_IDENTIFIER.accepts(token.kind)) { pos = token.pos; JCModifiers mods = F.at(Position.NOPOS).Modifiers(0); F.at(pos); @@ -2183,14 +2186,14 @@ public class JavacParser implements Parser { } case BREAK: { nextToken(); - Name label = (token.kind == IDENTIFIER || token.kind == ASSERT || token.kind == ENUM) ? ident() : null; + Name label = LAX_IDENTIFIER.accepts(token.kind) ? ident() : null; JCBreak t = to(F.at(pos).Break(label)); accept(SEMI); return t; } case CONTINUE: { nextToken(); - Name label = (token.kind == IDENTIFIER || token.kind == ASSERT || token.kind == ENUM) ? ident() : null; + Name label = LAX_IDENTIFIER.accepts(token.kind) ? ident() : null; JCContinue t = to(F.at(pos).Continue(label)); accept(SEMI); return t; @@ -2351,9 +2354,7 @@ public class JavacParser implements Parser { return variableDeclarators(optFinal(0), parseType(), stats).toList(); } else { JCExpression t = term(EXPR | TYPE); - if ((lastmode & TYPE) != 0 && - (token.kind == IDENTIFIER || token.kind == ASSERT || - token.kind == ENUM)) { + if ((lastmode & TYPE) != 0 && LAX_IDENTIFIER.accepts(token.kind)) { return variableDeclarators(modifiersOpt(), t, stats).toList(); } else if ((lastmode & TYPE) != 0 && token.kind == COLON) { error(pos, "bad.initializer", "for-loop"); @@ -2609,8 +2610,18 @@ public class JavacParser implements Parser { /** VariableDeclaratorId = Ident BracketsOpt */ JCVariableDecl variableDeclaratorId(JCModifiers mods, JCExpression type) { + return variableDeclaratorId(mods, type, false); + } + //where + JCVariableDecl variableDeclaratorId(JCModifiers mods, JCExpression type, boolean lambdaParameter) { int pos = token.pos; - Name name = ident(); + Name name; + if (lambdaParameter && token.kind == UNDERSCORE) { + syntaxError(pos, "expected", IDENTIFIER); + name = token.name(); + } else { + name = ident(); + } if ((mods.flags & Flags.VARARGS) != 0 && token.kind == LBRACKET) { log.error(token.pos, "varargs.and.old.array.syntax"); @@ -2770,7 +2781,7 @@ public class JavacParser implements Parser { } else { int pos = token.pos; List errs; - if (token.kind == IDENTIFIER) { + if (LAX_IDENTIFIER.accepts(token.kind)) { errs = List.of(mods, toP(F.at(pos).Ident(ident()))); setErrorEndPos(token.pos); } else { @@ -2787,7 +2798,7 @@ public class JavacParser implements Parser { } int pos = token.pos; List errs; - if (token.kind == IDENTIFIER) { + if (LAX_IDENTIFIER.accepts(token.kind)) { errs = List.of(mods, toP(F.at(pos).Ident(ident()))); setErrorEndPos(token.pos); } else { @@ -3182,14 +3193,17 @@ public class JavacParser implements Parser { * FormalParameterListNovarargs = [ FormalParameterListNovarargs , ] FormalParameter */ List formalParameters() { + return formalParameters(false); + } + List formalParameters(boolean lambdaParameters) { ListBuffer params = new ListBuffer(); JCVariableDecl lastParam = null; accept(LPAREN); if (token.kind != RPAREN) { - params.append(lastParam = formalParameter()); + params.append(lastParam = formalParameter(lambdaParameters)); while ((lastParam.mods.flags & Flags.VARARGS) == 0 && token.kind == COMMA) { nextToken(); - params.append(lastParam = formalParameter()); + params.append(lastParam = formalParameter(lambdaParameters)); } } accept(RPAREN); @@ -3225,6 +3239,9 @@ public class JavacParser implements Parser { * LastFormalParameter = { FINAL | '@' Annotation } Type '...' Ident | FormalParameter */ protected JCVariableDecl formalParameter() { + return formalParameter(false); + } + protected JCVariableDecl formalParameter(boolean lambdaParameter) { JCModifiers mods = optFinal(Flags.PARAMETER); JCExpression type = parseType(); if (token.kind == ELLIPSIS) { @@ -3233,12 +3250,12 @@ public class JavacParser implements Parser { type = to(F.at(token.pos).TypeArray(type)); nextToken(); } - return variableDeclaratorId(mods, type); + return variableDeclaratorId(mods, type, lambdaParameter); } protected JCVariableDecl implicitParameter() { JCModifiers mods = F.at(token.pos).Modifiers(Flags.PARAMETER); - return variableDeclaratorId(mods, null); + return variableDeclaratorId(mods, null, true); } /* ---------- auxiliary methods -------------- */ diff --git a/langtools/src/share/classes/com/sun/tools/javac/parser/Tokens.java b/langtools/src/share/classes/com/sun/tools/javac/parser/Tokens.java index 3e6362aa8e3..d55defedf73 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/parser/Tokens.java +++ b/langtools/src/share/classes/com/sun/tools/javac/parser/Tokens.java @@ -33,6 +33,7 @@ import com.sun.tools.javac.parser.Tokens.Token.Tag; import com.sun.tools.javac.util.List; import com.sun.tools.javac.util.Name; import com.sun.tools.javac.util.Context; +import com.sun.tools.javac.util.Filter; import com.sun.tools.javac.util.ListBuffer; import com.sun.tools.javac.util.Names; @@ -74,7 +75,6 @@ public class Tokens { protected Tokens(Context context) { context.put(tokensKey, this); names = Names.instance(context); - for (TokenKind t : TokenKind.values()) { if (t.name != null) enterKeyword(t.name, t); @@ -113,7 +113,7 @@ public class Tokens { * This enum defines all tokens used by the javac scanner. A token is * optionally associated with a name. */ - public enum TokenKind implements Formattable { + public enum TokenKind implements Formattable, Filter { EOF(), ERROR(), IDENTIFIER(Tag.NAMED), @@ -176,6 +176,7 @@ public class Tokens { TRUE("true", Tag.NAMED), FALSE("false", Tag.NAMED), NULL("null", Tag.NAMED), + UNDERSCORE("_", Tag.NAMED), ARROW("->"), COLCOL("::"), LPAREN("("), @@ -283,6 +284,11 @@ public class Tokens { public String toString(Locale locale, Messages messages) { return name != null ? toString() : messages.getLocalizedString(locale, "compiler.misc." + toString()); } + + @Override + public boolean accepts(TokenKind that) { + return this == that; + } } public interface Comment { diff --git a/langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties b/langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties index f04abc7c42a..c9febb4a215 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties +++ b/langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties @@ -2132,6 +2132,10 @@ compiler.warn.assert.as.identifier=\ as of release 1.4, ''assert'' is a keyword, and may not be used as an identifier\n\ (use -source 1.4 or higher to use ''assert'' as a keyword) +compiler.warn.underscore.as.identifier=\ + ''_'' used as an identifier\n\ + (use of ''_'' as an identifier might not be supported in future releases) + compiler.err.enum.as.identifier=\ as of release 5, ''enum'' is a keyword, and may not be used as an identifier\n\ (use -source 1.4 or lower to use ''enum'' as an identifier) diff --git a/langtools/test/tools/javac/lambda/LambdaParserTest.java b/langtools/test/tools/javac/lambda/LambdaParserTest.java index c4fb4f548a2..0574e47df62 100644 --- a/langtools/test/tools/javac/lambda/LambdaParserTest.java +++ b/langtools/test/tools/javac/lambda/LambdaParserTest.java @@ -23,8 +23,7 @@ /* * @test - * @bug 7115050 - * @bug 8003280 + * @bug 7115050 8003280 8005852 * @summary Add lambda tests * Add parser support for lambda expressions * @library ../lib @@ -46,12 +45,12 @@ public class LambdaParserTest enum LambdaKind { NILARY_EXPR("()->x"), NILARY_STMT("()->{ return x; }"), - ONEARY_SHORT_EXPR("x->x"), - ONEARY_SHORT_STMT("x->{ return x; }"), - ONEARY_EXPR("(#M1 #T1 x)->x"), - ONEARY_STMT("(#M1 #T1 x)->{ return x; }"), - TWOARY_EXPR("(#M1 #T1 x, #M2 #T2 y)->x"), - TWOARY_STMT("(#M1 #T1 x, #M2 #T2 y)->{ return x; }"); + ONEARY_SHORT_EXPR("#PN->x"), + ONEARY_SHORT_STMT("#PN->{ return x; }"), + ONEARY_EXPR("(#M1 #T1 #PN)->x"), + ONEARY_STMT("(#M1 #T1 #PN)->{ return x; }"), + TWOARY_EXPR("(#M1 #T1 #PN, #M2 #T2 y)->x"), + TWOARY_STMT("(#M1 #T1 #PN, #M2 #T2 y)->{ return x; }"); String lambdaTemplate; @@ -60,11 +59,12 @@ public class LambdaParserTest } String getLambdaString(LambdaParameterKind pk1, LambdaParameterKind pk2, - ModifierKind mk1, ModifierKind mk2) { + ModifierKind mk1, ModifierKind mk2, LambdaParameterName pn) { return lambdaTemplate.replaceAll("#M1", mk1.modifier) .replaceAll("#M2", mk2.modifier) .replaceAll("#T1", pk1.parameterType) - .replaceAll("#T2", pk2.parameterType); + .replaceAll("#T2", pk2.parameterType) + .replaceAll("#PN", pn.nameStr); } int arity() { @@ -87,6 +87,17 @@ public class LambdaParserTest } } + enum LambdaParameterName { + IDENT("x"), + UNDERSCORE("_"); + + String nameStr; + + LambdaParameterName(String nameStr) { + this.nameStr = nameStr; + } + } + enum LambdaParameterKind { IMPLICIT(""), EXPLIICT_SIMPLE("A"), @@ -151,8 +162,8 @@ public class LambdaParserTest } String expressionString(LambdaParameterKind pk1, LambdaParameterKind pk2, - ModifierKind mk1, ModifierKind mk2, LambdaKind lk, SubExprKind sk) { - return expressionTemplate.replaceAll("#L", lk.getLambdaString(pk1, pk2, mk1, mk2)) + ModifierKind mk1, ModifierKind mk2, LambdaKind lk, LambdaParameterName pn, SubExprKind sk) { + return expressionTemplate.replaceAll("#L", lk.getLambdaString(pk1, pk2, mk1, mk2, pn)) .replaceAll("#S", sk.subExpression); } } @@ -174,25 +185,27 @@ public class LambdaParserTest public static void main(String... args) throws Exception { for (LambdaKind lk : LambdaKind.values()) { - for (LambdaParameterKind pk1 : LambdaParameterKind.values()) { - if (lk.arity() < 1 && pk1 != LambdaParameterKind.IMPLICIT) - continue; - for (LambdaParameterKind pk2 : LambdaParameterKind.values()) { - if (lk.arity() < 2 && pk2 != LambdaParameterKind.IMPLICIT) + for (LambdaParameterName pn : LambdaParameterName.values()) { + for (LambdaParameterKind pk1 : LambdaParameterKind.values()) { + if (lk.arity() < 1 && pk1 != LambdaParameterKind.IMPLICIT) continue; - for (ModifierKind mk1 : ModifierKind.values()) { - if (mk1 != ModifierKind.NONE && lk.isShort()) + for (LambdaParameterKind pk2 : LambdaParameterKind.values()) { + if (lk.arity() < 2 && pk2 != LambdaParameterKind.IMPLICIT) continue; - if (lk.arity() < 1 && mk1 != ModifierKind.NONE) - continue; - for (ModifierKind mk2 : ModifierKind.values()) { - if (lk.arity() < 2 && mk2 != ModifierKind.NONE) + for (ModifierKind mk1 : ModifierKind.values()) { + if (mk1 != ModifierKind.NONE && lk.isShort()) continue; - for (SubExprKind sk : SubExprKind.values()) { - for (ExprKind ek : ExprKind.values()) { - pool.execute( - new LambdaParserTest(pk1, pk2, mk1, - mk2, lk, sk, ek)); + if (lk.arity() < 1 && mk1 != ModifierKind.NONE) + continue; + for (ModifierKind mk2 : ModifierKind.values()) { + if (lk.arity() < 2 && mk2 != ModifierKind.NONE) + continue; + for (SubExprKind sk : SubExprKind.values()) { + for (ExprKind ek : ExprKind.values()) { + pool.execute( + new LambdaParserTest(pk1, pk2, mk1, + mk2, lk, sk, ek, pn)); + } } } } @@ -209,6 +222,7 @@ public class LambdaParserTest ModifierKind mk1; ModifierKind mk2; LambdaKind lk; + LambdaParameterName pn; SubExprKind sk; ExprKind ek; JavaSource source; @@ -216,12 +230,13 @@ public class LambdaParserTest LambdaParserTest(LambdaParameterKind pk1, LambdaParameterKind pk2, ModifierKind mk1, ModifierKind mk2, LambdaKind lk, - SubExprKind sk, ExprKind ek) { + SubExprKind sk, ExprKind ek, LambdaParameterName pn) { this.pk1 = pk1; this.pk2 = pk2; this.mk1 = mk1; this.mk2 = mk2; this.lk = lk; + this.pn = pn; this.sk = sk; this.ek = ek; this.source = new JavaSource(); @@ -239,7 +254,7 @@ public class LambdaParserTest public JavaSource() { super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE); source = template.replaceAll("#E", - ek.expressionString(pk1, pk2, mk1, mk2, lk, sk)); + ek.expressionString(pk1, pk2, mk1, mk2, lk, pn, sk)); } @Override @@ -272,6 +287,9 @@ public class LambdaParserTest errorExpected = true; } + errorExpected |= pn == LambdaParameterName.UNDERSCORE && + lk.arity() > 0; + if (errorExpected != diagChecker.errorFound) { throw new Error("invalid diagnostics for source:\n" + source.getCharContent(true) + From e508ba9b0bd7553f7cf5e65858efafe26b56a956 Mon Sep 17 00:00:00 2001 From: Coleen Phillimore Date: Thu, 17 Jan 2013 13:40:31 -0500 Subject: [PATCH 050/210] 7174978: NPG: Fix bactrace builder for class redefinition Remove Method* from backtrace but save version so redefine classes doesn't give inaccurate line numbers. Removed old Merlin API with duplicate code. Reviewed-by: dholmes, sspitsyn --- hotspot/make/bsd/makefiles/mapfile-vers-debug | 3 +- .../make/bsd/makefiles/mapfile-vers-product | 3 +- .../make/linux/makefiles/mapfile-vers-debug | 3 +- .../make/linux/makefiles/mapfile-vers-product | 3 +- hotspot/make/solaris/makefiles/mapfile-vers | 3 +- .../src/share/vm/classfile/javaClasses.cpp | 530 +++++++++--------- .../src/share/vm/classfile/javaClasses.hpp | 17 +- hotspot/src/share/vm/oops/constantPool.cpp | 4 +- hotspot/src/share/vm/oops/constantPool.hpp | 13 +- hotspot/src/share/vm/prims/jvm.cpp | 11 +- hotspot/src/share/vm/prims/jvm.h | 5 +- .../share/vm/prims/jvmtiRedefineClasses.cpp | 43 +- 12 files changed, 297 insertions(+), 341 deletions(-) diff --git a/hotspot/make/bsd/makefiles/mapfile-vers-debug b/hotspot/make/bsd/makefiles/mapfile-vers-debug index 00fd1892716..ef827302c54 100644 --- a/hotspot/make/bsd/makefiles/mapfile-vers-debug +++ b/hotspot/make/bsd/makefiles/mapfile-vers-debug @@ -3,7 +3,7 @@ # # -# Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2002, 2013, 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 @@ -205,7 +205,6 @@ SUNWprivate_1.1 { JVM_NewMultiArray; JVM_OnExit; JVM_Open; - JVM_PrintStackTrace; JVM_RaiseSignal; JVM_RawMonitorCreate; JVM_RawMonitorDestroy; diff --git a/hotspot/make/bsd/makefiles/mapfile-vers-product b/hotspot/make/bsd/makefiles/mapfile-vers-product index dfa459f0316..0d2b04ca774 100644 --- a/hotspot/make/bsd/makefiles/mapfile-vers-product +++ b/hotspot/make/bsd/makefiles/mapfile-vers-product @@ -3,7 +3,7 @@ # # -# Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2002, 2013, 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 @@ -205,7 +205,6 @@ SUNWprivate_1.1 { JVM_NewMultiArray; JVM_OnExit; JVM_Open; - JVM_PrintStackTrace; JVM_RaiseSignal; JVM_RawMonitorCreate; JVM_RawMonitorDestroy; diff --git a/hotspot/make/linux/makefiles/mapfile-vers-debug b/hotspot/make/linux/makefiles/mapfile-vers-debug index d6ebedcb9bd..ae4e2f9bcc3 100644 --- a/hotspot/make/linux/makefiles/mapfile-vers-debug +++ b/hotspot/make/linux/makefiles/mapfile-vers-debug @@ -1,5 +1,5 @@ # -# Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2002, 2013, 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 @@ -201,7 +201,6 @@ SUNWprivate_1.1 { JVM_NewMultiArray; JVM_OnExit; JVM_Open; - JVM_PrintStackTrace; JVM_RaiseSignal; JVM_RawMonitorCreate; JVM_RawMonitorDestroy; diff --git a/hotspot/make/linux/makefiles/mapfile-vers-product b/hotspot/make/linux/makefiles/mapfile-vers-product index 733e3af4b11..9a3028d2a09 100644 --- a/hotspot/make/linux/makefiles/mapfile-vers-product +++ b/hotspot/make/linux/makefiles/mapfile-vers-product @@ -1,5 +1,5 @@ # -# Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2002, 2013, 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 @@ -201,7 +201,6 @@ SUNWprivate_1.1 { JVM_NewMultiArray; JVM_OnExit; JVM_Open; - JVM_PrintStackTrace; JVM_RaiseSignal; JVM_RawMonitorCreate; JVM_RawMonitorDestroy; diff --git a/hotspot/make/solaris/makefiles/mapfile-vers b/hotspot/make/solaris/makefiles/mapfile-vers index a10d5c1b4e6..bf21253062e 100644 --- a/hotspot/make/solaris/makefiles/mapfile-vers +++ b/hotspot/make/solaris/makefiles/mapfile-vers @@ -1,5 +1,5 @@ # -# Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2000, 2013, 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 @@ -201,7 +201,6 @@ SUNWprivate_1.1 { JVM_NewMultiArray; JVM_OnExit; JVM_Open; - JVM_PrintStackTrace; JVM_RaiseSignal; JVM_RawMonitorCreate; JVM_RawMonitorDestroy; diff --git a/hotspot/src/share/vm/classfile/javaClasses.cpp b/hotspot/src/share/vm/classfile/javaClasses.cpp index cb30a83d455..d63659fb867 100644 --- a/hotspot/src/share/vm/classfile/javaClasses.cpp +++ b/hotspot/src/share/vm/classfile/javaClasses.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, 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 @@ -1158,179 +1158,43 @@ void java_lang_Throwable::print(Handle throwable, outputStream* st) { } } -// Print stack trace element to resource allocated buffer -char* java_lang_Throwable::print_stack_element_to_buffer(Method* method, int bci) { - // Get strings and string lengths - InstanceKlass* klass = method->method_holder(); - const char* klass_name = klass->external_name(); - int buf_len = (int)strlen(klass_name); - char* source_file_name; - if (klass->source_file_name() == NULL) { - source_file_name = NULL; - } else { - source_file_name = klass->source_file_name()->as_C_string(); - buf_len += (int)strlen(source_file_name); - } - char* method_name = method->name()->as_C_string(); - buf_len += (int)strlen(method_name); +// After this many redefines, the stack trace is unreliable. +const int MAX_VERSION = USHRT_MAX; - // Allocate temporary buffer with extra space for formatting and line number - char* buf = NEW_RESOURCE_ARRAY(char, buf_len + 64); +// Helper backtrace functions to store bci|version together. +static inline int merge_bci_and_version(int bci, int version) { + // only store u2 for version, checking for overflow. + if (version > USHRT_MAX || version < 0) version = MAX_VERSION; + assert((jushort)bci == bci, "bci should be short"); + return build_int_from_shorts(version, bci); +} - // Print stack trace line in buffer - sprintf(buf, "\tat %s.%s", klass_name, method_name); +static inline int bci_at(unsigned int merged) { + return extract_high_short_from_int(merged); +} +static inline int version_at(unsigned int merged) { + return extract_low_short_from_int(merged); +} + +static inline bool version_matches(Method* method, int version) { + return (method->constants()->version() == version && version < MAX_VERSION); +} + +static inline int get_line_number(Method* method, int bci) { + int line_number = 0; if (method->is_native()) { - strcat(buf, "(Native Method)"); + // Negative value different from -1 below, enabling Java code in + // class java.lang.StackTraceElement to distinguish "native" from + // "no LineNumberTable". JDK tests for -2. + line_number = -2; } else { - int line_number = method->line_number_from_bci(bci); - if (source_file_name != NULL && (line_number != -1)) { - // Sourcename and linenumber - sprintf(buf + (int)strlen(buf), "(%s:%d)", source_file_name, line_number); - } else if (source_file_name != NULL) { - // Just sourcename - sprintf(buf + (int)strlen(buf), "(%s)", source_file_name); - } else { - // Neither soucename and linenumber - sprintf(buf + (int)strlen(buf), "(Unknown Source)"); - } - nmethod* nm = method->code(); - if (WizardMode && nm != NULL) { - sprintf(buf + (int)strlen(buf), "(nmethod " INTPTR_FORMAT ")", (intptr_t)nm); + // Returns -1 if no LineNumberTable, and otherwise actual line number + line_number = method->line_number_from_bci(bci); + if (line_number == -1 && ShowHiddenFrames) { + line_number = bci + 1000000; } } - - return buf; -} - - -void java_lang_Throwable::print_stack_element(Handle stream, Method* method, int bci) { - ResourceMark rm; - char* buf = print_stack_element_to_buffer(method, bci); - print_to_stream(stream, buf); -} - -void java_lang_Throwable::print_stack_element(outputStream *st, Method* method, int bci) { - ResourceMark rm; - char* buf = print_stack_element_to_buffer(method, bci); - st->print_cr("%s", buf); -} - -void java_lang_Throwable::print_to_stream(Handle stream, const char* str) { - if (stream.is_null()) { - tty->print_cr("%s", str); - } else { - EXCEPTION_MARK; - JavaValue result(T_VOID); - Handle arg (THREAD, oopFactory::new_charArray(str, THREAD)); - if (!HAS_PENDING_EXCEPTION) { - JavaCalls::call_virtual(&result, - stream, - KlassHandle(THREAD, stream->klass()), - vmSymbols::println_name(), - vmSymbols::char_array_void_signature(), - arg, - THREAD); - } - // Ignore any exceptions. we are in the middle of exception handling. Same as classic VM. - if (HAS_PENDING_EXCEPTION) CLEAR_PENDING_EXCEPTION; - } - -} - - -const char* java_lang_Throwable::no_stack_trace_message() { - return "\t<>"; -} - - -// Currently used only for exceptions occurring during startup -void java_lang_Throwable::print_stack_trace(oop throwable, outputStream* st) { - Thread *THREAD = Thread::current(); - Handle h_throwable(THREAD, throwable); - while (h_throwable.not_null()) { - objArrayHandle result (THREAD, objArrayOop(backtrace(h_throwable()))); - if (result.is_null()) { - st->print_cr(no_stack_trace_message()); - return; - } - - while (result.not_null()) { - typeArrayHandle methods (THREAD, - typeArrayOop(result->obj_at(trace_methods_offset))); - typeArrayHandle bcis (THREAD, - typeArrayOop(result->obj_at(trace_bcis_offset))); - - if (methods.is_null() || bcis.is_null()) { - st->print_cr(no_stack_trace_message()); - return; - } - - int length = methods()->length(); - for (int index = 0; index < length; index++) { - Method* method = ((Method*)methods()->metadata_at(index)); - if (method == NULL) goto handle_cause; - int bci = bcis->ushort_at(index); - print_stack_element(st, method, bci); - } - result = objArrayHandle(THREAD, objArrayOop(result->obj_at(trace_next_offset))); - } - handle_cause: - { - EXCEPTION_MARK; - JavaValue result(T_OBJECT); - JavaCalls::call_virtual(&result, - h_throwable, - KlassHandle(THREAD, h_throwable->klass()), - vmSymbols::getCause_name(), - vmSymbols::void_throwable_signature(), - THREAD); - // Ignore any exceptions. we are in the middle of exception handling. Same as classic VM. - if (HAS_PENDING_EXCEPTION) { - CLEAR_PENDING_EXCEPTION; - h_throwable = Handle(); - } else { - h_throwable = Handle(THREAD, (oop) result.get_jobject()); - if (h_throwable.not_null()) { - st->print("Caused by: "); - print(h_throwable, st); - st->cr(); - } - } - } - } -} - - -void java_lang_Throwable::print_stack_trace(oop throwable, oop print_stream) { - // Note: this is no longer used in Merlin, but we support it for compatibility. - Thread *thread = Thread::current(); - Handle stream(thread, print_stream); - objArrayHandle result (thread, objArrayOop(backtrace(throwable))); - if (result.is_null()) { - print_to_stream(stream, no_stack_trace_message()); - return; - } - - while (result.not_null()) { - typeArrayHandle methods(thread, - typeArrayOop(result->obj_at(trace_methods_offset))); - typeArrayHandle bcis (thread, - typeArrayOop(result->obj_at(trace_bcis_offset))); - - if (methods.is_null() || bcis.is_null()) { - print_to_stream(stream, no_stack_trace_message()); - return; - } - - int length = methods()->length(); - for (int index = 0; index < length; index++) { - Method* method = ((Method*)methods()->metadata_at(index)); - if (method == NULL) return; - int bci = bcis->ushort_at(index); - print_stack_element(stream, method, bci); - } - result = objArrayHandle(thread, objArrayOop(result->obj_at(trace_next_offset))); - } + return line_number; } // This class provides a simple wrapper over the internal structure of @@ -1350,13 +1214,30 @@ class BacktraceBuilder: public StackObj { enum { trace_methods_offset = java_lang_Throwable::trace_methods_offset, - trace_bcis_offset = java_lang_Throwable::trace_bcis_offset, + trace_bcis_offset = java_lang_Throwable::trace_bcis_offset, trace_mirrors_offset = java_lang_Throwable::trace_mirrors_offset, trace_next_offset = java_lang_Throwable::trace_next_offset, trace_size = java_lang_Throwable::trace_size, trace_chunk_size = java_lang_Throwable::trace_chunk_size }; + // get info out of chunks + static typeArrayOop get_methods(objArrayHandle chunk) { + typeArrayOop methods = typeArrayOop(chunk->obj_at(trace_methods_offset)); + assert(methods != NULL, "method array should be initialized in backtrace"); + return methods; + } + static typeArrayOop get_bcis(objArrayHandle chunk) { + typeArrayOop bcis = typeArrayOop(chunk->obj_at(trace_bcis_offset)); + assert(bcis != NULL, "bci array should be initialized in backtrace"); + return bcis; + } + static objArrayOop get_mirrors(objArrayHandle chunk) { + objArrayOop mirrors = objArrayOop(chunk->obj_at(trace_mirrors_offset)); + assert(mirrors != NULL, "mirror array should be initialized in backtrace"); + return mirrors; + } + // constructor for new backtrace BacktraceBuilder(TRAPS): _methods(NULL), _bcis(NULL), _head(NULL), _mirrors(NULL) { expand(CHECK); @@ -1364,6 +1245,19 @@ class BacktraceBuilder: public StackObj { _index = 0; } + BacktraceBuilder(objArrayHandle backtrace) { + _methods = get_methods(backtrace); + _bcis = get_bcis(backtrace); + _mirrors = get_mirrors(backtrace); + assert(_methods->length() == _bcis->length() && + _methods->length() == _mirrors->length(), + "method and source information arrays should match"); + + // head is the preallocated backtrace + _backtrace = _head = backtrace(); + _index = 0; + } + void expand(TRAPS) { objArrayHandle old_head(THREAD, _head); Pause_No_Safepoint_Verifier pnsv(&_nsv); @@ -1371,10 +1265,10 @@ class BacktraceBuilder: public StackObj { objArrayOop head = oopFactory::new_objectArray(trace_size, CHECK); objArrayHandle new_head(THREAD, head); - typeArrayOop methods = oopFactory::new_metaDataArray(trace_chunk_size, CHECK); + typeArrayOop methods = oopFactory::new_shortArray(trace_chunk_size, CHECK); typeArrayHandle new_methods(THREAD, methods); - typeArrayOop bcis = oopFactory::new_shortArray(trace_chunk_size, CHECK); + typeArrayOop bcis = oopFactory::new_intArray(trace_chunk_size, CHECK); typeArrayHandle new_bcis(THREAD, bcis); objArrayOop mirrors = oopFactory::new_objectArray(trace_chunk_size, CHECK); @@ -1389,7 +1283,7 @@ class BacktraceBuilder: public StackObj { _head = new_head(); _methods = new_methods(); - _bcis = new_bcis(); + _bcis = new_bcis(); _mirrors = new_mirrors(); _index = 0; } @@ -1403,7 +1297,6 @@ class BacktraceBuilder: public StackObj { // shorts. The later line number lookup would just smear the -1 // to a 0 even if it could be recorded. if (bci == SynchronizationEntryBCI) bci = 0; - assert(bci == (jushort)bci, "doesn't fit"); if (_index >= trace_chunk_size) { methodHandle mhandle(THREAD, method); @@ -1411,26 +1304,148 @@ class BacktraceBuilder: public StackObj { method = mhandle(); } - _methods->metadata_at_put(_index, method); - _bcis->ushort_at_put(_index, bci); - // we need to save the mirrors in the backtrace to keep the methods from - // being unloaded if their class loader is unloaded while we still have - // this stack trace. + _methods->short_at_put(_index, method->method_idnum()); + _bcis->int_at_put(_index, merge_bci_and_version(bci, method->constants()->version())); + + // We need to save the mirrors in the backtrace to keep the class + // from being unloaded while we still have this stack trace. + assert(method->method_holder()->java_mirror() != NULL, "never push null for mirror"); _mirrors->obj_at_put(_index, method->method_holder()->java_mirror()); _index++; } - Method* current_method() { - assert(_index >= 0 && _index < trace_chunk_size, "out of range"); - return ((Method*)_methods->metadata_at(_index)); - } - - jushort current_bci() { - assert(_index >= 0 && _index < trace_chunk_size, "out of range"); - return _bcis->ushort_at(_index); - } }; +// Print stack trace element to resource allocated buffer +char* java_lang_Throwable::print_stack_element_to_buffer(Handle mirror, + int method_id, int version, int bci) { + + // Get strings and string lengths + InstanceKlass* holder = InstanceKlass::cast(java_lang_Class::as_Klass(mirror())); + const char* klass_name = holder->external_name(); + int buf_len = (int)strlen(klass_name); + + // pushing to the stack trace added one. + Method* method = holder->method_with_idnum(method_id); + char* method_name = method->name()->as_C_string(); + buf_len += (int)strlen(method_name); + + char* source_file_name = NULL; + if (version_matches(method, version)) { + Symbol* source = holder->source_file_name(); + if (source != NULL) { + source_file_name = source->as_C_string(); + buf_len += (int)strlen(source_file_name); + } + } + + // Allocate temporary buffer with extra space for formatting and line number + char* buf = NEW_RESOURCE_ARRAY(char, buf_len + 64); + + // Print stack trace line in buffer + sprintf(buf, "\tat %s.%s", klass_name, method_name); + + if (!version_matches(method, version)) { + strcat(buf, "(Redefined)"); + } else { + int line_number = get_line_number(method, bci); + if (line_number == -2) { + strcat(buf, "(Native Method)"); + } else { + if (source_file_name != NULL && (line_number != -1)) { + // Sourcename and linenumber + sprintf(buf + (int)strlen(buf), "(%s:%d)", source_file_name, line_number); + } else if (source_file_name != NULL) { + // Just sourcename + sprintf(buf + (int)strlen(buf), "(%s)", source_file_name); + } else { + // Neither sourcename nor linenumber + sprintf(buf + (int)strlen(buf), "(Unknown Source)"); + } + nmethod* nm = method->code(); + if (WizardMode && nm != NULL) { + sprintf(buf + (int)strlen(buf), "(nmethod " INTPTR_FORMAT ")", (intptr_t)nm); + } + } + } + + return buf; +} + +void java_lang_Throwable::print_stack_element(outputStream *st, Handle mirror, + int method_id, int version, int bci) { + ResourceMark rm; + char* buf = print_stack_element_to_buffer(mirror, method_id, version, bci); + st->print_cr("%s", buf); +} + +void java_lang_Throwable::print_stack_element(outputStream *st, methodHandle method, int bci) { + Handle mirror = method->method_holder()->java_mirror(); + int method_id = method->method_idnum(); + int version = method->constants()->version(); + print_stack_element(st, mirror, method_id, version, bci); +} + +const char* java_lang_Throwable::no_stack_trace_message() { + return "\t<>"; +} + + +// Currently used only for exceptions occurring during startup +void java_lang_Throwable::print_stack_trace(oop throwable, outputStream* st) { + Thread *THREAD = Thread::current(); + Handle h_throwable(THREAD, throwable); + while (h_throwable.not_null()) { + objArrayHandle result (THREAD, objArrayOop(backtrace(h_throwable()))); + if (result.is_null()) { + st->print_cr(no_stack_trace_message()); + return; + } + + while (result.not_null()) { + + // Get method id, bci, version and mirror from chunk + typeArrayHandle methods (THREAD, BacktraceBuilder::get_methods(result)); + typeArrayHandle bcis (THREAD, BacktraceBuilder::get_bcis(result)); + objArrayHandle mirrors (THREAD, BacktraceBuilder::get_mirrors(result)); + + int length = methods()->length(); + for (int index = 0; index < length; index++) { + Handle mirror(THREAD, mirrors->obj_at(index)); + // NULL mirror means end of stack trace + if (mirror.is_null()) goto handle_cause; + int method = methods->short_at(index); + int version = version_at(bcis->int_at(index)); + int bci = bci_at(bcis->int_at(index)); + print_stack_element(st, mirror, method, version, bci); + } + result = objArrayHandle(THREAD, objArrayOop(result->obj_at(trace_next_offset))); + } + handle_cause: + { + EXCEPTION_MARK; + JavaValue cause(T_OBJECT); + JavaCalls::call_virtual(&cause, + h_throwable, + KlassHandle(THREAD, h_throwable->klass()), + vmSymbols::getCause_name(), + vmSymbols::void_throwable_signature(), + THREAD); + // Ignore any exceptions. we are in the middle of exception handling. Same as classic VM. + if (HAS_PENDING_EXCEPTION) { + CLEAR_PENDING_EXCEPTION; + h_throwable = Handle(); + } else { + h_throwable = Handle(THREAD, (oop) cause.get_jobject()); + if (h_throwable.not_null()) { + st->print("Caused by: "); + print(h_throwable, st); + st->cr(); + } + } + } + } +} void java_lang_Throwable::fill_in_stack_trace(Handle throwable, methodHandle method, TRAPS) { if (!StackTraceInThrowable) return; @@ -1591,21 +1606,8 @@ void java_lang_Throwable::allocate_backtrace(Handle throwable, TRAPS) { // No-op if stack trace is disabled if (!StackTraceInThrowable) return; - - objArrayOop h_oop = oopFactory::new_objectArray(trace_size, CHECK); - objArrayHandle backtrace (THREAD, h_oop); - typeArrayOop m_oop = oopFactory::new_metaDataArray(trace_chunk_size, CHECK); - typeArrayHandle methods (THREAD, m_oop); - typeArrayOop b = oopFactory::new_shortArray(trace_chunk_size, CHECK); - typeArrayHandle bcis(THREAD, b); - objArrayOop mirror_oop = oopFactory::new_objectArray(trace_chunk_size, CHECK); - objArrayHandle mirrors (THREAD, mirror_oop); - - // backtrace has space for one chunk (next is NULL) - backtrace->obj_at_put(trace_methods_offset, methods()); - backtrace->obj_at_put(trace_bcis_offset, bcis()); - backtrace->obj_at_put(trace_mirrors_offset, mirrors()); - set_backtrace(throwable(), backtrace()); + BacktraceBuilder bt(CHECK); // creates a backtrace + set_backtrace(throwable(), bt.backtrace()); } @@ -1617,48 +1619,26 @@ void java_lang_Throwable::fill_in_stack_trace_of_preallocated_backtrace(Handle t assert(throwable->is_a(SystemDictionary::Throwable_klass()), "sanity check"); - objArrayOop backtrace = (objArrayOop)java_lang_Throwable::backtrace(throwable()); - assert(backtrace != NULL, "backtrace not preallocated"); + JavaThread* THREAD = JavaThread::current(); - oop m = backtrace->obj_at(trace_methods_offset); - typeArrayOop methods = typeArrayOop(m); - assert(methods != NULL && methods->length() > 0, "method array not preallocated"); + objArrayHandle backtrace (THREAD, (objArrayOop)java_lang_Throwable::backtrace(throwable())); + assert(backtrace.not_null(), "backtrace should have been preallocated"); - oop b = backtrace->obj_at(trace_bcis_offset); - typeArrayOop bcis = typeArrayOop(b); - assert(bcis != NULL, "bci array not preallocated"); + ResourceMark rm(THREAD); + vframeStream st(THREAD); - oop mr = backtrace->obj_at(trace_mirrors_offset); - objArrayOop mirrors = objArrayOop(mr); - assert(mirrors != NULL, "bci array not preallocated"); - - assert(methods->length() == bcis->length() && - methods->length() == mirrors->length(), - "method and bci arrays should match"); - - JavaThread* thread = JavaThread::current(); - ResourceMark rm(thread); - vframeStream st(thread); + BacktraceBuilder bt(backtrace); // Unlike fill_in_stack_trace we do not skip fillInStackTrace or throwable init // methods as preallocated errors aren't created by "java" code. // fill in as much stack trace as possible + typeArrayOop methods = BacktraceBuilder::get_methods(backtrace); int max_chunks = MIN2(methods->length(), (int)MaxJavaStackTraceDepth); int chunk_count = 0; for (;!st.at_end(); st.next()) { - // Add entry and smear the -1 bci to 0 since the array only holds - // unsigned shorts. The later line number lookup would just smear - // the -1 to a 0 even if it could be recorded. - int bci = st.bci(); - if (bci == SynchronizationEntryBCI) bci = 0; - assert(bci == (jushort)bci, "doesn't fit"); - bcis->ushort_at_put(chunk_count, bci); - methods->metadata_at_put(chunk_count, st.method()); - mirrors->obj_at_put(chunk_count, - st.method()->method_holder()->java_mirror()); - + bt.push(st.method(), st.bci(), CHECK); chunk_count++; // Bail-out for deep stacks @@ -1672,7 +1652,6 @@ void java_lang_Throwable::fill_in_stack_trace_of_preallocated_backtrace(Handle t java_lang_Throwable::set_stacktrace(throwable(), java_lang_Throwable::unassigned_stacktrace()); assert(java_lang_Throwable::unassigned_stacktrace() != NULL, "not initialized"); } - } @@ -1691,12 +1670,12 @@ int java_lang_Throwable::get_stack_trace_depth(oop throwable, TRAPS) { chunk = next; } assert(chunk != NULL && chunk->obj_at(trace_next_offset) == NULL, "sanity check"); - // Count element in remaining partial chunk - typeArrayOop methods = typeArrayOop(chunk->obj_at(trace_methods_offset)); - typeArrayOop bcis = typeArrayOop(chunk->obj_at(trace_bcis_offset)); - assert(methods != NULL && bcis != NULL, "sanity check"); - for (int i = 0; i < methods->length(); i++) { - if (methods->metadata_at(i) == NULL) break; + // Count element in remaining partial chunk. NULL value for mirror + // marks the end of the stack trace elements that are saved. + objArrayOop mirrors = BacktraceBuilder::get_mirrors(chunk); + assert(mirrors != NULL, "sanity check"); + for (int i = 0; i < mirrors->length(); i++) { + if (mirrors->obj_at(i) == NULL) break; depth++; } } @@ -1722,25 +1701,28 @@ oop java_lang_Throwable::get_stack_trace_element(oop throwable, int index, TRAPS if (chunk == NULL) { THROW_(vmSymbols::java_lang_IndexOutOfBoundsException(), NULL); } - // Get method,bci from chunk - typeArrayOop methods = typeArrayOop(chunk->obj_at(trace_methods_offset)); - typeArrayOop bcis = typeArrayOop(chunk->obj_at(trace_bcis_offset)); - assert(methods != NULL && bcis != NULL, "sanity check"); - methodHandle method(THREAD, ((Method*)methods->metadata_at(chunk_index))); - int bci = bcis->ushort_at(chunk_index); + // Get method id, bci, version and mirror from chunk + typeArrayOop methods = BacktraceBuilder::get_methods(chunk); + typeArrayOop bcis = BacktraceBuilder::get_bcis(chunk); + objArrayOop mirrors = BacktraceBuilder::get_mirrors(chunk); + + assert(methods != NULL && bcis != NULL && mirrors != NULL, "sanity check"); + + int method = methods->short_at(chunk_index); + int version = version_at(bcis->int_at(chunk_index)); + int bci = bci_at(bcis->int_at(chunk_index)); + Handle mirror(THREAD, mirrors->obj_at(chunk_index)); + // Chunk can be partial full - if (method.is_null()) { + if (mirror.is_null()) { THROW_(vmSymbols::java_lang_IndexOutOfBoundsException(), NULL); } - oop element = java_lang_StackTraceElement::create(method, bci, CHECK_0); + oop element = java_lang_StackTraceElement::create(mirror, method, version, bci, CHECK_0); return element; } -oop java_lang_StackTraceElement::create(methodHandle method, int bci, TRAPS) { - // SystemDictionary::stackTraceElement_klass() will be null for pre-1.4 JDKs - assert(JDK_Version::is_gte_jdk14x_version(), "should only be called in >= 1.4"); - +oop java_lang_StackTraceElement::create(Handle mirror, int method_id, int version, int bci, TRAPS) { // Allocate java.lang.StackTraceElement instance Klass* k = SystemDictionary::StackTraceElement_klass(); assert(k != NULL, "must be loaded in 1.4+"); @@ -1752,37 +1734,39 @@ oop java_lang_StackTraceElement::create(methodHandle method, int bci, TRAPS) { Handle element = ik->allocate_instance_handle(CHECK_0); // Fill in class name ResourceMark rm(THREAD); - const char* str = method->method_holder()->external_name(); + InstanceKlass* holder = InstanceKlass::cast(java_lang_Class::as_Klass(mirror())); + const char* str = holder->external_name(); oop classname = StringTable::intern((char*) str, CHECK_0); java_lang_StackTraceElement::set_declaringClass(element(), classname); + // Fill in method name + Method* method = holder->method_with_idnum(method_id); oop methodname = StringTable::intern(method->name(), CHECK_0); java_lang_StackTraceElement::set_methodName(element(), methodname); - // Fill in source file name - Symbol* source = method->method_holder()->source_file_name(); - if (ShowHiddenFrames && source == NULL) - source = vmSymbols::unknown_class_name(); - oop filename = StringTable::intern(source, CHECK_0); - java_lang_StackTraceElement::set_fileName(element(), filename); - // File in source line number - int line_number; - if (method->is_native()) { - // Negative value different from -1 below, enabling Java code in - // class java.lang.StackTraceElement to distinguish "native" from - // "no LineNumberTable". - line_number = -2; - } else { - // Returns -1 if no LineNumberTable, and otherwise actual line number - line_number = method->line_number_from_bci(bci); - if (line_number == -1 && ShowHiddenFrames) { - line_number = bci + 1000000; - } - } - java_lang_StackTraceElement::set_lineNumber(element(), line_number); + if (!version_matches(method, version)) { + // The method was redefined, accurate line number information isn't available + java_lang_StackTraceElement::set_fileName(element(), NULL); + java_lang_StackTraceElement::set_lineNumber(element(), -1); + } else { + // Fill in source file name and line number. + Symbol* source = holder->source_file_name(); + if (ShowHiddenFrames && source == NULL) + source = vmSymbols::unknown_class_name(); + oop filename = StringTable::intern(source, CHECK_0); + java_lang_StackTraceElement::set_fileName(element(), filename); + + int line_number = get_line_number(method, bci); + java_lang_StackTraceElement::set_lineNumber(element(), line_number); + } return element(); } +oop java_lang_StackTraceElement::create(methodHandle method, int bci, TRAPS) { + Handle mirror (THREAD, method->method_holder()->java_mirror()); + int method_id = method->method_idnum(); + return create(mirror, method_id, method->constants()->version(), bci, THREAD); +} void java_lang_reflect_AccessibleObject::compute_offsets() { Klass* k = SystemDictionary::reflect_AccessibleObject_klass(); diff --git a/hotspot/src/share/vm/classfile/javaClasses.hpp b/hotspot/src/share/vm/classfile/javaClasses.hpp index 5ab16251c10..51ee95da145 100644 --- a/hotspot/src/share/vm/classfile/javaClasses.hpp +++ b/hotspot/src/share/vm/classfile/javaClasses.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, 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 @@ -469,8 +469,7 @@ class java_lang_Throwable: AllStatic { static int static_unassigned_stacktrace_offset; // Printing - static char* print_stack_element_to_buffer(Method* method, int bci); - static void print_to_stream(Handle stream, const char* str); + static char* print_stack_element_to_buffer(Handle mirror, int method, int version, int bci); // StackTrace (programmatic access, new since 1.4) static void clear_stacktrace(oop throwable); // No stack trace available @@ -490,12 +489,9 @@ class java_lang_Throwable: AllStatic { static oop message(oop throwable); static oop message(Handle throwable); static void set_message(oop throwable, oop value); - // Print stack trace stored in exception by call-back to Java - // Note: this is no longer used in Merlin, but we still suppport - // it for compatibility. - static void print_stack_trace(oop throwable, oop print_stream); - static void print_stack_element(Handle stream, Method* method, int bci); - static void print_stack_element(outputStream *st, Method* method, int bci); + static void print_stack_element(outputStream *st, Handle mirror, int method, + int version, int bci); + static void print_stack_element(outputStream *st, methodHandle method, int bci); static void print_stack_usage(Handle stream); // Allocate space for backtrace (created but stack trace not filled in) @@ -1263,7 +1259,8 @@ class java_lang_StackTraceElement: AllStatic { static void set_lineNumber(oop element, int value); // Create an instance of StackTraceElement - static oop create(methodHandle m, int bci, TRAPS); + static oop create(Handle mirror, int method, int version, int bci, TRAPS); + static oop create(methodHandle method, int bci, TRAPS); // Debugging friend class JavaClasses; diff --git a/hotspot/src/share/vm/oops/constantPool.cpp b/hotspot/src/share/vm/oops/constantPool.cpp index ff8472d3d79..770510c7880 100644 --- a/hotspot/src/share/vm/oops/constantPool.cpp +++ b/hotspot/src/share/vm/oops/constantPool.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, 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 @@ -66,7 +66,7 @@ ConstantPool::ConstantPool(Array* tags) { set_pool_holder(NULL); set_flags(0); // only set to non-zero if constant pool is merged by RedefineClasses - set_orig_length(0); + set_version(0); set_lock(new Monitor(Monitor::nonleaf + 2, "A constant pool lock")); // all fields are initialized; needed for GC set_on_stack(false); diff --git a/hotspot/src/share/vm/oops/constantPool.hpp b/hotspot/src/share/vm/oops/constantPool.hpp index 768cd39a65c..3872dfb81e3 100644 --- a/hotspot/src/share/vm/oops/constantPool.hpp +++ b/hotspot/src/share/vm/oops/constantPool.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, 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 @@ -103,8 +103,8 @@ class ConstantPool : public Metadata { union { // set for CDS to restore resolved references int _resolved_reference_length; - // only set to non-zero if constant pool is merged by RedefineClasses - int _orig_length; + // keeps version number for redefined classes (used in backtrace) + int _version; } _saved; Monitor* _lock; @@ -784,8 +784,11 @@ class ConstantPool : public Metadata { static void copy_cp_to_impl(constantPoolHandle from_cp, int start_i, int end_i, constantPoolHandle to_cp, int to_i, TRAPS); static void copy_entry_to(constantPoolHandle from_cp, int from_i, constantPoolHandle to_cp, int to_i, TRAPS); int find_matching_entry(int pattern_i, constantPoolHandle search_cp, TRAPS); - int orig_length() const { return _saved._orig_length; } - void set_orig_length(int orig_length) { _saved._orig_length = orig_length; } + int version() const { return _saved._version; } + void set_version(int version) { _saved._version = version; } + void increment_and_save_version(int version) { + _saved._version = version >= 0 ? version++ : version; // keep overflow + } void set_resolved_reference_length(int length) { _saved._resolved_reference_length = length; } int resolved_reference_length() const { return _saved._resolved_reference_length; } diff --git a/hotspot/src/share/vm/prims/jvm.cpp b/hotspot/src/share/vm/prims/jvm.cpp index 8b7b2583c5f..9b15947a7f1 100644 --- a/hotspot/src/share/vm/prims/jvm.cpp +++ b/hotspot/src/share/vm/prims/jvm.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, 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 @@ -484,15 +484,6 @@ JVM_ENTRY(void, JVM_FillInStackTrace(JNIEnv *env, jobject receiver)) JVM_END -JVM_ENTRY(void, JVM_PrintStackTrace(JNIEnv *env, jobject receiver, jobject printable)) - JVMWrapper("JVM_PrintStackTrace"); - // Note: This is no longer used in Merlin, but we still support it for compatibility. - oop exception = JNIHandles::resolve_non_null(receiver); - oop stream = JNIHandles::resolve_non_null(printable); - java_lang_Throwable::print_stack_trace(exception, stream); -JVM_END - - JVM_ENTRY(jint, JVM_GetStackTraceDepth(JNIEnv *env, jobject throwable)) JVMWrapper("JVM_GetStackTraceDepth"); oop exception = JNIHandles::resolve(throwable); diff --git a/hotspot/src/share/vm/prims/jvm.h b/hotspot/src/share/vm/prims/jvm.h index 899138ede9e..c081f872afa 100644 --- a/hotspot/src/share/vm/prims/jvm.h +++ b/hotspot/src/share/vm/prims/jvm.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, 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 @@ -212,9 +212,6 @@ JVM_IsNaN(jdouble d); JNIEXPORT void JNICALL JVM_FillInStackTrace(JNIEnv *env, jobject throwable); -JNIEXPORT void JNICALL -JVM_PrintStackTrace(JNIEnv *env, jobject throwable, jobject printable); - JNIEXPORT jint JNICALL JVM_GetStackTraceDepth(JNIEnv *env, jobject throwable); diff --git a/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp b/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp index a9d3d5f1e39..7e68f2b1059 100644 --- a/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp +++ b/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2013, 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 @@ -1334,20 +1334,8 @@ jvmtiError VM_RedefineClasses::merge_cp_and_rewrite( return JVMTI_ERROR_INTERNAL; } - int orig_length = old_cp->orig_length(); - if (orig_length == 0) { - // This old_cp is an actual original constant pool. We save - // the original length in the merged constant pool so that - // merge_constant_pools() can be more efficient. If a constant - // pool has a non-zero orig_length() value, then that constant - // pool was created by a merge operation in RedefineClasses. - merge_cp->set_orig_length(old_cp->length()); - } else { - // This old_cp is a merged constant pool from a previous - // RedefineClasses() calls so just copy the orig_length() - // value. - merge_cp->set_orig_length(old_cp->orig_length()); - } + // Update the version number of the constant pool + merge_cp->increment_and_save_version(old_cp->version()); ResourceMark rm(THREAD); _index_map_count = 0; @@ -2417,18 +2405,19 @@ void VM_RedefineClasses::set_new_constant_pool( int scratch_cp_length, TRAPS) { assert(scratch_cp->length() >= scratch_cp_length, "sanity check"); - // scratch_cp is a merged constant pool and has enough space for a - // worst case merge situation. We want to associate the minimum - // sized constant pool with the klass to save space. - constantPoolHandle smaller_cp(THREAD, - ConstantPool::allocate(loader_data, scratch_cp_length, - THREAD)); - // preserve orig_length() value in the smaller copy - int orig_length = scratch_cp->orig_length(); - assert(orig_length != 0, "sanity check"); - smaller_cp->set_orig_length(orig_length); - scratch_cp->copy_cp_to(1, scratch_cp_length - 1, smaller_cp, 1, THREAD); - scratch_cp = smaller_cp; + // scratch_cp is a merged constant pool and has enough space for a + // worst case merge situation. We want to associate the minimum + // sized constant pool with the klass to save space. + constantPoolHandle smaller_cp(THREAD, + ConstantPool::allocate(loader_data, scratch_cp_length, THREAD)); + + // preserve version() value in the smaller copy + int version = scratch_cp->version(); + assert(version != 0, "sanity check"); + smaller_cp->set_version(version); + + scratch_cp->copy_cp_to(1, scratch_cp_length - 1, smaller_cp, 1, THREAD); + scratch_cp = smaller_cp; // attach new constant pool to klass scratch_cp->set_pool_holder(scratch_class()); From 3d5f55b8512d649e68ee685058b9a6d7354c6cd9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20=C3=96hrstr=C3=B6m?= Date: Fri, 18 Jan 2013 00:16:21 +0100 Subject: [PATCH 051/210] 8004658: Add internal smart javac wrapper to solve JEP 139 Reviewed-by: jjg --- langtools/make/build.properties | 16 +- langtools/make/build.xml | 40 +- .../com/sun/tools/sjavac/BuildState.java | 275 +++++ .../com/sun/tools/sjavac/CleanProperties.java | 148 +++ .../com/sun/tools/sjavac/CompileChunk.java | 57 ++ .../sun/tools/sjavac/CompileJavaPackages.java | 344 +++++++ .../sun/tools/sjavac/CompileProperties.java | 221 ++++ .../com/sun/tools/sjavac/CopyFile.java | 116 +++ .../com/sun/tools/sjavac/JavacState.java | 857 ++++++++++++++++ .../classes/com/sun/tools/sjavac/Log.java | 92 ++ .../classes/com/sun/tools/sjavac/Main.java | 969 ++++++++++++++++++ .../classes/com/sun/tools/sjavac/Module.java | 141 +++ .../classes/com/sun/tools/sjavac/Package.java | 307 ++++++ .../sun/tools/sjavac/ProblemException.java | 41 + .../classes/com/sun/tools/sjavac/Source.java | 400 ++++++++ .../com/sun/tools/sjavac/Transformer.java | 99 ++ .../classes/com/sun/tools/sjavac/Util.java | 160 +++ .../sun/tools/sjavac/comp/Dependencies.java | 188 ++++ .../sjavac/comp/JavaCompilerWithDeps.java | 109 ++ .../sun/tools/sjavac/comp/PubapiVisitor.java | 157 +++ .../tools/sjavac/comp/ResolveWithDeps.java | 67 ++ .../tools/sjavac/comp/SmartFileManager.java | 221 ++++ .../tools/sjavac/comp/SmartFileObject.java | 126 +++ .../sun/tools/sjavac/comp/SmartWriter.java | 78 ++ .../sun/tools/sjavac/server/CompilerPool.java | 163 +++ .../tools/sjavac/server/CompilerThread.java | 419 ++++++++ .../sun/tools/sjavac/server/JavacServer.java | 751 ++++++++++++++ .../com/sun/tools/sjavac/server/PortFile.java | 259 +++++ .../com/sun/tools/sjavac/server/SysInfo.java | 45 + langtools/test/tools/sjavac/SJavac.java | 590 +++++++++++ 30 files changed, 7449 insertions(+), 7 deletions(-) create mode 100644 langtools/src/share/classes/com/sun/tools/sjavac/BuildState.java create mode 100644 langtools/src/share/classes/com/sun/tools/sjavac/CleanProperties.java create mode 100644 langtools/src/share/classes/com/sun/tools/sjavac/CompileChunk.java create mode 100644 langtools/src/share/classes/com/sun/tools/sjavac/CompileJavaPackages.java create mode 100644 langtools/src/share/classes/com/sun/tools/sjavac/CompileProperties.java create mode 100644 langtools/src/share/classes/com/sun/tools/sjavac/CopyFile.java create mode 100644 langtools/src/share/classes/com/sun/tools/sjavac/JavacState.java create mode 100644 langtools/src/share/classes/com/sun/tools/sjavac/Log.java create mode 100644 langtools/src/share/classes/com/sun/tools/sjavac/Main.java create mode 100644 langtools/src/share/classes/com/sun/tools/sjavac/Module.java create mode 100644 langtools/src/share/classes/com/sun/tools/sjavac/Package.java create mode 100644 langtools/src/share/classes/com/sun/tools/sjavac/ProblemException.java create mode 100644 langtools/src/share/classes/com/sun/tools/sjavac/Source.java create mode 100644 langtools/src/share/classes/com/sun/tools/sjavac/Transformer.java create mode 100644 langtools/src/share/classes/com/sun/tools/sjavac/Util.java create mode 100644 langtools/src/share/classes/com/sun/tools/sjavac/comp/Dependencies.java create mode 100644 langtools/src/share/classes/com/sun/tools/sjavac/comp/JavaCompilerWithDeps.java create mode 100644 langtools/src/share/classes/com/sun/tools/sjavac/comp/PubapiVisitor.java create mode 100644 langtools/src/share/classes/com/sun/tools/sjavac/comp/ResolveWithDeps.java create mode 100644 langtools/src/share/classes/com/sun/tools/sjavac/comp/SmartFileManager.java create mode 100644 langtools/src/share/classes/com/sun/tools/sjavac/comp/SmartFileObject.java create mode 100644 langtools/src/share/classes/com/sun/tools/sjavac/comp/SmartWriter.java create mode 100644 langtools/src/share/classes/com/sun/tools/sjavac/server/CompilerPool.java create mode 100644 langtools/src/share/classes/com/sun/tools/sjavac/server/CompilerThread.java create mode 100644 langtools/src/share/classes/com/sun/tools/sjavac/server/JavacServer.java create mode 100644 langtools/src/share/classes/com/sun/tools/sjavac/server/PortFile.java create mode 100644 langtools/src/share/classes/com/sun/tools/sjavac/server/SysInfo.java create mode 100644 langtools/test/tools/sjavac/SJavac.java diff --git a/langtools/make/build.properties b/langtools/make/build.properties index 3470a69d868..72ae8793c24 100644 --- a/langtools/make/build.properties +++ b/langtools/make/build.properties @@ -29,18 +29,18 @@ # Override this path as needed, either on the command line or in # one of the standard user build.properties files (see build.xml) -# boot.java.home = /opt/jdk/1.6.0 +# boot.java.home = /opt/jdk/1.7.0 boot.java = ${boot.java.home}/bin/java boot.javac = ${boot.java.home}/bin/javac -boot.javac.source = 6 -boot.javac.target = 6 +boot.javac.source = 7 +boot.javac.target = 7 # This is the JDK used to run the product version of the tools, # for example, for testing. If you're building a complete JDK, specify that. # Override this path as needed, either on the command line or in # one of the standard user build.properties files (see build.xml) -# target.java.home = /opt/jdk/1.7.0 +# target.java.home = /opt/jdk/1.8.0 target.java = ${target.java.home}/bin/java # Version info -- override as needed @@ -161,6 +161,14 @@ javap.tests = \ # +sjavac.includes = \ + com/sun/tools/sjavac/ + +sjavac.tests = \ + tools/sjavac + +# + # The following files require the latest JDK to be available. # The API can be provided by using a suitable boot.java.home # or by setting import.jdk diff --git a/langtools/make/build.xml b/langtools/make/build.xml index be1c357852c..9292ee3f392 100644 --- a/langtools/make/build.xml +++ b/langtools/make/build.xml @@ -241,15 +241,15 @@ - + @@ -656,6 +656,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + * @@ -1486,6 +1665,7 @@ public class Type implements PrimitiveType { R visitForAll(ForAll t, S s); R visitUndetVar(UndetVar t, S s); R visitErrorType(ErrorType t, S s); + R visitAnnotatedType(AnnotatedType t, S s); R visitType(Type t, S s); } } diff --git a/langtools/src/share/classes/com/sun/tools/javac/code/TypeAnnotationPosition.java b/langtools/src/share/classes/com/sun/tools/javac/code/TypeAnnotationPosition.java index c3fba38ff85..32a6ffdc8f4 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/code/TypeAnnotationPosition.java +++ b/langtools/src/share/classes/com/sun/tools/javac/code/TypeAnnotationPosition.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2013, 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 @@ -25,6 +25,8 @@ package com.sun.tools.javac.code; +import java.util.Iterator; + import com.sun.tools.javac.util.*; /** A type annotation position. @@ -34,12 +36,92 @@ import com.sun.tools.javac.util.*; * This code and its internal interfaces are subject to change or * deletion without notice. */ +// Code duplicated in com.sun.tools.classfile.TypeAnnotation.Position public class TypeAnnotationPosition { + public enum TypePathEntryKind { + ARRAY(0), + INNER_TYPE(1), + WILDCARD(2), + TYPE_ARGUMENT(3); + + public final int tag; + + private TypePathEntryKind(int tag) { + this.tag = tag; + } + } + + public static class TypePathEntry { + /** The fixed number of bytes per TypePathEntry. */ + public static final int bytesPerEntry = 2; + + public final TypePathEntryKind tag; + public final int arg; + + public static final TypePathEntry ARRAY = new TypePathEntry(TypePathEntryKind.ARRAY); + public static final TypePathEntry INNER_TYPE = new TypePathEntry(TypePathEntryKind.INNER_TYPE); + public static final TypePathEntry WILDCARD = new TypePathEntry(TypePathEntryKind.WILDCARD); + + private TypePathEntry(TypePathEntryKind tag) { + Assert.check(tag == TypePathEntryKind.ARRAY || + tag == TypePathEntryKind.INNER_TYPE || + tag == TypePathEntryKind.WILDCARD, + "Invalid TypePathEntryKind: " + tag); + this.tag = tag; + this.arg = 0; + } + + public TypePathEntry(TypePathEntryKind tag, int arg) { + Assert.check(tag == TypePathEntryKind.TYPE_ARGUMENT, + "Invalid TypePathEntryKind: " + tag); + this.tag = tag; + this.arg = arg; + } + + public static TypePathEntry fromBinary(int tag, int arg) { + Assert.check(arg == 0 || tag == TypePathEntryKind.TYPE_ARGUMENT.tag, + "Invalid TypePathEntry tag/arg: " + tag + "/" + arg); + switch (tag) { + case 0: + return ARRAY; + case 1: + return INNER_TYPE; + case 2: + return WILDCARD; + case 3: + return new TypePathEntry(TypePathEntryKind.TYPE_ARGUMENT, arg); + default: + Assert.error("Invalid TypePathEntryKind tag: " + tag); + return null; + } + } + + @Override + public String toString() { + return tag.toString() + + (tag == TypePathEntryKind.TYPE_ARGUMENT ? ("(" + arg + ")") : ""); + } + + @Override + public boolean equals(Object other) { + if (! (other instanceof TypePathEntry)) { + return false; + } + TypePathEntry tpe = (TypePathEntry) other; + return this.tag == tpe.tag && this.arg == tpe.arg; + } + + @Override + public int hashCode() { + return this.tag.hashCode() * 17 + this.arg; + } + } + public TargetType type = TargetType.UNKNOWN; // For generic/array types. - public List location = List.nil(); + public List location = List.nil(); // Tree position. public int pos = -1; @@ -59,11 +141,13 @@ public class TypeAnnotationPosition { // For type parameter and method parameter public int parameter_index = Integer.MIN_VALUE; - // For class extends, implements, and throws classes + // For class extends, implements, and throws clauses public int type_index = Integer.MIN_VALUE; - // For wildcards - public TypeAnnotationPosition wildcard_position = null; + // For exception parameters, index into exception table + public int exception_index = Integer.MIN_VALUE; + + public TypeAnnotationPosition() {} @Override public String toString() { @@ -72,27 +156,27 @@ public class TypeAnnotationPosition { sb.append(type); switch (type) { - // type case - case TYPECAST: - case TYPECAST_GENERIC_OR_ARRAY: - // object creation + // type cast + case CAST: + // instanceof case INSTANCEOF: - case INSTANCEOF_GENERIC_OR_ARRAY: - // new expression + // new expression case NEW: - case NEW_GENERIC_OR_ARRAY: - case NEW_TYPE_ARGUMENT: - case NEW_TYPE_ARGUMENT_GENERIC_OR_ARRAY: sb.append(", offset = "); sb.append(offset); break; - // local variable + // local variable case LOCAL_VARIABLE: - case LOCAL_VARIABLE_GENERIC_OR_ARRAY: + // resource variable + case RESOURCE_VARIABLE: + if (lvarOffset == null) { + sb.append(", lvarOffset is null!"); + break; + } sb.append(", {"); for (int i = 0; i < lvarOffset.length; ++i) { if (i != 0) sb.append("; "); - sb.append(", start_pc = "); + sb.append("start_pc = "); sb.append(lvarOffset[i]); sb.append(", length = "); sb.append(lvarLength[i]); @@ -101,73 +185,72 @@ public class TypeAnnotationPosition { } sb.append("}"); break; - // method receiver + // method receiver case METHOD_RECEIVER: // Do nothing break; - // type parameters + // type parameter case CLASS_TYPE_PARAMETER: case METHOD_TYPE_PARAMETER: sb.append(", param_index = "); sb.append(parameter_index); break; - // type parameters bound + // type parameter bound case CLASS_TYPE_PARAMETER_BOUND: - case CLASS_TYPE_PARAMETER_BOUND_GENERIC_OR_ARRAY: case METHOD_TYPE_PARAMETER_BOUND: - case METHOD_TYPE_PARAMETER_BOUND_GENERIC_OR_ARRAY: sb.append(", param_index = "); sb.append(parameter_index); sb.append(", bound_index = "); sb.append(bound_index); break; - // wildcard - case WILDCARD_BOUND: - case WILDCARD_BOUND_GENERIC_OR_ARRAY: - sb.append(", wild_card = "); - sb.append(wildcard_position); - break; - // Class extends and implements clauses + // class extends or implements clause case CLASS_EXTENDS: - case CLASS_EXTENDS_GENERIC_OR_ARRAY: sb.append(", type_index = "); sb.append(type_index); break; - // throws + // throws case THROWS: sb.append(", type_index = "); sb.append(type_index); break; - case CLASS_LITERAL: - case CLASS_LITERAL_GENERIC_OR_ARRAY: - sb.append(", offset = "); - sb.append(offset); + // exception parameter + case EXCEPTION_PARAMETER: + sb.append(", exception_index = "); + sb.append(exception_index); break; - // method parameter: not specified - case METHOD_PARAMETER_GENERIC_OR_ARRAY: + // method parameter + case METHOD_FORMAL_PARAMETER: sb.append(", param_index = "); sb.append(parameter_index); break; - // method type argument: wasn't specified - case METHOD_TYPE_ARGUMENT: - case METHOD_TYPE_ARGUMENT_GENERIC_OR_ARRAY: + // method/constructor/reference type argument + case CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT: + case METHOD_INVOCATION_TYPE_ARGUMENT: + case METHOD_REFERENCE_TYPE_ARGUMENT: sb.append(", offset = "); sb.append(offset); sb.append(", type_index = "); sb.append(type_index); break; - // We don't need to worry abut these - case METHOD_RETURN_GENERIC_OR_ARRAY: - case FIELD_GENERIC_OR_ARRAY: + // We don't need to worry about these + case METHOD_RETURN: + case FIELD: + break; + // lambda formal parameter + case LAMBDA_FORMAL_PARAMETER: + // TODO: also needs an offset? + sb.append(", param_index = "); + sb.append(parameter_index); break; case UNKNOWN: + sb.append(", position UNKNOWN!"); break; default: - // throw new AssertionError("unknown type: " + type); + Assert.error("Unknown target type: " + type); } // Append location data for generics/arrays. - if (type.hasLocation()) { + if (!location.isEmpty()) { sb.append(", location = ("); sb.append(location); sb.append(")"); @@ -186,10 +269,33 @@ public class TypeAnnotationPosition { * @return true if the target has not been optimized away */ public boolean emitToClassfile() { - if (type == TargetType.WILDCARD_BOUND - || type == TargetType.WILDCARD_BOUND_GENERIC_OR_ARRAY) - return wildcard_position.isValidOffset; - else - return !type.isLocal() || isValidOffset; + return !type.isLocal() || isValidOffset; + } + + /** + * Decode the binary representation for a type path and set + * the {@code location} field. + * + * @param list The bytecode representation of the type path. + */ + public static List getTypePathFromBinary(java.util.List list) { + ListBuffer loc = ListBuffer.lb(); + Iterator iter = list.iterator(); + while (iter.hasNext()) { + Integer fst = iter.next(); + Assert.check(iter.hasNext(), "Could not decode type path: " + list); + Integer snd = iter.next(); + loc = loc.append(TypePathEntry.fromBinary(fst, snd)); + } + return loc.toList(); + } + + public static List getBinaryFromTypePath(java.util.List locs) { + ListBuffer loc = ListBuffer.lb(); + for (TypePathEntry tpe : locs) { + loc = loc.append(tpe.tag.tag); + loc = loc.append(tpe.arg); + } + return loc.toList(); } } diff --git a/langtools/src/share/classes/com/sun/tools/javac/code/TypeAnnotations.java b/langtools/src/share/classes/com/sun/tools/javac/code/TypeAnnotations.java new file mode 100644 index 00000000000..b438b2f1e93 --- /dev/null +++ b/langtools/src/share/classes/com/sun/tools/javac/code/TypeAnnotations.java @@ -0,0 +1,1037 @@ +/* + * Copyright (c) 2009, 2013, 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. + */ + +package com.sun.tools.javac.code; + +import javax.lang.model.element.Element; +import javax.lang.model.element.ElementKind; +import javax.lang.model.type.TypeKind; + +import com.sun.tools.javac.code.Attribute; +import com.sun.tools.javac.code.Attribute.TypeCompound; +import com.sun.tools.javac.code.Flags; +import com.sun.tools.javac.code.Kinds; +import com.sun.tools.javac.code.Type.AnnotatedType; +import com.sun.tools.javac.code.Type.ArrayType; +import com.sun.tools.javac.code.Type.CapturedType; +import com.sun.tools.javac.code.Type.ClassType; +import com.sun.tools.javac.code.Type.ErrorType; +import com.sun.tools.javac.code.Type.ForAll; +import com.sun.tools.javac.code.Type.MethodType; +import com.sun.tools.javac.code.Type.PackageType; +import com.sun.tools.javac.code.Type.TypeVar; +import com.sun.tools.javac.code.Type.UndetVar; +import com.sun.tools.javac.code.Type.Visitor; +import com.sun.tools.javac.code.Type.WildcardType; +import com.sun.tools.javac.code.TypeAnnotationPosition.TypePathEntry; +import com.sun.tools.javac.code.TypeAnnotationPosition.TypePathEntryKind; +import com.sun.tools.javac.code.TypeTag; +import com.sun.tools.javac.code.Symbol.VarSymbol; +import com.sun.tools.javac.comp.Annotate.Annotator; +import com.sun.tools.javac.tree.JCTree; +import com.sun.tools.javac.tree.JCTree.JCBlock; +import com.sun.tools.javac.tree.JCTree.JCClassDecl; +import com.sun.tools.javac.tree.JCTree.JCExpression; +import com.sun.tools.javac.tree.JCTree.JCMethodDecl; +import com.sun.tools.javac.tree.JCTree.JCTypeApply; +import com.sun.tools.javac.tree.JCTree.JCVariableDecl; +import com.sun.tools.javac.tree.TreeScanner; +import com.sun.tools.javac.tree.JCTree.*; +import com.sun.tools.javac.util.Assert; +import com.sun.tools.javac.util.List; +import com.sun.tools.javac.util.ListBuffer; +import com.sun.tools.javac.util.Log; +import com.sun.tools.javac.util.Names; + +/** + * Contains operations specific to processing type annotations. + * This class has two functions: + * separate declaration from type annotations and insert the type + * annotations to their types; + * and determine the TypeAnnotationPositions for all type annotations. + */ +public class TypeAnnotations { + // Class cannot be instantiated. + private TypeAnnotations() {} + + /** + * Separate type annotations from declaration annotations and + * determine the correct positions for type annotations. + * This version only visits types in signatures and should be + * called from MemberEnter. + * The method returns the Annotator object that should be added + * to the correct Annotate queue for later processing. + */ + public static Annotator organizeTypeAnnotationsSignatures(final Symtab syms, final Names names, + final Log log, final JCClassDecl tree) { + return new Annotator() { + @Override + public void enterAnnotation() { + new TypeAnnotationPositions(syms, names, log, true).scan(tree); + } + }; + } + + /** + * This version only visits types in bodies, that is, field initializers, + * top-level blocks, and method bodies, and should be called from Attr. + */ + public static void organizeTypeAnnotationsBodies(Symtab syms, Names names, Log log, JCClassDecl tree) { + new TypeAnnotationPositions(syms, names, log, false).scan(tree); + } + + private static class TypeAnnotationPositions extends TreeScanner { + + private enum AnnotationType { DECLARATION, TYPE, BOTH }; + + private final Symtab syms; + private final Names names; + private final Log log; + private final boolean sigOnly; + + private TypeAnnotationPositions(Symtab syms, Names names, Log log, boolean sigOnly) { + this.syms = syms; + this.names = names; + this.log = log; + this.sigOnly = sigOnly; + } + + /* + * When traversing the AST we keep the "frames" of visited + * trees in order to determine the position of annotations. + */ + private ListBuffer frames = ListBuffer.lb(); + + protected void push(JCTree t) { frames = frames.prepend(t); } + protected JCTree pop() { return frames.next(); } + // could this be frames.elems.tail.head? + private JCTree peek2() { return frames.toList().tail.head; } + + @Override + public void scan(JCTree tree) { + push(tree); + super.scan(tree); + pop(); + } + + /** + * Separates type annotations from declaration annotations. + * This step is needed because in certain locations (where declaration + * and type annotations can be mixed, e.g. the type of a field) + * we never build an JCAnnotatedType. This step finds these + * annotations and marks them as if they were part of the type. + */ + private void separateAnnotationsKinds(JCTree typetree, Type type, Symbol sym, + TypeAnnotationPosition pos) { + /* + System.out.printf("separateAnnotationsKinds(typetree: %s, type: %s, symbol: %s, pos: %s%n", + typetree, type, sym, pos); + */ + List annotations = sym.getRawAttributes(); + ListBuffer declAnnos = new ListBuffer(); + ListBuffer typeAnnos = new ListBuffer(); + + for (Attribute.Compound a : annotations) { + switch (annotationType(a, sym)) { + case DECLARATION: + declAnnos.append(a); + break; + case BOTH: { + declAnnos.append(a); + Attribute.TypeCompound ta = toTypeCompound(a, pos); + typeAnnos.append(ta); + break; + } + case TYPE: { + Attribute.TypeCompound ta = toTypeCompound(a, pos); + typeAnnos.append(ta); + break; + } + } + } + + sym.annotations.reset(); + sym.annotations.setDeclarationAttributes(declAnnos.toList()); + + List typeAnnotations = typeAnnos.toList(); + + if (type == null) { + // When type is null, put the type annotations to the symbol. + // This is used for constructor return annotations, for which + // no appropriate type exists. + sym.annotations.appendUniqueTypes(typeAnnotations); + return; + } + + // type is non-null and annotations are added to that type + type = typeWithAnnotations(typetree, type, typeAnnotations, log); + + if (sym.getKind() == ElementKind.METHOD) { + sym.type.asMethodType().restype = type; + } else { + sym.type = type; + } + + sym.annotations.appendUniqueTypes(typeAnnotations); + if (sym.getKind() == ElementKind.PARAMETER && + sym.getQualifiedName().equals(names._this)) { + sym.owner.type.asMethodType().recvtype = type; + // note that the typeAnnotations will also be added to the owner below. + } + if (sym.getKind() == ElementKind.PARAMETER || + sym.getKind() == ElementKind.LOCAL_VARIABLE || + sym.getKind() == ElementKind.RESOURCE_VARIABLE || + sym.getKind() == ElementKind.EXCEPTION_PARAMETER) { + // Make sure all type annotations from the symbol are also + // on the owner. + sym.owner.annotations.appendUniqueTypes(sym.getTypeAnnotationMirrors()); + } + } + + // This method has a similar purpose as + // {@link com.sun.tools.javac.parser.JavacParser.insertAnnotationsToMostInner(JCExpression, List, boolean)} + // We found a type annotation in a declaration annotation position, + // for example, on the return type. + // Such an annotation is _not_ part of an JCAnnotatedType tree and we therefore + // need to set its position explicitly. + // The method returns a copy of type that contains these annotations. + private static Type typeWithAnnotations(final JCTree typetree, final Type type, + final List annotations, Log log) { + // System.out.printf("typeWithAnnotations(typetree: %s, type: %s, annotations: %s)%n", + // typetree, type, annotations); + if (annotations.isEmpty()) { + return type; + } + if (type.hasTag(TypeTag.ARRAY)) { + Type toreturn; + Type.ArrayType tomodify; + Type.ArrayType arType; + { + Type touse = type; + if (type.getKind() == TypeKind.ANNOTATED) { + Type.AnnotatedType atype = (Type.AnnotatedType)type; + toreturn = new Type.AnnotatedType(atype.underlyingType); + ((Type.AnnotatedType)toreturn).typeAnnotations = atype.typeAnnotations; + touse = atype.underlyingType; + arType = (Type.ArrayType) touse; + tomodify = new Type.ArrayType(null, arType.tsym); + ((Type.AnnotatedType)toreturn).underlyingType = tomodify; + } else { + arType = (Type.ArrayType) touse; + tomodify = new Type.ArrayType(null, arType.tsym); + toreturn = tomodify; + } + } + JCArrayTypeTree arTree = arrayTypeTree(typetree); + + ListBuffer depth = ListBuffer.lb(); + depth = depth.append(TypePathEntry.ARRAY); + while (arType.elemtype.hasTag(TypeTag.ARRAY)) { + if (arType.elemtype.getKind() == TypeKind.ANNOTATED) { + Type.AnnotatedType aelemtype = (Type.AnnotatedType) arType.elemtype; + Type.AnnotatedType newAT = new Type.AnnotatedType(aelemtype.underlyingType); + tomodify.elemtype = newAT; + newAT.typeAnnotations = aelemtype.typeAnnotations; + arType = (Type.ArrayType) aelemtype.underlyingType; + tomodify = new Type.ArrayType(null, arType.tsym); + newAT.underlyingType = tomodify; + } else { + arType = (Type.ArrayType) arType.elemtype; + tomodify.elemtype = new Type.ArrayType(null, arType.tsym); + tomodify = (Type.ArrayType) tomodify.elemtype; + } + arTree = arrayTypeTree(arTree.elemtype); + depth = depth.append(TypePathEntry.ARRAY); + } + Type arelemType = typeWithAnnotations(arTree.elemtype, arType.elemtype, annotations, log); + tomodify.elemtype = arelemType; + for (Attribute.TypeCompound a : annotations) { + TypeAnnotationPosition p = a.position; + p.location = p.location.prependList(depth.toList()); + } + return toreturn; + } else if (type.hasTag(TypeTag.TYPEVAR)) { + // Nothing to do for type variables. + return type; + } else { + Type enclTy = type; + Element enclEl = type.asElement(); + JCTree enclTr = typetree; + + while (enclEl != null && + enclEl.getKind() != ElementKind.PACKAGE && + enclTy != null && + enclTy.getKind() != TypeKind.NONE && + enclTy.getKind() != TypeKind.ERROR && + (enclTr.getKind() == JCTree.Kind.MEMBER_SELECT || + enclTr.getKind() == JCTree.Kind.PARAMETERIZED_TYPE || + enclTr.getKind() == JCTree.Kind.ANNOTATED_TYPE)) { + // Iterate also over the type tree, not just the type: the type is already + // completely resolved and we cannot distinguish where the annotation + // belongs for a nested type. + if (enclTr.getKind() == JCTree.Kind.MEMBER_SELECT) { + // only change encl in this case. + enclTy = enclTy.getEnclosingType(); + enclEl = enclEl.getEnclosingElement(); + enclTr = ((JCFieldAccess)enclTr).getExpression(); + } else if (enclTr.getKind() == JCTree.Kind.PARAMETERIZED_TYPE) { + enclTr = ((JCTypeApply)enclTr).getType(); + } else { + // only other option because of while condition + enclTr = ((JCAnnotatedType)enclTr).getUnderlyingType(); + } + } + + /** We are trying to annotate some enclosing type, + * but nothing more exists. + */ + if (enclTy != null && + enclTy.getKind() == TypeKind.NONE && + (enclTr.getKind() == JCTree.Kind.IDENTIFIER || + enclTr.getKind() == JCTree.Kind.MEMBER_SELECT || + enclTr.getKind() == JCTree.Kind.PARAMETERIZED_TYPE || + enclTr.getKind() == JCTree.Kind.ANNOTATED_TYPE)) { + // TODO: also if it's "java. @A lang.Object", that is, + // if it's on a package? + log.error(enclTr.pos(), "cant.annotate.nested.type", enclTr.toString()); + return type; + } + + // At this point we have visited the part of the nested + // type that is written in the source code. + // Now count from here to the actual top-level class to determine + // the correct nesting. + + // The genericLocation for the annotation. + ListBuffer depth = ListBuffer.lb(); + + Type topTy = enclTy; + while (enclEl != null && + enclEl.getKind() != ElementKind.PACKAGE && + topTy != null && + topTy.getKind() != TypeKind.NONE && + topTy.getKind() != TypeKind.ERROR) { + topTy = topTy.getEnclosingType(); + enclEl = enclEl.getEnclosingElement(); + + if (topTy != null && topTy.getKind() != TypeKind.NONE) { + // Only count enclosing types. + depth = depth.append(TypePathEntry.INNER_TYPE); + } + } + + if (depth.nonEmpty()) { + // Only need to change the annotation positions + // if they are on an enclosed type. + for (Attribute.TypeCompound a : annotations) { + TypeAnnotationPosition p = a.position; + p.location = p.location.appendList(depth.toList()); + } + } + + Type ret = typeWithAnnotations(type, enclTy, annotations); + return ret; + } + } + + private static JCArrayTypeTree arrayTypeTree(JCTree typetree) { + if (typetree.getKind() == JCTree.Kind.ARRAY_TYPE) { + return (JCArrayTypeTree) typetree; + } else if (typetree.getKind() == JCTree.Kind.ANNOTATED_TYPE) { + return (JCArrayTypeTree) ((JCAnnotatedType)typetree).underlyingType; + } else { + Assert.error("Could not determine array type from type tree: " + typetree); + return null; + } + } + + /** Return a copy of the first type that only differs by + * inserting the annotations to the left-most/inner-most type + * or the type given by stopAt. + * + * We need the stopAt parameter to know where on a type to + * put the annotations. + * If we have nested classes Outer > Middle > Inner, and we + * have the source type "@A Middle.Inner", we will invoke + * this method with type = Outer.Middle.Inner, + * stopAt = Middle.Inner, and annotations = @A. + * + * @param type The type to copy. + * @param stopAt The type to stop at. + * @param annotations The annotations to insert. + * @return A copy of type that contains the annotations. + */ + private static Type typeWithAnnotations(final Type type, + final Type stopAt, + final List annotations) { + Visitor> visitor = + new Type.Visitor>() { + @Override + public Type visitClassType(ClassType t, List s) { + // assert that t.constValue() == null? + if (t == stopAt || + t.getEnclosingType() == Type.noType) { + return new AnnotatedType(s, t); + } else { + ClassType ret = new ClassType(t.getEnclosingType().accept(this, s), + t.typarams_field, t.tsym); + ret.all_interfaces_field = t.all_interfaces_field; + ret.allparams_field = t.allparams_field; + ret.interfaces_field = t.interfaces_field; + ret.rank_field = t.rank_field; + ret.supertype_field = t.supertype_field; + return ret; + } + } + + @Override + public Type visitAnnotatedType(AnnotatedType t, List s) { + return new AnnotatedType(t.typeAnnotations, t.underlyingType.accept(this, s)); + } + + @Override + public Type visitWildcardType(WildcardType t, List s) { + return new AnnotatedType(s, t); + } + + @Override + public Type visitArrayType(ArrayType t, List s) { + ArrayType ret = new ArrayType(t.elemtype.accept(this, s), t.tsym); + return ret; + } + + @Override + public Type visitMethodType(MethodType t, List s) { + // Impossible? + return t; + } + + @Override + public Type visitPackageType(PackageType t, List s) { + // Impossible? + return t; + } + + @Override + public Type visitTypeVar(TypeVar t, List s) { + return new AnnotatedType(s, t); + } + + @Override + public Type visitCapturedType(CapturedType t, List s) { + return new AnnotatedType(s, t); + } + + @Override + public Type visitForAll(ForAll t, List s) { + // Impossible? + return t; + } + + @Override + public Type visitUndetVar(UndetVar t, List s) { + // Impossible? + return t; + } + + @Override + public Type visitErrorType(ErrorType t, List s) { + return new AnnotatedType(s, t); + } + + @Override + public Type visitType(Type t, List s) { + // Error? + return t; + } + }; + + return type.accept(visitor, annotations); + } + + private static Attribute.TypeCompound toTypeCompound(Attribute.Compound a, TypeAnnotationPosition p) { + // It is safe to alias the position. + return new Attribute.TypeCompound(a, p); + } + + private AnnotationType annotationType(Attribute.Compound a, Symbol s) { + Attribute.Compound atTarget = + a.type.tsym.attribute(syms.annotationTargetType.tsym); + if (atTarget == null) { + return inferTargetMetaInfo(a, s); + } + Attribute atValue = atTarget.member(names.value); + if (!(atValue instanceof Attribute.Array)) { + Assert.error("annotationType(): bad @Target argument " + atValue + + " (" + atValue.getClass() + ")"); + return AnnotationType.DECLARATION; // error recovery + } + Attribute.Array arr = (Attribute.Array) atValue; + boolean isDecl = false, isType = false; + for (Attribute app : arr.values) { + if (!(app instanceof Attribute.Enum)) { + Assert.error("annotationType(): unrecognized Attribute kind " + app + + " (" + app.getClass() + ")"); + isDecl = true; + continue; + } + Attribute.Enum e = (Attribute.Enum) app; + if (e.value.name == names.TYPE) { + if (s.kind == Kinds.TYP) + isDecl = true; + } else if (e.value.name == names.FIELD) { + if (s.kind == Kinds.VAR && + s.owner.kind != Kinds.MTH) + isDecl = true; + } else if (e.value.name == names.METHOD) { + if (s.kind == Kinds.MTH && + !s.isConstructor()) + isDecl = true; + } else if (e.value.name == names.PARAMETER) { + if (s.kind == Kinds.VAR && + s.owner.kind == Kinds.MTH && + (s.flags() & Flags.PARAMETER) != 0) + isDecl = true; + } else if (e.value.name == names.CONSTRUCTOR) { + if (s.kind == Kinds.MTH && + s.isConstructor()) + isDecl = true; + } else if (e.value.name == names.LOCAL_VARIABLE) { + if (s.kind == Kinds.VAR && + s.owner.kind == Kinds.MTH && + (s.flags() & Flags.PARAMETER) == 0) + isDecl = true; + } else if (e.value.name == names.ANNOTATION_TYPE) { + if (s.kind == Kinds.TYP && + (s.flags() & Flags.ANNOTATION) != 0) + isDecl = true; + } else if (e.value.name == names.PACKAGE) { + if (s.kind == Kinds.PCK) + isDecl = true; + } else if (e.value.name == names.TYPE_USE) { + if (s.kind == Kinds.TYP || + s.kind == Kinds.VAR || + (s.kind == Kinds.MTH && !s.isConstructor() && + !s.type.getReturnType().hasTag(TypeTag.VOID)) || + (s.kind == Kinds.MTH && s.isConstructor())) + isType = true; + } else if (e.value.name == names.TYPE_PARAMETER) { + /* Irrelevant in this case */ + // TYPE_PARAMETER doesn't aid in distinguishing between + // Type annotations and declaration annotations on an + // Element + } else { + Assert.error("annotationType(): unrecognized Attribute name " + e.value.name + + " (" + e.value.name.getClass() + ")"); + isDecl = true; + } + } + if (isDecl && isType) { + return AnnotationType.BOTH; + } else if (isType) { + return AnnotationType.TYPE; + } else { + return AnnotationType.DECLARATION; + } + } + + /** Infer the target annotation kind, if none is give. + * We only infer declaration annotations. + */ + private static AnnotationType inferTargetMetaInfo(Attribute.Compound a, Symbol s) { + return AnnotationType.DECLARATION; + } + + + /* This is the beginning of the second part of organizing + * type annotations: determine the type annotation positions. + */ + + private void resolveFrame(JCTree tree, JCTree frame, + List path, TypeAnnotationPosition p) { + /* + System.out.println("Resolving tree: " + tree + " kind: " + tree.getKind()); + System.out.println(" Framing tree: " + frame + " kind: " + frame.getKind()); + */ + switch (frame.getKind()) { + case TYPE_CAST: + p.type = TargetType.CAST; + p.pos = frame.pos; + return; + + case INSTANCE_OF: + p.type = TargetType.INSTANCEOF; + p.pos = frame.pos; + return; + + case NEW_CLASS: + JCNewClass frameNewClass = (JCNewClass)frame; + if (frameNewClass.typeargs.contains(tree)) { + p.type = TargetType.CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT; + p.type_index = frameNewClass.typeargs.indexOf(tree); + } else { + p.type = TargetType.NEW; + } + p.pos = frame.pos; + return; + + case NEW_ARRAY: + p.type = TargetType.NEW; + p.pos = frame.pos; + return; + + case ANNOTATION_TYPE: + case CLASS: + case ENUM: + case INTERFACE: + p.pos = frame.pos; + if (((JCClassDecl)frame).extending == tree) { + p.type = TargetType.CLASS_EXTENDS; + p.type_index = -1; + } else if (((JCClassDecl)frame).implementing.contains(tree)) { + p.type = TargetType.CLASS_EXTENDS; + p.type_index = ((JCClassDecl)frame).implementing.indexOf(tree); + } else if (((JCClassDecl)frame).typarams.contains(tree)) { + p.type = TargetType.CLASS_TYPE_PARAMETER; + p.parameter_index = ((JCClassDecl)frame).typarams.indexOf(tree); + } else { + Assert.error("Could not determine position of tree " + tree + + " within frame " + frame); + } + return; + + case METHOD: { + JCMethodDecl frameMethod = (JCMethodDecl) frame; + p.pos = frame.pos; + if (frameMethod.thrown.contains(tree)) { + p.type = TargetType.THROWS; + p.type_index = frameMethod.thrown.indexOf(tree); + } else if (frameMethod.restype == tree) { + p.type = TargetType.METHOD_RETURN; + } else if (frameMethod.typarams.contains(tree)) { + p.type = TargetType.METHOD_TYPE_PARAMETER; + p.parameter_index = frameMethod.typarams.indexOf(tree); + } else { + Assert.error("Could not determine position of tree " + tree + + " within frame " + frame); + } + return; + } + + case PARAMETERIZED_TYPE: { + if (((JCTypeApply)frame).clazz == tree) { + // generic: RAW; noop + } else if (((JCTypeApply)frame).arguments.contains(tree)) { + JCTypeApply taframe = (JCTypeApply) frame; + int arg = taframe.arguments.indexOf(tree); + p.location = p.location.prepend(new TypePathEntry(TypePathEntryKind.TYPE_ARGUMENT, arg)); + + locateNestedTypes(taframe.type, p); + } else { + Assert.error("Could not determine type argument position of tree " + tree + + " within frame " + frame); + } + + List newPath = path.tail; + resolveFrame(newPath.head, newPath.tail.head, newPath, p); + return; + } + + case ARRAY_TYPE: { + ListBuffer index = ListBuffer.lb(); + index = index.append(TypePathEntry.ARRAY); + List newPath = path.tail; + while (true) { + JCTree npHead = newPath.tail.head; + if (npHead.hasTag(JCTree.Tag.TYPEARRAY)) { + newPath = newPath.tail; + index = index.append(TypePathEntry.ARRAY); + } else if (npHead.hasTag(JCTree.Tag.ANNOTATED_TYPE)) { + newPath = newPath.tail; + } else { + break; + } + } + p.location = p.location.prependList(index.toList()); + resolveFrame(newPath.head, newPath.tail.head, newPath, p); + return; + } + + case TYPE_PARAMETER: + if (path.tail.tail.head.hasTag(JCTree.Tag.CLASSDEF)) { + JCClassDecl clazz = (JCClassDecl)path.tail.tail.head; + p.type = TargetType.CLASS_TYPE_PARAMETER_BOUND; + p.parameter_index = clazz.typarams.indexOf(path.tail.head); + p.bound_index = ((JCTypeParameter)frame).bounds.indexOf(tree); + if (((JCTypeParameter)frame).bounds.get(0).type.isInterface()) { + // Account for an implicit Object as bound 0 + p.bound_index += 1; + } + } else if (path.tail.tail.head.hasTag(JCTree.Tag.METHODDEF)) { + JCMethodDecl method = (JCMethodDecl)path.tail.tail.head; + p.type = TargetType.METHOD_TYPE_PARAMETER_BOUND; + p.parameter_index = method.typarams.indexOf(path.tail.head); + p.bound_index = ((JCTypeParameter)frame).bounds.indexOf(tree); + if (((JCTypeParameter)frame).bounds.get(0).type.isInterface()) { + // Account for an implicit Object as bound 0 + p.bound_index += 1; + } + } else { + Assert.error("Could not determine position of tree " + tree + + " within frame " + frame); + } + p.pos = frame.pos; + return; + + case VARIABLE: + VarSymbol v = ((JCVariableDecl)frame).sym; + p.pos = frame.pos; + switch (v.getKind()) { + case LOCAL_VARIABLE: + p.type = TargetType.LOCAL_VARIABLE; + break; + case FIELD: + p.type = TargetType.FIELD; + break; + case PARAMETER: + if (v.getQualifiedName().equals(names._this)) { + // TODO: Intro a separate ElementKind? + p.type = TargetType.METHOD_RECEIVER; + } else { + p.type = TargetType.METHOD_FORMAL_PARAMETER; + p.parameter_index = methodParamIndex(path, frame); + } + break; + case EXCEPTION_PARAMETER: + p.type = TargetType.EXCEPTION_PARAMETER; + break; + case RESOURCE_VARIABLE: + p.type = TargetType.RESOURCE_VARIABLE; + break; + default: + Assert.error("Found unexpected type annotation for variable: " + v + " with kind: " + v.getKind()); + } + return; + + case ANNOTATED_TYPE: { + if (frame == tree) { + // This is only true for the first annotated type we see. + // For any other annotated types along the path, we do + // not care about inner types. + JCAnnotatedType atypetree = (JCAnnotatedType) frame; + final Type utype = atypetree.underlyingType.type; + Symbol tsym = utype.tsym; + if (tsym.getKind().equals(ElementKind.TYPE_PARAMETER) || + utype.getKind().equals(TypeKind.WILDCARD) || + utype.getKind().equals(TypeKind.ARRAY)) { + // Type parameters, wildcards, and arrays have the declaring + // class/method as enclosing elements. + // There is actually nothing to do for them. + } else { + locateNestedTypes(utype, p); + } + } + List newPath = path.tail; + resolveFrame(newPath.head, newPath.tail.head, newPath, p); + return; + } + + case UNION_TYPE: { + // TODO: can we store any information here to help in + // determining the final position? + List newPath = path.tail; + resolveFrame(newPath.head, newPath.tail.head, newPath, p); + return; + } + + case METHOD_INVOCATION: { + JCMethodInvocation invocation = (JCMethodInvocation)frame; + if (!invocation.typeargs.contains(tree)) { + Assert.error("{" + tree + "} is not an argument in the invocation: " + invocation); + } + p.type = TargetType.METHOD_INVOCATION_TYPE_ARGUMENT; + p.pos = invocation.pos; + p.type_index = invocation.typeargs.indexOf(tree); + return; + } + + case EXTENDS_WILDCARD: + case SUPER_WILDCARD: { + // Annotations in wildcard bounds + p.location = p.location.prepend(TypePathEntry.WILDCARD); + List newPath = path.tail; + resolveFrame(newPath.head, newPath.tail.head, newPath, p); + return; + } + + case MEMBER_SELECT: { + List newPath = path.tail; + resolveFrame(newPath.head, newPath.tail.head, newPath, p); + return; + } + + default: + Assert.error("Unresolved frame: " + frame + " of kind: " + frame.getKind() + + "\n Looking for tree: " + tree); + return; + } + } + + private static void locateNestedTypes(Type type, TypeAnnotationPosition p) { + // The number of "steps" to get from the full type to the + // left-most outer type. + ListBuffer depth = ListBuffer.lb(); + + Type encl = type.getEnclosingType(); + while (encl != null && + encl.getKind() != TypeKind.NONE && + encl.getKind() != TypeKind.ERROR) { + depth = depth.append(TypePathEntry.INNER_TYPE); + encl = encl.getEnclosingType(); + } + if (depth.nonEmpty()) { + p.location = p.location.prependList(depth.toList()); + } + } + + private static int methodParamIndex(List path, JCTree param) { + List curr = path; + while (curr.head.getTag() != Tag.METHODDEF) { + curr = curr.tail; + } + JCMethodDecl method = (JCMethodDecl)curr.head; + return method.params.indexOf(param); + } + + // Each class (including enclosed inner classes) is visited separately. + // This flag is used to prevent from visiting inner classes. + private boolean isInClass = false; + + @Override + public void visitClassDef(JCClassDecl tree) { + if (isInClass) + return; + isInClass = true; + if (sigOnly) { + scan(tree.mods); + scan(tree.typarams); + scan(tree.extending); + scan(tree.implementing); + } + scan(tree.defs); + } + + /** + * Resolve declaration vs. type annotations in methods and + * then determine the positions. + */ + @Override + public void visitMethodDef(final JCMethodDecl tree) { + if (tree.sym == null) { + // Something most be wrong, e.g. a class not found. + // Quietly ignore. (See test FailOver15.java) + return; + } + if (sigOnly) { + { + TypeAnnotationPosition pos = new TypeAnnotationPosition(); + pos.type = TargetType.METHOD_RETURN; + if (tree.sym.isConstructor()) { + pos.pos = tree.pos; + // Use null to mark that the annotations go with the symbol. + separateAnnotationsKinds(tree, null, tree.sym, pos); + } else { + pos.pos = tree.restype.pos; + separateAnnotationsKinds(tree.restype, tree.sym.type.getReturnType(), + tree.sym, pos); + } + } + if (tree.recvparam != null && tree.recvparam.sym != null) { + // TODO: make sure there are no declaration annotations. + TypeAnnotationPosition pos = new TypeAnnotationPosition(); + pos.type = TargetType.METHOD_RECEIVER; + pos.pos = tree.recvparam.vartype.pos; + separateAnnotationsKinds(tree.recvparam.vartype, tree.recvparam.sym.type, + tree.recvparam.sym, pos); + } + int i = 0; + for (JCVariableDecl param : tree.params) { + TypeAnnotationPosition pos = new TypeAnnotationPosition(); + pos.type = TargetType.METHOD_FORMAL_PARAMETER; + pos.parameter_index = i; + pos.pos = param.vartype.pos; + separateAnnotationsKinds(param.vartype, param.sym.type, param.sym, pos); + ++i; + } + } + + push(tree); + // super.visitMethodDef(tree); + if (sigOnly) { + scan(tree.mods); + scan(tree.restype); + scan(tree.typarams); + scan(tree.recvparam); + scan(tree.params); + scan(tree.thrown); + } else { + scan(tree.defaultValue); + scan(tree.body); + } + pop(); + } + + /** + * Resolve declaration vs. type annotations in variable declarations and + * then determine the positions. + */ + @Override + public void visitVarDef(final JCVariableDecl tree) { + if (tree.sym == null) { + // Something is wrong already. Quietly ignore. + } else if (tree.sym.getKind() == ElementKind.FIELD) { + if (sigOnly) { + TypeAnnotationPosition pos = new TypeAnnotationPosition(); + pos.type = TargetType.FIELD; + pos.pos = tree.pos; + separateAnnotationsKinds(tree.vartype, tree.sym.type, tree.sym, pos); + } + } else if (tree.sym.getKind() == ElementKind.LOCAL_VARIABLE) { + TypeAnnotationPosition pos = new TypeAnnotationPosition(); + pos.type = TargetType.LOCAL_VARIABLE; + pos.pos = tree.pos; + separateAnnotationsKinds(tree.vartype, tree.sym.type, tree.sym, pos); + } else if (tree.sym.getKind() == ElementKind.EXCEPTION_PARAMETER) { + // System.out.println("Found exception param: " + tree); + TypeAnnotationPosition pos = new TypeAnnotationPosition(); + pos.type = TargetType.EXCEPTION_PARAMETER; + pos.pos = tree.pos; + separateAnnotationsKinds(tree.vartype, tree.sym.type, tree.sym, pos); + } else if (tree.sym.getKind() == ElementKind.RESOURCE_VARIABLE) { + TypeAnnotationPosition pos = new TypeAnnotationPosition(); + pos.type = TargetType.RESOURCE_VARIABLE; + pos.pos = tree.pos; + separateAnnotationsKinds(tree.vartype, tree.sym.type, tree.sym, pos); + } else { + // There is nothing else in a variable declaration that needs separation. + // System.out.println("We found a: " + tree); + } + + push(tree); + // super.visitVarDef(tree); + scan(tree.mods); + scan(tree.vartype); + if (!sigOnly) { + scan(tree.init); + } + pop(); + } + + @Override + public void visitBlock(JCBlock tree) { + // Do not descend into top-level blocks when only interested + // in the signature. + if (!sigOnly) { + scan(tree.stats); + } + } + + @Override + public void visitAnnotatedType(JCAnnotatedType tree) { + push(tree); + findPosition(tree, tree, tree.annotations); + pop(); + super.visitAnnotatedType(tree); + } + + @Override + public void visitTypeParameter(JCTypeParameter tree) { + findPosition(tree, peek2(), tree.annotations); + super.visitTypeParameter(tree); + } + + @Override + public void visitNewArray(JCNewArray tree) { + findPosition(tree, tree, tree.annotations); + int dimAnnosCount = tree.dimAnnotations.size(); + ListBuffer depth = ListBuffer.lb(); + + // handle annotations associated with dimensions + for (int i = 0; i < dimAnnosCount; ++i) { + TypeAnnotationPosition p = new TypeAnnotationPosition(); + p.pos = tree.pos; + p.type = TargetType.NEW; + if (i != 0) { + depth = depth.append(TypePathEntry.ARRAY); + p.location = p.location.appendList(depth.toList()); + } + + setTypeAnnotationPos(tree.dimAnnotations.get(i), p); + } + + // handle "free" annotations + // int i = dimAnnosCount == 0 ? 0 : dimAnnosCount - 1; + // TODO: is depth.size == i here? + JCExpression elemType = tree.elemtype; + while (elemType != null) { + if (elemType.hasTag(JCTree.Tag.ANNOTATED_TYPE)) { + JCAnnotatedType at = (JCAnnotatedType)elemType; + TypeAnnotationPosition p = new TypeAnnotationPosition(); + p.type = TargetType.NEW; + p.pos = tree.pos; + p.location = p.location.appendList(depth.toList()); + setTypeAnnotationPos(at.annotations, p); + elemType = at.underlyingType; + } else if (elemType.hasTag(JCTree.Tag.TYPEARRAY)) { + depth = depth.append(TypePathEntry.ARRAY); + elemType = ((JCArrayTypeTree)elemType).elemtype; + } else { + break; + } + } + scan(tree.elems); + } + + private void findPosition(JCTree tree, JCTree frame, List annotations) { + if (!annotations.isEmpty()) { + /* + System.out.println("Finding pos for: " + annotations); + System.out.println(" tree: " + tree); + System.out.println(" frame: " + frame); + */ + TypeAnnotationPosition p = new TypeAnnotationPosition(); + resolveFrame(tree, frame, frames.toList(), p); + setTypeAnnotationPos(annotations, p); + } + } + + private static void setTypeAnnotationPos(List annotations, + TypeAnnotationPosition position) { + for (JCAnnotation anno : annotations) { + ((Attribute.TypeCompound) anno.attribute).position = position; + } + } + } +} diff --git a/langtools/src/share/classes/com/sun/tools/javac/code/Types.java b/langtools/src/share/classes/com/sun/tools/javac/code/Types.java index 23a25738e2d..f7fa66625ef 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/code/Types.java +++ b/langtools/src/share/classes/com/sun/tools/javac/code/Types.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2013, 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 @@ -34,13 +34,14 @@ import java.util.Map; import java.util.Set; import java.util.WeakHashMap; +import javax.lang.model.type.TypeKind; + import com.sun.tools.javac.code.Attribute.RetentionPolicy; import com.sun.tools.javac.code.Lint.LintCategory; import com.sun.tools.javac.code.Type.UndetVar.InferenceBound; import com.sun.tools.javac.comp.Check; import com.sun.tools.javac.jvm.ClassReader; import com.sun.tools.javac.util.*; -import com.sun.tools.javac.util.List; import static com.sun.tools.javac.code.BoundKind.*; import static com.sun.tools.javac.code.Flags.*; import static com.sun.tools.javac.code.Scope.*; @@ -684,6 +685,8 @@ public class Types { //where private boolean isSubtypeUncheckedInternal(Type t, Type s, Warner warn) { if (t.hasTag(ARRAY) && s.hasTag(ARRAY)) { + t = t.unannotatedType(); + s = s.unannotatedType(); if (((ArrayType)t).elemtype.isPrimitive()) { return isSameType(elemtype(t), elemtype(s)); } else { @@ -709,7 +712,10 @@ public class Types { } private void checkUnsafeVarargsConversion(Type t, Type s, Warner warn) { - if (t.tag != ARRAY || isReifiable(t)) return; + if (t.tag != ARRAY || isReifiable(t)) + return; + t = t.unannotatedType(); + s = s.unannotatedType(); ArrayType from = (ArrayType)t; boolean shouldWarn = false; switch (s.tag) { @@ -739,6 +745,12 @@ public class Types { return isSubtype(t, s, false); } public boolean isSubtype(Type t, Type s, boolean capture) { + if (t == s) + return true; + + t = t.unannotatedType(); + s = s.unannotatedType(); + if (t == s) return true; @@ -1683,6 +1695,7 @@ public class Types { case WILDCARD: return elemtype(upperBound(t)); case ARRAY: + t = t.unannotatedType(); return ((ArrayType)t).elemtype; case FORALL: return elemtype(((ForAll)t).qtype); @@ -2011,6 +2024,11 @@ public class Types { public Type visitErrorType(ErrorType t, Boolean recurse) { return t; } + + @Override + public Type visitAnnotatedType(AnnotatedType t, Boolean recurse) { + return new AnnotatedType(t.typeAnnotations, erasure(t.underlyingType, recurse)); + } }; private Mapping erasureFun = new Mapping ("erasure") { @@ -2953,6 +2971,7 @@ public class Types { * graph. Undefined for all but reference types. */ public int rank(Type t) { + t = t.unannotatedType(); switch(t.tag) { case CLASS: { ClassType cls = (ClassType)t; @@ -3654,6 +3673,7 @@ public class Types { t = subst(type1, t.tsym.type.getTypeArguments(), t.getTypeArguments()); } } + t = t.unannotatedType(); ClassType cls = (ClassType)t; if (cls.isRaw() || !cls.isParameterized()) return cls; @@ -4172,6 +4192,8 @@ public class Types { public R visitForAll(ForAll t, S s) { return visitType(t, s); } public R visitUndetVar(UndetVar t, S s) { return visitType(t, s); } public R visitErrorType(ErrorType t, S s) { return visitType(t, s); } + // Pretend annotations don't exist + public R visitAnnotatedType(AnnotatedType t, S s) { return visit(t.underlyingType, s); } } /** diff --git a/langtools/src/share/classes/com/sun/tools/javac/comp/Annotate.java b/langtools/src/share/classes/com/sun/tools/javac/comp/Annotate.java index a2cd3851742..678d2c2bb6a 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/comp/Annotate.java +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Annotate.java @@ -26,6 +26,7 @@ package com.sun.tools.javac.comp; import java.util.Map; + import com.sun.tools.javac.util.*; import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; import com.sun.tools.javac.code.*; @@ -87,20 +88,30 @@ public class Annotate { private int enterCount = 0; ListBuffer q = new ListBuffer(); + ListBuffer typesQ = new ListBuffer(); ListBuffer repeatedQ = new ListBuffer(); - - public void normal(Annotator a) { - q.append(a); - } + ListBuffer afterRepeatedQ = new ListBuffer(); public void earlier(Annotator a) { q.prepend(a); } + public void normal(Annotator a) { + q.append(a); + } + + public void typeAnnotation(Annotator a) { + typesQ.append(a); + } + public void repeated(Annotator a) { repeatedQ.append(a); } + public void afterRepeated(Annotator a) { + afterRepeatedQ.append(a); + } + /** Called when the Enter phase starts. */ public void enterStart() { enterCount++; @@ -116,12 +127,18 @@ public class Annotate { if (enterCount != 0) return; enterCount++; try { - while (q.nonEmpty()) + while (q.nonEmpty()) { q.next().enterAnnotation(); - + } + while (typesQ.nonEmpty()) { + typesQ.next().enterAnnotation(); + } while (repeatedQ.nonEmpty()) { repeatedQ.next().enterAnnotation(); } + while (afterRepeatedQ.nonEmpty()) { + afterRepeatedQ.next().enterAnnotation(); + } } finally { enterCount--; } @@ -141,16 +158,18 @@ public class Annotate { * This context contains all the information needed to synthesize new * annotations trees by the completer for repeating annotations. */ - public class AnnotateRepeatedContext { + public class AnnotateRepeatedContext { public final Env env; - public final Map> annotated; - public final Map pos; + public final Map> annotated; + public final Map pos; public final Log log; + public final boolean isTypeCompound; public AnnotateRepeatedContext(Env env, - Map> annotated, - Map pos, - Log log) { + Map> annotated, + Map pos, + Log log, + boolean isTypeCompound) { Assert.checkNonNull(env); Assert.checkNonNull(annotated); Assert.checkNonNull(pos); @@ -160,6 +179,7 @@ public class Annotate { this.annotated = annotated; this.pos = pos; this.log = log; + this.isTypeCompound = isTypeCompound; } /** @@ -170,7 +190,7 @@ public class Annotate { * @param repeatingAnnotations a List of repeating annotations * @return a new Attribute.Compound that is the container for the repeatingAnnotations */ - public Attribute.Compound processRepeatedAnnotations(List repeatingAnnotations, Symbol sym) { + public T processRepeatedAnnotations(List repeatingAnnotations, Symbol sym) { return Annotate.this.processRepeatedAnnotations(repeatingAnnotations, this, sym); } @@ -246,7 +266,12 @@ public class Annotate { ((MethodSymbol)method, value)); t.type = result; } - return new Attribute.Compound(a.type, buf.toList()); + // TODO: this should be a TypeCompound if "a" is a JCTypeAnnotation. + // However, how do we find the correct position? + Attribute.Compound ac = new Attribute.Compound(a.type, buf.toList()); + // TODO: is this something we want? Who would use it? + // a.attribute = ac; + return ac; } Attribute enterAttributeValue(Type expected, @@ -329,6 +354,15 @@ public class Annotate { return new Attribute.Error(attr.attribExpr(tree, env, expected)); } + Attribute.TypeCompound enterTypeAnnotation(JCAnnotation a, + Type expected, + Env env) { + Attribute.Compound c = enterAnnotation(a, expected, env); + Attribute.TypeCompound tc = new Attribute.TypeCompound(c.type, c.values, new TypeAnnotationPosition()); + a.attribute = tc; + return tc; + } + /* ********************************* * Support for repeating annotations ***********************************/ @@ -337,10 +371,10 @@ public class Annotate { * synthesized container annotation or null IFF all repeating * annotation are invalid. This method reports errors/warnings. */ - private Attribute.Compound processRepeatedAnnotations(List annotations, - AnnotateRepeatedContext ctx, - Symbol on) { - Attribute.Compound firstOccurrence = annotations.head; + private T processRepeatedAnnotations(List annotations, + AnnotateRepeatedContext ctx, + Symbol on) { + T firstOccurrence = annotations.head; List repeated = List.nil(); Type origAnnoType = null; Type arrayOfOrigAnnoType = null; @@ -350,16 +384,16 @@ public class Annotate { Assert.check(!annotations.isEmpty() && !annotations.tail.isEmpty()); // i.e. size() > 1 - for (List al = annotations; + for (List al = annotations; !al.isEmpty(); al = al.tail) { - Attribute.Compound currentAnno = al.head; + T currentAnno = al.head; origAnnoType = currentAnno.type; if (arrayOfOrigAnnoType == null) { arrayOfOrigAnnoType = types.makeArrayType(origAnnoType); -} + } Type currentContainerType = getContainingType(currentAnno, ctx.pos.get(currentAnno)); if (currentContainerType == null) { @@ -383,25 +417,46 @@ public class Annotate { if (!repeated.isEmpty()) { repeated = repeated.reverse(); - JCAnnotation annoTree; TreeMaker m = make.at(ctx.pos.get(firstOccurrence)); Pair p = new Pair(containerValueSymbol, new Attribute.Array(arrayOfOrigAnnoType, repeated)); - annoTree = m.Annotation(new Attribute.Compound(targetContainerType, - List.of(p))); + if (ctx.isTypeCompound) { + /* TODO: the following code would be cleaner: + Attribute.TypeCompound at = new Attribute.TypeCompound(targetContainerType, List.of(p), + ((Attribute.TypeCompound)annotations.head).position); + JCTypeAnnotation annoTree = m.TypeAnnotation(at); + at = enterTypeAnnotation(annoTree, targetContainerType, ctx.env); + */ + // However, we directly construct the TypeCompound to keep the + // direct relation to the contained TypeCompounds. + Attribute.TypeCompound at = new Attribute.TypeCompound(targetContainerType, List.of(p), + ((Attribute.TypeCompound)annotations.head).position); - if (!chk.annotationApplicable(annoTree, on)) - log.error(annoTree.pos(), "invalid.repeatable.annotation.incompatible.target", targetContainerType, origAnnoType); + // TODO: annotation applicability checks from below? - if (!chk.validateAnnotationDeferErrors(annoTree)) - log.error(annoTree.pos(), "duplicate.annotation.invalid.repeated", origAnnoType); + at.setSynthesized(true); - Attribute.Compound c = enterAnnotation(annoTree, - targetContainerType, - ctx.env); - c.setSynthesized(true); - return c; + @SuppressWarnings("unchecked") + T x = (T) at; + return x; + } else { + Attribute.Compound c = new Attribute.Compound(targetContainerType, List.of(p)); + JCAnnotation annoTree = m.Annotation(c); + + if (!chk.annotationApplicable(annoTree, on)) + log.error(annoTree.pos(), "invalid.repeatable.annotation.incompatible.target", targetContainerType, origAnnoType); + + if (!chk.validateAnnotationDeferErrors(annoTree)) + log.error(annoTree.pos(), "duplicate.annotation.invalid.repeated", origAnnoType); + + c = enterAnnotation(annoTree, targetContainerType, ctx.env); + c.setSynthesized(true); + + @SuppressWarnings("unchecked") + T x = (T) c; + return x; + } } else { return null; // errors should have been reported elsewhere } diff --git a/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java b/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java index 20ddc1c09f5..db09cf5ed9b 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java @@ -26,9 +26,9 @@ package com.sun.tools.javac.comp; import java.util.*; -import java.util.Set; import javax.lang.model.element.ElementKind; +import javax.lang.model.type.TypeKind; import javax.tools.JavaFileObject; import com.sun.source.tree.IdentifierTree; @@ -45,7 +45,6 @@ import com.sun.tools.javac.comp.DeferredAttr.AttrMode; import com.sun.tools.javac.comp.Infer.InferenceContext; import com.sun.tools.javac.comp.Infer.InferenceContext.FreeTypeListener; import com.sun.tools.javac.jvm.*; -import com.sun.tools.javac.jvm.Target; import com.sun.tools.javac.tree.*; import com.sun.tools.javac.tree.JCTree.*; import com.sun.tools.javac.tree.JCTree.JCPolyExpression.*; @@ -880,6 +879,7 @@ public class Attr extends JCTree.Visitor { deferredLintHandler.flush(tree.pos()); chk.checkDeprecatedAnnotation(tree.pos(), m); + // Create a new environment with local scope // for attributing the method. Env localEnv = memberEnter.methodEnv(tree, env); @@ -923,6 +923,21 @@ public class Attr extends JCTree.Visitor { // Check that result type is well-formed. chk.validate(tree.restype, localEnv); + // Check that receiver type is well-formed. + if (tree.recvparam != null) { + // Use a new environment to check the receiver parameter. + // Otherwise I get "might not have been initialized" errors. + // Is there a better way? + Env newEnv = memberEnter.methodEnv(tree, env); + attribType(tree.recvparam, newEnv); + chk.validate(tree.recvparam, newEnv); + if (!(tree.recvparam.type == m.owner.type || types.isSameType(tree.recvparam.type, m.owner.type))) { + // The == covers the common non-generic case, but for generic classes we need isSameType; + // note that equals didn't work. + log.error(tree.recvparam.pos(), "incorrect.receiver.type"); + } + } + // annotation method checks if ((owner.flags() & ANNOTATION) != 0) { // annotation method cannot have throws clause @@ -996,9 +1011,14 @@ public class Attr extends JCTree.Visitor { } } + // Attribute all type annotations in the body + memberEnter.typeAnnotate(tree.body, localEnv, m); + annotate.flush(); + // Attribute method body. attribStat(tree.body, localEnv); } + localEnv.info.scope.leave(); result = tree.type = m.type; chk.validateAnnotations(tree.mods.annotations, m); @@ -1019,6 +1039,12 @@ public class Attr extends JCTree.Visitor { memberEnter.memberEnter(tree, env); annotate.flush(); } + } else { + if (tree.init != null) { + // Field initializer expression need to be entered. + memberEnter.typeAnnotate(tree.init, env, tree.sym); + annotate.flush(); + } } VarSymbol v = tree.sym; @@ -1076,6 +1102,11 @@ public class Attr extends JCTree.Visitor { new MethodSymbol(tree.flags | BLOCK, names.empty, null, env.info.scope.owner); if ((tree.flags & STATIC) != 0) localEnv.info.staticLevel++; + + // Attribute all type annotations in the block + memberEnter.typeAnnotate(tree, localEnv, localEnv.info.scope.owner); + annotate.flush(); + attribStats(tree.stats, localEnv); } else { // Create a new local environment with a local scope. @@ -1847,10 +1878,24 @@ public class Attr extends JCTree.Visitor { // If enclosing class is given, attribute it, and // complete class name to be fully qualified JCExpression clazz = tree.clazz; // Class field following new - JCExpression clazzid = // Identifier in class field - (clazz.hasTag(TYPEAPPLY)) - ? ((JCTypeApply) clazz).clazz - : clazz; + JCExpression clazzid; // Identifier in class field + JCAnnotatedType annoclazzid; // Annotated type enclosing clazzid + annoclazzid = null; + + if (clazz.hasTag(TYPEAPPLY)) { + clazzid = ((JCTypeApply) clazz).clazz; + if (clazzid.hasTag(ANNOTATED_TYPE)) { + annoclazzid = (JCAnnotatedType) clazzid; + clazzid = annoclazzid.underlyingType; + } + } else { + if (clazz.hasTag(ANNOTATED_TYPE)) { + annoclazzid = (JCAnnotatedType) clazz; + clazzid = annoclazzid.underlyingType; + } else { + clazzid = clazz; + } + } JCExpression clazzid1 = clazzid; // The same in fully qualified form @@ -1865,14 +1910,30 @@ public class Attr extends JCTree.Visitor { // yields a clazz T.C. Type encltype = chk.checkRefType(tree.encl.pos(), attribExpr(tree.encl, env)); + // TODO 308: in .new C, do we also want to add the type annotations + // from expr to the combined type, or not? Yes, do this. clazzid1 = make.at(clazz.pos).Select(make.Type(encltype), ((JCIdent) clazzid).name); - if (clazz.hasTag(TYPEAPPLY)) - clazz = make.at(tree.pos). + + if (clazz.hasTag(ANNOTATED_TYPE)) { + JCAnnotatedType annoType = (JCAnnotatedType) clazz; + List annos = annoType.annotations; + + if (annoType.underlyingType.hasTag(TYPEAPPLY)) { + clazzid1 = make.at(tree.pos). + TypeApply(clazzid1, + ((JCTypeApply) clazz).arguments); + } + + clazzid1 = make.at(tree.pos). + AnnotatedType(annos, clazzid1); + } else if (clazz.hasTag(TYPEAPPLY)) { + clazzid1 = make.at(tree.pos). TypeApply(clazzid1, ((JCTypeApply) clazz).arguments); - else - clazz = clazzid1; + } + + clazz = clazzid1; } // Attribute clazz expression and store @@ -1889,6 +1950,9 @@ public class Attr extends JCTree.Visitor { tree.clazz.type = clazztype; TreeInfo.setSymbol(clazzid, TreeInfo.symbol(clazzid1)); clazzid.type = ((JCIdent) clazzid).sym.type; + if (annoclazzid != null) { + annoclazzid.type = clazzid.type; + } if (!clazztype.isErroneous()) { if (cdef != null && clazztype.tsym.isInterface()) { log.error(tree.encl.pos(), "anon.class.impl.intf.no.qual.for.new"); @@ -3255,8 +3319,18 @@ public class Attr extends JCTree.Visitor { // Tree.Visitor. else if (ownOuter.hasTag(CLASS) && site != ownOuter) { Type normOuter = site; - if (normOuter.hasTag(CLASS)) + if (normOuter.hasTag(CLASS)) { normOuter = types.asEnclosingSuper(site, ownOuter.tsym); + if (site.getKind() == TypeKind.ANNOTATED) { + // Propagate any type annotations. + // TODO: should asEnclosingSuper do this? + // Note that the type annotations in site will be updated + // by annotateType. Therefore, modify site instead + // of creating a new AnnotatedType. + ((AnnotatedType)site).underlyingType = normOuter; + normOuter = site; + } + } if (normOuter == null) // perhaps from an import normOuter = types.erasure(ownOuter); if (normOuter != ownOuter) @@ -3644,8 +3718,15 @@ public class Attr extends JCTree.Visitor { tree.type = result = checkIntersection(tree, tree.bounds); } - public void visitTypeParameter(JCTypeParameter tree) { - TypeVar typeVar = (TypeVar)tree.type; + public void visitTypeParameter(JCTypeParameter tree) { + TypeVar typeVar = (TypeVar) tree.type; + + if (tree.annotations != null && tree.annotations.nonEmpty()) { + AnnotatedType antype = new AnnotatedType(typeVar); + annotateType(antype, tree.annotations); + tree.type = antype; + } + if (!typeVar.bound.isErroneous()) { //fixup type-parameter bound computed in 'attribTypeVariables' typeVar.bound = checkIntersection(tree, tree.bounds); @@ -3741,6 +3822,44 @@ public class Attr extends JCTree.Visitor { result = tree.type = syms.errType; } + public void visitAnnotatedType(JCAnnotatedType tree) { + Type underlyingType = attribType(tree.getUnderlyingType(), env); + this.attribAnnotationTypes(tree.annotations, env); + AnnotatedType antype = new AnnotatedType(underlyingType); + annotateType(antype, tree.annotations); + result = tree.type = antype; + } + + /** + * Apply the annotations to the particular type. + */ + public void annotateType(final AnnotatedType type, final List annotations) { + if (annotations.isEmpty()) + return; + annotate.typeAnnotation(new Annotate.Annotator() { + @Override + public String toString() { + return "annotate " + annotations + " onto " + type; + } + @Override + public void enterAnnotation() { + List compounds = fromAnnotations(annotations); + type.typeAnnotations = compounds; + } + }); + } + + private static List fromAnnotations(List annotations) { + if (annotations.isEmpty()) + return List.nil(); + + ListBuffer buf = ListBuffer.lb(); + for (JCAnnotation anno : annotations) { + buf.append((Attribute.TypeCompound) anno.attribute); + } + return buf.toList(); + } + public void visitErroneous(JCErroneous tree) { if (tree.errs != null) for (JCTree err : tree.errs) @@ -3972,6 +4091,12 @@ public class Attr extends JCTree.Visitor { (c.flags() & ABSTRACT) == 0) { checkSerialVersionUID(tree, c); } + + // Correctly organize the postions of the type annotations + TypeAnnotations.organizeTypeAnnotationsBodies(this.syms, this.names, this.log, tree); + + // Check type annotations applicability rules + validateTypeAnnotations(tree); } // where /** get a diagnostic position for an attribute of Type t, or null if attribute missing */ @@ -4029,6 +4154,94 @@ public class Attr extends JCTree.Visitor { return types.capture(type); } + private void validateTypeAnnotations(JCTree tree) { + tree.accept(typeAnnotationsValidator); + } + //where + private final JCTree.Visitor typeAnnotationsValidator = + new TreeScanner() { + public void visitAnnotation(JCAnnotation tree) { + if (tree.hasTag(TYPE_ANNOTATION)) { + // TODO: It seems to WMD as if the annotation in + // parameters, in particular also the recvparam, are never + // of type JCTypeAnnotation and therefore never checked! + // Luckily this check doesn't really do anything that isn't + // also done elsewhere. + chk.validateTypeAnnotation(tree, false); + } + super.visitAnnotation(tree); + } + public void visitTypeParameter(JCTypeParameter tree) { + chk.validateTypeAnnotations(tree.annotations, true); + scan(tree.bounds); + // Don't call super. + // This is needed because above we call validateTypeAnnotation with + // false, which would forbid annotations on type parameters. + // super.visitTypeParameter(tree); + } + public void visitMethodDef(JCMethodDecl tree) { + // Static methods cannot have receiver type annotations. + // In test case FailOver15.java, the nested method getString has + // a null sym, because an unknown class is instantiated. + // I would say it's safe to skip. + if (tree.sym != null && (tree.sym.flags() & Flags.STATIC) != 0) { + if (tree.recvparam != null) { + // TODO: better error message. Is the pos good? + log.error(tree.recvparam.pos(), "annotation.type.not.applicable"); + } + } + if (tree.restype != null && tree.restype.type != null) { + validateAnnotatedType(tree.restype, tree.restype.type); + } + super.visitMethodDef(tree); + } + public void visitVarDef(final JCVariableDecl tree) { + if (tree.sym != null && tree.sym.type != null) + validateAnnotatedType(tree, tree.sym.type); + super.visitVarDef(tree); + } + public void visitTypeCast(JCTypeCast tree) { + if (tree.clazz != null && tree.clazz.type != null) + validateAnnotatedType(tree.clazz, tree.clazz.type); + super.visitTypeCast(tree); + } + public void visitTypeTest(JCInstanceOf tree) { + if (tree.clazz != null && tree.clazz.type != null) + validateAnnotatedType(tree.clazz, tree.clazz.type); + super.visitTypeTest(tree); + } + // TODO: what else do we need? + // public void visitNewClass(JCNewClass tree) { + // public void visitNewArray(JCNewArray tree) { + + /* I would want to model this after + * com.sun.tools.javac.comp.Check.Validator.visitSelectInternal(JCFieldAccess) + * and override visitSelect and visitTypeApply. + * However, we only set the annotated type in the top-level type + * of the symbol. + * Therefore, we need to override each individual location where a type + * can occur. + */ + private void validateAnnotatedType(final JCTree errtree, final Type type) { + if (type.getEnclosingType() != null && + type != type.getEnclosingType()) { + validateEnclosingAnnotatedType(errtree, type.getEnclosingType()); + } + for (Type targ : type.getTypeArguments()) { + validateAnnotatedType(errtree, targ); + } + } + private void validateEnclosingAnnotatedType(final JCTree errtree, final Type type) { + validateAnnotatedType(errtree, type); + if (type.tsym != null && + type.tsym.isStatic() && + type.getAnnotations().nonEmpty()) { + // Enclosing static classes cannot have type annotations. + log.error(errtree.pos(), "cant.annotate.static.class"); + } + } + }; + // /** diff --git a/langtools/src/share/classes/com/sun/tools/javac/comp/Check.java b/langtools/src/share/classes/com/sun/tools/javac/comp/Check.java index ed38ae7042c..43283c8154f 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/comp/Check.java +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Check.java @@ -26,7 +26,7 @@ package com.sun.tools.javac.comp; import java.util.*; -import java.util.Set; + import javax.tools.JavaFileManager; import com.sun.tools.javac.code.*; @@ -101,6 +101,9 @@ public class Check { context.put(checkKey, this); names = Names.instance(context); + dfltTargetMeta = new Name[] { names.PACKAGE, names.TYPE, + names.FIELD, names.METHOD, names.CONSTRUCTOR, + names.ANNOTATION_TYPE, names.LOCAL_VARIABLE, names.PARAMETER}; log = Log.instance(context); rs = Resolve.instance(context); syms = Symtab.instance(context); @@ -572,35 +575,28 @@ public class Check { if (!tree.type.isErroneous() && (env.info.lint == null || env.info.lint.isEnabled(Lint.LintCategory.CAST)) && types.isSameType(tree.expr.type, tree.clazz.type) + && !(ignoreAnnotatedCasts && TreeInfo.containsTypeAnnotation(tree.clazz)) && !is292targetTypeCast(tree)) { log.warning(Lint.LintCategory.CAST, tree.pos(), "redundant.cast", tree.expr.type); } } //where - private boolean is292targetTypeCast(JCTypeCast tree) { - boolean is292targetTypeCast = false; - JCExpression expr = TreeInfo.skipParens(tree.expr); - if (expr.hasTag(APPLY)) { - JCMethodInvocation apply = (JCMethodInvocation)expr; - Symbol sym = TreeInfo.symbol(apply.meth); - is292targetTypeCast = sym != null && - sym.kind == MTH && - (sym.flags() & HYPOTHETICAL) != 0; - } - return is292targetTypeCast; + private boolean is292targetTypeCast(JCTypeCast tree) { + boolean is292targetTypeCast = false; + JCExpression expr = TreeInfo.skipParens(tree.expr); + if (expr.hasTag(APPLY)) { + JCMethodInvocation apply = (JCMethodInvocation)expr; + Symbol sym = TreeInfo.symbol(apply.meth); + is292targetTypeCast = sym != null && + sym.kind == MTH && + (sym.flags() & HYPOTHETICAL) != 0; } - - - -//where - /** Is type a type variable, or a (possibly multi-dimensional) array of - * type variables? - */ - boolean isTypeVar(Type t) { - return t.hasTag(TYPEVAR) || t.hasTag(ARRAY) && isTypeVar(types.elemtype(t)); + return is292targetTypeCast; } + private static final boolean ignoreAnnotatedCasts = true; + /** Check that a type is within some bounds. * * Used in TypeApply to verify that, e.g., X in {@code V} is a valid @@ -853,7 +849,7 @@ public class Check { // System.out.println("actuals: " + argtypes); List formals = owntype.getParameterTypes(); Type last = useVarargs ? formals.last() : null; - if (sym.name==names.init && + if (sym.name == names.init && sym.owner == syms.enumSym) formals = formals.tail.tail; List args = argtrees; @@ -1326,6 +1322,11 @@ public class Check { } } + @Override + public void visitAnnotatedType(JCAnnotatedType tree) { + tree.underlyingType.accept(this); + } + /** Default visitor method: do nothing. */ @Override @@ -2246,7 +2247,7 @@ public class Check { void checkImplementations(JCClassDecl tree) { checkImplementations(tree, tree.sym, tree.sym); } -//where + //where /** Check that all methods which implement some * method in `ic' conform to the method they implement. */ @@ -2587,6 +2588,13 @@ public class Check { validateAnnotation(a, s); } + /** Check the type annotations. + */ + public void validateTypeAnnotations(List annotations, boolean isTypeParameter) { + for (JCAnnotation a : annotations) + validateTypeAnnotation(a, isTypeParameter); + } + /** Check an annotation of a symbol. */ private void validateAnnotation(JCAnnotation a, Symbol s) { @@ -2613,6 +2621,14 @@ public class Check { } } + public void validateTypeAnnotation(JCAnnotation a, boolean isTypeParameter) { + Assert.checkNonNull(a.type, "annotation tree hasn't been attributed yet: " + a); + validateAnnotationTree(a); + + if (!isTypeAnnotation(a, isTypeParameter)) + log.error(a.pos(), "annotation.type.not.applicable"); + } + /** * Validate the proposed container 'repeatable' on the * annotation type symbol 's'. Report errors at position @@ -2795,45 +2811,90 @@ public class Check { return false; } + /** Is the annotation applicable to type annotations? */ + protected boolean isTypeAnnotation(JCAnnotation a, boolean isTypeParameter) { + Attribute.Compound atTarget = + a.annotationType.type.tsym.attribute(syms.annotationTargetType.tsym); + if (atTarget == null) { + // An annotation without @Target is not a type annotation. + return false; + } + + Attribute atValue = atTarget.member(names.value); + if (!(atValue instanceof Attribute.Array)) { + return false; // error recovery + } + + Attribute.Array arr = (Attribute.Array) atValue; + for (Attribute app : arr.values) { + if (!(app instanceof Attribute.Enum)) { + return false; // recovery + } + Attribute.Enum e = (Attribute.Enum) app; + + if (e.value.name == names.TYPE_USE) + return true; + else if (isTypeParameter && e.value.name == names.TYPE_PARAMETER) + return true; + } + return false; + } + /** Is the annotation applicable to the symbol? */ boolean annotationApplicable(JCAnnotation a, Symbol s) { Attribute.Array arr = getAttributeTargetAttribute(a.annotationType.type.tsym); + Name[] targets; + if (arr == null) { - return true; + targets = defaultTargetMetaInfo(a, s); + } else { + // TODO: can we optimize this? + targets = new Name[arr.values.length]; + for (int i=0; i typarams, List params, JCTree res, + JCVariableDecl recvparam, List thrown, Env env) { @@ -368,6 +375,15 @@ public class MemberEnter extends JCTree.Visitor implements Completer { // Attribute result type, if one is given. Type restype = res == null ? syms.voidType : attr.attribType(res, env); + // Attribute receiver type, if one is given. + Type recvtype; + if (recvparam!=null) { + memberEnter(recvparam, env); + recvtype = recvparam.vartype.type; + } else { + recvtype = null; + } + // Attribute thrown exceptions. ListBuffer thrownbuf = new ListBuffer(); for (List l = thrown; l.nonEmpty(); l = l.tail) { @@ -376,10 +392,12 @@ public class MemberEnter extends JCTree.Visitor implements Completer { exc = chk.checkClassType(l.head.pos(), exc); thrownbuf.append(exc); } - Type mtype = new MethodType(argbuf.toList(), + MethodType mtype = new MethodType(argbuf.toList(), restype, thrownbuf.toList(), syms.methodClass); + mtype.recvtype = recvtype; + return tvars.isEmpty() ? mtype : new ForAll(tvars, mtype); } @@ -573,7 +591,8 @@ public class MemberEnter extends JCTree.Visitor implements Completer { try { // Compute the method type m.type = signature(tree.typarams, tree.params, - tree.restype, tree.thrown, + tree.restype, tree.recvparam, + tree.thrown, localEnv); } finally { chk.setDeferredLintHandler(prevLintHandler); @@ -597,6 +616,10 @@ public class MemberEnter extends JCTree.Visitor implements Completer { enclScope.enter(m); } annotateLater(tree.mods.annotations, localEnv, m); + // Visit the signature of the method. Note that + // TypeAnnotate doesn't descend into the body. + typeAnnotate(tree, localEnv, m); + if (tree.defaultValue != null) annotateDefaultValueLater(tree.defaultValue, localEnv, m); } @@ -642,7 +665,7 @@ public class MemberEnter extends JCTree.Visitor implements Completer { //(a plain array type) with the more precise VarargsType --- we need //to do it this way because varargs is represented in the tree as a modifier //on the parameter declaration, and not as a distinct type of array node. - ArrayType atype = (ArrayType)tree.vartype.type; + ArrayType atype = (ArrayType)tree.vartype.type.unannotatedType(); tree.vartype.type = atype.makeVarargs(); } Scope enclScope = enter.enterScope(env); @@ -665,6 +688,8 @@ public class MemberEnter extends JCTree.Visitor implements Completer { enclScope.enter(v); } annotateLater(tree.mods.annotations, localEnv, v); + typeAnnotate(tree.vartype, env, tree.sym); + annotate.flush(); v.pos = tree.pos; } @@ -759,7 +784,7 @@ public class MemberEnter extends JCTree.Visitor implements Completer { log.error(annotations.head.pos, "already.annotated", kindName(s), s); - enterAnnotations(annotations, localEnv, s); + actualEnterAnnotations(annotations, localEnv, s); } finally { log.useSource(prev); } @@ -781,7 +806,7 @@ public class MemberEnter extends JCTree.Visitor implements Completer { } /** Enter a set of annotations. */ - private void enterAnnotations(List annotations, + private void actualEnterAnnotations(List annotations, Env env, Symbol s) { Map> annotated = @@ -817,11 +842,11 @@ public class MemberEnter extends JCTree.Visitor implements Completer { && s.owner.kind != MTH && types.isSameType(c.type, syms.deprecatedType)) { s.flags_field |= Flags.DEPRECATED; - } + } } - s.annotations.setAttributesWithCompletion( - annotate.new AnnotateRepeatedContext(env, annotated, pos, log)); + s.annotations.setDeclarationAttributesWithCompletion( + annotate.new AnnotateRepeatedContext(env, annotated, pos, log, false)); } /** Queue processing of an attribute default value. */ @@ -900,6 +925,12 @@ public class MemberEnter extends JCTree.Visitor implements Completer { // create an environment for evaluating the base clauses Env baseEnv = baseEnv(tree, env); + if (tree.extending != null) + typeAnnotate(tree.extending, baseEnv, sym); + for (JCExpression impl : tree.implementing) + typeAnnotate(impl, baseEnv, sym); + annotate.flush(); + // Determine supertype. Type supertype = (tree.extending != null) @@ -969,10 +1000,15 @@ public class MemberEnter extends JCTree.Visitor implements Completer { if (hasDeprecatedAnnotation(tree.mods.annotations)) c.flags_field |= DEPRECATED; annotateLater(tree.mods.annotations, baseEnv, c); + // class type parameters use baseEnv but everything uses env chk.checkNonCyclicDecl(tree); attr.attribTypeVariables(tree.typarams, baseEnv); + // Do this here, where we have the symbol. + for (JCTypeParameter tp : tree.typarams) + typeAnnotate(tp, baseEnv, sym); + annotate.flush(); // Add default constructor if needed. if ((c.flags() & INTERFACE) == 0 && @@ -1050,12 +1086,120 @@ public class MemberEnter extends JCTree.Visitor implements Completer { } finally { isFirst = true; } + } + annotate.afterRepeated(TypeAnnotations.organizeTypeAnnotationsSignatures(syms, names, log, tree)); + } - // commit pending annotations - annotate.flush(); + private void actualEnterTypeAnnotations(final List annotations, + final Env env, + final Symbol s) { + Map> annotated = + new LinkedHashMap>(); + Map pos = + new HashMap(); + + for (List al = annotations; !al.isEmpty(); al = al.tail) { + JCAnnotation a = al.head; + Attribute.TypeCompound tc = annotate.enterTypeAnnotation(a, + syms.annotationType, + env); + if (tc == null) { + continue; + } + + if (annotated.containsKey(a.type.tsym)) { + if (source.allowRepeatedAnnotations()) { + ListBuffer l = annotated.get(a.type.tsym); + l = l.append(tc); + annotated.put(a.type.tsym, l); + pos.put(tc, a.pos()); + } else { + log.error(a.pos(), "duplicate.annotation"); + } + } else { + annotated.put(a.type.tsym, ListBuffer.of(tc)); + pos.put(tc, a.pos()); + } + } + + s.annotations.appendTypeAttributesWithCompletion( + annotate.new AnnotateRepeatedContext(env, annotated, pos, log, true)); + } + + public void typeAnnotate(final JCTree tree, final Env env, final Symbol sym) { + tree.accept(new TypeAnnotate(env, sym)); + } + + /** + * We need to use a TreeScanner, because it is not enough to visit the top-level + * annotations. We also need to visit type arguments, etc. + */ + private class TypeAnnotate extends TreeScanner { + private Env env; + private Symbol sym; + + public TypeAnnotate(final Env env, final Symbol sym) { + this.env = env; + this.sym = sym; + } + + void annotateTypeLater(final List annotations) { + if (annotations.isEmpty()) { + return; + } + + annotate.normal(new Annotate.Annotator() { + @Override + public String toString() { + return "type annotate " + annotations + " onto " + sym + " in " + sym.owner; + } + @Override + public void enterAnnotation() { + JavaFileObject prev = log.useSource(env.toplevel.sourcefile); + try { + actualEnterTypeAnnotations(annotations, env, sym); + } finally { + log.useSource(prev); + } + } + }); + } + + @Override + public void visitAnnotatedType(final JCAnnotatedType tree) { + annotateTypeLater(tree.annotations); + super.visitAnnotatedType(tree); + } + + @Override + public void visitTypeParameter(final JCTypeParameter tree) { + annotateTypeLater(tree.annotations); + super.visitTypeParameter(tree); + } + + @Override + public void visitNewArray(final JCNewArray tree) { + annotateTypeLater(tree.annotations); + for (List dimAnnos : tree.dimAnnotations) + annotateTypeLater(dimAnnos); + super.visitNewArray(tree); + } + + @Override + public void visitMethodDef(final JCMethodDecl tree) { + scan(tree.mods); + scan(tree.restype); + scan(tree.typarams); + scan(tree.recvparam); + scan(tree.params); + scan(tree.thrown); + scan(tree.defaultValue); + // Do not annotate the body, just the signature. + // scan(tree.body); } } + private Env baseEnv(JCClassDecl tree, Env env) { Scope baseScope = new Scope(tree.sym); //import already entered local classes into base scope diff --git a/langtools/src/share/classes/com/sun/tools/javac/comp/Resolve.java b/langtools/src/share/classes/com/sun/tools/javac/comp/Resolve.java index c058d34de1e..08cc94f372f 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/comp/Resolve.java +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Resolve.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2013, 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 @@ -55,7 +55,6 @@ import java.util.Iterator; import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.Map; -import java.util.Set; import javax.lang.model.element.ElementVisitor; @@ -696,7 +695,7 @@ public class Resolve { if (varargsFormal == null && argtypes.size() != formals.size()) { - report(MethodCheckDiag.ARITY_MISMATCH, inferenceContext); // not enough args + reportMC(MethodCheckDiag.ARITY_MISMATCH, inferenceContext); // not enough args } while (argtypes.nonEmpty() && formals.head != varargsFormal) { @@ -707,7 +706,7 @@ public class Resolve { } if (formals.head != varargsFormal) { - report(MethodCheckDiag.ARITY_MISMATCH, inferenceContext); // not enough args + reportMC(MethodCheckDiag.ARITY_MISMATCH, inferenceContext); // not enough args } if (useVarargs) { @@ -724,7 +723,7 @@ public class Resolve { } } - private void report(MethodCheckDiag diag, InferenceContext inferenceContext, Object... args) { + private void reportMC(MethodCheckDiag diag, InferenceContext inferenceContext, Object... args) { boolean inferDiag = inferenceContext != infer.emptyContext; InapplicableMethodException ex = inferDiag ? infer.inferenceException : inapplicableMethodException; @@ -748,7 +747,7 @@ public class Resolve { } else { if (!isAccessible(env, t)) { Symbol location = env.enclClass.sym; - report(MethodCheckDiag.INACCESSIBLE_VARARGS, inferenceContext, t, Kinds.kindName(location), location); + reportMC(MethodCheckDiag.INACCESSIBLE_VARARGS, inferenceContext, t, Kinds.kindName(location), location); } } } @@ -761,7 +760,7 @@ public class Resolve { @Override public void report(DiagnosticPosition pos, JCDiagnostic details) { - report(methodDiag, deferredAttrContext.inferenceContext, details); + reportMC(methodDiag, deferredAttrContext.inferenceContext, details); } }; return new MethodResultInfo(to, checkContext); diff --git a/langtools/src/share/classes/com/sun/tools/javac/comp/TransTypes.java b/langtools/src/share/classes/com/sun/tools/javac/comp/TransTypes.java index 899e0c110b3..0b191293db7 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/comp/TransTypes.java +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/TransTypes.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2013, 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 @@ -483,6 +483,7 @@ public class TransTypes extends TreeTranslator { tree.restype = translate(tree.restype, null); tree.typarams = List.nil(); tree.params = translateVarDefs(tree.params); + tree.recvparam = translate(tree.recvparam, null); tree.thrown = translate(tree.thrown, null); tree.body = translate(tree.body, tree.sym.erasure(types).getReturnType()); tree.type = erasure(tree.type); diff --git a/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassReader.java b/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassReader.java index 33ee5a780fb..4061471be55 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassReader.java +++ b/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassReader.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2013, 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 @@ -351,8 +351,8 @@ public class ClassReader implements Completer { /** Read a byte. */ - byte nextByte() { - return buf[bp++]; + int nextByte() { + return buf[bp++] & 0xFF; } /** Read an integer. @@ -1172,6 +1172,19 @@ public class ClassReader implements Completer { } }, + new AttributeReader(names.RuntimeVisibleTypeAnnotations, V52, CLASS_OR_MEMBER_ATTRIBUTE) { + protected void read(Symbol sym, int attrLen) { + attachTypeAnnotations(sym); + } + }, + + new AttributeReader(names.RuntimeInvisibleTypeAnnotations, V52, CLASS_OR_MEMBER_ATTRIBUTE) { + protected void read(Symbol sym, int attrLen) { + attachTypeAnnotations(sym); + } + }, + + // The following attributes for a Code attribute are not currently handled // StackMapTable // SourceDebugExtension @@ -1381,6 +1394,17 @@ public class ClassReader implements Completer { } } + void attachTypeAnnotations(final Symbol sym) { + int numAttributes = nextChar(); + if (numAttributes != 0) { + ListBuffer proxies = + ListBuffer.lb(); + for (int i = 0; i < numAttributes; i++) + proxies.append(readTypeAnnotation()); + annotate.normal(new TypeAnnotationCompleter(sym, proxies.toList())); + } + } + /** Attach the default value for an annotation element. */ void attachAnnotationDefault(final Symbol sym) { @@ -1427,6 +1451,111 @@ public class ClassReader implements Completer { return new CompoundAnnotationProxy(t, pairs.toList()); } + TypeAnnotationProxy readTypeAnnotation() { + TypeAnnotationPosition position = readPosition(); + CompoundAnnotationProxy proxy = readCompoundAnnotation(); + + return new TypeAnnotationProxy(proxy, position); + } + + TypeAnnotationPosition readPosition() { + int tag = nextByte(); // TargetType tag is a byte + + if (!TargetType.isValidTargetTypeValue(tag)) + throw this.badClassFile("bad.type.annotation.value", String.format("0x%02X", tag)); + + TypeAnnotationPosition position = new TypeAnnotationPosition(); + TargetType type = TargetType.fromTargetTypeValue(tag); + + position.type = type; + + switch (type) { + // type cast + case CAST: + // instanceof + case INSTANCEOF: + // new expression + case NEW: + position.offset = nextChar(); + break; + // local variable + case LOCAL_VARIABLE: + // resource variable + case RESOURCE_VARIABLE: + int table_length = nextChar(); + position.lvarOffset = new int[table_length]; + position.lvarLength = new int[table_length]; + position.lvarIndex = new int[table_length]; + + for (int i = 0; i < table_length; ++i) { + position.lvarOffset[i] = nextChar(); + position.lvarLength[i] = nextChar(); + position.lvarIndex[i] = nextChar(); + } + break; + // exception parameter + case EXCEPTION_PARAMETER: + position.exception_index = nextByte(); + break; + // method receiver + case METHOD_RECEIVER: + // Do nothing + break; + // type parameter + case CLASS_TYPE_PARAMETER: + case METHOD_TYPE_PARAMETER: + position.parameter_index = nextByte(); + break; + // type parameter bound + case CLASS_TYPE_PARAMETER_BOUND: + case METHOD_TYPE_PARAMETER_BOUND: + position.parameter_index = nextByte(); + position.bound_index = nextByte(); + break; + // class extends or implements clause + case CLASS_EXTENDS: + position.type_index = nextChar(); + break; + // throws + case THROWS: + position.type_index = nextChar(); + break; + // method parameter + case METHOD_FORMAL_PARAMETER: + position.parameter_index = nextByte(); + break; + // method/constructor/reference type argument + case CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT: + case METHOD_INVOCATION_TYPE_ARGUMENT: + case METHOD_REFERENCE_TYPE_ARGUMENT: + position.offset = nextChar(); + position.type_index = nextByte(); + break; + // We don't need to worry about these + case METHOD_RETURN: + case FIELD: + break; + // lambda formal parameter + case LAMBDA_FORMAL_PARAMETER: + position.parameter_index = nextByte(); + break; + case UNKNOWN: + throw new AssertionError("jvm.ClassReader: UNKNOWN target type should never occur!"); + default: + throw new AssertionError("jvm.ClassReader: Unknown target type for position: " + position); + } + + { // See whether there is location info and read it + int len = nextByte(); + ListBuffer loc = ListBuffer.lb(); + for (int i = 0; i < len * TypeAnnotationPosition.TypePathEntry.bytesPerEntry; ++i) + loc = loc.append(nextByte()); + position.location = TypeAnnotationPosition.getTypePathFromBinary(loc.toList()); + } + + return position; + } + Attribute readAttributeValue() { char c = (char) buf[bp++]; switch (c) { @@ -1748,7 +1877,7 @@ public class ClassReader implements Completer { Annotations annotations = sym.annotations; List newList = deproxyCompoundList(l); if (annotations.pendingCompletion()) { - annotations.setAttributes(newList); + annotations.setDeclarationAttributes(newList); } else { annotations.append(newList); } @@ -1758,6 +1887,39 @@ public class ClassReader implements Completer { } } + class TypeAnnotationCompleter extends AnnotationCompleter { + + List proxies; + + TypeAnnotationCompleter(Symbol sym, + List proxies) { + super(sym, List.nil()); + this.proxies = proxies; + } + + List deproxyTypeCompoundList(List proxies) { + ListBuffer buf = ListBuffer.lb(); + for (TypeAnnotationProxy proxy: proxies) { + Attribute.Compound compound = deproxyCompound(proxy.compound); + Attribute.TypeCompound typeCompound = new Attribute.TypeCompound(compound, proxy.position); + buf.add(typeCompound); + } + return buf.toList(); + } + + @Override + public void enterAnnotation() { + JavaFileObject previousClassFile = currentClassFile; + try { + currentClassFile = classFile; + List newList = deproxyTypeCompoundList(proxies); + sym.annotations.setTypeAttributes(newList.prependList(sym.getRawTypeAttributes())); + } finally { + currentClassFile = previousClassFile; + } + } + } + /************************************************************************ * Reading Symbols diff --git a/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassWriter.java b/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassWriter.java index 329000d3e4f..b48701ee37c 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassWriter.java +++ b/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassWriter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2013, 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 @@ -31,12 +31,14 @@ import java.util.Map; import java.util.Set; import java.util.HashSet; +import javax.lang.model.type.TypeKind; import javax.tools.JavaFileManager; import javax.tools.FileObject; import javax.tools.JavaFileObject; import com.sun.tools.javac.code.*; import com.sun.tools.javac.code.Attribute.RetentionPolicy; +import com.sun.tools.javac.code.Attribute.TypeCompound; import com.sun.tools.javac.code.Symbol.*; import com.sun.tools.javac.code.Type.*; import com.sun.tools.javac.code.Types.UniqueType; @@ -47,7 +49,6 @@ import com.sun.tools.javac.jvm.Pool.MethodHandle; import com.sun.tools.javac.jvm.Pool.Variable; import com.sun.tools.javac.util.*; -import static com.sun.tools.javac.code.BoundKind.*; import static com.sun.tools.javac.code.Flags.*; import static com.sun.tools.javac.code.Kinds.*; import static com.sun.tools.javac.code.TypeTag.*; @@ -68,19 +69,17 @@ public class ClassWriter extends ClassFile { protected static final Context.Key classWriterKey = new Context.Key(); - private final Symtab syms; - private final Options options; /** Switch: verbose output. */ private boolean verbose; - /** Switch: scramble private names. + /** Switch: scramble private field names. */ private boolean scramble; - /** Switch: scramble private names. + /** Switch: scramble all field names. */ private boolean scrambleAll; @@ -96,7 +95,7 @@ public class ClassWriter extends ClassFile { */ private boolean genCrt; - /** Switch: describe the generated stackmap + /** Switch: describe the generated stackmap. */ boolean debugstackmap; @@ -114,7 +113,7 @@ public class ClassWriter extends ClassFile { private Types types; /** The initial sizes of the data and constant pool buffers. - * sizes are increased when buffers get full. + * Sizes are increased when buffers get full. */ static final int DATA_BUF_SIZE = 0x0fff0; static final int POOL_BUF_SIZE = 0x1fff0; @@ -181,7 +180,6 @@ public class ClassWriter extends ClassFile { log = Log.instance(context); names = Names.instance(context); - syms = Symtab.instance(context); options = Options.instance(context); target = Target.instance(context); source = Source.instance(context); @@ -279,6 +277,7 @@ public class ClassWriter extends ClassFile { /** Assemble signature of given type in string buffer. */ void assembleSig(Type type) { + type = type.unannotatedType(); switch (type.getTag()) { case BYTE: sigbuf.appendByte('B'); @@ -379,6 +378,7 @@ public class ClassWriter extends ClassFile { } void assembleClassSig(Type type) { + type = type.unannotatedType(); ClassType ct = (ClassType)type; ClassSymbol c = (ClassSymbol)ct.tsym; enterInner(c); @@ -722,6 +722,7 @@ public class ClassWriter extends ClassFile { acount++; } acount += writeJavaAnnotations(sym.getRawAttributes()); + acount += writeTypeAnnotations(sym.getRawTypeAttributes()); return acount; } @@ -838,6 +839,76 @@ public class ClassWriter extends ClassFile { return attrCount; } + int writeTypeAnnotations(List typeAnnos) { + if (typeAnnos.isEmpty()) return 0; + + ListBuffer visibles = ListBuffer.lb(); + ListBuffer invisibles = ListBuffer.lb(); + + for (Attribute.TypeCompound tc : typeAnnos) { + if (tc.position == null || tc.position.type == TargetType.UNKNOWN) { + boolean found = false; + // TODO: the position for the container annotation of a + // repeating type annotation has to be set. + // This cannot be done when the container is created, because + // then the position is not determined yet. + // How can we link these pieces better together? + if (tc.values.size() == 1) { + Pair val = tc.values.get(0); + if (val.fst.getSimpleName().contentEquals("value") && + val.snd instanceof Attribute.Array) { + Attribute.Array arr = (Attribute.Array) val.snd; + if (arr.values.length != 0 && + arr.values[0] instanceof Attribute.TypeCompound) { + TypeCompound atycomp = (Attribute.TypeCompound) arr.values[0]; + if (atycomp.position.type != TargetType.UNKNOWN) { + tc.position = atycomp.position; + found = true; + } + } + } + } + if (!found) { + // This happens for nested types like @A Outer. @B Inner. + // For method parameters we get the annotation twice! Once with + // a valid position, once unknown. + // TODO: find a cleaner solution. + // System.err.println("ClassWriter: Position UNKNOWN in type annotation: " + tc); + continue; + } + } + if (!tc.position.emitToClassfile()) + continue; + switch (types.getRetention(tc)) { + case SOURCE: break; + case CLASS: invisibles.append(tc); break; + case RUNTIME: visibles.append(tc); break; + default: ;// /* fail soft */ throw new AssertionError(vis); + } + } + + int attrCount = 0; + if (visibles.length() != 0) { + int attrIndex = writeAttr(names.RuntimeVisibleTypeAnnotations); + databuf.appendChar(visibles.length()); + for (Attribute.TypeCompound p : visibles) + writeTypeAnnotation(p); + endAttr(attrIndex); + attrCount++; + } + + if (invisibles.length() != 0) { + int attrIndex = writeAttr(names.RuntimeInvisibleTypeAnnotations); + databuf.appendChar(invisibles.length()); + for (Attribute.TypeCompound p : invisibles) + writeTypeAnnotation(p); + endAttr(attrIndex); + attrCount++; + } + + return attrCount; + } + /** A visitor to write an attribute including its leading * single-character marker. */ @@ -914,6 +985,94 @@ public class ClassWriter extends ClassFile { p.snd.accept(awriter); } } + + void writeTypeAnnotation(Attribute.TypeCompound c) { + writePosition(c.position); + writeCompoundAttribute(c); + } + + void writePosition(TypeAnnotationPosition p) { + databuf.appendByte(p.type.targetTypeValue()); // TargetType tag is a byte + switch (p.type) { + // type cast + case CAST: + // instanceof + case INSTANCEOF: + // new expression + case NEW: + databuf.appendChar(p.offset); + break; + // local variable + case LOCAL_VARIABLE: + // resource variable + case RESOURCE_VARIABLE: + databuf.appendChar(p.lvarOffset.length); // for table length + for (int i = 0; i < p.lvarOffset.length; ++i) { + databuf.appendChar(p.lvarOffset[i]); + databuf.appendChar(p.lvarLength[i]); + databuf.appendChar(p.lvarIndex[i]); + } + break; + // exception parameter + case EXCEPTION_PARAMETER: + databuf.appendByte(p.exception_index); + break; + // method receiver + case METHOD_RECEIVER: + // Do nothing + break; + // type parameter + case CLASS_TYPE_PARAMETER: + case METHOD_TYPE_PARAMETER: + databuf.appendByte(p.parameter_index); + break; + // type parameter bound + case CLASS_TYPE_PARAMETER_BOUND: + case METHOD_TYPE_PARAMETER_BOUND: + databuf.appendByte(p.parameter_index); + databuf.appendByte(p.bound_index); + break; + // class extends or implements clause + case CLASS_EXTENDS: + databuf.appendChar(p.type_index); + break; + // throws + case THROWS: + databuf.appendChar(p.type_index); + break; + // method parameter + case METHOD_FORMAL_PARAMETER: + databuf.appendByte(p.parameter_index); + break; + // method/constructor/reference type argument + case CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT: + case METHOD_INVOCATION_TYPE_ARGUMENT: + case METHOD_REFERENCE_TYPE_ARGUMENT: + databuf.appendChar(p.offset); + databuf.appendByte(p.type_index); + break; + // We don't need to worry about these + case METHOD_RETURN: + case FIELD: + break; + // lambda formal parameter + case LAMBDA_FORMAL_PARAMETER: + databuf.appendByte(p.parameter_index); + break; + case UNKNOWN: + throw new AssertionError("jvm.ClassWriter: UNKNOWN target type should never occur!"); + default: + throw new AssertionError("jvm.ClassWriter: Unknown target type for position: " + p); + } + + { // Append location data for generics/arrays. + databuf.appendByte(p.location.size()); + java.util.List loc = TypeAnnotationPosition.getBinaryFromTypePath(p.location); + for (int i : loc) + databuf.appendByte((byte)i); + } + } + /********************************************************************** * Writing Objects **********************************************************************/ @@ -1661,6 +1820,7 @@ public class ClassWriter extends ClassFile { acount += writeFlagAttrs(c.flags()); acount += writeJavaAnnotations(c.getRawAttributes()); + acount += writeTypeAnnotations(c.getRawTypeAttributes()); acount += writeEnclosingMethodAttribute(c); acount += writeExtraClassAttributes(c); diff --git a/langtools/src/share/classes/com/sun/tools/javac/jvm/Code.java b/langtools/src/share/classes/com/sun/tools/javac/jvm/Code.java index 87e1d6aea76..f5f37ef0435 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/jvm/Code.java +++ b/langtools/src/share/classes/com/sun/tools/javac/jvm/Code.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2013, 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 @@ -1924,17 +1924,70 @@ public class Code { if (length < Character.MAX_VALUE) { v.length = length; putVar(v); + fillLocalVarPosition(v); } } } state.defined.excl(adr); } + private void fillLocalVarPosition(LocalVar lv) { + if (lv == null || lv.sym == null + || lv.sym.annotations.isTypesEmpty()) + return; + for (Attribute.TypeCompound ta : lv.sym.getRawTypeAttributes()) { + TypeAnnotationPosition p = ta.position; + p.lvarOffset = new int[] { (int)lv.start_pc }; + p.lvarLength = new int[] { (int)lv.length }; + p.lvarIndex = new int[] { (int)lv.reg }; + p.isValidOffset = true; + } + } + + // Method to be called after compressCatchTable to + // fill in the exception table index for type + // annotations on exception parameters. + public void fillExceptionParameterPositions() { + for (int i = 0; i < varBufferSize; ++i) { + LocalVar lv = varBuffer[i]; + if (lv == null || lv.sym == null + || lv.sym.annotations.isTypesEmpty() + || !lv.sym.isExceptionParameter()) + return; + + int exidx = findExceptionIndex(lv); + + for (Attribute.TypeCompound ta : lv.sym.getRawTypeAttributes()) { + TypeAnnotationPosition p = ta.position; + p.exception_index = exidx; + } + } + } + + private int findExceptionIndex(LocalVar lv) { + List iter = catchInfo.toList(); + int len = catchInfo.length(); + for (int i = 0; i < len; ++i) { + char[] catchEntry = iter.head; + iter = iter.tail; + char handlerpc = catchEntry[2]; + if (lv.start_pc == handlerpc + 1) { + return i; + } + } + return -1; + } + /** Put a live variable range into the buffer to be output to the * class file. */ void putVar(LocalVar var) { - if (!varDebugInfo) return; + // Keep local variables if + // 1) we need them for debug information + // 2) it is an exception type and it contains type annotations + if (!varDebugInfo && + (!var.sym.isExceptionParameter() || + var.sym.annotations.isTypesEmpty())) return; if ((var.sym.flags() & Flags.SYNTHETIC) != 0) return; if (varBuffer == null) varBuffer = new LocalVar[20]; diff --git a/langtools/src/share/classes/com/sun/tools/javac/jvm/Gen.java b/langtools/src/share/classes/com/sun/tools/javac/jvm/Gen.java index f99c48b258c..b450fdcf43e 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/jvm/Gen.java +++ b/langtools/src/share/classes/com/sun/tools/javac/jvm/Gen.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2013, 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 @@ -1016,8 +1016,11 @@ public class Gen extends JCTree.Visitor { code.frameBeforeLast = null; } - //compress exception table + // Compress exception table code.compressCatchTable(); + + // Fill in type annotation positions for exception parameters + code.fillExceptionParameterPositions(); } } @@ -1738,6 +1741,7 @@ public class Gen extends JCTree.Visitor { *************************************************************************/ public void visitApply(JCMethodInvocation tree) { + setTypeAnnotationPositions(tree.pos); // Generate code for method. Item m = genExpr(tree.meth, methodType); // Generate code for all arguments, where the expected types are @@ -1775,10 +1779,48 @@ public class Gen extends JCTree.Visitor { result = items.makeStackItem(pt); } + private void setTypeAnnotationPositions(int treePos) { + MethodSymbol meth = code.meth; + + for (Attribute.TypeCompound ta : meth.getRawTypeAttributes()) { + if (ta.position.pos == treePos) { + ta.position.offset = code.cp; + ta.position.lvarOffset = new int[] { code.cp }; + ta.position.isValidOffset = true; + } + } + + if (code.meth.getKind() != javax.lang.model.element.ElementKind.CONSTRUCTOR + && code.meth.getKind() != javax.lang.model.element.ElementKind.STATIC_INIT) + return; + + for (Attribute.TypeCompound ta : meth.owner.getRawTypeAttributes()) { + if (ta.position.pos == treePos) { + ta.position.offset = code.cp; + ta.position.lvarOffset = new int[] { code.cp }; + ta.position.isValidOffset = true; + } + } + + ClassSymbol clazz = meth.enclClass(); + for (Symbol s : new com.sun.tools.javac.model.FilteredMemberList(clazz.members())) { + if (!s.getKind().isField()) + continue; + for (Attribute.TypeCompound ta : s.getRawTypeAttributes()) { + if (ta.position.pos == treePos) { + ta.position.offset = code.cp; + ta.position.lvarOffset = new int[] { code.cp }; + ta.position.isValidOffset = true; + } + } + } + } + public void visitNewClass(JCNewClass tree) { // Enclosing instances or anonymous classes should have been eliminated // by now. Assert.check(tree.encl == null && tree.def == null); + setTypeAnnotationPositions(tree.pos); code.emitop2(new_, makeRef(tree.pos(), tree.type)); code.emitop0(dup); @@ -1793,6 +1835,7 @@ public class Gen extends JCTree.Visitor { } public void visitNewArray(JCNewArray tree) { + setTypeAnnotationPositions(tree.pos); if (tree.elems != null) { Type elemtype = types.elemtype(tree.type); @@ -2122,6 +2165,7 @@ public class Gen extends JCTree.Visitor { } public void visitTypeCast(JCTypeCast tree) { + setTypeAnnotationPositions(tree.pos); result = genExpr(tree.expr, tree.clazz.type).load(); // Additional code is only needed if we cast to a reference type // which is not statically a supertype of the expression's type. @@ -2138,6 +2182,7 @@ public class Gen extends JCTree.Visitor { } public void visitTypeTest(JCInstanceOf tree) { + setTypeAnnotationPositions(tree.pos); genExpr(tree.expr, tree.expr.type).load(); code.emitop2(instanceof_, makeRef(tree.pos(), tree.clazz.type)); result = items.makeStackItem(syms.booleanType); @@ -2184,7 +2229,7 @@ public class Gen extends JCTree.Visitor { code.emitop2(ldc2, makeRef(tree.pos(), tree.selected.type)); result = items.makeStackItem(pt); return; - } + } Symbol ssym = TreeInfo.symbol(tree.selected); diff --git a/langtools/src/share/classes/com/sun/tools/javac/jvm/JNIWriter.java b/langtools/src/share/classes/com/sun/tools/javac/jvm/JNIWriter.java index b1b8444bd6f..139ba519a9f 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/jvm/JNIWriter.java +++ b/langtools/src/share/classes/com/sun/tools/javac/jvm/JNIWriter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2013, 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 @@ -158,7 +158,7 @@ public class JNIWriter { return false; /* temporary code for backwards compatibility */ - for (Attribute.Compound a: c.annotations.getAttributes()) { + for (Attribute.Compound a: c.annotations.getDeclarationAttributes()) { if (a.type.tsym == syms.nativeHeaderType_old.tsym) return true; } @@ -167,7 +167,7 @@ public class JNIWriter { for (Scope.Entry i = c.members_field.elems; i != null; i = i.sibling) { if (i.sym.kind == Kinds.MTH && (i.sym.flags() & Flags.NATIVE) != 0) return true; - for (Attribute.Compound a: i.sym.annotations.getAttributes()) { + for (Attribute.Compound a: i.sym.annotations.getDeclarationAttributes()) { if (a.type.tsym == syms.nativeHeaderType.tsym) return true; } diff --git a/langtools/src/share/classes/com/sun/tools/javac/main/JavaCompiler.java b/langtools/src/share/classes/com/sun/tools/javac/main/JavaCompiler.java index 40fbd22bd25..5bf9d276872 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/main/JavaCompiler.java +++ b/langtools/src/share/classes/com/sun/tools/javac/main/JavaCompiler.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2013, 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 @@ -513,7 +513,7 @@ public class JavaCompiler implements ClassReader.SourceCompleter { */ public CompileState shouldStopPolicyIfNoError; - /** A queue of all as yet unattributed classes.oLo + /** A queue of all as yet unattributed classes. */ public Todo todo; diff --git a/langtools/src/share/classes/com/sun/tools/javac/model/JavacTypes.java b/langtools/src/share/classes/com/sun/tools/javac/model/JavacTypes.java index 83ce128cd35..9d8933daa5c 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/model/JavacTypes.java +++ b/langtools/src/share/classes/com/sun/tools/javac/model/JavacTypes.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2013, 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 @@ -25,9 +25,9 @@ package com.sun.tools.javac.model; +import java.lang.annotation.Annotation; import java.util.Collections; import java.util.EnumSet; -import java.util.HashSet; import java.util.LinkedHashSet; import java.util.List; import java.util.Set; @@ -333,4 +333,28 @@ public class JavacTypes implements javax.lang.model.util.Types { return results; } + + public List typeAnnotationsOf(TypeMirror type) { + // TODO: these methods can be removed. + return null; // ((Type)type).typeAnnotations; + } + + public A typeAnnotationOf(TypeMirror type, + Class annotationType) { + // TODO: these methods can be removed. + return null; // JavacElements.getAnnotation(((Type)type).typeAnnotations, annotationType); + } + + public TypeMirror receiverTypeOf(ExecutableType type) { + return ((Type)type).asMethodType().recvtype; + } + + /* + public A receiverTypeAnnotationOf( + ExecutableType type, Class annotationType) { + return JavacElements.getAnnotation( + ((Type)type).asMethodType().receiverTypeAnnotations, + annotationType); + }*/ + } diff --git a/langtools/src/share/classes/com/sun/tools/javac/parser/JavacParser.java b/langtools/src/share/classes/com/sun/tools/javac/parser/JavacParser.java index 95de4c1756c..52e8e087aa9 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/parser/JavacParser.java +++ b/langtools/src/share/classes/com/sun/tools/javac/parser/JavacParser.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2013, 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 @@ -88,6 +88,41 @@ public class JavacParser implements Parser { /** End position mappings container */ private final AbstractEndPosTable endPosTable; + // Because of javac's limited lookahead, some contexts are ambiguous in + // the presence of type annotations even though they are not ambiguous + // in the absence of type annotations. Consider this code: + // void m(String [] m) { } + // void m(String ... m) { } + // After parsing "String", javac calls bracketsOpt which immediately + // returns if the next character is not '['. Similarly, javac can see + // if the next token is ... and in that case parse an ellipsis. But in + // the presence of type annotations: + // void m(String @A [] m) { } + // void m(String @A ... m) { } + // no finite lookahead is enough to determine whether to read array + // levels or an ellipsis. Furthermore, if you call bracketsOpt, then + // bracketsOpt first reads all the leading annotations and only then + // discovers that it needs to fail. bracketsOpt needs a way to push + // back the extra annotations that it read. (But, bracketsOpt should + // not *always* be allowed to push back extra annotations that it finds + // -- in most contexts, any such extra annotation is an error. + // + // The following two variables permit type annotations that have + // already been read to be stored for later use. Alternate + // implementations are possible but would cause much larger changes to + // the parser. + + /** Type annotations that have already been read but have not yet been used. **/ + private List typeAnnotationsPushedBack = List.nil(); + + /** + * If the parser notices extra annotations, then it either immediately + * issues an error (if this variable is false) or places the extra + * annotations in variable typeAnnotationsPushedBack (if this variable + * is true). + */ + private boolean permitTypeAnnotationsPushBack = false; + interface ErrorRecoveryAction { JCTree doRecover(JavacParser parser); } @@ -126,6 +161,7 @@ public class JavacParser implements Parser { this.allowDefaultMethods = source.allowDefaultMethods(); this.allowStaticInterfaceMethods = source.allowStaticInterfaceMethods(); this.allowIntersectionTypesInCast = source.allowIntersectionTypesInCast(); + this.allowTypeAnnotations = source.allowTypeAnnotations(); this.keepDocComments = keepDocComments; docComments = newDocCommentTable(keepDocComments, fac); this.keepLineMap = keepLineMap; @@ -215,6 +251,20 @@ public class JavacParser implements Parser { */ boolean keepLineMap; + /** Switch: should we recognize type annotations? + */ + boolean allowTypeAnnotations; + + /** Switch: is "this" allowed as an identifier? + * This is needed to parse receiver types. + */ + boolean allowThisIdent; + + /** The type of the method receiver, as specified by a first "this" parameter. + */ + JCVariableDecl receiverParam; + + /** When terms are parsed, the mode determines which is expected: * mode = EXPR : an expression * mode = TYPE : a type @@ -558,6 +608,18 @@ public class JavacParser implements Parser { nextToken(); return name; } + } else if (token.kind == THIS) { + if (allowThisIdent) { + // Make sure we're using a supported source version. + checkTypeAnnotations(); + Name name = token.name(); + nextToken(); + return name; + } else { + error(token.pos, "this.as.identifier"); + nextToken(); + return names.error; + } } else if (token.kind == UNDERSCORE) { warning(token.pos, "underscore.as.identifier"); Name name = token.name(); @@ -570,14 +632,21 @@ public class JavacParser implements Parser { } /** - * Qualident = Ident { DOT Ident } + * Qualident = Ident { DOT [Annotations] Ident } */ - public JCExpression qualident() { + public JCExpression qualident(boolean allowAnnos) { JCExpression t = toP(F.at(token.pos).Ident(ident())); while (token.kind == DOT) { int pos = token.pos; nextToken(); + List tyannos = null; + if (allowAnnos) { + tyannos = typeAnnotationsOpt(); + } t = toP(F.at(pos).Select(t, ident())); + if (tyannos != null && tyannos.nonEmpty()) { + t = toP(F.at(tyannos.head.pos).AnnotatedType(tyannos, t)); + } } return t; } @@ -686,7 +755,7 @@ public class JavacParser implements Parser { nextToken(); return t; } -//where + //where boolean isZero(String s) { char[] cs = s.toCharArray(); int base = ((cs.length > 1 && Character.toLowerCase(cs[1]) == 'x') ? 16 : 10); @@ -706,7 +775,34 @@ public class JavacParser implements Parser { return term(EXPR); } + /** + * parses (optional) type annotations followed by a type. If the + * annotations are present before the type and are not consumed during array + * parsing, this method returns a {@link JCAnnotatedType} consisting of + * these annotations and the underlying type. Otherwise, it returns the + * underlying type. + * + *

+ * + * Note that this method sets {@code mode} to {@code TYPE} first, before + * parsing annotations. + */ public JCExpression parseType() { + List annotations = typeAnnotationsOpt(); + return parseType(annotations); + } + + public JCExpression parseType(List annotations) { + JCExpression result = unannotatedType(); + + if (annotations.nonEmpty()) { + result = insertAnnotationsToMostInner(result, annotations, false); + } + + return result; + } + + public JCExpression unannotatedType() { return term(TYPE); } @@ -864,7 +960,7 @@ public class JavacParser implements Parser { opStackSupply.add(opStack); return t; } -//where + //where /** Construct a binary or type test node. */ private JCExpression makeOp(int pos, @@ -943,9 +1039,9 @@ public class JavacParser implements Parser { * | NEW [TypeArguments] Creator * | "(" Arguments ")" "->" ( Expression | Block ) * | Ident "->" ( Expression | Block ) - * | Ident { "." Ident } + * | [Annotations] Ident { "." [Annotations] Ident } * | Expression3 MemberReferenceSuffix - * [ "[" ( "]" BracketsOpt "." CLASS | Expression "]" ) + * [ [Annotations] "[" ( "]" BracketsOpt "." CLASS | Expression "]" ) * | Arguments * | "." ( CLASS | THIS | [TypeArguments] SUPER Arguments | NEW [TypeArguments] InnerCreator ) * ] @@ -1067,6 +1163,34 @@ public class JavacParser implements Parser { typeArgs = null; } else return illegal(); break; + case MONKEYS_AT: + // Only annotated cast types are valid + List typeAnnos = typeAnnotationsOpt(); + if (typeAnnos.isEmpty()) { + // else there would be no '@' + throw new AssertionError("Expected type annotations, but found none!"); + } + + JCExpression expr = term3(); + + if ((mode & TYPE) == 0) { + // Type annotations on class literals no longer legal + if (!expr.hasTag(Tag.SELECT)) { + return illegal(typeAnnos.head.pos); + } + JCFieldAccess sel = (JCFieldAccess)expr; + + if (sel.name != names._class) { + return illegal(); + } else { + log.error(token.pos, "no.annotations.on.dot.class"); + return expr; + } + } else { + // Type annotations targeting a cast + t = insertAnnotationsToMostInner(expr, typeAnnos, false); + } + break; case UNDERSCORE: case IDENTIFIER: case ASSERT: case ENUM: if (typeArgs != null) return illegal(); if ((mode & EXPR) != 0 && peekToken(ARROW)) { @@ -1075,6 +1199,13 @@ public class JavacParser implements Parser { t = toP(F.at(token.pos).Ident(ident())); loop: while (true) { pos = token.pos; + final List annos = typeAnnotationsOpt(); + + // need to report an error later if LBRACKET is for array + // index access rather than array creation level + if (!annos.isEmpty() && token.kind != LBRACKET && token.kind != ELLIPSIS) + return illegal(annos.head.pos); + switch (token.kind) { case LBRACKET: nextToken(); @@ -1082,11 +1213,23 @@ public class JavacParser implements Parser { nextToken(); t = bracketsOpt(t); t = toP(F.at(pos).TypeArray(t)); - t = bracketsSuffix(t); + if (annos.nonEmpty()) { + t = toP(F.at(pos).AnnotatedType(annos, t)); + } + // .class is only allowed if there were no annotations + JCExpression nt = bracketsSuffix(t); + if (nt != t && (annos.nonEmpty() || TreeInfo.containsTypeAnnotation(t))) { + // t and nt are different if bracketsSuffix parsed a .class. + // The check for nonEmpty covers the case when the whole array is annotated. + // Helper method isAnnotated looks for annos deeply within t. + syntaxError("no.annotations.on.dot.class"); + } + t = nt; } else { if ((mode & EXPR) != 0) { mode = EXPR; JCExpression t1 = term(); + if (!annos.isEmpty()) t = illegal(annos.head.pos); t = to(F.at(pos).Indexed(t, t1)); } accept(RBRACKET); @@ -1096,6 +1239,7 @@ public class JavacParser implements Parser { if ((mode & EXPR) != 0) { mode = EXPR; t = arguments(typeArgs, t); + if (!annos.isEmpty()) t = illegal(annos.head.pos); typeArgs = null; } break loop; @@ -1136,9 +1280,25 @@ public class JavacParser implements Parser { break loop; } } + + List tyannos = null; + if ((mode & TYPE) != 0 && token.kind == MONKEYS_AT) { + tyannos = typeAnnotationsOpt(); + } // typeArgs saved for next loop iteration. t = toP(F.at(pos).Select(t, ident())); + if (tyannos != null && tyannos.nonEmpty()) { + t = toP(F.at(tyannos.head.pos).AnnotatedType(tyannos, t)); + } break; + case ELLIPSIS: + if (this.permitTypeAnnotationsPushBack) { + this.typeAnnotationsPushedBack = annos; + } else if (annos.nonEmpty()) { + // Don't return here -- error recovery attempt + illegal(annos.head.pos); + } + break loop; case LT: if ((mode & TYPE) == 0 && isUnboundMemberRef()) { //this is an unbound method reference whose qualifier @@ -1212,6 +1372,8 @@ public class JavacParser implements Parser { if (typeArgs != null) illegal(); while (true) { int pos1 = token.pos; + final List annos = typeAnnotationsOpt(); + if (token.kind == LBRACKET) { nextToken(); if ((mode & TYPE) != 0) { @@ -1225,6 +1387,9 @@ public class JavacParser implements Parser { mode = EXPR; continue; } + if (annos.nonEmpty()) { + t = toP(F.at(pos1).AnnotatedType(annos, t)); + } return t; } mode = oldmode; @@ -1253,7 +1418,15 @@ public class JavacParser implements Parser { t = innerCreator(pos2, typeArgs, t); typeArgs = null; } else { + List tyannos = null; + if ((mode & TYPE) != 0 && token.kind == MONKEYS_AT) { + // is the mode check needed? + tyannos = typeAnnotationsOpt(); + } t = toP(F.at(pos1).Select(t, ident())); + if (tyannos != null && tyannos.nonEmpty()) { + t = toP(F.at(tyannos.head.pos).AnnotatedType(tyannos, t)); + } t = argumentsOpt(typeArgs, typeArgumentsOpt(t)); typeArgs = null; } @@ -1263,6 +1436,12 @@ public class JavacParser implements Parser { accept(COLCOL); t = memberReferenceSuffix(pos1, t); } else { + if (!annos.isEmpty()) { + if (permitTypeAnnotationsPushBack) + typeAnnotationsPushedBack = annos; + else + return illegal(annos.head.pos); + } break; } } @@ -1321,7 +1500,7 @@ public class JavacParser implements Parser { ParensResult analyzeParens() { int depth = 0; boolean type = false; - for (int lookahead = 0 ; ; lookahead++) { + outer: for (int lookahead = 0 ; ; lookahead++) { TokenKind tk = S.token(lookahead).kind; switch (tk) { case EXTENDS: case SUPER: case COMMA: @@ -1382,9 +1561,36 @@ public class JavacParser implements Parser { break; case FINAL: case ELLIPSIS: - case MONKEYS_AT: //those can only appear in explicit lambdas return ParensResult.EXPLICIT_LAMBDA; + case MONKEYS_AT: + type = true; + lookahead += 1; //skip '@' + while (peekToken(lookahead, DOT)) { + lookahead += 2; + } + if (peekToken(lookahead, LPAREN)) { + lookahead++; + //skip annotation values + int nesting = 0; + for (; ; lookahead++) { + TokenKind tk2 = S.token(lookahead).kind; + switch (tk2) { + case EOF: + return ParensResult.PARENS; + case LPAREN: + nesting++; + break; + case RPAREN: + nesting--; + if (nesting == 0) { + continue outer; + } + break; + } + } + } + break; case LBRACKET: if (peekToken(lookahead, RBRACKET, LAX_IDENTIFIER)) { // '[', ']', Identifier/'_'/'assert'/'enum' -> explicit lambda @@ -1618,25 +1824,27 @@ public class JavacParser implements Parser { /** * {@literal * TypeArgument = Type - * | "?" - * | "?" EXTENDS Type {"&" Type} - * | "?" SUPER Type + * | [Annotations] "?" + * | [Annotations] "?" EXTENDS Type {"&" Type} + * | [Annotations] "?" SUPER Type * } */ JCExpression typeArgument() { - if (token.kind != QUES) return parseType(); + List annotations = typeAnnotationsOpt(); + if (token.kind != QUES) return parseType(annotations); int pos = token.pos; nextToken(); + JCExpression result; if (token.kind == EXTENDS) { TypeBoundKind t = to(F.at(pos).TypeBoundKind(BoundKind.EXTENDS)); nextToken(); JCExpression bound = parseType(); - return F.at(pos).Wildcard(t, bound); + result = F.at(pos).Wildcard(t, bound); } else if (token.kind == SUPER) { TypeBoundKind t = to(F.at(pos).TypeBoundKind(BoundKind.SUPER)); nextToken(); JCExpression bound = parseType(); - return F.at(pos).Wildcard(t, bound); + result = F.at(pos).Wildcard(t, bound); } else if (LAX_IDENTIFIER.accepts(token.kind)) { //error recovery TypeBoundKind t = F.at(Position.NOPOS).TypeBoundKind(BoundKind.UNBOUND); @@ -1644,11 +1852,15 @@ public class JavacParser implements Parser { JCIdent id = toP(F.at(token.pos).Ident(ident())); JCErroneous err = F.at(pos).Erroneous(List.of(wc, id)); reportSyntaxError(err, "expected3", GT, EXTENDS, SUPER); - return err; + result = err; } else { TypeBoundKind t = toP(F.at(pos).TypeBoundKind(BoundKind.UNBOUND)); - return toP(F.at(pos).Wildcard(t, null)); + result = toP(F.at(pos).Wildcard(t, null)); } + if (!annotations.isEmpty()) { + result = toP(F.at(annotations.head.pos).AnnotatedType(annotations,result)); + } + return result; } JCTypeApply typeArguments(JCExpression t, boolean diamondAllowed) { @@ -1657,22 +1869,51 @@ public class JavacParser implements Parser { return toP(F.at(pos).TypeApply(t, args)); } - /** BracketsOpt = {"[" "]"} + /** + * BracketsOpt = { [Annotations] "[" "]" }* + * + *

+ * + * annotations is the list of annotations targeting + * the expression t. */ - private JCExpression bracketsOpt(JCExpression t) { + private JCExpression bracketsOpt(JCExpression t, + List annotations) { + List nextLevelAnnotations = typeAnnotationsOpt(); + if (token.kind == LBRACKET) { int pos = token.pos; nextToken(); - t = bracketsOptCont(t, pos); - F.at(pos); + t = bracketsOptCont(t, pos, nextLevelAnnotations); + } else if (!nextLevelAnnotations.isEmpty()) { + if (permitTypeAnnotationsPushBack) { + this.typeAnnotationsPushedBack = nextLevelAnnotations; + } else { + return illegal(nextLevelAnnotations.head.pos); + } + } + + if (!annotations.isEmpty()) { + t = toP(F.at(token.pos).AnnotatedType(annotations, t)); } return t; } - private JCArrayTypeTree bracketsOptCont(JCExpression t, int pos) { + /** BracketsOpt = [ "[" "]" { [Annotations] "[" "]"} ] + */ + private JCExpression bracketsOpt(JCExpression t) { + return bracketsOpt(t, List.nil()); + } + + private JCExpression bracketsOptCont(JCExpression t, int pos, + List annotations) { accept(RBRACKET); t = bracketsOpt(t); - return toP(F.at(pos).TypeArray(t)); + t = toP(F.at(pos).TypeArray(t)); + if (annotations.nonEmpty()) { + t = toP(F.at(pos).AnnotatedType(annotations, t)); + } + return t; } /** BracketsSuffixExpr = "." CLASS @@ -1686,7 +1927,7 @@ public class JavacParser implements Parser { accept(CLASS); if (token.pos == endPosTable.errorEndPos) { // error recovery - Name name = null; + Name name; if (LAX_IDENTIFIER.accepts(token.kind)) { name = token.name(); nextToken(); @@ -1724,8 +1965,8 @@ public class JavacParser implements Parser { if (token.kind == LT) { typeArgs = typeArguments(false); } - Name refName = null; - ReferenceMode refMode = null; + Name refName; + ReferenceMode refMode; if (token.kind == NEW) { refMode = ReferenceMode.NEW; refName = names.init; @@ -1737,18 +1978,31 @@ public class JavacParser implements Parser { return toP(F.at(t.getStartPosition()).Reference(refMode, refName, t, typeArgs)); } - /** Creator = Qualident [TypeArguments] ( ArrayCreatorRest | ClassCreatorRest ) + /** Creator = [Annotations] Qualident [TypeArguments] ( ArrayCreatorRest | ClassCreatorRest ) */ JCExpression creator(int newpos, List typeArgs) { + List newAnnotations = typeAnnotationsOpt(); + switch (token.kind) { case BYTE: case SHORT: case CHAR: case INT: case LONG: case FLOAT: case DOUBLE: case BOOLEAN: - if (typeArgs == null) - return arrayCreatorRest(newpos, basicType()); + if (typeArgs == null) { + if (newAnnotations.isEmpty()) { + return arrayCreatorRest(newpos, basicType()); + } else { + return arrayCreatorRest(newpos, toP(F.at(newAnnotations.head.pos).AnnotatedType(newAnnotations, basicType()))); + } + } break; default: } - JCExpression t = qualident(); + JCExpression t = qualident(true); + + // handle type annotations for non primitive arrays + if (newAnnotations.nonEmpty()) { + t = insertAnnotationsToMostInner(t, newAnnotations, false); + } + int oldmode = mode; mode = TYPE; boolean diamondFound = false; @@ -1766,7 +2020,13 @@ public class JavacParser implements Parser { } int pos = token.pos; nextToken(); + List tyannos = typeAnnotationsOpt(); t = toP(F.at(pos).Select(t, ident())); + + if (tyannos != null && tyannos.nonEmpty()) { + t = toP(F.at(tyannos.head.pos).AnnotatedType(tyannos, t)); + } + if (token.kind == LT) { lastTypeargsPos = token.pos; checkGenerics(); @@ -1775,7 +2035,7 @@ public class JavacParser implements Parser { } } mode = oldmode; - if (token.kind == LBRACKET) { + if (token.kind == LBRACKET || token.kind == MONKEYS_AT) { JCExpression e = arrayCreatorRest(newpos, t); if (diamondFound) { reportSyntaxError(lastTypeargsPos, "cannot.create.array.with.diamond"); @@ -1796,7 +2056,15 @@ public class JavacParser implements Parser { } return e; } else if (token.kind == LPAREN) { - return classCreatorRest(newpos, null, typeArgs, t); + JCNewClass newClass = classCreatorRest(newpos, null, typeArgs, t); + if (newClass.def != null) { + assert newClass.def.mods.annotations.isEmpty(); + if (newAnnotations.nonEmpty()) { + newClass.def.mods.pos = earlier(newClass.def.mods.pos, newAnnotations.head.pos); + newClass.def.mods.annotations = List.convert(JCAnnotation.class, newAnnotations); + } + } + return newClass; } else { setErrorEndPos(token.pos); reportSyntaxError(token.pos, "expected2", LPAREN, LBRACKET); @@ -1805,10 +2073,17 @@ public class JavacParser implements Parser { } } - /** InnerCreator = Ident [TypeArguments] ClassCreatorRest + /** InnerCreator = [Annotations] Ident [TypeArguments] ClassCreatorRest */ JCExpression innerCreator(int newpos, List typeArgs, JCExpression encl) { + List newAnnotations = typeAnnotationsOpt(); + JCExpression t = toP(F.at(token.pos).Ident(ident())); + + if (newAnnotations.nonEmpty()) { + t = toP(F.at(newAnnotations.head.pos).AnnotatedType(newAnnotations, t)); + } + if (token.kind == LT) { int oldmode = mode; checkGenerics(); @@ -1818,35 +2093,65 @@ public class JavacParser implements Parser { return classCreatorRest(newpos, encl, typeArgs, t); } - /** ArrayCreatorRest = "[" ( "]" BracketsOpt ArrayInitializer - * | Expression "]" {"[" Expression "]"} BracketsOpt ) + /** ArrayCreatorRest = [Annotations] "[" ( "]" BracketsOpt ArrayInitializer + * | Expression "]" {[Annotations] "[" Expression "]"} BracketsOpt ) */ JCExpression arrayCreatorRest(int newpos, JCExpression elemtype) { + List annos = typeAnnotationsOpt(); + accept(LBRACKET); if (token.kind == RBRACKET) { accept(RBRACKET); - elemtype = bracketsOpt(elemtype); + elemtype = bracketsOpt(elemtype, annos); if (token.kind == LBRACE) { - return arrayInitializer(newpos, elemtype); + JCNewArray na = (JCNewArray)arrayInitializer(newpos, elemtype); + if (annos.nonEmpty()) { + // when an array initializer is present then + // the parsed annotations should target the + // new array tree + // bracketsOpt inserts the annotation in + // elemtype, and it needs to be corrected + // + JCAnnotatedType annotated = (JCAnnotatedType)elemtype; + assert annotated.annotations == annos; + na.annotations = annotated.annotations; + na.elemtype = annotated.underlyingType; + } + return na; } else { JCExpression t = toP(F.at(newpos).NewArray(elemtype, List.nil(), null)); return syntaxError(token.pos, List.of(t), "array.dimension.missing"); } } else { ListBuffer dims = new ListBuffer(); + + // maintain array dimension type annotations + ListBuffer> dimAnnotations = ListBuffer.lb(); + dimAnnotations.append(annos); + dims.append(parseExpression()); accept(RBRACKET); - while (token.kind == LBRACKET) { + while (token.kind == LBRACKET + || token.kind == MONKEYS_AT) { + List maybeDimAnnos = typeAnnotationsOpt(); int pos = token.pos; nextToken(); if (token.kind == RBRACKET) { - elemtype = bracketsOptCont(elemtype, pos); + elemtype = bracketsOptCont(elemtype, pos, maybeDimAnnos); } else { - dims.append(parseExpression()); - accept(RBRACKET); + if (token.kind == RBRACKET) { // no dimension + elemtype = bracketsOptCont(elemtype, pos, maybeDimAnnos); + } else { + dimAnnotations.append(maybeDimAnnos); + dims.append(parseExpression()); + accept(RBRACKET); + } } } - return toP(F.at(newpos).NewArray(elemtype, dims.toList(), null)); + + JCNewArray na = toP(F.at(newpos).NewArray(elemtype, dims.toList(), null)); + na.dimAnnotations = dimAnnotations.toList(); + return na; } } @@ -2254,6 +2559,7 @@ public class JavacParser implements Parser { } /** CatchClause = CATCH "(" FormalParameter ")" Block + * TODO: the "FormalParameter" is not correct, it uses the special "catchTypes" rule below. */ protected JCCatch catchClause() { int pos = token.pos; @@ -2276,7 +2582,9 @@ public class JavacParser implements Parser { while (token.kind == BAR) { checkMulticatch(); nextToken(); - catchTypes.add(qualident()); + // Instead of qualident this is now parseType. + // But would that allow too much, e.g. arrays or generics? + catchTypes.add(parseType()); } return catchTypes.toList(); } @@ -2377,16 +2685,28 @@ public class JavacParser implements Parser { } /** AnnotationsOpt = { '@' Annotation } + * + * @param kind Whether to parse an ANNOTATION or TYPE_ANNOTATION */ - List annotationsOpt() { + List annotationsOpt(Tag kind) { if (token.kind != MONKEYS_AT) return List.nil(); // optimization ListBuffer buf = new ListBuffer(); + int prevmode = mode; while (token.kind == MONKEYS_AT) { int pos = token.pos; nextToken(); - buf.append(annotation(pos)); + buf.append(annotation(pos, kind)); } - return buf.toList(); + lastmode = mode; + mode = prevmode; + List annotations = buf.toList(); + + return annotations; + } + + List typeAnnotationsOpt() { + List annotations = annotationsOpt(Tag.TYPE_ANNOTATION); + return annotations; } /** ModifiersOpt = { Modifier } @@ -2412,7 +2732,7 @@ public class JavacParser implements Parser { if (token.deprecatedFlag()) { flags |= Flags.DEPRECATED; } - int lastPos = Position.NOPOS; + int lastPos; loop: while (true) { long flag; @@ -2439,12 +2759,11 @@ public class JavacParser implements Parser { if (flag == Flags.ANNOTATION) { checkAnnotations(); if (token.kind != INTERFACE) { - JCAnnotation ann = annotation(lastPos); + JCAnnotation ann = annotation(lastPos, Tag.ANNOTATION); // if first modifier is an annotation, set pos to annotation's. if (flags == 0 && annotations.isEmpty()) pos = ann.pos; annotations.append(ann); - lastPos = ann.pos; flag = 0; } } @@ -2468,14 +2787,27 @@ public class JavacParser implements Parser { } /** Annotation = "@" Qualident [ "(" AnnotationFieldValues ")" ] + * * @param pos position of "@" token + * @param kind Whether to parse an ANNOTATION or TYPE_ANNOTATION */ - JCAnnotation annotation(int pos) { + JCAnnotation annotation(int pos, Tag kind) { // accept(AT); // AT consumed by caller checkAnnotations(); - JCTree ident = qualident(); + if (kind == Tag.TYPE_ANNOTATION) { + checkTypeAnnotations(); + } + JCTree ident = qualident(false); List fieldValues = annotationFieldValuesOpt(); - JCAnnotation ann = F.at(pos).Annotation(ident, fieldValues); + JCAnnotation ann; + if (kind == Tag.ANNOTATION) { + ann = F.at(pos).Annotation(ident, fieldValues); + } else if (kind == Tag.TYPE_ANNOTATION) { + ann = F.at(pos).TypeAnnotation(ident, fieldValues); + } else { + throw new AssertionError("Unhandled annotation kind: " + kind); + } + storeEnd(ann, S.prevToken().endPos); return ann; } @@ -2528,7 +2860,7 @@ public class JavacParser implements Parser { case MONKEYS_AT: pos = token.pos; nextToken(); - return annotation(pos); + return annotation(pos, Tag.ANNOTATION); case LBRACE: pos = token.pos; accept(LBRACE); @@ -2683,7 +3015,7 @@ public class JavacParser implements Parser { mods = null; } nextToken(); - pid = qualident(); + pid = qualident(false); accept(SEMI); } ListBuffer defs = new ListBuffer(); @@ -2934,7 +3266,7 @@ public class JavacParser implements Parser { flags |= Flags.DEPRECATED; } int pos = token.pos; - List annotations = annotationsOpt(); + List annotations = annotationsOpt(Tag.ANNOTATION); JCModifiers mods = F.at(annotations.isEmpty() ? Position.NOPOS : pos).Modifiers(flags, annotations); List typeArgs = typeArgumentsOpt(); int identPos = token.pos; @@ -3037,15 +3369,25 @@ public class JavacParser implements Parser { mods.pos = pos; storeEnd(mods, pos); } + List annosAfterParams = annotationsOpt(Tag.ANNOTATION); + Token tk = token; pos = token.pos; JCExpression type; boolean isVoid = token.kind == VOID; if (isVoid) { + if (annosAfterParams.nonEmpty()) + illegal(annosAfterParams.head.pos); type = to(F.at(pos).TypeIdent(TypeTag.VOID)); nextToken(); } else { - type = parseType(); + if (annosAfterParams.nonEmpty()) { + mods.annotations = mods.annotations.appendList(annosAfterParams); + if (mods.pos == Position.NOPOS) + mods.pos = mods.annotations.head.pos; + } + // method returns types are un-annotated types + type = unannotatedType(); } if (token.kind == LPAREN && !isInterface && type.hasTag(IDENT)) { if (isInterface || tk.name() != className) @@ -3101,51 +3443,68 @@ public class JavacParser implements Parser { if (isInterface && (mods.flags & Flags.STATIC) != 0) { checkStaticInterfaceMethods(); } - List params = formalParameters(); - if (!isVoid) type = bracketsOpt(type); - List thrown = List.nil(); - if (token.kind == THROWS) { - nextToken(); - thrown = qualidentList(); - } - JCBlock body = null; - JCExpression defaultValue; - if (token.kind == LBRACE) { - body = block(); - defaultValue = null; - } else { - if (token.kind == DEFAULT) { - accept(DEFAULT); - defaultValue = annotationValue(); - } else { - defaultValue = null; + JCVariableDecl prevReceiverParam = this.receiverParam; + try { + this.receiverParam = null; + // Parsing formalParameters sets the receiverParam, if present + List params = formalParameters(); + if (!isVoid) type = bracketsOpt(type); + List thrown = List.nil(); + if (token.kind == THROWS) { + nextToken(); + thrown = qualidentList(); } - accept(SEMI); - if (token.pos <= endPosTable.errorEndPos) { - // error recovery - skip(false, true, false, false); - if (token.kind == LBRACE) { - body = block(); + JCBlock body = null; + JCExpression defaultValue; + if (token.kind == LBRACE) { + body = block(); + defaultValue = null; + } else { + if (token.kind == DEFAULT) { + accept(DEFAULT); + defaultValue = annotationValue(); + } else { + defaultValue = null; + } + accept(SEMI); + if (token.pos <= endPosTable.errorEndPos) { + // error recovery + skip(false, true, false, false); + if (token.kind == LBRACE) { + body = block(); + } } } - } - JCMethodDecl result = - toP(F.at(pos).MethodDef(mods, name, type, typarams, - params, thrown, - body, defaultValue)); - attach(result, dc); - return result; + JCMethodDecl result = + toP(F.at(pos).MethodDef(mods, name, type, typarams, + receiverParam, params, thrown, + body, defaultValue)); + attach(result, dc); + return result; + } finally { + this.receiverParam = prevReceiverParam; + } } - /** QualidentList = Qualident {"," Qualident} + /** QualidentList = [Annotations] Qualident {"," [Annotations] Qualident} */ List qualidentList() { ListBuffer ts = new ListBuffer(); - ts.append(qualident()); + + List typeAnnos = typeAnnotationsOpt(); + if (!typeAnnos.isEmpty()) + ts.append(toP(F.at(typeAnnos.head.pos).AnnotatedType(typeAnnos, qualident(true)))); + else + ts.append(qualident(true)); while (token.kind == COMMA) { nextToken(); - ts.append(qualident()); + + typeAnnos = typeAnnotationsOpt(); + if (!typeAnnos.isEmpty()) + ts.append(toP(F.at(typeAnnos.head.pos).AnnotatedType(typeAnnos, qualident(true)))); + else + ts.append(qualident(true)); } return ts.toList(); } @@ -3174,13 +3533,14 @@ public class JavacParser implements Parser { /** * {@literal - * TypeParameter = TypeVariable [TypeParameterBound] + * TypeParameter = [Annotations] TypeVariable [TypeParameterBound] * TypeParameterBound = EXTENDS Type {"&" Type} * TypeVariable = Ident * } */ JCTypeParameter typeParameter() { int pos = token.pos; + List annos = typeAnnotationsOpt(); Name name = ident(); ListBuffer bounds = new ListBuffer(); if (token.kind == EXTENDS) { @@ -3191,7 +3551,7 @@ public class JavacParser implements Parser { bounds.append(parseType()); } } - return toP(F.at(pos).TypeParameter(name, bounds.toList())); + return toP(F.at(pos).TypeParameter(name, bounds.toList(), annos)); } /** FormalParameters = "(" [ FormalParameterList ] ")" @@ -3203,10 +3563,17 @@ public class JavacParser implements Parser { } List formalParameters(boolean lambdaParameters) { ListBuffer params = new ListBuffer(); - JCVariableDecl lastParam = null; + JCVariableDecl lastParam; accept(LPAREN); if (token.kind != RPAREN) { - params.append(lastParam = formalParameter(lambdaParameters)); + this.allowThisIdent = true; + lastParam = formalParameter(lambdaParameters); + if (lastParam.name.contentEquals(TokenKind.THIS.name)) { + this.receiverParam = lastParam; + } else { + params.append(lastParam); + } + this.allowThisIdent = false; while ((lastParam.mods.flags & Flags.VARARGS) == 0 && token.kind == COMMA) { nextToken(); params.append(lastParam = formalParameter(lambdaParameters)); @@ -3241,6 +3608,77 @@ public class JavacParser implements Parser { return mods; } + /** + * Inserts the annotations (and possibly a new array level) + * to the left-most type in an array or nested type. + * + * When parsing a type like {@code @B Outer.Inner @A []}, the + * {@code @A} annotation should target the array itself, while + * {@code @B} targets the nested type {@code Outer}. + * + * Currently the parser parses the annotation first, then + * the array, and then inserts the annotation to the left-most + * nested type. + * + * When {@code createNewLevel} is true, then a new array + * level is inserted as the most inner type, and have the + * annotations target it. This is useful in the case of + * varargs, e.g. {@code String @A [] @B ...}, as the parser + * first parses the type {@code String @A []} then inserts + * a new array level with {@code @B} annotation. + */ + private JCExpression insertAnnotationsToMostInner( + JCExpression type, List annos, + boolean createNewLevel) { + int origEndPos = getEndPos(type); + JCExpression mostInnerType = type; + JCArrayTypeTree mostInnerArrayType = null; + while (TreeInfo.typeIn(mostInnerType).hasTag(TYPEARRAY)) { + mostInnerArrayType = (JCArrayTypeTree) TreeInfo.typeIn(mostInnerType); + mostInnerType = mostInnerArrayType.elemtype; + } + + if (createNewLevel) { + mostInnerType = to(F.at(token.pos).TypeArray(mostInnerType)); + } + + JCExpression mostInnerTypeToReturn = mostInnerType; + if (annos.nonEmpty()) { + JCExpression lastToModify = mostInnerType; + + while (TreeInfo.typeIn(mostInnerType).hasTag(SELECT) || + TreeInfo.typeIn(mostInnerType).hasTag(TYPEAPPLY)) { + while (TreeInfo.typeIn(mostInnerType).hasTag(SELECT)) { + lastToModify = mostInnerType; + mostInnerType = ((JCFieldAccess) TreeInfo.typeIn(mostInnerType)).getExpression(); + } + while (TreeInfo.typeIn(mostInnerType).hasTag(TYPEAPPLY)) { + lastToModify = mostInnerType; + mostInnerType = ((JCTypeApply) TreeInfo.typeIn(mostInnerType)).clazz; + } + } + + mostInnerType = F.at(annos.head.pos).AnnotatedType(annos, mostInnerType); + + if (TreeInfo.typeIn(lastToModify).hasTag(TYPEAPPLY)) { + ((JCTypeApply) TreeInfo.typeIn(lastToModify)).clazz = mostInnerType; + } else if (TreeInfo.typeIn(lastToModify).hasTag(SELECT)) { + ((JCFieldAccess) TreeInfo.typeIn(lastToModify)).selected = mostInnerType; + } else { + // We never saw a SELECT or TYPEAPPLY, return the annotated type. + mostInnerTypeToReturn = mostInnerType; + } + } + + if (mostInnerArrayType == null) { + return mostInnerTypeToReturn; + } else { + mostInnerArrayType.elemtype = mostInnerTypeToReturn; + storeEnd(type, origEndPos); + return type; + } + } + /** FormalParameter = { FINAL | '@' Annotation } Type VariableDeclaratorId * LastFormalParameter = { FINAL | '@' Annotation } Type '...' Ident | FormalParameter */ @@ -3249,12 +3687,27 @@ public class JavacParser implements Parser { } protected JCVariableDecl formalParameter(boolean lambdaParameter) { JCModifiers mods = optFinal(Flags.PARAMETER); + // need to distinguish between vararg annos and array annos + // look at typeAnnotationsPushedBack comment + this.permitTypeAnnotationsPushBack = true; JCExpression type = parseType(); + this.permitTypeAnnotationsPushBack = false; + if (token.kind == ELLIPSIS) { + List varargsAnnos = typeAnnotationsPushedBack; + typeAnnotationsPushedBack = List.nil(); checkVarargs(); mods.flags |= Flags.VARARGS; - type = to(F.at(token.pos).TypeArray(type)); + // insert var arg type annotations + type = insertAnnotationsToMostInner(type, varargsAnnos, true); nextToken(); + } else { + // if not a var arg, then typeAnnotationsPushedBack should be null + if (typeAnnotationsPushedBack.nonEmpty()) { + reportSyntaxError(typeAnnotationsPushedBack.head.pos, + "illegal.start.of.type"); + } + typeAnnotationsPushedBack = List.nil(); } return variableDeclaratorId(mods, type, lambdaParameter); } @@ -3508,6 +3961,12 @@ public class JavacParser implements Parser { allowStaticInterfaceMethods = true; } } + void checkTypeAnnotations() { + if (!allowTypeAnnotations) { + log.error(token.pos, "type.annotations.not.supported.in.source", source.name); + allowTypeAnnotations = true; + } + } /* * a functional source tree and end position mappings diff --git a/langtools/src/share/classes/com/sun/tools/javac/parser/Scanner.java b/langtools/src/share/classes/com/sun/tools/javac/parser/Scanner.java index 20c49e6cfc2..8a813f0e9de 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/parser/Scanner.java +++ b/langtools/src/share/classes/com/sun/tools/javac/parser/Scanner.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2013, 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 @@ -59,6 +59,7 @@ public class Scanner implements Lexer { private List savedTokens = new ArrayList(); private JavaTokenizer tokenizer; + /** * Create a scanner from the input array. This method might * modify the array. To avoid copying the input array, ensure diff --git a/langtools/src/share/classes/com/sun/tools/javac/parser/UnicodeReader.java b/langtools/src/share/classes/com/sun/tools/javac/parser/UnicodeReader.java index 84e6792cdd1..8b308c5834a 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/parser/UnicodeReader.java +++ b/langtools/src/share/classes/com/sun/tools/javac/parser/UnicodeReader.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2013, 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 @@ -38,7 +38,7 @@ import static com.sun.tools.javac.util.LayoutCharacters.*; /** The char reader used by the javac lexer/tokenizer. Returns the sequence of * characters contained in the input stream, handling unicode escape accordingly. - * Additionally, it provide features for saving chars into a buffer and to retrieve + * Additionally, it provides features for saving chars into a buffer and to retrieve * them at a later stage. * *

This is NOT part of any supported API. diff --git a/langtools/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java b/langtools/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java index 498ca34b415..d71184d5157 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java +++ b/langtools/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2013, 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 @@ -817,9 +817,6 @@ public class JavacProcessingEnvironment implements ProcessingEnvironment, Closea /** The set of package-info files to be processed this round. */ List packageInfoFiles; - /** The number of Messager errors generated in this round. */ - int nMessagerErrors; - /** Create a round (common code). */ private Round(Context context, int number, int priorErrors, int priorWarnings, Log.DeferredDiagnosticHandler deferredDiagnosticHandler) { @@ -829,7 +826,7 @@ public class JavacProcessingEnvironment implements ProcessingEnvironment, Closea compiler = JavaCompiler.instance(context); log = Log.instance(context); log.nerrors = priorErrors; - log.nwarnings += priorWarnings; + log.nwarnings = priorWarnings; if (number == 1) { Assert.checkNonNull(deferredDiagnosticHandler); this.deferredDiagnosticHandler = deferredDiagnosticHandler; @@ -870,7 +867,7 @@ public class JavacProcessingEnvironment implements ProcessingEnvironment, Closea Set newSourceFiles, Map newClassFiles) { this(prev.nextContext(), prev.number+1, - prev.nMessagerErrors, + prev.compiler.log.nerrors, prev.compiler.log.nwarnings, null); this.genClassFiles = prev.genClassFiles; @@ -911,15 +908,12 @@ public class JavacProcessingEnvironment implements ProcessingEnvironment, Closea } /** Create the compiler to be used for the final compilation. */ - JavaCompiler finalCompiler(boolean errorStatus) { + JavaCompiler finalCompiler() { try { Context nextCtx = nextContext(); JavacProcessingEnvironment.this.context = nextCtx; JavaCompiler c = JavaCompiler.instance(nextCtx); - c.log.nwarnings += compiler.log.nwarnings; - if (errorStatus) { - c.log.nerrors += compiler.log.nerrors; - } + c.log.initRound(compiler.log); return c; } finally { compiler.close(false); @@ -1027,8 +1021,6 @@ public class JavacProcessingEnvironment implements ProcessingEnvironment, Closea if (!taskListener.isEmpty()) taskListener.finished(new TaskEvent(TaskEvent.Kind.ANNOTATION_PROCESSING_ROUND)); } - - nMessagerErrors = messager.errorCount(); } void showDiagnostics(boolean showAll) { @@ -1107,9 +1099,7 @@ public class JavacProcessingEnvironment implements ProcessingEnvironment, Closea next.put(Tokens.tokensKey, tokens); Log nextLog = Log.instance(next); - // propogate the log's writers directly, instead of going through context - nextLog.setWriters(log); - nextLog.setSourceMap(log); + nextLog.initRound(log); JavaCompiler oldCompiler = JavaCompiler.instance(context); JavaCompiler nextCompiler = JavaCompiler.instance(next); @@ -1206,7 +1196,7 @@ public class JavacProcessingEnvironment implements ProcessingEnvironment, Closea new LinkedHashSet(filer.getGeneratedSourceFileObjects()); roots = cleanTrees(round.roots); - JavaCompiler compiler = round.finalCompiler(errorStatus); + JavaCompiler compiler = round.finalCompiler(); if (newSourceFiles.size() > 0) roots = roots.appendList(compiler.parseFiles(newSourceFiles)); @@ -1311,7 +1301,6 @@ public class JavacProcessingEnvironment implements ProcessingEnvironment, Closea if (procNames != null) return true; - String procPath; URL[] urls = new URL[1]; for(File pathElement : workingpath) { try { @@ -1382,6 +1371,10 @@ public class JavacProcessingEnvironment implements ProcessingEnvironment, Closea node.sym = null; super.visitIdent(node); } + public void visitAnnotation(JCAnnotation node) { + node.attribute = null; + super.visitAnnotation(node); + } }; diff --git a/langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties b/langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties index ec60b811201..5161bedb3b4 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties +++ b/langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties @@ -1666,6 +1666,9 @@ compiler.misc.bad.const.pool.tag.at=\ compiler.misc.bad.signature=\ bad signature: {0} +compiler.misc.bad.type.annotation.value=\ + bad type annotation target type value: {0} + compiler.misc.class.file.wrong.class=\ class file contains wrong class: {0} @@ -2149,6 +2152,23 @@ compiler.err.assert.as.identifier=\ as of release 1.4, ''assert'' is a keyword, and may not be used as an identifier\n\ (use -source 1.3 or lower to use ''assert'' as an identifier) +# TODO 308: make a better error message +compiler.err.this.as.identifier=\ + as of release 8, ''this'' is allowed as the parameter name for the receiver type only, which has to be the first parameter + +# TODO 308: make a better error message +compiler.err.cant.annotate.static.class=\ + enclosing static nested class cannot be annotated +# TODO 308: make a better error message +compiler.err.cant.annotate.nested.type=\ + nested type cannot be annotated + +compiler.err.incorrect.receiver.type=\ + the receiver type does not match the enclosing class type + +compiler.err.no.annotations.on.dot.class=\ + no annotations are allowed in the type of a class literal + # 0: string compiler.err.generics.not.supported.in.source=\ generics are not supported in -source {0}\n\ @@ -2164,9 +2184,10 @@ compiler.err.annotations.not.supported.in.source=\ annotations are not supported in -source {0}\n\ (use -source 5 or higher to enable annotations) -#308 compiler.err.type.annotations.not.supported.in.source=\ -#308 type annotations are not supported in -source {0}\n\ -#308 (use -source 7 or higher to enable type annotations) +# 0: string +compiler.err.type.annotations.not.supported.in.source=\ + type annotations are not supported in -source {0}\n\ +(use -source 8 or higher to enable type annotations) # 0: string compiler.err.foreach.not.supported.in.source=\ diff --git a/langtools/src/share/classes/com/sun/tools/javac/resources/compiler_ja.properties b/langtools/src/share/classes/com/sun/tools/javac/resources/compiler_ja.properties index 890ae3f9597..6f1096aeab2 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/resources/compiler_ja.properties +++ b/langtools/src/share/classes/com/sun/tools/javac/resources/compiler_ja.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 1999, 2013, 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 @@ -1340,6 +1340,10 @@ compiler.err.enum.as.identifier=\u30EA\u30EA\u30FC\u30B95\u304B\u3089''enum''\u3 compiler.err.assert.as.identifier=\u30EA\u30EA\u30FC\u30B91.4\u304B\u3089''assert''\u306F\u30AD\u30FC\u30EF\u30FC\u30C9\u306A\u306E\u3067\u3001\u8B58\u5225\u5B50\u3068\u3057\u3066\u4F7F\u7528\u3059\u308B\u3053\u3068\u306F\u3067\u304D\u307E\u305B\u3093\n(''assert''\u3092\u8B58\u5225\u5B50\u3068\u3057\u3066\u4F7F\u7528\u3059\u308B\u306B\u306F\u3001-source 1.3\u4EE5\u524D\u3092\u4F7F\u7528\u3057\u3066\u304F\u3060\u3055\u3044) +# TODO 308: make a better error message +# compiler.err.this.as.identifier=\ +# as of release 8, ''this'' is allowed as the parameter name for the receiver type only, which has to be the first parameter + # 0: string compiler.err.generics.not.supported.in.source=\u7DCF\u79F0\u578B\u306F-source {0}\u3067\u30B5\u30DD\u30FC\u30C8\u3055\u308C\u3066\u3044\u307E\u305B\u3093\n(\u7DCF\u79F0\u578B\u3092\u4F7F\u7528\u53EF\u80FD\u306B\u3059\u308B\u306B\u306F\u3001-source 5\u4EE5\u964D\u3092\u4F7F\u7528\u3057\u3066\u304F\u3060\u3055\u3044) @@ -1351,7 +1355,7 @@ compiler.err.annotations.not.supported.in.source=\u6CE8\u91C8\u306F-source {0}\u #308 compiler.err.type.annotations.not.supported.in.source=\ #308 type annotations are not supported in -source {0}\n\ -#308 (use -source 7 or higher to enable type annotations) +#308 (use -source 8 or higher to enable type annotations) # 0: string compiler.err.foreach.not.supported.in.source=for-each\u30EB\u30FC\u30D7\u306F-source {0}\u3067\u30B5\u30DD\u30FC\u30C8\u3055\u308C\u3066\u3044\u307E\u305B\u3093\n(for-each\u30EB\u30FC\u30D7\u3092\u4F7F\u7528\u53EF\u80FD\u306B\u3059\u308B\u306B\u306F\u3001-source 5\u4EE5\u964D\u3092\u4F7F\u7528\u3057\u3066\u304F\u3060\u3055\u3044) diff --git a/langtools/src/share/classes/com/sun/tools/javac/resources/compiler_zh_CN.properties b/langtools/src/share/classes/com/sun/tools/javac/resources/compiler_zh_CN.properties index 9ede9a363ba..005bc3b3e69 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/resources/compiler_zh_CN.properties +++ b/langtools/src/share/classes/com/sun/tools/javac/resources/compiler_zh_CN.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 1999, 2013, 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 @@ -1340,6 +1340,10 @@ compiler.err.enum.as.identifier=\u4ECE\u53D1\u884C\u7248 5 \u5F00\u59CB, ''enum' compiler.err.assert.as.identifier=\u4ECE\u53D1\u884C\u7248 1.4 \u5F00\u59CB, ''assert'' \u662F\u4E00\u4E2A\u5173\u952E\u5B57, \u4F46\u4E0D\u80FD\u7528\u4F5C\u6807\u8BC6\u7B26\n(\u8BF7\u4F7F\u7528 -source 1.3 \u6216\u66F4\u4F4E\u7248\u672C\u4EE5\u5C06 ''assert'' \u7528\u4F5C\u6807\u8BC6\u7B26) +# TODO 308: make a better error message +# compiler.err.this.as.identifier=\ +# as of release 8, ''this'' is allowed as the parameter name for the receiver type only, which has to be the first parameter + # 0: string compiler.err.generics.not.supported.in.source=-source {0} \u4E2D\u4E0D\u652F\u6301\u6CDB\u578B\n(\u8BF7\u4F7F\u7528 -source 5 \u6216\u66F4\u9AD8\u7248\u672C\u4EE5\u542F\u7528\u6CDB\u578B) @@ -1351,7 +1355,7 @@ compiler.err.annotations.not.supported.in.source=-source {0} \u4E2D\u4E0D\u652F\ #308 compiler.err.type.annotations.not.supported.in.source=\ #308 type annotations are not supported in -source {0}\n\ -#308 (use -source 7 or higher to enable type annotations) +#308 (use -source 8 or higher to enable type annotations) # 0: string compiler.err.foreach.not.supported.in.source=-source {0} \u4E2D\u4E0D\u652F\u6301 for-each \u5FAA\u73AF\n(\u8BF7\u4F7F\u7528 -source 5 \u6216\u66F4\u9AD8\u7248\u672C\u4EE5\u542F\u7528 for-each \u5FAA\u73AF) diff --git a/langtools/src/share/classes/com/sun/tools/javac/tree/JCTree.java b/langtools/src/share/classes/com/sun/tools/javac/tree/JCTree.java index b6ca54757c5..97a31131440 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/tree/JCTree.java +++ b/langtools/src/share/classes/com/sun/tools/javac/tree/JCTree.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2013, 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 @@ -250,11 +250,11 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition { */ TYPEAPPLY, - /** Union types, of type TypeUnion + /** Union types, of type TypeUnion. */ TYPEUNION, - /** Intersection types, of type TypeIntersection + /** Intersection types, of type TypeIntersection. */ TYPEINTERSECTION, @@ -274,10 +274,16 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition { */ ANNOTATION, + /** metadata: Type annotation. + */ + TYPE_ANNOTATION, + /** metadata: Modifiers */ MODIFIERS, + /** An annotated type tree. + */ ANNOTATED_TYPE, /** Error trees, of type Erroneous. @@ -725,6 +731,8 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition { public JCExpression restype; /** type parameters */ public List typarams; + /** receiver parameter */ + public JCVariableDecl recvparam; /** value parameters */ public List params; /** exceptions thrown by this method */ @@ -739,6 +747,7 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition { Name name, JCExpression restype, List typarams, + JCVariableDecl recvparam, List params, List thrown, JCBlock body, @@ -750,6 +759,9 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition { this.restype = restype; this.typarams = typarams; this.params = params; + this.recvparam = recvparam; + // TODO: do something special if the given type is null? + // receiver != null ? receiver : List.nil()); this.thrown = thrown; this.body = body; this.defaultValue = defaultValue; @@ -768,6 +780,7 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition { public List getParameters() { return params; } + public JCVariableDecl getReceiverParameter() { return recvparam; } public List getThrows() { return thrown; } @@ -1505,6 +1518,10 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition { public static class JCNewArray extends JCExpression implements NewArrayTree { public JCExpression elemtype; public List dims; + // type annotations on inner-most component + public List annotations; + // type annotations on dimensions + public List> dimAnnotations; public List elems; protected JCNewArray(JCExpression elemtype, List dims, @@ -1512,6 +1529,8 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition { { this.elemtype = elemtype; this.dims = dims; + this.annotations = List.nil(); + this.dimAnnotations = List.nil(); this.elems = elems; } @Override @@ -2152,9 +2171,12 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition { public Name name; /** bounds */ public List bounds; - protected JCTypeParameter(Name name, List bounds) { + /** type annotations on type parameter */ + public List annotations; + protected JCTypeParameter(Name name, List bounds, List annotations) { this.name = name; this.bounds = bounds; + this.annotations = annotations; } @Override public void accept(Visitor v) { v.visitTypeParameter(this); } @@ -2164,6 +2186,9 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition { public List getBounds() { return bounds; } + public List getAnnotations() { + return annotations; + } @Override public R accept(TreeVisitor v, D d) { return v.visitTypeParameter(this, d); @@ -2230,16 +2255,27 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition { } public static class JCAnnotation extends JCExpression implements AnnotationTree { + // Either Tag.ANNOTATION or Tag.TYPE_ANNOTATION + private Tag tag; + public JCTree annotationType; public List args; - protected JCAnnotation(JCTree annotationType, List args) { + + // Attribute.Compound if tag is ANNOTATION + // Attribute.TypeCompound if tag is TYPE_ANNOTATION + public Attribute.Compound attribute; + + protected JCAnnotation(Tag tag, JCTree annotationType, List args) { + this.tag = tag; this.annotationType = annotationType; this.args = args; } + @Override public void accept(Visitor v) { v.visitAnnotation(this); } - public Kind getKind() { return Kind.ANNOTATION; } + public Kind getKind() { return TreeInfo.tagToKind(getTag()); } + public JCTree getAnnotationType() { return annotationType; } public List getArguments() { return args; @@ -2250,7 +2286,7 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition { } @Override public Tag getTag() { - return ANNOTATION; + return tag; } } @@ -2281,6 +2317,35 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition { } } + public static class JCAnnotatedType extends JCExpression implements com.sun.source.tree.AnnotatedTypeTree { + // type annotations + public List annotations; + public JCExpression underlyingType; + + protected JCAnnotatedType(List annotations, JCExpression underlyingType) { + this.annotations = annotations; + this.underlyingType = underlyingType; + } + @Override + public void accept(Visitor v) { v.visitAnnotatedType(this); } + + public Kind getKind() { return Kind.ANNOTATED_TYPE; } + public List getAnnotations() { + return annotations; + } + public JCExpression getUnderlyingType() { + return underlyingType; + } + @Override + public R accept(TreeVisitor v, D d) { + return v.visitAnnotatedType(this, d); + } + @Override + public Tag getTag() { + return ANNOTATED_TYPE; + } + } + public static class JCErroneous extends JCExpression implements com.sun.source.tree.ErroneousTree { public List errs; @@ -2347,6 +2412,7 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition { Name name, JCExpression restype, List typarams, + JCVariableDecl recvparam, List params, List thrown, JCBlock body, @@ -2472,6 +2538,7 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition { public void visitTypeBoundKind(TypeBoundKind that) { visitTree(that); } public void visitAnnotation(JCAnnotation that) { visitTree(that); } public void visitModifiers(JCModifiers that) { visitTree(that); } + public void visitAnnotatedType(JCAnnotatedType that) { visitTree(that); } public void visitErroneous(JCErroneous that) { visitTree(that); } public void visitLetExpr(LetExpr that) { visitTree(that); } diff --git a/langtools/src/share/classes/com/sun/tools/javac/tree/Pretty.java b/langtools/src/share/classes/com/sun/tools/javac/tree/Pretty.java index 094b8610c0b..3e6c149fbbc 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/tree/Pretty.java +++ b/langtools/src/share/classes/com/sun/tools/javac/tree/Pretty.java @@ -29,7 +29,6 @@ import java.io.*; import com.sun.source.tree.MemberReferenceTree.ReferenceMode; import com.sun.tools.javac.code.*; -import com.sun.tools.javac.code.Symbol.*; import com.sun.tools.javac.tree.JCTree.*; import com.sun.tools.javac.util.*; import com.sun.tools.javac.util.List; @@ -261,6 +260,15 @@ public class Pretty extends JCTree.Visitor { } } + public void printTypeAnnotations(List trees) throws IOException { + if (trees.nonEmpty()) + print(" "); + for (List l = trees; l.nonEmpty(); l = l.tail) { + printExpr(l.head); + print(" "); + } + } + /** Print documentation comment, if it exists * @param tree The tree for which a documentation comment should be printed. */ @@ -491,6 +499,12 @@ public class Pretty extends JCTree.Visitor { print(" " + tree.name); } print("("); + if (tree.recvparam!=null) { + printExpr(tree.recvparam); + if (tree.params.size() > 0) { + print(", "); + } + } printExprs(tree.params); print(")"); if (tree.thrown.nonEmpty()) { @@ -543,7 +557,15 @@ public class Pretty extends JCTree.Visitor { } else { printExpr(tree.mods); if ((tree.mods.flags & VARARGS) != 0) { - printExpr(((JCArrayTypeTree) tree.vartype).elemtype); + JCTree vartype = tree.vartype; + List tas = null; + if (vartype instanceof JCAnnotatedType) { + tas = ((JCAnnotatedType)vartype).annotations; + vartype = ((JCAnnotatedType)vartype).underlyingType; + } + printExpr(((JCArrayTypeTree) vartype).elemtype); + if (tas != null) + printTypeAnnotations(tas); print("... " + tree.name); } else { printExpr(tree.vartype); @@ -919,16 +941,29 @@ public class Pretty extends JCTree.Visitor { try { if (tree.elemtype != null) { print("new "); + printTypeAnnotations(tree.annotations); JCTree elem = tree.elemtype; - if (elem.hasTag(TYPEARRAY)) - printBaseElementType((JCArrayTypeTree) elem); - else - printExpr(elem); + printBaseElementType(elem); + boolean isElemAnnoType = elem instanceof JCAnnotatedType; + int i = 0; + List> da = tree.dimAnnotations; for (List l = tree.dims; l.nonEmpty(); l = l.tail) { + if (da.size() > i) { + printTypeAnnotations(da.get(i)); + } print("["); + i++; printExpr(l.head); print("]"); } + if (tree.elems != null) { + if (isElemAnnoType) { + printTypeAnnotations(((JCAnnotatedType)tree.elemtype).annotations); + } + print("[]"); + } + if (isElemAnnoType) + elem = ((JCAnnotatedType)elem).underlyingType; if (elem instanceof JCArrayTypeTree) printBrackets((JCArrayTypeTree) elem); } @@ -1225,6 +1260,12 @@ public class Pretty extends JCTree.Visitor { JCTree elem; while (true) { elem = tree.elemtype; + if (elem.hasTag(ANNOTATED_TYPE)) { + JCAnnotatedType atype = (JCAnnotatedType) elem; + elem = atype.underlyingType; + if (!elem.hasTag(TYPEARRAY)) break; + printTypeAnnotations(atype.annotations); + } print("[]"); if (!elem.hasTag(TYPEARRAY)) break; tree = (JCArrayTypeTree) elem; @@ -1327,6 +1368,32 @@ public class Pretty extends JCTree.Visitor { } } + public void visitAnnotatedType(JCAnnotatedType tree) { + try { + if (tree.underlyingType.getKind() == JCTree.Kind.MEMBER_SELECT) { + JCFieldAccess access = (JCFieldAccess) tree.underlyingType; + printExpr(access.selected, TreeInfo.postfixPrec); + print("."); + printTypeAnnotations(tree.annotations); + print(access.name); + } else if (tree.underlyingType.getKind() == JCTree.Kind.ARRAY_TYPE) { + JCArrayTypeTree array = (JCArrayTypeTree) tree.underlyingType; + printBaseElementType(tree); + printTypeAnnotations(tree.annotations); + print("[]"); + JCExpression elem = array.elemtype; + if (elem.hasTag(TYPEARRAY)) { + printBrackets((JCArrayTypeTree) elem); + } + } else { + printTypeAnnotations(tree.annotations); + printExpr(tree.underlyingType); + } + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + public void visitTree(JCTree tree) { try { print("(UNKNOWN: " + tree + ")"); diff --git a/langtools/src/share/classes/com/sun/tools/javac/tree/TreeCopier.java b/langtools/src/share/classes/com/sun/tools/javac/tree/TreeCopier.java index c2e2ef92290..49f988d8b6d 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/tree/TreeCopier.java +++ b/langtools/src/share/classes/com/sun/tools/javac/tree/TreeCopier.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 2013, 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 @@ -71,11 +71,26 @@ public class TreeCopier

implements TreeVisitor { return lb.toList(); } + public JCTree visitAnnotatedType(AnnotatedTypeTree node, P p) { + JCAnnotatedType t = (JCAnnotatedType) node; + List annotations = copy(t.annotations, p); + JCExpression underlyingType = copy(t.underlyingType, p); + return M.at(t.pos).AnnotatedType(annotations, underlyingType); + } + public JCTree visitAnnotation(AnnotationTree node, P p) { JCAnnotation t = (JCAnnotation) node; JCTree annotationType = copy(t.annotationType, p); List args = copy(t.args, p); - return M.at(t.pos).Annotation(annotationType, args); + if (t.getKind() == Tree.Kind.TYPE_ANNOTATION) { + JCAnnotation newTA = M.at(t.pos).TypeAnnotation(annotationType, args); + newTA.attribute = t.attribute; + return newTA; + } else { + JCAnnotation newT = M.at(t.pos).Annotation(annotationType, args); + newT.attribute = t.attribute; + return newT; + } } public JCTree visitAssert(AssertTree node, P p) { @@ -233,10 +248,11 @@ public class TreeCopier

implements TreeVisitor { JCExpression restype = copy(t.restype, p); List typarams = copy(t.typarams, p); List params = copy(t.params, p); + JCVariableDecl recvparam = copy(t.recvparam, p); List thrown = copy(t.thrown, p); JCBlock body = copy(t.body, p); JCExpression defaultValue = copy(t.defaultValue, p); - return M.at(t.pos).MethodDef(mods, t.name, restype, typarams, params, thrown, body, defaultValue); + return M.at(t.pos).MethodDef(mods, t.name, restype, typarams, recvparam, params, thrown, body, defaultValue); } public JCTree visitMethodInvocation(MethodInvocationTree node, P p) { @@ -384,8 +400,9 @@ public class TreeCopier

implements TreeVisitor { public JCTree visitTypeParameter(TypeParameterTree node, P p) { JCTypeParameter t = (JCTypeParameter) node; + List annos = copy(t.annotations, p); List bounds = copy(t.bounds, p); - return M.at(t.pos).TypeParameter(t.name, bounds); + return M.at(t.pos).TypeParameter(t.name, bounds, annos); } public JCTree visitInstanceOf(InstanceOfTree node, P p) { diff --git a/langtools/src/share/classes/com/sun/tools/javac/tree/TreeInfo.java b/langtools/src/share/classes/com/sun/tools/javac/tree/TreeInfo.java index deed8352494..36e3a100729 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/tree/TreeInfo.java +++ b/langtools/src/share/classes/com/sun/tools/javac/tree/TreeInfo.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2013, 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 @@ -453,6 +453,19 @@ public class TreeInfo { case POSTINC: case POSTDEC: return getStartPos(((JCUnary) tree).arg); + case ANNOTATED_TYPE: { + JCAnnotatedType node = (JCAnnotatedType) tree; + if (node.annotations.nonEmpty()) { + if (node.underlyingType.hasTag(TYPEARRAY) || + node.underlyingType.hasTag(SELECT)) { + return getStartPos(node.underlyingType); + } else { + return getStartPos(node.annotations.head); + } + } else { + return getStartPos(node.underlyingType); + } + } case NEWCLASS: { JCNewClass node = (JCNewClass)tree; if (node.encl != null) @@ -560,6 +573,8 @@ public class TreeInfo { return getEndPos(((JCUnary) tree).arg, endPosTable); case WHILELOOP: return getEndPos(((JCWhileLoop) tree).body, endPosTable); + case ANNOTATED_TYPE: + return getEndPos(((JCAnnotatedType) tree).underlyingType, endPosTable); case ERRONEOUS: { JCErroneous node = (JCErroneous)tree; if (node.errs != null && node.errs.nonEmpty()) @@ -799,6 +814,8 @@ public class TreeInfo { return ((JCFieldAccess) tree).sym; case TYPEAPPLY: return symbol(((JCTypeApply) tree).clazz); + case ANNOTATED_TYPE: + return symbol(((JCAnnotatedType) tree).underlyingType); default: return null; } @@ -1036,17 +1053,24 @@ public class TreeInfo { case NULLCHK: return Tree.Kind.OTHER; + case ANNOTATION: + return Tree.Kind.ANNOTATION; + case TYPE_ANNOTATION: + return Tree.Kind.TYPE_ANNOTATION; + default: return null; } } /** - * Returns the underlying type of the tree if it is annotated type, - * or the tree itself otherwise + * Returns the underlying type of the tree if it is an annotated type, + * or the tree itself otherwise. */ public static JCExpression typeIn(JCExpression tree) { switch (tree.getTag()) { + case ANNOTATED_TYPE: + return ((JCAnnotatedType)tree).underlyingType; case IDENT: /* simple names */ case TYPEIDENT: /* primitive name */ case SELECT: /* qualified name */ @@ -1054,20 +1078,55 @@ public class TreeInfo { case WILDCARD: /* wild cards */ case TYPEPARAMETER: /* type parameters */ case TYPEAPPLY: /* parameterized types */ + case ERRONEOUS: /* error tree TODO: needed for BadCast JSR308 test case. Better way? */ return tree; default: throw new AssertionError("Unexpected type tree: " + tree); } } + /* Return the inner-most type of a type tree. + * For an array that contains an annotated type, return that annotated type. + * TODO: currently only used by Pretty. Describe behavior better. + */ public static JCTree innermostType(JCTree type) { - switch (type.getTag()) { - case TYPEARRAY: - return innermostType(((JCArrayTypeTree)type).elemtype); - case WILDCARD: - return innermostType(((JCWildcard)type).inner); - default: - return type; + JCTree lastAnnotatedType = null; + JCTree cur = type; + loop: while (true) { + switch (cur.getTag()) { + case TYPEARRAY: + lastAnnotatedType = null; + cur = ((JCArrayTypeTree)cur).elemtype; + break; + case WILDCARD: + lastAnnotatedType = null; + cur = ((JCWildcard)cur).inner; + break; + case ANNOTATED_TYPE: + lastAnnotatedType = cur; + cur = ((JCAnnotatedType)cur).underlyingType; + break; + default: + break loop; + } + } + if (lastAnnotatedType!=null) { + return lastAnnotatedType; + } else { + return cur; } } + + private static class TypeAnnotationFinder extends TreeScanner { + public boolean foundTypeAnno = false; + public void visitAnnotation(JCAnnotation tree) { + foundTypeAnno = foundTypeAnno || tree.hasTag(TYPE_ANNOTATION); + } + } + + public static boolean containsTypeAnnotation(JCTree e) { + TypeAnnotationFinder finder = new TypeAnnotationFinder(); + finder.scan(e); + return finder.foundTypeAnno; + } } diff --git a/langtools/src/share/classes/com/sun/tools/javac/tree/TreeMaker.java b/langtools/src/share/classes/com/sun/tools/javac/tree/TreeMaker.java index 27a2d74feda..cc6405e22d9 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/tree/TreeMaker.java +++ b/langtools/src/share/classes/com/sun/tools/javac/tree/TreeMaker.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2013, 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 @@ -169,10 +169,26 @@ public class TreeMaker implements JCTree.Factory { List thrown, JCBlock body, JCExpression defaultValue) { + return MethodDef( + mods, name, restype, typarams, null, params, + thrown, body, defaultValue); + } + + public JCMethodDecl MethodDef(JCModifiers mods, + Name name, + JCExpression restype, + List typarams, + JCVariableDecl recvparam, + List params, + List thrown, + JCBlock body, + JCExpression defaultValue) + { JCMethodDecl tree = new JCMethodDecl(mods, name, restype, typarams, + recvparam, params, thrown, body, @@ -463,7 +479,11 @@ public class TreeMaker implements JCTree.Factory { } public JCTypeParameter TypeParameter(Name name, List bounds) { - JCTypeParameter tree = new JCTypeParameter(name, bounds); + return TypeParameter(name, bounds, List.nil()); + } + + public JCTypeParameter TypeParameter(Name name, List bounds, List annos) { + JCTypeParameter tree = new JCTypeParameter(name, bounds, annos); tree.pos = pos; return tree; } @@ -481,7 +501,13 @@ public class TreeMaker implements JCTree.Factory { } public JCAnnotation Annotation(JCTree annotationType, List args) { - JCAnnotation tree = new JCAnnotation(annotationType, args); + JCAnnotation tree = new JCAnnotation(Tag.ANNOTATION, annotationType, args); + tree.pos = pos; + return tree; + } + + public JCAnnotation TypeAnnotation(JCTree annotationType, List args) { + JCAnnotation tree = new JCAnnotation(Tag.TYPE_ANNOTATION, annotationType, args); tree.pos = pos; return tree; } @@ -497,6 +523,12 @@ public class TreeMaker implements JCTree.Factory { return Modifiers(flags, List.nil()); } + public JCAnnotatedType AnnotatedType(List annotations, JCExpression underlyingType) { + JCAnnotatedType tree = new JCAnnotatedType(annotations, underlyingType); + tree.pos = pos; + return tree; + } + public JCErroneous Erroneous() { return Erroneous(List.nil()); } @@ -755,7 +787,11 @@ public class TreeMaker implements JCTree.Factory { result = Erroneous(); } public void visitCompound(Attribute.Compound compound) { - result = visitCompoundInternal(compound); + if (compound instanceof Attribute.TypeCompound) { + result = visitTypeCompoundInternal((Attribute.TypeCompound) compound); + } else { + result = visitCompoundInternal(compound); + } } public JCAnnotation visitCompoundInternal(Attribute.Compound compound) { ListBuffer args = new ListBuffer(); @@ -766,6 +802,15 @@ public class TreeMaker implements JCTree.Factory { } return Annotation(Type(compound.type), args.toList()); } + public JCAnnotation visitTypeCompoundInternal(Attribute.TypeCompound compound) { + ListBuffer args = new ListBuffer(); + for (List> values = compound.values; values.nonEmpty(); values=values.tail) { + Pair pair = values.head; + JCExpression valueTree = translate(pair.snd); + args.append(Assign(Ident(pair.fst), valueTree).setType(valueTree.type)); + } + return TypeAnnotation(Type(compound.type), args.toList()); + } public void visitArray(Attribute.Array array) { ListBuffer elems = new ListBuffer(); for (int i = 0; i < array.values.length; i++) @@ -779,7 +824,11 @@ public class TreeMaker implements JCTree.Factory { JCAnnotation translate(Attribute.Compound a) { return visitCompoundInternal(a); } + JCAnnotation translate(Attribute.TypeCompound a) { + return visitTypeCompoundInternal(a); + } } + AnnotationBuilder annotationBuilder = new AnnotationBuilder(); /** Create an annotation tree from an attribute. @@ -788,6 +837,10 @@ public class TreeMaker implements JCTree.Factory { return annotationBuilder.translate((Attribute.Compound)a); } + public JCAnnotation TypeAnnotation(Attribute a) { + return annotationBuilder.translate((Attribute.TypeCompound) a); + } + /** Create a method definition from a method symbol and a method body. */ public JCMethodDecl MethodDef(MethodSymbol m, JCBlock body) { @@ -804,6 +857,7 @@ public class TreeMaker implements JCTree.Factory { m.name, Type(mtype.getReturnType()), TypeParams(mtype.getTypeArguments()), + null, // receiver type Params(mtype.getParameterTypes(), m), Types(mtype.getThrownTypes()), body, @@ -822,7 +876,6 @@ public class TreeMaker implements JCTree.Factory { */ public List TypeParams(List typarams) { ListBuffer tparams = new ListBuffer(); - int i = 0; for (List l = typarams; l.nonEmpty(); l = l.tail) tparams.append(TypeParam(l.head.tsym.name, (TypeVar)l.head)); return tparams.toList(); diff --git a/langtools/src/share/classes/com/sun/tools/javac/tree/TreeScanner.java b/langtools/src/share/classes/com/sun/tools/javac/tree/TreeScanner.java index eff0fe2c617..57724d34292 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/tree/TreeScanner.java +++ b/langtools/src/share/classes/com/sun/tools/javac/tree/TreeScanner.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2013, 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 @@ -84,6 +84,7 @@ public class TreeScanner extends Visitor { scan(tree.mods); scan(tree.restype); scan(tree.typarams); + scan(tree.recvparam); scan(tree.params); scan(tree.thrown); scan(tree.defaultValue); @@ -200,15 +201,18 @@ public class TreeScanner extends Visitor { public void visitNewClass(JCNewClass tree) { scan(tree.encl); - scan(tree.clazz); scan(tree.typeargs); + scan(tree.clazz); scan(tree.args); scan(tree.def); } public void visitNewArray(JCNewArray tree) { + scan(tree.annotations); scan(tree.elemtype); scan(tree.dims); + for (List annos : tree.dimAnnotations) + scan(annos); scan(tree.elems); } @@ -291,6 +295,7 @@ public class TreeScanner extends Visitor { } public void visitTypeParameter(JCTypeParameter tree) { + scan(tree.annotations); scan(tree.bounds); } @@ -314,6 +319,11 @@ public class TreeScanner extends Visitor { scan(tree.args); } + public void visitAnnotatedType(JCAnnotatedType tree) { + scan(tree.annotations); + scan(tree.underlyingType); + } + public void visitErroneous(JCErroneous tree) { } diff --git a/langtools/src/share/classes/com/sun/tools/javac/tree/TreeTranslator.java b/langtools/src/share/classes/com/sun/tools/javac/tree/TreeTranslator.java index daf456fa90d..42e97deee11 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/tree/TreeTranslator.java +++ b/langtools/src/share/classes/com/sun/tools/javac/tree/TreeTranslator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2013, 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 @@ -139,6 +139,7 @@ public class TreeTranslator extends JCTree.Visitor { tree.mods = translate(tree.mods); tree.restype = translate(tree.restype); tree.typarams = translateTypeParams(tree.typarams); + tree.recvparam = translate(tree.recvparam); tree.params = translateVarDefs(tree.params); tree.thrown = translate(tree.thrown); tree.body = translate(tree.body); @@ -289,6 +290,11 @@ public class TreeTranslator extends JCTree.Visitor { } public void visitNewArray(JCNewArray tree) { + tree.annotations = translate(tree.annotations); + List> dimAnnos = List.nil(); + for (List origDimAnnos : tree.dimAnnotations) + dimAnnos = dimAnnos.append(translate(origDimAnnos)); + tree.dimAnnotations = dimAnnos; tree.elemtype = translate(tree.elemtype); tree.dims = translate(tree.dims); tree.elems = translate(tree.elems); @@ -385,6 +391,7 @@ public class TreeTranslator extends JCTree.Visitor { } public void visitTypeParameter(JCTypeParameter tree) { + tree.annotations = translate(tree.annotations); tree.bounds = translate(tree.bounds); result = tree; } @@ -422,6 +429,12 @@ public class TreeTranslator extends JCTree.Visitor { result = tree; } + public void visitAnnotatedType(JCAnnotatedType tree) { + tree.annotations = translate(tree.annotations); + tree.underlyingType = translate(tree.underlyingType); + result = tree; + } + public void visitTree(JCTree tree) { throw new AssertionError(tree); } diff --git a/langtools/src/share/classes/com/sun/tools/javac/util/JCDiagnostic.java b/langtools/src/share/classes/com/sun/tools/javac/util/JCDiagnostic.java index 17ce2319dc1..be531e0ef03 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/util/JCDiagnostic.java +++ b/langtools/src/share/classes/com/sun/tools/javac/util/JCDiagnostic.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2013, 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 @@ -388,7 +388,7 @@ public class JCDiagnostic implements Diagnostic { this.source = source; this.position = pos; this.key = key; - this.args = args; + this.args = args; int n = (pos == null ? Position.NOPOS : pos.getPreferredPosition()); if (n == Position.NOPOS || source == null) diff --git a/langtools/src/share/classes/com/sun/tools/javac/util/Log.java b/langtools/src/share/classes/com/sun/tools/javac/util/Log.java index 70267f7097c..4ed16c1eb6d 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/util/Log.java +++ b/langtools/src/share/classes/com/sun/tools/javac/util/Log.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2013, 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 @@ -217,7 +217,7 @@ public class Log extends AbstractLog { private JavacMessages messages; /** -+ * Handler for initial dispatch of diagnostics. + * Handler for initial dispatch of diagnostics. */ private DiagnosticHandler diagnosticHandler; @@ -385,14 +385,17 @@ public class Log extends AbstractLog { noticeWriter = warnWriter = errWriter = pw; } - public void setWriters(Log other) { + /** + * Propagate the previous log's information. + */ + public void initRound(Log other) { this.noticeWriter = other.noticeWriter; this.warnWriter = other.warnWriter; this.errWriter = other.errWriter; - } - - public void setSourceMap(Log other) { this.sourceMap = other.sourceMap; + this.recorded = other.recorded; + this.nerrors = other.nerrors; + this.nwarnings = other.nwarnings; } /** diff --git a/langtools/src/share/classes/com/sun/tools/javadoc/AbstractTypeImpl.java b/langtools/src/share/classes/com/sun/tools/javadoc/AbstractTypeImpl.java index e589bfa8678..6adcb43f90b 100644 --- a/langtools/src/share/classes/com/sun/tools/javadoc/AbstractTypeImpl.java +++ b/langtools/src/share/classes/com/sun/tools/javadoc/AbstractTypeImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2013, 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 @@ -104,4 +104,8 @@ abstract class AbstractTypeImpl implements com.sun.javadoc.Type { public AnnotationTypeDoc asAnnotationTypeDoc() { return null; } + + public AnnotatedType asAnnotatedType() { + return null; + } } diff --git a/langtools/src/share/classes/com/sun/tools/javadoc/AnnotatedTypeImpl.java b/langtools/src/share/classes/com/sun/tools/javadoc/AnnotatedTypeImpl.java new file mode 100644 index 00000000000..a49dc8a3134 --- /dev/null +++ b/langtools/src/share/classes/com/sun/tools/javadoc/AnnotatedTypeImpl.java @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2003, 2013, 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. + */ + +package com.sun.tools.javadoc; + +import com.sun.javadoc.*; +import com.sun.tools.javac.code.Attribute; +import com.sun.tools.javac.code.Attribute.TypeCompound; +import com.sun.tools.javac.util.List; + +/** + * Implementation of AnnotatedType, which + * represents an annotated type. + * + * @author Mahmood Ali + * @since 1.8 + */ +public class AnnotatedTypeImpl + extends AbstractTypeImpl implements AnnotatedType { + + AnnotatedTypeImpl(DocEnv env, com.sun.tools.javac.code.Type.AnnotatedType type) { + super(env, type); + } + + /** + * Get the annotations of this program element. + * Return an empty array if there are none. + */ + @Override + public AnnotationDesc[] annotations() { + List tas = ((com.sun.tools.javac.code.Type.AnnotatedType)type).typeAnnotations; + if (tas == null || + tas.isEmpty()) { + return new AnnotationDesc[0]; + } + AnnotationDesc res[] = new AnnotationDesc[tas.length()]; + int i = 0; + for (Attribute.Compound a : tas) { + res[i++] = new AnnotationDescImpl(env, a); + } + return res; + } + + @Override + public com.sun.javadoc.Type underlyingType() { + return TypeMaker.getType(env, ((com.sun.tools.javac.code.Type.AnnotatedType)type).underlyingType, true, false); + } + + @Override + public AnnotatedType asAnnotatedType() { + return this; + } + + @Override + public String toString() { + return typeName(); + } + + @Override + public String typeName() { + return this.underlyingType().typeName(); + } + + @Override + public String qualifiedTypeName() { + return this.underlyingType().qualifiedTypeName(); + } + + @Override + public String simpleTypeName() { + return this.underlyingType().simpleTypeName(); + } + + @Override + public String dimension() { + return this.underlyingType().dimension(); + } + + @Override + public boolean isPrimitive() { + return this.underlyingType().isPrimitive(); + } + + @Override + public ClassDoc asClassDoc() { + return this.underlyingType().asClassDoc(); + } + + @Override + public TypeVariable asTypeVariable() { + return this.underlyingType().asTypeVariable(); + } + + @Override + public WildcardType asWildcardType() { + return this.underlyingType().asWildcardType(); + } + + @Override + public ParameterizedType asParameterizedType() { + return this.underlyingType().asParameterizedType(); + } +} diff --git a/langtools/src/share/classes/com/sun/tools/javadoc/ClassDocImpl.java b/langtools/src/share/classes/com/sun/tools/javadoc/ClassDocImpl.java index ffcc5e7853f..3d1ac353cc0 100644 --- a/langtools/src/share/classes/com/sun/tools/javadoc/ClassDocImpl.java +++ b/langtools/src/share/classes/com/sun/tools/javadoc/ClassDocImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, 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 @@ -1185,6 +1185,13 @@ public class ClassDocImpl extends ProgramElementDocImpl implements ClassDoc { return null; } + /** + * Returns null, as this is not an annotated type. + */ + public AnnotatedType asAnnotatedType() { + return null; + } + /** * Return false, as this is not a primitive type. */ diff --git a/langtools/src/share/classes/com/sun/tools/javadoc/ExecutableMemberDocImpl.java b/langtools/src/share/classes/com/sun/tools/javadoc/ExecutableMemberDocImpl.java index 72a666d27a7..a1a741d10ff 100644 --- a/langtools/src/share/classes/com/sun/tools/javadoc/ExecutableMemberDocImpl.java +++ b/langtools/src/share/classes/com/sun/tools/javadoc/ExecutableMemberDocImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, 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 @@ -28,10 +28,14 @@ package com.sun.tools.javadoc; import java.lang.reflect.Modifier; import java.text.CollationKey; +import javax.lang.model.type.TypeKind; + import com.sun.javadoc.*; import com.sun.source.util.TreePath; +import com.sun.tools.javac.code.Attribute; import com.sun.tools.javac.code.Flags; +import com.sun.tools.javac.code.Attribute.Compound; import com.sun.tools.javac.code.Symbol.*; import com.sun.tools.javac.code.Type; import com.sun.tools.javac.util.List; @@ -195,6 +199,24 @@ public abstract class ExecutableMemberDocImpl return result; } + public AnnotationDesc[] receiverAnnotations() { + // TODO: change how receiver annotations are output! + Type recvtype = sym.type.asMethodType().recvtype; + if (recvtype == null) { + return new AnnotationDesc[0]; + } + if (recvtype.getKind() != TypeKind.ANNOTATED) { + return new AnnotationDesc[0]; + } + List typeAnnos = ((com.sun.tools.javac.code.Type.AnnotatedType)recvtype).typeAnnotations; + AnnotationDesc result[] = new AnnotationDesc[typeAnnos.length()]; + int i = 0; + for (Attribute.Compound a : typeAnnos) { + result[i++] = new AnnotationDescImpl(env, a); + } + return result; + } + /** * Return the formal type parameters of this method or constructor. * Return an empty array if there are none. diff --git a/langtools/src/share/classes/com/sun/tools/javadoc/PrimitiveType.java b/langtools/src/share/classes/com/sun/tools/javadoc/PrimitiveType.java index 15679a79f46..9f6345f98b0 100644 --- a/langtools/src/share/classes/com/sun/tools/javadoc/PrimitiveType.java +++ b/langtools/src/share/classes/com/sun/tools/javadoc/PrimitiveType.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2013, 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 @@ -121,12 +121,19 @@ class PrimitiveType implements com.sun.javadoc.Type { } /** - * Return null, as this is not a wildcard type; + * Return null, as this is not a wildcard type. */ public WildcardType asWildcardType() { return null; } + /** + * Return null, as this is not an annotated type. + */ + public AnnotatedType asAnnotatedType() { + return null; + } + /** * Returns a string representation of the type. * diff --git a/langtools/src/share/classes/com/sun/tools/javadoc/TypeMaker.java b/langtools/src/share/classes/com/sun/tools/javadoc/TypeMaker.java index dd0f355fa24..4a24e9406a5 100644 --- a/langtools/src/share/classes/com/sun/tools/javadoc/TypeMaker.java +++ b/langtools/src/share/classes/com/sun/tools/javadoc/TypeMaker.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, 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 @@ -25,6 +25,8 @@ package com.sun.tools.javadoc; +import javax.lang.model.type.TypeKind; + import com.sun.javadoc.*; import com.sun.tools.javac.code.Symbol; import com.sun.tools.javac.code.Symbol.ClassSymbol; @@ -51,12 +53,27 @@ public class TypeMaker { * @param errToClassDoc if true, ERROR type results in a ClassDoc; * false preserves legacy behavior */ + public static com.sun.javadoc.Type getType(DocEnv env, Type t, + boolean errorToClassDoc) { + return getType(env, t, errorToClassDoc, true); + } + @SuppressWarnings("fallthrough") public static com.sun.javadoc.Type getType(DocEnv env, Type t, - boolean errToClassDoc) { + boolean errToClassDoc, boolean considerAnnotations) { if (env.legacyDoclet) { t = env.types.erasure(t); } + if (considerAnnotations + && t.getKind() == TypeKind.ANNOTATED) { + return new AnnotatedTypeImpl(env, (com.sun.tools.javac.code.Type.AnnotatedType) t); + } + + if (t.getKind() == TypeKind.ANNOTATED) { + Type.AnnotatedType at = (Type.AnnotatedType) t; + return new AnnotatedTypeImpl(env, at); + } + switch (t.getTag()) { case CLASS: if (ClassDocImpl.isGeneric((ClassSymbol)t.tsym)) { @@ -129,6 +146,11 @@ public class TypeMaker { * Class names are qualified if "full" is true. */ static String getTypeString(DocEnv env, Type t, boolean full) { + // TODO: should annotations be included here? + if (t.getKind() == TypeKind.ANNOTATED) { + Type.AnnotatedType at = (Type.AnnotatedType)t; + t = at.underlyingType; + } switch (t.getTag()) { case ARRAY: StringBuilder s = new StringBuilder(); @@ -281,6 +303,13 @@ public class TypeMaker { return null; } + /** + * Return null, as there are no annotations of the type + */ + public AnnotatedType asAnnotatedType() { + return null; + } + /** * Return this type as an AnnotationTypeDoc if it * represents an annotation type. Array dimensions are ignored. diff --git a/langtools/src/share/classes/com/sun/tools/javadoc/TypeVariableImpl.java b/langtools/src/share/classes/com/sun/tools/javadoc/TypeVariableImpl.java index 85f946c6bf9..19a5bb9fab4 100644 --- a/langtools/src/share/classes/com/sun/tools/javadoc/TypeVariableImpl.java +++ b/langtools/src/share/classes/com/sun/tools/javadoc/TypeVariableImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2013, 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 @@ -25,8 +25,12 @@ package com.sun.tools.javadoc; +import javax.lang.model.type.TypeKind; + import com.sun.javadoc.*; +import com.sun.tools.javac.code.Attribute; +import com.sun.tools.javac.code.Attribute.TypeCompound; import com.sun.tools.javac.code.Kinds; import com.sun.tools.javac.code.Symbol; import com.sun.tools.javac.code.Symbol.ClassSymbol; @@ -120,11 +124,30 @@ public class TypeVariableImpl extends AbstractTypeImpl implements TypeVariable { * Get the bounds of a type variable as listed in the "extends" clause. */ private static List getBounds(TypeVar v, DocEnv env) { - Name boundname = v.getUpperBound().tsym.getQualifiedName(); - if (boundname == boundname.table.names.java_lang_Object) { + final Type upperBound = v.getUpperBound(); + Name boundname = upperBound.tsym.getQualifiedName(); + if (boundname == boundname.table.names.java_lang_Object + && upperBound.getKind() != TypeKind.ANNOTATED) { return List.nil(); } else { return env.types.getBounds(v); } } + + /** + * Get the annotations of this program element. + * Return an empty array if there are none. + */ + public AnnotationDesc[] annotations() { + if (type.getKind() != TypeKind.ANNOTATED) { + return new AnnotationDesc[0]; + } + List tas = ((com.sun.tools.javac.code.Type.AnnotatedType) type).typeAnnotations; + AnnotationDesc res[] = new AnnotationDesc[tas.length()]; + int i = 0; + for (Attribute.Compound a : tas) { + res[i++] = new AnnotationDescImpl(env, a); + } + return res; + } } diff --git a/langtools/src/share/classes/com/sun/tools/javap/AnnotationWriter.java b/langtools/src/share/classes/com/sun/tools/javap/AnnotationWriter.java index 37ec6b291e4..6f894e7cb62 100644 --- a/langtools/src/share/classes/com/sun/tools/javap/AnnotationWriter.java +++ b/langtools/src/share/classes/com/sun/tools/javap/AnnotationWriter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2013, 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 @@ -26,6 +26,7 @@ package com.sun.tools.javap; import com.sun.tools.classfile.Annotation; +import com.sun.tools.classfile.TypeAnnotation; import com.sun.tools.classfile.Annotation.Annotation_element_value; import com.sun.tools.classfile.Annotation.Array_element_value; import com.sun.tools.classfile.Annotation.Class_element_value; @@ -76,6 +77,124 @@ public class AnnotationWriter extends BasicWriter { print(")"); } + public void write(TypeAnnotation annot) { + write(annot, true, false); + } + + public void write(TypeAnnotation annot, boolean showOffsets, boolean resolveIndices) { + write(annot.annotation, resolveIndices); + print(": "); + write(annot.position, showOffsets); + } + + public void write(TypeAnnotation.Position pos, boolean showOffsets) { + print(pos.type); + + switch (pos.type) { + // type cast + case CAST: + // instanceof + case INSTANCEOF: + // new expression + case NEW: + if (showOffsets) { + print(", offset="); + print(pos.offset); + } + break; + // local variable + case LOCAL_VARIABLE: + // resource variable + case RESOURCE_VARIABLE: + if (pos.lvarOffset == null) { + print(", lvarOffset is Null!"); + break; + } + print(", {"); + for (int i = 0; i < pos.lvarOffset.length; ++i) { + if (i != 0) print("; "); + if (showOffsets) { + print("start_pc="); + print(pos.lvarOffset[i]); + } + print(", length="); + print(pos.lvarLength[i]); + print(", index="); + print(pos.lvarIndex[i]); + } + print("}"); + break; + // exception parameter + case EXCEPTION_PARAMETER: + print(", exception_index="); + print(pos.exception_index); + break; + // method receiver + case METHOD_RECEIVER: + // Do nothing + break; + // type parameter + case CLASS_TYPE_PARAMETER: + case METHOD_TYPE_PARAMETER: + print(", param_index="); + print(pos.parameter_index); + break; + // type parameter bound + case CLASS_TYPE_PARAMETER_BOUND: + case METHOD_TYPE_PARAMETER_BOUND: + print(", param_index="); + print(pos.parameter_index); + print(", bound_index="); + print(pos.bound_index); + break; + // class extends or implements clause + case CLASS_EXTENDS: + print(", type_index="); + print(pos.type_index); + break; + // throws + case THROWS: + print(", type_index="); + print(pos.type_index); + break; + // method parameter + case METHOD_FORMAL_PARAMETER: + print(", param_index="); + print(pos.parameter_index); + break; + // method/constructor/reference type argument + case CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT: + case METHOD_INVOCATION_TYPE_ARGUMENT: + case METHOD_REFERENCE_TYPE_ARGUMENT: + if (showOffsets) { + print(", offset="); + print(pos.offset); + } + print(", type_index="); + print(pos.type_index); + break; + // We don't need to worry about these + case METHOD_RETURN: + case FIELD: + break; + // lambda formal parameter + case LAMBDA_FORMAL_PARAMETER: + print(", param_index="); + print(pos.parameter_index); + break; + case UNKNOWN: + throw new AssertionError("AnnotationWriter: UNKNOWN target type should never occur!"); + default: + throw new AssertionError("AnnotationWriter: Unknown target type for position: " + pos); + } + + // Append location data for generics/arrays. + if (!pos.location.isEmpty()) { + print(", location="); + print(pos.location); + } + } + public void write(Annotation.element_value_pair pair) { write(pair, false); } diff --git a/langtools/src/share/classes/com/sun/tools/javap/AttributeWriter.java b/langtools/src/share/classes/com/sun/tools/javap/AttributeWriter.java index 329dccb2f87..d25477b237e 100644 --- a/langtools/src/share/classes/com/sun/tools/javap/AttributeWriter.java +++ b/langtools/src/share/classes/com/sun/tools/javap/AttributeWriter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2013, 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 @@ -49,8 +49,10 @@ import com.sun.tools.classfile.LocalVariableTypeTable_attribute; import com.sun.tools.classfile.MethodParameters_attribute; import com.sun.tools.classfile.RuntimeInvisibleAnnotations_attribute; import com.sun.tools.classfile.RuntimeInvisibleParameterAnnotations_attribute; +import com.sun.tools.classfile.RuntimeInvisibleTypeAnnotations_attribute; import com.sun.tools.classfile.RuntimeVisibleAnnotations_attribute; import com.sun.tools.classfile.RuntimeVisibleParameterAnnotations_attribute; +import com.sun.tools.classfile.RuntimeVisibleTypeAnnotations_attribute; import com.sun.tools.classfile.Signature_attribute; import com.sun.tools.classfile.SourceDebugExtension_attribute; import com.sun.tools.classfile.SourceFile_attribute; @@ -433,6 +435,30 @@ public class AttributeWriter extends BasicWriter return null; } + public Void visitRuntimeVisibleTypeAnnotations(RuntimeVisibleTypeAnnotations_attribute attr, Void ignore) { + println("RuntimeVisibleTypeAnnotations:"); + indent(+1); + for (int i = 0; i < attr.annotations.length; i++) { + print(i + ": "); + annotationWriter.write(attr.annotations[i]); + println(); + } + indent(-1); + return null; + } + + public Void visitRuntimeInvisibleTypeAnnotations(RuntimeInvisibleTypeAnnotations_attribute attr, Void ignore) { + println("RuntimeInvisibleTypeAnnotations:"); + indent(+1); + for (int i = 0; i < attr.annotations.length; i++) { + print(i + ": "); + annotationWriter.write(attr.annotations[i]); + println(); + } + indent(-1); + return null; + } + public Void visitRuntimeVisibleParameterAnnotations(RuntimeVisibleParameterAnnotations_attribute attr, Void ignore) { println("RuntimeVisibleParameterAnnotations:"); indent(+1); diff --git a/langtools/src/share/classes/com/sun/tools/javap/CodeWriter.java b/langtools/src/share/classes/com/sun/tools/javap/CodeWriter.java index 50ce27dcbdf..657194d19c6 100644 --- a/langtools/src/share/classes/com/sun/tools/javap/CodeWriter.java +++ b/langtools/src/share/classes/com/sun/tools/javap/CodeWriter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2013, 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 @@ -64,6 +64,7 @@ public class CodeWriter extends BasicWriter { stackMapWriter = StackMapWriter.instance(context); localVariableTableWriter = LocalVariableTableWriter.instance(context); localVariableTypeTableWriter = LocalVariableTypeTableWriter.instance(context); + typeAnnotationWriter = TypeAnnotationWriter.instance(context); options = Options.instance(context); } @@ -265,6 +266,11 @@ public class CodeWriter extends BasicWriter { detailWriters.add(tryBlockWriter); } + if (options.details.contains(InstructionDetailWriter.Kind.TYPE_ANNOS)) { + typeAnnotationWriter.reset(attr); + detailWriters.add(typeAnnotationWriter); + } + return detailWriters; } @@ -273,6 +279,7 @@ public class CodeWriter extends BasicWriter { private ConstantWriter constantWriter; private LocalVariableTableWriter localVariableTableWriter; private LocalVariableTypeTableWriter localVariableTypeTableWriter; + private TypeAnnotationWriter typeAnnotationWriter; private SourceWriter sourceWriter; private StackMapWriter stackMapWriter; private TryBlockWriter tryBlockWriter; diff --git a/langtools/src/share/classes/com/sun/tools/javap/InstructionDetailWriter.java b/langtools/src/share/classes/com/sun/tools/javap/InstructionDetailWriter.java index 7459d6c0d11..8a828b8f2b3 100644 --- a/langtools/src/share/classes/com/sun/tools/javap/InstructionDetailWriter.java +++ b/langtools/src/share/classes/com/sun/tools/javap/InstructionDetailWriter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2013, 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 @@ -42,10 +42,13 @@ public abstract class InstructionDetailWriter extends BasicWriter { LOCAL_VAR_TYPES("localVariableTypes"), SOURCE("source"), STACKMAPS("stackMaps"), - TRY_BLOCKS("tryBlocks"); + TRY_BLOCKS("tryBlocks"), + TYPE_ANNOS("typeAnnotations"); + Kind(String option) { this.option = option; } + final String option; } diff --git a/langtools/src/share/classes/com/sun/tools/javap/TypeAnnotationWriter.java b/langtools/src/share/classes/com/sun/tools/javap/TypeAnnotationWriter.java new file mode 100644 index 00000000000..e5a3a68f1a3 --- /dev/null +++ b/langtools/src/share/classes/com/sun/tools/javap/TypeAnnotationWriter.java @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2009, 2013, 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. + */ +package com.sun.tools.javap; + +import com.sun.tools.classfile.Attribute; +import com.sun.tools.classfile.Code_attribute; +import com.sun.tools.classfile.TypeAnnotation; +import com.sun.tools.classfile.TypeAnnotation.Position; +import com.sun.tools.classfile.Instruction; +import com.sun.tools.classfile.Method; +import com.sun.tools.classfile.RuntimeInvisibleTypeAnnotations_attribute; +import com.sun.tools.classfile.RuntimeTypeAnnotations_attribute; +import com.sun.tools.classfile.RuntimeVisibleTypeAnnotations_attribute; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * Annotate instructions with details about type annotations. + * + *

This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own risk. + * This code and its internal interfaces are subject to change or + * deletion without notice. + */ +public class TypeAnnotationWriter extends InstructionDetailWriter { + public enum NoteKind { VISIBLE, INVISIBLE }; + public static class Note { + Note(NoteKind kind, TypeAnnotation anno) { + this.kind = kind; + this.anno = anno; + } + public final NoteKind kind; + public final TypeAnnotation anno; + } + + static TypeAnnotationWriter instance(Context context) { + TypeAnnotationWriter instance = context.get(TypeAnnotationWriter.class); + if (instance == null) + instance = new TypeAnnotationWriter(context); + return instance; + } + + protected TypeAnnotationWriter(Context context) { + super(context); + context.put(TypeAnnotationWriter.class, this); + annotationWriter = AnnotationWriter.instance(context); + classWriter = ClassWriter.instance(context); + } + + public void reset(Code_attribute attr) { + Method m = classWriter.getMethod(); + pcMap = new HashMap>(); + check(NoteKind.VISIBLE, (RuntimeVisibleTypeAnnotations_attribute) m.attributes.get(Attribute.RuntimeVisibleTypeAnnotations)); + check(NoteKind.INVISIBLE, (RuntimeInvisibleTypeAnnotations_attribute) m.attributes.get(Attribute.RuntimeInvisibleTypeAnnotations)); + } + + private void check(NoteKind kind, RuntimeTypeAnnotations_attribute attr) { + if (attr == null) + return; + + for (TypeAnnotation anno: attr.annotations) { + Position p = anno.position; + Note note = null; + if (p.offset != -1) + addNote(p.offset, note = new Note(kind, anno)); + if (p.lvarOffset != null) { + for (int i = 0; i < p.lvarOffset.length; i++) { + if (note == null) + note = new Note(kind, anno); + addNote(p.lvarOffset[i], note); + } + } + } + } + + private void addNote(int pc, Note note) { + List list = pcMap.get(pc); + if (list == null) + pcMap.put(pc, list = new ArrayList()); + list.add(note); + } + + @Override + void writeDetails(Instruction instr) { + String indent = space(2); // get from Options? + int pc = instr.getPC(); + List notes = pcMap.get(pc); + if (notes != null) { + for (Note n: notes) { + print(indent); + print("@"); + annotationWriter.write(n.anno, false, true); + print(", "); + println(n.kind.toString().toLowerCase()); + } + } + } + + private AnnotationWriter annotationWriter; + private ClassWriter classWriter; + private Map> pcMap; +} diff --git a/langtools/src/share/classes/javax/lang/model/SourceVersion.java b/langtools/src/share/classes/javax/lang/model/SourceVersion.java index c810c9e6013..e2f3bfd538f 100644 --- a/langtools/src/share/classes/javax/lang/model/SourceVersion.java +++ b/langtools/src/share/classes/javax/lang/model/SourceVersion.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2013, 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 @@ -46,7 +46,7 @@ import java.util.HashSet; */ public enum SourceVersion { /* - * Summary of language evoluation + * Summary of language evolution * 1.1: nested classes * 1.2: strictfp * 1.3: no changes diff --git a/langtools/src/share/classes/javax/lang/model/type/AnnotatedType.java b/langtools/src/share/classes/javax/lang/model/type/AnnotatedType.java new file mode 100644 index 00000000000..c2a27dc6e1a --- /dev/null +++ b/langtools/src/share/classes/javax/lang/model/type/AnnotatedType.java @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2012, 2013, 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. + */ + +package javax.lang.model.type; + +import java.util.List; + +import javax.lang.model.element.AnnotationMirror; + +/** + * Represents an annotated type. + * + * As of the {@link javax.lang.model.SourceVersion#RELEASE_8 + * RELEASE_8} source version, annotated types can appear for all + * type uses. + * + * @author Werner Dietl + * @since 1.8 + */ +public interface AnnotatedType extends TypeMirror, + DeclaredType, TypeVariable, WildcardType, + PrimitiveType, ArrayType { + + List getAnnotations(); + TypeMirror getUnderlyingType(); +} diff --git a/langtools/src/share/classes/javax/lang/model/type/ExecutableType.java b/langtools/src/share/classes/javax/lang/model/type/ExecutableType.java index 7b2e63adc93..9bdccaaefb3 100644 --- a/langtools/src/share/classes/javax/lang/model/type/ExecutableType.java +++ b/langtools/src/share/classes/javax/lang/model/type/ExecutableType.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2013, 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 @@ -77,6 +77,14 @@ public interface ExecutableType extends TypeMirror { */ List getParameterTypes(); + /** + * Returns the type of this executable's receiver parameter. + * + * @return the type of this executable's receiver parameter + * TODO: null if none specified or always a valid value? + */ + TypeMirror getReceiverType(); + /** * Returns the exceptions and other throwables listed in this * executable's {@code throws} clause. diff --git a/langtools/src/share/classes/javax/lang/model/type/TypeKind.java b/langtools/src/share/classes/javax/lang/model/type/TypeKind.java index 0f67a3ba7b6..1a9f11d895e 100644 --- a/langtools/src/share/classes/javax/lang/model/type/TypeKind.java +++ b/langtools/src/share/classes/javax/lang/model/type/TypeKind.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2013, 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 @@ -151,7 +151,14 @@ public enum TypeKind { * * @since 1.8 */ - INTERSECTION; + INTERSECTION, + + /** + * An annotated type. + * + * @since 1.8 + */ + ANNOTATED; /** * Returns {@code true} if this kind corresponds to a primitive diff --git a/langtools/src/share/classes/javax/lang/model/type/TypeVisitor.java b/langtools/src/share/classes/javax/lang/model/type/TypeVisitor.java index f95af6c87d9..b59cce20b74 100644 --- a/langtools/src/share/classes/javax/lang/model/type/TypeVisitor.java +++ b/langtools/src/share/classes/javax/lang/model/type/TypeVisitor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2013, 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 @@ -182,4 +182,14 @@ public interface TypeVisitor { * @since 1.8 */ R visitIntersection(IntersectionType t, P p); + + /** + * Visits an annotated type. + * + * @param t the type to visit + * @param p a visitor-specified parameter + * @return a visitor-specified result + * @since 1.8 + */ + R visitAnnotated(AnnotatedType t, P p); } diff --git a/langtools/src/share/classes/javax/lang/model/util/AbstractTypeVisitor6.java b/langtools/src/share/classes/javax/lang/model/util/AbstractTypeVisitor6.java index c36fda3dec9..aa07280c91a 100644 --- a/langtools/src/share/classes/javax/lang/model/util/AbstractTypeVisitor6.java +++ b/langtools/src/share/classes/javax/lang/model/util/AbstractTypeVisitor6.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2013, 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 @@ -124,6 +124,23 @@ public abstract class AbstractTypeVisitor6 implements TypeVisitor { return visitUnknown(t, p); } + /** + * Visits an {@code AnnotatedType} element by calling {@code + * visit} on the underlying type. + + * @param t {@inheritDoc} + * @param p {@inheritDoc} + * @return the result of calling {@code visit} on the underlying type + * + * @since 1.8 + * + * TODO: should xxxVisitor8 subclasses override this and call + * the defaultAction? + */ + public R visitAnnotated(AnnotatedType t, P p) { + return visit(t.getUnderlyingType(), p); + } + /** * {@inheritDoc} * diff --git a/langtools/src/share/classes/javax/lang/model/util/Types.java b/langtools/src/share/classes/javax/lang/model/util/Types.java index a53e66a53f2..7e41ddf70cd 100644 --- a/langtools/src/share/classes/javax/lang/model/util/Types.java +++ b/langtools/src/share/classes/javax/lang/model/util/Types.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2013, 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 @@ -25,6 +25,9 @@ package javax.lang.model.util; +import java.lang.annotation.Annotation; +import java.lang.annotation.AnnotationTypeMismatchException; +import java.lang.annotation.IncompleteAnnotationException; import java.util.List; import javax.lang.model.element.*; import javax.lang.model.type.*; @@ -298,4 +301,116 @@ public interface Types { * for the given type */ TypeMirror asMemberOf(DeclaredType containing, Element element); + + /** + * Returns the annotations targeting the type. + * + * @param type the targeted type + * @return the type annotations targeting the type + */ + List typeAnnotationsOf(TypeMirror type); + + /** + * Returns the type's annotation for the specified type if + * such an annotation is present, else {@code null}. The + * annotation has to be directly present on this + * element. + * + *

The annotation returned by this method could contain an element + * whose value is of type {@code Class}. + * This value cannot be returned directly: information necessary to + * locate and load a class (such as the class loader to use) is + * not available, and the class might not be loadable at all. + * Attempting to read a {@code Class} object by invoking the relevant + * method on the returned annotation + * will result in a {@link MirroredTypeException}, + * from which the corresponding {@link TypeMirror} may be extracted. + * Similarly, attempting to read a {@code Class[]}-valued element + * will result in a {@link MirroredTypesException}. + * + *

+ * Note: This method is unlike others in this and related + * interfaces. It operates on runtime reflective information — + * representations of annotation types currently loaded into the + * VM — rather than on the representations defined by and used + * throughout these interfaces. Consequently, calling methods on + * the returned annotation object can throw many of the exceptions + * that can be thrown when calling methods on an annotation object + * returned by core reflection. This method is intended for + * callers that are written to operate on a known, fixed set of + * annotation types. + *
+ * + * @param
the annotation type + * @param type the targeted type + * @param annotationType the {@code Class} object corresponding to + * the annotation type + * @return the type's annotation for the specified annotation + * type if present on the type, else {@code null} + * + * @see Element#getAnnotationMirrors() + * @see EnumConstantNotPresentException + * @see AnnotationTypeMismatchException + * @see IncompleteAnnotationException + * @see MirroredTypeException + * @see MirroredTypesException + */ + A typeAnnotationOf(TypeMirror type, Class annotationType); + + /** + * Returns the annotations targeting the method receiver type. + * + * @param type the targeted type + * @return the receiver type of the executable type + */ + TypeMirror receiverTypeOf(ExecutableType type); + + /** + * Returns the type's annotation for the specified executable type + * receiver if such an annotation is present, else {@code null}. The + * annotation has to be directly present on this + * element. + * + *

The annotation returned by this method could contain an element + * whose value is of type {@code Class}. + * This value cannot be returned directly: information necessary to + * locate and load a class (such as the class loader to use) is + * not available, and the class might not be loadable at all. + * Attempting to read a {@code Class} object by invoking the relevant + * method on the returned annotation + * will result in a {@link MirroredTypeException}, + * from which the corresponding {@link TypeMirror} may be extracted. + * Similarly, attempting to read a {@code Class[]}-valued element + * will result in a {@link MirroredTypesException}. + * + *

+ * Note: This method is unlike others in this and related + * interfaces. It operates on runtime reflective information — + * representations of annotation types currently loaded into the + * VM — rather than on the representations defined by and used + * throughout these interfaces. Consequently, calling methods on + * the returned annotation object can throw many of the exceptions + * that can be thrown when calling methods on an annotation object + * returned by core reflection. This method is intended for + * callers that are written to operate on a known, fixed set of + * annotation types. + *
+ * + * @param
the annotation type + * @param type the method type + * @param annotationType the {@code Class} object corresponding to + * the annotation type + * @return the type's annotation for the specified annotation + * type if present on the type, else {@code null} + * + * @see Element#getAnnotationMirrors() + * @see EnumConstantNotPresentException + * @see AnnotationTypeMismatchException + * @see IncompleteAnnotationException + * @see MirroredTypeException + * @see MirroredTypesException + */ + // TODO: no longer needed? + // A receiverTypeAnnotationOf(ExecutableType type, Class annotationType); + } diff --git a/langtools/test/com/sun/javadoc/testAnnotationOptional/TestAnnotationOptional.java b/langtools/test/com/sun/javadoc/testAnnotationOptional/TestAnnotationOptional.java new file mode 100644 index 00000000000..ecd96852281 --- /dev/null +++ b/langtools/test/com/sun/javadoc/testAnnotationOptional/TestAnnotationOptional.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2009 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. + * + * 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. + */ + +/* + * @test + * @summary Make sure that annotations types with optional elements has + * element headers + * @author Mahmood Ali + * @library ../lib/ + * @build JavadocTester + * @build TestAnnotationOptional + * @run main TestAnnotationOptional + */ + +public class TestAnnotationOptional extends JavadocTester { + + //Test information. + private static final String BUG_ID = "NO_BUG_ID_YET"; + + //Javadoc arguments. + private static final String[] ARGS = new String[] { + "-d", BUG_ID, "-sourcepath", SRC_DIR, "-source", "1.5", "pkg" + }; + + //Input for string search tests. + private static final String[][] TEST = { + {BUG_ID + FS + "pkg" + FS + "AnnotationOptional.html", + "" + } + }; + + private static final String[][] NEGATED_TEST = NO_TEST; + + /** + * The entry point of the test. + * @param args the array of command line arguments. + */ + public static void main(String[] args) { + TestAnnotationOptional tester = new TestAnnotationOptional(); + run(tester, ARGS, TEST, NEGATED_TEST); + tester.printSummary(); + } + + /** + * {@inheritDoc} + */ + public String getBugId() { + return BUG_ID; + } + + /** + * {@inheritDoc} + */ + public String getBugName() { + return getClass().getName(); + } +} diff --git a/langtools/test/com/sun/javadoc/testAnnotationOptional/pkg/AnnotationOptional.java b/langtools/test/com/sun/javadoc/testAnnotationOptional/pkg/AnnotationOptional.java new file mode 100644 index 00000000000..7004c1d4344 --- /dev/null +++ b/langtools/test/com/sun/javadoc/testAnnotationOptional/pkg/AnnotationOptional.java @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2009 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. + * + * 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. + */ + +package pkg; + +import java.lang.annotation.*; + +/** + * This is just a test annotation type with optional value element. + * + * @author Mahmood Ali + * @since 1.5 + */ +@Documented public @interface AnnotationOptional { + String value() default ""; +} diff --git a/langtools/test/com/sun/javadoc/typeAnnotations/smoke/TestSmoke.java b/langtools/test/com/sun/javadoc/typeAnnotations/smoke/TestSmoke.java new file mode 100644 index 00000000000..dc8d10b1146 --- /dev/null +++ b/langtools/test/com/sun/javadoc/typeAnnotations/smoke/TestSmoke.java @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2010 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. + * + * 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. + */ + +/* + * @test + * @bug 8006735 + * @ignore + * @summary Smoke test for ensuring that annotations are emited to javadoc + * + * @author Mahmood Ali + * @library ../../lib/ + * @build JavadocTester + * @build TestSmoke + * @run main TestSmoke + */ + +public class TestSmoke extends JavadocTester { + + //Test information. + private static final String BUG_ID = "NOT_SPECIFIED_YET"; + + //Javadoc arguments. + private static final String[] ARGS = new String[] { + "-d", BUG_ID, "-private", "-sourcepath", SRC_DIR, "pkg" + }; + + //Input for string search tests. + private static final String[][] TEST = { + {BUG_ID + FS + "pkg" + FS + "T0x1C.html", "@DA"}, + {BUG_ID + FS + "pkg" + FS + "T0x1D.html", "@DA"}, + {BUG_ID + FS + "pkg" + FS + "T0x0D.html", "@DA"}, + {BUG_ID + FS + "pkg" + FS + "T0x06.html", "@DA"}, + {BUG_ID + FS + "pkg" + FS + "T0x0B.html", "@DA"}, + {BUG_ID + FS + "pkg" + FS + "T0x0F.html", "@DA"}, + {BUG_ID + FS + "pkg" + FS + "T0x20.html", "@DA"}, + {BUG_ID + FS + "pkg" + FS + "T0x22.html", "@DA"}, + {BUG_ID + FS + "pkg" + FS + "T0x10.html", "@DA"}, + {BUG_ID + FS + "pkg" + FS + "T0x10A.html", "@DA"}, + {BUG_ID + FS + "pkg" + FS + "T0x12.html", "@DA"}, + {BUG_ID + FS + "pkg" + FS + "T0x11.html", "@DA"}, + {BUG_ID + FS + "pkg" + FS + "T0x13.html", "@DA"}, + {BUG_ID + FS + "pkg" + FS + "T0x15.html", "@DA"}, + {BUG_ID + FS + "pkg" + FS + "T0x14.html", "@DA"}, + {BUG_ID + FS + "pkg" + FS + "T0x16.html", "@DA"} + }; + + private static final String[][] NEGATED_TEST = { + {BUG_ID + FS + "pkg" + FS + "T0x1C.html", "@A"}, + {BUG_ID + FS + "pkg" + FS + "T0x1D.html", "@A"}, + {BUG_ID + FS + "pkg" + FS + "T0x00.html", "@A"}, + {BUG_ID + FS + "pkg" + FS + "T0x01.html", "@A"}, + {BUG_ID + FS + "pkg" + FS + "T0x02.html", "@A"}, + {BUG_ID + FS + "pkg" + FS + "T0x04.html", "@A"}, + {BUG_ID + FS + "pkg" + FS + "T0x08.html", "@A"}, + {BUG_ID + FS + "pkg" + FS + "T0x0D.html", "@A"}, + {BUG_ID + FS + "pkg" + FS + "T0x06.html", "@A"}, + {BUG_ID + FS + "pkg" + FS + "T0x0B.html", "@A"}, + {BUG_ID + FS + "pkg" + FS + "T0x0F.html", "@A"}, + {BUG_ID + FS + "pkg" + FS + "T0x20.html", "@A"}, + {BUG_ID + FS + "pkg" + FS + "T0x22.html", "@A"}, + {BUG_ID + FS + "pkg" + FS + "T0x10.html", "@A"}, + {BUG_ID + FS + "pkg" + FS + "T0x10A.html", "@A"}, + {BUG_ID + FS + "pkg" + FS + "T0x12.html", "@A"}, + {BUG_ID + FS + "pkg" + FS + "T0x11.html", "@A"}, + {BUG_ID + FS + "pkg" + FS + "T0x13.html", "@A"}, + {BUG_ID + FS + "pkg" + FS + "T0x15.html", "@A"}, + {BUG_ID + FS + "pkg" + FS + "T0x14.html", "@A"}, + {BUG_ID + FS + "pkg" + FS + "T0x16.html", "@A"} + }; + + /** + * The entry point of the test. + * @param args the array of command line arguments. + */ + public static void main(String[] args) { + TestSmoke tester = new TestSmoke(); + run(tester, ARGS, TEST, NEGATED_TEST); + tester.printSummary(); + } + + /** + * {@inheritDoc} + */ + public String getBugId() { + return BUG_ID; + } + + /** + * {@inheritDoc} + */ + public String getBugName() { + return getClass().getName(); + } +} diff --git a/langtools/test/com/sun/javadoc/typeAnnotations/smoke/pkg/TargetTypes.java b/langtools/test/com/sun/javadoc/typeAnnotations/smoke/pkg/TargetTypes.java new file mode 100644 index 00000000000..24c93e3ba08 --- /dev/null +++ b/langtools/test/com/sun/javadoc/typeAnnotations/smoke/pkg/TargetTypes.java @@ -0,0 +1,214 @@ +/* + * Copyright (c) 2010 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. + * + * 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. + */ + +package pkg; + +import java.lang.annotation.*; +import static java.lang.annotation.ElementType.*; +import static java.lang.annotation.RetentionPolicy.*; + +import java.util.*; +import java.io.*; + +/* + * @summary compiler accepts all values + * @author Mahmood Ali + * @author Yuri Gaevsky + */ + +@Target({TYPE_USE}) +@Retention(RetentionPolicy.RUNTIME) +@interface A {} + +@Target({TYPE_USE}) +@Retention(RetentionPolicy.RUNTIME) +@Documented +@interface DA {} + +/** wildcard bound */ +class T0x1C { + void m0x1C(List lst) {} +} + +/** wildcard bound generic/array */ +class T0x1D { + void m0x1D(List> lst) {} +} + +/** typecast */ +class T0x00 { + void m0x00(Long l1) { + Object l2 = (@A @DA Long) l1; + } +} + +/** typecast generic/array */ +class T0x01 { + void m0x01(List list) { + List l = (List<@A @DA T>) list; + } +} + +/** instanceof */ +class T0x02 { + boolean m0x02(String s) { + return (s instanceof @A @DA String); + } +} + +/** object creation (new) */ +class T0x04 { + void m0x04() { + new @A @DA ArrayList(); + } +} + +/** local variable */ +class T0x08 { + void m0x08() { + @A @DA String s = null; + } +} + +/** method parameter generic/array */ +class T0x0D { + void m0x0D(HashMap<@A @DA Object, List<@A @DA List<@A @DA Class>>> s1) {} +} + +/** method receiver */ +class T0x06 { + void m0x06(@A @DA T0x06 this) {} +} + +/** method return type generic/array */ +class T0x0B { + Class<@A @DA Object> m0x0B() { return null; } +} + +/** field generic/array */ +class T0x0F { + HashMap<@A @DA Object, @A @DA Object> c1; +} + +/** method type parameter */ +class T0x20 { + <@A @DA T, @A @DA U> void m0x20() {} +} + +/** class type parameter */ +class T0x22<@A @DA T, @A @DA U> { +} + +/** class type parameter bound */ +class T0x10 { +} + +class T0x10A { +} + +/** method type parameter bound */ +class T0x12 { + void m0x12() {} +} + +/** class type parameter bound generic/array */ +class T0x11> { +} + +/** method type parameter bound generic/array */ +class T0x13 { + static > T m0x13() { + return null; + } +} + +/** class extends/implements generic/array */ +class T0x15 extends ArrayList<@A @DA T> { +} + +/** type test (instanceof) generic/array */ +class T0x03 { + void m0x03(T typeObj, Object obj) { + boolean ok = obj instanceof String @A @DA []; + } +} + +/** object creation (new) generic/array */ +class T0x05 { + void m0x05() { + new ArrayList<@A @DA T>(); + } +} + +/** local variable generic/array */ +class T0x09 { + void g() { + List<@A @DA String> l = null; + } + + void a() { + String @A @DA [] as = null; + } +} + +/** type argument in constructor call generic/array */ +class T0x19 { + T0x19() {} + + void g() { + new > T0x19(); + } +} + +/** type argument in method call generic/array */ +class T0x1B { + void m0x1B() { + Collections.emptyList(); + } +} + +/** type argument in constructor call */ +class T0x18 { + T0x18() {} + + void m() { + new <@A @DA Integer> T0x18(); + } +} + +/** type argument in method call */ +class T0x1A { + public static T m() { return null; } + static void m0x1A() { + T0x1A.<@A @DA Integer, @A @DA Short>m(); + } +} + +/** class extends/implements */ +class T0x14 extends @A @DA Thread implements @A @DA Serializable, @A @DA Cloneable { +} + +/** exception type in throws */ +class T0x16 { + void m0x16() throws @A @DA Exception {} +} diff --git a/langtools/test/tools/javac/7129225/TestImportStar.java b/langtools/test/tools/javac/7129225/TestImportStar.java index c22e5b9d4ec..eaca9ed23c3 100644 --- a/langtools/test/tools/javac/7129225/TestImportStar.java +++ b/langtools/test/tools/javac/7129225/TestImportStar.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2013, 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 @@ -30,7 +30,7 @@ * @build JavacTestingAbstractProcessor * @compile/fail/ref=NegTest.ref -XDrawDiagnostics TestImportStar.java * @compile Anno.java AnnoProcessor.java - * @compile/ref=TestImportStar.ref -XDrawDiagnostics -processor AnnoProcessor -proc:only TestImportStar.java + * @compile/fail/ref=TestImportStar.ref -XDrawDiagnostics -processor AnnoProcessor -proc:only TestImportStar.java */ //The @compile/fail... verifies that the fix doesn't break the normal compilation of import xxx.* diff --git a/langtools/test/tools/javac/7129225/TestImportStar.ref b/langtools/test/tools/javac/7129225/TestImportStar.ref index 6248faddde8..5b3c75d7d89 100644 --- a/langtools/test/tools/javac/7129225/TestImportStar.ref +++ b/langtools/test/tools/javac/7129225/TestImportStar.ref @@ -1,3 +1,4 @@ - compiler.note.proc.messager: RUNNING - lastRound = false TestImportStar.java:39:1: compiler.err.doesnt.exist: xxx - compiler.note.proc.messager: RUNNING - lastRound = true +1 error \ No newline at end of file diff --git a/langtools/test/tools/javac/T6873845.java b/langtools/test/tools/javac/T6873845.java index ff84028326f..b1cfea6d203 100644 --- a/langtools/test/tools/javac/T6873845.java +++ b/langtools/test/tools/javac/T6873845.java @@ -19,8 +19,8 @@ public class T6873845 { if (out.contains("sunapi")) throw new Exception("unexpected output for -X"); - String warn1 = "T6873845.java:72:9: compiler.warn.sun.proprietary: sun.misc.Unsafe" + newline; - String warn2 = "T6873845.java:77:9: compiler.warn.sun.proprietary: sun.misc.Unsafe" + newline; + String warn1 = "T6873845.java:73:9: compiler.warn.sun.proprietary: sun.misc.Unsafe" + newline; + String warn2 = "T6873845.java:78:9: compiler.warn.sun.proprietary: sun.misc.Unsafe" + newline; String note1 = "- compiler.note.sunapi.filename: T6873845.java" + newline; String note2 = "- compiler.note.sunapi.recompile" + newline; @@ -52,7 +52,8 @@ public class T6873845 { args.add(0, "-XDrawDiagnostics"); String out = compile(args); if (!out.equals(expect)) - throw new Exception("unexpected output from compiler"); + throw new Exception("unexpected output from compiler; expected: " + expect + + "\n found: " + out); } String compile(List args) throws Exception{ diff --git a/langtools/test/tools/javac/T6985181.java b/langtools/test/tools/javac/T6985181.java new file mode 100644 index 00000000000..2211ff45fc2 --- /dev/null +++ b/langtools/test/tools/javac/T6985181.java @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2010, 2013, 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. + * + * 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. + */ + +/* + * @test + * @bug 6985181 + * @summary Annotations lost from classfile + */ + +import java.io.*; +import java.util.*; + +public class T6985181 { + public static void main(String... args) throws Exception{ + new T6985181().run(); + } + + public void run() throws Exception { + String code = "@java.lang.annotation.Target(java.lang.annotation.ElementType.TYPE_PARAMETER)\n" + + "@interface Simple { }\n" + + "interface Test<@Simple T> { }"; + + File srcFile = writeFile("Test.java", code); + File classesDir = new File("classes"); + classesDir.mkdirs(); + compile("-d", classesDir.getPath(), srcFile.getPath()); + String out = javap(new File(classesDir, srcFile.getName().replace(".java", ".class"))); + if (!out.contains("RuntimeInvisibleTypeAnnotations")) + throw new Exception("RuntimeInvisibleTypeAnnotations not found"); + } + + void compile(String... args) throws Exception { + StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter(sw); + int rc = com.sun.tools.javac.Main.compile(args, pw); + pw.close(); + String out = sw.toString(); + if (out.length() > 0) + System.err.println(out); + if (rc != 0) + throw new Exception("Compilation failed: rc=" + rc); + } + + String javap(File classFile) throws Exception { + StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter(sw); + String[] args = { "-v", classFile.getPath() }; + int rc = com.sun.tools.javap.Main.run(args, pw); + pw.close(); + String out = sw.toString(); + if (out.length() > 0) + System.err.println(out); + if (rc != 0) + throw new Exception("javap failed: rc=" + rc); + return out; + } + + File writeFile(String path, String body) throws IOException { + File f = new File(path); + FileWriter out = new FileWriter(f); + try { + out.write(body); + } finally { + out.close(); + } + return f; + } +} diff --git a/langtools/test/tools/javac/annotations/6881115/T6881115.java b/langtools/test/tools/javac/annotations/6881115/T6881115.java index 2f779c4ac46..0c917f15c64 100644 --- a/langtools/test/tools/javac/annotations/6881115/T6881115.java +++ b/langtools/test/tools/javac/annotations/6881115/T6881115.java @@ -1,3 +1,6 @@ +import java.lang.annotation.Target; +import java.lang.annotation.ElementType; + /* * @test /nodynamiccopyright/ * @bug 6881115 6976649 @@ -6,15 +9,18 @@ * @compile/fail/ref=T6881115.out -XDrawDiagnostics T6881115.java */ +@Target({ElementType.TYPE, ElementType.TYPE_PARAMETER, ElementType.ANNOTATION_TYPE}) @interface A { B b() default @B(b2 = 1, b2 = 2); B[] b_arr() default {@B(), @B(b2 = 1, b2 = 2)}; } + @interface B { String b1(); int b2(); } + @A(b = @B(b2 = 1, b2 = 2), b_arr = {@B(), @B(b2 = 1, b2 = 2)}) -class T6881115 {} +class T6881115<@A(b = @B(b2 = 1, b2 = 2), + b_arr = {@B(), @B(b2 = 1, b2 = 2)}) X> {} diff --git a/langtools/test/tools/javac/annotations/6881115/T6881115.out b/langtools/test/tools/javac/annotations/6881115/T6881115.out index 93b90cff473..a924a311590 100644 --- a/langtools/test/tools/javac/annotations/6881115/T6881115.out +++ b/langtools/test/tools/javac/annotations/6881115/T6881115.out @@ -1,11 +1,16 @@ -T6881115.java:10:30: compiler.err.duplicate.annotation.member.value: b2, B -T6881115.java:10:19: compiler.err.annotation.missing.default.value: B, b1 -T6881115.java:11:26: compiler.err.annotation.missing.default.value.1: B, b1,b2 -T6881115.java:11:43: compiler.err.duplicate.annotation.member.value: b2, B -T6881115.java:11:32: compiler.err.annotation.missing.default.value: B, b1 -T6881115.java:17:19: compiler.err.duplicate.annotation.member.value: b2, B -T6881115.java:17:8: compiler.err.annotation.missing.default.value: B, b1 -T6881115.java:18:13: compiler.err.annotation.missing.default.value.1: B, b1,b2 -T6881115.java:18:30: compiler.err.duplicate.annotation.member.value: b2, B -T6881115.java:18:19: compiler.err.annotation.missing.default.value: B, b1 -10 errors +T6881115.java:14:30: compiler.err.duplicate.annotation.member.value: b2, B +T6881115.java:14:19: compiler.err.annotation.missing.default.value: B, b1 +T6881115.java:15:26: compiler.err.annotation.missing.default.value.1: B, b1,b2 +T6881115.java:15:43: compiler.err.duplicate.annotation.member.value: b2, B +T6881115.java:15:32: compiler.err.annotation.missing.default.value: B, b1 +T6881115.java:23:19: compiler.err.duplicate.annotation.member.value: b2, B +T6881115.java:23:8: compiler.err.annotation.missing.default.value: B, b1 +T6881115.java:24:13: compiler.err.annotation.missing.default.value.1: B, b1,b2 +T6881115.java:24:30: compiler.err.duplicate.annotation.member.value: b2, B +T6881115.java:24:19: compiler.err.annotation.missing.default.value: B, b1 +T6881115.java:25:34: compiler.err.duplicate.annotation.member.value: b2, B +T6881115.java:25:23: compiler.err.annotation.missing.default.value: B, b1 +T6881115.java:26:28: compiler.err.annotation.missing.default.value.1: B, b1,b2 +T6881115.java:26:45: compiler.err.duplicate.annotation.member.value: b2, B +T6881115.java:26:34: compiler.err.annotation.missing.default.value: B, b1 +15 errors diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/6967002/T6967002.java b/langtools/test/tools/javac/annotations/typeAnnotations/6967002/T6967002.java new file mode 100644 index 00000000000..a0cbc78c690 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/6967002/T6967002.java @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2010, 2013, 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. + * + * 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. + */ + +/* + * @test + * @bug 6967002 8006775 + * @summary JDK7 b99 javac compilation error (java.lang.AssertionError) + * @author Maurizio Cimadamore + * @compile/fail/ref=T6967002.out -XDrawDiagnostics T6967002.java + */ +class Test { + private static void m(byte[] octets) { + return m(octets..., ?); + } +} diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/6967002/T6967002.out b/langtools/test/tools/javac/annotations/typeAnnotations/6967002/T6967002.out new file mode 100644 index 00000000000..18b75307f04 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/6967002/T6967002.out @@ -0,0 +1,8 @@ +T6967002.java:33:22: compiler.err.expected: ')' +T6967002.java:33:25: compiler.err.illegal.start.of.expr +T6967002.java:33:28: compiler.err.illegal.start.of.expr +T6967002.java:33:29: compiler.err.illegal.start.of.expr +T6967002.java:33:27: compiler.err.not.stmt +T6967002.java:33:30: compiler.err.expected: ';' +T6967002.java:35:2: compiler.err.premature.eof +7 errors diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/InnerClass.java b/langtools/test/tools/javac/annotations/typeAnnotations/InnerClass.java new file mode 100644 index 00000000000..53cab9fa589 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/InnerClass.java @@ -0,0 +1,65 @@ +import java.lang.annotation.ElementType; + +/* + * Copyright (c) 2009, 2013, 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. + * + * 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. + */ + +/* + * @test + * @bug 6843077 8006775 + * @summary compiler crashes when visiting inner classes + * @author Mahmood Ali + * @compile InnerClass.java + */ + +import java.lang.annotation.*; + +class InnerClass { + + InnerClass() {} + InnerClass(Object o) {} + + private void a() { + new Object() { + public void method() { } + }; + } + + Object f1 = new InnerClass() { + void method() { } + }; + + Object f2 = new InnerClass() { + <@A R> void method() { } + }; + + Object f3 = new InnerClass(null) { + void method() { } + }; + + Object f4 = new InnerClass(null) { + <@A R> void method() { } + }; + + @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) + @interface A { } +} diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/MultipleTargets.java b/langtools/test/tools/javac/annotations/typeAnnotations/MultipleTargets.java new file mode 100644 index 00000000000..041366cd701 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/MultipleTargets.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2008, 2013, 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. + * + * 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. + */ + +/* + * @test + * @bug 6843077 8006775 + * @summary check that type annotations may appear on void method if it is a + * method annotation too. + * @author Mahmood Ali + * @compile MultipleTargets.java + */ + +import java.lang.annotation.Target; +import java.lang.annotation.ElementType; + +class TypeUseTarget { + @A void voidMethod() { } +} + +@Target({ElementType.TYPE_USE, ElementType.METHOD}) +@interface A { } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/TargetTypes.java b/langtools/test/tools/javac/annotations/typeAnnotations/TargetTypes.java new file mode 100644 index 00000000000..f808a8d4cda --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/TargetTypes.java @@ -0,0 +1,206 @@ +/* + * Copyright (c) 2009 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. + * + * 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. + */ +import java.lang.annotation.*; +import static java.lang.annotation.ElementType.*; +import static java.lang.annotation.RetentionPolicy.*; + +import java.util.*; +import java.io.*; + +/* + * @test + * @summary compiler accepts all values + * @author Mahmood Ali + * @author Yuri Gaevsky + * @compile TargetTypes.java + */ + +@Target({TYPE_USE, TYPE_PARAMETER, TYPE}) +@Retention(RetentionPolicy.RUNTIME) +@interface A {} + +/** wildcard bound */ +class T0x1C { + void m0x1C(List lst) {} +} + +/** wildcard bound generic/array */ +class T0x1D { + void m0x1D(List> lst) {} +} + +/** typecast */ +class T0x00 { + void m0x00(Long l1) { + Object l2 = (@A Long) l1; + } +} + +/** typecast generic/array */ +class T0x01 { + void m0x01(List list) { + List l = (List<@A T>) list; + } +} + +/** instanceof */ +class T0x02 { + boolean m0x02(String s) { + return (s instanceof @A String); + } +} + +/** object creation (new) */ +class T0x04 { + void m0x04() { + new @A ArrayList(); + } +} + +/** local variable */ +class T0x08 { + void m0x08() { + @A String s = null; + } +} + +/** method parameter generic/array */ +class T0x0D { + void m0x0D(HashMap<@A Object, List<@A List<@A Class>>> s1) {} +} + +/** method receiver */ +class T0x06 { + void m0x06(@A T0x06 this) {} +} + +/** method return type generic/array */ +class T0x0B { + Class<@A Object> m0x0B() { return null; } +} + +/** field generic/array */ +class T0x0F { + HashMap<@A Object, @A Object> c1; +} + +/** method type parameter */ +class T0x20 { + <@A T, @A U> void m0x20() {} +} + +/** class type parameter */ +class T0x22<@A T, @A U> { +} + +/** class type parameter bound */ +class T0x10 { +} + +/** method type parameter bound */ +class T0x12 { + void m0x12() {} +} + +/** class type parameter bound generic/array */ +class T0x11> { +} + + +/** method type parameter bound generic/array */ +class T0x13 { + static > T m0x13() { + return null; + } +} + +/** class extends/implements generic/array */ +class T0x15 extends ArrayList<@A T> { +} + +/** type test (instanceof) generic/array */ +class T0x03 { + void m0x03(T typeObj, Object obj) { + boolean ok = obj instanceof String @A []; + } +} + +/** object creation (new) generic/array */ +class T0x05 { + void m0x05() { + new ArrayList<@A T>(); + } +} + +/** local variable generic/array */ +class T0x09 { + void g() { + List<@A String> l = null; + } + + void a() { + String @A [] as = null; + } +} + +/** type argument in constructor call generic/array */ +class T0x19 { + T0x19() {} + + void g() { + new > T0x19(); + } +} + +/** type argument in method call generic/array */ +class T0x1B { + void m0x1B() { + Collections.emptyList(); + } +} + +/** type argument in constructor call */ +class T0x18 { + T0x18() {} + + void m() { + new <@A Integer> T0x18(); + } +} + +/** type argument in method call */ +class T0x1A { + public static T m() { return null; } + static void m0x1A() { + T0x1A.<@A Integer, @A Short>m(); + } +} + +/** class extends/implements */ +class T0x14 extends @A Object implements @A Serializable, @A Cloneable { +} + +/** exception type in throws */ +class T0x16 { + void m0x16() throws @A Exception {} +} diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/TypeParameterTarget.java b/langtools/test/tools/javac/annotations/typeAnnotations/TypeParameterTarget.java new file mode 100644 index 00000000000..100331c1090 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/TypeParameterTarget.java @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2008, 2013, 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. + * + * 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. + */ + +/* + * @test + * @bug 6843077 8006775 + * @summary check that type annotations may appear on all type parameter + * @author Mahmood Ali + * @compile TypeParameterTarget.java + */ + +import java.lang.annotation.Target; +import java.lang.annotation.ElementType; + +class TypeUseTarget<@A K extends Object> { + String[] field; + + <@A K, @A V> String genericMethod(K k) { return null; } +} + +interface MyInterface { } + +@interface MyAnnotation { } + +@Target(ElementType.TYPE_PARAMETER) +@interface A { } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/TypeProcOnly.java b/langtools/test/tools/javac/annotations/typeAnnotations/TypeProcOnly.java new file mode 100644 index 00000000000..73d28971ee0 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/TypeProcOnly.java @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2009 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. + * + * 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. + */ +import java.io.*; +import java.util.Set; +import java.util.HashSet; + +import javax.annotation.processing.*; +import javax.lang.model.SourceVersion; +import javax.lang.model.element.*; +import javax.lang.model.util.ElementFilter; + +import com.sun.source.util.JavacTask; +import com.sun.source.util.TaskEvent; +import com.sun.source.util.TaskListener; +import com.sun.source.util.TreePath; +import com.sun.tools.javac.main.JavaCompiler; +import com.sun.tools.javac.main.JavaCompiler.CompileState; +import com.sun.tools.javac.processing.JavacProcessingEnvironment; +import com.sun.tools.javac.util.Context; + +/* + * @test + * @summary test that type processors are run when -proc:only is passed. + * This class implements the functionality of a type processor, as previously + * embodied by the AbstractTypeProcessor class. + * + * @author Mahmood Ali + * @author Werner Dietl + */ +@SupportedAnnotationTypes("*") +public class TypeProcOnly extends AbstractProcessor { + private static final String INDICATOR = "INDICATOR"; + + private final AttributionTaskListener listener = new AttributionTaskListener(); + private final Set elements = new HashSet(); + + @Override + public final void init(ProcessingEnvironment env) { + super.init(env); + JavacTask.instance(env).addTaskListener(listener); + Context ctx = ((JavacProcessingEnvironment)processingEnv).getContext(); + JavaCompiler compiler = JavaCompiler.instance(ctx); + compiler.shouldStopPolicyIfNoError = CompileState.max( + compiler.shouldStopPolicyIfNoError, + CompileState.FLOW); + } + + @Override + public final boolean process(Set annotations, + RoundEnvironment roundEnv) { + for (TypeElement elem : ElementFilter.typesIn(roundEnv.getRootElements())) { + elements.add(elem.getQualifiedName()); + } + return false; + } + + @Override + public SourceVersion getSupportedSourceVersion() { + return SourceVersion.latest(); + } + + private final class AttributionTaskListener implements TaskListener { + @Override + public void started(TaskEvent e) { } + + @Override + public void finished(TaskEvent e) { + if (e.getKind() != TaskEvent.Kind.ANALYZE) + return; + + if (!elements.remove(e.getTypeElement().getQualifiedName())) + return; + + System.out.println(INDICATOR); + } + } + + + private static File writeTestFile() throws IOException { + File f = new File("Test.java"); + PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(f))); + out.println("class Test { }"); + out.close(); + return f; + } + + public static void main(String[] args) throws Exception { + PrintStream prevOut = System.out; + + ByteArrayOutputStream bytes = new ByteArrayOutputStream(); + PrintStream out = new PrintStream(bytes); + System.setOut(out); + + try { + File f = writeTestFile(); + com.sun.tools.javac.Main.compile(new String[] {"-proc:only", "-processor", "TypeProcOnly", f.getAbsolutePath()}); + } finally { + System.setOut(prevOut); + } + + if (bytes.toString().trim().equals(INDICATOR)) { + System.out.println("PASSED"); + } else { + throw new Exception("Processor did not run correctly. Output: " + bytes); + } + } +} diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/TypeUseTarget.java b/langtools/test/tools/javac/annotations/typeAnnotations/TypeUseTarget.java new file mode 100644 index 00000000000..4ec21c0ef2a --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/TypeUseTarget.java @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2008, 2013, 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. + * + * 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. + */ + +/* + * @test + * @bug 6843077 8006775 + * @summary check that type annotations may appear on all type declarations + * @author Mahmood Ali + * @compile TypeUseTarget.java + */ + +import java.lang.annotation.Target; +import java.lang.annotation.ElementType; + +@A +class TypeUseTarget { + @A String @A [] field; + + @A String test(@A TypeUseTarget this, @A String param, @A String @A ... vararg) { + @A Object o = new @A String @A [3]; + TypeUseTarget<@A String> target; + return (@A String) null; + } + + @A String genericMethod(K k) { return null; } + @Decl @A String genericMethod1(K k) { return null; } + @A @Decl String genericMethod2(K k) { return null; } + @Decl @A String genericMethod3(K k) { return null; } + @Decl String genericMethod4(K k) { return null; } + @A @Decl String genericMethod5(K k) { return null; } +} + +@A +interface MyInterface { } + +@A +@interface MyAnnotation { } + +@Target(ElementType.TYPE_USE) +@interface A { } + +@interface Decl { } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/api/AnnotatedArrayOrder.java b/langtools/test/tools/javac/annotations/typeAnnotations/api/AnnotatedArrayOrder.java new file mode 100644 index 00000000000..947b46536cc --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/api/AnnotatedArrayOrder.java @@ -0,0 +1,161 @@ +/* + * Copyright (c) 2010 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. + * + * 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. + */ + +/* + * @test + * @summary Checks the annotation types targeting array types + */ + +import com.sun.tools.javac.api.JavacTool; +import java.io.File; +import java.io.PrintWriter; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.HashMap; +import java.lang.annotation.*; +import javax.tools.JavaFileManager; +import javax.tools.JavaFileObject; +import com.sun.source.tree.*; +import com.sun.source.util.JavacTask; +import com.sun.source.util.TreeScanner; +import javax.tools.StandardJavaFileManager; + + +public class AnnotatedArrayOrder { + public static void main(String[] args) throws Exception { + PrintWriter out = new PrintWriter(System.out, true); + JavacTool tool = JavacTool.create(); + StandardJavaFileManager fm = tool.getStandardFileManager(null, null, null); + File testSrc = new File(System.getProperty("test.src")); + Iterable f = + fm.getJavaFileObjectsFromFiles(Arrays.asList(new File(testSrc, "AnnotatedArrayOrder.java"))); + JavacTask task = tool.getTask(out, fm, null, null, null, f); + Iterable trees = task.parse(); + out.flush(); + + Scanner s = new Scanner(); + for (CompilationUnitTree t: trees) + s.scan(t, null); + + } + + private static class Scanner extends TreeScanner { + public Void visitCompilationUnit(CompilationUnitTree node, Void ignore) { + super.visitCompilationUnit(node, ignore); + if (!expectedLocations.isEmpty()) { + throw new AssertionError("Didn't found all annotations: " + expectedLocations); + } + return null; + } + + private void testAnnotations(List annos, int found) { + String annotation = annos.get(0).toString(); + + if (!expectedLocations.containsKey(annotation)) + throw new AssertionError("Found unexpected annotation: " + annotation + expectedLocations); + + int expected = expectedLocations.get(annotation); + if (found != expected) + throw new AssertionError("The expected array length for this error doesn't match"); + + expectedLocations.remove(annotation); + } + + public Void visitAnnotatedType(AnnotatedTypeTree node, Void ignore) { + testAnnotations(node.getAnnotations(), arrayLength(node)); + return super.visitAnnotatedType(node, ignore); + } + + private int arrayLength(Tree tree) { + switch (tree.getKind()) { + case ARRAY_TYPE: + return 1 + arrayLength(((ArrayTypeTree)tree).getType()); + case ANNOTATED_TYPE: + return arrayLength(((AnnotatedTypeTree)tree).getUnderlyingType()); + default: + return 0; + } + } + } + + // expectedLocations values: + static Map expectedLocations = new HashMap(); + + // visited code + @A String @C [] @B [] field; + static { + // Shouldn't find @A(), as it is field annotation + expectedLocations.put("@B()", 1); + expectedLocations.put("@C()", 2); + } + + List<@D String @F [] @E []> typearg; + static { + expectedLocations.put("@D()", 0); + expectedLocations.put("@E()", 1); + expectedLocations.put("@F()", 2); + } + + void varargSimple(@G String @H ... vararg1) { } + static { + // Shouldn't find @G(), as it is a parameter annotation + expectedLocations.put("@H()", 1); + } + + void varargLong(@I String @L [] @K [] @J ... vararg2) { } + static { + // Shouldn't find @I(), as it is a parameter annotation + expectedLocations.put("@J()", 1); + expectedLocations.put("@K()", 2); + expectedLocations.put("@L()", 3); + } + + @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) + @interface A {} + @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) + @interface B {} + @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) + @interface C {} + + @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) + @interface D {} + @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) + @interface E {} + @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) + @interface F {} + + @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) + @interface G {} + @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) + @interface H {} + @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) + @interface I {} + + @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) + @interface J {} + @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) + @interface K {} + @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) + @interface L {} +} diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/api/ArrayCreationTree.java b/langtools/test/tools/javac/annotations/typeAnnotations/api/ArrayCreationTree.java new file mode 100644 index 00000000000..55f81eb7cf6 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/api/ArrayCreationTree.java @@ -0,0 +1,152 @@ +/* + * Copyright (c) 2010 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. + * + * 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. + */ + +/* + * @test + * @summary Checks that the interaction between annotated and unannotated + * array levels in array creation trees + */ + +import com.sun.tools.javac.api.JavacTool; +import com.sun.tools.javac.tree.JCTree.JCNewArray; +import java.lang.annotation.*; +import java.io.File; +import java.io.PrintWriter; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.HashMap; +import javax.tools.JavaFileManager; +import javax.tools.JavaFileObject; +import com.sun.source.tree.*; +import com.sun.source.util.JavacTask; +import com.sun.source.util.TreeScanner; +import javax.tools.StandardJavaFileManager; + + +public class ArrayCreationTree { + public static void main(String[] args) throws Exception { + PrintWriter out = new PrintWriter(System.out, true); + JavacTool tool = JavacTool.create(); + StandardJavaFileManager fm = tool.getStandardFileManager(null, null, null); + File testSrc = new File(System.getProperty("test.src")); + Iterable f = + fm.getJavaFileObjectsFromFiles(Arrays.asList(new File(testSrc, "ArrayCreationTree.java"))); + JavacTask task = tool.getTask(out, fm, null, null, null, f); + Iterable trees = task.parse(); + out.flush(); + + Scanner s = new Scanner(); + for (CompilationUnitTree t: trees) + s.scan(t, null); + + } + + private static class Scanner extends TreeScanner { + int foundAnnotations = 0; + public Void visitCompilationUnit(CompilationUnitTree node, Void ignore) { + super.visitCompilationUnit(node, ignore); + if (foundAnnotations != expectedAnnotations) { + throw new AssertionError("Expected " + expectedAnnotations + + " annotations but found: " + foundAnnotations); + } + return null; + } + + private void testAnnotations(List annos, int found) { + if (annos.isEmpty()) return; + + String annotation = annos.get(0).toString(); + foundAnnotations++; + + int expected = -1; + if (annotation.equals("@A()")) + expected = 0; + else if (annotation.equals("@B()")) + expected = 1; + else if (annotation.equals("@C()")) + expected = 2; + else + throw new AssertionError("found an unexpected annotation: " + annotation); + if (found != expected) { + throw new AssertionError("Unexpected found length" + + ", found " + found + " but expected " + expected); + } + } + + public Void visitAnnotatedType(AnnotatedTypeTree node, Void ignore) { + testAnnotations(node.getAnnotations(), arrayLength(node)); + return super.visitAnnotatedType(node, ignore); + } + + public Void visitNewArray(NewArrayTree node, Void ignore) { + // the Tree API hasn't been updated to expose annotations yet + JCNewArray newArray = (JCNewArray)node; + int totalLength = node.getDimensions().size() + + arrayLength(node.getType()) + + ((newArray.getInitializers() != null) ? 1 : 0); + testAnnotations(newArray.annotations, totalLength); + int count = 0; + for (List annos : newArray.dimAnnotations) { + testAnnotations(annos, totalLength - count); + count++; + } + return super.visitNewArray(node, ignore); + } + + private int arrayLength(Tree tree) { + // TODO: the tree is null when called with node.getType(). Why? + if (tree==null) return -1; + switch (tree.getKind()) { + case ARRAY_TYPE: + return 1 + arrayLength(((ArrayTypeTree)tree).getType()); + case ANNOTATED_TYPE: + return arrayLength(((AnnotatedTypeTree)tree).getUnderlyingType()); + default: + return 0; + } + } + } + + static int expectedAnnotations = 21; + + Object a1 = new @A Object @C [2] @B [1]; + Object b1 = new @A Object @C [2] @B [ ]; + Object c1 = new @A Object @C [ ] @B [ ] { }; + + Object a2 = new @A Object @C [2] [1]; + Object b2 = new @A Object @C [2] [ ]; + Object c2 = new @A Object @C [ ] [ ] { }; + + Object a3 = new @A Object [2] @B [1]; + Object b3 = new @A Object [2] @B [ ]; + Object c3 = new @A Object [ ] @B [ ] { }; + + @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) + @interface A {} + @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) + @interface B {} + @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) + @interface C {} + +} diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/api/ArrayPositionConsistency.java b/langtools/test/tools/javac/annotations/typeAnnotations/api/ArrayPositionConsistency.java new file mode 100644 index 00000000000..7d00ef3aa19 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/api/ArrayPositionConsistency.java @@ -0,0 +1,141 @@ +/* + * Copyright (c) 2010 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. + * + * 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. + */ + +/* + * @test + * @summary Checks that the interaction between annotated and unannotated + * array levels + */ + +import com.sun.tools.javac.api.JavacTool; +import java.lang.annotation.*; +import java.io.File; +import java.io.PrintWriter; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.HashMap; +import javax.tools.JavaFileManager; +import javax.tools.JavaFileObject; +import com.sun.source.tree.*; +import com.sun.source.util.JavacTask; +import com.sun.source.util.TreeScanner; +import javax.tools.StandardJavaFileManager; + + +public class ArrayPositionConsistency { + public static void main(String[] args) throws Exception { + PrintWriter out = new PrintWriter(System.out, true); + JavacTool tool = JavacTool.create(); + StandardJavaFileManager fm = tool.getStandardFileManager(null, null, null); + File testSrc = new File(System.getProperty("test.src")); + Iterable f = + fm.getJavaFileObjectsFromFiles(Arrays.asList(new File(testSrc, "ArrayPositionConsistency.java"))); + JavacTask task = tool.getTask(out, fm, null, null, null, f); + Iterable trees = task.parse(); + out.flush(); + + Scanner s = new Scanner(); + for (CompilationUnitTree t: trees) + s.scan(t, null); + + } + + private static class Scanner extends TreeScanner { + int foundAnnotations = 0; + public Void visitCompilationUnit(CompilationUnitTree node, Void ignore) { + super.visitCompilationUnit(node, ignore); + if (foundAnnotations != expectedAnnotations) { + throw new AssertionError("Expected " + expectedAnnotations + + " annotations but found: " + foundAnnotations); + } + return null; + } + + private void testAnnotations(List annos, int found) { + String annotation = annos.get(0).toString(); + foundAnnotations++; + + int expected = -1; + if (annotation.equals("@A()")) + expected = 0; + else if (annotation.equals("@B()")) + expected = 1; + else if (annotation.equals("@C()")) + expected = 2; + else + throw new AssertionError("found an unexpected annotation: " + annotation); + if (found != expected) { + throw new AssertionError("Unexpected found length" + + ", found " + found + " but expected " + expected); + } + } + + public Void visitAnnotatedType(AnnotatedTypeTree node, Void ignore) { + testAnnotations(node.getAnnotations(), arrayLength(node)); + return super.visitAnnotatedType(node, ignore); + } + + private int arrayLength(Tree tree) { + switch (tree.getKind()) { + case ARRAY_TYPE: + return 1 + arrayLength(((ArrayTypeTree)tree).getType()); + case ANNOTATED_TYPE: + return arrayLength(((AnnotatedTypeTree)tree).getUnderlyingType()); + default: + return 0; + } + } + } + + static int expectedAnnotations = 23; + + // visited code + @A String @C [] @B [] field1; + @A String @C [] [] field2; + @A String [] @B [] field3; + String [] @B [] field4; + + @A List @C [] @B [] genfield1; + @A List @C [] [] genfield2; + @A List [] @B [] genfield3; + List [] @B [] genfield4; + + List<@A String @C [] @B []> typearg1; + List<@A String @C [] []> typearg2; + List<@A String [] @B []> typearg3; + List< String [] @B []> typearg4; + + void vararg1(@A String @C [] @B ... arg) {} + void vararg2(@A String @C [] ... arg) {} + void vararg3(@A String [] @B ... arg) {} + void vararg4( String [] @B ... arg) {} + + @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) + @interface A {} + @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) + @interface B {} + @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) + @interface C {} + +} diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/attribution/Scopes.java b/langtools/test/tools/javac/annotations/typeAnnotations/attribution/Scopes.java new file mode 100644 index 00000000000..da01c38d096 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/attribution/Scopes.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2008, 2013, 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. + * + * 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. + */ + +/* + * @test + * @bug 6843077 8006775 + * @summary test scopes of attribution + * @author Mahmood Ali + * @compile Scopes.java + */ +class Scopes { + + void test(@A(VALUE) Scopes this) { } + void test1(@A(value=VALUE) Scopes this) { } + + private static final int VALUE = 1; + @interface A { int value(); } +} diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/classfile/ClassfileTestHelper.java b/langtools/test/tools/javac/annotations/typeAnnotations/classfile/ClassfileTestHelper.java new file mode 100644 index 00000000000..a06407e0144 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/classfile/ClassfileTestHelper.java @@ -0,0 +1,195 @@ +/* + * Copyright (c) 2012, 2013 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. + * + * 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. + */ + +import java.lang.annotation.*; +import java.io.*; +import java.net.URL; +import java.util.List; + +import com.sun.tools.classfile.*; + +public class ClassfileTestHelper { + int expected_tinvisibles = 0; + int expected_tvisibles = 0; + int expected_invisibles = 0; + int expected_visibles = 0; + + //Makes debugging much easier. Set to 'false' for less output. + public Boolean verbose = true; + void println(String msg) { if(verbose) System.out.println(msg); } + + File writeTestFile(String fname, String source) throws IOException { + File f = new File(fname); + PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(f))); + out.println(source); + out.close(); + return f; + } + + File compile(File f) { + int rc = com.sun.tools.javac.Main.compile(new String[] { + "-source", "1.8", "-g", f.getPath() }); + if (rc != 0) + throw new Error("compilation failed. rc=" + rc); + String path = f.getPath(); + return new File(path.substring(0, path.length() - 5) + ".class"); + } + + ClassFile getClassFile(String name) throws IOException, ConstantPoolException { + URL url = getClass().getResource(name); + InputStream in = url.openStream(); + try { + return ClassFile.read(in); + } finally { + in.close(); + } + } + + ClassFile getClassFile(URL url) throws IOException, ConstantPoolException { + InputStream in = url.openStream(); + try { + return ClassFile.read(in); + } finally { + in.close(); + } + } + + /************ Helper annotations counting methods ******************/ + void test(ClassFile cf) { + test("CLASS",cf, null, null, Attribute.RuntimeVisibleTypeAnnotations, true); + test("CLASS",cf, null, null, Attribute.RuntimeInvisibleTypeAnnotations, false); + //RuntimeAnnotations since one annotation can result in two attributes. + test("CLASS",cf, null, null, Attribute.RuntimeVisibleAnnotations, true); + test("CLASS",cf, null, null, Attribute.RuntimeInvisibleAnnotations, false); + } + + void test(ClassFile cf, Method m) { + test("METHOD",cf, null, m, Attribute.RuntimeVisibleTypeAnnotations, true); + test("METHOD",cf, null, m, Attribute.RuntimeInvisibleTypeAnnotations, false); + test("METHOD",cf, null, m, Attribute.RuntimeVisibleAnnotations, true); + test("METHOD",cf, null, m, Attribute.RuntimeInvisibleAnnotations, false); + } + + void test(ClassFile cf, Field f) { + test("FIELD",cf, f, null, Attribute.RuntimeVisibleTypeAnnotations, true); + test("FIELD",cf, f, null, Attribute.RuntimeInvisibleTypeAnnotations, false); + test("FIELD",cf, f, null, Attribute.RuntimeVisibleAnnotations, true); + test("FIELD",cf, f, null, Attribute.RuntimeInvisibleAnnotations, false); + } + + + // Test the result of Attributes.getIndex according to expectations + // encoded in the class/field/method name; increment annotations counts. + void test(String ttype, ClassFile cf, Field f, Method m, String annName, boolean visible) { + String testtype = ttype; + String name = null; + int index = -1; + Attribute attr = null; + boolean isTAattr = annName.contains("TypeAnnotations"); + try { + switch(testtype) { + case "FIELD": + name = f.getName(cf.constant_pool); + index = f.attributes.getIndex(cf.constant_pool, annName); + if(index!= -1) attr = f.attributes.get(index); + break; + case "METHOD": + name = m.getName(cf.constant_pool); + index = m.attributes.getIndex(cf.constant_pool, annName); + if(index!= -1) attr = m.attributes.get(index); + break; + default: + name = cf.getName(); + index = cf.attributes.getIndex(cf.constant_pool, annName); + if(index!= -1) attr = cf.attributes.get(index); + } + } catch(ConstantPoolException cpe) { cpe.printStackTrace(); } + + if (index != -1) { + assert attr instanceof RuntimeTypeAnnotations_attribute; + if(isTAattr) { //count RuntimeTypeAnnotations + RuntimeTypeAnnotations_attribute tAttr = + (RuntimeTypeAnnotations_attribute)attr; + println(testtype + ": " + name + ", " + annName + ": " + + tAttr.annotations.length ); + allt += tAttr.annotations.length; + if (visible) + tvisibles += tAttr.annotations.length; + else + tinvisibles += tAttr.annotations.length; + } else { + RuntimeAnnotations_attribute tAttr = + (RuntimeAnnotations_attribute)attr; + println(testtype + ": " + name + ", " + annName + ": " + + tAttr.annotations.length ); + all += tAttr.annotations.length; + if (visible) + visibles += tAttr.annotations.length; + else + invisibles += tAttr.annotations.length; + } + } + } + + void countAnnotations() { + errors=0; + int expected_allt = expected_tvisibles + expected_tinvisibles; + int expected_all = expected_visibles + expected_invisibles; + + if (expected_allt != allt) { + errors++; + System.err.println("Failure: expected " + expected_allt + + " type annotations but found " + allt); + } + if (expected_all != all) { + errors++; + System.err.println("Failure: expected " + expected_all + + " annotations but found " + all); + } + if (expected_tvisibles != tvisibles) { + errors++; + System.err.println("Failure: expected " + expected_tvisibles + + " typevisible annotations but found " + tvisibles); + } + + if (expected_tinvisibles != tinvisibles) { + errors++; + System.err.println("Failure: expected " + expected_tinvisibles + + " typeinvisible annotations but found " + tinvisibles); + } + allt=0; + tvisibles=0; + tinvisibles=0; + all=0; + visibles=0; + invisibles=0; + } + + int errors; + int allt; + int tvisibles; + int tinvisibles; + int all; + int visibles; + int invisibles; +} diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/classfile/CombinationsTargetTest1.java b/langtools/test/tools/javac/annotations/typeAnnotations/classfile/CombinationsTargetTest1.java new file mode 100644 index 00000000000..0041dd35f61 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/classfile/CombinationsTargetTest1.java @@ -0,0 +1,369 @@ +/* + * Copyright (c) 2013 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. + * + * 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. + */ + +/* + * @test + * @bug 8005085 8005877 8004829 8005681 8006734 8006775 + * @ignore + * @summary Combinations of Target ElementTypes on (repeated)type annotations. + */ + +import com.sun.tools.classfile.*; +import java.io.File; + +public class CombinationsTargetTest1 extends ClassfileTestHelper { + // Helps identify test case in event of failure. + int testcount = 0; + int src1 = 1, src2 = 2, src4 = 4, + src5 = 5, src6 = 6, src7 = 7; + + String[] ETypes={"TYPE", "FIELD", "METHOD", "PARAMETER", "CONSTRUCTOR", + "LOCAL_VARIABLE", "ANNOTATION_TYPE", "PACKAGE"}; + + // local class tests will have an inner class. + Boolean hasInnerClass=false; + String innerClassname=""; + + public static void main(String[] args) throws Exception { + new CombinationsTargetTest1().run(); + } + + void run() throws Exception { + // Determines which repeat and order in source(ABMix). + Boolean As= false, BDs=true, ABMix=false; + int testrun=0; + // A repeats and/or B/D repeats, ABMix for order of As and Bs. + Boolean [][] bRepeat = new Boolean[][]{{false,false,false},//no repeats + {true,false,false}, //repeat @A + {false,true,false}, //repeat @B + {true,true,false}, //repeat both + {false,false,true} //repeat mix + }; + for(Boolean[] bCombo : bRepeat) { + As=bCombo[0]; BDs=bCombo[1]; ABMix=bCombo[2]; + for(String et : ETypes) { + switch(et) { + case "METHOD": + test( 8, 0, 2, 0, As, BDs, ABMix, "CLASS", et, ++testrun, src1); + test(10, 0, 2, 0, As, BDs, ABMix, "CLASS", et, ++testrun, src2); + test( 8, 0, 0, 0, As, BDs, ABMix, "CLASS", et, ++testrun, src4); + test(10, 0, 2, 0, As, BDs, ABMix, "CLASS", et, ++testrun, src6); + test( 0, 8, 0, 2, As, BDs, ABMix, "RUNTIME", et, ++testrun, src1); + test( 0, 10, 0, 2, As, BDs, ABMix, "RUNTIME", et, ++testrun, src2); + test( 0, 8, 0, 0, As, BDs, ABMix, "RUNTIME", et, ++testrun, src4); + test( 0, 10, 0, 2, As, BDs, ABMix, "RUNTIME", et, ++testrun, src6); + break; + case "CONSTRUCTOR": + case "FIELD": + test( 8, 0, 4, 0, As, BDs, ABMix, "CLASS", et, ++testrun, src1); + test( 6, 0, 3, 0, As, BDs, ABMix, "CLASS", et, ++testrun, src5); + test( 9, 0, 0, 0, As, BDs, ABMix, "CLASS", et, ++testrun, src7); + test( 0, 8, 0, 4, As, BDs, ABMix, "RUNTIME", et, ++testrun, src1); + test( 0, 6, 0, 3, As, BDs, ABMix, "RUNTIME", et, ++testrun, src5); + test( 0, 9, 0, 0, As, BDs, ABMix, "RUNTIME", et, ++testrun, src7); + break; + default:/*TYPE,PARAMETER,LOCAL_VARIABLE,ANNOTATION_TYPE,PACKAGE*/ + test( 8, 0, 2, 0, As, BDs, ABMix, "CLASS", et, ++testrun, src1); + test( 6, 0, 3, 0, As, BDs, ABMix, "CLASS", et, ++testrun, src5); + test( 0, 8, 0, 2, As, BDs, ABMix, "RUNTIME", et, ++testrun, src1); + test( 0, 6, 0, 3, As, BDs, ABMix, "RUNTIME", et, ++testrun, src5); + } + } + } + } + + public void test(int tinv, int tvis, int inv, int vis, Boolean Arepeats, + Boolean BDrepeats, Boolean ABmix, String rtn, String et2, + Integer N, int source) throws Exception { + ++testcount; + expected_tvisibles = tvis; + expected_tinvisibles = tinv; + expected_visibles = vis; + expected_invisibles = inv; + File testFile = null; + String tname="Test" + N.toString(); + hasInnerClass=false; + String testDef = "Test " + testcount + " parameters: tinv=" + tinv + + ", tvis=" + tvis + ", inv=" + inv + ", vis=" + vis + + ", Arepeats=" + Arepeats + ", BDrepeats=" + BDrepeats + + ", ABmix=" + ABmix + ", retention: " + rtn + ", anno2: " + + et2 + ", src=" + source; + + println(testDef); + // Create test source and File. + String sourceString = sourceString(tname, rtn, et2, Arepeats, + BDrepeats, ABmix, source); + testFile = writeTestFile(tname+".java", sourceString); + // Compile test source and read classfile. + File classFile = null; + try { + classFile = compile(testFile); + } catch (Error err) { + System.err.println("Failed compile. Source:\n" + sourceString); + throw err; + } + //if sourcString() set hasInnerClass it also set innerClassname. + if(hasInnerClass) { + StringBuffer sb = new StringBuffer(classFile.getAbsolutePath()); + classFile=new File(sb.insert(sb.lastIndexOf(".class"),innerClassname).toString()); + } + ClassFile cf = ClassFile.read(classFile); + + //Test class,fields and method counts. + test(cf); + + for (Field f : cf.fields) { + test(cf, f); + } + for (Method m: cf.methods) { + test(cf, m); + } + countAnnotations(); + if (errors > 0) { + System.err.println( testDef ); + System.err.println( "Source:\n" + sourceString ); + throw new Exception( errors + " errors found" ); + } + println("Pass"); + } + + // + // Source for test cases + // + String sourceString(String testname, String retentn, String annot2, + Boolean Arepeats, Boolean BDrepeats, Boolean ABmix, + int src) { + + String As = "@A", Bs = "@B", Ds = "@D"; + if(Arepeats) As = "@A @A"; + if(BDrepeats) { + Bs = "@B @B"; + Ds = "@D @D"; + } + if(ABmix) { As = "@A @B"; Bs = "@A @B"; Ds = "@D @D"; } + + // Source to check for TYPE_USE and TYPE_PARAMETER annotations. + // Source base (annotations) is same for all test cases. + String source = new String(); + String imports = new String("import java.lang.annotation.*; \n" + + "import static java.lang.annotation.RetentionPolicy.*; \n" + + "import static java.lang.annotation.ElementType.*; \n" + + "import java.util.List; \n" + + "import java.util.HashMap; \n" + + "import java.util.Map; \n\n"); + + String sourceBase = new String("@Retention("+retentn+")\n" + + "@Target({TYPE_USE,_OTHER_})\n" + + "@ContainedBy( AC.class )\n" + + "@interface A { }\n\n" + + + "@Retention("+retentn+")\n" + + "@Target({TYPE_USE,_OTHER_})\n" + + "@ContainerFor(A.class)\n" + + "@interface AC { A[] value(); }\n\n" + + + "@Retention("+retentn+")\n" + + "@Target({TYPE_USE,_OTHER_})\n" + + "@ContainedBy( BC.class )\n" + + "@interface B { }\n\n" + + + "@Retention("+retentn+")\n" + + "@Target({TYPE_USE,_OTHER_})\n" + + "@ContainerFor(B.class)\n" + + "@interface BC { B[] value(); } \n\n" + + + "@Retention("+retentn+")\n" + + "@Target({TYPE_PARAMETER,_OTHER_})\n" + + "@interface C { }\n\n" + + + "@Retention("+retentn+")\n" + + "@Target({TYPE_USE,TYPE_PARAMETER,_OTHER_})\n" + + "@ContainedBy(DC.class)\n" + + "@interface D { }\n\n" + + + "@Retention("+retentn+")\n" + + "@Target({TYPE_USE,TYPE_PARAMETER,_OTHER_})\n" + + "@ContainerFor(D.class) \n" + + "@interface DC { D[] value(); }\n\n"); + + // Test case sources with sample generated source. + switch(src) { + case 1: // repeating type annotations at class level + /* + * @A @B class Test1 { + * @A @B Test1(){} + * @A @B Integer i1 = 0; + * String @A @B [] @A @B [] sa = null; + * // type usage in method body + * String test(Test1 this, String param, String ... vararg) { + * Object o = new String [3]; + * return (String) null; + * }} + */ + source = new String( + "// (repeating) type annotations at class level. \n" + + "_As_ _Bs_ class " + testname + " {\n" + + "_As_ _Bs_ " + testname +"(){} \n" + + "_As_ _Bs_ Integer i1 = 0; \n" + + "String _As_ _Bs_ [] _As_ _Bs_ [] sa = null; \n" + + "// type usage in method body \n" + + "String test("+testname+" this, " + + "String param, String ... vararg) { \n" + + " Object o = new String [3]; \n" + + " return (String) null; \n" + + "} \n" + + "} \n").concat(sourceBase).replace("_OTHER_", annot2).replace("_As_",As).replace("_Bs_",Bs) + + "\n\n"; + break; + case 2: // (repeating) type annotations on method. + /* + * class Test12 { + * Test12(){} + * // type usage on method + * @A @B String test(@A @B Test12 this, @A @B String param, @A @B String @A @B ... vararg) { + * Object o = new String [3]; + * return (String) null; + * }} + */ + source = new String( + "// (repeating) type annotations on method. \n" + + "class " + testname + " {\n" + + testname +"(){} \n" + + "// type usage on method \n" + + "_As_ _Bs_ String test(_As_ _Bs_ "+testname+" this, " + + "_As_ _Bs_ String param, _As_ _Bs_ String _As_ _Bs_ ... vararg) { \n" + + " Object o = new String [3]; \n" + + " return (String) null; \n" + + "} \n" + + "} \n").concat(sourceBase).replace("_OTHER_", annot2).replace("_As_",As).replace("_Bs_",Bs) + + "\n\n"; + break; + case 4: //(repeating) annotations on wildcard, type arguments in anonymous class. + /* + * class Test13 { + * public T data = null; + * T getData() { return data;} + * String mtest( Test13 t){ return t.getData(); } + * public void test() { + * mtest( new Test13<@A @B String>() { + * void m1(List<@A @B ? extends @A @B Object> lst) {} + * void m2() throws@A @B Exception { } + * }); + * } + * } + */ + source = new String( source + + "// (repeating) annotations on wildcard, type arguments in anonymous class. \n" + + "class " + testname + " {\n" + + " public T data = null;\n" + + " T getData() { return data;}\n" + + " String mtest( " + testname + " t){ return t.getData(); }\n" + + " public void test() {\n" + + " mtest( new " + testname + "<_As_ _Bs_ String>() {\n" + + " void m1(List<_As_ _Bs_ ? extends _As_ _Bs_ Object> lst) {}\n" + + " void m2() throws_As_ _Bs_ Exception { }\n" + + " });\n" + + " }\n" + + "}\n").concat(sourceBase).replace("_OTHER_", annot2).replace("_As_",As).replace("_Bs_",Bs) + "\n\n"; + hasInnerClass=true; + innerClassname="$1"; + break; + case 5: // (repeating)annotations on type parameters, bounds and type arguments on class decl. + /* + * @A @B @D + * class Test2<@A @B @C @D T extends @A @B Object> { + * Map, Integer> map = + * new HashMap, Integer>(); + * Map,Integer> map2 = new HashMap<>(); + * String test(Test2 this) { return null;} + * String genericMethod(T t) { return null; } + * } + */ + source = new String( source + + "// (repeating)annotations on type parameters, bounds and type arguments on class decl. \n" + + "_As_ _Bs_ _Ds_\n" + //8004829: A and B on type parameter below. + "class " + testname + "<_As_ _Bs_ @C _Ds_ T extends _As_ _Bs_ Object> {\n" + + " Map, Integer> map =\n" + + " new HashMap, Integer>();\n" + + " Map,Integer> map2 = new HashMap<>();\n" + + " String test(" + testname + " this) { return null;}\n" + + " String genericMethod(T t) { return null; }\n" + + "}\n").concat(sourceBase).replace("_OTHER_", annot2).replace("_As_",As).replace("_Bs_",Bs).replace("_Ds_",Ds) + + "\n\n"; + break; + case 6: // (repeating) annotations on type parameters, bounds and type arguments on method. + /* + * class Test14 { + * Map, Integer> map = + * new HashMap, Integer>(); + * Map, Integer> map2 = new HashMap<>(); + * String test(@A @B Test14<@D T> this) { return null;} + * <@C @D T> @A @B String genericMethod(@A @B @D T t) { return null; } + * } + */ + source = new String( source + + "// (repeating) annotations on type parameters, bounds and type arguments on method. \n" + + "class " + testname + " {\n" + + " Map, Integer> map =\n" + + " new HashMap, Integer>();\n" + + " Map, Integer> map2 = new HashMap<>();\n" + + " String test(_As_ _Bs_ " + testname + "<_Ds_ T> this) { return null;}\n" + + " <@C _Ds_ T> _As_ _Bs_ String genericMethod(_As_ _Bs_ _Ds_ T t) { return null; }\n" + + "}\n").concat(sourceBase).replace("_OTHER_", annot2).replace("_As_",As).replace("_Bs_",Bs).replace("_Ds_",Ds) + + "\n\n"; + break; + case 7: // repeating annotations on type parameters, bounds and type arguments in method. + /* + * class Test7{ + * Map, E > foo(E e) { + * class maptest <@A @B @D E> { + * Map,@A @B @D E> getMap() { + * return new HashMap,E>(); + * } + * } + * return new maptest().getMap(); + * } + * Map,String> shm = foo(new String("hello")); + * } + */ + source = new String( source + + "// (repeating)annotations on type parameters of class, method return value in method. \n" + + "class "+ testname + "{\n" + + " Map, E > foo(E e) {\n" + + " class maptest <_As_ _Bs_ _Ds_ E> {\n" + // inner class $1maptest + " Map,_As_ _Bs_ _Ds_ E> getMap() { \n" + + " return new HashMap,E>();\n" + + " }\n" + + " }\n" + + " return new maptest().getMap();\n" + + " }\n" + + " Map,String> shm = foo(new String(\"hello\"));\n" + + "}\n").concat(sourceBase).replace("_OTHER_", annot2).replace("_As_",As).replace("_Bs_",Bs).replace("_Ds_",Ds) + + "\n\n"; + hasInnerClass=true; + innerClassname="$1maptest"; + break; + } + return imports + source; + } +} diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/classfile/CombinationsTargetTest2.java b/langtools/test/tools/javac/annotations/typeAnnotations/classfile/CombinationsTargetTest2.java new file mode 100644 index 00000000000..a0308a38975 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/classfile/CombinationsTargetTest2.java @@ -0,0 +1,285 @@ +/* + * Copyright (c) 2013 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. + * + * 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. + */ + +/* + * @test + * @bug 8005085 8005877 8004829 8005681 8006734 8006775 + * @ignore + * @summary Combinations of Target ElementTypes on (repeated)type annotations. + */ + +import com.sun.tools.classfile.*; +import java.io.File; + +public class CombinationsTargetTest2 extends ClassfileTestHelper { + // Helps identify test case in event of failure. + int testcount = 0; + int src3 = 3, src8 = 8, src9 = 9; + + String[] ETypes={"TYPE", "FIELD", "METHOD", "PARAMETER", "CONSTRUCTOR", + "LOCAL_VARIABLE", "ANNOTATION_TYPE", "PACKAGE"}; + + // local class tests will have an inner class. + Boolean hasInnerClass=false; + String innerClassname=""; + + public static void main(String[] args) throws Exception { + new CombinationsTargetTest2().run(); + } + + void run() throws Exception { + // Determines which repeat and order in source(ABMix). + Boolean As= false, BDs=true, ABMix=false; + int testrun=0; + // A repeats and/or B/D repeats, ABMix for order of As and Bs. + Boolean [][] bRepeat = new Boolean[][]{{false,false,false},//no repeats + {true,false,false}, //repeat @A + {false,true,false}, //repeat @B + {true,true,false}, //repeat both + {false,false,true} //repeat mix + }; + for(Boolean[] bCombo : bRepeat) { + As=bCombo[0]; BDs=bCombo[1]; ABMix=bCombo[2]; + for(String et : ETypes) { + switch(et) { + case "METHOD": + test( 8, 0, 0, 0, As, BDs, ABMix, "CLASS", et, ++testrun, src3); + test( 0, 8, 0, 0, As, BDs, ABMix, "RUNTIME", et, ++testrun, src3); + break; + case "CONSTRUCTOR": + case "FIELD": + test( 8, 0, 0, 0, As, BDs, ABMix, "CLASS", et, ++testrun, src3); + test( 8, 0, 0, 0, As, BDs, ABMix, "CLASS", et, ++testrun, src8); + test( 6, 0, 0, 0, As, BDs, ABMix, "CLASS", et, ++testrun, src9); + test( 0, 8, 0, 0, As, BDs, ABMix, "RUNTIME", et, ++testrun, src3); + test( 0, 8, 0, 0, As, BDs, ABMix, "RUNTIME", et, ++testrun, src8); + test( 0, 6, 0, 0, As, BDs, ABMix, "RUNTIME", et, ++testrun, src9); + break; + default:/*TYPE,PARAMETER,LOCAL_VARIABLE,ANNOTATION_TYPE,PACKAGE*/ + break; + } + } + } + } + + public void test(int tinv, int tvis, int inv, int vis, Boolean Arepeats, + Boolean BDrepeats, Boolean ABmix, String rtn, String et2, + Integer N, int source) throws Exception { + ++testcount; + expected_tvisibles = tvis; + expected_tinvisibles = tinv; + expected_visibles = vis; + expected_invisibles = inv; + File testFile = null; + String tname="Test" + N.toString(); + hasInnerClass=false; + String testDef = "Test " + testcount + " parameters: tinv=" + tinv + + ", tvis=" + tvis + ", inv=" + inv + ", vis=" + vis + + ", Arepeats=" + Arepeats + ", BDrepeats=" + BDrepeats + + ", ABmix=" + ABmix + ", retention: " + rtn + ", anno2: " + + et2 + ", src=" + source; + +// Uncomment this block to run the tests but skip failing scenarios. +// // 8005681 - skip cases with repeated annotations on new, array, cast. +// if((source==3 || source==8 || source==9) && (ABmix || (Arepeats && BDrepeats))) { +// System.out.println(testDef+"\n8005681-skip repeated annotations on new,array,cast"); +// return; +// } + + println(testDef); + // Create test source and File. + String sourceString = sourceString(tname, rtn, et2, Arepeats, + BDrepeats, ABmix, source); + testFile = writeTestFile(tname+".java", sourceString); + // Compile test source and read classfile. + File classFile = null; + try { + classFile = compile(testFile); + } catch (Error err) { + System.err.println("Failed compile. Source:\n" + sourceString); + throw err; + } + //if sourcString() set hasInnerClass it also set innerClassname. + if(hasInnerClass) { + StringBuffer sb = new StringBuffer(classFile.getAbsolutePath()); + classFile=new File(sb.insert(sb.lastIndexOf(".class"),innerClassname).toString()); + } + ClassFile cf = ClassFile.read(classFile); + + //Test class,fields and method counts. + test(cf); + + for (Field f : cf.fields) { + test(cf, f); + } + for (Method m: cf.methods) { + test(cf, m); + } + countAnnotations(); + if (errors > 0) { + System.err.println( testDef ); + System.err.println( "Source:\n" + sourceString ); + throw new Exception( errors + " errors found" ); + } + println("Pass"); + } + + // + // Source for test cases + // + String sourceString(String testname, String retentn, String annot2, + Boolean Arepeats, Boolean BDrepeats, Boolean ABmix, + int src) { + + String As = "@A", Bs = "@B", Ds = "@D"; + if(Arepeats) As = "@A @A"; + if(BDrepeats) { + Bs = "@B @B"; + Ds = "@D @D"; + } + if(ABmix) { As = "@A @B"; Bs = "@A @B"; Ds = "@D @D"; } + + // Source to check for TYPE_USE and TYPE_PARAMETER annotations. + // Source base (annotations) is same for all test cases. + String source = new String(); + String imports = new String("import java.lang.annotation.*; \n" + + "import static java.lang.annotation.RetentionPolicy.*; \n" + + "import static java.lang.annotation.ElementType.*; \n" + + "import java.util.List; \n" + + "import java.util.HashMap; \n" + + "import java.util.Map; \n\n"); + + String sourceBase = new String("@Retention("+retentn+")\n" + + "@Target({TYPE_USE,_OTHER_})\n" + + "@ContainedBy( AC.class )\n" + + "@interface A { }\n\n" + + + "@Retention("+retentn+")\n" + + "@Target({TYPE_USE,_OTHER_})\n" + + "@ContainerFor(A.class)\n" + + "@interface AC { A[] value(); }\n\n" + + + "@Retention("+retentn+")\n" + + "@Target({TYPE_USE,_OTHER_})\n" + + "@ContainedBy( BC.class )\n" + + "@interface B { }\n\n" + + + "@Retention("+retentn+")\n" + + "@Target({TYPE_USE,_OTHER_})\n" + + "@ContainerFor(B.class)\n" + + "@interface BC { B[] value(); } \n\n" + + + "@Retention("+retentn+")\n" + + "@Target({TYPE_USE,TYPE_PARAMETER,_OTHER_})\n" + + "@ContainedBy(DC.class)\n" + + "@interface D { }\n\n" + + + "@Retention("+retentn+")\n" + + "@Target({TYPE_USE,TYPE_PARAMETER,_OTHER_})\n" + + "@ContainerFor(D.class) \n" + + "@interface DC { D[] value(); }\n\n"); + + // Test case sources with sample generated source + switch(src) { + case 3: // (repeating) type annotations on field in method body + /* + * class Test1 { + * Test1(){} + * // type usage in method body + * String test(Test1 this, String param, String ... vararg) { + * @A @B + * Object o = new @A @B String @A @B [3]; + * return (@A @B String) null; + * }} + */ + source = new String( + "class " + testname + " {\n" + + "" + testname +"(){} \n" + + "// type usage in method body \n" + + "String test("+testname+" this, " + + "String param, String ... vararg) { \n" + + " _As_ _Bs_\n Object o = new _As_ _Bs_ String _As_ _Bs_ [3]; \n" + + " return (_As_ _Bs_ String) null; \n" + + "} \n" + + "} \n").concat(sourceBase).replace("_OTHER_", annot2).replace("_As_",As).replace("_Bs_",Bs) + + "\n\n"; + break; + case 8: // (repeating) annotations on type parameters, bounds and type arguments in new statement. + /* + * class Test2 { + * Map, Integer> map = + * new HashMap<@A @B List<@A @B String>, @A @B Integer>(); + * Map, Integer> map2 = new @A @B HashMap<>(); + * String test(Test2 this) { return null;} + * String genericMethod(T t) { return null; } + * } + */ + source = new String( source + + "// (repeating) annotations on type parameters, bounds and type arguments. \n" + + "class " + testname + " {\n" + + " Map, Integer> map =\n" + + " new HashMap<_As_ _Bs_ List<_As_ _Bs_ String>, _As_ _Bs_ Integer>();\n" + + " Map, Integer> map2 = new _As_ _Bs_ HashMap<>();\n" + + " String test(" + testname + " this) { return null;}\n" + + " String genericMethod(T t) { return null; }\n" + + "}\n").concat(sourceBase).replace("_OTHER_", annot2).replace("_As_",As).replace("_Bs_",Bs) + + "\n\n"; + break; + case 9: // (repeating)annotations on type parameters of class, method return value in method. + /* + * class Test3{ + * Map, E > foo(E e) { + * class maptest { + * Map,E> getMap() { + * Map,E> Em = new HashMap,@A @B @D E>(); + * return Em; + * } + * } + * return new maptest().getMap(); + * } + * Map,String> shm = foo(new String("hello")); + * } + */ + source = new String( source + + "// (repeating)annotations on type parameters of class, method return value in method. \n" + + "class "+ testname + "{\n" + + " Map, E > foo(E e) {\n" + + " class maptest {\n" + // inner class $1maptest + " Map,E> getMap() { \n" + + " Map,E> Em = new HashMap,_As_ _Bs_ _Ds_ E>();\n" + + " return Em;\n" + + " }\n" + + " }\n" + + " return new maptest().getMap();\n" + + " }\n" + + " Map,String> shm = foo(new String(\"hello\"));\n" + + "}\n").concat(sourceBase).replace("_OTHER_", annot2).replace("_As_",As).replace("_Bs_",Bs).replace("_Ds_",Ds) + + "\n\n"; + hasInnerClass=true; + innerClassname="$1maptest"; + break; + + } + return imports + source; + } +} diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/classfile/DeadCode.java b/langtools/test/tools/javac/annotations/typeAnnotations/classfile/DeadCode.java new file mode 100644 index 00000000000..6d00bcc2ce6 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/classfile/DeadCode.java @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2009, 2013, 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. + * + * 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. + */ + +import java.lang.annotation.*; +import java.io.*; +import java.net.URL; +import java.util.List; + +import com.sun.tools.classfile.*; + +/* + * @test + * @bug 6917130 8006775 + * @summary test that optimized away annotations are not emited to classfile + */ + +public class DeadCode extends ClassfileTestHelper { + public static void main(String[] args) throws Exception { + new DeadCode().run(); + } + + public void run() throws Exception { + expected_tinvisibles = 1; + expected_tvisibles = 0; + + ClassFile cf = getClassFile("DeadCode$Test.class"); + test(cf); + for (Field f : cf.fields) { + test(cf, f); + } + for (Method m: cf.methods) { + test(cf, m); + } + + countAnnotations(); + + if (errors > 0) + throw new Exception(errors + " errors found"); + System.out.println("PASSED"); + } + + /*********************** Test class *************************/ + static class Test { + @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) + @interface A {} + + void test() { + List o = null; + o.toString(); + + @A String m; + if (false) { + @A String a; + @A String b = "m"; + b.toString(); + List c = null; + c.toString(); + } + } + } + +} diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/classfile/NewTypeArguments.java b/langtools/test/tools/javac/annotations/typeAnnotations/classfile/NewTypeArguments.java new file mode 100644 index 00000000000..84b9a85b3ae --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/classfile/NewTypeArguments.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2009 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. + * + * 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. + */ + +import java.lang.annotation.*; +import java.io.*; +import java.net.URL; +import java.util.List; + +import com.sun.tools.classfile.*; + +/* + * @test ClassLiterals + * @summary test that new type arguments are emitted to classfile + */ + +public class NewTypeArguments extends ClassfileTestHelper{ + public static void main(String[] args) throws Exception { + new NewTypeArguments().run(); + } + + public void run() throws Exception { + expected_tinvisibles = 3; + expected_tvisibles = 0; + + ClassFile cf = getClassFile("NewTypeArguments$Test.class"); + test(cf); + for (Field f : cf.fields) { + test(cf, f); + } + for (Method m: cf.methods) { + test(cf, m); + } + + countAnnotations(); + + if (errors > 0) + throw new Exception(errors + " errors found"); + System.out.println("PASSED"); + } + + /*********************** Test class *************************/ + static class Test { + @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) + @interface A {} + Test(E e) {} + + void test() { + new <@A String> Test(null); + new <@A List<@A String>> Test(null); + } + } +} diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/classfile/NoTargetAnnotations.java b/langtools/test/tools/javac/annotations/typeAnnotations/classfile/NoTargetAnnotations.java new file mode 100644 index 00000000000..6458d54234b --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/classfile/NoTargetAnnotations.java @@ -0,0 +1,204 @@ +/* + * Copyright (c) 2008 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. + * + * 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. + */ + +import java.io.*; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.net.URL; +import java.util.List; + +import com.sun.tools.classfile.*; + +/* + * @test NoTargetAnnotations + * @summary test that annotations with no Target meta type is emitted + * only once as declaration annotation + */ +public class NoTargetAnnotations { + + public static void main(String[] args) throws Exception { + new NoTargetAnnotations().run(); + } + + public void run() throws Exception { + ClassFile cf = getClassFile("NoTargetAnnotations$Test.class"); + for (Field f : cf.fields) { + test(cf, f); + testDeclaration(cf, f); + } + for (Method m: cf.methods) { + test(cf, m); + testDeclaration(cf, m); + } + + countAnnotations(); + + if (errors > 0) + throw new Exception(errors + " errors found"); + System.out.println("PASSED"); + } + + ClassFile getClassFile(String name) throws IOException, ConstantPoolException { + URL url = getClass().getResource(name); + InputStream in = url.openStream(); + try { + return ClassFile.read(in); + } finally { + in.close(); + } + } + + /************ Helper annotations counting methods ******************/ + void test(ClassFile cf, Method m) { + test(cf, m, Attribute.RuntimeVisibleTypeAnnotations, true); + test(cf, m, Attribute.RuntimeInvisibleTypeAnnotations, false); + } + + void test(ClassFile cf, Field m) { + test(cf, m, Attribute.RuntimeVisibleTypeAnnotations, true); + test(cf, m, Attribute.RuntimeInvisibleTypeAnnotations, false); + } + + void testDeclaration(ClassFile cf, Method m) { + testDecl(cf, m, Attribute.RuntimeVisibleAnnotations, true); + testDecl(cf, m, Attribute.RuntimeInvisibleAnnotations, false); + } + + void testDeclaration(ClassFile cf, Field m) { + testDecl(cf, m, Attribute.RuntimeVisibleAnnotations, true); + testDecl(cf, m, Attribute.RuntimeInvisibleAnnotations, false); + } + + // test the result of Attributes.getIndex according to expectations + // encoded in the method's name + void test(ClassFile cf, Method m, String name, boolean visible) { + int index = m.attributes.getIndex(cf.constant_pool, name); + if (index != -1) { + Attribute attr = m.attributes.get(index); + assert attr instanceof RuntimeTypeAnnotations_attribute; + RuntimeTypeAnnotations_attribute tAttr = (RuntimeTypeAnnotations_attribute)attr; + all += tAttr.annotations.length; + if (visible) + visibles += tAttr.annotations.length; + else + invisibles += tAttr.annotations.length; + } + } + + // test the result of Attributes.getIndex according to expectations + // encoded in the method's name + void test(ClassFile cf, Field m, String name, boolean visible) { + int index = m.attributes.getIndex(cf.constant_pool, name); + if (index != -1) { + Attribute attr = m.attributes.get(index); + assert attr instanceof RuntimeTypeAnnotations_attribute; + RuntimeTypeAnnotations_attribute tAttr = (RuntimeTypeAnnotations_attribute)attr; + all += tAttr.annotations.length; + if (visible) + visibles += tAttr.annotations.length; + else + invisibles += tAttr.annotations.length; + } + } + + // test the result of Attributes.getIndex according to expectations + // encoded in the method's name + void testDecl(ClassFile cf, Method m, String name, boolean visible) { + int index = m.attributes.getIndex(cf.constant_pool, name); + if (index != -1) { + Attribute attr = m.attributes.get(index); + assert attr instanceof RuntimeAnnotations_attribute; + RuntimeAnnotations_attribute tAttr = (RuntimeAnnotations_attribute)attr; + this.declAnnotations += tAttr.annotations.length; + } + } + + // test the result of Attributes.getIndex according to expectations + // encoded in the method's name + void testDecl(ClassFile cf, Field m, String name, boolean visible) { + int index = m.attributes.getIndex(cf.constant_pool, name); + if (index != -1) { + Attribute attr = m.attributes.get(index); + assert attr instanceof RuntimeAnnotations_attribute; + RuntimeAnnotations_attribute tAttr = (RuntimeAnnotations_attribute)attr; + this.declAnnotations += tAttr.annotations.length; + } + } + + File compileTestFile(File f) { + int rc = com.sun.tools.javac.Main.compile(new String[] { "-XDTA:writer", "-source", "1.8", "-g", f.getPath() }); + if (rc != 0) + throw new Error("compilation failed. rc=" + rc); + String path = f.getPath(); + return new File(path.substring(0, path.length() - 5) + ".class"); + } + + void countAnnotations() { + int expected_all = expected_visibles + expected_invisibles; + + if (expected_all != all) { + errors++; + System.err.println("expected " + expected_all + + " annotations but found " + all); + } + + if (expected_visibles != visibles) { + errors++; + System.err.println("expected " + expected_visibles + + " visibles annotations but found " + visibles); + } + + if (expected_invisibles != invisibles) { + errors++; + System.err.println("expected " + expected_invisibles + + " invisibles annotations but found " + invisibles); + } + + if (expected_decl != declAnnotations) { + errors++; + System.err.println("expected " + expected_decl + + " declaration annotations but found " + declAnnotations); + } + } + + int errors; + int all; + int visibles; + int invisibles; + + int declAnnotations; + + /*********************** Test class *************************/ + static int expected_invisibles = 0; + static int expected_visibles = 0; + static int expected_decl = 1; + + static class Test { + @Retention(RetentionPolicy.RUNTIME) + @interface A {} + + @A String method() { + return null; + } + } +} diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/classfile/TypeCasts.java b/langtools/test/tools/javac/annotations/typeAnnotations/classfile/TypeCasts.java new file mode 100644 index 00000000000..18f8e3b36bd --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/classfile/TypeCasts.java @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2009 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. + * + * 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. + */ + +import java.lang.annotation.*; +import java.io.*; +import java.net.URL; +import java.util.List; + +import com.sun.tools.classfile.*; + +/* + * @test + * @bug 6843077 8006775 + * @summary test that typecasts annotation are emitted if only the cast + * expression is optimized away + */ + +public class TypeCasts extends ClassfileTestHelper{ + public static void main(String[] args) throws Exception { + new TypeCasts().run(); + } + + public void run() throws Exception { + expected_tinvisibles = 4; + expected_tvisibles = 0; + + ClassFile cf = getClassFile("TypeCasts$Test.class"); + test(cf); + for (Field f : cf.fields) { + test(cf, f); + } + for (Method m: cf.methods) { + test(cf, m); + } + + countAnnotations(); + + if (errors > 0) + throw new Exception(errors + " errors found"); + System.out.println("PASSED"); + } + + /*********************** Test class *************************/ + static class Test { + @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) + @interface A {} + + void emit() { + Object o = null; + String s = null; + + String a0 = (@A String)o; + Object a1 = (@A Object)o; + + String b0 = (@A String)s; + Object b1 = (@A Object)s; + } + + void alldeadcode() { + Object o = null; + + if (false) { + String a0 = (@A String)o; + } + } + } +} diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/classfile/Wildcards.java b/langtools/test/tools/javac/annotations/typeAnnotations/classfile/Wildcards.java new file mode 100644 index 00000000000..d4621047ac5 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/classfile/Wildcards.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2009 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. + * + * 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. + */ + +import java.lang.annotation.*; +import java.io.*; +import java.net.URL; +import java.util.List; + +import com.sun.tools.classfile.*; + +/* + * @test Wildcards + * @bug 6843077 8006775 + * @summary test that annotations target wildcards get emitted to classfile + */ +public class Wildcards extends ClassfileTestHelper { + public static void main(String[] args) throws Exception { + new Wildcards().run(); + } + + public void run() throws Exception { + expected_tinvisibles = 3; + expected_tvisibles = 0; + + ClassFile cf = getClassFile("Wildcards$Test.class"); + test(cf); + for (Field f : cf.fields) { + test(cf, f); + } + for (Method m: cf.methods) { + test(cf, m); + } + + countAnnotations(); + + if (errors > 0) + throw new Exception(errors + " errors found"); + System.out.println("PASSED"); + } + + /*********************** Test class *************************/ + static class Test { + @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) + @interface A {} + + List f; + + List test(List p) { + List l; // not counted... gets optimized away + return null; + } + } +} diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/AnnotatedImport.java b/langtools/test/tools/javac/annotations/typeAnnotations/failures/AnnotatedImport.java new file mode 100644 index 00000000000..db14aefee15 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/AnnotatedImport.java @@ -0,0 +1,15 @@ +/* + * @test /nodynamiccopyright/ + * @bug 8006775 + * @summary Import clauses cannot use annotations. + * @author Werner Dietl + * @compile/fail/ref=AnnotatedImport.out -XDrawDiagnostics AnnotatedImport.java + */ + +import java.@A util.List; +import @A java.util.Map; +import java.util.@A HashMap; + +class AnnotatedImport { } + +@interface A { } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/AnnotatedImport.out b/langtools/test/tools/javac/annotations/typeAnnotations/failures/AnnotatedImport.out new file mode 100644 index 00000000000..dbd0d42c1e3 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/AnnotatedImport.out @@ -0,0 +1,7 @@ +AnnotatedImport.java:9:13: compiler.err.expected: token.identifier +AnnotatedImport.java:9:14: compiler.err.expected3: class, interface, enum +AnnotatedImport.java:10:7: compiler.err.expected: token.identifier +AnnotatedImport.java:10:10: compiler.err.expected: ';' +AnnotatedImport.java:11:18: compiler.err.expected: token.identifier +AnnotatedImport.java:11:19: compiler.err.expected3: class, interface, enum +6 errors diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/AnnotatedPackage1.java b/langtools/test/tools/javac/annotations/typeAnnotations/failures/AnnotatedPackage1.java new file mode 100644 index 00000000000..6b8b64a656f --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/AnnotatedPackage1.java @@ -0,0 +1,13 @@ +/* + * @test /nodynamiccopyright/ + * @bug 8006775 + * @summary Package declarations cannot use annotations. + * @author Werner Dietl + * @compile/fail/ref=AnnotatedPackage1.out -XDrawDiagnostics AnnotatedPackage1.java + */ + +package name.@A p1.p2; + +class AnnotatedPackage1 { } + +@interface A { } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/AnnotatedPackage1.out b/langtools/test/tools/javac/annotations/typeAnnotations/failures/AnnotatedPackage1.out new file mode 100644 index 00000000000..66ae60f72f2 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/AnnotatedPackage1.out @@ -0,0 +1,3 @@ +AnnotatedPackage1.java:9:14: compiler.err.expected: token.identifier +AnnotatedPackage1.java:9:15: compiler.err.expected3: class, interface, enum +2 errors diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/AnnotatedPackage2.java b/langtools/test/tools/javac/annotations/typeAnnotations/failures/AnnotatedPackage2.java new file mode 100644 index 00000000000..53eb5b142f3 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/AnnotatedPackage2.java @@ -0,0 +1,13 @@ +/* + * @test /nodynamiccopyright/ + * @bug 8006775 + * @summary Package declarations cannot use annotations. + * @author Werner Dietl + * @compile/fail/ref=AnnotatedPackage2.out -XDrawDiagnostics AnnotatedPackage2.java + */ + +package @A p1.p2; + +class AnnotatedPackage2 { } + +@interface A { } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/AnnotatedPackage2.out b/langtools/test/tools/javac/annotations/typeAnnotations/failures/AnnotatedPackage2.out new file mode 100644 index 00000000000..2ab804500f8 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/AnnotatedPackage2.out @@ -0,0 +1,3 @@ +AnnotatedPackage2.java:9:8: compiler.err.expected: token.identifier +AnnotatedPackage2.java:9:10: compiler.err.expected3: class, interface, enum +2 errors diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/AnnotationVersion.java b/langtools/test/tools/javac/annotations/typeAnnotations/failures/AnnotationVersion.java new file mode 100644 index 00000000000..9f80b2e9f28 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/AnnotationVersion.java @@ -0,0 +1,13 @@ +/* + * @test /nodynamiccopyright/ + * @bug 6843077 8006775 + * @summary test that only Java 8 allows type annotations + * @author Mahmood Ali + * @compile/fail/ref=AnnotationVersion.out -XDrawDiagnostics -Xlint:-options -source 1.6 AnnotationVersion.java + * @compile/fail/ref=AnnotationVersion7.out -XDrawDiagnostics -Xlint:-options -source 1.7 AnnotationVersion.java + */ +class AnnotationVersion { + public void method(@A AnnotationVersion this) { } +} + +@interface A { } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/AnnotationVersion.out b/langtools/test/tools/javac/annotations/typeAnnotations/failures/AnnotationVersion.out new file mode 100644 index 00000000000..d836ff3532a --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/AnnotationVersion.out @@ -0,0 +1,2 @@ +AnnotationVersion.java:10:43: compiler.err.type.annotations.not.supported.in.source: 1.6 +1 error diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/AnnotationVersion7.out b/langtools/test/tools/javac/annotations/typeAnnotations/failures/AnnotationVersion7.out new file mode 100644 index 00000000000..cb2fca3edce --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/AnnotationVersion7.out @@ -0,0 +1,2 @@ +AnnotationVersion.java:10:43: compiler.err.type.annotations.not.supported.in.source: 1.7 +1 error diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/BadCast.java b/langtools/test/tools/javac/annotations/typeAnnotations/failures/BadCast.java new file mode 100644 index 00000000000..a24c323d746 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/BadCast.java @@ -0,0 +1,14 @@ +/* + * @test /nodynamiccopyright/ + * @bug 8006775 + * @summary A cast cannot consist of only an annotation. + * @author Werner Dietl + * @compile/fail/ref=BadCast.out -XDrawDiagnostics BadCast.java + */ +class BadCast { + static void main() { + Object o = (@A) ""; + } +} + +@interface A { } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/BadCast.out b/langtools/test/tools/javac/annotations/typeAnnotations/failures/BadCast.out new file mode 100644 index 00000000000..f1b8bf04ca6 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/BadCast.out @@ -0,0 +1,2 @@ +BadCast.java:10:19: compiler.err.illegal.start.of.type +1 error \ No newline at end of file diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/CantAnnotateStaticClass.java b/langtools/test/tools/javac/annotations/typeAnnotations/failures/CantAnnotateStaticClass.java new file mode 100644 index 00000000000..8cd7d6aa155 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/CantAnnotateStaticClass.java @@ -0,0 +1,41 @@ +/* + * @test /nodynamiccopyright/ + * @bug 8006733 8006775 + * @ignore + * @summary A static outer class cannot be annotated. + * @author Werner Dietl + * @compile/fail/ref=CantAnnotateStaticClass.out -XDrawDiagnostics CantAnnotateStaticClass.java + */ + +import java.util.List; +import java.lang.annotation.*; + +class CantAnnotateStaticClass { + @Target(ElementType.TYPE_USE) + @interface A {} + + static class Outer { + class Inner {} + } + + // 8 errors: + @A Outer.Inner f1; + @A Outer.Inner f1r() { return null; } + void f1p(@A Outer.Inner p) { } + void f1c(Object o) { + Object l = (@A Outer.Inner) o; + } + + List<@A Outer.Inner> f2; + List<@A Outer.Inner> f2r() { return null; } + void f2p(List<@A Outer.Inner> p) { } + void f2c(Object o) { + Object l = (List<@A Outer.Inner>) o; + } + + // OK: + @A Outer g1; + List<@A Outer> g2; + Outer. @A Inner g3; + List g4; +} diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/CantAnnotateStaticClass.out b/langtools/test/tools/javac/annotations/typeAnnotations/failures/CantAnnotateStaticClass.out new file mode 100644 index 00000000000..2995a4d0e74 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/CantAnnotateStaticClass.out @@ -0,0 +1 @@ +dummy \ No newline at end of file diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/IncompleteArray.java b/langtools/test/tools/javac/annotations/typeAnnotations/failures/IncompleteArray.java new file mode 100644 index 00000000000..c414a5f807e --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/IncompleteArray.java @@ -0,0 +1,12 @@ +/* + * @test /nodynamiccopyright/ + * @bug 6843077 8006775 + * @summary test incomplete array declaration + * @author Mahmood Ali + * @compile/fail/ref=IncompleteArray.out -XDrawDiagnostics IncompleteArray.java + */ +class IncompleteArray { + int @A [] @A var; +} + +@interface A { } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/IncompleteArray.out b/langtools/test/tools/javac/annotations/typeAnnotations/failures/IncompleteArray.out new file mode 100644 index 00000000000..a03a09283ee --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/IncompleteArray.out @@ -0,0 +1,2 @@ +IncompleteArray.java:9:13: compiler.err.illegal.start.of.type +1 error diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/IncompleteVararg.java b/langtools/test/tools/javac/annotations/typeAnnotations/failures/IncompleteVararg.java new file mode 100644 index 00000000000..1bb05a43aec --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/IncompleteVararg.java @@ -0,0 +1,13 @@ +/* + * @test /nodynamiccopyright/ + * @bug 6843077 8006775 + * @summary test incomplete vararg declaration + * @author Mahmood Ali + * @compile/fail/ref=IncompleteVararg.out -XDrawDiagnostics IncompleteVararg.java + */ +class IncompleteArray { + // the last variable may be vararg + void method(int @A test) { } +} + +@interface A { } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/IncompleteVararg.out b/langtools/test/tools/javac/annotations/typeAnnotations/failures/IncompleteVararg.out new file mode 100644 index 00000000000..7cec6c9ee78 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/IncompleteVararg.out @@ -0,0 +1,2 @@ +IncompleteVararg.java:10:19: compiler.err.illegal.start.of.type +1 error diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/IndexArray.java b/langtools/test/tools/javac/annotations/typeAnnotations/failures/IndexArray.java new file mode 100644 index 00000000000..7098b93ee81 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/IndexArray.java @@ -0,0 +1,13 @@ +/* + * @test /nodynamiccopyright/ + * @bug 6843077 8006775 + * @summary test indexing of an array + * @author Mahmood Ali + * @compile/fail/ref=IndexArray.out -XDrawDiagnostics IndexArray.java + */ +class IndexArray { + int[] var; + int a = var @A [1]; +} + +@interface A { } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/IndexArray.out b/langtools/test/tools/javac/annotations/typeAnnotations/failures/IndexArray.out new file mode 100644 index 00000000000..762f38b15a8 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/IndexArray.out @@ -0,0 +1,2 @@ +IndexArray.java:10:15: compiler.err.illegal.start.of.expr +1 error diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/LintCast.java b/langtools/test/tools/javac/annotations/typeAnnotations/failures/LintCast.java new file mode 100644 index 00000000000..fdb31832ae5 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/LintCast.java @@ -0,0 +1,69 @@ +import java.lang.annotation.*; +import java.util.List; + +/* + * @test /nodynamiccopyright/ + * @bug 6843077 8006775 + * @summary test that compiler doesn't warn about annotated redundant casts + * @author Mahmood Ali + * @author Werner Dietl + * @compile/ref=LintCast.out -Xlint:cast -XDrawDiagnostics LintCast.java + */ +class LintCast { + void unparameterized() { + String s = "m"; + String s1 = (String)s; + String s2 = (@A String)s; + } + + void parameterized() { + List l = null; + List l1 = (List)l; + List l2 = (List<@A String>)l; + } + + void array() { + int @A [] a = null; + int[] a1 = (int[])a; + int[] a2 = (int @A [])a; + } + + void sameAnnotations() { + @A String annotated = null; + String unannotated = null; + + // compiler ignore annotated casts even if redundant + @A String anno1 = (@A String)annotated; + + // warn if redundant without an annotation + String anno2 = (String)annotated; + String unanno2 = (String)unannotated; + } + + void more() { + Object @A [] a = null; + Object[] a1 = (Object[])a; + Object[] a2 = (Object @A [])a; + + @A List l3 = null; + List l4 = (List)l3; + List l5 = (@A List)l3; + + List<@A String> l6 = null; + List l7 = (List)l6; + List l8 = (List<@A String>)l6; + + @A Object o = null; + Object o1 = (Object)o; + Object o2 = (@A Object)o; + + Outer. @A Inner oi = null; + Outer.Inner oi1 = (Outer.Inner)oi; + Outer.Inner oi2 = (Outer. @A Inner)oi; + } + + class Outer { class Inner {} } +} + +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface A { } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/LintCast.out b/langtools/test/tools/javac/annotations/typeAnnotations/failures/LintCast.out new file mode 100644 index 00000000000..212423e8895 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/LintCast.out @@ -0,0 +1,11 @@ +LintCast.java:15:21: compiler.warn.redundant.cast: java.lang.String +LintCast.java:21:27: compiler.warn.redundant.cast: java.util.List +LintCast.java:27:20: compiler.warn.redundant.cast: (@A :: int[]) +LintCast.java:39:24: compiler.warn.redundant.cast: java.lang.String +LintCast.java:40:26: compiler.warn.redundant.cast: java.lang.String +LintCast.java:45:23: compiler.warn.redundant.cast: (@A :: java.lang.Object[]) +LintCast.java:49:27: compiler.warn.redundant.cast: java.util.List +LintCast.java:53:27: compiler.warn.redundant.cast: java.util.List +LintCast.java:57:21: compiler.warn.redundant.cast: java.lang.Object +LintCast.java:61:27: compiler.warn.redundant.cast: LintCast.Outer.Inner +10 warnings \ No newline at end of file diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/OldArray.java b/langtools/test/tools/javac/annotations/typeAnnotations/failures/OldArray.java new file mode 100644 index 00000000000..4ed4e87aec1 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/OldArray.java @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2008, 2013, 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. + * + * 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. + */ + +/* + * @test + * @bug 6843077 8006775 + * @summary test old array syntax + * @author Mahmood Ali + * @compile/fail -XDrawDiagnostics OldArray.java + */ +class OldArray { + String [@A] s() { return null; } +} + +@interface A { } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/Scopes.java b/langtools/test/tools/javac/annotations/typeAnnotations/failures/Scopes.java new file mode 100644 index 00000000000..aab3c55832c --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/Scopes.java @@ -0,0 +1,17 @@ +/* + * @test /nodynamiccopyright/ + * @bug 6843077 8006775 + * @summary check that A is accessible in the class type parameters + * @author Mahmood Ali + * @compile/fail/ref=Scopes.out -XDrawDiagnostics Scopes.java + */ +class Scopes { + // UniqueInner is not visible in the type parameters. + // One has to use Scopes.UniqueInner. + // Annotations with the default @Target are not allowed there, + // so we also get the second error about the invalid location. + // Adding the target here doesn't matter, as we don't resolve + // the annotation type. + // @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) + @interface UniqueInner { }; +} diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/Scopes.out b/langtools/test/tools/javac/annotations/typeAnnotations/failures/Scopes.out new file mode 100644 index 00000000000..cf7eeceb9d8 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/Scopes.out @@ -0,0 +1,3 @@ +Scopes.java:8:25: compiler.err.cant.resolve: kindname.class, UniqueInner, , +Scopes.java:8:24: compiler.err.annotation.type.not.applicable +2 errors diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/StaticFields.java b/langtools/test/tools/javac/annotations/typeAnnotations/failures/StaticFields.java new file mode 100644 index 00000000000..f75583f9688 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/StaticFields.java @@ -0,0 +1,13 @@ +/* + * @test /nodynamiccopyright/ + * @bug 6843077 8006775 + * @summary static field access isn't a valid location + * @author Mahmood Ali + * @compile/fail/ref=StaticFields.out -XDrawDiagnostics StaticFields.java + */ +class C { + int f; + int a = @A C.f; +} + +@interface A { } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/StaticFields.out b/langtools/test/tools/javac/annotations/typeAnnotations/failures/StaticFields.out new file mode 100644 index 00000000000..3364c661fdb --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/StaticFields.out @@ -0,0 +1,2 @@ +StaticFields.java:10:17: compiler.err.illegal.start.of.expr +1 error diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/StaticMethods.java b/langtools/test/tools/javac/annotations/typeAnnotations/failures/StaticMethods.java new file mode 100644 index 00000000000..cb386d1abab --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/StaticMethods.java @@ -0,0 +1,12 @@ +/* + * @test /nodynamiccopyright/ + * @bug 6843077 8006775 + * @summary static methods don't have receivers + * @author Mahmood Ali + * @compile/fail/ref=StaticMethods.out -XDrawDiagnostics StaticMethods.java + */ +class StaticMethods { + static void main(@A StaticMethods this) { } +} + +@interface A { } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/StaticMethods.out b/langtools/test/tools/javac/annotations/typeAnnotations/failures/StaticMethods.out new file mode 100644 index 00000000000..d75a02bffe3 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/StaticMethods.out @@ -0,0 +1,2 @@ +StaticMethods.java:9:37: compiler.err.annotation.type.not.applicable +1 error diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/TypeAndField.java b/langtools/test/tools/javac/annotations/typeAnnotations/failures/TypeAndField.java new file mode 100644 index 00000000000..4f600f44abc --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/TypeAndField.java @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2013, 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. + * + * 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. + */ + +/* + * @test + * @bug 8006703 8006775 + * @summary Ensure that TYPE_USE and FIELD work together. + * @author Werner Dietl + * @compile TypeAndField.java + */ +import java.lang.annotation.*; + +class TypeAndField { + @TA Integer i; + @TA int j; +} + +@Retention(RetentionPolicy.CLASS) +@Target({ElementType.TYPE_USE, ElementType.FIELD}) +@interface TA { } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/VoidGenericMethod.java b/langtools/test/tools/javac/annotations/typeAnnotations/failures/VoidGenericMethod.java new file mode 100644 index 00000000000..38a0395ffab --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/VoidGenericMethod.java @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2008, 2013, 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. + * + * 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. + */ + +/* + * @test + * @bug 6843077 8006775 + * @summary test type annotation on void generic methods + * @author Mahmood Ali + * @compile/fail VoidGenericMethod.java + */ +class VoidGenericMethod { + public @A void method() { } +} + +@interface A { } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/arrays/DuplicateAnnotationValue.java b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/arrays/DuplicateAnnotationValue.java new file mode 100644 index 00000000000..cc0b2d96db9 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/arrays/DuplicateAnnotationValue.java @@ -0,0 +1,16 @@ +/* + * @test /nodynamiccopyright/ + * @bug 6843077 6919944 8006775 + * @summary check for duplicate annotation values + * @author Mahmood Ali + * @compile/fail/ref=DuplicateAnnotationValue.out -XDrawDiagnostics DuplicateAnnotationValue.java + */ +import java.lang.annotation.*; +class DuplicateAnnotationValue { + void test() { + String @A(value = 2, value = 1) [] s; + } +} + +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface A { int value(); } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/arrays/DuplicateAnnotationValue.out b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/arrays/DuplicateAnnotationValue.out new file mode 100644 index 00000000000..566321c05db --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/arrays/DuplicateAnnotationValue.out @@ -0,0 +1,2 @@ +DuplicateAnnotationValue.java:11:26: compiler.err.duplicate.annotation.member.value: value, A +1 error diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/arrays/DuplicateTypeAnnotation.java b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/arrays/DuplicateTypeAnnotation.java new file mode 100644 index 00000000000..da0438eda17 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/arrays/DuplicateTypeAnnotation.java @@ -0,0 +1,16 @@ +/* + * @test /nodynamiccopyright/ + * @bug 6843077 8006775 + * @summary check for duplicate annotations + * @author Mahmood Ali + * @compile/fail/ref=DuplicateTypeAnnotation.out -XDrawDiagnostics DuplicateTypeAnnotation.java + */ +import java.lang.annotation.*; +class DuplicateTypeAnnotation { + void test() { + String @A @A [] s; + } +} + +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface A { } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/arrays/DuplicateTypeAnnotation.out b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/arrays/DuplicateTypeAnnotation.out new file mode 100644 index 00000000000..3c5f6ea1c68 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/arrays/DuplicateTypeAnnotation.out @@ -0,0 +1,3 @@ +DuplicateTypeAnnotation.java:11:12: compiler.err.duplicate.annotation.missing.container: A, java.lang.annotation.Repeatable +DuplicateTypeAnnotation.java:11:15: compiler.err.duplicate.annotation.missing.container: A, java.lang.annotation.Repeatable +2 errors diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/arrays/InvalidLocation.java b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/arrays/InvalidLocation.java new file mode 100644 index 00000000000..da44d219383 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/arrays/InvalidLocation.java @@ -0,0 +1,16 @@ +/* + * @test /nodynamiccopyright/ + * @bug 6843077 8006775 + * @summary check for invalid annotatins given the target + * @author Mahmood Ali + * @compile/fail/ref=InvalidLocation.out -XDrawDiagnostics InvalidLocation.java + */ + +class InvalidLocation { + void test() { + String @A [] s; + } +} + +@java.lang.annotation.Target(java.lang.annotation.ElementType.TYPE) +@interface A { } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/arrays/InvalidLocation.out b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/arrays/InvalidLocation.out new file mode 100644 index 00000000000..868ab979837 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/arrays/InvalidLocation.out @@ -0,0 +1,2 @@ +InvalidLocation.java:11:12: compiler.err.annotation.type.not.applicable +1 error diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/arrays/MissingAnnotationValue.java b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/arrays/MissingAnnotationValue.java new file mode 100644 index 00000000000..4f099e03156 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/arrays/MissingAnnotationValue.java @@ -0,0 +1,14 @@ +/* + * @test /nodynamiccopyright/ + * @bug 6843077 8006775 + * @summary check for missing annotation value + * @author Mahmood Ali + * @compile/fail/ref=MissingAnnotationValue.out -XDrawDiagnostics MissingAnnotationValue.java + */ +class MissingAnnotationValue { + void test() { + String @A [] s; + } +} + +@interface A { int field(); } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/arrays/MissingAnnotationValue.out b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/arrays/MissingAnnotationValue.out new file mode 100644 index 00000000000..74a7ef7340b --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/arrays/MissingAnnotationValue.out @@ -0,0 +1,2 @@ +MissingAnnotationValue.java:10:12: compiler.err.annotation.missing.default.value: A, field +1 error diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/innertypeparams/DuplicateAnnotationValue.java b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/innertypeparams/DuplicateAnnotationValue.java new file mode 100644 index 00000000000..2230767d300 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/innertypeparams/DuplicateAnnotationValue.java @@ -0,0 +1,16 @@ +/* + * @test /nodynamiccopyright/ + * @bug 6843077 6919944 8006775 + * @summary check for duplicate annotation values for type parameter + * @author Mahmood Ali + * @compile/fail/ref=DuplicateAnnotationValue.out -XDrawDiagnostics DuplicateAnnotationValue.java + */ +import java.lang.annotation.*; +class DuplicateAnnotationValue { + void method() { + class Inner<@A(value = 2, value = 1) K> {} + } +} + +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface A { int value(); } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/innertypeparams/DuplicateAnnotationValue.out b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/innertypeparams/DuplicateAnnotationValue.out new file mode 100644 index 00000000000..12248c81a87 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/innertypeparams/DuplicateAnnotationValue.out @@ -0,0 +1,2 @@ +DuplicateAnnotationValue.java:11:31: compiler.err.duplicate.annotation.member.value: value, A +1 error diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/innertypeparams/DuplicateTypeAnnotation.java b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/innertypeparams/DuplicateTypeAnnotation.java new file mode 100644 index 00000000000..3438dd2a9fc --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/innertypeparams/DuplicateTypeAnnotation.java @@ -0,0 +1,16 @@ +/* + * @test /nodynamiccopyright/ + * @bug 6843077 8006775 + * @summary check for duplicate annotations + * @author Mahmood Ali + * @compile/fail/ref=DuplicateTypeAnnotation.out -XDrawDiagnostics DuplicateTypeAnnotation.java + */ +import java.lang.annotation.*; +class DuplicateTypeAnno { + void innermethod() { + class Inner<@A @A K> { } + } +} + +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface A { } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/innertypeparams/DuplicateTypeAnnotation.out b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/innertypeparams/DuplicateTypeAnnotation.out new file mode 100644 index 00000000000..7eb43efa3ed --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/innertypeparams/DuplicateTypeAnnotation.out @@ -0,0 +1,3 @@ +DuplicateTypeAnnotation.java:11:17: compiler.err.duplicate.annotation.missing.container: A, java.lang.annotation.Repeatable +DuplicateTypeAnnotation.java:11:20: compiler.err.duplicate.annotation.missing.container: A, java.lang.annotation.Repeatable +2 errors diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/innertypeparams/InvalidLocation.java b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/innertypeparams/InvalidLocation.java new file mode 100644 index 00000000000..46d65a8daef --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/innertypeparams/InvalidLocation.java @@ -0,0 +1,15 @@ +/* + * @test /nodynamiccopyright/ + * @bug 6843077 8006775 + * @summary check for invalid annotatins given the target + * @author Mahmood Ali + * @compile/fail/ref=InvalidLocation.out -XDrawDiagnostics InvalidLocation.java + */ +class InvalidLocation { + void innermethod() { + class Inner<@A K> {} + } +} + +@java.lang.annotation.Target(java.lang.annotation.ElementType.TYPE) +@interface A { } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/innertypeparams/InvalidLocation.out b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/innertypeparams/InvalidLocation.out new file mode 100644 index 00000000000..b74ad54ba94 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/innertypeparams/InvalidLocation.out @@ -0,0 +1,2 @@ +InvalidLocation.java:10:17: compiler.err.annotation.type.not.applicable +1 error diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/innertypeparams/MissingAnnotationValue.java b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/innertypeparams/MissingAnnotationValue.java new file mode 100644 index 00000000000..5a5c8b69587 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/innertypeparams/MissingAnnotationValue.java @@ -0,0 +1,14 @@ +/* + * @test /nodynamiccopyright/ + * @bug 6843077 8006775 + * @summary check for missing annotation value + * @author Mahmood Ali + * @compile/fail/ref=MissingAnnotationValue.out -XDrawDiagnostics MissingAnnotationValue.java + */ +class MissingAnnotationValue { + void innermethod() { + class Inner<@A K> { } + } +} + +@interface A { int field(); } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/innertypeparams/MissingAnnotationValue.out b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/innertypeparams/MissingAnnotationValue.out new file mode 100644 index 00000000000..637ff4acc0a --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/innertypeparams/MissingAnnotationValue.out @@ -0,0 +1,2 @@ +MissingAnnotationValue.java:10:17: compiler.err.annotation.missing.default.value: A, field +1 error diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/newarray/DuplicateAnnotationValue.java b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/newarray/DuplicateAnnotationValue.java new file mode 100644 index 00000000000..f3f36165b64 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/newarray/DuplicateAnnotationValue.java @@ -0,0 +1,16 @@ +/* + * @test /nodynamiccopyright/ + * @bug 6843077 6919944 8006775 + * @summary check for duplicate annotation values + * @author Mahmood Ali + * @compile/fail/ref=DuplicateAnnotationValue.out -XDrawDiagnostics DuplicateAnnotationValue.java + */ +import java.lang.annotation.*; +class DuplicateAnnotationValue { + void test() { + String[] a = new String @A(value = 2, value = 1) [5] ; + } +} + +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface A { int value(); } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/newarray/DuplicateAnnotationValue.out b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/newarray/DuplicateAnnotationValue.out new file mode 100644 index 00000000000..cb7b69d86f9 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/newarray/DuplicateAnnotationValue.out @@ -0,0 +1,2 @@ +DuplicateAnnotationValue.java:11:43: compiler.err.duplicate.annotation.member.value: value, A +1 error diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/newarray/DuplicateTypeAnnotation.java b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/newarray/DuplicateTypeAnnotation.java new file mode 100644 index 00000000000..be8f479fedf --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/newarray/DuplicateTypeAnnotation.java @@ -0,0 +1,16 @@ +/* + * @test /nodynamiccopyright/ + * @bug 6843077 8006775 + * @summary check for duplicate annotations + * @author Mahmood Ali + * @compile/fail/ref=DuplicateTypeAnnotation.out -XDrawDiagnostics DuplicateTypeAnnotation.java + */ +import java.lang.annotation.*; +class DuplicateTypeAnnotation { + void test() { + String[] a = new String @A @A [5] ; + } +} + +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface A { } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/newarray/DuplicateTypeAnnotation.out b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/newarray/DuplicateTypeAnnotation.out new file mode 100644 index 00000000000..537e6156ef3 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/newarray/DuplicateTypeAnnotation.out @@ -0,0 +1,3 @@ +DuplicateTypeAnnotation.java:11:29: compiler.err.duplicate.annotation.missing.container: A, java.lang.annotation.Repeatable +DuplicateTypeAnnotation.java:11:32: compiler.err.duplicate.annotation.missing.container: A, java.lang.annotation.Repeatable +2 errors diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/newarray/InvalidLocation.java b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/newarray/InvalidLocation.java new file mode 100644 index 00000000000..a43e2e7b070 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/newarray/InvalidLocation.java @@ -0,0 +1,16 @@ +/* + * @test /nodynamiccopyright/ + * @bug 6843077 8006775 + * @summary check for invalid annotatins given the target + * @author Mahmood Ali + * @compile/fail/ref=InvalidLocation.out -XDrawDiagnostics InvalidLocation.java + */ + +class InvalidLocation { + void test() { + String[] s = new String @A [5] ; + } +} + +@java.lang.annotation.Target(java.lang.annotation.ElementType.TYPE) +@interface A { } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/newarray/InvalidLocation.out b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/newarray/InvalidLocation.out new file mode 100644 index 00000000000..1d98d174319 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/newarray/InvalidLocation.out @@ -0,0 +1,2 @@ +InvalidLocation.java:11:29: compiler.err.annotation.type.not.applicable +1 error diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/newarray/MissingAnnotationValue.java b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/newarray/MissingAnnotationValue.java new file mode 100644 index 00000000000..15cf6e91496 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/newarray/MissingAnnotationValue.java @@ -0,0 +1,14 @@ +/* + * @test /nodynamiccopyright/ + * @bug 6843077 8006775 + * @summary check for missing annotation value + * @author Mahmood Ali + * @compile/fail/ref=MissingAnnotationValue.out -XDrawDiagnostics MissingAnnotationValue.java + */ +class MissingAnnotationValue { + void test() { + String[] a = new String @A [5]; + } +} + +@interface A { int field(); } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/newarray/MissingAnnotationValue.out b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/newarray/MissingAnnotationValue.out new file mode 100644 index 00000000000..6865348250b --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/newarray/MissingAnnotationValue.out @@ -0,0 +1,2 @@ +MissingAnnotationValue.java:10:29: compiler.err.annotation.missing.default.value: A, field +1 error diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/parambounds/BrokenAnnotation.java b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/parambounds/BrokenAnnotation.java new file mode 100644 index 00000000000..7e4581851e5 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/parambounds/BrokenAnnotation.java @@ -0,0 +1,99 @@ +/* + * @test /nodynamiccopyright/ + * @bug 8006775 + * @summary Ensure unresolved upper bound annotation is handled correctly + * @author Werner Dietl + * @compile/fail/ref=BrokenAnnotation.out -XDrawDiagnostics BrokenAnnotation.java + */ + +// No import, making the annotation @A invalid. +// import java.lang.annotation.*; + +// Works: @Broke.A class... +// Works: class Broke<@Broke.A T> { +// Used to fail: +class BrokenAnnotation { + @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) + @interface A { } +} + +// If the Annotation is e.g. on the top-level class, we +// get something like this: +// +// Broke.java:6: cannot find symbol +// symbol : class Target +// location: class Broke +// @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +// ^ +// 1 error +// +// When the annotation is in the upper bound, one used to get +// the following stack trace: +// +// An exception has occurred in the compiler (1.7.0-jsr308-1.2.7). Please report this bug so we can fix it. For instructions, see http://types.cs.washington.edu/checker-framework/current/README-jsr308.html#reporting-bugs . Thank you. +// java.lang.NullPointerException +// at com.sun.tools.javac.code.Type.isCompound(Type.java:346) +// at com.sun.tools.javac.code.Types.getBounds(Types.java:1940) +// at com.sun.tools.javac.util.RichDiagnosticFormatter$1.visitTypeVar(RichDiagnosticFormatter.java:534) +// at com.sun.tools.javac.util.RichDiagnosticFormatter$1.visitTypeVar(RichDiagnosticFormatter.java:1) +// at com.sun.tools.javac.code.Type$TypeVar.accept(Type.java:1049) +// at com.sun.tools.javac.code.Types$UnaryVisitor.visit(Types.java:3809) +// at com.sun.tools.javac.util.RichDiagnosticFormatter$1.visit(RichDiagnosticFormatter.java:450) +// at com.sun.tools.javac.util.RichDiagnosticFormatter$1.visitClassType(RichDiagnosticFormatter.java:518) +// at com.sun.tools.javac.util.RichDiagnosticFormatter$1.visitClassType(RichDiagnosticFormatter.java:1) +// at com.sun.tools.javac.code.Type$ClassType.accept(Type.java:596) +// at com.sun.tools.javac.code.Types$UnaryVisitor.visit(Types.java:3809) +// at com.sun.tools.javac.util.RichDiagnosticFormatter.preprocessType(RichDiagnosticFormatter.java:442) +// at com.sun.tools.javac.util.RichDiagnosticFormatter.preprocessArgument(RichDiagnosticFormatter.java:172) +// at com.sun.tools.javac.util.RichDiagnosticFormatter.preprocessDiagnostic(RichDiagnosticFormatter.java:155) +// at com.sun.tools.javac.util.RichDiagnosticFormatter.preprocessArgument(RichDiagnosticFormatter.java:178) +// at com.sun.tools.javac.util.RichDiagnosticFormatter.preprocessDiagnostic(RichDiagnosticFormatter.java:155) +// at com.sun.tools.javac.util.RichDiagnosticFormatter.format(RichDiagnosticFormatter.java:111) +// at com.sun.tools.javac.util.RichDiagnosticFormatter.format(RichDiagnosticFormatter.java:1) +// at com.sun.tools.javac.util.Log.writeDiagnostic(Log.java:514) +// at com.sun.tools.javac.util.Log.report(Log.java:496) +// at com.sun.tools.javac.comp.Resolve.logResolveError(Resolve.java:2160) +// at com.sun.tools.javac.comp.Resolve.access(Resolve.java:1553) +// at com.sun.tools.javac.comp.Resolve.access(Resolve.java:1580) +// at com.sun.tools.javac.comp.Resolve.access(Resolve.java:1592) +// at com.sun.tools.javac.comp.Resolve.resolveIdent(Resolve.java:1653) +// at com.sun.tools.javac.comp.Attr.visitIdent(Attr.java:2191) +// at com.sun.tools.javac.tree.JCTree$JCIdent.accept(JCTree.java:1873) +// at com.sun.tools.javac.comp.Attr.attribTree(Attr.java:467) +// at com.sun.tools.javac.comp.Attr.attribType(Attr.java:503) +// at com.sun.tools.javac.comp.Attr.attribType(Attr.java:496) +// at com.sun.tools.javac.comp.Attr.attribAnnotationTypes(Attr.java:605) +// at com.sun.tools.javac.comp.MemberEnter.complete(MemberEnter.java:944) +// at com.sun.tools.javac.code.Symbol.complete(Symbol.java:432) +// at com.sun.tools.javac.code.Symbol$ClassSymbol.complete(Symbol.java:832) +// at com.sun.tools.javac.code.Symbol$ClassSymbol.flags(Symbol.java:775) +// at com.sun.tools.javac.comp.Resolve.isAccessible(Resolve.java:350) +// at com.sun.tools.javac.comp.Resolve.isAccessible(Resolve.java:346) +// at com.sun.tools.javac.comp.Resolve.findMemberType(Resolve.java:1346) +// at com.sun.tools.javac.comp.Resolve.findIdentInType(Resolve.java:1512) +// at com.sun.tools.javac.comp.Attr.selectSym(Attr.java:2434) +// at com.sun.tools.javac.comp.Attr.visitSelect(Attr.java:2312) +// at com.sun.tools.javac.tree.JCTree$JCFieldAccess.accept(JCTree.java:1805) +// at com.sun.tools.javac.comp.Attr.attribTree(Attr.java:467) +// at com.sun.tools.javac.comp.Attr.attribType(Attr.java:503) +// at com.sun.tools.javac.comp.Attr.attribType(Attr.java:496) +// at com.sun.tools.javac.comp.Attr.attribAnnotationTypes(Attr.java:605) +// at com.sun.tools.javac.comp.Attr.visitAnnotatedType(Attr.java:3016) +// at com.sun.tools.javac.tree.JCTree$JCAnnotatedType.accept(JCTree.java:2253) +// at com.sun.tools.javac.comp.Attr.attribTree(Attr.java:467) +// at com.sun.tools.javac.comp.Attr.attribType(Attr.java:503) +// at com.sun.tools.javac.comp.Attr.attribType(Attr.java:496) +// at com.sun.tools.javac.comp.Attr.attribTypeVariables(Attr.java:569) +// at com.sun.tools.javac.comp.MemberEnter.complete(MemberEnter.java:955) +// at com.sun.tools.javac.code.Symbol.complete(Symbol.java:432) +// at com.sun.tools.javac.code.Symbol$ClassSymbol.complete(Symbol.java:832) +// at com.sun.tools.javac.comp.Enter.complete(Enter.java:500) +// at com.sun.tools.javac.comp.Enter.main(Enter.java:478) +// at com.sun.tools.javac.main.JavaCompiler.enterTrees(JavaCompiler.java:950) +// at com.sun.tools.javac.main.JavaCompiler.compile(JavaCompiler.java:841) +// at com.sun.tools.javac.main.Main.compile(Main.java:441) +// at com.sun.tools.javac.main.Main.compile(Main.java:358) +// at com.sun.tools.javac.main.Main.compile(Main.java:347) +// at com.sun.tools.javac.main.Main.compile(Main.java:338) +// at com.sun.tools.javac.Main.compile(Main.java:76) +// at com.sun.tools.javac.Main.main(Main.java:61) diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/parambounds/BrokenAnnotation.out b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/parambounds/BrokenAnnotation.out new file mode 100644 index 00000000000..caeb4bb158d --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/parambounds/BrokenAnnotation.out @@ -0,0 +1,3 @@ +BrokenAnnotation.java:16:6: compiler.err.cant.resolve.location: kindname.class, Target, , , (compiler.misc.location: kindname.class, BrokenAnnotation, null) +BrokenAnnotation.java:15:34: compiler.err.annotation.type.not.applicable +2 errors \ No newline at end of file diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/parambounds/DuplicateAnnotationValue.java b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/parambounds/DuplicateAnnotationValue.java new file mode 100644 index 00000000000..ae1a043495f --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/parambounds/DuplicateAnnotationValue.java @@ -0,0 +1,13 @@ +/* + * @test /nodynamiccopyright/ + * @bug 6843077 6919944 8006775 + * @summary check for duplicate annotation values for type parameter + * @author Mahmood Ali + * @compile/fail/ref=DuplicateAnnotationValue.out -XDrawDiagnostics DuplicateAnnotationValue.java + */ +import java.lang.annotation.*; +class DuplicateAnnotationValue { +} + +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface A { int value(); } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/parambounds/DuplicateAnnotationValue.out b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/parambounds/DuplicateAnnotationValue.out new file mode 100644 index 00000000000..5badf2cc240 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/parambounds/DuplicateAnnotationValue.out @@ -0,0 +1,2 @@ +DuplicateAnnotationValue.java:9:56: compiler.err.duplicate.annotation.member.value: value, A +1 error diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/parambounds/DuplicateTypeAnnotation.java b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/parambounds/DuplicateTypeAnnotation.java new file mode 100644 index 00000000000..0e64a844f57 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/parambounds/DuplicateTypeAnnotation.java @@ -0,0 +1,13 @@ +/* + * @test /nodynamiccopyright/ + * @bug 6843077 8006775 + * @summary check for duplicate annotations + * @author Mahmood Ali + * @compile/fail/ref=DuplicateTypeAnnotation.out -XDrawDiagnostics DuplicateTypeAnnotation.java + */ +import java.lang.annotation.*; +class DuplicateTypeAnno { +} + +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface A { } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/parambounds/DuplicateTypeAnnotation.out b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/parambounds/DuplicateTypeAnnotation.out new file mode 100644 index 00000000000..09b7843aaf3 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/parambounds/DuplicateTypeAnnotation.out @@ -0,0 +1,3 @@ +DuplicateTypeAnnotation.java:9:35: compiler.err.duplicate.annotation.missing.container: A, java.lang.annotation.Repeatable +DuplicateTypeAnnotation.java:9:38: compiler.err.duplicate.annotation.missing.container: A, java.lang.annotation.Repeatable +2 errors \ No newline at end of file diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/parambounds/InvalidLocation.java b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/parambounds/InvalidLocation.java new file mode 100644 index 00000000000..374a143d26a --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/parambounds/InvalidLocation.java @@ -0,0 +1,13 @@ +/* + * @test /nodynamiccopyright/ + * @bug 6843077 8006775 + * @summary check for invalid annotatins given the target + * @author Mahmood Ali + * @compile/fail/ref=InvalidLocation.out -XDrawDiagnostics InvalidLocation.java + */ + +class InvalidLocation { +} + +@java.lang.annotation.Target(java.lang.annotation.ElementType.TYPE) +@interface A { } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/parambounds/InvalidLocation.out b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/parambounds/InvalidLocation.out new file mode 100644 index 00000000000..d474f174346 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/parambounds/InvalidLocation.out @@ -0,0 +1,2 @@ +InvalidLocation.java:9:33: compiler.err.annotation.type.not.applicable +1 error diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/parambounds/MissingAnnotationValue.java b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/parambounds/MissingAnnotationValue.java new file mode 100644 index 00000000000..58cb921c925 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/parambounds/MissingAnnotationValue.java @@ -0,0 +1,14 @@ +import java.lang.annotation.*; + +/* + * @test /nodynamiccopyright/ + * @bug 6843077 8006775 + * @summary check for missing annotation value + * @author Mahmood Ali + * @compile/fail/ref=MissingAnnotationValue.out -XDrawDiagnostics MissingAnnotationValue.java + */ +class MissingAnnotationValue { +} + +@Target(ElementType.TYPE_USE) +@interface A { int field(); } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/parambounds/MissingAnnotationValue.out b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/parambounds/MissingAnnotationValue.out new file mode 100644 index 00000000000..89f3ef0de98 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/parambounds/MissingAnnotationValue.out @@ -0,0 +1,2 @@ +MissingAnnotationValue.java:10:40: compiler.err.annotation.missing.default.value: A, field +1 error diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/receiver/DuplicateAnnotationValue.java b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/receiver/DuplicateAnnotationValue.java new file mode 100644 index 00000000000..aa0dd5c1eb6 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/receiver/DuplicateAnnotationValue.java @@ -0,0 +1,14 @@ +/* + * @test /nodynamiccopyright/ + * @bug 6843077 6919944 8006775 + * @summary check for duplicate annotation values in receiver + * @author Mahmood Ali + * @compile/fail/ref=DuplicateAnnotationValue.out -XDrawDiagnostics DuplicateAnnotationValue.java + */ +import java.lang.annotation.*; +class DuplicateAnnotationValue { + void test(@A(value = 2, value = 1) DuplicateAnnotationValue this) { } +} + +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface A { int value(); } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/receiver/DuplicateAnnotationValue.out b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/receiver/DuplicateAnnotationValue.out new file mode 100644 index 00000000000..73cff02fa91 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/receiver/DuplicateAnnotationValue.out @@ -0,0 +1,2 @@ +DuplicateAnnotationValue.java:10:27: compiler.err.duplicate.annotation.member.value: value, A +1 error diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/receiver/DuplicateTypeAnnotation.java b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/receiver/DuplicateTypeAnnotation.java new file mode 100644 index 00000000000..1ba2846c42d --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/receiver/DuplicateTypeAnnotation.java @@ -0,0 +1,14 @@ +/* + * @test /nodynamiccopyright/ + * @bug 6843077 8006775 + * @summary check for duplicate annotations in receiver + * @author Mahmood Ali + * @compile/fail/ref=DuplicateTypeAnnotation.out -XDrawDiagnostics DuplicateTypeAnnotation.java + */ +import java.lang.annotation.*; +class DuplicateTypeAnnotation { + void test(@A @A DuplicateTypeAnnotation this) { } +} + +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface A { } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/receiver/DuplicateTypeAnnotation.out b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/receiver/DuplicateTypeAnnotation.out new file mode 100644 index 00000000000..a2f6dba28c3 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/receiver/DuplicateTypeAnnotation.out @@ -0,0 +1,3 @@ +DuplicateTypeAnnotation.java:10:13: compiler.err.duplicate.annotation.missing.container: A, java.lang.annotation.Repeatable +DuplicateTypeAnnotation.java:10:16: compiler.err.duplicate.annotation.missing.container: A, java.lang.annotation.Repeatable +2 errors diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/receiver/InvalidLocation.java b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/receiver/InvalidLocation.java new file mode 100644 index 00000000000..a0f03434387 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/receiver/InvalidLocation.java @@ -0,0 +1,15 @@ +/* + * @test /nodynamiccopyright/ + * @bug 6843077 8006775 + * @summary check for invalid annotatins given the target + * @author Mahmood Ali + * @compile/fail/ref=InvalidLocation.out -XDrawDiagnostics InvalidLocation.java + */ + +class InvalidLocation { + void test(@A InvalidLocation this) { + } +} + +@java.lang.annotation.Target(java.lang.annotation.ElementType.TYPE) +@interface A { } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/receiver/InvalidLocation.out b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/receiver/InvalidLocation.out new file mode 100644 index 00000000000..96a01cec454 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/receiver/InvalidLocation.out @@ -0,0 +1,2 @@ +InvalidLocation.java:10:13: compiler.err.annotation.type.not.applicable +1 error diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/receiver/MissingAnnotationValue.java b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/receiver/MissingAnnotationValue.java new file mode 100644 index 00000000000..4043ed6bc50 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/receiver/MissingAnnotationValue.java @@ -0,0 +1,12 @@ +/* + * @test /nodynamiccopyright/ + * @bug 6843077 8006775 + * @summary check for missing annotation value + * @author Mahmood Ali + * @compile/fail/ref=MissingAnnotationValue.out -XDrawDiagnostics MissingAnnotationValue.java + */ +class MissingAnnotationValue { + void test(@A MissingAnnotationValue this) { } +} + +@interface A { int field(); } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/receiver/MissingAnnotationValue.out b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/receiver/MissingAnnotationValue.out new file mode 100644 index 00000000000..c83391029bf --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/receiver/MissingAnnotationValue.out @@ -0,0 +1,2 @@ +MissingAnnotationValue.java:9:13: compiler.err.annotation.missing.default.value: A, field +1 error diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/receiver/Nesting.java b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/receiver/Nesting.java new file mode 100644 index 00000000000..6b5d7fc3a9f --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/receiver/Nesting.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2008, 2013, 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. + * + * 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. + */ + +/* + * @test + * @bug 8006775 + * @summary Ensure that nested classes/methods work + * @author Werner Dietl + * @compile Nesting.java + */ +@interface A { } + +class Nesting { + void top(@A Nesting this) {} + + class B { + void inB(@A B this) {} + } + + void meth(@A Nesting this) { + class C { + void inMethod(@A C this) {} + } + } +} diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/receiver/StaticThings.java b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/receiver/StaticThings.java new file mode 100644 index 00000000000..35ee8432812 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/receiver/StaticThings.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2008, 2013, 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. + * + * 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. + */ + +/* + * @test + * @bug 8006775 + * @summary the receiver parameter and static methods/classes + * @author Werner Dietl + * @compile/fail/ref=StaticThings.out -XDrawDiagnostics StaticThings.java + */ +class Test { + // bad + static void test1(Test this) {} + + // bad + static Object test2(Test this) { return null; } + + class Nested1 { + // good + void test3a(Nested1 this) {} + // good + void test3b(Test.Nested1 this) {} + // No static methods + // static void test3c(Nested1 this) {} + } + static class Nested2 { + // good + void test4a(Nested2 this) {} + // good + void test4b(Test.Nested2 this) {} + // bad + static void test4c(Nested2 this) {} + // bad + static void test4d(Test.Nested2 this) {} + } +} diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/receiver/StaticThings.out b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/receiver/StaticThings.out new file mode 100644 index 00000000000..fc50011c1b8 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/receiver/StaticThings.out @@ -0,0 +1,5 @@ +StaticThings.java:52:32: compiler.err.annotation.type.not.applicable +StaticThings.java:54:37: compiler.err.annotation.type.not.applicable +StaticThings.java:33:26: compiler.err.annotation.type.not.applicable +StaticThings.java:36:28: compiler.err.annotation.type.not.applicable +4 errors \ No newline at end of file diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/receiver/WrongType.java b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/receiver/WrongType.java new file mode 100644 index 00000000000..63277109f30 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/receiver/WrongType.java @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2008, 2013, 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. + * + * 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. + */ + +/* + * @test + * @bug 8006775 + * @summary the receiver parameter has the type of the surrounding class + * @author Werner Dietl + * @compile/fail/ref=WrongType.out -XDrawDiagnostics WrongType.java + */ + +@interface A {} + +class WrongType { + Object f; + + void good1(@A WrongType this) {} + + void good2(@A WrongType this) { + this.f = null; + Object o = this.f; + } + + void bad1(@A Object this) {} + + void bad2(@A Object this) { + this.f = null; + Object o = this.f; + } + + void wow(@A XYZ this) { + this.f = null; + } + + class Inner { + void good1(@A Inner this) {} + void good2(@A WrongType.Inner this) {} + + void outerOnly(@A WrongType this) {} + void wrongInner(@A Object this) {} + void badOuter(@A Outer.Inner this) {} + void badInner(@A WrongType.XY this) {} + } + + class Generics { + void m(Generics this) {} + } +} diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/receiver/WrongType.out b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/receiver/WrongType.out new file mode 100644 index 00000000000..804425aaf76 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/receiver/WrongType.out @@ -0,0 +1,9 @@ +WrongType.java:51:15: compiler.err.cant.resolve.location: kindname.class, XYZ, , , (compiler.misc.location: kindname.class, WrongType, null) +WrongType.java:61:27: compiler.err.doesnt.exist: Outer +WrongType.java:62:31: compiler.err.cant.resolve.location: kindname.class, XY, , , (compiler.misc.location: kindname.class, WrongType, null) +WrongType.java:44:23: compiler.err.incorrect.receiver.type +WrongType.java:46:23: compiler.err.incorrect.receiver.type +WrongType.java:59:33: compiler.err.incorrect.receiver.type +WrongType.java:60:31: compiler.err.incorrect.receiver.type +WrongType.java:66:28: compiler.err.incorrect.receiver.type +8 errors \ No newline at end of file diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/rest/DuplicateAnnotationValue.java b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/rest/DuplicateAnnotationValue.java new file mode 100644 index 00000000000..5f399fa276f --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/rest/DuplicateAnnotationValue.java @@ -0,0 +1,16 @@ +/* + * @test /nodynamiccopyright/ + * @bug 6843077 8006775 + * @summary check for Duplicate annotation value + * @author Mahmood Ali + * @compile/fail/ref=DuplicateAnnotationValue.out -XDrawDiagnostics DuplicateAnnotationValue.java + */ +import java.lang.annotation.*; +class DuplicateAnnotationValue { + void test() { + new @A String(); + } +} + +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface A { int field(); } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/rest/DuplicateAnnotationValue.out b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/rest/DuplicateAnnotationValue.out new file mode 100644 index 00000000000..dd7e50bbade --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/rest/DuplicateAnnotationValue.out @@ -0,0 +1,2 @@ +DuplicateAnnotationValue.java:11:9: compiler.err.annotation.missing.default.value: A, field +1 error diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/rest/DuplicateTypeAnnotation.java b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/rest/DuplicateTypeAnnotation.java new file mode 100644 index 00000000000..014490f6104 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/rest/DuplicateTypeAnnotation.java @@ -0,0 +1,16 @@ +/* + * @test /nodynamiccopyright/ + * @bug 6843077 8006775 + * @summary check for duplicate annotations + * @author Mahmood Ali + * @compile/fail/ref=DuplicateTypeAnnotation.out -XDrawDiagnostics DuplicateTypeAnnotation.java + */ +import java.lang.annotation.*; +class DuplicateTypeAnnotation { + void test() { + new @A @A String(); + } +} + +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface A { } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/rest/DuplicateTypeAnnotation.out b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/rest/DuplicateTypeAnnotation.out new file mode 100644 index 00000000000..04b67141421 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/rest/DuplicateTypeAnnotation.out @@ -0,0 +1,3 @@ +DuplicateTypeAnnotation.java:11:9: compiler.err.duplicate.annotation.missing.container: A, java.lang.annotation.Repeatable +DuplicateTypeAnnotation.java:11:12: compiler.err.duplicate.annotation.missing.container: A, java.lang.annotation.Repeatable +2 errors \ No newline at end of file diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/rest/InvalidLocation.java b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/rest/InvalidLocation.java new file mode 100644 index 00000000000..c3622976c75 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/rest/InvalidLocation.java @@ -0,0 +1,16 @@ +/* + * @test /nodynamiccopyright/ + * @bug 6843077 8006775 + * @summary check for invalid annotatins given the target + * @author Mahmood Ali + * @compile/fail/ref=InvalidLocation.out -XDrawDiagnostics InvalidLocation.java + */ + +class InvalidLocation { + void test() { + new @A String(); + } +} + +@java.lang.annotation.Target(java.lang.annotation.ElementType.TYPE) +@interface A { } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/rest/InvalidLocation.out b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/rest/InvalidLocation.out new file mode 100644 index 00000000000..ad9861c2f6f --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/rest/InvalidLocation.out @@ -0,0 +1,2 @@ +InvalidLocation.java:11:9: compiler.err.annotation.type.not.applicable +1 error diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/rest/MissingAnnotationValue.java b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/rest/MissingAnnotationValue.java new file mode 100644 index 00000000000..5a6bb4299b8 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/rest/MissingAnnotationValue.java @@ -0,0 +1,14 @@ +/* + * @test /nodynamiccopyright/ + * @bug 6843077 8006775 + * @summary check for missing annotation value + * @author Mahmood Ali + * @compile/fail/ref=MissingAnnotationValue.out -XDrawDiagnostics MissingAnnotationValue.java + */ +class MissingAnnotationValue { + void test() { + new @A String(); + } +} + +@interface A { int field(); } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/rest/MissingAnnotationValue.out b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/rest/MissingAnnotationValue.out new file mode 100644 index 00000000000..f83f6dfa58a --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/rest/MissingAnnotationValue.out @@ -0,0 +1,2 @@ +MissingAnnotationValue.java:10:9: compiler.err.annotation.missing.default.value: A, field +1 error diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/typeArgs/DuplicateAnnotationValue.java b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/typeArgs/DuplicateAnnotationValue.java new file mode 100644 index 00000000000..a1f432e5563 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/typeArgs/DuplicateAnnotationValue.java @@ -0,0 +1,14 @@ +/* + * @test /nodynamiccopyright/ + * @bug 6843077 6919944 8006775 + * @summary check for duplicate annotation values for type parameter + * @author Mahmood Ali + * @compile/fail/ref=DuplicateAnnotationValue.out -XDrawDiagnostics DuplicateAnnotationValue.java + */ +import java.lang.annotation.*; +class DuplicateAnnotationValue { + DuplicateAnnotationValue<@A(value = 2, value = 1) String> l; +} + +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface A { int value(); } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/typeArgs/DuplicateAnnotationValue.out b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/typeArgs/DuplicateAnnotationValue.out new file mode 100644 index 00000000000..c8e21def939 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/typeArgs/DuplicateAnnotationValue.out @@ -0,0 +1,2 @@ +DuplicateAnnotationValue.java:10:42: compiler.err.duplicate.annotation.member.value: value, A +1 error diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/typeArgs/DuplicateTypeAnnotation.java b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/typeArgs/DuplicateTypeAnnotation.java new file mode 100644 index 00000000000..c25afb5c412 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/typeArgs/DuplicateTypeAnnotation.java @@ -0,0 +1,14 @@ +/* + * @test /nodynamiccopyright/ + * @bug 6843077 8006775 + * @summary check for duplicate annotations + * @author Mahmood Ali + * @compile/fail/ref=DuplicateTypeAnnotation.out -XDrawDiagnostics DuplicateTypeAnnotation.java + */ +import java.lang.annotation.*; +class DuplicateTypeAnno { + DuplicateTypeAnno<@A @A String> l; +} + +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface A { } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/typeArgs/DuplicateTypeAnnotation.out b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/typeArgs/DuplicateTypeAnnotation.out new file mode 100644 index 00000000000..3b6802d9038 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/typeArgs/DuplicateTypeAnnotation.out @@ -0,0 +1,3 @@ +DuplicateTypeAnnotation.java:10:21: compiler.err.duplicate.annotation.missing.container: A, java.lang.annotation.Repeatable +DuplicateTypeAnnotation.java:10:24: compiler.err.duplicate.annotation.missing.container: A, java.lang.annotation.Repeatable +2 errors \ No newline at end of file diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/typeArgs/InvalidLocation.java b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/typeArgs/InvalidLocation.java new file mode 100644 index 00000000000..4b12e79df24 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/typeArgs/InvalidLocation.java @@ -0,0 +1,14 @@ +/* + * @test /nodynamiccopyright/ + * @bug 6843077 8006775 + * @summary check for invalid annotatins given the target + * @author Mahmood Ali + * @compile/fail/ref=InvalidLocation.out -XDrawDiagnostics InvalidLocation.java + */ + +class InvalidLocation { + InvalidLocation<@A String> l; +} + +@java.lang.annotation.Target(java.lang.annotation.ElementType.TYPE) +@interface A { } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/typeArgs/InvalidLocation.out b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/typeArgs/InvalidLocation.out new file mode 100644 index 00000000000..30841b78f0f --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/typeArgs/InvalidLocation.out @@ -0,0 +1,2 @@ +InvalidLocation.java:10:19: compiler.err.annotation.type.not.applicable +1 error diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/typeArgs/MissingAnnotationValue.java b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/typeArgs/MissingAnnotationValue.java new file mode 100644 index 00000000000..a6e00304fa1 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/typeArgs/MissingAnnotationValue.java @@ -0,0 +1,12 @@ +/* + * @test /nodynamiccopyright/ + * @bug 6843077 8006775 + * @summary check for missing annotation value + * @author Mahmood Ali + * @compile/fail/ref=MissingAnnotationValue.out -XDrawDiagnostics MissingAnnotationValue.java + */ +class MissingAnnotationValue { + MissingAnnotationValue<@A String> l; +} + +@interface A { int field(); } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/typeArgs/MissingAnnotationValue.out b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/typeArgs/MissingAnnotationValue.out new file mode 100644 index 00000000000..749442f45b6 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/typeArgs/MissingAnnotationValue.out @@ -0,0 +1,2 @@ +MissingAnnotationValue.java:9:26: compiler.err.annotation.missing.default.value: A, field +1 error diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/typeparams/DuplicateAnnotationValue.java b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/typeparams/DuplicateAnnotationValue.java new file mode 100644 index 00000000000..22ab06ef225 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/typeparams/DuplicateAnnotationValue.java @@ -0,0 +1,13 @@ +/* + * @test /nodynamiccopyright/ + * @bug 6843077 6919944 8006775 + * @summary check for duplicate annotation values for type parameter + * @author Mahmood Ali + * @compile/fail/ref=DuplicateAnnotationValue.out -XDrawDiagnostics DuplicateAnnotationValue.java + */ +import java.lang.annotation.*; +class DuplicateAnnotationValue<@A(value = 2, value = 1) K> { +} + +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface A { int value(); } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/typeparams/DuplicateAnnotationValue.out b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/typeparams/DuplicateAnnotationValue.out new file mode 100644 index 00000000000..b3485b2332b --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/typeparams/DuplicateAnnotationValue.out @@ -0,0 +1,2 @@ +DuplicateAnnotationValue.java:9:46: compiler.err.duplicate.annotation.member.value: value, A +1 error diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/typeparams/DuplicateTypeAnnotation.java b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/typeparams/DuplicateTypeAnnotation.java new file mode 100644 index 00000000000..20883a0ba85 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/typeparams/DuplicateTypeAnnotation.java @@ -0,0 +1,13 @@ +/* + * @test /nodynamiccopyright/ + * @bug 6843077 8006775 + * @summary check for duplicate annotations + * @author Mahmood Ali + * @compile/fail/ref=DuplicateTypeAnnotation.out -XDrawDiagnostics DuplicateTypeAnnotation.java + */ +import java.lang.annotation.*; +class DuplicateTypeAnno<@A @A K> { +} + +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface A { } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/typeparams/DuplicateTypeAnnotation.out b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/typeparams/DuplicateTypeAnnotation.out new file mode 100644 index 00000000000..6fd3ba6e32b --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/typeparams/DuplicateTypeAnnotation.out @@ -0,0 +1,3 @@ +DuplicateTypeAnnotation.java:9:25: compiler.err.duplicate.annotation.missing.container: A, java.lang.annotation.Repeatable +DuplicateTypeAnnotation.java:9:28: compiler.err.duplicate.annotation.missing.container: A, java.lang.annotation.Repeatable +2 errors \ No newline at end of file diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/typeparams/InvalidLocation.java b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/typeparams/InvalidLocation.java new file mode 100644 index 00000000000..094a76ccab1 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/typeparams/InvalidLocation.java @@ -0,0 +1,13 @@ +/* + * @test /nodynamiccopyright/ + * @bug 6843077 8006775 + * @summary check for invalid annotatins given the target + * @author Mahmood Ali + * @compile/fail/ref=InvalidLocation.out -XDrawDiagnostics InvalidLocation.java + */ + +class InvalidLocation<@A K> { +} + +@java.lang.annotation.Target(java.lang.annotation.ElementType.TYPE) +@interface A { } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/typeparams/InvalidLocation.out b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/typeparams/InvalidLocation.out new file mode 100644 index 00000000000..87d42a278c4 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/typeparams/InvalidLocation.out @@ -0,0 +1,2 @@ +InvalidLocation.java:9:23: compiler.err.annotation.type.not.applicable +1 error diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/typeparams/MissingAnnotationValue.java b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/typeparams/MissingAnnotationValue.java new file mode 100644 index 00000000000..39f8bee930f --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/typeparams/MissingAnnotationValue.java @@ -0,0 +1,11 @@ +/* + * @test /nodynamiccopyright/ + * @bug 6843077 8006775 + * @summary check for missing annotation value + * @author Mahmood Ali + * @compile/fail/ref=MissingAnnotationValue.out -XDrawDiagnostics MissingAnnotationValue.java + */ +class MissingAnnotationValue<@A K> { +} + +@interface A { int field(); } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/typeparams/MissingAnnotationValue.out b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/typeparams/MissingAnnotationValue.out new file mode 100644 index 00000000000..acac021869b --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/typeparams/MissingAnnotationValue.out @@ -0,0 +1,2 @@ +MissingAnnotationValue.java:8:30: compiler.err.annotation.missing.default.value: A, field +1 error diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/wildcards/DuplicateAnnotationValue.java b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/wildcards/DuplicateAnnotationValue.java new file mode 100644 index 00000000000..7355719f607 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/wildcards/DuplicateAnnotationValue.java @@ -0,0 +1,14 @@ +/* + * @test /nodynamiccopyright/ + * @bug 6843077 6919944 8006775 + * @summary check for duplicate annotation values for type parameter + * @author Mahmood Ali + * @compile/fail/ref=DuplicateAnnotationValue.out -XDrawDiagnostics DuplicateAnnotationValue.java + */ +import java.lang.annotation.*; +class DuplicateAnnotationValue { + DuplicateAnnotationValue<@A(value = 2, value = 1) ?> l; +} + +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface A { int value(); } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/wildcards/DuplicateAnnotationValue.out b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/wildcards/DuplicateAnnotationValue.out new file mode 100644 index 00000000000..c8e21def939 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/wildcards/DuplicateAnnotationValue.out @@ -0,0 +1,2 @@ +DuplicateAnnotationValue.java:10:42: compiler.err.duplicate.annotation.member.value: value, A +1 error diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/wildcards/DuplicateTypeAnnotation.java b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/wildcards/DuplicateTypeAnnotation.java new file mode 100644 index 00000000000..17ac7a98cbe --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/wildcards/DuplicateTypeAnnotation.java @@ -0,0 +1,14 @@ +/* + * @test /nodynamiccopyright/ + * @bug 6843077 8006775 + * @summary check for duplicate annotations + * @author Mahmood Ali + * @compile/fail/ref=DuplicateTypeAnnotation.out -XDrawDiagnostics DuplicateTypeAnnotation.java + */ +import java.lang.annotation.*; +class DuplicateTypeAnno { + DuplicateTypeAnno<@A @A ?> l; +} + +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface A { } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/wildcards/DuplicateTypeAnnotation.out b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/wildcards/DuplicateTypeAnnotation.out new file mode 100644 index 00000000000..3b6802d9038 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/wildcards/DuplicateTypeAnnotation.out @@ -0,0 +1,3 @@ +DuplicateTypeAnnotation.java:10:21: compiler.err.duplicate.annotation.missing.container: A, java.lang.annotation.Repeatable +DuplicateTypeAnnotation.java:10:24: compiler.err.duplicate.annotation.missing.container: A, java.lang.annotation.Repeatable +2 errors \ No newline at end of file diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/wildcards/InvalidLocation.java b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/wildcards/InvalidLocation.java new file mode 100644 index 00000000000..eee6ed28b73 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/wildcards/InvalidLocation.java @@ -0,0 +1,14 @@ +/* + * @test /nodynamiccopyright/ + * @bug 6843077 8006775 + * @summary check for invalid annotatins given the target + * @author Mahmood Ali + * @compile/fail/ref=InvalidLocation.out -XDrawDiagnostics InvalidLocation.java + */ + +class InvalidLocation { + InvalidLocation<@A ?> l; +} + +@java.lang.annotation.Target(java.lang.annotation.ElementType.TYPE) +@interface A { } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/wildcards/InvalidLocation.out b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/wildcards/InvalidLocation.out new file mode 100644 index 00000000000..30841b78f0f --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/wildcards/InvalidLocation.out @@ -0,0 +1,2 @@ +InvalidLocation.java:10:19: compiler.err.annotation.type.not.applicable +1 error diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/wildcards/MissingAnnotationValue.java b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/wildcards/MissingAnnotationValue.java new file mode 100644 index 00000000000..c111c895c7d --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/wildcards/MissingAnnotationValue.java @@ -0,0 +1,12 @@ +/* + * @test /nodynamiccopyright/ + * @bug 6843077 8006775 + * @summary check for missing annotation value + * @author Mahmood Ali + * @compile/fail/ref=MissingAnnotationValue.out -XDrawDiagnostics MissingAnnotationValue.java + */ +class MissingAnnotationValue { + MissingAnnotationValue<@A ?> l; +} + +@interface A { int field(); } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/wildcards/MissingAnnotationValue.out b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/wildcards/MissingAnnotationValue.out new file mode 100644 index 00000000000..749442f45b6 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/wildcards/MissingAnnotationValue.out @@ -0,0 +1,2 @@ +MissingAnnotationValue.java:9:26: compiler.err.annotation.missing.default.value: A, field +1 error diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/target/Constructor.java b/langtools/test/tools/javac/annotations/typeAnnotations/failures/target/Constructor.java new file mode 100644 index 00000000000..bbba6345611 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/target/Constructor.java @@ -0,0 +1,37 @@ +/* + * @test /nodynamiccopyright/ + * @bug 6843077 8006775 + * @summary test invalid location of TypeUse + * @author Mahmood Ali + * @compile/fail/ref=Constructor.out -XDrawDiagnostics Constructor.java + */ + +import java.lang.annotation.Target; +import java.lang.annotation.ElementType; + +class Constructor { + // Constructor result type use annotation + @A Constructor() { } + + // Not type parameter annotation + @B Constructor(int x) { } + + // TODO add err: no "this" receiver parameter for constructors + // Constructor(@A Constructor this, Object o) { } + + // TODO: support Outer.this. +} + +class Constructor2 { + class Inner { + // OK + @A Inner() { } + } +} + +@Target(ElementType.TYPE_USE) +@interface A { } + +@Target(ElementType.TYPE_PARAMETER) +@interface B { } + diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/target/Constructor.out b/langtools/test/tools/javac/annotations/typeAnnotations/failures/target/Constructor.out new file mode 100644 index 00000000000..05689245d5f --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/target/Constructor.out @@ -0,0 +1,2 @@ +Constructor.java:17:3: compiler.err.annotation.type.not.applicable +1 error \ No newline at end of file diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/target/DotClass.java b/langtools/test/tools/javac/annotations/typeAnnotations/failures/target/DotClass.java new file mode 100644 index 00000000000..9aaa99e7e99 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/target/DotClass.java @@ -0,0 +1,74 @@ +import static java.lang.annotation.ElementType.TYPE; +import static java.lang.annotation.ElementType.TYPE_PARAMETER; +import static java.lang.annotation.ElementType.TYPE_USE; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/* + * Copyright (c) 2009 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. + * + * 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. + */ + +/* + * @test + * @summary Class literals are not type uses and cannot be annotated + * @author Werner Dietl + * @compile/fail/ref=DotClass.out -XDrawDiagnostics DotClass.java + */ + +@Target({TYPE_USE, TYPE_PARAMETER, TYPE}) +@Retention(RetentionPolicy.RUNTIME) +@interface A {} + +@interface B { int value(); } + +class T0x1E { + void m0x1E() { + Class c = @A Object.class; + } + + Class c = @A String.class; + + Class as = @A String.class; +} + +class ClassLiterals { + public static void main(String[] args) { + if (String.class != @A String.class) throw new Error(); + if (@A int.class != int.class) throw new Error(); + if (@A int.class != Integer.TYPE) throw new Error(); + if (@A int @B(0) [].class != int[].class) throw new Error(); + + if (String[].class != @A String[].class) throw new Error(); + if (String[].class != String @A [].class) throw new Error(); + if (@A int[].class != int[].class) throw new Error(); + if (@A int @B(0) [].class != int[].class) throw new Error(); + } + + Object classLit1 = @A String @C [] @B(0) [].class; + Object classLit2 = @A String @C [] [].class; + Object classLit3 = @A String [] @B(0) [].class; + Object classLit4 = String [] @B(0) [].class; + Object classLit5 = String @C [] [].class; + Object classLit6 = String [] [].class; +} diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/target/DotClass.out b/langtools/test/tools/javac/annotations/typeAnnotations/failures/target/DotClass.out new file mode 100644 index 00000000000..c40f3d7cd74 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/target/DotClass.out @@ -0,0 +1,17 @@ +DotClass.java:47:42: compiler.err.no.annotations.on.dot.class +DotClass.java:50:33: compiler.err.no.annotations.on.dot.class +DotClass.java:52:52: compiler.err.no.annotations.on.dot.class +DotClass.java:57:44: compiler.err.no.annotations.on.dot.class +DotClass.java:58:26: compiler.err.no.annotations.on.dot.class +DotClass.java:59:26: compiler.err.no.annotations.on.dot.class +DotClass.java:60:35: compiler.err.no.annotations.on.dot.class +DotClass.java:62:48: compiler.err.no.annotations.on.dot.class +DotClass.java:63:49: compiler.err.no.annotations.on.dot.class +DotClass.java:64:28: compiler.err.no.annotations.on.dot.class +DotClass.java:65:35: compiler.err.no.annotations.on.dot.class +DotClass.java:68:54: compiler.err.no.annotations.on.dot.class +DotClass.java:69:54: compiler.err.no.annotations.on.dot.class +DotClass.java:70:54: compiler.err.no.annotations.on.dot.class +DotClass.java:71:54: compiler.err.no.annotations.on.dot.class +DotClass.java:72:54: compiler.err.no.annotations.on.dot.class +16 errors \ No newline at end of file diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/target/IncompleteArray.java b/langtools/test/tools/javac/annotations/typeAnnotations/failures/target/IncompleteArray.java new file mode 100644 index 00000000000..c414a5f807e --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/target/IncompleteArray.java @@ -0,0 +1,12 @@ +/* + * @test /nodynamiccopyright/ + * @bug 6843077 8006775 + * @summary test incomplete array declaration + * @author Mahmood Ali + * @compile/fail/ref=IncompleteArray.out -XDrawDiagnostics IncompleteArray.java + */ +class IncompleteArray { + int @A [] @A var; +} + +@interface A { } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/target/IncompleteArray.out b/langtools/test/tools/javac/annotations/typeAnnotations/failures/target/IncompleteArray.out new file mode 100644 index 00000000000..a03a09283ee --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/target/IncompleteArray.out @@ -0,0 +1,2 @@ +IncompleteArray.java:9:13: compiler.err.illegal.start.of.type +1 error diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/target/NotTypeParameter.java b/langtools/test/tools/javac/annotations/typeAnnotations/failures/target/NotTypeParameter.java new file mode 100644 index 00000000000..49ba85f344d --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/target/NotTypeParameter.java @@ -0,0 +1,25 @@ +/* + * @test /nodynamiccopyright/ + * @bug 6843077 8006775 + * @summary test invalid location of TypeUse and TypeParameter + * @author Mahmood Ali + * @compile/fail/ref=NotTypeParameter.out -XDrawDiagnostics NotTypeParameter.java + */ + +import java.lang.annotation.Target; +import java.lang.annotation.ElementType; + +class VoidMethod<@A K> { + @A void test() { } +} + +@Target(ElementType.TYPE_USE) +@interface A { } + +class TypeVariable<@B T> { + @B T test1() { return null; } + void test2(@B T p) {} +} + +@Target(ElementType.TYPE_PARAMETER) +@interface B { } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/target/NotTypeParameter.out b/langtools/test/tools/javac/annotations/typeAnnotations/failures/target/NotTypeParameter.out new file mode 100644 index 00000000000..40e4ebc7068 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/target/NotTypeParameter.out @@ -0,0 +1,4 @@ +NotTypeParameter.java:13:3: compiler.err.annotation.type.not.applicable +NotTypeParameter.java:20:3: compiler.err.annotation.type.not.applicable +NotTypeParameter.java:21:14: compiler.err.annotation.type.not.applicable +3 errors diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/target/NotTypeUse.java b/langtools/test/tools/javac/annotations/typeAnnotations/failures/target/NotTypeUse.java new file mode 100644 index 00000000000..6c8bfeee3b6 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/target/NotTypeUse.java @@ -0,0 +1,17 @@ +/* + * @test /nodynamiccopyright/ + * @bug 6843077 8006775 + * @summary test invalid location of TypeUse + * @author Mahmood Ali + * @compile/fail/ref=NotTypeUse.out -XDrawDiagnostics NotTypeUse.java + */ + +import java.lang.annotation.Target; +import java.lang.annotation.ElementType; + +class VoidMethod { + @A void test() { } +} + +@Target(ElementType.TYPE) +@interface A { } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/target/NotTypeUse.out b/langtools/test/tools/javac/annotations/typeAnnotations/failures/target/NotTypeUse.out new file mode 100644 index 00000000000..9728d3589ec --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/target/NotTypeUse.out @@ -0,0 +1,2 @@ +NotTypeUse.java:13:3: compiler.err.annotation.type.not.applicable +1 error diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/target/VoidMethod.java b/langtools/test/tools/javac/annotations/typeAnnotations/failures/target/VoidMethod.java new file mode 100644 index 00000000000..a82768ce76b --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/target/VoidMethod.java @@ -0,0 +1,33 @@ +/* + * @test /nodynamiccopyright/ + * @bug 6843077 8006775 + * @summary test invalid location of TypeUse and TypeParameter + * @author Mahmood Ali + * @compile/fail/ref=VoidMethod.out -XDrawDiagnostics VoidMethod.java + */ + +import java.lang.annotation.Target; +import java.lang.annotation.ElementType; + +class VoidMethod { + // Invalid + @A void test1() { } + // The following is legal: + @B void test2() { } + // Invalid + @C void test3() { } + // The following is legal: + @D void test4() { } +} + +@Target(ElementType.TYPE_USE) +@interface A { } + +@Target({ElementType.TYPE_USE, ElementType.METHOD}) +@interface B { } + +@Target(ElementType.TYPE_PARAMETER) +@interface C { } + +@Target({ElementType.TYPE_PARAMETER, ElementType.METHOD}) +@interface D { } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/target/VoidMethod.out b/langtools/test/tools/javac/annotations/typeAnnotations/failures/target/VoidMethod.out new file mode 100644 index 00000000000..7cbba4aa163 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/target/VoidMethod.out @@ -0,0 +1,3 @@ +VoidMethod.java:14:3: compiler.err.annotation.type.not.applicable +VoidMethod.java:18:3: compiler.err.annotation.type.not.applicable +2 errors diff --git a/langtools/test/tools/javac/typeAnnotations/newlocations/BasicTest.java b/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/BasicTest.java similarity index 73% rename from langtools/test/tools/javac/typeAnnotations/newlocations/BasicTest.java rename to langtools/test/tools/javac/annotations/typeAnnotations/newlocations/BasicTest.java index a5de45959cb..8c7fb83a3f1 100644 --- a/langtools/test/tools/javac/typeAnnotations/newlocations/BasicTest.java +++ b/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/BasicTest.java @@ -1,6 +1,6 @@ /* - * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2013, 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 @@ -24,22 +24,25 @@ /* * @test - * @bug 6843077 + * @bug 6843077 8006775 * @summary random tests for new locations * @author Matt Papi - * @compile/fail/ref=BasicTest.out -XDrawDiagnostics BasicTest.java + * @compile BasicTest.java */ +import java.lang.annotation.*; import java.util.*; import java.io.*; +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) @interface A {} +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) @interface B {} +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) @interface C {} +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) @interface D {} -//308: Test inverted to verify that type annotations can not be parsed yet. - /** * Tests basic JSR 308 parser functionality. We don't really care about what * the parse tree looks like, just that these annotations can be parsed. @@ -48,8 +51,7 @@ class BasicTest extends @B LinkedList implements @C List void test() { - // Handle annotated class literals/cast types - Class c = @A String.class; + // Handle annotated cast types Object o = (@A Object) "foo"; // Handle annotated "new" expressions (except arrays; see ArrayTest) @@ -57,21 +59,23 @@ class BasicTest extends @B LinkedList implements @C List boolean b = o instanceof @A Object; - @A Map<@B List<@C String>, @D String> map = new @A HashMap<@B List<@C String>, @D String>(); - Class c2 = @A String.class; + Class c2 = null; } // Handle receiver annotations // Handle annotations on a qualified identifier list - void test2() @C @D throws @A IllegalArgumentException, @B IOException { + void test2(@C @D BasicTest this) throws @A IllegalArgumentException, @B IOException { } // Handle annotations on a varargs element type - void test3(Object @A... objs) { + void test3(@B Object @A... objs) { } - } + void test4(@B Class<@C ?> @A ... clz) { } + + + // TODO: add more tests... nested classes, etc. } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/ClassExtends.java b/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/ClassExtends.java new file mode 100644 index 00000000000..24df0774fa4 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/ClassExtends.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2008, 2013, 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. + * + * 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. + */ + +import java.lang.annotation.*; + +/* + * @test + * @bug 6843077 8006775 + * @summary new type annotation location: class extends/implements + * @author Mahmood Ali + * @compile ClassExtends.java + */ +abstract class MyClass extends @A ParameterizedClass<@B String> + implements @B CharSequence, @A ParameterizedInterface<@B String> { } + +interface MyInterface extends @A ParameterizedInterface<@A String>, + @B CharSequence { } + +class ParameterizedClass {} +interface ParameterizedInterface {} + +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface A {} +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface B {} diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/ClassParameters.java b/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/ClassParameters.java new file mode 100644 index 00000000000..9b2fbbe8045 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/ClassParameters.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2008, 2013, 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. + * + * 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. + */ + +import java.lang.annotation.*; + +/* + * @test + * @bug 6843077 8006775 + * @summary new type annotation location: class type parameter bounds + * @author Mahmood Ali + * @compile ClassParameters.java + */ +class Unannotated { } + +class ExtendsBound { } +class ExtendsGeneric> { } +class TwoBounds { } + +class Complex1 { } +class Complex2 { } +class ComplexBoth { } + +class Outer { + void inner() { + class Unannotated { } + + class ExtendsBound { } + class ExtendsGeneric> { } + class TwoBounds { } + + class Complex1 { } + class Complex2 { } + class ComplexBoth { } + } +} + +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface A { } +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface B { } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/ConstructorTypeArgs.java b/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/ConstructorTypeArgs.java new file mode 100644 index 00000000000..6db9804fdee --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/ConstructorTypeArgs.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2008, 2013, 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. + * + * 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. + */ + +import java.lang.annotation.*; + +/* + * @test + * @bug 6843077 8006775 + * @summary new type annotation location: constructor type args + * @author Mahmood Ali + * @compile ConstructorTypeArgs.java + */ + +class ConstructorTypeArgs { + void oneArg() { + new @A MyList<@A String>(); + new MyList<@A MyList<@B(0) String>>(); + } + + void twoArg() { + new MyMap(); + new MyMap<@A String, @B(0) MyList<@A String>>(); + } + + void withArraysIn() { + new MyList(); + new MyList<@A String @B(0) [] @A []>(); + + new MyMap<@A String[], @B(0) MyList<@A String> @A []>(); + } +} + +class MyList { } +class MyMap { } + +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface A { } +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface B { int value(); } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/ExceptionParameters.java b/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/ExceptionParameters.java new file mode 100644 index 00000000000..81b327c5c04 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/ExceptionParameters.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2013, 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. + * + * 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. + */ + +import java.lang.annotation.*; + +import java.io.*; + +/* + * @test + * @bug 6843077 8006775 + * @summary new type annotation location: exception parameters + * @author Werner Dietl + * @compile ExceptionParameters.java + */ + +class ExceptionParameters { + + void exception() { + try { + foobar(); + } catch (@A Exception e) { + e.toString(); + } + } + + void finalException() { + try { + foobar(); + } catch (final @B Exception e) { + e.toString(); + } + } + + void multiException1() { + try { + foobar(); + } catch (@A NullPointerException | @B IndexOutOfBoundsException e) { + e.toString(); + } + } + + void multiException2() { + try { + foobar(); + } catch (java.lang.@A NullPointerException | java.lang.@B IndexOutOfBoundsException e) { + e.toString(); + } + } + + void foobar() {} +} + +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface A { } +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface B { } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/Expressions.java b/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/Expressions.java new file mode 100644 index 00000000000..bd4acc9c895 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/Expressions.java @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2008, 2013, 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. + * + * 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. + */ + +import java.lang.annotation.*; + +/* + * @test + * @bug 6843077 8006775 + * @summary new type annotation location: expressions + * @author Mahmood Ali + * @compile Expressions.java + */ +class Expressions { + void instanceOf() { + Object o = null; + boolean a = o instanceof @A String; + boolean b = o instanceof @B(0) String; + } + + void instanceOfArray() { + Object o = null; + boolean a1 = o instanceof @A String []; + boolean a2 = o instanceof @B(0) String []; + + boolean b1 = o instanceof String @A []; + boolean b2 = o instanceof String @B(0) []; + } + + void objectCreation() { + new @A String(); + new @B(0) String(); + } + + void objectCreationArray() { + Object a1 = new @A String [] [] { }; + Object a2 = new @A String [1] []; + Object a3 = new @A String [1] [2]; + + Object b1 = new @A String @B(0) [] [] { }; + Object b2 = new @A String @B(0) [1] []; + Object b3 = new @A String @B(0) [1] [2]; + + Object c1 = new @A String [] @B(0) [] { }; + Object c2 = new @A String [1] @B(0) []; + Object c3 = new @A String [1] @B(0) [2]; + + Object d1 = new @A String @B(0) [] @B(0) [] { }; + Object d2 = new @A String @B(0) [1] @B(0) []; + Object d3 = new @A String @B(0) [1] @B(0) [2]; + + Object rand = new @A String @B(value = 0) [1] @B(value = 0) [2]; + + } +} + +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface A { } +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface B { int value(); } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/Fields.java b/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/Fields.java new file mode 100644 index 00000000000..04fb39f021e --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/Fields.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2008, 2013, 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. + * + * 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. + */ + +import java.lang.annotation.*; + +/* + * @test + * @bug 6843077 8006775 + * @summary new type annotation location: field type array/generics + * @author Mahmood Ali + * @compile Fields.java + */ + +class DefaultScope { + Parameterized unannotated; + Parameterized<@A String, String> firstTypeArg; + Parameterized secondTypeArg; + Parameterized<@A String, @B String> bothTypeArgs; + + Parameterized<@A Parameterized<@A String, @B String>, @B String> + nestedParameterized; + + @A String [] array1; + @A String @B [] array1Deep; + @A String [] [] array2; + @A String @A [] @B [] array2Deep; + String @A [] [] array2First; + String [] @B [] array2Second; + + // Old-style array syntax + String array2FirstOld @A []; + String array2SecondOld [] @B []; +} + +class ModifiedScoped { + public final Parameterized unannotated = null; + public final Parameterized<@A String, String> firstTypeArg = null; + public final Parameterized secondTypeArg = null; + public final Parameterized<@A String, @B String> bothTypeArgs = null; + + public final Parameterized<@A Parameterized<@A String, @B String>, @B String> + nestedParameterized = null; + + public final @A String [] array1 = null; + public final @A String @B [] array1Deep = null; + public final @A String [] [] array2 = null; + public final @A String @A [] @B [] array2Deep = null; + public final String @A [] [] array2First = null; + public final String [] @B [] array2Second = null; +} + +class Parameterized { } + +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface A { } +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface B { } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/LocalVariables.java b/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/LocalVariables.java new file mode 100644 index 00000000000..9f057f5807a --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/LocalVariables.java @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2008, 2013, 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. + * + * 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. + */ + +import java.lang.annotation.*; + +/* + * @test + * @bug 6843077 8006775 + * @summary new type annotation location: local variables array/generics + * @author Mahmood Ali + * @compile LocalVariables.java + */ + +class DefaultScope { + void parameterized() { + Parameterized unannotated; + Parameterized<@A String, String> firstTypeArg; + Parameterized secondTypeArg; + Parameterized<@A String, @B String> bothTypeArgs; + + Parameterized<@A Parameterized<@A String, @B String>, @B String> + nestedParameterized; + } + + void arrays() { + @A String [] array1; + @A String @B [] array1Deep; + @A String [] [] array2; + @A String @A [] @B [] array2Deep; + String @A [] [] array2First; + String [] @B [] array2Second; + } +} + +class ModifiedVars { + void parameterized() { + final Parameterized unannotated = null; + final Parameterized<@A String, String> firstTypeArg = null; + final Parameterized secondTypeArg = null; + final Parameterized<@A String, @B String> bothTypeArgs = null; + + final Parameterized<@A Parameterized<@A String, @B String>, @B String> + nestedParameterized = null; + } + + void arrays() { + final @A String [] array1 = null; + final @A String @B [] array1Deep = null; + final @A String [] [] array2 = null; + final @A String @A [] @B [] array2Deep = null; + final String @A [] [] array2First = null; + final String [] @B [] array2Second = null; + } +} + +class Parameterized { } + +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface A { } +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface B { } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/MethodReturnType.java b/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/MethodReturnType.java new file mode 100644 index 00000000000..1a3b4905155 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/MethodReturnType.java @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2008, 2013, 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. + * + * 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. + */ + +import java.lang.annotation.*; + +/* + * @test + * @bug 6843077 8006775 + * @summary new type annotation location: method return type array/generics + * @author Mahmood Ali + * @compile MethodReturnType.java + */ + +class DefaultScope { + Parameterized unannotated() { return null; } + Parameterized<@A String, String> firstTypeArg() { return null; } + Parameterized secondTypeArg() { return null; } + Parameterized<@A String, @B String> bothTypeArgs() { return null; } + + Parameterized<@A Parameterized<@A String, @B String>, @B String> + nestedParameterized() { return null; } + + public @A String method() { return null; } + + @A String [] array1() { return null; } + @A String @B [] array1Deep() { return null; } + @A String [] [] array2() { return null; } + @A String @A [] @B [] array2Deep() { return null; } + String @A [] [] array2First() { return null; } + String [] @B [] array2Second() { return null; } + + // Old-style array syntax + String array2FirstOld() @A [] { return null; } + String array2SecondOld() [] @B [] { return null; } +} + +class ModifiedScoped { + public final Parameterized unannotated() { return null; } + public final Parameterized<@A String, String> firstTypeArg() { return null; } + public final Parameterized secondTypeArg() { return null; } + public final Parameterized<@A String, @B String> bothTypeArgs() { return null; } + + public final Parameterized<@A Parameterized<@A String, @B String>, @B String> + nestedParameterized() { return null; } + + public final @A String [] array1() { return null; } + public final @A String @B [] array1Deep() { return null; } + public final @A String [] [] array2() { return null; } + public final @A String @A [] @B [] array2Deep() { return null; } + public final String @A [] [] array2First() { return null; } + public final String [] @B [] array2Second() { return null; } +} + +class Parameterized { } + +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface A { } +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface B { } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/MethodTypeArgs.java b/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/MethodTypeArgs.java new file mode 100644 index 00000000000..1da62766208 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/MethodTypeArgs.java @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2008, 2013, 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. + * + * 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. + */ + +import java.lang.annotation.*; + +/* + * @test + * @bug 6843077 8006775 + * @summary new type annotation location: method type args + * @author Mahmood Ali + * @compile MethodTypeArgs.java + */ + +class MethodTypeArgs { + void oneArg() { + this.<@A String>newList(); + this.<@A MyList<@B(0) String>>newList(); + + MethodTypeArgs.<@A String>newList(); + MethodTypeArgs.<@A MyList<@B(0) String>>newList(); + } + + void twoArg() { + this.newMap(); + this.<@A String, @B(0) MyList<@A String>>newMap(); + + MethodTypeArgs.newMap(); + MethodTypeArgs.<@A String, @B(0) MyList<@A String>>newMap(); + } + + void withArraysIn() { + this.newList(); + this.<@A String @B(0) [] @A []>newList(); + + this.<@A String[], @B(0) MyList<@A String> @A []>newMap(); + } + + static void newList() { } + static void newMap() { } +} + +class MyList { } + +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface A { } +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface B { int value(); } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/MethodTypeParameters.java b/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/MethodTypeParameters.java new file mode 100644 index 00000000000..4363af11364 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/MethodTypeParameters.java @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2008, 2013, 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. + * + * 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. + */ + +import java.lang.annotation.*; + +/* + * @test + * @bug 6843077 8006775 + * @summary new type annotation location: method type parameter bounds + * @author Mahmood Ali + * @compile MethodTypeParameters.java + */ + +class UnscopedUnmodified { + void methodExtends() {} + > void nestedExtends() {} + > void dual() {} + > void dualOneAnno() {} +} + +class PublicModifiedMethods { + public final void methodExtends() {} + public final > void nestedExtends() {} + public final > void dual() {} + public final > void dualOneAnno() {} +} + +class Parameterized { } + +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface A { } +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface B { } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/MultiCatch.java b/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/MultiCatch.java new file mode 100644 index 00000000000..1745e61ae6b --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/MultiCatch.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2008, 2013, 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. + * + * 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. + */ + +import java.lang.annotation.*; + +/* + * @test + * @ignore // syntax not sure yet. + * @bug 8006775 + * @summary new type annotation location: multicatch + * @author Werner Dietl + * @compile MultiCatch.java + */ + +class DefaultScope { + void exception01() { + try { + System.out.println("Hello 1!"); + } catch (@B NullPointerException | @C IllegalArgumentException e) { + e.toString(); + } + } + void exception02() { + try { + System.out.println("Hello 2!"); + } catch @A (@B NullPointerException | @C IllegalArgumentException e) { + e.toString(); + } + } +} + +class ModifiedVars { + /* + void exception() { + try { + arrays(); + } catch (final @A Exception e) { + e.toString(); + } + } + */ +} + +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface A { } +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface B { } +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface C { } +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface D { } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/NestedTypes.java b/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/NestedTypes.java new file mode 100644 index 00000000000..7572b4fefb2 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/NestedTypes.java @@ -0,0 +1,212 @@ +/* + * Copyright (c) 2008, 2013, 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. + * + * 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. + */ + +import java.lang.annotation.*; +import java.util.Map; + +/* + * @test + * @bug 8006775 + * @summary new type annotation location: nested types + * @author Werner Dietl + * @compile NestedTypes.java + */ +class Outer { + class Inner { + class Inner2 { + // m1a-c all have the same parameter type. + void m1a(@A Inner2 p1a) {} + void m1b(Inner.@A Inner2 p1b) {} + void m1c(Outer.Inner.@A Inner2 p1c) {} + // notice the difference to m1d + void m1d(@A Outer.Inner.Inner2 p1d) {} + + // m2a-b both have the same parameter type. + void m2a(@A Inner.Inner2 p2a) {} + void m2b(Outer.@A Inner.Inner2 p2b) {} + + // The location for @A is the same in m3a-c + void m3a(@A Outer p3a) {} + void m3b(@A Outer.Inner p3b) {} + void m3c(@A Outer.Inner.Inner2 p3c) {} + + // Test combinations + void m4a(@A Outer p3a) {} + void m4b(@A Outer. @B Inner p3b) {} + void m4c(@A Outer. @B Inner. @C Inner2 p3c) {} + } + } + + void m4a(@A Map p4a) {} + void m4b(Map.@B Entry p4c) {} + // Illegal: + // void m4b(@A Map.Entry p4b) {} + // void m4c(@A Map.@B Entry p4c) {} + + void m4c(Map.@B Entry p4d) {} + // Illegal: + // void m4d(@A Map.@B Entry p4d) {} + + void m4e(MyList p4e) {} + void m4f(MyList p4f) {} + // Illegal: + // void m4g(MyList<@A Map.Entry> p4e) {} + // void m4h(MyList<@A Map.@B Entry> p4f) {} + + class GInner { + class GInner2 {} + } + + static class Static {} + static class GStatic { + static class GStatic2 {} + } +} + +class Test1 { + // Outer.GStatic.GStatic2 gs; + Outer.GStatic.@A GStatic2 gsgood; + // TODO: add failing test + // Outer.@A GStatic.GStatic2 gsbad; + + MyList<@A Outer . @B Inner. @C Inner2> f; + @A Outer .GInner.GInner2 g; + + // TODO: Make sure that something like this fails gracefully: + // MyList pkg; + + @A Outer f1; + @A Outer . @B Inner f2 = f1.new @B Inner(); + // TODO: ensure type annos on new are stored. + @A Outer . @B GInner<@C Object> f3 = f1.new @B GInner<@C Object>(); + + MyList<@A Outer . @B GInner<@C MyList<@D Object>>. @E GInner2<@F Integer, @G Object>> f4; + // MyList.GInner2> f4clean; + + @A Outer . @B GInner<@C MyList<@D Object>>. @E GInner2<@F Integer, @G Object> f4top; + + MyList<@A Outer . @B GInner<@C MyList<@D Object @E[] @F[]>>. @G GInner2<@H Integer, @I Object> @J[] @K[]> f4arr; + + @A Outer . @B GInner<@C MyList<@D Object @E[] @F[]>>. @G GInner2<@H Integer, @I Object> @J[] @K[] f4arrtop; + + MyList f5; + // Illegal: + // MyList<@A Outer . @B Static> f5; + + Outer . @B Static f6; + // Illegal: + // @A Outer . @B Static f6; + + Outer . @Bv("B") GStatic<@Cv("C") String, @Dv("D") Object> f7; + // Illegal: + // @Av("A") Outer . @Bv("B") GStatic<@Cv("C") String, @Dv("D") Object> f7; + + Outer . @Cv("Data") Static f8; + // Illegal: + // @A Outer . @Cv("Data") Static f8; + + MyList f9; + // Illegal: + // MyList<@A Outer . @Cv("Data") Static> f9; +} + +class Test2 { + void m() { + @A Outer f1 = null; + @A Outer.@B Inner f2 = null; + Outer.@B Static f3 = null; + // Illegal: + // @A Outer.@B Static f3 = null; + @A Outer.@C Inner f4 = null; + + Outer . @B Static f5 = null; + Outer . @Cv("Data") Static f6 = null; + MyList f7 = null; + } +} + +class Test3 { + void monster(@A Outer p1, + @A Outer.@B Inner p2, + Outer.@B Static p3, + @A Outer.@Cv("Test") Inner p4, + Outer . @B Static p5, + Outer . @Cv("Data") Static p6, + MyList p7) { + } +} + +class Test4 { + void m() { + @A Outer p1 = new @A Outer(); + @A Outer.@B Inner p2 = p1.new @B Inner(); + // Illegal: + // @A Outer.@B Static p3 = new @A Outer.@B Static(); + // Object o3 = new @A Outer.@B Static(); + + @A Outer.@Cv("Test") Inner p4 = p1.new @Cv("Test") Inner(); + Outer . @B Static p5 = new Outer . @B Static(); + Outer . @Cv("Data") Static p6 = new Outer . @Cv("Data") Static(); + MyList p7 = new MyList(); + } +} + +class MyList { } + + +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface A { } +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface B { } +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface C { } +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface D { } +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface E { } +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface F { } +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface G { } +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface H { } +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface I { } +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface J { } +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface K { } + +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface Av { String value(); } +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface Bv { String value(); } +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface Cv { String value(); } +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface Dv { String value(); } +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface Ev { String value(); } +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface Fv { String value(); } + diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/Parameters.java b/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/Parameters.java new file mode 100644 index 00000000000..4952986d347 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/Parameters.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2008, 2013, 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. + * + * 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. + */ + +import java.lang.annotation.*; + +/* + * @test + * @bug 6843077 8006775 + * @summary new type annotation location: parameter type array/generics + * @author Mahmood Ali + * @compile Parameters.java + */ + +class Parameters { + void unannotated(Parameterized a) {} + void firstTypeArg(Parameterized<@A String, String> a) {} + void secondTypeArg(Parameterized a) {} + void bothTypeArgs(Parameterized<@A String, @B String> both) {} + + void nestedParameterized(Parameterized<@A Parameterized<@A String, @B String>, @B String> a) {} + + void array1(@A String [] a) {} + void array1Deep(@A String @B [] a) {} + void array2(@A String [] [] a) {} + void array2Deep(@A String @A [] @B [] a) {} + void array2First(String @A [] [] a) {} + void array2Second(String [] @B [] a) {} +} + +class Parameterized { } + +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface A { } +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface B { } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/Receivers.java b/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/Receivers.java new file mode 100644 index 00000000000..95103ff1670 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/Receivers.java @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2008, 2013, 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. + * + * 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. + */ + +import java.lang.annotation.*; + +/* + * @test + * @bug 6843077 8006775 + * @summary new type annotation location: receivers + * @author Mahmood Ali, Werner Dietl + * @compile Receivers.java + */ +class DefaultUnmodified { + void plain(@A DefaultUnmodified this) { } + void generic(@A DefaultUnmodified this) { } + void withException(@A DefaultUnmodified this) throws Exception { } + String nonVoid(@A DefaultUnmodified this) { return null; } + void accept(@A DefaultUnmodified this, T r) throws Exception { } +} + +class PublicModified { + public final void plain(@A PublicModified this) { } + public final void generic(@A PublicModified this) { } + public final void withException(@A PublicModified this) throws Exception { } + public final String nonVoid(@A PublicModified this) { return null; } + public final void accept(@A PublicModified this, T r) throws Exception { } +} + +class WithValue { + void plain(@B("m") WithValue this) { } + void generic(@B("m") WithValue this) { } + void withException(@B("m") WithValue this) throws Exception { } + String nonVoid(@B("m") WithValue this) { return null; } + void accept(@B("m") WithValue this, T r) throws Exception { } +} + +class WithFinal { + void plain(final @B("m") WithFinal this) { } + void generic(final @B("m") WithFinal this) { } + void withException(final @B("m") WithFinal this) throws Exception { } + String nonVoid(final @B("m") WithFinal this) { return null; } + void accept(final @B("m") WithFinal this, T r) throws Exception { } +} + +class WithBody { + Object f; + + void field(@A WithBody this) { + this.f = null; + } + void meth(@A WithBody this) { + this.toString(); + } +} + +class Generic1 { + void test1(Generic1 this) {} + void test2(@A Generic1 this) {} + void test3(Generic1<@A X> this) {} + void test4(@A Generic1<@A X> this) {} +} + +class Generic2<@A X> { + void test1(Generic2 this) {} + void test2(@A Generic2 this) {} + void test3(Generic2<@A X> this) {} + void test4(@A Generic2<@A X> this) {} +} + +class Generic3 { + void test1(Generic3 this) {} + void test2(@A Generic3 this) {} + void test3(Generic3<@A X> this) {} + void test4(@A Generic3<@A X> this) {} +} + +class Generic4 { + void test1(Generic4 this) {} + void test2(@A Generic4 this) {} + void test3(Generic4<@A X> this) {} + void test4(@A Generic4<@A X> this) {} +} + +class Outer { + class Inner { + void none(Outer.Inner this) {} + void outer(@A Outer.Inner this) {} + void inner(Outer. @B("i") Inner this) {} + void both(@A Outer.@B("i") Inner this) {} + + void innerOnlyNone(Inner this) {} + void innerOnly(@A Inner this) {} + } +} + +class GenericOuter { + class GenericInner { + void none(GenericOuter.GenericInner this) {} + void outer(@A GenericOuter.GenericInner this) {} + void inner(GenericOuter. @B("i") GenericInner this) {} + void both(@A GenericOuter.@B("i") GenericInner this) {} + + void innerOnlyNone(GenericInner this) {} + void innerOnly(@A GenericInner this) {} + } +} + +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface A {} +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface B { String value(); } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/RepeatingTypeAnnotations.java b/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/RepeatingTypeAnnotations.java new file mode 100644 index 00000000000..db227cb56f6 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/RepeatingTypeAnnotations.java @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2012, 2013, 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. + * + * 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. + */ + +import java.lang.annotation.*; + +/* + * @test + * @bug 8006775 + * @summary repeating type annotations are possible + * @author Werner Dietl + * @compile/fail/ref=RepeatingTypeAnnotations.out -XDrawDiagnostics RepeatingTypeAnnotations.java + */ + +class RepeatingTypeAnnotations { + // Fields + @RTA @RTA Object fr1 = null; + Object fr2 = new @RTA @RTA Object(); + // error + Object fs = new @TA @TA Object(); + // error + Object ft = new @TA @TA Object(); + Object fe = new @TA @TA Object(); + + // Local variables + Object foo() { + Object o = new @RTA @RTA Object(); + o = new @TA @RTA @RTA Object(); + o = new @RTA @TA @RTA Object(); + // error + o = new @RTA @TA @RTA @TA Object(); + // error + return new @TA @TA Object(); + } + + // Instance creation + Object bar() { + Object o = new @RTA @RTA MyList<@RTA @RTA Object>(); + o = new @TA @RTA MyList<@TA @RTA Object>(); + o = new @TA @RTA @RTA MyList<@RTA @TA @RTA Object>(); + // error + o = new @TA @TA MyList<@RTA @RTA Object>(); + // error + o = new @RTA @RTA MyList<@TA @TA Object>(); + // error + return new @TA @TA MyList<@RTA @RTA Object>(); + } + + // More tests + void oneArg() { + Object o = new @RTA @RTA Object(); + // error + o = new @TA @TA Object(); + o = new @RTA @TA @RTA Object(); + + o = new MyList<@RTA @RTA Object>(); + // error + o = new MyList<@TA @TA Object>(); + // error + o = new @TA @TA MyList<@TA @TA Object>(); + // error + this.<@TA @TA String>newList(); + + this.<@RTA @RTA MyList<@RTA @RTA String>>newList(); + // error + this.<@TA @TA MyList<@TA @TA String>>newList(); + + o = (@RTA @RTA MyList<@RTA @RTA Object>) o; + // error + o = (@TA @TA MyList<@TA @TA Object>) o; + + this.<@RTA @RTA String, @RTA @RTA Object>newMap(); + // error + this.<@TA @TA String, @TA @TA Object>newMap(); + + this.<@RTA @RTA String @RTA @RTA []>newList(); + // error + this.<@TA @TA String @TA @TA []>newList(); + + this.<@RTA @RTA String @RTA @RTA [] @RTA @RTA [], MyList<@RTA @RTA String> @RTA @RTA []>newMap(); + // error + this. @TA @TA []>newMap(); + } + + static void newList() { } + static void newMap() { } +} + +class MyList { } + + +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface TA { } + +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface TAs { + TA[] value(); +} + +@Repeatable(RTAs.class) +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface RTA { } + +@ContainerFor(RTA.class) +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface RTAs { + RTA[] value(); +} diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/RepeatingTypeAnnotations.out b/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/RepeatingTypeAnnotations.out new file mode 100644 index 00000000000..4866c6ef697 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/RepeatingTypeAnnotations.out @@ -0,0 +1,53 @@ +RepeatingTypeAnnotations.java:39:21: compiler.err.duplicate.annotation.missing.container: TA, java.lang.annotation.Repeatable +RepeatingTypeAnnotations.java:39:25: compiler.err.duplicate.annotation.missing.container: TA, java.lang.annotation.Repeatable +RepeatingTypeAnnotations.java:41:21: compiler.err.duplicate.annotation.missing.container: TA, java.lang.annotation.Repeatable +RepeatingTypeAnnotations.java:41:25: compiler.err.duplicate.annotation.missing.container: TA, java.lang.annotation.Repeatable +RepeatingTypeAnnotations.java:42:21: compiler.err.duplicate.annotation.missing.container: TA, java.lang.annotation.Repeatable +RepeatingTypeAnnotations.java:42:25: compiler.err.duplicate.annotation.missing.container: TA, java.lang.annotation.Repeatable +RepeatingTypeAnnotations.java:50:22: compiler.err.duplicate.annotation.missing.container: TA, java.lang.annotation.Repeatable +RepeatingTypeAnnotations.java:50:31: compiler.err.duplicate.annotation.missing.container: TA, java.lang.annotation.Repeatable +RepeatingTypeAnnotations.java:52:20: compiler.err.duplicate.annotation.missing.container: TA, java.lang.annotation.Repeatable +RepeatingTypeAnnotations.java:52:24: compiler.err.duplicate.annotation.missing.container: TA, java.lang.annotation.Repeatable +RepeatingTypeAnnotations.java:61:17: compiler.err.duplicate.annotation.missing.container: TA, java.lang.annotation.Repeatable +RepeatingTypeAnnotations.java:61:21: compiler.err.duplicate.annotation.missing.container: TA, java.lang.annotation.Repeatable +RepeatingTypeAnnotations.java:63:34: compiler.err.duplicate.annotation.missing.container: TA, java.lang.annotation.Repeatable +RepeatingTypeAnnotations.java:63:38: compiler.err.duplicate.annotation.missing.container: TA, java.lang.annotation.Repeatable +RepeatingTypeAnnotations.java:65:20: compiler.err.duplicate.annotation.missing.container: TA, java.lang.annotation.Repeatable +RepeatingTypeAnnotations.java:65:24: compiler.err.duplicate.annotation.missing.container: TA, java.lang.annotation.Repeatable +RepeatingTypeAnnotations.java:72:17: compiler.err.duplicate.annotation.missing.container: TA, java.lang.annotation.Repeatable +RepeatingTypeAnnotations.java:72:21: compiler.err.duplicate.annotation.missing.container: TA, java.lang.annotation.Repeatable +RepeatingTypeAnnotations.java:77:24: compiler.err.duplicate.annotation.missing.container: TA, java.lang.annotation.Repeatable +RepeatingTypeAnnotations.java:77:28: compiler.err.duplicate.annotation.missing.container: TA, java.lang.annotation.Repeatable +RepeatingTypeAnnotations.java:79:17: compiler.err.duplicate.annotation.missing.container: TA, java.lang.annotation.Repeatable +RepeatingTypeAnnotations.java:79:21: compiler.err.duplicate.annotation.missing.container: TA, java.lang.annotation.Repeatable +RepeatingTypeAnnotations.java:79:32: compiler.err.duplicate.annotation.missing.container: TA, java.lang.annotation.Repeatable +RepeatingTypeAnnotations.java:79:36: compiler.err.duplicate.annotation.missing.container: TA, java.lang.annotation.Repeatable +RepeatingTypeAnnotations.java:81:15: compiler.err.duplicate.annotation.missing.container: TA, java.lang.annotation.Repeatable +RepeatingTypeAnnotations.java:81:19: compiler.err.duplicate.annotation.missing.container: TA, java.lang.annotation.Repeatable +RepeatingTypeAnnotations.java:85:15: compiler.err.duplicate.annotation.missing.container: TA, java.lang.annotation.Repeatable +RepeatingTypeAnnotations.java:85:19: compiler.err.duplicate.annotation.missing.container: TA, java.lang.annotation.Repeatable +RepeatingTypeAnnotations.java:85:30: compiler.err.duplicate.annotation.missing.container: TA, java.lang.annotation.Repeatable +RepeatingTypeAnnotations.java:85:34: compiler.err.duplicate.annotation.missing.container: TA, java.lang.annotation.Repeatable +RepeatingTypeAnnotations.java:89:14: compiler.err.duplicate.annotation.missing.container: TA, java.lang.annotation.Repeatable +RepeatingTypeAnnotations.java:89:18: compiler.err.duplicate.annotation.missing.container: TA, java.lang.annotation.Repeatable +RepeatingTypeAnnotations.java:89:29: compiler.err.duplicate.annotation.missing.container: TA, java.lang.annotation.Repeatable +RepeatingTypeAnnotations.java:89:33: compiler.err.duplicate.annotation.missing.container: TA, java.lang.annotation.Repeatable +RepeatingTypeAnnotations.java:93:15: compiler.err.duplicate.annotation.missing.container: TA, java.lang.annotation.Repeatable +RepeatingTypeAnnotations.java:93:19: compiler.err.duplicate.annotation.missing.container: TA, java.lang.annotation.Repeatable +RepeatingTypeAnnotations.java:93:31: compiler.err.duplicate.annotation.missing.container: TA, java.lang.annotation.Repeatable +RepeatingTypeAnnotations.java:93:35: compiler.err.duplicate.annotation.missing.container: TA, java.lang.annotation.Repeatable +RepeatingTypeAnnotations.java:97:30: compiler.err.duplicate.annotation.missing.container: TA, java.lang.annotation.Repeatable +RepeatingTypeAnnotations.java:97:34: compiler.err.duplicate.annotation.missing.container: TA, java.lang.annotation.Repeatable +RepeatingTypeAnnotations.java:97:15: compiler.err.duplicate.annotation.missing.container: TA, java.lang.annotation.Repeatable +RepeatingTypeAnnotations.java:97:19: compiler.err.duplicate.annotation.missing.container: TA, java.lang.annotation.Repeatable +RepeatingTypeAnnotations.java:101:22: compiler.err.duplicate.annotation.missing.container: TA, java.lang.annotation.Repeatable +RepeatingTypeAnnotations.java:101:26: compiler.err.duplicate.annotation.missing.container: TA, java.lang.annotation.Repeatable +RepeatingTypeAnnotations.java:101:33: compiler.err.duplicate.annotation.missing.container: TA, java.lang.annotation.Repeatable +RepeatingTypeAnnotations.java:101:37: compiler.err.duplicate.annotation.missing.container: TA, java.lang.annotation.Repeatable +RepeatingTypeAnnotations.java:101:68: compiler.err.duplicate.annotation.missing.container: TA, java.lang.annotation.Repeatable +RepeatingTypeAnnotations.java:101:72: compiler.err.duplicate.annotation.missing.container: TA, java.lang.annotation.Repeatable +RepeatingTypeAnnotations.java:101:52: compiler.err.duplicate.annotation.missing.container: TA, java.lang.annotation.Repeatable +RepeatingTypeAnnotations.java:101:56: compiler.err.duplicate.annotation.missing.container: TA, java.lang.annotation.Repeatable +- compiler.note.unchecked.filename: RepeatingTypeAnnotations.java +- compiler.note.unchecked.recompile +50 errors \ No newline at end of file diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/ResourceVariables.java b/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/ResourceVariables.java new file mode 100644 index 00000000000..7482e043f51 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/ResourceVariables.java @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2013, 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. + * + * 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. + */ + +import java.lang.annotation.*; + +import java.io.*; + +/* + * @test + * @bug 6843077 8006775 + * @summary new type annotation location: resource variables + * @author Werner Dietl + * @compile ResourceVariables.java + */ + +class ResourceVariables { + void m() throws Exception { + try (@A InputStream is = new @B FileInputStream("xxx")) { + } + } +} + +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface A { } +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface B { } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/Throws.java b/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/Throws.java new file mode 100644 index 00000000000..147325a0214 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/Throws.java @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2008, 2013, 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. + * + * 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. + */ + +import java.lang.annotation.*; + +/* + * @test + * @bug 6843077 8006775 + * @summary new type annotation location: throw clauses + * @author Mahmood Ali + * @compile Throws.java + */ +class DefaultUnmodified { + void oneException() throws @A Exception {} + void twoExceptions() throws @A RuntimeException, @A Exception {} +} + +class PublicModified { + public final void oneException(String a) throws @A Exception {} + public final void twoExceptions(String a) throws @A RuntimeException, @A Exception {} +} + +class WithValue { + void oneException() throws @B("m") Exception {} + void twoExceptions() throws @B(value="m") RuntimeException, @A Exception {} +} + +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface A {} +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface B { String value(); } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/TopLevelBlocks.java b/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/TopLevelBlocks.java new file mode 100644 index 00000000000..ee2a6710ca6 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/TopLevelBlocks.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2012, 2013, 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. + * + * 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. + */ + +import java.lang.annotation.*; +import java.util.Map; + +/* + * @test + * @bug 8006775 + * @summary type annotation location: top level blocks + * @author Werner Dietl + * @compile TopLevelBlocks.java + */ + +class TopLevelBlocks { + static Object f; + + { + f = new @A Object(); + } + + static final Object sf; + + static { + sf = new @A Object(); + } +} + +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface A { } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/TypeCasts.java b/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/TypeCasts.java new file mode 100644 index 00000000000..c7508e25451 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/TypeCasts.java @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2008, 2013, 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. + * + * 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. + */ + +import java.lang.annotation.*; + +/* + * @test + * @bug 6843077 8006775 + * @summary new type annotation location: type casts + * @author Mahmood Ali + * @compile TypeCasts.java + */ +class TypeCasts { + void methodA() { + String s = (@A String) null; + Object o = (@A Class<@A String>) null; + } + + void methodB() { + String s = (@B("m") String) null; + Object o = (@B("m") Class<@B("m") String>) null; + } +} + +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface A { } +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface B { String value(); } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/TypeParameters.java b/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/TypeParameters.java new file mode 100644 index 00000000000..1e93ba54639 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/TypeParameters.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2008, 2013, 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. + * + * 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. + */ + +import java.lang.annotation.*; + +/* + * @test + * @bug 6843077 8006775 + * @summary new type annotation location: class and method type parameters + * @author Mahmood Ali + * @compile TypeParameters.java + */ + +class Unannotated { } +class OneAnnotated<@A K> { } +class TwoAnnotated<@A K, @A V> { } +class SecondAnnotated { } + +class TestMethods { + void unannotated() { } + <@A K> void oneAnnotated() { } + <@A K, @B("m") V> void twoAnnotated() { } + void secondAnnotated() { } +} + +class UnannotatedB { } +class OneAnnotatedB<@B("m") K> { } +class TwoAnnotatedB<@B("m") K, @B("m") V> { } +class SecondAnnotatedB { } + +class OneAnnotatedC<@C K> { } +class TwoAnnotatedC<@C K, @C V> { } +class SecondAnnotatedC { } + +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface A { } +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface B { String value(); } +@Target(ElementType.TYPE_USE) +@interface C { } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/Varargs.java b/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/Varargs.java new file mode 100644 index 00000000000..d28c108a6c6 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/Varargs.java @@ -0,0 +1,46 @@ + +/* + * Copyright (c) 2008 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. + * + * 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. + */ + +import java.lang.annotation.*; + +/* + * @test + * @summary test acceptance of varargs annotations + * @author Mahmood Ali + * @compile Varargs.java + */ + +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface A {} + +class Varargs { + + // Handle annotations on a varargs element type + void varargPlain(Object @A... objs) { + + } + + void varargGeneric(Class @A ... clz) { + } +} diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/Wildcards.java b/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/Wildcards.java new file mode 100644 index 00000000000..38de895a767 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/Wildcards.java @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2008, 2013, 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. + * + * 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. + */ + +import java.lang.annotation.*; + +/* + * @test + * @bug 6843077 8006775 + * @summary new type annotation location: wildcard bound + * @author Mahmood Ali + * @compile Wildcards.java + */ +class BoundTest { + void wcExtends(MyList l) { } + void wcSuper(MyList l) { } + + MyList returnWcExtends() { return null; } + MyList returnWcSuper() { return null; } + MyList> complex() { return null; } +} + +class BoundWithValue { + void wcExtends(MyList l) { } + void wcSuper(MyList l) { } + + MyList returnWcExtends() { return null; } + MyList returnWcSuper() { return null; } + MyList> complex() { return null; } +} + +class SelfTest { + void wcExtends(MyList<@A ?> l) { } + void wcSuper(MyList<@A ?> l) { } + + MyList<@A ?> returnWcExtends() { return null; } + MyList<@A ?> returnWcSuper() { return null; } + MyList<@A ? extends @A MyList<@B("m") ?>> complex() { return null; } +} + +class SelfWithValue { + void wcExtends(MyList<@B("m") ?> l) { } + void wcSuper(MyList<@B(value="m") ?> l) { } + + MyList<@B("m") ?> returnWcExtends() { return null; } + MyList<@B(value="m") ?> returnWcSuper() { return null; } + MyList<@B("m") ? extends MyList<@B("m") ? super String>> complex() { return null; } +} + +class MyList { } + +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface A { } +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface B { String value(); } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/packageanno/PackageProcessor.java b/langtools/test/tools/javac/annotations/typeAnnotations/packageanno/PackageProcessor.java new file mode 100644 index 00000000000..4f0d56522f9 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/packageanno/PackageProcessor.java @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2009 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. + * + * 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. + */ +import java.util.HashSet; +import java.util.Set; + +import javax.annotation.processing.*; +import javax.lang.model.SourceVersion; +import javax.lang.model.element.*; +import javax.lang.model.util.ElementFilter; + +import com.sun.source.util.JavacTask; +import com.sun.source.util.TaskEvent; +import com.sun.source.util.TaskListener; +import com.sun.source.util.TreePath; +import com.sun.tools.javac.main.JavaCompiler; +import com.sun.tools.javac.main.JavaCompiler.CompileState; +import com.sun.tools.javac.processing.JavacProcessingEnvironment; +import com.sun.tools.javac.util.Context; + +/* + * @test + * @summary test that package annotations are available to type processors. + * This class implements the functionality of a type processor, as previously + * embodied by the AbstractTypeProcessor class. + * + * @author Mahmood Ali + * @author Werner Dietl + * + * @compile PackageProcessor.java + * @compile -cp . -processor PackageProcessor mypackage/Anno.java mypackage/MyClass.java mypackage/package-info.java + */ + +@SupportedAnnotationTypes("*") +public class PackageProcessor extends AbstractProcessor { + + private final AttributionTaskListener listener = new AttributionTaskListener(); + private final Set elements = new HashSet(); + + @Override + public final void init(ProcessingEnvironment env) { + super.init(env); + JavacTask.instance(env).addTaskListener(listener); + Context ctx = ((JavacProcessingEnvironment)processingEnv).getContext(); + JavaCompiler compiler = JavaCompiler.instance(ctx); + compiler.shouldStopPolicyIfNoError = CompileState.max(compiler.shouldStopPolicyIfNoError, + CompileState.FLOW); + } + + @Override + public final boolean process(Set annotations, + RoundEnvironment roundEnv) { + for (TypeElement elem : ElementFilter.typesIn(roundEnv.getRootElements())) { + elements.add(elem.getQualifiedName()); + } + return false; + } + + @Override + public SourceVersion getSupportedSourceVersion() { + return SourceVersion.latest(); + } + + private final class AttributionTaskListener implements TaskListener { + @Override + public void started(TaskEvent e) { } + + @Override + public void finished(TaskEvent e) { + if (e.getKind() != TaskEvent.Kind.ANALYZE) + return; + + if (!elements.remove(e.getTypeElement().getQualifiedName())) + return; + + if (e.getTypeElement().getSimpleName().contentEquals("MyClass")) { + Element owner = e.getTypeElement().getEnclosingElement(); + if (owner.getKind() != ElementKind.PACKAGE) + throw new RuntimeException("class owner should be a package: " + owner); + if (owner.getAnnotationMirrors().size() != 1) + throw new RuntimeException("the owner package should have one annotation: " + owner); + } + } + } + +} diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/packageanno/mypackage/Anno.java b/langtools/test/tools/javac/annotations/typeAnnotations/packageanno/mypackage/Anno.java new file mode 100644 index 00000000000..25f05341fbc --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/packageanno/mypackage/Anno.java @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2009 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. + * + * 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. + */ +package mypackage; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Retention; + +@Retention(RetentionPolicy.RUNTIME) +public @interface Anno {} diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/packageanno/mypackage/MyClass.java b/langtools/test/tools/javac/annotations/typeAnnotations/packageanno/mypackage/MyClass.java new file mode 100644 index 00000000000..e955ffc825e --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/packageanno/mypackage/MyClass.java @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2009 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. + * + * 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. + */ +package mypackage; + +public class MyClass {} diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/packageanno/mypackage/package-info.java b/langtools/test/tools/javac/annotations/typeAnnotations/packageanno/mypackage/package-info.java new file mode 100644 index 00000000000..f80bd8afa53 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/packageanno/mypackage/package-info.java @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2009 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. + * + * 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. + */ + +@mypackage.Anno +package mypackage; diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/ClassExtends.java b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/ClassExtends.java new file mode 100644 index 00000000000..5fd9751879a --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/ClassExtends.java @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2009 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. + * + * 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. + */ + +import static com.sun.tools.classfile.TypeAnnotation.TargetType.*; + +/* + * @test + * @summary Test population of reference info for class extends clauses + * @compile -g Driver.java ReferenceInfoUtil.java ClassExtends.java + * @run main Driver ClassExtends + */ +public class ClassExtends { + + @TADescriptions({ + @TADescription(annotation = "TA", type = CLASS_EXTENDS, typeIndex = -1), + @TADescription(annotation = "TB", type = CLASS_EXTENDS, typeIndex = 1) + }) + public String regularClass() { + return "class Test extends @TA Object implements Cloneable, @TB Runnable {" + + " public void run() { } }"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = CLASS_EXTENDS, typeIndex = -1, + genericLocation = { 3, 0 }), + @TADescription(annotation = "TB", type = CLASS_EXTENDS, typeIndex = 1, + genericLocation = { 3, 1 }) + }) + public String regularClassExtendsParametrized() { + return "class Test extends HashMap<@TA String, String> implements Cloneable, Map{ } "; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = CLASS_EXTENDS, typeIndex = -1), + @TADescription(annotation = "TB", type = CLASS_EXTENDS, typeIndex = 1) + }) + public String abstractClass() { + return "abstract class Test extends @TA Date implements Cloneable, @TB Runnable {" + + " public void run() { } }"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = CLASS_EXTENDS, typeIndex = -1, + genericLocation = { 3, 0 }), + @TADescription(annotation = "TB", type = CLASS_EXTENDS, typeIndex = 1, + genericLocation = { 3, 1 }) + }) + public String abstractClassExtendsParametrized() { + return "abstract class Test extends HashMap<@TA String, String> implements Cloneable, Map{ } "; + } + + @TADescription(annotation = "TB", type = CLASS_EXTENDS, typeIndex = 1) + public String regularInterface() { + return "interface Test extends Cloneable, @TB Runnable { }"; + } + + @TADescription(annotation = "TB", type = CLASS_EXTENDS, typeIndex = 1, + genericLocation = { 3, 1 }) + public String regularInterfaceExtendsParametrized() { + return "interface Test extends Cloneable, Map{ } "; + } + + @TADescription(annotation = "TB", type = CLASS_EXTENDS, typeIndex = 1) + public String regularEnum() { + return "enum Test implements Cloneable, @TB Runnable { TEST; public void run() { } }"; + } + + @TADescription(annotation = "TB", type = CLASS_EXTENDS, typeIndex = 1, + genericLocation = { 3, 0 }) + public String regularEnumExtendsParametrized() { + return + "enum Test implements Cloneable, Comparator<@TB String> { TEST; " + + "public int compare(String a, String b) { return 0; }}"; + } + +} diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/ClassTypeParam.java b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/ClassTypeParam.java new file mode 100644 index 00000000000..0d82706984f --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/ClassTypeParam.java @@ -0,0 +1,158 @@ +/* + * Copyright (c) 2009 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. + * + * 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. + */ + +import static com.sun.tools.classfile.TypeAnnotation.TargetType.*; + +/* + * @test + * @summary Test population of reference info for class type parameters + * @compile -g Driver.java ReferenceInfoUtil.java ClassTypeParam.java + * @run main Driver ClassTypeParam + */ +public class ClassTypeParam { + + @TADescriptions({ + @TADescription(annotation = "TA", type = CLASS_TYPE_PARAMETER, paramIndex = 0), + @TADescription(annotation = "TB", type = CLASS_TYPE_PARAMETER_BOUND, paramIndex = 0, boundIndex = 0), + @TADescription(annotation = "TC", type = CLASS_TYPE_PARAMETER, paramIndex = 1), + @TADescription(annotation = "TD", type = CLASS_TYPE_PARAMETER_BOUND, paramIndex = 1, boundIndex = 0), + @TADescription(annotation = "TE", type = CLASS_TYPE_PARAMETER_BOUND, paramIndex = 1, boundIndex = 1) + }) + public String regularClass() { + return "class Test<@TA K extends @TB Date, @TC V extends @TD Object & @TE Cloneable> { }"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = CLASS_TYPE_PARAMETER, paramIndex = 0), + @TADescription(annotation = "TB", type = CLASS_TYPE_PARAMETER_BOUND, paramIndex = 0, boundIndex = 0), + @TADescription(annotation = "TC", type = CLASS_TYPE_PARAMETER, paramIndex = 1), + @TADescription(annotation = "TE", type = CLASS_TYPE_PARAMETER_BOUND, paramIndex = 1, boundIndex = 1) + }) + public String regularClass2() { + return "class Test<@TA K extends @TB Date, @TC V extends @TE Cloneable> { }"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = CLASS_TYPE_PARAMETER_BOUND, paramIndex = 0, boundIndex = 1), + @TADescription(annotation = "TB", type = CLASS_TYPE_PARAMETER_BOUND, paramIndex = 0, boundIndex = 1, genericLocation = {3, 1}), + @TADescription(annotation = "TC", type = CLASS_TYPE_PARAMETER_BOUND, paramIndex = 1, boundIndex = 1), + @TADescription(annotation = "TD", type = CLASS_TYPE_PARAMETER_BOUND, paramIndex = 1, boundIndex = 1, genericLocation = {3, 0}), + @TADescription(annotation = "TE", type = CLASS_TYPE_PARAMETER_BOUND, paramIndex = 1, boundIndex = 1, genericLocation = {3, 0, 3, 0}) + }) + public String regularClassParameterized() { + return "class Test, V extends @TC List<@TD List<@TE Object>>> { }"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = CLASS_TYPE_PARAMETER_BOUND, paramIndex = 0, boundIndex = 1), + @TADescription(annotation = "TB", type = CLASS_TYPE_PARAMETER_BOUND, paramIndex = 0, boundIndex = 1, genericLocation = {3, 1}), + @TADescription(annotation = "TC", type = CLASS_TYPE_PARAMETER_BOUND, paramIndex = 1, boundIndex = 1), + @TADescription(annotation = "TD", type = CLASS_TYPE_PARAMETER_BOUND, paramIndex = 1, boundIndex = 1, genericLocation = {3, 0}), + @TADescription(annotation = "TE", type = CLASS_TYPE_PARAMETER_BOUND, paramIndex = 1, boundIndex = 1, genericLocation = {3, 0, 3, 0}), + @TADescription(annotation = "TF", type = CLASS_TYPE_PARAMETER_BOUND, paramIndex = 1, boundIndex = 0), + @TADescription(annotation = "TG", type = CLASS_TYPE_PARAMETER_BOUND, paramIndex = 0, boundIndex = 0) + }) + public String regularClassParameterized2() { + return "class Test, V extends @TF Object & @TC List<@TD List<@TE Object>>> { }"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = CLASS_TYPE_PARAMETER, paramIndex = 0), + @TADescription(annotation = "TB", type = CLASS_TYPE_PARAMETER_BOUND, paramIndex = 0, boundIndex = 0), + @TADescription(annotation = "TC", type = CLASS_TYPE_PARAMETER, paramIndex = 1), + @TADescription(annotation = "TD", type = CLASS_TYPE_PARAMETER_BOUND, paramIndex = 1, boundIndex = 0), + @TADescription(annotation = "TE", type = CLASS_TYPE_PARAMETER_BOUND, paramIndex = 1, boundIndex = 1) + }) + public String abstractClass() { + return "abstract class Test<@TA K extends @TB Date, @TC V extends @TD Object & @TE Cloneable> { }"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = CLASS_TYPE_PARAMETER_BOUND, paramIndex = 0, boundIndex = 1), + @TADescription(annotation = "TB", type = CLASS_TYPE_PARAMETER_BOUND, paramIndex = 0, boundIndex = 1, genericLocation = {3, 1}), + @TADescription(annotation = "TC", type = CLASS_TYPE_PARAMETER_BOUND, paramIndex = 1, boundIndex = 1), + @TADescription(annotation = "TD", type = CLASS_TYPE_PARAMETER_BOUND, paramIndex = 1, boundIndex = 1, genericLocation = {3, 0}), + @TADescription(annotation = "TE", type = CLASS_TYPE_PARAMETER_BOUND, paramIndex = 1, boundIndex = 1, genericLocation = {3, 0, 3, 0}), + @TADescription(annotation = "TF", type = CLASS_TYPE_PARAMETER_BOUND, paramIndex = 1, boundIndex = 0) + }) + public String abstractClassParameterized() { + return "abstract class Test, V extends @TF Object & @TC List<@TD List<@TE Object>>> { }"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = CLASS_TYPE_PARAMETER, paramIndex = 0), + @TADescription(annotation = "TB", type = CLASS_TYPE_PARAMETER_BOUND, paramIndex = 0, boundIndex = 0), + @TADescription(annotation = "TC", type = CLASS_TYPE_PARAMETER, paramIndex = 1), + @TADescription(annotation = "TD", type = CLASS_TYPE_PARAMETER_BOUND, paramIndex = 1, boundIndex = 0), + @TADescription(annotation = "TE", type = CLASS_TYPE_PARAMETER_BOUND, paramIndex = 1, boundIndex = 1) + }) + public String regularInterface() { + return "interface Test<@TA K extends @TB Date, @TC V extends @TD Object & @TE Cloneable> { }"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = CLASS_TYPE_PARAMETER_BOUND, paramIndex = 0, boundIndex = 1), + @TADescription(annotation = "TB", type = CLASS_TYPE_PARAMETER_BOUND, paramIndex = 0, boundIndex = 1, genericLocation = {3, 1}), + @TADescription(annotation = "TC", type = CLASS_TYPE_PARAMETER_BOUND, paramIndex = 1, boundIndex = 1), + @TADescription(annotation = "TD", type = CLASS_TYPE_PARAMETER_BOUND, paramIndex = 1, boundIndex = 1, genericLocation = {3, 0}), + @TADescription(annotation = "TE", type = CLASS_TYPE_PARAMETER_BOUND, paramIndex = 1, boundIndex = 1, genericLocation = {3, 0, 3, 0}) + }) + public String regularInterfaceParameterized() { + return "interface Test, V extends @TC List<@TD List<@TE Object>>> { }"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = CLASS_TYPE_PARAMETER_BOUND, paramIndex = 0, boundIndex = 1), + @TADescription(annotation = "TB", type = CLASS_TYPE_PARAMETER_BOUND, paramIndex = 0, boundIndex = 1, genericLocation = {3, 1}), + @TADescription(annotation = "TC", type = CLASS_TYPE_PARAMETER_BOUND, paramIndex = 1, boundIndex = 1), + @TADescription(annotation = "TD", type = CLASS_TYPE_PARAMETER_BOUND, paramIndex = 1, boundIndex = 1, genericLocation = {3, 0}), + @TADescription(annotation = "TE", type = CLASS_TYPE_PARAMETER_BOUND, paramIndex = 1, boundIndex = 1, genericLocation = {3, 0, 3, 0}), + @TADescription(annotation = "TF", type = CLASS_TYPE_PARAMETER_BOUND, paramIndex = 1, boundIndex = 0), + @TADescription(annotation = "TG", type = CLASS_TYPE_PARAMETER_BOUND, paramIndex = 0, boundIndex = 0) + }) + public String regularInterfaceParameterized2() { + return "interface Test, V extends @TF Object & @TC List<@TD List<@TE Object>>> { }"; + } + + @TADescription(annotation = "TA", type = METHOD_RETURN) + public String useInReturn1() { + return "class Test { @TA T m() { throw new RuntimeException(); } }"; + } + + @TADescription(annotation = "TA", type = METHOD_RETURN, genericLocation = {3, 0}) + public String useInReturn2() { + return "class Test { Class<@TA T> m() { throw new RuntimeException(); } }"; + } + + @TADescription(annotation = "TA", type = METHOD_FORMAL_PARAMETER, + paramIndex = 0, genericLocation = {3, 0}) + public String useInParam1() { + return "class Test { void m(Class<@TA T> p) { throw new RuntimeException(); } }"; + } + + @TADescription(annotation = "TA", type = METHOD_FORMAL_PARAMETER, + paramIndex = 0, genericLocation = {3, 0}) + public String useInParam2() { + return "class Test { void m(Class<@TA Object> p) { throw new RuntimeException(); } }"; + } +} diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/Constructors.java b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/Constructors.java new file mode 100644 index 00000000000..2ad8b31badc --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/Constructors.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2012 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. + * + * 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. + */ + +import static com.sun.tools.classfile.TypeAnnotation.TargetType.*; + +/* + * @test + * @summary Test population of reference info for constructor results + * @compile -g Driver.java ReferenceInfoUtil.java Constructors.java + * @run main Driver Constructors + */ +public class Constructors { + + @TADescriptions({ + @TADescription(annotation = "TA", type = METHOD_RETURN), + @TADescription(annotation = "TB", type = METHOD_RETURN), + @TADescription(annotation = "TC", type = METHOD_FORMAL_PARAMETER, paramIndex = 0) + }) + public String regularClass() { + return "class Test { @TA Test() {}" + + " @TB Test(@TC int b) {} }"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = METHOD_RETURN), + @TADescription(annotation = "TB", type = METHOD_RETURN), + @TADescription(annotation = "TC", type = METHOD_FORMAL_PARAMETER, paramIndex = 0) + }) + @TestClass("Test$Inner") + public String innerClass() { + return "class Test { class Inner {" + + " @TA Inner() {}" + + " @TB Inner(@TC int b) {}" + + " } }"; + } + + /* TODO: Outer.this annotation support. + @TADescriptions({ + @TADescription(annotation = "TA", type = METHOD_RECEIVER), + @TADescription(annotation = "TB", type = METHOD_RETURN), + @TADescription(annotation = "TC", type = METHOD_RECEIVER), + @TADescription(annotation = "TD", type = METHOD_RETURN), + @TADescription(annotation = "TE", type = METHOD_FORMAL_PARAMETER, paramIndex = 0) + }) + @TestClass("Test$Inner") + public String innerClass2() { + return "class Test { class Inner {" + + " @TB Inner(@TA Test Test.this) {}" + + " @TD Inner(@TC Test Test.this, @TE int b) {}" + + " } }"; + } + */ +} diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/Driver.java b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/Driver.java new file mode 100644 index 00000000000..5986fa95de8 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/Driver.java @@ -0,0 +1,289 @@ +/* + * Copyright (c) 2009 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. + * + * 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. + */ + +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.io.PrintStream; +import java.io.PrintWriter; +import java.lang.annotation.*; +import java.lang.reflect.*; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import com.sun.tools.classfile.ClassFile; +import com.sun.tools.classfile.TypeAnnotation; +import com.sun.tools.classfile.TypeAnnotation.TargetType; + +public class Driver { + + private static final PrintStream out = System.out; + + public static void main(String[] args) throws Exception { + if (args.length == 0 || args.length > 1) + throw new IllegalArgumentException("Usage: java Driver "); + String name = args[0]; + Class clazz = Class.forName(name); + new Driver().runDriver(clazz.newInstance()); + } + + protected void runDriver(Object object) throws Exception { + int passed = 0, failed = 0; + Class clazz = object.getClass(); + out.println("Tests for " + clazz.getName()); + + // Find methods + for (Method method : clazz.getMethods()) { + Map expected = expectedOf(method); + if (expected == null) + continue; + if (method.getReturnType() != String.class) + throw new IllegalArgumentException("Test method needs to return a string: " + method); + String testClass = testClassOf(method); + + try { + String compact = (String)method.invoke(object); + String fullFile = wrap(compact); + ClassFile cf = compileAndReturn(fullFile, testClass); + List actual = ReferenceInfoUtil.extendedAnnotationsOf(cf); + ReferenceInfoUtil.compare(expected, actual, cf); + out.println("PASSED: " + method.getName()); + ++passed; + } catch (Throwable e) { + out.println("FAILED: " + method.getName()); + out.println(" " + e.toString()); + ++failed; + } + } + + out.println(); + int total = passed + failed; + out.println(total + " total tests: " + passed + " PASSED, " + failed + " FAILED"); + + out.flush(); + + if (failed != 0) + throw new RuntimeException(failed + " tests failed"); + } + + private Map expectedOf(Method m) { + TADescription ta = m.getAnnotation(TADescription.class); + TADescriptions tas = m.getAnnotation(TADescriptions.class); + + if (ta == null && tas == null) + return null; + + Map result = + new HashMap(); + + if (ta != null) + result.putAll(expectedOf(ta)); + + if (tas != null) { + for (TADescription a : tas.value()) { + result.putAll(expectedOf(a)); + } + } + + return result; + } + + private Map expectedOf(TADescription d) { + String annoName = d.annotation(); + + TypeAnnotation.Position p = new TypeAnnotation.Position(); + p.type = d.type(); + if (d.offset() != NOT_SET) + p.offset = d.offset(); + if (d.lvarOffset().length != 0) + p.lvarOffset = d.lvarOffset(); + if (d.lvarLength().length != 0) + p.lvarLength = d.lvarLength(); + if (d.lvarIndex().length != 0) + p.lvarIndex = d.lvarIndex(); + if (d.boundIndex() != NOT_SET) + p.bound_index = d.boundIndex(); + if (d.paramIndex() != NOT_SET) + p.parameter_index = d.paramIndex(); + if (d.typeIndex() != NOT_SET) + p.type_index = d.typeIndex(); + if (d.exceptionIndex() != NOT_SET) + p.exception_index = d.exceptionIndex(); + if (d.genericLocation().length != 0) { + p.location = TypeAnnotation.Position.getTypePathFromBinary(wrapIntArray(d.genericLocation())); + } + + return Collections.singletonMap(annoName, p); + } + + private List wrapIntArray(int[] ints) { + List list = new ArrayList(ints.length); + for (int i : ints) + list.add(i); + return list; + } + + private String testClassOf(Method m) { + TestClass tc = m.getAnnotation(TestClass.class); + if (tc != null) { + return tc.value(); + } else { + return "Test"; + } + } + + private ClassFile compileAndReturn(String fullFile, String testClass) throws Exception { + File source = writeTestFile(fullFile); + File clazzFile = compileTestFile(source, testClass); + return ClassFile.read(clazzFile); + } + + protected File writeTestFile(String fullFile) throws IOException { + File f = new File("Test.java"); + PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(f))); + out.println(fullFile); + out.close(); + return f; + } + + protected File compileTestFile(File f, String testClass) { + int rc = com.sun.tools.javac.Main.compile(new String[] { "-source", "1.8", "-g", f.getPath() }); + if (rc != 0) + throw new Error("compilation failed. rc=" + rc); + String path; + if (f.getParent() != null) { + path = f.getParent(); + } else { + path = ""; + } + + return new File(path + testClass + ".class"); + } + + private String wrap(String compact) { + StringBuilder sb = new StringBuilder(); + + // Automatically import java.util + sb.append("\nimport java.util.*;"); + sb.append("\nimport java.lang.annotation.*;"); + + sb.append("\n\n"); + boolean isSnippet = !(compact.startsWith("class") + || compact.contains(" class")) + && !compact.contains("interface") + && !compact.contains("enum"); + if (isSnippet) + sb.append("class Test {\n"); + + sb.append(compact); + sb.append("\n"); + + if (isSnippet) + sb.append("}\n\n"); + + if (isSnippet) { + // Have a few common nested types for testing + sb.append("class Outer { class Inner {} }"); + sb.append("class SOuter { static class SInner {} }"); + sb.append("class GOuter { class GInner {} }"); + } + + // create A ... F annotation declarations + sb.append("\n@interface A {}"); + sb.append("\n@interface B {}"); + sb.append("\n@interface C {}"); + sb.append("\n@interface D {}"); + sb.append("\n@interface E {}"); + sb.append("\n@interface F {}"); + + // create TA ... TF proper type annotations + sb.append("\n"); + sb.append("\n@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) @interface TA {}"); + sb.append("\n@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) @interface TB {}"); + sb.append("\n@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) @interface TC {}"); + sb.append("\n@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) @interface TD {}"); + sb.append("\n@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) @interface TE {}"); + sb.append("\n@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) @interface TF {}"); + sb.append("\n@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) @interface TG {}"); + sb.append("\n@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) @interface TH {}"); + sb.append("\n@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) @interface TI {}"); + sb.append("\n@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) @interface TJ {}"); + sb.append("\n@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) @interface TK {}"); + sb.append("\n@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) @interface TL {}"); + sb.append("\n@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) @interface TM {}"); + + // create RTA, RTAs, RTB, RTBs for repeating type annotations + sb.append("\n"); + sb.append("\n@Repeatable(RTAs.class) @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) @interface RTA {}"); + sb.append("\n@Repeatable(RTBs.class) @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) @interface RTB {}"); + + sb.append("\n@ContainerFor(RTA.class) @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) @interface RTAs { RTA[] value(); }"); + sb.append("\n@ContainerFor(RTB.class) @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) @interface RTBs { RTB[] value(); }"); + + sb.append("\n@Target(value={ElementType.TYPE,ElementType.FIELD,ElementType.METHOD,ElementType.PARAMETER,ElementType.CONSTRUCTOR,ElementType.LOCAL_VARIABLE})"); + sb.append("\n@interface Decl {}"); + + return sb.toString(); + } + + public static final int NOT_SET = -888; + +} + +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.METHOD) +@interface TADescription { + String annotation(); + + TargetType type(); + int offset() default Driver.NOT_SET; + int[] lvarOffset() default { }; + int[] lvarLength() default { }; + int[] lvarIndex() default { }; + int boundIndex() default Driver.NOT_SET; + int paramIndex() default Driver.NOT_SET; + int typeIndex() default Driver.NOT_SET; + int exceptionIndex() default Driver.NOT_SET; + + int[] genericLocation() default {}; +} + +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.METHOD) +@interface TADescriptions { + TADescription[] value() default {}; +} + +/** + * The name of the class that should be analyzed. + * Should only need to be provided when analyzing inner classes. + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.METHOD) +@interface TestClass { + String value() default "Test"; +} diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/ExceptionParameters.java b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/ExceptionParameters.java new file mode 100644 index 00000000000..70ca77aa560 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/ExceptionParameters.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2013 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. + * + * 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. + */ + +import static com.sun.tools.classfile.TypeAnnotation.TargetType.*; + +/* + * @test + * @summary Test population of reference info for exception parameters + * @author Werner Dietl + * @compile -g Driver.java ReferenceInfoUtil.java ExceptionParameters.java + * @run main Driver ExceptionParameters + */ +public class ExceptionParameters { + + @TADescription(annotation = "TA", type = EXCEPTION_PARAMETER, exceptionIndex = 0) + public String exception() { + return "void exception() { try { new Object(); } catch(@TA Exception e) { } }"; + } + + @TADescription(annotation = "TA", type = EXCEPTION_PARAMETER, exceptionIndex = 0) + public String finalException() { + return "void finalException() { try { new Object(); } catch(final @TA Exception e) { } }"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = EXCEPTION_PARAMETER, exceptionIndex = 0), + @TADescription(annotation = "TB", type = EXCEPTION_PARAMETER, exceptionIndex = 1), + @TADescription(annotation = "TC", type = EXCEPTION_PARAMETER, exceptionIndex = 2) + }) + public String multipleExceptions() { + return "void multipleExceptions() { " + + "try { new Object(); } catch(@TA Exception e) { }" + + "try { new Object(); } catch(@TB Exception e) { }" + + "try { new Object(); } catch(@TC Exception e) { }" + + " }"; + } +} diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/Fields.java b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/Fields.java new file mode 100644 index 00000000000..d352fa79b23 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/Fields.java @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2009 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. + * + * 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. + */ + +import static com.sun.tools.classfile.TypeAnnotation.TargetType.*; + +/* + * @test + * @summary Test population of reference info for field + * @compile -g Driver.java ReferenceInfoUtil.java Fields.java + * @run main Driver Fields + */ +public class Fields { + + // field types + @TADescription(annotation = "TA", type = FIELD) + public String fieldAsPrimitive() { + return "@TA int test;"; + } + + @TADescription(annotation = "TA", type = FIELD) + public String fieldAsObject() { + return "@TA Object test;"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = FIELD), + @TADescription(annotation = "TB", type = FIELD, + genericLocation = { 3, 0 }), + @TADescription(annotation = "TC", type = FIELD, + genericLocation = { 3, 1 }), + @TADescription(annotation = "TD", type = FIELD, + genericLocation = { 3, 1, 3, 0 }) + }) + public String fieldAsParametrized() { + return "@TA Map<@TB String, @TC List<@TD String>> test;"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = FIELD), + @TADescription(annotation = "TB", type = FIELD, + genericLocation = { 0, 0 }), + @TADescription(annotation = "TC", type = FIELD, + genericLocation = { 0, 0, 0, 0 }) + }) + public String fieldAsArray() { + return "@TC String @TA [] @TB [] test;"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = FIELD), + @TADescription(annotation = "TB", type = FIELD, + genericLocation = { 0, 0 }), + @TADescription(annotation = "TC", type = FIELD, + genericLocation = { 0, 0, 0, 0 }) + }) + public String fieldAsArrayOld() { + return "@TC String test @TA [] @TB [];"; + } + + @TADescriptions({}) + public String fieldWithDeclarationAnnotatin() { + return "@Decl String test;"; + } + + @TADescriptions({}) + public String fieldWithNoTargetAnno() { + return "@A String test;"; + } + + // Smoke tests + @TADescription(annotation = "TA", type = FIELD) + public String interfacefieldAsObject() { + return "interface Test { @TA String test = null; }"; + } + + @TADescription(annotation = "TA", type = FIELD) + public String abstractfieldAsObject() { + return "abstract class Test { @TA String test; }"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = FIELD), + @TADescription(annotation = "TB", type = FIELD, + genericLocation = { 3, 0 }), + @TADescription(annotation = "TC", type = FIELD, + genericLocation = { 3, 1 }), + @TADescription(annotation = "TD", type = FIELD, + genericLocation = { 3, 1, 3, 0 }) + }) + public String interfacefieldAsParametrized() { + return "interface Test { @TA Map<@TB String, @TC List<@TD String>> test = null; }"; + } + + + @TADescriptions({ + @TADescription(annotation = "TA", type = FIELD), + @TADescription(annotation = "TB", type = FIELD, + genericLocation = { 3, 0 }), + @TADescription(annotation = "TC", type = FIELD, + genericLocation = { 3, 1 }), + @TADescription(annotation = "TD", type = FIELD, + genericLocation = { 3, 1, 3, 0 }) + }) + public String staticFieldAsParametrized() { + return "static @TA Map<@TB String, @TC List<@TD String>> test;"; + } + +} diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/FromSpecification.java b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/FromSpecification.java new file mode 100644 index 00000000000..e8e111d8c30 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/FromSpecification.java @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2012 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. + * + * 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. + */ + +import static com.sun.tools.classfile.TypeAnnotation.TargetType.*; + +/* + * @test + * @summary Test that the examples from the manual are stored as expected + * @compile -g Driver.java ReferenceInfoUtil.java FromSpecification.java + * @run main Driver FromSpecification + */ +public class FromSpecification { + + @TADescriptions({ + @TADescription(annotation = "TA", type = METHOD_FORMAL_PARAMETER, paramIndex = 0), + @TADescription(annotation = "TB", type = METHOD_FORMAL_PARAMETER, + genericLocation = {3, 0}, paramIndex = 0), + @TADescription(annotation = "TC", type = METHOD_FORMAL_PARAMETER, + genericLocation = {3, 0, 2, 0}, paramIndex = 0), + @TADescription(annotation = "TD", type = METHOD_FORMAL_PARAMETER, + genericLocation = {3, 1}, paramIndex = 0), + @TADescription(annotation = "TE", type = METHOD_FORMAL_PARAMETER, + genericLocation = {3, 1, 3, 0}, paramIndex = 0) + }) + public String testSpec1() { + return "void test(@TA Map<@TB ? extends @TC String, @TD List<@TE Object>> a) { }"; + } + + @TADescriptions({ + @TADescription(annotation = "TF", type = METHOD_FORMAL_PARAMETER, paramIndex = 0), + @TADescription(annotation = "TG", type = METHOD_FORMAL_PARAMETER, + genericLocation = {0, 0}, paramIndex = 0), + @TADescription(annotation = "TH", type = METHOD_FORMAL_PARAMETER, + genericLocation = {0, 0, 0, 0}, paramIndex = 0), + @TADescription(annotation = "TI", type = METHOD_FORMAL_PARAMETER, + genericLocation = {0, 0, 0, 0, 0, 0}, paramIndex = 0) + }) + public String testSpec2() { + return "void test(@TI String @TF [] @TG [] @TH [] a) { }"; + } + + // Note first "1, 0" for top-level class Test. + @TADescriptions({ + @TADescription(annotation = "TJ", type = METHOD_FORMAL_PARAMETER, + genericLocation = {1, 0, 1, 0, 1, 0, 1, 0}, paramIndex = 0), + @TADescription(annotation = "TK", type = METHOD_FORMAL_PARAMETER, + genericLocation = {1, 0, 1, 0, 1, 0}, paramIndex = 0), + @TADescription(annotation = "TL", type = METHOD_FORMAL_PARAMETER, + genericLocation = {1, 0, 1, 0}, paramIndex = 0), + @TADescription(annotation = "TM", type = METHOD_FORMAL_PARAMETER, + genericLocation = {1, 0}, paramIndex = 0) + }) + public String testSpec3() { + return "class Test { class O1 { class O2 { class O3 { class NestedStatic {} } } }" + + "void test(@TM O1.@TL O2.@TK O3.@TJ NestedStatic a) { } }"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = METHOD_FORMAL_PARAMETER, paramIndex = 0), + @TADescription(annotation = "TB", type = METHOD_FORMAL_PARAMETER, + genericLocation = {3, 0}, paramIndex = 0), + @TADescription(annotation = "TC", type = METHOD_FORMAL_PARAMETER, + genericLocation = {3, 0, 3, 0}, paramIndex = 0), + @TADescription(annotation = "TD", type = METHOD_FORMAL_PARAMETER, + genericLocation = {3, 0, 3, 0, 0, 0}, paramIndex = 0), + @TADescription(annotation = "TE", type = METHOD_FORMAL_PARAMETER, + genericLocation = {3, 0, 3, 0, 0, 0, 0, 0}, paramIndex = 0), + @TADescription(annotation = "TF", type = METHOD_FORMAL_PARAMETER, + genericLocation = {3, 0, 3, 0, 0, 0, 0, 0, 0, 0}, paramIndex = 0), + @TADescription(annotation = "TG", type = METHOD_FORMAL_PARAMETER, + genericLocation = {3, 1}, paramIndex = 0), + @TADescription(annotation = "TH", type = METHOD_FORMAL_PARAMETER, + genericLocation = {3, 1, 3, 0}, paramIndex = 0) + }) + public String testSpec4() { + return "void test(@TA Map<@TB Comparable<@TF Object @TC [] @TD [] @TE []>, @TG List<@TH String>> a) { }"; + } + + // Note first "1, 0" for top-level class Test. + @TADescriptions({ + @TADescription(annotation = "TA", type = METHOD_FORMAL_PARAMETER, + genericLocation = {1, 0, 1, 0, 1, 0, 1, 0}, paramIndex = 0), + @TADescription(annotation = "TB", type = METHOD_FORMAL_PARAMETER, + genericLocation = {1, 0, 1, 0, 1, 0, 1, 0, 3, 0}, paramIndex = 0), + @TADescription(annotation = "TC", type = METHOD_FORMAL_PARAMETER, + genericLocation = {1, 0, 1, 0, 1, 0, 1, 0, 3, 1}, paramIndex = 0), + @TADescription(annotation = "TD", type = METHOD_FORMAL_PARAMETER, + genericLocation = {1, 0, 1, 0, 1, 0}, paramIndex = 0), + @TADescription(annotation = "TE", type = METHOD_FORMAL_PARAMETER, + genericLocation = {1, 0, 1, 0}, paramIndex = 0), + @TADescription(annotation = "TF", type = METHOD_FORMAL_PARAMETER, + genericLocation = {1, 0, 1, 0, 3, 0}, paramIndex = 0), + @TADescription(annotation = "TG", type = METHOD_FORMAL_PARAMETER, + genericLocation = {1, 0, 1, 0, 3, 1}, paramIndex = 0), + @TADescription(annotation = "TH", type = METHOD_FORMAL_PARAMETER, + genericLocation = {1, 0}, paramIndex = 0) + }) + public String testSpec5() { + return "class Test { class O1 { class O2 { class O3 { class Nested {} } } }" + + "void test(@TH O1.@TE O2<@TF String, @TG String>.@TD O3.@TA Nested<@TB String, @TC String> a) { } }"; + } +} diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/MethodParameters.java b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/MethodParameters.java new file mode 100644 index 00000000000..cfe36ed9ae2 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/MethodParameters.java @@ -0,0 +1,151 @@ +/* + * Copyright (c) 2009 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. + * + * 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. + */ + +import static com.sun.tools.classfile.TypeAnnotation.TargetType.*; + +/* + * @test + * @summary Test population of reference info for method parameters + * @compile -g Driver.java ReferenceInfoUtil.java MethodParameters.java + * @run main Driver MethodParameters + */ +public class MethodParameters { + + @TADescription(annotation = "TA", type = METHOD_FORMAL_PARAMETER, paramIndex = 0) + public String methodParamAsPrimitive() { + return "void test(@TA int a) { }"; + } + + @TADescription(annotation = "TA", type = METHOD_FORMAL_PARAMETER, paramIndex = 1) + public String methodParamAsObject() { + return "void test(Object b, @TA Object a) { }"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = METHOD_FORMAL_PARAMETER, paramIndex = 0), + @TADescription(annotation = "TB", type = METHOD_FORMAL_PARAMETER, + genericLocation = { 3, 0 }, paramIndex = 0), + @TADescription(annotation = "TC", type = METHOD_FORMAL_PARAMETER, + genericLocation = { 3, 1 }, paramIndex = 0), + @TADescription(annotation = "TD", type = METHOD_FORMAL_PARAMETER, + genericLocation = { 3, 1, 3, 0 }, paramIndex = 0) + }) + public String methodParamAsParametrized() { + return "void test(@TA Map<@TB String, @TC List<@TD String>> a) { }"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = METHOD_FORMAL_PARAMETER, paramIndex = 0), + @TADescription(annotation = "TB", type = METHOD_FORMAL_PARAMETER, + genericLocation = { 3, 0 }, paramIndex = 0), + @TADescription(annotation = "TC", type = METHOD_FORMAL_PARAMETER, + genericLocation = { 3, 0, 2, 0 }, paramIndex = 0), + @TADescription(annotation = "TD", type = METHOD_FORMAL_PARAMETER, + genericLocation = { 3, 1 }, paramIndex = 0), + @TADescription(annotation = "TE", type = METHOD_FORMAL_PARAMETER, + genericLocation = { 3, 1, 3, 0 }, paramIndex = 0), + @TADescription(annotation = "TF", type = METHOD_FORMAL_PARAMETER, + genericLocation = { 3, 1, 3, 0, 2, 0 }, paramIndex = 0), + @TADescription(annotation = "TG", type = METHOD_FORMAL_PARAMETER, + genericLocation = { 3, 1, 3, 0, 2, 0, 3, 0 }, paramIndex = 0), + @TADescription(annotation = "TH", type = METHOD_FORMAL_PARAMETER, + genericLocation = { 3, 1, 3, 0, 2, 0, 3, 0, 2, 0 }, paramIndex = 0), + @TADescription(annotation = "TI", type = METHOD_FORMAL_PARAMETER, + genericLocation = { 3, 1, 3, 0, 2, 0, 3, 1 }, paramIndex = 0), + @TADescription(annotation = "TJ", type = METHOD_FORMAL_PARAMETER, + genericLocation = { 3, 1, 3, 0, 2, 0, 3, 1, 2, 0 }, paramIndex = 0) + }) + public String methodParamAsWildcard() { + return "void test(@TA Map<@TB ? extends @TC String," + + " @TD List<@TE ? extends @TF Map<@TG ? super @TH String," + + " @TI ? extends @TJ Object>>> a) { }"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = METHOD_FORMAL_PARAMETER, paramIndex = 1), + @TADescription(annotation = "TB", type = METHOD_FORMAL_PARAMETER, + genericLocation = { 0, 0 }, paramIndex = 1), + @TADescription(annotation = "TC", type = METHOD_FORMAL_PARAMETER, + genericLocation = { 0, 0, 0, 0 }, paramIndex = 1) + }) + public String methodParamAsArray() { + return "void test(Object b, @TC String @TA [] @TB [] a) { }"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = METHOD_FORMAL_PARAMETER, paramIndex = 1), + @TADescription(annotation = "TB", type = METHOD_FORMAL_PARAMETER, + genericLocation = { 0, 0 }, paramIndex = 1), + @TADescription(annotation = "TC", type = METHOD_FORMAL_PARAMETER, + genericLocation = { 0, 0, 0, 0 }, paramIndex = 1) + }) + public String methodParamAsVararg() { + return "void test(Object b, @TC String @TA [] @TB ... a) { }"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = METHOD_FORMAL_PARAMETER, paramIndex = 1), + @TADescription(annotation = "TB", type = METHOD_FORMAL_PARAMETER, + genericLocation = { 0, 0 }, paramIndex = 1), + @TADescription(annotation = "TC", type = METHOD_FORMAL_PARAMETER, + genericLocation = { 0, 0, 0, 0 }, paramIndex = 1) + }) + public String methodParamAsFQVararg() { + return "void test(Object b, java.lang.@TC String @TA [] @TB ... a) { }"; + } + + @TADescriptions({}) + public String methodWithDeclarationAnnotatin() { + return "void test(@Decl String a) { }"; + } + + @TADescriptions({}) + public String methodWithNoTargetAnno() { + return "void test(@A String a) { }"; + } + + // Smoke tests + @TADescription(annotation = "TA", type = METHOD_FORMAL_PARAMETER, paramIndex = 0) + public String interfacemethodParamAsObject() { + return "interface Test { void test(@TA Object a); }"; + } + + @TADescription(annotation = "TA", type = METHOD_FORMAL_PARAMETER, paramIndex = 2) + public String abstractmethodParamAsObject() { + return "abstract class Test { abstract void test(Object b, Object c, @TA Object a); }"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = METHOD_FORMAL_PARAMETER, paramIndex = 0), + @TADescription(annotation = "TB", type = METHOD_FORMAL_PARAMETER, + genericLocation = { 3, 0 }, paramIndex = 0), + @TADescription(annotation = "TC", type = METHOD_FORMAL_PARAMETER, + genericLocation = { 3, 1 }, paramIndex = 0), + @TADescription(annotation = "TD", type = METHOD_FORMAL_PARAMETER, + genericLocation = { 3, 1, 3, 0 }, paramIndex = 0) + }) + public String interfacemethodParamAsParametrized() { + return "interface Test { void test(@TA Map<@TB String, @TC List<@TD String>> a); }"; + } + +} diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/MethodReceivers.java b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/MethodReceivers.java new file mode 100644 index 00000000000..c834d0cef56 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/MethodReceivers.java @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2009 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. + * + * 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. + */ + +import static com.sun.tools.classfile.TypeAnnotation.TargetType.*; + +/* + * @test + * @summary Test population of reference info for method receivers + * @compile -g Driver.java ReferenceInfoUtil.java MethodReceivers.java + * @run main Driver MethodReceivers + */ +public class MethodReceivers { + + @TADescription(annotation = "TA", type = METHOD_RECEIVER) + public String regularMethod() { + return "class Test { void test(@TA Test this) { } }"; + } + + @TADescription(annotation = "TA", type = METHOD_RECEIVER) + public String abstractMethod() { + return "abstract class Test { abstract void test(@TA Test this); }"; + } + + @TADescription(annotation = "TA", type = METHOD_RECEIVER) + public String interfaceMethod() { + return "interface Test { void test(@TA Test this); }"; + } + + @TADescription(annotation = "TA", type = METHOD_RECEIVER) + public String regularWithThrows() { + return "class Test { void test(@TA Test this) throws Exception { } }"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = METHOD_RECEIVER, + genericLocation = {}), + @TADescription(annotation = "TB", type = METHOD_RECEIVER, + genericLocation = {1, 0}) + }) + @TestClass("TestOuter$TestInner") + public String nestedtypes1() { + return "class TestOuter { class TestInner { void test(@TA TestOuter. @TB TestInner this) { } } }"; + } + + @TADescription(annotation = "TA", type = METHOD_RECEIVER, + genericLocation = {}) + @TestClass("TestOuter$TestInner") + public String nestedtypes2() { + return "class TestOuter { class TestInner { void test(@TA TestOuter.TestInner this) { } } }"; + } + + @TADescription(annotation = "TB", type = METHOD_RECEIVER, + genericLocation = {1, 0}) + @TestClass("TestOuter$TestInner") + public String nestedtypes3() { + return "class TestOuter { class TestInner { void test(TestOuter. @TB TestInner this) { } } }"; + } + +} diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/MethodReturns.java b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/MethodReturns.java new file mode 100644 index 00000000000..07fc9f23742 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/MethodReturns.java @@ -0,0 +1,186 @@ +/* + * Copyright (c) 2009 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. + * + * 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. + */ + +import static com.sun.tools.classfile.TypeAnnotation.TargetType.*; + +/* + * @test + * @summary Test population of reference info for method return + * @compile -g Driver.java ReferenceInfoUtil.java MethodReturns.java + * @run main Driver MethodReturns + */ +public class MethodReturns { + + // Method returns + @TADescription(annotation = "TA", type = METHOD_RETURN) + public String methodReturnAsPrimitive() { + return "@TA int test() { return 0; }"; + } + + @TADescription(annotation = "TA", type = METHOD_RETURN) + public String methodReturnAsObject() { + return "@TA Object test() { return null; }"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = METHOD_RETURN), + @TADescription(annotation = "TB", type = METHOD_RETURN, + genericLocation = { 3, 0 }), + @TADescription(annotation = "TC", type = METHOD_RETURN, + genericLocation = { 3, 1 }), + @TADescription(annotation = "TD", type = METHOD_RETURN, + genericLocation = { 3, 1, 3, 0 }) + }) + public String methodReturnAsParametrized() { + return "@TA Map<@TB String, @TC List<@TD String>> test() { return null; }"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = METHOD_RETURN), + @TADescription(annotation = "TB", type = METHOD_RETURN, + genericLocation = { 0, 0 }), + @TADescription(annotation = "TC", type = METHOD_RETURN, + genericLocation = { 0, 0, 0, 0 }) + }) + public String methodReturnAsArray() { + return "@TC String @TA [] @TB [] test() { return null; }"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = METHOD_RETURN), + @TADescription(annotation = "TB", type = METHOD_RETURN, + genericLocation = { 0, 0 }), + @TADescription(annotation = "TC", type = METHOD_RETURN, + genericLocation = { 0, 0, 0, 0 }) + }) + public String methodReturnAsArrayOld() { + return "@TC String test() @TA [] @TB [] { return null; }"; + } + + @TADescriptions({}) + public String methodWithDeclarationAnnotation() { + return "@Decl String test() { return null; }"; + } + + @TADescriptions({}) + public String methodWithNoTargetAnno() { + return "@A String test() { return null; }"; + } + + // Smoke tests + @TADescription(annotation = "TA", type = METHOD_RETURN) + public String interfaceMethodReturnAsObject() { + return "interface Test { @TA Object test(); }"; + } + + @TADescription(annotation = "TA", type = METHOD_RETURN) + public String abstractMethodReturnAsObject() { + return "abstract class Test { abstract @TA Object test(); }"; + } + + + @TADescriptions({ + @TADescription(annotation = "TA", type = METHOD_RETURN), + @TADescription(annotation = "TB", type = METHOD_RETURN, + genericLocation = { 3, 0 }), + @TADescription(annotation = "TC", type = METHOD_RETURN, + genericLocation = { 3, 1 }), + @TADescription(annotation = "TD", type = METHOD_RETURN, + genericLocation = { 3, 1, 3, 0 }) + }) + public String interfaceMethodReturnAsParametrized() { + return "interface Test { @TA Map<@TB String, @TC List<@TD String>> test(); }"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = METHOD_RETURN, + genericLocation = { 3, 0 }), + @TADescription(annotation = "TB", type = METHOD_RETURN, + genericLocation = { 3, 0, 2, 0 }), + @TADescription(annotation = "TC", type = METHOD_RETURN, + genericLocation = { 3, 0, 2, 0, 1, 0 }), + @TADescription(annotation = "TD", type = METHOD_RETURN, + genericLocation = { 3, 0, 2, 0, 1, 0, 3, 0 }), + @TADescription(annotation = "TE", type = METHOD_RETURN, + genericLocation = { 3, 0, 2, 0, 1, 0, 3, 1 }), + @TADescription(annotation = "TF", type = METHOD_RETURN, + genericLocation = { 3, 0, 2, 0, 1, 0, 3, 1, 2, 0 }) + }) + public String methodReturnAsNestedWildcard() { + return "Set<@TA ? extends @TB GOuter. @TC GInner<@TD String, @TE ? super @TF Object>> entrySet() { return null; }"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = METHOD_RETURN, + genericLocation = { 3, 0, 1, 0, 3, 0 }), + @TADescription(annotation = "TB", type = METHOD_RETURN, + genericLocation = { 3, 0, 1, 0, 3, 1 }), + @TADescription(annotation = "TC", type = METHOD_RETURN, + genericLocation = { 3, 0, 1, 0, 3, 1, 2, 0 }) + }) + public String methodReturnAsNestedWildcard2() { + return "class GOuter { class GInner {} } " + + "class Test { Set.GInner<@TA K, @TB ? extends @TC Object>> entrySet() { return null; } }"; + } + + @TADescriptions({ + @TADescription(annotation = "TB", type = METHOD_RETURN, + genericLocation = { 3, 0, 2, 0 }), + @TADescription(annotation = "TC", type = METHOD_RETURN, + genericLocation = { 3, 0, 2, 0, 1, 0 }), + }) + public String methodReturnAsNestedWildcard3() { + return "Set. @TC GInner> entrySet() { return null; }"; + } + + @TADescriptions({ + @TADescription(annotation = "TC", type = METHOD_RETURN, + genericLocation = { 3, 0, 2, 0, 1, 0 }), + }) + public String methodReturnAsNestedWildcard4() { + return "Set. @TC GInner> entrySet() { return null; }"; + } + + @TADescriptions({ + @TADescription(annotation = "TB", type = METHOD_RETURN, + genericLocation = { 3, 0, 2, 0 }), + @TADescription(annotation = "TC", type = METHOD_RETURN, + genericLocation = { 3, 0, 2, 0, 1, 0 }), + }) + public String methodReturnAsNestedWildcard5() { + return "Set entrySet() { return null; }"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = METHOD_RETURN, + genericLocation = { 3, 0, 2, 0, 1, 0, 3, 0 }), + @TADescription(annotation = "TB", type = METHOD_RETURN, + genericLocation = { 3, 0, 2, 0, 1, 0, 3, 1 }), + @TADescription(annotation = "TC", type = METHOD_RETURN, + genericLocation = { 3, 0, 2, 0, 1, 0 }), + }) + public String methodReturnAsNestedWildcard6() { + return "Set. @TC GInner<@TA String, @TB Object>> entrySet() { return null; }"; + } + +} diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/MethodThrows.java b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/MethodThrows.java new file mode 100644 index 00000000000..155e4bbfb71 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/MethodThrows.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2009 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. + * + * 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. + */ + +import static com.sun.tools.classfile.TypeAnnotation.TargetType.*; + +/* + * @test + * @summary Test population of reference info for method exception clauses + * @compile -g Driver.java ReferenceInfoUtil.java MethodThrows.java + * @run main Driver MethodThrows + */ +public class MethodThrows { + + @TADescriptions({ + @TADescription(annotation = "TA", type = THROWS, typeIndex = 0), + @TADescription(annotation = "TB", type = THROWS, typeIndex = 2) + }) + public String regularMethod() { + return "class Test { void test() throws @TA RuntimeException, IllegalArgumentException, @TB Exception { } }"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = THROWS, typeIndex = 0), + @TADescription(annotation = "TB", type = THROWS, typeIndex = 2) + }) + public String abstractMethod() { + return "abstract class Test { abstract void test() throws @TA RuntimeException, IllegalArgumentException, @TB Exception; }"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = THROWS, typeIndex = 0), + @TADescription(annotation = "TB", type = THROWS, typeIndex = 2) + }) + public String interfaceMethod() { + return "interface Test { void test() throws @TA RuntimeException, IllegalArgumentException, @TB Exception; }"; + } +} diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/MethodTypeParam.java b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/MethodTypeParam.java new file mode 100644 index 00000000000..4b7b521904f --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/MethodTypeParam.java @@ -0,0 +1,251 @@ +/* + * Copyright (c) 2009 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. + * + * 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. + */ + +import static com.sun.tools.classfile.TypeAnnotation.TargetType.*; + +/* + * @test + * @summary Test population of reference info for method type parameters + * @compile -g Driver.java ReferenceInfoUtil.java MethodTypeParam.java + * @run main Driver MethodTypeParam + */ +public class MethodTypeParam { + + @TADescriptions({ + @TADescription(annotation = "TA", type = METHOD_TYPE_PARAMETER, paramIndex = 0), + @TADescription(annotation = "TB", type = METHOD_TYPE_PARAMETER_BOUND, paramIndex = 0, boundIndex = 0), + @TADescription(annotation = "TC", type = METHOD_TYPE_PARAMETER, paramIndex = 1), + @TADescription(annotation = "TD", type = METHOD_TYPE_PARAMETER_BOUND, paramIndex = 1, boundIndex = 0), + @TADescription(annotation = "TE", type = METHOD_TYPE_PARAMETER_BOUND, paramIndex = 1, boundIndex = 1) + }) + public String regularClass() { + return "<@TA K extends @TB Date, @TC V extends @TD Object & @TE Cloneable> void test() { }"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = METHOD_TYPE_PARAMETER, paramIndex = 0), + @TADescription(annotation = "TB", type = METHOD_TYPE_PARAMETER_BOUND, paramIndex = 0, boundIndex = 0), + @TADescription(annotation = "TC", type = METHOD_TYPE_PARAMETER, paramIndex = 1), + @TADescription(annotation = "TE", type = METHOD_TYPE_PARAMETER_BOUND, paramIndex = 1, boundIndex = 1) + }) + public String regularClass2() { + return "<@TA K extends @TB Date, @TC V extends @TE Cloneable> void test() { }"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = METHOD_TYPE_PARAMETER_BOUND, paramIndex = 0, boundIndex = 1), + @TADescription(annotation = "TB", type = METHOD_TYPE_PARAMETER_BOUND, paramIndex = 0, boundIndex = 1, genericLocation = {3, 1}), + @TADescription(annotation = "TC", type = METHOD_TYPE_PARAMETER_BOUND, paramIndex = 1, boundIndex = 1), + @TADescription(annotation = "TD", type = METHOD_TYPE_PARAMETER_BOUND, paramIndex = 1, boundIndex = 1, genericLocation = {3, 0}), + @TADescription(annotation = "TE", type = METHOD_TYPE_PARAMETER_BOUND, paramIndex = 1, boundIndex = 1, genericLocation = {3, 0, 3, 0}), + @TADescription(annotation = "TF", type = METHOD_TYPE_PARAMETER_BOUND, paramIndex = 1, boundIndex = 0) + }) + public String regularClassParameterized() { + return ", V extends @TF Object & @TC List<@TD List<@TE Object>>> void test() { }"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = METHOD_TYPE_PARAMETER, paramIndex = 0), + @TADescription(annotation = "TB", type = METHOD_TYPE_PARAMETER_BOUND, paramIndex = 0, boundIndex = 0), + @TADescription(annotation = "TC", type = METHOD_TYPE_PARAMETER, paramIndex = 1), + @TADescription(annotation = "TD", type = METHOD_TYPE_PARAMETER_BOUND, paramIndex = 1, boundIndex = 0), + @TADescription(annotation = "TE", type = METHOD_TYPE_PARAMETER_BOUND, paramIndex = 1, boundIndex = 1) + }) + public String abstractClass() { + return "abstract class Test { abstract <@TA K extends @TB Date, @TC V extends @TD Object & @TE Cloneable> void test(); }"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = METHOD_TYPE_PARAMETER_BOUND, paramIndex = 0, boundIndex = 1), + @TADescription(annotation = "TB", type = METHOD_TYPE_PARAMETER_BOUND, paramIndex = 0, boundIndex = 1, genericLocation = {3, 1}), + @TADescription(annotation = "TC", type = METHOD_TYPE_PARAMETER_BOUND, paramIndex = 1, boundIndex = 1), + @TADescription(annotation = "TD", type = METHOD_TYPE_PARAMETER_BOUND, paramIndex = 1, boundIndex = 1, genericLocation = {3, 0}), + @TADescription(annotation = "TE", type = METHOD_TYPE_PARAMETER_BOUND, paramIndex = 1, boundIndex = 1, genericLocation = {3, 0, 3, 0}), + @TADescription(annotation = "TF", type = METHOD_TYPE_PARAMETER_BOUND, paramIndex = 1, boundIndex = 0), + @TADescription(annotation = "TG", type = METHOD_TYPE_PARAMETER_BOUND, paramIndex = 0, boundIndex = 0) + }) + public String abstractClassParameterized() { + return "abstract class Test { abstract , V extends @TF Object & @TC List<@TD List<@TE Object>>> void test(); }"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = METHOD_TYPE_PARAMETER_BOUND, paramIndex = 0, boundIndex = 1), + @TADescription(annotation = "TB", type = METHOD_TYPE_PARAMETER_BOUND, paramIndex = 0, boundIndex = 1, genericLocation = {3, 1}), + @TADescription(annotation = "TC", type = METHOD_TYPE_PARAMETER_BOUND, paramIndex = 1, boundIndex = 1), + @TADescription(annotation = "TD", type = METHOD_TYPE_PARAMETER_BOUND, paramIndex = 1, boundIndex = 1, genericLocation = {3, 0}), + @TADescription(annotation = "TE", type = METHOD_TYPE_PARAMETER_BOUND, paramIndex = 1, boundIndex = 1, genericLocation = {3, 0, 3, 0}) + }) + public String abstractClassParameterized2() { + return "abstract class Test { abstract , V extends @TC List<@TD List<@TE Object>>> void test(); }"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = METHOD_TYPE_PARAMETER_BOUND, paramIndex = 0, boundIndex = 1), + @TADescription(annotation = "TB", type = METHOD_TYPE_PARAMETER_BOUND, paramIndex = 1, boundIndex = 1) + }) + public String abstractClassParameterized3() { + return "abstract class Test { abstract , V extends @TB List> void test(); }"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = METHOD_TYPE_PARAMETER, paramIndex = 0), + @TADescription(annotation = "TB", type = METHOD_TYPE_PARAMETER_BOUND, paramIndex = 0, boundIndex = 0), + @TADescription(annotation = "TC", type = METHOD_TYPE_PARAMETER, paramIndex = 1), + @TADescription(annotation = "TD", type = METHOD_TYPE_PARAMETER_BOUND, paramIndex = 1, boundIndex = 0), + @TADescription(annotation = "TE", type = METHOD_TYPE_PARAMETER_BOUND, paramIndex = 1, boundIndex = 1) + }) + public String regularInterface() { + return "interface Test { <@TA K extends @TB Date, @TC V extends @TD Object & @TE Cloneable> void test(); }"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = METHOD_TYPE_PARAMETER_BOUND, paramIndex = 0, boundIndex = 1), + @TADescription(annotation = "TB", type = METHOD_TYPE_PARAMETER_BOUND, paramIndex = 0, boundIndex = 1, genericLocation = {3, 1}), + @TADescription(annotation = "TC", type = METHOD_TYPE_PARAMETER_BOUND, paramIndex = 1, boundIndex = 1), + @TADescription(annotation = "TD", type = METHOD_TYPE_PARAMETER_BOUND, paramIndex = 1, boundIndex = 1, genericLocation = {3, 0}), + @TADescription(annotation = "TE", type = METHOD_TYPE_PARAMETER_BOUND, paramIndex = 1, boundIndex = 1, genericLocation = {3, 0, 3, 0}), + @TADescription(annotation = "TF", type = METHOD_TYPE_PARAMETER_BOUND, paramIndex = 1, boundIndex = 0), + @TADescription(annotation = "TG", type = METHOD_TYPE_PARAMETER_BOUND, paramIndex = 0, boundIndex = 0), + @TADescription(annotation = "TH", type = METHOD_TYPE_PARAMETER, paramIndex = 0), + @TADescription(annotation = "TI", type = METHOD_TYPE_PARAMETER, paramIndex = 1) + }) + public String regularInterfaceParameterized() { + return "interface Test { <@TH K extends @TG Object & @TA Map, @TI V extends @TF Object & @TC List<@TD List<@TE Object>>> void test(); }"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = METHOD_TYPE_PARAMETER_BOUND, paramIndex = 0, boundIndex = 1), + @TADescription(annotation = "TB", type = METHOD_TYPE_PARAMETER_BOUND, paramIndex = 0, boundIndex = 1, genericLocation = {3, 1}), + @TADescription(annotation = "TC", type = METHOD_TYPE_PARAMETER_BOUND, paramIndex = 1, boundIndex = 1), + @TADescription(annotation = "TD", type = METHOD_TYPE_PARAMETER_BOUND, paramIndex = 1, boundIndex = 1, genericLocation = {3, 0}), + @TADescription(annotation = "TE", type = METHOD_TYPE_PARAMETER_BOUND, paramIndex = 1, boundIndex = 1, genericLocation = {3, 0, 3, 0}), + @TADescription(annotation = "TF", type = METHOD_TYPE_PARAMETER, paramIndex = 0), + @TADescription(annotation = "TG", type = METHOD_TYPE_PARAMETER, paramIndex = 1) + }) + public String regularInterfaceParameterized2() { + return "interface Test { <@TF K extends @TA Map, @TG V extends @TC List<@TD List<@TE Object>>> void test(); }"; + } + + @TADescription(annotation = "TA", type = METHOD_RETURN) + public String useInReturn1() { + return "class Test { @TA T m() { throw new RuntimeException(); } }"; + } + + @TADescription(annotation = "TA", type = METHOD_RETURN, genericLocation = {3, 0}) + public String useInReturn2() { + return "class Test { Class<@TA T> m() { throw new RuntimeException(); } }"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = METHOD_TYPE_PARAMETER_BOUND, paramIndex = 0, boundIndex = 0), + @TADescription(annotation = "TB", type = METHOD_RETURN) + }) + public String useInReturn3() { + return "class Test { @TB T m() { throw new RuntimeException(); } }"; + } + + @TADescription(annotation = "TA", type = METHOD_FORMAL_PARAMETER, + paramIndex = 0, genericLocation = {3, 0}) + public String useInParam1() { + return "class Test { void m(Class<@TA T> p) { throw new RuntimeException(); } }"; + } + + @TADescription(annotation = "TA", type = METHOD_FORMAL_PARAMETER, + paramIndex = 0, genericLocation = {3, 0}) + public String useInParam2() { + return "class Test { void m(Class<@TA Object> p) { throw new RuntimeException(); } }"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = METHOD_TYPE_PARAMETER_BOUND, paramIndex = 0, boundIndex = 1), + @TADescription(annotation = "TB", type = METHOD_TYPE_PARAMETER_BOUND, paramIndex = 0, boundIndex = 2), + @TADescription(annotation = "TC", type = METHOD_FORMAL_PARAMETER, paramIndex = 0) + }) + public String useInParam3() { + return "interface IA {} " + + "interface IB {} " + + "interface IC {} " + + "class Test { & @TB IC> void m(@TC T p) { throw new RuntimeException(); } }"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = METHOD_TYPE_PARAMETER_BOUND, + paramIndex = 0, boundIndex = 1, + genericLocation = {}), + @TADescription(annotation = "TB", type = METHOD_TYPE_PARAMETER_BOUND, + paramIndex = 0, boundIndex = 2, + genericLocation = {}), + @TADescription(annotation = "TC", type = METHOD_FORMAL_PARAMETER, + paramIndex = 0) + }) + public String useInParam4() { + return "class Test {" + + " interface IA {} " + + " interface IB {} " + + " interface IC {} " + + " & @TB IC> void m(@TC T p) { throw new RuntimeException(); } }"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = METHOD_TYPE_PARAMETER_BOUND, + paramIndex = 0, boundIndex = 0, + genericLocation = {}), + @TADescription(annotation = "TB", type = METHOD_TYPE_PARAMETER_BOUND, + paramIndex = 0, boundIndex = 0, + genericLocation = {1, 0}), + @TADescription(annotation = "TC", type = METHOD_TYPE_PARAMETER_BOUND, + paramIndex = 0, boundIndex = 0, + genericLocation = {1, 0, 3, 0}), + }) + public String useInParam5() { + return "class Test {" + + " interface IA {} " + + " class CB {} " + + " > void m(T p) { throw new RuntimeException(); } }"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = METHOD_TYPE_PARAMETER, + paramIndex = 0), + @TADescription(annotation = "TB", type = METHOD_TYPE_PARAMETER_BOUND, + paramIndex = 0, boundIndex = 0, + genericLocation = {}), + @TADescription(annotation = "TC", type = METHOD_TYPE_PARAMETER_BOUND, + paramIndex = 0, boundIndex = 0, + genericLocation = {1, 0, 3, 0}), + @TADescription(annotation = "TD", type = METHOD_TYPE_PARAMETER_BOUND, + paramIndex = 0, boundIndex = 1, + genericLocation = {}), + @TADescription(annotation = "TE", type = METHOD_TYPE_PARAMETER_BOUND, + paramIndex = 0, boundIndex = 1, + genericLocation = {3, 0}) + }) + public String useInParam6() { + return "class Test {" + + " interface IA {} " + + " interface IB {} " + + " class CC {} " + + " interface ID {} " + + " <@TA T extends @TB Test.CC<@TC IA> & Test. @TD ID<@TE IA>> void m(T p) { throw new RuntimeException(); } }"; + } +} diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/MultiCatch.java b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/MultiCatch.java new file mode 100644 index 00000000000..d62d52ff158 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/MultiCatch.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2013 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. + * + * 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. + */ + +import static com.sun.tools.classfile.TypeAnnotation.TargetType.*; + +/* + * @test + * @bug 8006732 8006775 + * @ignore + * @summary Test population of reference info for multicatch exception parameters + * @author Werner Dietl + * @compile -g Driver.java ReferenceInfoUtil.java MultiCatch.java + * @run main Driver MultiCatch + */ +public class MultiCatch { + + @TADescriptions({ + @TADescription(annotation = "TA", type = EXCEPTION_PARAMETER, exceptionIndex = 0), + @TADescription(annotation = "TB", type = EXCEPTION_PARAMETER, exceptionIndex = 1) + }) + public String multiCatch1() { + return "void multiCatch1() { " + + "try { new Object(); } catch (@TA NullPointerException | @TB IndexOutOfBoundsException e) { e.toString(); } }"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = EXCEPTION_PARAMETER, exceptionIndex = 0), + @TADescription(annotation = "TB", type = EXCEPTION_PARAMETER, exceptionIndex = 1), + @TADescription(annotation = "TC", type = EXCEPTION_PARAMETER, exceptionIndex = 2), + }) + public String multiCatch2() { + return "void multiCatch2() { " + + "try { new Object(); } catch (@TA NullPointerException | @TB IndexOutOfBoundsException | @TC IllegalArgumentException e) { e.toString(); } }"; + } + +} diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/NestedTypes.java b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/NestedTypes.java new file mode 100644 index 00000000000..476e23f05ce --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/NestedTypes.java @@ -0,0 +1,834 @@ +/* + * Copyright (c) 2012 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. + * + * 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. + */ + +import static com.sun.tools.classfile.TypeAnnotation.TargetType.*; + +/* + * @test + * @summary Test population of reference info for nested types + * @compile -g Driver.java ReferenceInfoUtil.java NestedTypes.java + * @run main Driver NestedTypes + */ +public class NestedTypes { + + // method parameters + + @TADescriptions({ + @TADescription(annotation = "TA", type = METHOD_FORMAL_PARAMETER, + genericLocation = {}, paramIndex = 0), + @TADescription(annotation = "TB", type = METHOD_FORMAL_PARAMETER, + genericLocation = {1, 0}, paramIndex = 0) + }) + public String testParam1() { + return "void test(@TA Outer.@TB Inner a) { }"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = METHOD_FORMAL_PARAMETER, + genericLocation = {3, 0}, paramIndex = 0), + @TADescription(annotation = "TB", type = METHOD_FORMAL_PARAMETER, + genericLocation = {3, 0, 1, 0}, paramIndex = 0) + }) + public String testParam1b() { + return "void test(List<@TA Outer.@TB Inner> a) { }"; + } + + // TODO: the tests that use @TA Map.Entry should fail, as + // Map cannot be annotated. + // We need some tests for the fully qualified name syntax. + /* + @TADescription(annotation = "TA", type = METHOD_FORMAL_PARAMETER, + genericLocation = {}, paramIndex = 0) + public String testParam1c() { + return "void test(java.util.@TA Map.Entry a) { }"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = METHOD_FORMAL_PARAMETER, + genericLocation = {}, paramIndex = 0), + @TADescription(annotation = "TB", type = METHOD_FORMAL_PARAMETER, + genericLocation = {1, 0}, paramIndex = 0) + }) + public String testParam1d() { + return "void test(java.util.@TA Map.@TB Entry a) { }"; + } + + @TADescription(annotation = "TA", type = METHOD_FORMAL_PARAMETER, + genericLocation = {3, 0}, paramIndex = 0) + public String testParam1e() { + return "void test(List a) { }"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = METHOD_FORMAL_PARAMETER, + genericLocation = {3, 0}, paramIndex = 0), + @TADescription(annotation = "TB", type = METHOD_FORMAL_PARAMETER, + genericLocation = {3, 0, 1, 0}, paramIndex = 0) + }) + public String testParam1f() { + return "void test(List a) { }"; + } + */ + + @TADescription(annotation = "TB", type = METHOD_FORMAL_PARAMETER, + genericLocation = {3, 0}, paramIndex = 0) + public String testParam1g() { + return "void test(List a) { }"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = METHOD_FORMAL_PARAMETER, + genericLocation = {}, paramIndex = 0), + @TADescription(annotation = "TB", type = METHOD_FORMAL_PARAMETER, + genericLocation = {1, 0}, paramIndex = 0) + }) + public String testParam2() { + return "void test(@TA GOuter.@TB GInner a) { }"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = METHOD_FORMAL_PARAMETER, + genericLocation = {3, 0}, paramIndex = 0), + @TADescription(annotation = "TB", type = METHOD_FORMAL_PARAMETER, + genericLocation = {3, 0, 1, 0}, paramIndex = 0) + }) + public String testParam2b() { + return "void test(List<@TA GOuter.@TB GInner> a) { }"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = METHOD_FORMAL_PARAMETER, + genericLocation = {0, 0, 0, 0}, paramIndex = 0), + @TADescription(annotation = "TB", type = METHOD_FORMAL_PARAMETER, + genericLocation = {0, 0, 0, 0, 1, 0}, paramIndex = 0), + @TADescription(annotation = "TC", type = METHOD_FORMAL_PARAMETER, + genericLocation = {0, 0, 0, 0, 1, 0, 3, 0}, paramIndex = 0), + @TADescription(annotation = "TD", type = METHOD_FORMAL_PARAMETER, + genericLocation = {0, 0, 0, 0, 1, 0, 3, 0, 3, 0, 0, 0, 0, 0}, paramIndex = 0), + @TADescription(annotation = "TE", type = METHOD_FORMAL_PARAMETER, + genericLocation = {0, 0, 0, 0, 1, 0, 3, 0, 3, 0}, paramIndex = 0), + @TADescription(annotation = "TF", type = METHOD_FORMAL_PARAMETER, + genericLocation = {0, 0, 0, 0, 1, 0, 3, 0, 3, 0, 0, 0}, paramIndex = 0), + @TADescription(annotation = "TG", type = METHOD_FORMAL_PARAMETER, + genericLocation = {0, 0, 0, 0, 1, 0, 1, 0}, paramIndex = 0), + @TADescription(annotation = "TH", type = METHOD_FORMAL_PARAMETER, + genericLocation = {0, 0, 0, 0, 1, 0, 1, 0, 3, 0}, paramIndex = 0), + @TADescription(annotation = "TI", type = METHOD_FORMAL_PARAMETER, + genericLocation = {0, 0, 0, 0, 1, 0, 1, 0, 3, 1}, paramIndex = 0), + @TADescription(annotation = "TJ", type = METHOD_FORMAL_PARAMETER, paramIndex = 0), + @TADescription(annotation = "TK", type = METHOD_FORMAL_PARAMETER, + genericLocation = {0, 0}, paramIndex = 0) + }) + public String testParam3() { + return "class Outer {\n" + + " class GInner {\n" + + " class GInner2 {}\n" + + "}}\n\n" + + "class Test {\n" + + " void test(@TA Outer . @TB GInner<@TC List<@TD Object @TE[] @TF[]>>. @TG GInner2<@TH Integer, @TI Object> @TJ[] @TK[] a) { }\n" + + "}"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = METHOD_FORMAL_PARAMETER, + genericLocation = {3, 0, 0, 0, 0, 0}, paramIndex = 0), + @TADescription(annotation = "TB", type = METHOD_FORMAL_PARAMETER, + genericLocation = {3, 0, 0, 0, 0, 0, 1, 0}, paramIndex = 0), + @TADescription(annotation = "TC", type = METHOD_FORMAL_PARAMETER, + genericLocation = {3, 0, 0, 0, 0, 0, 1, 0, 3, 0}, paramIndex = 0), + @TADescription(annotation = "TD", type = METHOD_FORMAL_PARAMETER, + genericLocation = {3, 0, 0, 0, 0, 0, 1, 0, 3, 0, 3, 0, 0, 0, 0, 0}, paramIndex = 0), + @TADescription(annotation = "TE", type = METHOD_FORMAL_PARAMETER, + genericLocation = {3, 0, 0, 0, 0, 0, 1, 0, 3, 0, 3, 0}, paramIndex = 0), + @TADescription(annotation = "TF", type = METHOD_FORMAL_PARAMETER, + genericLocation = {3, 0, 0, 0, 0, 0, 1, 0, 3, 0, 3, 0, 0, 0}, paramIndex = 0), + @TADescription(annotation = "TG", type = METHOD_FORMAL_PARAMETER, + genericLocation = {3, 0, 0, 0, 0, 0, 1, 0, 1, 0}, paramIndex = 0), + @TADescription(annotation = "TH", type = METHOD_FORMAL_PARAMETER, + genericLocation = {3, 0, 0, 0, 0, 0, 1, 0, 1, 0, 3, 0}, paramIndex = 0), + @TADescription(annotation = "TI", type = METHOD_FORMAL_PARAMETER, + genericLocation = {3, 0, 0, 0, 0, 0, 1, 0, 1, 0, 3, 1}, paramIndex = 0), + @TADescription(annotation = "TJ", type = METHOD_FORMAL_PARAMETER, + genericLocation = {3, 0}, paramIndex = 0), + @TADescription(annotation = "TK", type = METHOD_FORMAL_PARAMETER, + genericLocation = {3, 0, 0, 0}, paramIndex = 0) + }) + public String testParam4() { + return "class Outer {\n" + + " class GInner {\n" + + " class GInner2 {}\n" + + "}}\n\n" + + "class Test {\n" + + " void test(List<@TA Outer . @TB GInner<@TC List<@TD Object @TE[] @TF[]>>. @TG GInner2<@TH Integer, @TI Object> @TJ[] @TK[]> a) { }\n" + + "}"; + } + + + // Local variables + + @TADescriptions({ + @TADescription(annotation = "TA", type = LOCAL_VARIABLE, + genericLocation = {}, + lvarOffset = {2}, lvarLength = {1}, lvarIndex = {1}), + @TADescription(annotation = "TB", type = LOCAL_VARIABLE, + genericLocation = {1, 0}, + lvarOffset = {2}, lvarLength = {1}, lvarIndex = {1}) + }) + public String testLocal1a() { + return "void test() { @TA Outer.@TB Inner a = null; }"; + } + + @TADescription(annotation = "TA", type = LOCAL_VARIABLE, + genericLocation = {}, + lvarOffset = {2}, lvarLength = {1}, lvarIndex = {1}) + public String testLocal1b() { + return "void test() { @TA Outer.Inner a = null; }"; + } + + @TADescription(annotation = "TB", type = LOCAL_VARIABLE, + genericLocation = {1, 0}, + lvarOffset = {2}, lvarLength = {1}, lvarIndex = {1}) + public String testLocal1c() { + return "void test() { Outer.@TB Inner a = null; }"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = LOCAL_VARIABLE, + genericLocation = {}, + lvarOffset = {2}, lvarLength = {1}, lvarIndex = {1}), + @TADescription(annotation = "TB", type = LOCAL_VARIABLE, + genericLocation = {1, 0}, + lvarOffset = {2}, lvarLength = {1}, lvarIndex = {1}) + }) + public String testLocal2() { + return "void test() { @TA GOuter.@TB GInner a = null; }"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = LOCAL_VARIABLE, + genericLocation = {0, 0, 0, 0}, + lvarOffset = {5}, lvarLength = {1}, lvarIndex = {1}), + @TADescription(annotation = "TB", type = LOCAL_VARIABLE, + genericLocation = {0, 0, 0, 0, 1, 0}, + lvarOffset = {5}, lvarLength = {1}, lvarIndex = {1}), + @TADescription(annotation = "TC", type = LOCAL_VARIABLE, + genericLocation = {0, 0, 0, 0, 1, 0, 3, 0}, + lvarOffset = {5}, lvarLength = {1}, lvarIndex = {1}), + @TADescription(annotation = "TD", type = LOCAL_VARIABLE, + genericLocation = {0, 0, 0, 0, 1, 0, 3, 0, 3, 0, 0, 0, 0, 0}, + lvarOffset = {5}, lvarLength = {1}, lvarIndex = {1}), + @TADescription(annotation = "TE", type = LOCAL_VARIABLE, + genericLocation = {0, 0, 0, 0, 1, 0, 3, 0, 3, 0}, + lvarOffset = {5}, lvarLength = {1}, lvarIndex = {1}), + @TADescription(annotation = "TF", type = LOCAL_VARIABLE, + genericLocation = {0, 0, 0, 0, 1, 0, 3, 0, 3, 0, 0, 0}, + lvarOffset = {5}, lvarLength = {1}, lvarIndex = {1}), + @TADescription(annotation = "TG", type = LOCAL_VARIABLE, + genericLocation = {0, 0, 0, 0, 1, 0, 1, 0}, + lvarOffset = {5}, lvarLength = {1}, lvarIndex = {1}), + @TADescription(annotation = "TH", type = LOCAL_VARIABLE, + genericLocation = {0, 0, 0, 0, 1, 0, 1, 0, 3, 0}, + lvarOffset = {5}, lvarLength = {1}, lvarIndex = {1}), + @TADescription(annotation = "TI", type = LOCAL_VARIABLE, + genericLocation = {0, 0, 0, 0, 1, 0, 1, 0, 3, 1}, + lvarOffset = {5}, lvarLength = {1}, lvarIndex = {1}), + @TADescription(annotation = "TJ", type = LOCAL_VARIABLE, + genericLocation = {}, + lvarOffset = {5}, lvarLength = {1}, lvarIndex = {1}), + @TADescription(annotation = "TK", type = LOCAL_VARIABLE, + genericLocation = {0, 0}, + lvarOffset = {5}, lvarLength = {1}, lvarIndex = {1}) + }) + public String testLocal3() { + return "class Outer {\n" + + " class GInner {\n" + + " class GInner2 {}\n" + + "}}\n\n" + + "class Test {\n" + + " void test() { @TA Outer . @TB GInner<@TC List<@TD Object @TE[] @TF[]>>. @TG GInner2<@TH Integer, @TI Object> @TJ[] @TK[] a = null; }\n" + + "}"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = LOCAL_VARIABLE, + genericLocation = {3, 0, 0, 0, 0, 0}, + lvarOffset = {2}, lvarLength = {1}, lvarIndex = {1}), + @TADescription(annotation = "TB", type = LOCAL_VARIABLE, + genericLocation = {3, 0, 0, 0, 0, 0, 1, 0}, + lvarOffset = {2}, lvarLength = {1}, lvarIndex = {1}), + @TADescription(annotation = "TC", type = LOCAL_VARIABLE, + genericLocation = {3, 0, 0, 0, 0, 0, 1, 0, 3, 0}, + lvarOffset = {2}, lvarLength = {1}, lvarIndex = {1}), + @TADescription(annotation = "TD", type = LOCAL_VARIABLE, + genericLocation = {3, 0, 0, 0, 0, 0, 1, 0, 3, 0, 3, 0, 0, 0, 0, 0}, + lvarOffset = {2}, lvarLength = {1}, lvarIndex = {1}), + @TADescription(annotation = "TE", type = LOCAL_VARIABLE, + genericLocation = {3, 0, 0, 0, 0, 0, 1, 0, 3, 0, 3, 0}, + lvarOffset = {2}, lvarLength = {1}, lvarIndex = {1}), + @TADescription(annotation = "TF", type = LOCAL_VARIABLE, + genericLocation = {3, 0, 0, 0, 0, 0, 1, 0, 3, 0, 3, 0, 0, 0}, + lvarOffset = {2}, lvarLength = {1}, lvarIndex = {1}), + @TADescription(annotation = "TG", type = LOCAL_VARIABLE, + genericLocation = {3, 0, 0, 0, 0, 0, 1, 0, 1, 0}, + lvarOffset = {2}, lvarLength = {1}, lvarIndex = {1}), + @TADescription(annotation = "TH", type = LOCAL_VARIABLE, + genericLocation = {3, 0, 0, 0, 0, 0, 1, 0, 1, 0, 3, 0}, + lvarOffset = {2}, lvarLength = {1}, lvarIndex = {1}), + @TADescription(annotation = "TI", type = LOCAL_VARIABLE, + genericLocation = {3, 0, 0, 0, 0, 0, 1, 0, 1, 0, 3, 1}, + lvarOffset = {2}, lvarLength = {1}, lvarIndex = {1}), + @TADescription(annotation = "TJ", type = LOCAL_VARIABLE, + genericLocation = {3, 0}, + lvarOffset = {2}, lvarLength = {1}, lvarIndex = {1}), + @TADescription(annotation = "TK", type = LOCAL_VARIABLE, + genericLocation = {3, 0, 0, 0}, + lvarOffset = {2}, lvarLength = {1}, lvarIndex = {1}) + }) + public String testLocal4() { + return "class Outer {\n" + + " class GInner {\n" + + " class GInner2 {}\n" + + "}}\n\n" + + "class Test {\n" + + " void test() { List<@TA Outer . @TB GInner<@TC List<@TD Object @TE[] @TF[]>>. @TG GInner2<@TH Integer, @TI Object> @TJ[] @TK[]> a = null; }\n" + + "}"; + } + + + // fields + + @TADescriptions({ + @TADescription(annotation = "TA", type = FIELD, + genericLocation = {}), + @TADescription(annotation = "TB", type = FIELD, + genericLocation = {1, 0}) + }) + public String testField1a() { + return "@TA Outer.@TB Inner a;"; + } + + @TADescription(annotation = "TA", type = FIELD, + genericLocation = {}) + public String testField1b() { + return "@TA Outer.Inner a;"; + } + + @TADescription(annotation = "TB", type = FIELD, + genericLocation = {1, 0}) + public String testField1c() { + return "Outer.@TB Inner a;"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = FIELD, + genericLocation = {}), + @TADescription(annotation = "TB", type = FIELD, + genericLocation = {1, 0}) + }) + public String testField2() { + return "@TA GOuter.@TB GInner a;"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = FIELD, + genericLocation = {0, 0, 0, 0}), + @TADescription(annotation = "TB", type = FIELD, + genericLocation = {0, 0, 0, 0, 1, 0}), + @TADescription(annotation = "TC", type = FIELD, + genericLocation = {0, 0, 0, 0, 1, 0, 3, 0}), + @TADescription(annotation = "TD", type = FIELD, + genericLocation = {0, 0, 0, 0, 1, 0, 3, 0, 3, 0, 0, 0, 0, 0}), + @TADescription(annotation = "TE", type = FIELD, + genericLocation = {0, 0, 0, 0, 1, 0, 3, 0, 3, 0}), + @TADescription(annotation = "TF", type = FIELD, + genericLocation = {0, 0, 0, 0, 1, 0, 3, 0, 3, 0, 0, 0}), + @TADescription(annotation = "TG", type = FIELD, + genericLocation = {0, 0, 0, 0, 1, 0, 1, 0}), + @TADescription(annotation = "TH", type = FIELD, + genericLocation = {0, 0, 0, 0, 1, 0, 1, 0, 3, 0}), + @TADescription(annotation = "TI", type = FIELD, + genericLocation = {0, 0, 0, 0, 1, 0, 1, 0, 3, 1}), + @TADescription(annotation = "TJ", type = FIELD), + @TADescription(annotation = "TK", type = FIELD, + genericLocation = {0, 0}) + }) + public String testField3() { + return "class Outer {\n" + + " class GInner {\n" + + " class GInner2 {}\n" + + "}}\n\n" + + "class Test {\n" + + " @TA Outer . @TB GInner<@TC List<@TD Object @TE[] @TF[]>>. @TG GInner2<@TH Integer, @TI Object> @TJ[] @TK[] a;\n" + + "}"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = FIELD, + genericLocation = {3, 0, 0, 0, 0, 0}), + @TADescription(annotation = "TB", type = FIELD, + genericLocation = {3, 0, 0, 0, 0, 0, 1, 0}), + @TADescription(annotation = "TC", type = FIELD, + genericLocation = {3, 0, 0, 0, 0, 0, 1, 0, 3, 0}), + @TADescription(annotation = "TD", type = FIELD, + genericLocation = {3, 0, 0, 0, 0, 0, 1, 0, 3, 0, 3, 0, 0, 0, 0, 0}), + @TADescription(annotation = "TE", type = FIELD, + genericLocation = {3, 0, 0, 0, 0, 0, 1, 0, 3, 0, 3, 0}), + @TADescription(annotation = "TF", type = FIELD, + genericLocation = {3, 0, 0, 0, 0, 0, 1, 0, 3, 0, 3, 0, 0, 0}), + @TADescription(annotation = "TG", type = FIELD, + genericLocation = {3, 0, 0, 0, 0, 0, 1, 0, 1, 0}), + @TADescription(annotation = "TH", type = FIELD, + genericLocation = {3, 0, 0, 0, 0, 0, 1, 0, 1, 0, 3, 0}), + @TADescription(annotation = "TI", type = FIELD, + genericLocation = {3, 0, 0, 0, 0, 0, 1, 0, 1, 0, 3, 1}), + @TADescription(annotation = "TJ", type = FIELD, + genericLocation = {3, 0}), + @TADescription(annotation = "TK", type = FIELD, + genericLocation = {3, 0, 0, 0}) + }) + public String testField4() { + return "class Outer {\n" + + " class GInner {\n" + + " class GInner2 {}\n" + + "}}\n\n" + + "class Test {\n" + + " List<@TA Outer . @TB GInner<@TC List<@TD Object @TE[] @TF[]>>. @TG GInner2<@TH Integer, @TI Object> @TJ[] @TK[]> a;\n" + + "}"; + } + + + // return types + + @TADescriptions({ + @TADescription(annotation = "TA", type = METHOD_RETURN, + genericLocation = {}), + @TADescription(annotation = "TB", type = METHOD_RETURN, + genericLocation = {1, 0}) + }) + public String testReturn1() { + return "@TA Outer.@TB Inner test() { return null; }"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = METHOD_RETURN, + genericLocation = {}), + @TADescription(annotation = "TB", type = METHOD_RETURN, + genericLocation = {1, 0}) + }) + public String testReturn2() { + return "@TA GOuter.@TB GInner test() { return null; }"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = METHOD_RETURN, + genericLocation = {0, 0, 0, 0}), + @TADescription(annotation = "TB", type = METHOD_RETURN, + genericLocation = {0, 0, 0, 0, 1, 0}), + @TADescription(annotation = "TC", type = METHOD_RETURN, + genericLocation = {0, 0, 0, 0, 1, 0, 3, 0}), + @TADescription(annotation = "TD", type = METHOD_RETURN, + genericLocation = {0, 0, 0, 0, 1, 0, 3, 0, 3, 0, 0, 0, 0, 0}), + @TADescription(annotation = "TE", type = METHOD_RETURN, + genericLocation = {0, 0, 0, 0, 1, 0, 3, 0, 3, 0}), + @TADescription(annotation = "TF", type = METHOD_RETURN, + genericLocation = {0, 0, 0, 0, 1, 0, 3, 0, 3, 0, 0, 0}), + @TADescription(annotation = "TG", type = METHOD_RETURN, + genericLocation = {0, 0, 0, 0, 1, 0, 1, 0}), + @TADescription(annotation = "TH", type = METHOD_RETURN, + genericLocation = {0, 0, 0, 0, 1, 0, 1, 0, 3, 0}), + @TADescription(annotation = "TI", type = METHOD_RETURN, + genericLocation = {0, 0, 0, 0, 1, 0, 1, 0, 3, 1}), + @TADescription(annotation = "TJ", type = METHOD_RETURN), + @TADescription(annotation = "TK", type = METHOD_RETURN, + genericLocation = {0, 0}) + }) + public String testReturn3() { + return "class Outer {\n" + + " class GInner {\n" + + " class GInner2 {}\n" + + "}}\n\n" + + "class Test {\n" + + " @TA Outer . @TB GInner<@TC List<@TD Object @TE[] @TF[]>>. @TG GInner2<@TH Integer, @TI Object> @TJ[] @TK[] test() { return null; }\n" + + "}"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = METHOD_RETURN, + genericLocation = {3, 0, 0, 0, 0, 0}), + @TADescription(annotation = "TB", type = METHOD_RETURN, + genericLocation = {3, 0, 0, 0, 0, 0, 1, 0}), + @TADescription(annotation = "TC", type = METHOD_RETURN, + genericLocation = {3, 0, 0, 0, 0, 0, 1, 0, 3, 0}), + @TADescription(annotation = "TD", type = METHOD_RETURN, + genericLocation = {3, 0, 0, 0, 0, 0, 1, 0, 3, 0, 3, 0, 0, 0, 0, 0}), + @TADescription(annotation = "TE", type = METHOD_RETURN, + genericLocation = {3, 0, 0, 0, 0, 0, 1, 0, 3, 0, 3, 0}), + @TADescription(annotation = "TF", type = METHOD_RETURN, + genericLocation = {3, 0, 0, 0, 0, 0, 1, 0, 3, 0, 3, 0, 0, 0}), + @TADescription(annotation = "TG", type = METHOD_RETURN, + genericLocation = {3, 0, 0, 0, 0, 0, 1, 0, 1, 0}), + @TADescription(annotation = "TH", type = METHOD_RETURN, + genericLocation = {3, 0, 0, 0, 0, 0, 1, 0, 1, 0, 3, 0}), + @TADescription(annotation = "TI", type = METHOD_RETURN, + genericLocation = {3, 0, 0, 0, 0, 0, 1, 0, 1, 0, 3, 1}), + @TADescription(annotation = "TJ", type = METHOD_RETURN, + genericLocation = {3, 0}), + @TADescription(annotation = "TK", type = METHOD_RETURN, + genericLocation = {3, 0, 0, 0}) + }) + public String testReturn4() { + return "class Outer {\n" + + " class GInner {\n" + + " class GInner2 {}\n" + + "}}\n\n" + + "class Test {\n" + + " List<@TA Outer . @TB GInner<@TC List<@TD Object @TE[] @TF[]>>. @TG GInner2<@TH Integer, @TI Object> @TJ[] @TK[]> test() { return null; }\n" + + "}"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = METHOD_RETURN, + genericLocation = {3, 0}), + @TADescription(annotation = "TB", type = METHOD_RETURN, + genericLocation = {3, 0, 3, 0}), + @TADescription(annotation = "TC", type = METHOD_RETURN, + genericLocation = {3, 0, 3, 1}), + @TADescription(annotation = "TD", type = METHOD_RETURN, + genericLocation = {3, 0, 3, 1, 3, 0}), + @TADescription(annotation = "TE", type = METHOD_RETURN, + genericLocation = {3, 0, 1, 0}), + @TADescription(annotation = "TF", type = METHOD_RETURN, + genericLocation = {3, 0, 1, 0, 3, 0}), + @TADescription(annotation = "TG", type = METHOD_RETURN, + genericLocation = {3, 0, 1, 0, 3, 0, 3, 0, 0, 0, 0, 0}), + @TADescription(annotation = "TH", type = METHOD_RETURN, + genericLocation = {3, 0, 1, 0, 3, 0, 3, 0}), + @TADescription(annotation = "TI", type = METHOD_RETURN, + genericLocation = {3, 0, 1, 0, 3, 0, 3, 0, 0, 0}), + @TADescription(annotation = "TJ", type = METHOD_RETURN, + genericLocation = {3, 0, 1, 0, 1, 0}), + }) + public String testReturn5() { + return "class GOuter {\n" + + " class GInner {\n" + + " class GInner2 {}\n" + + "}}\n\n" + + "class Test {\n" + + " List<@TA GOuter<@TB String, @TC List<@TD Object>> . @TE GInner<@TF List<@TG Object @TH[] @TI[]>>. @TJ GInner2> test() { return null; }\n" + + "}"; + } + + + // type parameters + + @TADescriptions({ + @TADescription(annotation = "TA", type = METHOD_TYPE_PARAMETER_BOUND, + genericLocation = {}, paramIndex = 0, boundIndex = 0), + @TADescription(annotation = "TB", type = METHOD_TYPE_PARAMETER_BOUND, + genericLocation = {1, 0}, paramIndex = 0, boundIndex = 0) + }) + public String testTypeparam1() { + return " X test() { return null; }"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = METHOD_TYPE_PARAMETER_BOUND, + genericLocation = {}, paramIndex = 0, boundIndex = 0), + @TADescription(annotation = "TB", type = METHOD_TYPE_PARAMETER_BOUND, + genericLocation = {1, 0}, paramIndex = 0, boundIndex = 0) + }) + public String testTypeparam2() { + return ".@TB GInner> X test() { return null; }"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = METHOD_TYPE_PARAMETER_BOUND, + genericLocation = {}, + paramIndex = 0, boundIndex = 0), + @TADescription(annotation = "TB", type = METHOD_TYPE_PARAMETER_BOUND, + genericLocation = {1, 0}, + paramIndex = 0, boundIndex = 0), + @TADescription(annotation = "TC", type = METHOD_TYPE_PARAMETER_BOUND, + genericLocation = {1, 0, 3, 0}, + paramIndex = 0, boundIndex = 0), + @TADescription(annotation = "TD", type = METHOD_TYPE_PARAMETER_BOUND, + genericLocation = {1, 0, 3, 0, 3, 0, 0, 0, 0, 0}, + paramIndex = 0, boundIndex = 0), + @TADescription(annotation = "TE", type = METHOD_TYPE_PARAMETER_BOUND, + genericLocation = {1, 0, 3, 0, 3, 0}, + paramIndex = 0, boundIndex = 0), + @TADescription(annotation = "TF", type = METHOD_TYPE_PARAMETER_BOUND, + genericLocation = {1, 0, 3, 0, 3, 0, 0, 0}, + paramIndex = 0, boundIndex = 0), + @TADescription(annotation = "TG", type = METHOD_TYPE_PARAMETER_BOUND, + genericLocation = {1, 0, 1, 0}, + paramIndex = 0, boundIndex = 0), + @TADescription(annotation = "TH", type = METHOD_TYPE_PARAMETER_BOUND, + genericLocation = {1, 0, 1, 0, 3, 0}, + paramIndex = 0, boundIndex = 0), + @TADescription(annotation = "TI", type = METHOD_TYPE_PARAMETER_BOUND, + genericLocation = {1, 0, 1, 0, 3, 1}, + paramIndex = 0, boundIndex = 0), + }) + public String testTypeparam3() { + return "class Outer {\n" + + " class GInner {\n" + + " class GInner2 {}\n" + + "}}\n\n" + + "class Test {\n" + + " >. @TG GInner2<@TH Integer, @TI Object>> X test() { return null; }\n" + + "}"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = METHOD_TYPE_PARAMETER_BOUND, + genericLocation = {3, 0, 0, 0, 0, 0}, + paramIndex = 0, boundIndex = 1), + @TADescription(annotation = "TB", type = METHOD_TYPE_PARAMETER_BOUND, + genericLocation = {3, 0, 0, 0, 0, 0, 1, 0}, + paramIndex = 0, boundIndex = 1), + @TADescription(annotation = "TC", type = METHOD_TYPE_PARAMETER_BOUND, + genericLocation = {3, 0, 0, 0, 0, 0, 1, 0, 3, 0}, + paramIndex = 0, boundIndex = 1), + @TADescription(annotation = "TD", type = METHOD_TYPE_PARAMETER_BOUND, + genericLocation = {3, 0, 0, 0, 0, 0, 1, 0, 3, 0, 3, 0, 0, 0, 0, 0}, + paramIndex = 0, boundIndex = 1), + @TADescription(annotation = "TE", type = METHOD_TYPE_PARAMETER_BOUND, + genericLocation = {3, 0, 0, 0, 0, 0, 1, 0, 3, 0, 3, 0}, + paramIndex = 0, boundIndex = 1), + @TADescription(annotation = "TF", type = METHOD_TYPE_PARAMETER_BOUND, + genericLocation = {3, 0, 0, 0, 0, 0, 1, 0, 3, 0, 3, 0, 0, 0}, + paramIndex = 0, boundIndex = 1), + @TADescription(annotation = "TG", type = METHOD_TYPE_PARAMETER_BOUND, + genericLocation = {3, 0, 0, 0, 0, 0, 1, 0, 1, 0}, + paramIndex = 0, boundIndex = 1), + @TADescription(annotation = "TH", type = METHOD_TYPE_PARAMETER_BOUND, + genericLocation = {3, 0, 0, 0, 0, 0, 1, 0, 1, 0, 3, 0}, + paramIndex = 0, boundIndex = 1), + @TADescription(annotation = "TI", type = METHOD_TYPE_PARAMETER_BOUND, + genericLocation = {3, 0, 0, 0, 0, 0, 1, 0, 1, 0, 3, 1}, + paramIndex = 0, boundIndex = 1), + @TADescription(annotation = "TJ", type = METHOD_TYPE_PARAMETER_BOUND, + genericLocation = {3, 0}, + paramIndex = 0, boundIndex = 1), + @TADescription(annotation = "TK", type = METHOD_TYPE_PARAMETER_BOUND, + genericLocation = {3, 0, 0, 0}, + paramIndex = 0, boundIndex = 1) + }) + public String testTypeparam4() { + return "class Outer {\n" + + " class GInner {\n" + + " class GInner2 {}\n" + + "}}\n\n" + + "class Test {\n" + + " >. @TG GInner2<@TH Integer, @TI Object> @TJ[] @TK[]>> X test() { return null; }\n" + + "}"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = METHOD_TYPE_PARAMETER_BOUND, + genericLocation = {3, 0}, paramIndex = 0, boundIndex = 1), + @TADescription(annotation = "TB", type = METHOD_TYPE_PARAMETER_BOUND, + genericLocation = {3, 0, 3, 0}, paramIndex = 0, boundIndex = 1), + @TADescription(annotation = "TC", type = METHOD_TYPE_PARAMETER_BOUND, + genericLocation = {3, 0, 3, 1}, paramIndex = 0, boundIndex = 1), + @TADescription(annotation = "TD", type = METHOD_TYPE_PARAMETER_BOUND, + genericLocation = {3, 0, 3, 1, 3, 0}, paramIndex = 0, boundIndex = 1), + @TADescription(annotation = "TE", type = METHOD_TYPE_PARAMETER_BOUND, + genericLocation = {3, 0, 1, 0}, paramIndex = 0, boundIndex = 1), + @TADescription(annotation = "TF", type = METHOD_TYPE_PARAMETER_BOUND, + genericLocation = {3, 0, 1, 0, 3, 0}, paramIndex = 0, boundIndex = 1), + @TADescription(annotation = "TG", type = METHOD_TYPE_PARAMETER_BOUND, + genericLocation = {3, 0, 1, 0, 3, 0, 3, 0, 0, 0, 0, 0}, paramIndex = 0, boundIndex = 1), + @TADescription(annotation = "TH", type = METHOD_TYPE_PARAMETER_BOUND, + genericLocation = {3, 0, 1, 0, 3, 0, 3, 0}, paramIndex = 0, boundIndex = 1), + @TADescription(annotation = "TI", type = METHOD_TYPE_PARAMETER_BOUND, + genericLocation = {3, 0, 1, 0, 3, 0, 3, 0, 0, 0}, paramIndex = 0, boundIndex = 1), + @TADescription(annotation = "TJ", type = METHOD_TYPE_PARAMETER_BOUND, + genericLocation = {3, 0, 1, 0, 1, 0}, paramIndex = 0, boundIndex = 1), + }) + public String testTypeparam5() { + return "class GOuter {\n" + + " class GInner {\n" + + " class GInner2 {}\n" + + "}}\n\n" + + "class Test {\n" + + " > . @TE GInner<@TF List<@TG Object @TH[] @TI[]>>. @TJ GInner2>> X test() { return null; }\n" + + "}"; + } + + @TADescription(annotation = "TA", type = FIELD, + genericLocation = {3, 0, 1, 0}) + public String testUses1a() { + return "class Test { class Inner {} List<@TA Inner> f; }"; + } + + @TADescription(annotation = "TA", type = FIELD, + genericLocation = {3, 0}) + public String testUses1b() { + return "class Test { class Inner {} List<@TA Test.Inner> f; }"; + } + + @TADescription(annotation = "TA", type = FIELD, + genericLocation = {3, 0, 1, 0, 1, 0}) + @TestClass("Test$Inner") + public String testUses2a() { + return "class Test { class Inner { class Inner2{} List<@TA Inner2> f; }}"; + } + + @TADescription(annotation = "TA", type = FIELD, + genericLocation = {3, 0, 1, 0}) + @TestClass("Test$Inner") + public String testUses2b() { + return "class Test { class Inner { class Inner2{} List<@TA Inner.Inner2> f; }}"; + } + + @TADescription(annotation = "TA", type = FIELD, + genericLocation = {3, 0, 1, 0, 1, 0}) + @TestClass("Test$Inner") + public String testUses2c() { + return "class Test { class Inner { class Inner2{} List f; }}"; + } + + @TADescription(annotation = "TA", type = FIELD, + genericLocation = {3, 0}) + @TestClass("Test$Inner") + public String testUses2d() { + return "class Test{ class Inner { class Inner2{} List<@TA Test.Inner.Inner2> f; }}"; + } + + @TADescription(annotation = "TA", type = FIELD, + genericLocation = {3, 0, 1, 0}) + @TestClass("Test$Inner") + public String testUses2e() { + return "class Test { class Inner { class Inner2{} List f; }}"; + } + + @TADescription(annotation = "TA", type = FIELD, + genericLocation = {3, 0, 1, 0, 1, 0}) + @TestClass("Test$Inner") + public String testUses2f() { + return "class Test { class Inner { class Inner2{} List f; }}"; + } + + @TADescription(annotation = "TA", type = FIELD, + genericLocation = {3, 0, 1, 0, 1, 0}) + @TestClass("Test$Inner") + public String testUses3a() { + return "class Test { class Inner { class Inner2{}\n" + + " List f; }}"; + } + + @TADescription(annotation = "TA", type = FIELD, + genericLocation = {3, 0, 1, 0}) + @TestClass("Test$Inner") + public String testUses3b() { + return "class Test { class Inner { class Inner2{}\n" + + " List f; }}"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = FIELD, + genericLocation = {}), + @TADescription(annotation = "TB", type = FIELD, + genericLocation = {3, 0}) + }) + public String testUses4() { + return "class Test { static class TInner {}\n" + + " @TA TInner f; \n" + + " List<@TB TInner> g; }"; + } + + @TADescription(annotation = "TA", type = FIELD, + genericLocation = {3, 0, 1, 0, 3, 1}) + @TestClass("Test$Inner") + public String testUses3c() { + return "class Test { class Inner { class Inner2{}\n" + + " List.Inner2> f; }}"; + } + + @TADescription(annotation = "TA", type = METHOD_FORMAL_PARAMETER, paramIndex=0) + public String testFullyQualified1() { + return "void testme(java.security.@TA ProtectionDomain protectionDomain) {}"; + } + + @TADescription(annotation = "TA", type = METHOD_FORMAL_PARAMETER, paramIndex=0, + genericLocation = {3, 0}) + public String testFullyQualified2() { + return "void testme(List protectionDomain) {}"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = LOCAL_VARIABLE, + genericLocation = {}, + lvarOffset = ReferenceInfoUtil.IGNORE_VALUE, + lvarLength = ReferenceInfoUtil.IGNORE_VALUE, + lvarIndex = ReferenceInfoUtil.IGNORE_VALUE), + @TADescription(annotation = "TB", type = LOCAL_VARIABLE, + genericLocation = {1, 0}, + lvarOffset = ReferenceInfoUtil.IGNORE_VALUE, + lvarLength = ReferenceInfoUtil.IGNORE_VALUE, + lvarIndex = ReferenceInfoUtil.IGNORE_VALUE), + @TADescription(annotation = "TC", type = LOCAL_VARIABLE, + // Only classes count, not methods. + genericLocation = {1, 0, 1, 0}, + lvarOffset = ReferenceInfoUtil.IGNORE_VALUE, + lvarLength = ReferenceInfoUtil.IGNORE_VALUE, + lvarIndex = ReferenceInfoUtil.IGNORE_VALUE), + }) + @TestClass("Outer$Inner") + public String testMethodNesting1() { + return "class Outer {\n" + + " class Inner {\n" + + " void foo() {\n" + + " class MInner {}\n" + + " @TA Outer . @TB Inner l1 = null;\n" + + " @TC MInner l2 = null;\n" + + " }\n" + + "}}\n"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = NEW, + genericLocation = {}, + offset = 0), + @TADescription(annotation = "TB", type = NEW, + genericLocation = {1, 0}, + offset = 0), + @TADescription(annotation = "TC", type = NEW, + // Only classes count, not methods. + genericLocation = {1, 0, 1, 0}, + offset = 12), + }) + @TestClass("Outer$Inner") + public String testMethodNesting2() { + return "class Outer {\n" + + " class Inner {\n" + + " void foo() {\n" + + " class MInner {}\n" + + " Object o1 = new @TA Outer . @TB Inner();" + + " Object o2 = new @TC MInner();\n" + + " }\n" + + "}}\n"; + } +} diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/NewObjects.java b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/NewObjects.java new file mode 100644 index 00000000000..b56dbb74d23 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/NewObjects.java @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2009 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. + * + * 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. + */ + +import static com.sun.tools.classfile.TypeAnnotation.TargetType.*; + +/* + * @test + * @summary Test population of reference info for new object creations + * @compile -g Driver.java ReferenceInfoUtil.java NewObjects.java + * @run main Driver NewObjects + */ +public class NewObjects { + + @TADescription(annotation = "TA", type = NEW, offset = ReferenceInfoUtil.IGNORE_VALUE) + public String returnObject() { + return "Object returnObject() { return new @TA String(); }"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = NEW, offset = ReferenceInfoUtil.IGNORE_VALUE), + @TADescription(annotation = "TB", type = NEW, + genericLocation = { 3, 0 }, offset = ReferenceInfoUtil.IGNORE_VALUE) + }) + public String returnObjectGeneric() { + return "Object returnObjectGeneric() { return new @TA ArrayList<@TB String>(); }"; + } + + @TADescription(annotation = "TA", type = NEW, offset = ReferenceInfoUtil.IGNORE_VALUE) + public String initObject() { + return "void initObject() { Object a = new @TA String(); }"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = NEW, offset = ReferenceInfoUtil.IGNORE_VALUE), + @TADescription(annotation = "TB", type = NEW, + genericLocation = { 3, 0 }, offset = ReferenceInfoUtil.IGNORE_VALUE), + @TADescription(annotation = "TC", type = NEW, + genericLocation = { 3, 1 }, offset = ReferenceInfoUtil.IGNORE_VALUE) + }) + public String initObjectGeneric() { + return "void initObjectGeneric() { Object a = new @TA HashMap<@TB String, @TC String>(); }"; + } + + @TADescription(annotation = "TA", type = NEW, offset = ReferenceInfoUtil.IGNORE_VALUE) + public String eqtestObject() { + return "void eqtestObject() { if (null == new @TA String()); }"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = NEW, offset = ReferenceInfoUtil.IGNORE_VALUE), + @TADescription(annotation = "TB", type = NEW, + genericLocation = { 3, 0 }, offset = ReferenceInfoUtil.IGNORE_VALUE) + }) + public String eqtestObjectGeneric() { + return "void eqtestObjectGeneric() { if (null == new @TA ArrayList<@TB String >()); }"; + } + +} diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/ReferenceInfoUtil.java b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/ReferenceInfoUtil.java new file mode 100644 index 00000000000..0a94ee07de3 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/ReferenceInfoUtil.java @@ -0,0 +1,332 @@ +/* + * Copyright (c) 2009 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. + * + * 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. + */ + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +import com.sun.tools.classfile.Attribute; +import com.sun.tools.classfile.ClassFile; +import com.sun.tools.classfile.TypeAnnotation; +import com.sun.tools.classfile.Field; +import com.sun.tools.classfile.Method; +import com.sun.tools.classfile.RuntimeTypeAnnotations_attribute; +import com.sun.tools.classfile.ConstantPool.InvalidIndex; +import com.sun.tools.classfile.ConstantPool.UnexpectedEntry; + +public class ReferenceInfoUtil { + + public static final int IGNORE_VALUE = -321; + + public static List extendedAnnotationsOf(ClassFile cf) { + List annos = new ArrayList(); + findAnnotations(cf, annos); + return annos; + } + + /////////////////// Extract type annotations ////////////////// + private static void findAnnotations(ClassFile cf, List annos) { + findAnnotations(cf, Attribute.RuntimeVisibleTypeAnnotations, annos); + findAnnotations(cf, Attribute.RuntimeInvisibleTypeAnnotations, annos); + + for (Field f : cf.fields) { + findAnnotations(cf, f, annos); + } + for (Method m: cf.methods) { + findAnnotations(cf, m, annos); + } + } + + private static void findAnnotations(ClassFile cf, Method m, List annos) { + findAnnotations(cf, m, Attribute.RuntimeVisibleTypeAnnotations, annos); + findAnnotations(cf, m, Attribute.RuntimeInvisibleTypeAnnotations, annos); + } + + private static void findAnnotations(ClassFile cf, Field m, List annos) { + findAnnotations(cf, m, Attribute.RuntimeVisibleTypeAnnotations, annos); + findAnnotations(cf, m, Attribute.RuntimeInvisibleTypeAnnotations, annos); + } + + // test the result of Attributes.getIndex according to expectations + // encoded in the method's name + private static void findAnnotations(ClassFile cf, String name, List annos) { + int index = cf.attributes.getIndex(cf.constant_pool, name); + if (index != -1) { + Attribute attr = cf.attributes.get(index); + assert attr instanceof RuntimeTypeAnnotations_attribute; + RuntimeTypeAnnotations_attribute tAttr = (RuntimeTypeAnnotations_attribute)attr; + annos.addAll(Arrays.asList(tAttr.annotations)); + } + } + + // test the result of Attributes.getIndex according to expectations + // encoded in the method's name + private static void findAnnotations(ClassFile cf, Method m, String name, List annos) { + int index = m.attributes.getIndex(cf.constant_pool, name); + if (index != -1) { + Attribute attr = m.attributes.get(index); + assert attr instanceof RuntimeTypeAnnotations_attribute; + RuntimeTypeAnnotations_attribute tAttr = (RuntimeTypeAnnotations_attribute)attr; + annos.addAll(Arrays.asList(tAttr.annotations)); + } + } + + // test the result of Attributes.getIndex according to expectations + // encoded in the method's name + private static void findAnnotations(ClassFile cf, Field m, String name, List annos) { + int index = m.attributes.getIndex(cf.constant_pool, name); + if (index != -1) { + Attribute attr = m.attributes.get(index); + assert attr instanceof RuntimeTypeAnnotations_attribute; + RuntimeTypeAnnotations_attribute tAttr = (RuntimeTypeAnnotations_attribute)attr; + annos.addAll(Arrays.asList(tAttr.annotations)); + } + } + + /////////////////// TA Position Builder /////////////////////// + /* TODO: comment out this dead code. Was this unfinished code that was + * supposed to be used somewhere? The tests pass without this. + private static class TAPositionBuilder { + private TypeAnnotation.Position pos = new TypeAnnotation.Position(); + + private TAPositionBuilder() { } + + public TypeAnnotation.Position build() { return pos; } + + public static TAPositionBuilder ofType(TypeAnnotation.TargetType type) { + TAPositionBuilder builder = new TAPositionBuilder(); + builder.pos.type = type; + return builder; + } + + public TAPositionBuilder atOffset(int offset) { + switch (pos.type) { + // type cast + case TYPECAST: + // instanceof + case INSTANCEOF: + // new expression + case NEW: + pos.offset = offset; + break; + default: + throw new IllegalArgumentException("invalid field for given type: " + pos.type); + } + return this; + } + + public TAPositionBuilder atLocalPosition(int offset, int length, int index) { + switch (pos.type) { + // local variable + case LOCAL_VARIABLE: + pos.lvarOffset = new int[] { offset }; + pos.lvarLength = new int[] { length }; + pos.lvarIndex = new int[] { index }; + break; + default: + throw new IllegalArgumentException("invalid field for given type: " + pos.type); + } + return this; + } + + public TAPositionBuilder atParameterIndex(int index) { + switch (pos.type) { + // type parameters + case CLASS_TYPE_PARAMETER: + case METHOD_TYPE_PARAMETER: + // method parameter + case METHOD_FORMAL_PARAMETER: + pos.parameter_index = index; + break; + default: + throw new IllegalArgumentException("invalid field for given type: " + pos.type); + } + return this; + } + + public TAPositionBuilder atParamBound(int param, int bound) { + switch (pos.type) { + // type parameters bounds + case CLASS_TYPE_PARAMETER_BOUND: + case METHOD_TYPE_PARAMETER_BOUND: + pos.parameter_index = param; + pos.bound_index = bound; + break; + default: + throw new IllegalArgumentException("invalid field for given type: " + pos.type); + } + return this; + } + + public TAPositionBuilder atWildcardPosition(TypeAnnotation.Position pos) { + switch (pos.type) { + // wildcards + case WILDCARD_BOUND: + pos.wildcard_position = pos; + break; + default: + throw new IllegalArgumentException("invalid field for given type: " + pos.type); + } + return this; + } + + public TAPositionBuilder atTypeIndex(int index) { + switch (pos.type) { + // class extends or implements clauses + case CLASS_EXTENDS: + // throws + case THROWS: + pos.type_index = index; + break; + default: + throw new IllegalArgumentException("invalid field for given type: " + pos.type); + } + return this; + } + + public TAPositionBuilder atOffsetWithIndex(int offset, int index) { + switch (pos.type) { + // method type argument: wasn't specified + case NEW_TYPE_ARGUMENT: + case METHOD_TYPE_ARGUMENT: + pos.offset = offset; + pos.type_index = index; + break; + default: + throw new IllegalArgumentException("invalid field for given type: " + pos.type); + } + return this; + } + + public TAPositionBuilder atGenericLocation(Integer ...loc) { + pos.location = Arrays.asList(loc); + pos.type = pos.type.getGenericComplement(); + return this; + } + }*/ + + /////////////////////// Equality testing ///////////////////// + private static boolean areEquals(int a, int b) { + return a == b || a == IGNORE_VALUE || b == IGNORE_VALUE; + } + + private static boolean areEquals(int[] a, int[] a2) { + if (a==a2) + return true; + if (a==null || a2==null) + return false; + + int length = a.length; + if (a2.length != length) + return false; + + for (int i=0; i annotations, ClassFile cf) throws InvalidIndex, UnexpectedEntry { + String properName = "L" + name + ";"; + for (TypeAnnotation anno : annotations) { + String actualName = cf.constant_pool.getUTF8Value(anno.annotation.type_index); + if (properName.equals(actualName)) + return anno; + } + return null; + } + + public static boolean compare(Map expectedAnnos, + List actualAnnos, ClassFile cf) throws InvalidIndex, UnexpectedEntry { + if (actualAnnos.size() != expectedAnnos.size()) { + throw new ComparisionException("Wrong number of annotations", + expectedAnnos, + actualAnnos); + } + + for (Map.Entry e : expectedAnnos.entrySet()) { + String aName = e.getKey(); + TypeAnnotation.Position expected = e.getValue(); + TypeAnnotation actual = findAnnotation(aName, actualAnnos, cf); + if (actual == null) + throw new ComparisionException("Expected annotation not found: " + aName); + + // TODO: you currently get an exception if the test case does not use all necessary + // annotation attributes, e.g. forgetting the offset for a local variable. + // It would be nicer to give an understandable warning instead. + if (!areEquals(expected, actual.position)) { + throw new ComparisionException("Unexpected position for annotation : " + aName + + "\n Expected: " + expected.toString() + + "\n Found: " + actual.position.toString()); + } + } + return true; + } +} + +class ComparisionException extends RuntimeException { + private static final long serialVersionUID = -3930499712333815821L; + + public final Map expected; + public final List found; + + public ComparisionException(String message) { + this(message, null, null); + } + + public ComparisionException(String message, Map expected, List found) { + super(message); + this.expected = expected; + this.found = found; + } + + public String toString() { + String str = super.toString(); + if (expected != null && found != null) { + str += "\n\tExpected: " + expected.size() + " annotations; but found: " + found.size() + " annotations\n" + + " Expected: " + expected + + "\n Found: " + found; + } + return str; + } +} diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/RepeatingTypeAnnotations.java b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/RepeatingTypeAnnotations.java new file mode 100644 index 00000000000..2755b4871c7 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/RepeatingTypeAnnotations.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2012 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. + * + * 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. + */ + +import static com.sun.tools.classfile.TypeAnnotation.TargetType.*; + +/* + * @test + * @summary Test population of reference info for repeating type annotations + * @compile -g Driver.java ReferenceInfoUtil.java RepeatingTypeAnnotations.java + * @run main Driver RepeatingTypeAnnotations + * @author Werner Dietl + */ +public class RepeatingTypeAnnotations { + // Field types + @TADescription(annotation = "RTAs", type = FIELD) + public String fieldAsPrimitive() { + return "@RTA @RTA int test;"; + } + + // Method returns + @TADescription(annotation = "RTAs", type = METHOD_RETURN) + public String methodReturn1() { + return "@RTA @RTA int test() { return 0; }"; + } + + @TADescription(annotation = "RTAs", type = METHOD_RETURN) + public String methodReturn2() { + return "@RTAs({@RTA, @RTA}) int test() { return 0; }"; + } + + // Method parameters + @TADescriptions({ + @TADescription(annotation = "RTAs", type = METHOD_FORMAL_PARAMETER, + paramIndex = 0), + @TADescription(annotation = "RTBs", type = METHOD_FORMAL_PARAMETER, + paramIndex = 0, + genericLocation = { 3, 0 }) + }) + public String methodParam1() { + return "void m(@RTA @RTA List<@RTB @RTB String> p) {}"; + } + + @TADescriptions({ + @TADescription(annotation = "RTAs", type = METHOD_FORMAL_PARAMETER, + paramIndex = 0), + @TADescription(annotation = "RTBs", type = METHOD_FORMAL_PARAMETER, + paramIndex = 0, + genericLocation = { 3, 0 }) + }) + public String methodParam2() { + return "void m(@RTAs({@RTA, @RTA}) List<@RTBs({@RTB, @RTB}) String> p) {}"; + } + + // TODO: test that all other locations work with repeated type annotations. +} diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/TypeCasts.java b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/TypeCasts.java new file mode 100644 index 00000000000..c77dcdc5857 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/TypeCasts.java @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2009 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. + * + * 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. + */ + +import static com.sun.tools.classfile.TypeAnnotation.TargetType.*; + +/* + * @test + * @summary Test population of reference info for type casts + * @compile -g Driver.java ReferenceInfoUtil.java TypeCasts.java + * @run main Driver TypeCasts + */ +public class TypeCasts { + + @TADescription(annotation = "TA", type = CAST, offset = ReferenceInfoUtil.IGNORE_VALUE) + public String returnObject() { + return "Object returnObject() { return (@TA String)null; }"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = CAST, offset = ReferenceInfoUtil.IGNORE_VALUE), + @TADescription(annotation = "TB", type = CAST, + genericLocation = { 0, 0 }, offset = ReferenceInfoUtil.IGNORE_VALUE), + @TADescription(annotation = "TC", type = CAST, + genericLocation = { 0, 0, 0, 0 }, offset = ReferenceInfoUtil.IGNORE_VALUE) + }) + public String returnObjectArray() { + return "Object returnObjectArray() { return (@TC String @TA [] @TB [])null; }"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = CAST, offset = ReferenceInfoUtil.IGNORE_VALUE), + @TADescription(annotation = "TB", type = CAST, + genericLocation = { 3, 0 }, offset = ReferenceInfoUtil.IGNORE_VALUE) + }) + public String returnObjectGeneric() { + return "Object returnObjectGeneric() { return (@TA List<@TB String>)null; }"; + } + + @TADescription(annotation = "TA", type = CAST, offset = ReferenceInfoUtil.IGNORE_VALUE) + public String returnPrim() { + return "Object returnPrim() { return (@TA int)0; }"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = CAST, offset = ReferenceInfoUtil.IGNORE_VALUE), + @TADescription(annotation = "TB", type = CAST, + genericLocation = { 0, 0 }, offset = ReferenceInfoUtil.IGNORE_VALUE) + }) + public String returnPrimArray() { + return "Object returnPrimArray() { return (@TB int @TA [])null; }"; + } + + @TADescription(annotation = "TA", type = CAST, offset = ReferenceInfoUtil.IGNORE_VALUE) + public String initObject() { + return "void initObject() { Object a = (@TA String)null; }"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = CAST, offset = ReferenceInfoUtil.IGNORE_VALUE), + @TADescription(annotation = "TB", type = CAST, + genericLocation = { 0, 0 }, offset = ReferenceInfoUtil.IGNORE_VALUE) + }) + public String initObjectArray() { + return "void initObjectArray() { Object a = (@TB String @TA [])null; }"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = CAST, offset = ReferenceInfoUtil.IGNORE_VALUE), + @TADescription(annotation = "TB", type = CAST, + genericLocation = { 3, 0 }, offset = ReferenceInfoUtil.IGNORE_VALUE) + }) + public String initObjectGeneric() { + return "void initObjectGeneric() { Object a = (@TA List<@TB String>)null; }"; + } + + @TADescription(annotation = "TA", type = CAST, offset = ReferenceInfoUtil.IGNORE_VALUE) + public String initPrim() { + return "void initPrim() { Object a = (@TA int)0; }"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = CAST, offset = ReferenceInfoUtil.IGNORE_VALUE), + @TADescription(annotation = "TB", type = CAST, + genericLocation = { 0, 0 }, offset = ReferenceInfoUtil.IGNORE_VALUE) + }) + public String initPrimArray() { + return "void initPrimArray() { Object a = (@TB int @TA [])null; }"; + } + + @TADescription(annotation = "TA", type = CAST, offset = ReferenceInfoUtil.IGNORE_VALUE) + public String eqtestObject() { + return "void eqtestObject() { if (null == (@TA String)null); }"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = CAST, offset = ReferenceInfoUtil.IGNORE_VALUE), + @TADescription(annotation = "TB", type = CAST, + genericLocation = { 0, 0 }, offset = ReferenceInfoUtil.IGNORE_VALUE) + }) + public String eqtestObjectArray() { + return "void eqtestObjectArray() { if (null == (@TB String @TA [])null); }"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = CAST, offset = ReferenceInfoUtil.IGNORE_VALUE), + @TADescription(annotation = "TB", type = CAST, + genericLocation = { 3, 0 }, offset = ReferenceInfoUtil.IGNORE_VALUE) + }) + public String eqtestObjectGeneric() { + return "void eqtestObjectGeneric() { if (null == (@TA List<@TB String >)null); }"; + } + + @TADescription(annotation = "TA", type = CAST, offset = ReferenceInfoUtil.IGNORE_VALUE) + // compiler optimizes away compile time constants casts + public String eqtestPrim() { + return "void eqtestPrim(int a) { if (0 == (@TA int)a); }"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = CAST, offset = ReferenceInfoUtil.IGNORE_VALUE), + @TADescription(annotation = "TB", type = CAST, + genericLocation = { 0, 0 }, offset = ReferenceInfoUtil.IGNORE_VALUE) + }) + public String eqtestPrimArray() { + return "void eqtestPrimArray() { if (null == (@TB int @TA [])null); }"; + } + +} diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/TypeTests.java b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/TypeTests.java new file mode 100644 index 00000000000..5aa07b88db6 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/TypeTests.java @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2009 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. + * + * 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. + */ + +import static com.sun.tools.classfile.TypeAnnotation.TargetType.*; + +/* + * @test + * @summary Test population of reference info for class literals + * @compile -g Driver.java ReferenceInfoUtil.java TypeTests.java + * @run main Driver TypeTests + */ +public class TypeTests { + + @TADescription(annotation = "TA", type = INSTANCEOF, offset = ReferenceInfoUtil.IGNORE_VALUE) + public String returnObject() { + return "Object returnObject() { return null instanceof @TA String; }"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = INSTANCEOF, offset = ReferenceInfoUtil.IGNORE_VALUE), + @TADescription(annotation = "TB", type = INSTANCEOF, + genericLocation = { 0, 0 }, offset = ReferenceInfoUtil.IGNORE_VALUE), + @TADescription(annotation = "TC", type = INSTANCEOF, + genericLocation = { 0, 0, 0, 0 }, offset = ReferenceInfoUtil.IGNORE_VALUE) + }) + public String returnObjectArray() { + return "Object returnObjectArray() { return null instanceof @TC String @TA [] @TB []; }"; + } + + // no type test for primitives + + @TADescriptions({ + @TADescription(annotation = "TA", type = INSTANCEOF, offset = ReferenceInfoUtil.IGNORE_VALUE), + @TADescription(annotation = "TB", type = INSTANCEOF, + genericLocation = { 0, 0 }, offset = ReferenceInfoUtil.IGNORE_VALUE), + @TADescription(annotation = "TC", type = INSTANCEOF, + genericLocation = { 0, 0, 0, 0 }, offset = ReferenceInfoUtil.IGNORE_VALUE) + }) + public String returnPrimArray() { + return "Object returnPrimArray() { return null instanceof @TC int @TA [] @TB []; }"; + } + + // no void + // no void array + + @TADescription(annotation = "TA", type = INSTANCEOF, offset = ReferenceInfoUtil.IGNORE_VALUE) + public String initObject() { + return "void initObject() { Object a = null instanceof @TA String; }"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = INSTANCEOF, offset = ReferenceInfoUtil.IGNORE_VALUE), + @TADescription(annotation = "TB", type = INSTANCEOF, + genericLocation = { 0, 0 }, offset = ReferenceInfoUtil.IGNORE_VALUE), + @TADescription(annotation = "TC", type = INSTANCEOF, + genericLocation = { 0, 0, 0, 0 }, offset = ReferenceInfoUtil.IGNORE_VALUE) + }) + public String initObjectArray() { + return "void initObjectArray() { Object a = null instanceof @TC String @TA [] @TB []; }"; + } + + // no primitive instanceof + + @TADescriptions({ + @TADescription(annotation = "TA", type = INSTANCEOF, offset = ReferenceInfoUtil.IGNORE_VALUE), + @TADescription(annotation = "TB", type = INSTANCEOF, + genericLocation = { 0, 0 }, offset = ReferenceInfoUtil.IGNORE_VALUE), + @TADescription(annotation = "TC", type = INSTANCEOF, + genericLocation = { 0, 0, 0, 0 }, offset = ReferenceInfoUtil.IGNORE_VALUE) + }) + public String initPrimArray() { + return "void initPrimArray() { Object a = null instanceof @TC int @TA [] @TB []; }"; + } + + // no void + // no void array + + @TADescription(annotation = "TA", type = INSTANCEOF, offset = ReferenceInfoUtil.IGNORE_VALUE) + public String eqtestObject() { + return "void eqtestObject() { if (true == (null instanceof @TA String)); }"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = INSTANCEOF, offset = ReferenceInfoUtil.IGNORE_VALUE), + @TADescription(annotation = "TB", type = INSTANCEOF, + genericLocation = { 0, 0 }, offset = ReferenceInfoUtil.IGNORE_VALUE), + @TADescription(annotation = "TC", type = INSTANCEOF, + genericLocation = { 0, 0, 0, 0 }, offset = ReferenceInfoUtil.IGNORE_VALUE) + }) + public String eqtestObjectArray() { + return "void eqtestObjectArray() { if (true == (null instanceof @TC String @TA [] @TB [])); }"; + } + + // no primitives + + @TADescriptions({ + @TADescription(annotation = "TA", type = INSTANCEOF, offset = ReferenceInfoUtil.IGNORE_VALUE), + @TADescription(annotation = "TB", type = INSTANCEOF, + genericLocation = { 0, 0 }, offset = ReferenceInfoUtil.IGNORE_VALUE), + @TADescription(annotation = "TC", type = INSTANCEOF, + genericLocation = { 0, 0, 0, 0 }, offset = ReferenceInfoUtil.IGNORE_VALUE) + }) + public String eqtestPrimArray() { + return "void eqtestPrimArray() { if (true == (null instanceof @TC int @TA [] @TB [])); }"; + } + + // no void + // no void array + +} diff --git a/langtools/test/tools/javac/api/EndPositions.java b/langtools/test/tools/javac/api/EndPositions.java index 1971a7dd5ac..f791cc7666b 100644 --- a/langtools/test/tools/javac/api/EndPositions.java +++ b/langtools/test/tools/javac/api/EndPositions.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2013, 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 @@ -28,11 +28,7 @@ * an annotation processor is present */ -import com.sun.source.tree.ClassTree; -import com.sun.source.tree.CompilationUnitTree; -import com.sun.source.tree.Tree; import com.sun.source.util.JavacTask; -import com.sun.source.util.Trees; import java.io.IOException; import java.net.URI; import java.util.Arrays; @@ -72,16 +68,17 @@ public class EndPositions extends AbstractProcessor { JavacTask task = (JavacTask)javac.getTask(null, null, diagnostics, options, null, compilationUnits); boolean valid = task.call(); if (valid) - throw new AssertionError("Compilation succeeded unexpectedly"); + throw new AssertionError("Expected one error, but found none."); List> errors = diagnostics.getDiagnostics(); if (errors.size() != 1) - throw new AssertionError("Expected one error only, but found " + errors.size() + " errors"); + throw new AssertionError("Expected one error only, but found " + errors.size() + "; errors: " + errors); Diagnostic error = errors.get(0); if (error.getStartPosition() >= error.getEndPosition()) throw new AssertionError("Expected start to be less than end position: start [" + - error.getStartPosition() + "], end [" + error.getEndPosition() +"]"); + error.getStartPosition() + "], end [" + error.getEndPosition() +"]" + + "; diagnostics code: " + error.getCode()); System.out.println("All is good!"); } diff --git a/langtools/test/tools/javac/diags/CheckResourceKeys.java b/langtools/test/tools/javac/diags/CheckResourceKeys.java index 4c10b1a9878..bb9e10bd7cf 100644 --- a/langtools/test/tools/javac/diags/CheckResourceKeys.java +++ b/langtools/test/tools/javac/diags/CheckResourceKeys.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2013, 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 @@ -200,6 +200,7 @@ public class CheckResourceKeys { Set needToInvestigate = new TreeSet(Arrays.asList( + "compiler.misc.fatal.err.cant.close.loader", // Supressed by JSR308 "compiler.err.cant.read.file", // UNUSED "compiler.err.illegal.self.ref", // UNUSED "compiler.err.io.exception", // UNUSED diff --git a/langtools/test/tools/javac/diags/examples.not-yet.txt b/langtools/test/tools/javac/diags/examples.not-yet.txt index 3583063294e..437d61d2406 100644 --- a/langtools/test/tools/javac/diags/examples.not-yet.txt +++ b/langtools/test/tools/javac/diags/examples.not-yet.txt @@ -48,6 +48,7 @@ compiler.misc.bad.enclosing.class # bad class file compiler.misc.bad.enclosing.method # bad class file compiler.misc.bad.runtime.invisible.param.annotations # bad class file compiler.misc.bad.signature # bad class file +compiler.misc.bad.type.annotation.value compiler.misc.base.membership # UNUSED compiler.misc.ccf.found.later.version compiler.misc.ccf.unrecognized.attribute diff --git a/langtools/test/tools/javac/diags/examples/CantAnnotateNestedType.java b/langtools/test/tools/javac/diags/examples/CantAnnotateNestedType.java new file mode 100644 index 00000000000..30d4572e601 --- /dev/null +++ b/langtools/test/tools/javac/diags/examples/CantAnnotateNestedType.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2012, 2013, 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. + * + * 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. + */ + +// key: compiler.err.cant.annotate.nested.type + +import java.lang.annotation.*; + +class CantAnnotateStaticClass { + @Target(ElementType.TYPE_USE) + @interface A {} + + interface Outer { + interface Inner {} + } + + // Error: + @A Outer.Inner f; + + // OK: + @A Outer g; +} diff --git a/langtools/test/tools/javac/diags/examples/CantAnnotateStaticClass.java b/langtools/test/tools/javac/diags/examples/CantAnnotateStaticClass.java new file mode 100644 index 00000000000..d3505bbd461 --- /dev/null +++ b/langtools/test/tools/javac/diags/examples/CantAnnotateStaticClass.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2012, 2013, 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. + * + * 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. + */ + +// key: compiler.err.cant.annotate.static.class + +import java.lang.annotation.*; + +class CantAnnotateStaticClass { + @Target(ElementType.TYPE_USE) + @interface A {} + + static class Outer { + class Inner {} + } + + // Error: + @A Outer.Inner f; + + // OK: + @A Outer g; +} diff --git a/langtools/test/tools/javac/diags/examples/IncorrectReceiverType.java b/langtools/test/tools/javac/diags/examples/IncorrectReceiverType.java new file mode 100644 index 00000000000..548067b503b --- /dev/null +++ b/langtools/test/tools/javac/diags/examples/IncorrectReceiverType.java @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2012, 2013, 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. + * + * 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. + */ + +// key: compiler.err.incorrect.receiver.type + +class IncorrectReceiverType { + void m(Object this) {} +} diff --git a/langtools/test/tools/javac/diags/examples/NoAnnotationsOnDotClass.java b/langtools/test/tools/javac/diags/examples/NoAnnotationsOnDotClass.java new file mode 100644 index 00000000000..0ce65530e6f --- /dev/null +++ b/langtools/test/tools/javac/diags/examples/NoAnnotationsOnDotClass.java @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2012, 2013, 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. + * + * 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. + */ + +// key: compiler.err.no.annotations.on.dot.class + +class NoAnnotationsOnDotClass { + @Target(ElementType.TYPE_USE) + @interface A {} + + Object o = @A Object.class; +} diff --git a/langtools/test/tools/javac/diags/examples/ThisAsIdentifier.java b/langtools/test/tools/javac/diags/examples/ThisAsIdentifier.java new file mode 100644 index 00000000000..cb3be6172dc --- /dev/null +++ b/langtools/test/tools/javac/diags/examples/ThisAsIdentifier.java @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2012, 2013, 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. + * + * 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. + */ + +// key: compiler.err.this.as.identifier + +class ThisAsIdentifier { + Object this; +} diff --git a/langtools/test/tools/javac/diags/examples/TypeAnnotationsNotSupported.java b/langtools/test/tools/javac/diags/examples/TypeAnnotationsNotSupported.java new file mode 100644 index 00000000000..16e6b8b51d3 --- /dev/null +++ b/langtools/test/tools/javac/diags/examples/TypeAnnotationsNotSupported.java @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2010, 2013, 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. + * + * 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. + */ + +// key: compiler.err.type.annotations.not.supported.in.source +// key: compiler.warn.source.no.bootclasspath +// options: -source 6 + +@interface Anno { } + +class TypeAnnotationsNotSupported { + void m() { + int i = (@Anno int) 3.14; + } +} diff --git a/langtools/test/tools/javac/failover/CheckAttributedTree.java b/langtools/test/tools/javac/failover/CheckAttributedTree.java index 14d1e40ca03..8f7fc379a18 100644 --- a/langtools/test/tools/javac/failover/CheckAttributedTree.java +++ b/langtools/test/tools/javac/failover/CheckAttributedTree.java @@ -362,11 +362,18 @@ public class CheckAttributedTree extends JavacTestingAbstractThreadedTest { } Info self = new Info(tree, endPosTable); - check(!mandatoryType(tree) || - (tree.type != null && - checkFields(tree)), - "'null' found in tree ", - self); + if (mandatoryType(tree)) { + check(tree.type != null, + "'null' field 'type' found in tree ", self); + if (tree.type==null) + new Throwable().printStackTrace(); + } + + Field errField = checkFields(tree); + if (errField!=null) { + check(false, + "'null' field '" + errField.getName() + "' found in tree ", self); + } Info prevEncl = encl; encl = self; @@ -395,7 +402,7 @@ public class CheckAttributedTree extends JavacTestingAbstractThreadedTest { } } - boolean checkFields(JCTree t) { + Field checkFields(JCTree t) { List fieldsToCheck = treeUtil.getFieldsOfType(t, excludedFields, Symbol.class, @@ -403,7 +410,7 @@ public class CheckAttributedTree extends JavacTestingAbstractThreadedTest { for (Field f : fieldsToCheck) { try { if (f.get(t) == null) { - return false; + return f; } } catch (IllegalAccessException e) { @@ -411,7 +418,7 @@ public class CheckAttributedTree extends JavacTestingAbstractThreadedTest { //swallow it } } - return true; + return null; } @Override diff --git a/langtools/test/tools/javac/processing/6994946/SemanticErrorTest.2.out b/langtools/test/tools/javac/processing/6994946/SemanticErrorTest.2.out index 37632783d8f..5e68e1d9c15 100644 --- a/langtools/test/tools/javac/processing/6994946/SemanticErrorTest.2.out +++ b/langtools/test/tools/javac/processing/6994946/SemanticErrorTest.2.out @@ -1,4 +1,3 @@ SemanticErrorTest.java:11:46: compiler.err.repeated.interface - compiler.err.proc.messager: Deliberate Error -SemanticErrorTest.java:11:46: compiler.err.repeated.interface -2 errors +2 errors \ No newline at end of file diff --git a/langtools/test/tools/javac/processing/model/element/TestAnonClassNames.java b/langtools/test/tools/javac/processing/model/element/TestAnonClassNames.java index 33466e65476..13fe97c18af 100644 --- a/langtools/test/tools/javac/processing/model/element/TestAnonClassNames.java +++ b/langtools/test/tools/javac/processing/model/element/TestAnonClassNames.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2013, 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 @@ -78,7 +78,7 @@ public class TestAnonClassNames { @Nesting(LOCAL) class LocalClass{}; - Object o = new /*@Nesting(ANONYMOUS)*/ Object() { // An anonymous annotated class + Object o = new @Nesting(ANONYMOUS) Object() { // An anonymous annotated class public String toString() { return "I have no name!"; } @@ -96,10 +96,9 @@ public class TestAnonClassNames { List names = new ArrayList(); for(Class clazz : classes) { String name = clazz.getName(); - Nesting anno = clazz.getAnnotation(Nesting.class); System.out.format("%s is %s%n", clazz.getName(), - anno == null ? "(unset/ANONYMOUS)" : anno.value()); + clazz.getAnnotation(Nesting.class).value()); testClassName(name); names.add(name); } @@ -158,6 +157,7 @@ public class TestAnonClassNames { } } +@Target({ElementType.TYPE, ElementType.TYPE_USE}) @Retention(RUNTIME) @interface Nesting { NestingKind value(); @@ -185,8 +185,8 @@ class ClassNameProber extends JavacTestingAbstractProcessor { typeElt.getQualifiedName().toString(), typeElt.getKind().toString(), nestingKind.toString()); - Nesting anno = typeElt.getAnnotation(Nesting.class); - if ((anno == null ? NestingKind.ANONYMOUS : anno.value()) != nestingKind) { + + if (typeElt.getAnnotation(Nesting.class).value() != nestingKind) { throw new RuntimeException("Mismatch of expected and reported nesting kind."); } } diff --git a/langtools/test/tools/javac/processing/model/element/TestMissingElement/TestMissingElement.java b/langtools/test/tools/javac/processing/model/element/TestMissingElement/TestMissingElement.java index 70666856a21..2ddcd10bd26 100644 --- a/langtools/test/tools/javac/processing/model/element/TestMissingElement/TestMissingElement.java +++ b/langtools/test/tools/javac/processing/model/element/TestMissingElement/TestMissingElement.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2013, 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 @@ -28,7 +28,7 @@ * @summary Modeling type implementing missing interfaces * @library /tools/javac/lib * @build JavacTestingAbstractProcessor TestMissingElement - * @compile -proc:only -XprintRounds -processor TestMissingElement InvalidSource.java + * @compile/fail/ref=TestMissingElement.ref -proc:only -XprintRounds -XDrawDiagnostics -processor TestMissingElement InvalidSource.java */ import java.util.*; diff --git a/langtools/test/tools/javac/processing/model/element/TestMissingElement/TestMissingElement.ref b/langtools/test/tools/javac/processing/model/element/TestMissingElement/TestMissingElement.ref new file mode 100644 index 00000000000..4c31a101dbb --- /dev/null +++ b/langtools/test/tools/javac/processing/model/element/TestMissingElement/TestMissingElement.ref @@ -0,0 +1,49 @@ +Round 1: + input files: {ExpectInterfaces, ExpectSupertype, OK, InvalidSource} + annotations: [ExpectSupertype, ExpectInterfaces] + last round: false +Round 2: + input files: {} + annotations: [] + last round: true +InvalidSource.java:55:42: compiler.err.cant.resolve.location: kindname.class, A, , , (compiler.misc.location: kindname.class, InvalidSource, null) +InvalidSource.java:58:44: compiler.err.doesnt.exist: A +InvalidSource.java:61:54: compiler.err.cant.resolve.location: kindname.class, A, , , (compiler.misc.location: kindname.package, java.util, null) +InvalidSource.java:64:47: compiler.err.cant.resolve.location: kindname.class, A, , , (compiler.misc.location: kindname.class, InvalidSource, null) +InvalidSource.java:67:44: compiler.err.cant.resolve.location: kindname.class, A, , , (compiler.misc.location: kindname.class, InvalidSource, null) +InvalidSource.java:70:46: compiler.err.doesnt.exist: A +InvalidSource.java:73:55: compiler.err.cant.resolve.location: kindname.class, A, , , (compiler.misc.location: kindname.class, InvalidSource, null) +InvalidSource.java:76:59: compiler.err.cant.resolve.location: kindname.class, A, , , (compiler.misc.location: kindname.class, InvalidSource, null) +InvalidSource.java:79:46: compiler.err.cant.resolve.location: kindname.class, A, , , (compiler.misc.location: kindname.class, InvalidSource, null) +InvalidSource.java:79:49: compiler.err.cant.resolve.location: kindname.class, B, , , (compiler.misc.location: kindname.class, InvalidSource, null) +InvalidSource.java:82:44: compiler.err.cant.resolve.location: kindname.class, A, , , (compiler.misc.location: kindname.class, InvalidSource, null) +InvalidSource.java:85:46: compiler.err.cant.resolve.location: kindname.class, A, , , (compiler.misc.location: kindname.class, InvalidSource, null) +InvalidSource.java:88:50: compiler.err.cant.resolve.location: kindname.class, A, , , (compiler.misc.location: kindname.class, InvalidSource, null) +InvalidSource.java:91:45: compiler.err.cant.resolve.location: kindname.class, A, , , (compiler.misc.location: kindname.class, InvalidSource, null) +InvalidSource.java:91:48: compiler.err.cant.resolve.location: kindname.class, B, , , (compiler.misc.location: kindname.class, InvalidSource, null) +InvalidSource.java:94:49: compiler.err.cant.resolve.location: kindname.class, A, , , (compiler.misc.location: kindname.class, InvalidSource, null) +InvalidSource.java:97:51: compiler.err.cant.resolve.location: kindname.class, A, , , (compiler.misc.location: kindname.class, InvalidSource, null) +InvalidSource.java:97:57: compiler.err.cant.resolve.location: kindname.class, B, , , (compiler.misc.location: kindname.class, InvalidSource, null) +InvalidSource.java:100:49: compiler.err.cant.resolve.location: kindname.class, A, , , (compiler.misc.location: kindname.class, InvalidSource, null) +InvalidSource.java:103:51: compiler.err.cant.resolve.location: kindname.class, A, , , (compiler.misc.location: kindname.class, InvalidSource, null) +InvalidSource.java:103:57: compiler.err.cant.resolve.location: kindname.class, B, , , (compiler.misc.location: kindname.class, InvalidSource, null) +InvalidSource.java:106:58: compiler.err.cant.resolve.location: kindname.class, X, , , (compiler.misc.location: kindname.class, InvalidSource, null) +22 errors +check supertype: InvalidSource.TestClassMissingClassA -- !:empty clss A! +check supertype: InvalidSource.TestClassMissingClassAB -- !:empty clss (pkg A).B! +check supertype: InvalidSource.TestClassMissingClass_juA -- !:empty clss (pkg java.util).A! +check supertype: InvalidSource.TestClassTMissingClassAT -- !:empty clss A! +check interfaces: InvalidSource.TestClassMissingIntfA -- !:empty intf A! +check interfaces: InvalidSource.TestClassMissingIntfAB -- !:empty intf (pkg A).B! +check interfaces: InvalidSource.TestClassMissingIntfAOK -- !:empty intf A!, intf OK +check interfaces: InvalidSource.TestClassOKMissingIntfA -- intf OK, !:empty intf A! +check interfaces: InvalidSource.TestClassMissingIntfA_B -- !:empty intf A!, !:empty intf B! +check interfaces: InvalidSource.TestIntfMissingIntfA -- !:empty intf A! +check interfaces: InvalidSource.TestIntfMissingIntfAOK -- !:empty intf A!, intf OK +check interfaces: InvalidSource.TestIntfOKMissingIntfA -- intf OK, !:empty intf A! +check interfaces: InvalidSource.TestIntfMissingIntfAB -- !:empty intf A!, !:empty intf B! +check interfaces: InvalidSource.TestClassTMissingIntfAT -- !:empty intf A! +check interfaces: InvalidSource.TestClassTMissingIntfAT_B -- !:empty intf A!, !:empty intf B! +check interfaces: InvalidSource.TestIntfTMissingIntfAT -- !:empty intf A! +check interfaces: InvalidSource.TestIntfTMissingIntfAT_B -- !:empty intf A!, !:empty intf B! +check interfaces: InvalidSource.TestClassListMissingX -- intf (pkg java.util).List \ No newline at end of file diff --git a/langtools/test/tools/javac/processing/model/util/directSupersOfErr/DirectSupersOfErr.java b/langtools/test/tools/javac/processing/model/util/directSupersOfErr/DirectSupersOfErr.java index 78808318ba3..ee0b9039737 100644 --- a/langtools/test/tools/javac/processing/model/util/directSupersOfErr/DirectSupersOfErr.java +++ b/langtools/test/tools/javac/processing/model/util/directSupersOfErr/DirectSupersOfErr.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 2013, 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 @@ -28,7 +28,7 @@ * @author Scott Seligman * @library /tools/javac/lib * @build JavacTestingAbstractProcessor DirectSupersOfErr - * @compile -processor DirectSupersOfErr -proc:only C1.java + * @compile/fail/ref=DirectSupersOfErr.ref -processor DirectSupersOfErr -proc:only -XDrawDiagnostics C1.java */ import java.util.Set; diff --git a/langtools/test/tools/javac/processing/model/util/directSupersOfErr/DirectSupersOfErr.ref b/langtools/test/tools/javac/processing/model/util/directSupersOfErr/DirectSupersOfErr.ref new file mode 100644 index 00000000000..8fe9c7ed8be --- /dev/null +++ b/langtools/test/tools/javac/processing/model/util/directSupersOfErr/DirectSupersOfErr.ref @@ -0,0 +1,2 @@ +C1.java:24:18: compiler.err.cant.resolve: kindname.class, Bogus, , +1 error diff --git a/langtools/test/tools/javac/tree/TreeKindTest.java b/langtools/test/tools/javac/tree/TreeKindTest.java index 608c45a4df7..8497308afb6 100644 --- a/langtools/test/tools/javac/tree/TreeKindTest.java +++ b/langtools/test/tools/javac/tree/TreeKindTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 2013, 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 @@ -29,7 +29,7 @@ import com.sun.source.tree.*; -public class TreeKindTest{ +public class TreeKindTest { public static void main(String... args) { boolean ok = true; @@ -108,6 +108,11 @@ public class TreeKindTest{ ok = ok & verify(k, i, i == ClassTree.class); break; + case ANNOTATION: + case TYPE_ANNOTATION: + ok = ok & verify(k, i, i == AnnotationTree.class); + break; + case OTHER: ok = ok & verify(k, i, i == null); break; diff --git a/langtools/test/tools/javac/tree/TreePosTest.java b/langtools/test/tools/javac/tree/TreePosTest.java index b8f8a36b1b0..8fed3e5c07f 100644 --- a/langtools/test/tools/javac/tree/TreePosTest.java +++ b/langtools/test/tools/javac/tree/TreePosTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2013, 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 @@ -75,6 +75,7 @@ import com.sun.tools.javac.api.JavacTool; import com.sun.tools.javac.code.Flags; import com.sun.tools.javac.tree.EndPosTable; import com.sun.tools.javac.tree.JCTree; +import com.sun.tools.javac.tree.JCTree.JCAnnotatedType; import com.sun.tools.javac.tree.JCTree.JCCompilationUnit; import com.sun.tools.javac.tree.JCTree.JCNewClass; import com.sun.tools.javac.tree.JCTree.JCVariableDecl; @@ -100,7 +101,8 @@ import static com.sun.tools.javac.util.Position.NOPOS; * @test * @bug 6919889 * @summary assorted position errors in compiler syntax trees - * @run main TreePosTest -q -r -ef ./tools/javac/typeAnnotations -ef ./tools/javap/typeAnnotations -et ANNOTATED_TYPE . + * OLD: -q -r -ef ./tools/javac/typeAnnotations -ef ./tools/javap/typeAnnotations -et ANNOTATED_TYPE . + * @run main TreePosTest -q -r . */ public class TreePosTest { /** @@ -367,15 +369,24 @@ public class TreePosTest { // e.g. int[][] a = new int[2][]; check("encl.start <= start", encl, self, encl.start <= self.start); check("start <= pos", encl, self, self.start <= self.pos); - if (!(self.tag == TYPEARRAY + if (!( (self.tag == TYPEARRAY || + isAnnotatedArray(self.tree)) && (encl.tag == VARDEF || encl.tag == METHODDEF || - encl.tag == TYPEARRAY))) { + encl.tag == TYPEARRAY || + isAnnotatedArray(encl.tree)) + || + encl.tag == ANNOTATED_TYPE && self.tag == SELECT + )) { check("encl.pos <= start || end <= encl.pos", encl, self, encl.pos <= self.start || self.end <= encl.pos); } check("pos <= end", encl, self, self.pos <= self.end); - if (!(self.tag == TYPEARRAY && encl.tag == TYPEARRAY)) { + if (!( (self.tag == TYPEARRAY || isAnnotatedArray(self.tree)) && + (encl.tag == TYPEARRAY || isAnnotatedArray(encl.tree)) + || + encl.tag == MODIFIERS && self.tag == ANNOTATION + ) ) { check("end <= encl.end", encl, self, self.end <= encl.end); } } @@ -387,6 +398,11 @@ public class TreePosTest { encl = prevEncl; } + private boolean isAnnotatedArray(JCTree tree) { + return tree.hasTag(ANNOTATED_TYPE) && + ((JCAnnotatedType)tree).underlyingType.hasTag(TYPEARRAY); + } + @Override public void visitVarDef(JCVariableDecl tree) { // enum member declarations are desugared in the parser and have @@ -427,7 +443,8 @@ public class TreePosTest { viewer.addEntry(sourcefile, label, encl, self); } - String s = self.tree.toString(); + String s = "encl: " + encl.tree.toString() + + " this: " + self.tree.toString(); String msg = sourcefile.getName() + ": " + label + ": " + "encl:" + encl + " this:" + self + "\n" + s.substring(0, Math.min(80, s.length())).replaceAll("[\r\n]+", " "); diff --git a/langtools/test/tools/javac/treeannotests/AnnoTreeTests.java b/langtools/test/tools/javac/treeannotests/AnnoTreeTests.java new file mode 100644 index 00000000000..0db46b5774b --- /dev/null +++ b/langtools/test/tools/javac/treeannotests/AnnoTreeTests.java @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2010, 2013, 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. + * + * 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. + */ + +/* + * @test + * @build DA TA Test TestProcessor + * @compile -proc:only -processor TestProcessor AnnoTreeTests.java + */ + +@Test(4) +class AnnoTreeTests { + // primitive types + // @TA("int") int i1 = 0; // TODO: Only visible via ClassFile + long i2 = (@TA("long") long) 0; + + // simple array types + // @DA("short") short[] a1; // TODO: Only visible via ClassFile + byte @TA("byte[]") [] a2; + float[] a3 = (@TA("float") float[]) null; + double[] a4 = (double @TA("double[]") []) null; + + // multi-dimensional array types + // (still to come) +} diff --git a/langtools/test/tools/javac/treeannotests/TestProcessor.java b/langtools/test/tools/javac/treeannotests/TestProcessor.java index f74cd3c7cea..8b6c4adb265 100644 --- a/langtools/test/tools/javac/treeannotests/TestProcessor.java +++ b/langtools/test/tools/javac/treeannotests/TestProcessor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2013, 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 @@ -203,13 +203,16 @@ public class TestProcessor extends AbstractProcessor { * expression name=value. */ String getStringValue(JCExpression e) { - if (e.getTag() == JCTree.ASSIGN) { + if (e.hasTag(JCTree.Tag.ASSIGN)) { JCAssign a = (JCAssign) e; JCExpression rhs = a.rhs; - if (rhs.getTag() == JCTree.LITERAL) { + if (rhs.hasTag(JCTree.Tag.LITERAL)) { JCLiteral l = (JCLiteral) rhs; return (String) l.value; } + } else if (e.hasTag(JCTree.Tag.LITERAL)) { + JCLiteral l = (JCLiteral) e; + return (String) l.value; } throw new IllegalArgumentException(e.toString()); } diff --git a/langtools/test/tools/javac/typeAnnotations/newlocations/BasicTest.out b/langtools/test/tools/javac/typeAnnotations/newlocations/BasicTest.out deleted file mode 100644 index eecd7f7e638..00000000000 --- a/langtools/test/tools/javac/typeAnnotations/newlocations/BasicTest.out +++ /dev/null @@ -1,61 +0,0 @@ -BasicTest.java:47:27: compiler.err.illegal.start.of.type -BasicTest.java:47:28: compiler.err.expected: '{' -BasicTest.java:47:36: compiler.err.expected: token.identifier -BasicTest.java:47:38: compiler.err.illegal.start.of.type -BasicTest.java:47:45: compiler.err.expected: token.identifier -BasicTest.java:47:47: compiler.err.expected: ';' -BasicTest.java:47:62: compiler.err.expected: token.identifier -BasicTest.java:47:84: compiler.err.expected: token.identifier -BasicTest.java:52:22: compiler.err.illegal.start.of.expr -BasicTest.java:52:31: compiler.err.expected: ';' -BasicTest.java:52:37: compiler.err.expected: token.identifier -BasicTest.java:53:30: compiler.err.expected: token.identifier -BasicTest.java:53:31: compiler.err.expected: -> -BasicTest.java:56:23: compiler.err.expected: token.identifier -BasicTest.java:56:24: compiler.err.expected2: '(', '[' -BasicTest.java:56:25: compiler.err.expected: ';' -BasicTest.java:56:27: compiler.err.invalid.meth.decl.ret.type.req -BasicTest.java:56:34: compiler.err.illegal.start.of.type -BasicTest.java:58:34: compiler.err.illegal.start.of.type -BasicTest.java:61:16: compiler.err.illegal.start.of.type -BasicTest.java:61:18: compiler.err.expected: ';' -BasicTest.java:61:24: compiler.err.illegal.start.of.type -BasicTest.java:61:26: compiler.err.expected: ';' -BasicTest.java:61:33: compiler.err.expected: token.identifier -BasicTest.java:61:34: compiler.err.illegal.start.of.type -BasicTest.java:61:35: compiler.err.expected: token.identifier -BasicTest.java:61:37: compiler.err.expected: ';' -BasicTest.java:61:45: compiler.err.expected: token.identifier -BasicTest.java:61:50: compiler.err.expected: token.identifier -BasicTest.java:62:16: compiler.err.expected: token.identifier -BasicTest.java:62:17: compiler.err.expected2: '(', '[' -BasicTest.java:62:18: compiler.err.expected: ';' -BasicTest.java:62:28: compiler.err.illegal.start.of.type -BasicTest.java:62:30: compiler.err.expected: ';' -BasicTest.java:62:36: compiler.err.illegal.start.of.type -BasicTest.java:62:38: compiler.err.expected: ';' -BasicTest.java:62:45: compiler.err.expected: token.identifier -BasicTest.java:62:46: compiler.err.illegal.start.of.type -BasicTest.java:62:47: compiler.err.expected: token.identifier -BasicTest.java:62:49: compiler.err.expected: ';' -BasicTest.java:62:57: compiler.err.expected: token.identifier -BasicTest.java:62:58: compiler.err.illegal.start.of.type -BasicTest.java:62:59: compiler.err.expected: token.identifier -BasicTest.java:64:25: compiler.err.illegal.start.of.type -BasicTest.java:64:27: compiler.err.expected: ';' -BasicTest.java:64:34: compiler.err.expected: token.identifier -BasicTest.java:64:38: compiler.err.expected: token.identifier -BasicTest.java:64:41: compiler.err.illegal.start.of.expr -BasicTest.java:64:50: compiler.err.expected: ';' -BasicTest.java:64:56: compiler.err.expected: token.identifier -BasicTest.java:69:17: compiler.err.expected: ';' -BasicTest.java:69:24: compiler.err.illegal.start.of.type -BasicTest.java:69:30: compiler.err.expected: ';' -BasicTest.java:69:59: compiler.err.expected: token.identifier -BasicTest.java:69:74: compiler.err.expected: ';' -BasicTest.java:74:22: compiler.err.expected: token.identifier -BasicTest.java:74:24: compiler.err.expected: ';' -BasicTest.java:74:25: compiler.err.illegal.start.of.type -BasicTest.java:74:33: compiler.err.expected: ';' -BasicTest.java:77:2: compiler.err.premature.eof -60 errors diff --git a/langtools/test/tools/javap/typeAnnotations/JSR175Annotations.java b/langtools/test/tools/javap/typeAnnotations/JSR175Annotations.java new file mode 100644 index 00000000000..3504cb520bb --- /dev/null +++ b/langtools/test/tools/javap/typeAnnotations/JSR175Annotations.java @@ -0,0 +1,152 @@ +/* + * Copyright (c) 2008, 2013, 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. + * + * 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. + */ + +import java.io.*; +import com.sun.tools.classfile.*; + +/* + * @test JSR175Annotations + * @bug 6843077 + * @summary test that only type annotations are recorded as such in classfile + */ + +public class JSR175Annotations { + public static void main(String[] args) throws Exception { + new JSR175Annotations().run(); + } + + public void run() throws Exception { + File javaFile = writeTestFile(); + File classFile = compileTestFile(javaFile); + + ClassFile cf = ClassFile.read(classFile); + for (Field f : cf.fields) { + test(cf, f); + } + for (Method m: cf.methods) { + test(cf, m); + } + + countAnnotations(); + + if (errors > 0) + throw new Exception(errors + " errors found"); + System.out.println("PASSED"); + } + + void test(ClassFile cf, Method m) { + test(cf, m, Attribute.RuntimeVisibleTypeAnnotations, true); + test(cf, m, Attribute.RuntimeInvisibleTypeAnnotations, false); + } + + void test(ClassFile cf, Field m) { + test(cf, m, Attribute.RuntimeVisibleTypeAnnotations, true); + test(cf, m, Attribute.RuntimeInvisibleTypeAnnotations, false); + } + + // test the result of Attributes.getIndex according to expectations + // encoded in the method's name + void test(ClassFile cf, Method m, String name, boolean visible) { + int index = m.attributes.getIndex(cf.constant_pool, name); + if (index != -1) { + Attribute attr = m.attributes.get(index); + assert attr instanceof RuntimeTypeAnnotations_attribute; + RuntimeTypeAnnotations_attribute tAttr = (RuntimeTypeAnnotations_attribute)attr; + all += tAttr.annotations.length; + if (visible) + visibles += tAttr.annotations.length; + else + invisibles += tAttr.annotations.length; + } + } + + // test the result of Attributes.getIndex according to expectations + // encoded in the method's name + void test(ClassFile cf, Field m, String name, boolean visible) { + int index = m.attributes.getIndex(cf.constant_pool, name); + if (index != -1) { + Attribute attr = m.attributes.get(index); + assert attr instanceof RuntimeTypeAnnotations_attribute; + RuntimeTypeAnnotations_attribute tAttr = (RuntimeTypeAnnotations_attribute)attr; + all += tAttr.annotations.length; + if (visible) + visibles += tAttr.annotations.length; + else + invisibles += tAttr.annotations.length; + } + } + + File writeTestFile() throws IOException { + File f = new File("Test.java"); + PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(f))); + out.println("import java.lang.annotation.*;"); + out.println("abstract class Test { "); + out.println(" @Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER})"); + out.println(" @Retention(RetentionPolicy.RUNTIME)"); + out.println(" @interface A { }"); + out.println(" @A String m;"); + out.println(" @A String method(@A String a) {"); + out.println(" return a;"); + out.println(" }"); + out.println("}"); + out.close(); + return f; + } + + File compileTestFile(File f) { + int rc = com.sun.tools.javac.Main.compile(new String[] { "-source", "1.8", "-g", f.getPath() }); + if (rc != 0) + throw new Error("compilation failed. rc=" + rc); + String path = f.getPath(); + return new File(path.substring(0, path.length() - 5) + ".class"); + } + + void countAnnotations() { + int expected_visibles = 0, expected_invisibles = 0; + int expected_all = expected_visibles + expected_invisibles; + + if (expected_all != all) { + errors++; + System.err.println("expected " + expected_all + + " annotations but found " + all); + } + + if (expected_visibles != visibles) { + errors++; + System.err.println("expected " + expected_visibles + + " visibles annotations but found " + visibles); + } + + if (expected_invisibles != invisibles) { + errors++; + System.err.println("expected " + expected_invisibles + + " invisibles annotations but found " + invisibles); + } + + } + + int errors; + int all; + int visibles; + int invisibles; +} diff --git a/langtools/test/tools/javap/typeAnnotations/NewArray.java b/langtools/test/tools/javap/typeAnnotations/NewArray.java new file mode 100644 index 00000000000..bcb25efc047 --- /dev/null +++ b/langtools/test/tools/javap/typeAnnotations/NewArray.java @@ -0,0 +1,177 @@ +/* + * Copyright (c) 2008, 2013, 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. + * + * 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. + */ + +import java.io.*; +import com.sun.tools.classfile.*; + +/* + * @test NewArray + * @bug 6843077 + * @summary test that all type annotations are present in the classfile + */ + +public class NewArray { + public static void main(String[] args) throws Exception { + new NewArray().run(); + } + + public void run() throws Exception { + File javaFile = writeTestFile(); + File classFile = compileTestFile(javaFile); + + ClassFile cf = ClassFile.read(classFile); + test(cf); + for (Field f : cf.fields) { + test(cf, f); + } + for (Method m: cf.methods) { + test(cf, m); + } + + countAnnotations(); + + if (errors > 0) + throw new Exception(errors + " errors found"); + System.out.println("PASSED"); + } + + void test(ClassFile cf) { + test(cf, Attribute.RuntimeVisibleTypeAnnotations, true); + test(cf, Attribute.RuntimeInvisibleTypeAnnotations, false); + } + + void test(ClassFile cf, Method m) { + test(cf, m, Attribute.RuntimeVisibleTypeAnnotations, true); + test(cf, m, Attribute.RuntimeInvisibleTypeAnnotations, false); + } + + void test(ClassFile cf, Field m) { + test(cf, m, Attribute.RuntimeVisibleTypeAnnotations, true); + test(cf, m, Attribute.RuntimeInvisibleTypeAnnotations, false); + } + + // test the result of Attributes.getIndex according to expectations + // encoded in the method's name + void test(ClassFile cf, String name, boolean visible) { + int index = cf.attributes.getIndex(cf.constant_pool, name); + if (index != -1) { + Attribute attr = cf.attributes.get(index); + assert attr instanceof RuntimeTypeAnnotations_attribute; + RuntimeTypeAnnotations_attribute tAttr = (RuntimeTypeAnnotations_attribute)attr; + all += tAttr.annotations.length; + if (visible) + visibles += tAttr.annotations.length; + else + invisibles += tAttr.annotations.length; + } + } + + // test the result of Attributes.getIndex according to expectations + // encoded in the method's name + void test(ClassFile cf, Method m, String name, boolean visible) { + int index = m.attributes.getIndex(cf.constant_pool, name); + if (index != -1) { + Attribute attr = m.attributes.get(index); + assert attr instanceof RuntimeTypeAnnotations_attribute; + RuntimeTypeAnnotations_attribute tAttr = (RuntimeTypeAnnotations_attribute)attr; + all += tAttr.annotations.length; + if (visible) + visibles += tAttr.annotations.length; + else + invisibles += tAttr.annotations.length; + } + } + + // test the result of Attributes.getIndex according to expectations + // encoded in the method's name + void test(ClassFile cf, Field m, String name, boolean visible) { + int index = m.attributes.getIndex(cf.constant_pool, name); + if (index != -1) { + Attribute attr = m.attributes.get(index); + assert attr instanceof RuntimeTypeAnnotations_attribute; + RuntimeTypeAnnotations_attribute tAttr = (RuntimeTypeAnnotations_attribute)attr; + all += tAttr.annotations.length; + if (visible) + visibles += tAttr.annotations.length; + else + invisibles += tAttr.annotations.length; + } + } + + File writeTestFile() throws IOException { + File f = new File("Test.java"); + PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(f))); + out.println("import java.lang.annotation.*;"); + out.println("import java.util.*;"); + out.println("class Test { "); + out.println(" @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER})"); + out.println(" @interface A { }"); + + out.println(" void test() {"); + out.println(" Object a = new @A String @A [5] @A [];"); + out.println(" Object b = new @A String @A [5] @A [3];"); + out.println(" Object c = new @A String @A [] @A [] {};"); + out.println(" }"); + out.println("}"); + + out.close(); + return f; + } + + File compileTestFile(File f) { + int rc = com.sun.tools.javac.Main.compile(new String[] { "-source", "1.8", "-g", f.getPath() }); + if (rc != 0) + throw new Error("compilation failed. rc=" + rc); + String path = f.getPath(); + return new File(path.substring(0, path.length() - 5) + ".class"); + } + + void countAnnotations() { + int expected_visibles = 0, expected_invisibles = 9; + int expected_all = expected_visibles + expected_invisibles; + + if (expected_all != all) { + errors++; + System.err.println("expected " + expected_all + + " annotations but found " + all); + } + + if (expected_visibles != visibles) { + errors++; + System.err.println("expected " + expected_visibles + + " visibles annotations but found " + visibles); + } + + if (expected_invisibles != invisibles) { + errors++; + System.err.println("expected " + expected_invisibles + + " invisibles annotations but found " + invisibles); + } + + } + + int errors; + int all; + int visibles; + int invisibles; +} diff --git a/langtools/test/tools/javap/typeAnnotations/Presence.java b/langtools/test/tools/javap/typeAnnotations/Presence.java new file mode 100644 index 00000000000..6ed86083eb8 --- /dev/null +++ b/langtools/test/tools/javap/typeAnnotations/Presence.java @@ -0,0 +1,195 @@ +/* + * Copyright (c) 2008, 2013, 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. + * + * 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. + */ + +import java.io.*; +import java.lang.annotation.ElementType; + +import com.sun.tools.classfile.*; + +/* + * @test Presence + * @bug 6843077 + * @summary test that all type annotations are present in the classfile + */ + +public class Presence { + public static void main(String[] args) throws Exception { + new Presence().run(); + } + + public void run() throws Exception { + File javaFile = writeTestFile(); + File classFile = compileTestFile(javaFile); + + ClassFile cf = ClassFile.read(classFile); + test(cf); + for (Field f : cf.fields) { + test(cf, f); + } + for (Method m: cf.methods) { + test(cf, m); + } + + countAnnotations(); + + if (errors > 0) + throw new Exception(errors + " errors found"); + System.out.println("PASSED"); + } + + void test(ClassFile cf) { + test(cf, Attribute.RuntimeVisibleTypeAnnotations, true); + test(cf, Attribute.RuntimeInvisibleTypeAnnotations, false); + } + + void test(ClassFile cf, Method m) { + test(cf, m, Attribute.RuntimeVisibleTypeAnnotations, true); + test(cf, m, Attribute.RuntimeInvisibleTypeAnnotations, false); + } + + void test(ClassFile cf, Field m) { + test(cf, m, Attribute.RuntimeVisibleTypeAnnotations, true); + test(cf, m, Attribute.RuntimeInvisibleTypeAnnotations, false); + } + + // test the result of Attributes.getIndex according to expectations + // encoded in the method's name + void test(ClassFile cf, String name, boolean visible) { + int index = cf.attributes.getIndex(cf.constant_pool, name); + if (index != -1) { + Attribute attr = cf.attributes.get(index); + assert attr instanceof RuntimeTypeAnnotations_attribute; + RuntimeTypeAnnotations_attribute tAttr = (RuntimeTypeAnnotations_attribute)attr; + all += tAttr.annotations.length; + if (visible) + visibles += tAttr.annotations.length; + else + invisibles += tAttr.annotations.length; + } + } + + // test the result of Attributes.getIndex according to expectations + // encoded in the method's name + void test(ClassFile cf, Method m, String name, boolean visible) { + int index = m.attributes.getIndex(cf.constant_pool, name); + if (index != -1) { + Attribute attr = m.attributes.get(index); + assert attr instanceof RuntimeTypeAnnotations_attribute; + RuntimeTypeAnnotations_attribute tAttr = (RuntimeTypeAnnotations_attribute)attr; + all += tAttr.annotations.length; + if (visible) + visibles += tAttr.annotations.length; + else + invisibles += tAttr.annotations.length; + } + } + + // test the result of Attributes.getIndex according to expectations + // encoded in the method's name + void test(ClassFile cf, Field m, String name, boolean visible) { + int index = m.attributes.getIndex(cf.constant_pool, name); + if (index != -1) { + Attribute attr = m.attributes.get(index); + assert attr instanceof RuntimeTypeAnnotations_attribute; + RuntimeTypeAnnotations_attribute tAttr = (RuntimeTypeAnnotations_attribute)attr; + all += tAttr.annotations.length; + if (visible) + visibles += tAttr.annotations.length; + else + invisibles += tAttr.annotations.length; + } + } + + File writeTestFile() throws IOException { + File f = new File("Test.java"); + PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(f))); + out.println("import java.util.*;"); + out.println("import java.lang.annotation.*;"); + + out.println("class Test<@Test.A T extends @Test.A List<@Test.A String>> { "); + out.println(" @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER})"); + out.println(" @interface A { }"); + + out.println(" Map<@A String, Map<@A String, @A String>> f1;"); + + out.println(" <@A TM extends @A List<@A String>>"); + out.println(" Map<@A String, @A List<@A String>>"); + out.println(" method(@A Test this, List<@A String> @A [] param1, String @A [] @A ... param2)"); + out.println(" throws @A Exception {"); + out.println(" @A String lc1 = null;"); + out.println(" @A List<@A String> lc2 = null;"); + out.println(" @A String @A [] [] @A[] lc3 = null;"); + out.println(" List> lc4 = null;"); + out.println(" Object lc5 = (@A List<@A String>) null;"); + out.println(" boolean lc6 = lc1 instanceof @A String;"); + out.println(" boolean lc7 = lc5 instanceof @A String @A [] @A [];"); + out.println(" new @A ArrayList<@A String>();"); + out.println(" Object lc8 = new @A String @A [4];"); + out.println(" try {"); + out.println(" Object lc10 = int.class;"); + out.println(" } catch (@A Exception e) { e.toString(); }"); + out.println(" return null;"); + out.println(" }"); + out.println(" void vararg1(String @A ... t) { } "); + out.println("}"); + out.close(); + return f; + } + + File compileTestFile(File f) { + int rc = com.sun.tools.javac.Main.compile(new String[] { "-source", "1.8", "-g", f.getPath() }); + if (rc != 0) + throw new Error("compilation failed. rc=" + rc); + String path = f.getPath(); + return new File(path.substring(0, path.length() - 5) + ".class"); + } + + void countAnnotations() { + int expected_visibles = 0, expected_invisibles = 38; + int expected_all = expected_visibles + expected_invisibles; + + if (expected_all != all) { + errors++; + System.err.println("expected " + expected_all + + " annotations but found " + all); + } + + if (expected_visibles != visibles) { + errors++; + System.err.println("expected " + expected_visibles + + " visibles annotations but found " + visibles); + } + + if (expected_invisibles != invisibles) { + errors++; + System.err.println("expected " + expected_invisibles + + " invisibles annotations but found " + invisibles); + } + + } + + int errors; + int all; + int visibles; + int invisibles; +} diff --git a/langtools/test/tools/javap/typeAnnotations/PresenceInner.java b/langtools/test/tools/javap/typeAnnotations/PresenceInner.java new file mode 100644 index 00000000000..1b859206a3d --- /dev/null +++ b/langtools/test/tools/javap/typeAnnotations/PresenceInner.java @@ -0,0 +1,187 @@ +/* + * Copyright (c) 2009, 2013, 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. + * + * 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. + */ + +import java.io.*; +import com.sun.tools.classfile.*; + +/* + * @test PresenceInner + * @bug 6843077 + * @summary test that annotations in inner types count only once + */ + +public class PresenceInner { + public static void main(String[] args) throws Exception { + new PresenceInner().run(); + } + + public void run() throws Exception { + File javaFile = writeTestFile(); + File classFile = compileTestFile(javaFile); + + ClassFile cf = ClassFile.read(classFile); + test(cf); + for (Field f : cf.fields) { + test(cf, f); + } + for (Method m: cf.methods) { + test(cf, m); + } + + // counts are zero when vising outer class + countAnnotations(0); + + // visit inner class + File innerFile = new File("Test$1Inner.class"); + ClassFile icf = ClassFile.read(innerFile); + test(icf); + for (Field f : icf.fields) { + test(cf, f); + } + for (Method m: icf.methods) { + test(cf, m); + } + + countAnnotations(1); + if (errors > 0) + throw new Exception(errors + " errors found"); + System.out.println("PASSED"); + } + + void test(ClassFile cf) { + test(cf, Attribute.RuntimeVisibleTypeAnnotations, true); + test(cf, Attribute.RuntimeInvisibleTypeAnnotations, false); + } + + void test(ClassFile cf, Method m) { + test(cf, m, Attribute.RuntimeVisibleTypeAnnotations, true); + test(cf, m, Attribute.RuntimeInvisibleTypeAnnotations, false); + } + + void test(ClassFile cf, Field m) { + test(cf, m, Attribute.RuntimeVisibleTypeAnnotations, true); + test(cf, m, Attribute.RuntimeInvisibleTypeAnnotations, false); + } + + // test the result of Attributes.getIndex according to expectations + // encoded in the method's name + void test(ClassFile cf, String name, boolean visible) { + int index = cf.attributes.getIndex(cf.constant_pool, name); + if (index != -1) { + Attribute attr = cf.attributes.get(index); + assert attr instanceof RuntimeTypeAnnotations_attribute; + RuntimeTypeAnnotations_attribute tAttr = (RuntimeTypeAnnotations_attribute)attr; + all += tAttr.annotations.length; + if (visible) + visibles += tAttr.annotations.length; + else + invisibles += tAttr.annotations.length; + } + } + + // test the result of Attributes.getIndex according to expectations + // encoded in the method's name + void test(ClassFile cf, Method m, String name, boolean visible) { + int index = m.attributes.getIndex(cf.constant_pool, name); + if (index != -1) { + Attribute attr = m.attributes.get(index); + assert attr instanceof RuntimeTypeAnnotations_attribute; + RuntimeTypeAnnotations_attribute tAttr = (RuntimeTypeAnnotations_attribute)attr; + all += tAttr.annotations.length; + if (visible) + visibles += tAttr.annotations.length; + else + invisibles += tAttr.annotations.length; + } + } + + // test the result of Attributes.getIndex according to expectations + // encoded in the method's name + void test(ClassFile cf, Field m, String name, boolean visible) { + int index = m.attributes.getIndex(cf.constant_pool, name); + if (index != -1) { + Attribute attr = m.attributes.get(index); + assert attr instanceof RuntimeTypeAnnotations_attribute; + RuntimeTypeAnnotations_attribute tAttr = (RuntimeTypeAnnotations_attribute)attr; + all += tAttr.annotations.length; + if (visible) + visibles += tAttr.annotations.length; + else + invisibles += tAttr.annotations.length; + } + } + + File writeTestFile() throws IOException { + File f = new File("Test.java"); + PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(f))); + + out.println("import java.lang.annotation.*;"); + out.println("class Test {"); + out.println(" void method() {"); + out.println(" class Inner { }"); + out.println(" }"); + out.println("}"); + out.println("@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER})"); + out.println("@interface A { }"); + out.close(); + System.out.println(f.getAbsolutePath()); + return f; + } + + File compileTestFile(File f) { + int rc = com.sun.tools.javac.Main.compile(new String[] { "-source", "1.8", "-g", f.getPath() }); + if (rc != 0) + throw new Error("compilation failed. rc=" + rc); + String path = f.getPath(); + return new File(path.substring(0, path.length() - 5) + ".class"); + } + + void countAnnotations(int expected_invisibles) { + int expected_visibles = 0; + int expected_all = expected_visibles + expected_invisibles; + + if (expected_all != all) { + errors++; + System.err.println("expected " + expected_all + + " annotations but found " + all); + } + + if (expected_visibles != visibles) { + errors++; + System.err.println("expected " + expected_visibles + + " visibles annotations but found " + visibles); + } + + if (expected_invisibles != invisibles) { + errors++; + System.err.println("expected " + expected_invisibles + + " invisibles annotations but found " + invisibles); + } + + } + + int errors; + int all; + int visibles; + int invisibles; +} diff --git a/langtools/test/tools/javap/typeAnnotations/T6855990.java b/langtools/test/tools/javap/typeAnnotations/T6855990.java new file mode 100644 index 00000000000..bc24eda6f11 --- /dev/null +++ b/langtools/test/tools/javap/typeAnnotations/T6855990.java @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2009, 2013, 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. + * + * 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. + */ + +import java.io.*; + +/* + * @test + * @bug 6855990 + * @summary InstructionDetailWriter should support new 308 annotations attribute + */ + +public class T6855990 { + public static void main(String[] args) throws Exception { + new T6855990().run(); + } + + public void run() throws Exception { + @Simple String[] args = { "-c", "-XDdetails:typeAnnotations", "T6855990" }; + StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter(sw); + int rc = com.sun.tools.javap.Main.run(args, pw); + pw.close(); + String out = sw.toString(); + System.out.println(out); + if (out.indexOf("@Simple: LOCAL_VARIABLE") == -1) + throw new Exception("expected output not found"); + } +} + +@interface Simple { } + diff --git a/langtools/test/tools/javap/typeAnnotations/TypeCasts.java b/langtools/test/tools/javap/typeAnnotations/TypeCasts.java new file mode 100644 index 00000000000..589b91fa13e --- /dev/null +++ b/langtools/test/tools/javap/typeAnnotations/TypeCasts.java @@ -0,0 +1,191 @@ +/* + * Copyright (c) 2009, 2013, 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. + * + * 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. + */ + +import java.io.*; +import com.sun.tools.classfile.*; + +/* + * @test + * @bug 6843077 + * @summary test that typecasts annotation are emitted if only the cast + * expression is optimized away + */ + +public class TypeCasts { + public static void main(String[] args) throws Exception { + new TypeCasts().run(); + } + + public void run() throws Exception { + File javaFile = writeTestFile(); + File classFile = compileTestFile(javaFile); + + ClassFile cf = ClassFile.read(classFile); + test(cf); + for (Field f : cf.fields) { + test(cf, f); + } + for (Method m: cf.methods) { + test(cf, m); + } + + countAnnotations(); + + if (errors > 0) + throw new Exception(errors + " errors found"); + System.out.println("PASSED"); + } + + void test(ClassFile cf) { + test(cf, Attribute.RuntimeVisibleTypeAnnotations, true); + test(cf, Attribute.RuntimeInvisibleTypeAnnotations, false); + } + + void test(ClassFile cf, Method m) { + test(cf, m, Attribute.RuntimeVisibleTypeAnnotations, true); + test(cf, m, Attribute.RuntimeInvisibleTypeAnnotations, false); + } + + void test(ClassFile cf, Field m) { + test(cf, m, Attribute.RuntimeVisibleTypeAnnotations, true); + test(cf, m, Attribute.RuntimeInvisibleTypeAnnotations, false); + } + + // test the result of Attributes.getIndex according to expectations + // encoded in the method's name + void test(ClassFile cf, String name, boolean visible) { + int index = cf.attributes.getIndex(cf.constant_pool, name); + if (index != -1) { + Attribute attr = cf.attributes.get(index); + assert attr instanceof RuntimeTypeAnnotations_attribute; + RuntimeTypeAnnotations_attribute tAttr = (RuntimeTypeAnnotations_attribute)attr; + all += tAttr.annotations.length; + if (visible) + visibles += tAttr.annotations.length; + else + invisibles += tAttr.annotations.length; + } + } + + // test the result of Attributes.getIndex according to expectations + // encoded in the method's name + void test(ClassFile cf, Method m, String name, boolean visible) { + int index = m.attributes.getIndex(cf.constant_pool, name); + if (index != -1) { + Attribute attr = m.attributes.get(index); + assert attr instanceof RuntimeTypeAnnotations_attribute; + RuntimeTypeAnnotations_attribute tAttr = (RuntimeTypeAnnotations_attribute)attr; + all += tAttr.annotations.length; + if (visible) + visibles += tAttr.annotations.length; + else + invisibles += tAttr.annotations.length; + } + } + + // test the result of Attributes.getIndex according to expectations + // encoded in the method's name + void test(ClassFile cf, Field m, String name, boolean visible) { + int index = m.attributes.getIndex(cf.constant_pool, name); + if (index != -1) { + Attribute attr = m.attributes.get(index); + assert attr instanceof RuntimeTypeAnnotations_attribute; + RuntimeTypeAnnotations_attribute tAttr = (RuntimeTypeAnnotations_attribute)attr; + all += tAttr.annotations.length; + if (visible) + visibles += tAttr.annotations.length; + else + invisibles += tAttr.annotations.length; + } + } + + + File writeTestFile() throws IOException { + File f = new File("Test.java"); + PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(f))); + out.println("import java.lang.annotation.*;"); + out.println("class Test { "); + out.println(" @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER})"); + out.println(" @interface A { }"); + + out.println(" void emit() {"); + out.println(" Object o = null;"); + out.println(" String s = null;"); + + out.println(" String a0 = (@A String)o;"); + out.println(" Object a1 = (@A Object)o;"); + + out.println(" String b0 = (@A String)s;"); + out.println(" Object b1 = (@A Object)s;"); + out.println(" }"); + + out.println(" void alldeadcode() {"); + out.println(" Object o = null;"); + + out.println(" if (false) {"); + out.println(" String a0 = (@A String)o;"); + out.println(" }"); + out.println(" }"); + + out.println("}"); + out.close(); + return f; + } + + File compileTestFile(File f) { + int rc = com.sun.tools.javac.Main.compile(new String[] { "-source", "1.8", "-g", f.getPath() }); + if (rc != 0) + throw new Error("compilation failed. rc=" + rc); + String path = f.getPath(); + return new File(path.substring(0, path.length() - 5) + ".class"); + } + + void countAnnotations() { + int expected_visibles = 0, expected_invisibles = 4; + int expected_all = expected_visibles + expected_invisibles; + + if (expected_all != all) { + errors++; + System.err.println("expected " + expected_all + + " annotations but found " + all); + } + + if (expected_visibles != visibles) { + errors++; + System.err.println("expected " + expected_visibles + + " visibles annotations but found " + visibles); + } + + if (expected_invisibles != invisibles) { + errors++; + System.err.println("expected " + expected_invisibles + + " invisibles annotations but found " + invisibles); + } + + } + + int errors; + int all; + int visibles; + int invisibles; +} diff --git a/langtools/test/tools/javap/typeAnnotations/Visibility.java b/langtools/test/tools/javap/typeAnnotations/Visibility.java new file mode 100644 index 00000000000..9fe348bad6c --- /dev/null +++ b/langtools/test/tools/javap/typeAnnotations/Visibility.java @@ -0,0 +1,145 @@ +/* + * Copyright (c) 2008, 2013, 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. + * + * 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. + */ + +import java.io.*; +import com.sun.tools.classfile.*; + +/* + * @test Visibility + * @bug 6843077 + * @summary test that type annotations are recorded in the classfile + */ + +public class Visibility { + public static void main(String[] args) throws Exception { + new Visibility().run(); + } + + public void run() throws Exception { + File javaFile = writeTestFile(); + File classFile = compileTestFile(javaFile); + + ClassFile cf = ClassFile.read(classFile); + for (Method m: cf.methods) { + test(cf, m); + } + + countAnnotations(); + + if (errors > 0) + throw new Exception(errors + " errors found"); + System.out.println("PASSED"); + } + + void test(ClassFile cf, Method m) { + test(cf, m, Attribute.RuntimeVisibleTypeAnnotations, true); + test(cf, m, Attribute.RuntimeInvisibleTypeAnnotations, false); + } + + // test the result of Attributes.getIndex according to expectations + // encoded in the method's name + void test(ClassFile cf, Method m, String name, boolean visible) { + int index = m.attributes.getIndex(cf.constant_pool, name); + if (index != -1) { + Attribute attr = m.attributes.get(index); + assert attr instanceof RuntimeTypeAnnotations_attribute; + RuntimeTypeAnnotations_attribute tAttr = (RuntimeTypeAnnotations_attribute)attr; + all += tAttr.annotations.length; + if (visible) + visibles += tAttr.annotations.length; + else + invisibles += tAttr.annotations.length; + } + } + + File writeTestFile() throws IOException { + File f = new File("Test.java"); + PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(f))); + out.println("import java.lang.annotation.ElementType;"); + out.println("import java.lang.annotation.Retention;"); + out.println("import java.lang.annotation.RetentionPolicy;"); + out.println("import java.lang.annotation.Target;"); + out.println("abstract class Test { "); + // visible annotations: RUNTIME + out.println(" @Retention(RetentionPolicy.RUNTIME)"); + out.println(" @Target(ElementType.TYPE_USE)"); + out.println(" @interface A { }"); + out.println(" void visible(@A Test this) { }"); + + // invisible annotations: CLASS + out.println(" @Retention(RetentionPolicy.CLASS)"); + out.println(" @Target(ElementType.TYPE_USE)"); + out.println(" @interface B { }"); + out.println(" void invisible(@B Test this) { }"); + + // source annotations + out.println(" @Retention(RetentionPolicy.SOURCE)"); + out.println(" @Target(ElementType.TYPE_USE)"); + out.println(" @interface C { }"); + out.println(" void source(@C Test this) { }"); + + // default visibility: CLASS + out.println(" @Target(ElementType.TYPE_USE)"); + out.println(" @interface D { }"); + out.println(" void def(@D Test this) { }"); + out.println("}"); + out.close(); + return f; + } + + File compileTestFile(File f) { + int rc = com.sun.tools.javac.Main.compile(new String[] { "-source", "1.8", "-g", f.getPath() }); + if (rc != 0) + throw new Error("compilation failed. rc=" + rc); + String path = f.getPath(); + return new File(path.substring(0, path.length() - 5) + ".class"); + } + + void countAnnotations() { + int expected_all = 3, expected_visibles = 1, expected_invisibles = 2; + + if (expected_all != all) { + errors++; + System.err.println("expected " + expected_all + + " annotations but found " + all); + } + + if (expected_visibles != visibles) { + errors++; + System.err.println("expected " + expected_visibles + + " visibles annotations but found " + visibles); + } + + if (expected_invisibles != invisibles) { + errors++; + System.err.println("expected " + expected_invisibles + + " invisibles annotations but found " + invisibles); + } + + } + + int errors; + int all; + int visibles; + int invisibles; +} diff --git a/langtools/test/tools/javap/typeAnnotations/Wildcards.java b/langtools/test/tools/javap/typeAnnotations/Wildcards.java new file mode 100644 index 00000000000..7e011b260d3 --- /dev/null +++ b/langtools/test/tools/javap/typeAnnotations/Wildcards.java @@ -0,0 +1,177 @@ +/* + * Copyright (c) 2009, 2013, 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. + * + * 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. + */ + +import java.io.*; +import com.sun.tools.classfile.*; + +/* + * @test Wildcards + * @bug 6843077 + * @summary test that annotations target wildcards get emitted to classfile + */ +public class Wildcards { + public static void main(String[] args) throws Exception { + new Wildcards().run(); + } + + public void run() throws Exception { + File javaFile = writeTestFile(); + File classFile = compileTestFile(javaFile); + + ClassFile cf = ClassFile.read(classFile); + test(cf); + for (Field f : cf.fields) { + test(cf, f); + } + for (Method m: cf.methods) { + test(cf, m); + } + + countAnnotations(); + + if (errors > 0) + throw new Exception(errors + " errors found"); + System.out.println("PASSED"); + } + + void test(ClassFile cf) { + test(cf, Attribute.RuntimeVisibleTypeAnnotations, true); + test(cf, Attribute.RuntimeInvisibleTypeAnnotations, false); + } + + void test(ClassFile cf, Method m) { + test(cf, m, Attribute.RuntimeVisibleTypeAnnotations, true); + test(cf, m, Attribute.RuntimeInvisibleTypeAnnotations, false); + } + + void test(ClassFile cf, Field m) { + test(cf, m, Attribute.RuntimeVisibleTypeAnnotations, true); + test(cf, m, Attribute.RuntimeInvisibleTypeAnnotations, false); + } + + // test the result of Attributes.getIndex according to expectations + // encoded in the method's name + void test(ClassFile cf, String name, boolean visible) { + int index = cf.attributes.getIndex(cf.constant_pool, name); + if (index != -1) { + Attribute attr = cf.attributes.get(index); + assert attr instanceof RuntimeTypeAnnotations_attribute; + RuntimeTypeAnnotations_attribute tAttr = (RuntimeTypeAnnotations_attribute)attr; + all += tAttr.annotations.length; + if (visible) + visibles += tAttr.annotations.length; + else + invisibles += tAttr.annotations.length; + } + } + + // test the result of Attributes.getIndex according to expectations + // encoded in the method's name + void test(ClassFile cf, Method m, String name, boolean visible) { + int index = m.attributes.getIndex(cf.constant_pool, name); + if (index != -1) { + Attribute attr = m.attributes.get(index); + assert attr instanceof RuntimeTypeAnnotations_attribute; + RuntimeTypeAnnotations_attribute tAttr = (RuntimeTypeAnnotations_attribute)attr; + all += tAttr.annotations.length; + if (visible) + visibles += tAttr.annotations.length; + else + invisibles += tAttr.annotations.length; + } + } + + // test the result of Attributes.getIndex according to expectations + // encoded in the method's name + void test(ClassFile cf, Field m, String name, boolean visible) { + int index = m.attributes.getIndex(cf.constant_pool, name); + if (index != -1) { + Attribute attr = m.attributes.get(index); + assert attr instanceof RuntimeTypeAnnotations_attribute; + RuntimeTypeAnnotations_attribute tAttr = (RuntimeTypeAnnotations_attribute)attr; + all += tAttr.annotations.length; + if (visible) + visibles += tAttr.annotations.length; + else + invisibles += tAttr.annotations.length; + } + } + + File writeTestFile() throws IOException { + File f = new File("Test.java"); + PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(f))); + out.println("import java.lang.annotation.*;"); + out.println("import java.util.*;"); + out.println("class Test { "); + out.println(" @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER})"); + out.println(" @interface A { }"); + + out.println(" List f;"); + + out.println(" List test(List p) {"); + out.println(" List l;"); // not counted... gets optimized away + out.println(" return null;"); + out.println(" }"); + out.println("}"); + + out.close(); + return f; + } + + File compileTestFile(File f) { + int rc = com.sun.tools.javac.Main.compile(new String[] { "-source", "1.8", "-g", f.getPath() }); + if (rc != 0) + throw new Error("compilation failed. rc=" + rc); + String path = f.getPath(); + return new File(path.substring(0, path.length() - 5) + ".class"); + } + + void countAnnotations() { + int expected_visibles = 0, expected_invisibles = 3; + int expected_all = expected_visibles + expected_invisibles; + + if (expected_all != all) { + errors++; + System.err.println("expected " + expected_all + + " annotations but found " + all); + } + + if (expected_visibles != visibles) { + errors++; + System.err.println("expected " + expected_visibles + + " visibles annotations but found " + visibles); + } + + if (expected_invisibles != invisibles) { + errors++; + System.err.println("expected " + expected_invisibles + + " invisibles annotations but found " + invisibles); + } + + } + + int errors; + int all; + int visibles; + int invisibles; +} From 89152955605ad92d71d5ed48e89f2571417ea40b Mon Sep 17 00:00:00 2001 From: Vladimir Kozlov Date: Wed, 23 Jan 2013 15:11:03 -0800 Subject: [PATCH 085/210] 8003878: compiler/7196199 test failed on OS X since 8b54, jdk7u12b01 Limit vectors size to 16 bytes on BSD until the problem is fixed Reviewed-by: twisti --- hotspot/src/cpu/x86/vm/vm_version_x86.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/hotspot/src/cpu/x86/vm/vm_version_x86.cpp b/hotspot/src/cpu/x86/vm/vm_version_x86.cpp index 01d99c37219..90066c1041a 100644 --- a/hotspot/src/cpu/x86/vm/vm_version_x86.cpp +++ b/hotspot/src/cpu/x86/vm/vm_version_x86.cpp @@ -661,6 +661,14 @@ void VM_Version::get_processor_features() { } } } +#if defined(COMPILER2) && defined(_ALLBSD_SOURCE) + if (MaxVectorSize > 16) { + // Limit vectors size to 16 bytes on BSD until it fixes + // restoring upper 128bit of YMM registers on return + // from signal handler. + FLAG_SET_DEFAULT(MaxVectorSize, 16); + } +#endif // COMPILER2 // Use population count instruction if available. if (supports_popcnt()) { From 6b27e0670184ea24ab6761a04de4e5437d8a1c2f Mon Sep 17 00:00:00 2001 From: Joe Darcy Date: Wed, 23 Jan 2013 20:11:07 -0800 Subject: [PATCH 086/210] 8006264: Add explanation of why default methods cannot be used in JDK 8 javax.lang.model Reviewed-by: jjg --- .../lang/model/element/AnnotationValueVisitor.java | 14 +++++++++++++- .../javax/lang/model/element/ElementVisitor.java | 14 +++++++++++++- .../classes/javax/lang/model/type/TypeVisitor.java | 12 ++++++++++++ .../util/AbstractAnnotationValueVisitor6.java | 9 +++++++++ .../util/AbstractAnnotationValueVisitor7.java | 11 ++++++++++- .../util/AbstractAnnotationValueVisitor8.java | 11 ++++++++++- .../lang/model/util/AbstractElementVisitor6.java | 11 ++++++++++- .../lang/model/util/AbstractElementVisitor7.java | 11 ++++++++++- .../lang/model/util/AbstractElementVisitor8.java | 11 ++++++++++- .../lang/model/util/AbstractTypeVisitor6.java | 9 +++++++++ .../lang/model/util/AbstractTypeVisitor7.java | 11 ++++++++++- .../lang/model/util/AbstractTypeVisitor8.java | 11 ++++++++++- .../javax/lang/model/util/ElementKindVisitor6.java | 11 ++++++++++- .../javax/lang/model/util/ElementKindVisitor7.java | 11 ++++++++++- .../javax/lang/model/util/ElementKindVisitor8.java | 11 ++++++++++- .../model/util/SimpleAnnotationValueVisitor6.java | 11 ++++++++++- .../model/util/SimpleAnnotationValueVisitor7.java | 11 ++++++++++- .../model/util/SimpleAnnotationValueVisitor8.java | 11 ++++++++++- .../lang/model/util/SimpleElementVisitor6.java | 11 ++++++++++- .../lang/model/util/SimpleElementVisitor7.java | 11 ++++++++++- .../lang/model/util/SimpleElementVisitor8.java | 11 ++++++++++- .../javax/lang/model/util/SimpleTypeVisitor6.java | 11 ++++++++++- .../javax/lang/model/util/SimpleTypeVisitor7.java | 11 ++++++++++- .../javax/lang/model/util/SimpleTypeVisitor8.java | 11 ++++++++++- .../javax/lang/model/util/TypeKindVisitor6.java | 11 ++++++++++- .../javax/lang/model/util/TypeKindVisitor7.java | 11 ++++++++++- .../javax/lang/model/util/TypeKindVisitor8.java | 11 ++++++++++- 27 files changed, 276 insertions(+), 24 deletions(-) diff --git a/langtools/src/share/classes/javax/lang/model/element/AnnotationValueVisitor.java b/langtools/src/share/classes/javax/lang/model/element/AnnotationValueVisitor.java index 888ab35f397..6d01d0f1734 100644 --- a/langtools/src/share/classes/javax/lang/model/element/AnnotationValueVisitor.java +++ b/langtools/src/share/classes/javax/lang/model/element/AnnotationValueVisitor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2013, 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 @@ -61,6 +61,18 @@ import javax.lang.model.type.TypeMirror; * parameters, return type, etc. rather than one of the abstract * classes. * + *

Note that methods to accommodate new language constructs could + * be added in a source compatible way if they were added as + * default methods. However, default methods are only + * available on Java SE 8 and higher releases and the {@code + * javax.lang.model.*} packages bundled in Java SE 8 are required to + * also be runnable on Java SE 7. Therefore, default methods + * cannot be used when extending {@code javax.lang.model.*} + * to cover Java SE 8 language features. However, default methods may + * be used in subsequent revisions of the {@code javax.lang.model.*} + * packages that are only required to run on Java SE 8 and higher + * platform versions. + * * @param the return type of this visitor's methods * @param

the type of the additional parameter to this visitor's methods. * @author Joseph D. Darcy diff --git a/langtools/src/share/classes/javax/lang/model/element/ElementVisitor.java b/langtools/src/share/classes/javax/lang/model/element/ElementVisitor.java index 34fb9328c6c..56c07bde4b8 100644 --- a/langtools/src/share/classes/javax/lang/model/element/ElementVisitor.java +++ b/langtools/src/share/classes/javax/lang/model/element/ElementVisitor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2013, 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 @@ -52,6 +52,18 @@ import javax.lang.model.util.*; * parameters, return type, etc. rather than one of the abstract * classes. * + *

Note that methods to accommodate new language constructs could + * be added in a source compatible way if they were added as + * default methods. However, default methods are only + * available on Java SE 8 and higher releases and the {@code + * javax.lang.model.*} packages bundled in Java SE 8 are required to + * also be runnable on Java SE 7. Therefore, default methods + * cannot be used when extending {@code javax.lang.model.*} + * to cover Java SE 8 language features. However, default methods may + * be used in subsequent revisions of the {@code javax.lang.model.*} + * packages that are only required to run on Java SE 8 and higher + * platform versions. + * * @param the return type of this visitor's methods. Use {@link * Void} for visitors that do not need to return results. * @param

the type of the additional parameter to this visitor's diff --git a/langtools/src/share/classes/javax/lang/model/type/TypeVisitor.java b/langtools/src/share/classes/javax/lang/model/type/TypeVisitor.java index b59cce20b74..2d8674d6512 100644 --- a/langtools/src/share/classes/javax/lang/model/type/TypeVisitor.java +++ b/langtools/src/share/classes/javax/lang/model/type/TypeVisitor.java @@ -52,6 +52,18 @@ import javax.lang.model.element.*; * parameters, return type, etc. rather than one of the abstract * classes. * + *

Note that methods to accommodate new language constructs could + * be added in a source compatible way if they were added as + * default methods. However, default methods are only + * available on Java SE 8 and higher releases and the {@code + * javax.lang.model.*} packages bundled in Java SE 8 are required to + * also be runnable on Java SE 7. Therefore, default methods + * cannot be used when extending {@code javax.lang.model.*} + * to cover Java SE 8 language features. However, default methods may + * be used in subsequent revisions of the {@code javax.lang.model.*} + * packages that are only required to run on Java SE 8 and higher + * platform versions. + * * @param the return type of this visitor's methods. Use {@link * Void} for visitors that do not need to return results. * @param

the type of the additional parameter to this visitor's diff --git a/langtools/src/share/classes/javax/lang/model/util/AbstractAnnotationValueVisitor6.java b/langtools/src/share/classes/javax/lang/model/util/AbstractAnnotationValueVisitor6.java index 109349aa612..2d4d6b4e4b5 100644 --- a/langtools/src/share/classes/javax/lang/model/util/AbstractAnnotationValueVisitor6.java +++ b/langtools/src/share/classes/javax/lang/model/util/AbstractAnnotationValueVisitor6.java @@ -54,6 +54,15 @@ import javax.annotation.processing.SupportedSourceVersion; * behavior for the visit method in question. When the new visitor is * introduced, all or portions of this visitor may be deprecated. * + *

Note that adding a default implementation of a new visit method + * in a visitor class will occur instead of adding a default + * method directly in the visitor interface since a Java SE 8 + * language feature cannot be used to this version of the API since + * this version is required to be runnable on Java SE 7 + * implementations. Future versions of the API that are only required + * to run on Java SE 8 and later may take advantage of default methods + * in this situation. + * * @param the return type of this visitor's methods * @param

the type of the additional parameter to this visitor's methods. * diff --git a/langtools/src/share/classes/javax/lang/model/util/AbstractAnnotationValueVisitor7.java b/langtools/src/share/classes/javax/lang/model/util/AbstractAnnotationValueVisitor7.java index 35a93718615..ae2438e065e 100644 --- a/langtools/src/share/classes/javax/lang/model/util/AbstractAnnotationValueVisitor7.java +++ b/langtools/src/share/classes/javax/lang/model/util/AbstractAnnotationValueVisitor7.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2013, 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 @@ -51,6 +51,15 @@ import javax.annotation.processing.SupportedSourceVersion; * behavior for the visit method in question. When the new visitor is * introduced, all or portions of this visitor may be deprecated. * + *

Note that adding a default implementation of a new visit method + * in a visitor class will occur instead of adding a default + * method directly in the visitor interface since a Java SE 8 + * language feature cannot be used to this version of the API since + * this version is required to be runnable on Java SE 7 + * implementations. Future versions of the API that are only required + * to run on Java SE 8 and later may take advantage of default methods + * in this situation. + * * @param the return type of this visitor's methods * @param

the type of the additional parameter to this visitor's methods. * diff --git a/langtools/src/share/classes/javax/lang/model/util/AbstractAnnotationValueVisitor8.java b/langtools/src/share/classes/javax/lang/model/util/AbstractAnnotationValueVisitor8.java index c7a0f7be70f..47c25598d61 100644 --- a/langtools/src/share/classes/javax/lang/model/util/AbstractAnnotationValueVisitor8.java +++ b/langtools/src/share/classes/javax/lang/model/util/AbstractAnnotationValueVisitor8.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2013, 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 @@ -51,6 +51,15 @@ import javax.annotation.processing.SupportedSourceVersion; * behavior for the visit method in question. When the new visitor is * introduced, all or portions of this visitor may be deprecated. * + *

Note that adding a default implementation of a new visit method + * in a visitor class will occur instead of adding a default + * method directly in the visitor interface since a Java SE 8 + * language feature cannot be used to this version of the API since + * this version is required to be runnable on Java SE 7 + * implementations. Future versions of the API that are only required + * to run on Java SE 8 and later may take advantage of default methods + * in this situation. + * * @param the return type of this visitor's methods * @param

the type of the additional parameter to this visitor's methods. * diff --git a/langtools/src/share/classes/javax/lang/model/util/AbstractElementVisitor6.java b/langtools/src/share/classes/javax/lang/model/util/AbstractElementVisitor6.java index 8e1d65613d5..2ce7465d151 100644 --- a/langtools/src/share/classes/javax/lang/model/util/AbstractElementVisitor6.java +++ b/langtools/src/share/classes/javax/lang/model/util/AbstractElementVisitor6.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2013, 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 @@ -53,6 +53,15 @@ import static javax.lang.model.SourceVersion.*; * visit method in question. When the new visitor is introduced, all * or portions of this visitor may be deprecated. * + *

Note that adding a default implementation of a new visit method + * in a visitor class will occur instead of adding a default + * method directly in the visitor interface since a Java SE 8 + * language feature cannot be used to this version of the API since + * this version is required to be runnable on Java SE 7 + * implementations. Future versions of the API that are only required + * to run on Java SE 8 and later may take advantage of default methods + * in this situation. + * * @param the return type of this visitor's methods. Use {@link * Void} for visitors that do not need to return results. * @param

the type of the additional parameter to this visitor's diff --git a/langtools/src/share/classes/javax/lang/model/util/AbstractElementVisitor7.java b/langtools/src/share/classes/javax/lang/model/util/AbstractElementVisitor7.java index 0e5d8daeebc..f5c87e46d0f 100644 --- a/langtools/src/share/classes/javax/lang/model/util/AbstractElementVisitor7.java +++ b/langtools/src/share/classes/javax/lang/model/util/AbstractElementVisitor7.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2013, 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 @@ -52,6 +52,15 @@ import static javax.lang.model.SourceVersion.*; * visit method in question. When the new visitor is introduced, all * or portions of this visitor may be deprecated. * + *

Note that adding a default implementation of a new visit method + * in a visitor class will occur instead of adding a default + * method directly in the visitor interface since a Java SE 8 + * language feature cannot be used to this version of the API since + * this version is required to be runnable on Java SE 7 + * implementations. Future versions of the API that are only required + * to run on Java SE 8 and later may take advantage of default methods + * in this situation. + * * @param the return type of this visitor's methods. Use {@link * Void} for visitors that do not need to return results. * @param

the type of the additional parameter to this visitor's diff --git a/langtools/src/share/classes/javax/lang/model/util/AbstractElementVisitor8.java b/langtools/src/share/classes/javax/lang/model/util/AbstractElementVisitor8.java index b4afe113fac..fb99d187f36 100644 --- a/langtools/src/share/classes/javax/lang/model/util/AbstractElementVisitor8.java +++ b/langtools/src/share/classes/javax/lang/model/util/AbstractElementVisitor8.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2013, 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 @@ -52,6 +52,15 @@ import static javax.lang.model.SourceVersion.*; * visit method in question. When the new visitor is introduced, all * or portions of this visitor may be deprecated. * + *

Note that adding a default implementation of a new visit method + * in a visitor class will occur instead of adding a default + * method directly in the visitor interface since a Java SE 8 + * language feature cannot be used to this version of the API since + * this version is required to be runnable on Java SE 7 + * implementations. Future versions of the API that are only required + * to run on Java SE 8 and later may take advantage of default methods + * in this situation. + * * @param the return type of this visitor's methods. Use {@link * Void} for visitors that do not need to return results. * @param

the type of the additional parameter to this visitor's diff --git a/langtools/src/share/classes/javax/lang/model/util/AbstractTypeVisitor6.java b/langtools/src/share/classes/javax/lang/model/util/AbstractTypeVisitor6.java index aa07280c91a..0ae91ef0977 100644 --- a/langtools/src/share/classes/javax/lang/model/util/AbstractTypeVisitor6.java +++ b/langtools/src/share/classes/javax/lang/model/util/AbstractTypeVisitor6.java @@ -49,6 +49,15 @@ import javax.lang.model.type.*; * visit method in question. When the new visitor is introduced, all * or portions of this visitor may be deprecated. * + *

Note that adding a default implementation of a new visit method + * in a visitor class will occur instead of adding a default + * method directly in the visitor interface since a Java SE 8 + * language feature cannot be used to this version of the API since + * this version is required to be runnable on Java SE 7 + * implementations. Future versions of the API that are only required + * to run on Java SE 8 and later may take advantage of default methods + * in this situation. + * * @param the return type of this visitor's methods. Use {@link * Void} for visitors that do not need to return results. * @param

the type of the additional parameter to this visitor's diff --git a/langtools/src/share/classes/javax/lang/model/util/AbstractTypeVisitor7.java b/langtools/src/share/classes/javax/lang/model/util/AbstractTypeVisitor7.java index 7deefe9bed7..3fe08dcc1db 100644 --- a/langtools/src/share/classes/javax/lang/model/util/AbstractTypeVisitor7.java +++ b/langtools/src/share/classes/javax/lang/model/util/AbstractTypeVisitor7.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2013, 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 @@ -49,6 +49,15 @@ import javax.lang.model.type.*; * visit method in question. When the new visitor is introduced, all * or portions of this visitor may be deprecated. * + *

Note that adding a default implementation of a new visit method + * in a visitor class will occur instead of adding a default + * method directly in the visitor interface since a Java SE 8 + * language feature cannot be used to this version of the API since + * this version is required to be runnable on Java SE 7 + * implementations. Future versions of the API that are only required + * to run on Java SE 8 and later may take advantage of default methods + * in this situation. + * * @param the return type of this visitor's methods. Use {@link * Void} for visitors that do not need to return results. * @param

the type of the additional parameter to this visitor's diff --git a/langtools/src/share/classes/javax/lang/model/util/AbstractTypeVisitor8.java b/langtools/src/share/classes/javax/lang/model/util/AbstractTypeVisitor8.java index 5713b24b82b..a23b6e7fc5b 100644 --- a/langtools/src/share/classes/javax/lang/model/util/AbstractTypeVisitor8.java +++ b/langtools/src/share/classes/javax/lang/model/util/AbstractTypeVisitor8.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2013, 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 @@ -49,6 +49,15 @@ import javax.lang.model.type.*; * visit method in question. When the new visitor is introduced, all * or portions of this visitor may be deprecated. * + *

Note that adding a default implementation of a new visit method + * in a visitor class will occur instead of adding a default + * method directly in the visitor interface since a Java SE 8 + * language feature cannot be used to this version of the API since + * this version is required to be runnable on Java SE 7 + * implementations. Future versions of the API that are only required + * to run on Java SE 8 and later may take advantage of default methods + * in this situation. + * * @param the return type of this visitor's methods. Use {@link * Void} for visitors that do not need to return results. * @param

the type of the additional parameter to this visitor's diff --git a/langtools/src/share/classes/javax/lang/model/util/ElementKindVisitor6.java b/langtools/src/share/classes/javax/lang/model/util/ElementKindVisitor6.java index f1ad3fed21f..9925955ed9a 100644 --- a/langtools/src/share/classes/javax/lang/model/util/ElementKindVisitor6.java +++ b/langtools/src/share/classes/javax/lang/model/util/ElementKindVisitor6.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2013, 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 @@ -67,6 +67,15 @@ import javax.lang.model.SourceVersion; * for the visit method in question. When the new visitor is * introduced, all or portions of this visitor may be deprecated. * + *

Note that adding a default implementation of a new visit method + * in a visitor class will occur instead of adding a default + * method directly in the visitor interface since a Java SE 8 + * language feature cannot be used to this version of the API since + * this version is required to be runnable on Java SE 7 + * implementations. Future versions of the API that are only required + * to run on Java SE 8 and later may take advantage of default methods + * in this situation. + * * @param the return type of this visitor's methods. Use {@link * Void} for visitors that do not need to return results. * @param

the type of the additional parameter to this visitor's diff --git a/langtools/src/share/classes/javax/lang/model/util/ElementKindVisitor7.java b/langtools/src/share/classes/javax/lang/model/util/ElementKindVisitor7.java index 25a68a909f7..ebaeb6ba67b 100644 --- a/langtools/src/share/classes/javax/lang/model/util/ElementKindVisitor7.java +++ b/langtools/src/share/classes/javax/lang/model/util/ElementKindVisitor7.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2013, 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 @@ -65,6 +65,15 @@ import static javax.lang.model.SourceVersion.*; * for the visit method in question. When the new visitor is * introduced, all or portions of this visitor may be deprecated. * + *

Note that adding a default implementation of a new visit method + * in a visitor class will occur instead of adding a default + * method directly in the visitor interface since a Java SE 8 + * language feature cannot be used to this version of the API since + * this version is required to be runnable on Java SE 7 + * implementations. Future versions of the API that are only required + * to run on Java SE 8 and later may take advantage of default methods + * in this situation. + * * @param the return type of this visitor's methods. Use {@link * Void} for visitors that do not need to return results. * @param

the type of the additional parameter to this visitor's diff --git a/langtools/src/share/classes/javax/lang/model/util/ElementKindVisitor8.java b/langtools/src/share/classes/javax/lang/model/util/ElementKindVisitor8.java index d5ea0f6f960..61ccc789073 100644 --- a/langtools/src/share/classes/javax/lang/model/util/ElementKindVisitor8.java +++ b/langtools/src/share/classes/javax/lang/model/util/ElementKindVisitor8.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2013, 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 @@ -65,6 +65,15 @@ import javax.lang.model.SourceVersion; * for the visit method in question. When the new visitor is * introduced, all or portions of this visitor may be deprecated. * + *

Note that adding a default implementation of a new visit method + * in a visitor class will occur instead of adding a default + * method directly in the visitor interface since a Java SE 8 + * language feature cannot be used to this version of the API since + * this version is required to be runnable on Java SE 7 + * implementations. Future versions of the API that are only required + * to run on Java SE 8 and later may take advantage of default methods + * in this situation. + * * @param the return type of this visitor's methods. Use {@link * Void} for visitors that do not need to return results. * @param

the type of the additional parameter to this visitor's diff --git a/langtools/src/share/classes/javax/lang/model/util/SimpleAnnotationValueVisitor6.java b/langtools/src/share/classes/javax/lang/model/util/SimpleAnnotationValueVisitor6.java index b2995723564..1bb58b96376 100644 --- a/langtools/src/share/classes/javax/lang/model/util/SimpleAnnotationValueVisitor6.java +++ b/langtools/src/share/classes/javax/lang/model/util/SimpleAnnotationValueVisitor6.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2013, 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 @@ -63,6 +63,15 @@ import javax.annotation.processing.SupportedSourceVersion; * behavior for the visit method in question. When the new visitor is * introduced, all or portions of this visitor may be deprecated. * + *

Note that adding a default implementation of a new visit method + * in a visitor class will occur instead of adding a default + * method directly in the visitor interface since a Java SE 8 + * language feature cannot be used to this version of the API since + * this version is required to be runnable on Java SE 7 + * implementations. Future versions of the API that are only required + * to run on Java SE 8 and later may take advantage of default methods + * in this situation. + * * @param the return type of this visitor's methods * @param

the type of the additional parameter to this visitor's methods. * diff --git a/langtools/src/share/classes/javax/lang/model/util/SimpleAnnotationValueVisitor7.java b/langtools/src/share/classes/javax/lang/model/util/SimpleAnnotationValueVisitor7.java index 2e3cfafcc70..0a442111cf7 100644 --- a/langtools/src/share/classes/javax/lang/model/util/SimpleAnnotationValueVisitor7.java +++ b/langtools/src/share/classes/javax/lang/model/util/SimpleAnnotationValueVisitor7.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2013, 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 @@ -58,6 +58,15 @@ import static javax.lang.model.SourceVersion.*; * behavior for the visit method in question. When the new visitor is * introduced, all or portions of this visitor may be deprecated. * + *

Note that adding a default implementation of a new visit method + * in a visitor class will occur instead of adding a default + * method directly in the visitor interface since a Java SE 8 + * language feature cannot be used to this version of the API since + * this version is required to be runnable on Java SE 7 + * implementations. Future versions of the API that are only required + * to run on Java SE 8 and later may take advantage of default methods + * in this situation. + * * @param the return type of this visitor's methods * @param

the type of the additional parameter to this visitor's methods. * diff --git a/langtools/src/share/classes/javax/lang/model/util/SimpleAnnotationValueVisitor8.java b/langtools/src/share/classes/javax/lang/model/util/SimpleAnnotationValueVisitor8.java index 30823cdd584..1b84d328ca8 100644 --- a/langtools/src/share/classes/javax/lang/model/util/SimpleAnnotationValueVisitor8.java +++ b/langtools/src/share/classes/javax/lang/model/util/SimpleAnnotationValueVisitor8.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2013, 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 @@ -58,6 +58,15 @@ import static javax.lang.model.SourceVersion.*; * behavior for the visit method in question. When the new visitor is * introduced, all or portions of this visitor may be deprecated. * + *

Note that adding a default implementation of a new visit method + * in a visitor class will occur instead of adding a default + * method directly in the visitor interface since a Java SE 8 + * language feature cannot be used to this version of the API since + * this version is required to be runnable on Java SE 7 + * implementations. Future versions of the API that are only required + * to run on Java SE 8 and later may take advantage of default methods + * in this situation. + * * @param the return type of this visitor's methods * @param

the type of the additional parameter to this visitor's methods. * diff --git a/langtools/src/share/classes/javax/lang/model/util/SimpleElementVisitor6.java b/langtools/src/share/classes/javax/lang/model/util/SimpleElementVisitor6.java index a0055f76cfe..8c7ff87fbd9 100644 --- a/langtools/src/share/classes/javax/lang/model/util/SimpleElementVisitor6.java +++ b/langtools/src/share/classes/javax/lang/model/util/SimpleElementVisitor6.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2013, 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 @@ -65,6 +65,15 @@ import static javax.lang.model.SourceVersion.*; * visit method in question. When the new visitor is introduced, all * or portions of this visitor may be deprecated. * + *

Note that adding a default implementation of a new visit method + * in a visitor class will occur instead of adding a default + * method directly in the visitor interface since a Java SE 8 + * language feature cannot be used to this version of the API since + * this version is required to be runnable on Java SE 7 + * implementations. Future versions of the API that are only required + * to run on Java SE 8 and later may take advantage of default methods + * in this situation. + * * @param the return type of this visitor's methods. Use {@code Void} * for visitors that do not need to return results. * @param

the type of the additional parameter to this visitor's methods. Use {@code Void} diff --git a/langtools/src/share/classes/javax/lang/model/util/SimpleElementVisitor7.java b/langtools/src/share/classes/javax/lang/model/util/SimpleElementVisitor7.java index 5d54cff9333..b9df9c49e1c 100644 --- a/langtools/src/share/classes/javax/lang/model/util/SimpleElementVisitor7.java +++ b/langtools/src/share/classes/javax/lang/model/util/SimpleElementVisitor7.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2013, 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 @@ -62,6 +62,15 @@ import static javax.lang.model.SourceVersion.*; * visit method in question. When the new visitor is introduced, all * or portions of this visitor may be deprecated. * + *

Note that adding a default implementation of a new visit method + * in a visitor class will occur instead of adding a default + * method directly in the visitor interface since a Java SE 8 + * language feature cannot be used to this version of the API since + * this version is required to be runnable on Java SE 7 + * implementations. Future versions of the API that are only required + * to run on Java SE 8 and later may take advantage of default methods + * in this situation. + * * @param the return type of this visitor's methods. Use {@code Void} * for visitors that do not need to return results. * @param

the type of the additional parameter to this visitor's methods. Use {@code Void} diff --git a/langtools/src/share/classes/javax/lang/model/util/SimpleElementVisitor8.java b/langtools/src/share/classes/javax/lang/model/util/SimpleElementVisitor8.java index 63cacd00f3c..f0cb871c99c 100644 --- a/langtools/src/share/classes/javax/lang/model/util/SimpleElementVisitor8.java +++ b/langtools/src/share/classes/javax/lang/model/util/SimpleElementVisitor8.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2013, 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 @@ -61,6 +61,15 @@ import static javax.lang.model.SourceVersion.*; * visit method in question. When the new visitor is introduced, all * or portions of this visitor may be deprecated. * + *

Note that adding a default implementation of a new visit method + * in a visitor class will occur instead of adding a default + * method directly in the visitor interface since a Java SE 8 + * language feature cannot be used to this version of the API since + * this version is required to be runnable on Java SE 7 + * implementations. Future versions of the API that are only required + * to run on Java SE 8 and later may take advantage of default methods + * in this situation. + * * @param the return type of this visitor's methods. Use {@code Void} * for visitors that do not need to return results. * @param

the type of the additional parameter to this visitor's methods. Use {@code Void} diff --git a/langtools/src/share/classes/javax/lang/model/util/SimpleTypeVisitor6.java b/langtools/src/share/classes/javax/lang/model/util/SimpleTypeVisitor6.java index 7fadd6de08d..5d1b3d7a309 100644 --- a/langtools/src/share/classes/javax/lang/model/util/SimpleTypeVisitor6.java +++ b/langtools/src/share/classes/javax/lang/model/util/SimpleTypeVisitor6.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2013, 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 @@ -64,6 +64,15 @@ import static javax.lang.model.SourceVersion.*; * visit method in question. When the new visitor is introduced, all * or portions of this visitor may be deprecated. * + *

Note that adding a default implementation of a new visit method + * in a visitor class will occur instead of adding a default + * method directly in the visitor interface since a Java SE 8 + * language feature cannot be used to this version of the API since + * this version is required to be runnable on Java SE 7 + * implementations. Future versions of the API that are only required + * to run on Java SE 8 and later may take advantage of default methods + * in this situation. + * * @param the return type of this visitor's methods. Use {@link * Void} for visitors that do not need to return results. * @param

the type of the additional parameter to this visitor's diff --git a/langtools/src/share/classes/javax/lang/model/util/SimpleTypeVisitor7.java b/langtools/src/share/classes/javax/lang/model/util/SimpleTypeVisitor7.java index dfb1f5d9187..66eb20aafa7 100644 --- a/langtools/src/share/classes/javax/lang/model/util/SimpleTypeVisitor7.java +++ b/langtools/src/share/classes/javax/lang/model/util/SimpleTypeVisitor7.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2013, 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 @@ -61,6 +61,15 @@ import static javax.lang.model.SourceVersion.*; * visit method in question. When the new visitor is introduced, all * or portions of this visitor may be deprecated. * + *

Note that adding a default implementation of a new visit method + * in a visitor class will occur instead of adding a default + * method directly in the visitor interface since a Java SE 8 + * language feature cannot be used to this version of the API since + * this version is required to be runnable on Java SE 7 + * implementations. Future versions of the API that are only required + * to run on Java SE 8 and later may take advantage of default methods + * in this situation. + * * @param the return type of this visitor's methods. Use {@link * Void} for visitors that do not need to return results. * @param

the type of the additional parameter to this visitor's diff --git a/langtools/src/share/classes/javax/lang/model/util/SimpleTypeVisitor8.java b/langtools/src/share/classes/javax/lang/model/util/SimpleTypeVisitor8.java index fc023d869c2..c4faae9f45e 100644 --- a/langtools/src/share/classes/javax/lang/model/util/SimpleTypeVisitor8.java +++ b/langtools/src/share/classes/javax/lang/model/util/SimpleTypeVisitor8.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2013, 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 @@ -60,6 +60,15 @@ import static javax.lang.model.SourceVersion.*; * visit method in question. When the new visitor is introduced, all * or portions of this visitor may be deprecated. * + *

Note that adding a default implementation of a new visit method + * in a visitor class will occur instead of adding a default + * method directly in the visitor interface since a Java SE 8 + * language feature cannot be used to this version of the API since + * this version is required to be runnable on Java SE 7 + * implementations. Future versions of the API that are only required + * to run on Java SE 8 and later may take advantage of default methods + * in this situation. + * * @param the return type of this visitor's methods. Use {@link * Void} for visitors that do not need to return results. * @param

the type of the additional parameter to this visitor's diff --git a/langtools/src/share/classes/javax/lang/model/util/TypeKindVisitor6.java b/langtools/src/share/classes/javax/lang/model/util/TypeKindVisitor6.java index 9e007fe54f3..3add039d49a 100644 --- a/langtools/src/share/classes/javax/lang/model/util/TypeKindVisitor6.java +++ b/langtools/src/share/classes/javax/lang/model/util/TypeKindVisitor6.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2013, 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 @@ -63,6 +63,15 @@ import static javax.lang.model.SourceVersion.*; * method in question. When the new visitor is introduced, all or * portions of this visitor may be deprecated. * + *

Note that adding a default implementation of a new visit method + * in a visitor class will occur instead of adding a default + * method directly in the visitor interface since a Java SE 8 + * language feature cannot be used to this version of the API since + * this version is required to be runnable on Java SE 7 + * implementations. Future versions of the API that are only required + * to run on Java SE 8 and later may take advantage of default methods + * in this situation. + * * @param the return type of this visitor's methods. Use {@link * Void} for visitors that do not need to return results. * @param

the type of the additional parameter to this visitor's diff --git a/langtools/src/share/classes/javax/lang/model/util/TypeKindVisitor7.java b/langtools/src/share/classes/javax/lang/model/util/TypeKindVisitor7.java index 4bbe1d6635a..a0a0c1276a3 100644 --- a/langtools/src/share/classes/javax/lang/model/util/TypeKindVisitor7.java +++ b/langtools/src/share/classes/javax/lang/model/util/TypeKindVisitor7.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2013, 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 @@ -63,6 +63,15 @@ import javax.lang.model.SourceVersion; * method in question. When the new visitor is introduced, all or * portions of this visitor may be deprecated. * + *

Note that adding a default implementation of a new visit method + * in a visitor class will occur instead of adding a default + * method directly in the visitor interface since a Java SE 8 + * language feature cannot be used to this version of the API since + * this version is required to be runnable on Java SE 7 + * implementations. Future versions of the API that are only required + * to run on Java SE 8 and later may take advantage of default methods + * in this situation. + * * @param the return type of this visitor's methods. Use {@link * Void} for visitors that do not need to return results. * @param

the type of the additional parameter to this visitor's diff --git a/langtools/src/share/classes/javax/lang/model/util/TypeKindVisitor8.java b/langtools/src/share/classes/javax/lang/model/util/TypeKindVisitor8.java index 698364f791e..60b3b6125d1 100644 --- a/langtools/src/share/classes/javax/lang/model/util/TypeKindVisitor8.java +++ b/langtools/src/share/classes/javax/lang/model/util/TypeKindVisitor8.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2013, 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 @@ -63,6 +63,15 @@ import static javax.lang.model.SourceVersion.*; * method in question. When the new visitor is introduced, all or * portions of this visitor may be deprecated. * + *

Note that adding a default implementation of a new visit method + * in a visitor class will occur instead of adding a default + * method directly in the visitor interface since a Java SE 8 + * language feature cannot be used to this version of the API since + * this version is required to be runnable on Java SE 7 + * implementations. Future versions of the API that are only required + * to run on Java SE 8 and later may take advantage of default methods + * in this situation. + * * @param the return type of this visitor's methods. Use {@link * Void} for visitors that do not need to return results. * @param

the type of the additional parameter to this visitor's From ae1a2f5e3c8f92b39804dcba66b984bde4292880 Mon Sep 17 00:00:00 2001 From: Krystal Mo Date: Thu, 24 Jan 2013 02:03:38 -0800 Subject: [PATCH 087/210] 8006758: LinkResolver assertion (caused by @Contended changes) Treat anonymous classes as privileged code to restore the special handling for @Compiled during class file parsing Reviewed-by: jrose, coleenp, kvn, dholmes --- hotspot/src/share/vm/classfile/classFileParser.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/hotspot/src/share/vm/classfile/classFileParser.cpp b/hotspot/src/share/vm/classfile/classFileParser.cpp index e0558af122b..557707ba432 100644 --- a/hotspot/src/share/vm/classfile/classFileParser.cpp +++ b/hotspot/src/share/vm/classfile/classFileParser.cpp @@ -1802,11 +1802,9 @@ ClassFileParser::AnnotationCollector::ID ClassFileParser::AnnotationCollector::annotation_index(ClassLoaderData* loader_data, Symbol* name) { vmSymbols::SID sid = vmSymbols::find_sid(name); - bool privileged = false; - if (loader_data->is_the_null_class_loader_data()) { - // Privileged code can use all annotations. Other code silently drops some. - privileged = true; - } + // Privileged code can use all annotations. Other code silently drops some. + bool privileged = loader_data->is_the_null_class_loader_data() || + loader_data->is_anonymous(); switch (sid) { case vmSymbols::VM_SYMBOL_ENUM_NAME(java_lang_invoke_ForceInline_signature): if (_location != _in_method) break; // only allow for methods From 27c881b2fbb927f27ab3bb2f0f22c69ec947620b Mon Sep 17 00:00:00 2001 From: Ioi Lam Date: Thu, 24 Jan 2013 10:57:38 -0800 Subject: [PATCH 088/210] 8006280: Need to reorder metadata structures to reduce size (64-bit) Reordered Klass, InstanceKlass and Method to save 8 bytes each Reviewed-by: coleenp, jiangli --- hotspot/src/share/vm/oops/instanceKlass.hpp | 19 ++++++++++--------- hotspot/src/share/vm/oops/klass.hpp | 16 ++++++++-------- hotspot/src/share/vm/oops/method.hpp | 2 +- 3 files changed, 19 insertions(+), 18 deletions(-) diff --git a/hotspot/src/share/vm/oops/instanceKlass.hpp b/hotspot/src/share/vm/oops/instanceKlass.hpp index 97b3dd23313..2d3aa4835f0 100644 --- a/hotspot/src/share/vm/oops/instanceKlass.hpp +++ b/hotspot/src/share/vm/oops/instanceKlass.hpp @@ -256,6 +256,16 @@ class InstanceKlass: public Klass { // JVMTI fields can be moved to their own structure - see 6315920 unsigned char * _cached_class_file_bytes; // JVMTI: cached class file, before retransformable agent modified it in CFLH jint _cached_class_file_len; // JVMTI: length of above + + volatile u2 _idnum_allocated_count; // JNI/JVMTI: increments with the addition of methods, old ids don't change + + // Class states are defined as ClassState (see above). + // Place the _init_state here to utilize the unused 2-byte after + // _idnum_allocated_count. + u1 _init_state; // state of class + u1 _reference_type; // reference type + + JvmtiCachedClassFieldMap* _jvmti_cached_class_field_map; // JVMTI: used during heap iteration // Method array. @@ -281,15 +291,6 @@ class InstanceKlass: public Klass { // ... Array* _fields; - volatile u2 _idnum_allocated_count; // JNI/JVMTI: increments with the addition of methods, old ids don't change - - // Class states are defined as ClassState (see above). - // Place the _init_state here to utilize the unused 2-byte after - // _idnum_allocated_count. - u1 _init_state; // state of class - - u1 _reference_type; // reference type - // embedded Java vtable follows here // embedded Java itables follows here // embedded static fields follows here diff --git a/hotspot/src/share/vm/oops/klass.hpp b/hotspot/src/share/vm/oops/klass.hpp index be5d0c5293d..245499e39da 100644 --- a/hotspot/src/share/vm/oops/klass.hpp +++ b/hotspot/src/share/vm/oops/klass.hpp @@ -75,11 +75,11 @@ // [class_loader_data] // [modifier_flags] // [access_flags ] -// [verify_count ] - not in product -// [alloc_count ] // [last_biased_lock_bulk_revocation_time] (64 bits) // [prototype_header] // [biased_lock_revocation_count] +// [verify_count ] - not in product +// [alloc_count ] // [_modified_oops] // [_accumulated_modified_oops] // [trace_id] @@ -164,18 +164,18 @@ class Klass : public Metadata { jint _modifier_flags; // Processed access flags, for use by Class.getModifiers. AccessFlags _access_flags; // Access flags. The class/interface distinction is stored here. -#ifndef PRODUCT - int _verify_count; // to avoid redundant verifies -#endif - - juint _alloc_count; // allocation profiling support - // Biased locking implementation and statistics // (the 64-bit chunk goes first, to avoid some fragmentation) jlong _last_biased_lock_bulk_revocation_time; markOop _prototype_header; // Used when biased locking is both enabled and disabled for this type jint _biased_lock_revocation_count; +#ifndef PRODUCT + int _verify_count; // to avoid redundant verifies +#endif + + juint _alloc_count; // allocation profiling support + TRACE_DEFINE_KLASS_TRACE_ID; // Remembered sets support for the oops in the klasses. diff --git a/hotspot/src/share/vm/oops/method.hpp b/hotspot/src/share/vm/oops/method.hpp index 72a4faf11d7..802467b8ec2 100644 --- a/hotspot/src/share/vm/oops/method.hpp +++ b/hotspot/src/share/vm/oops/method.hpp @@ -127,8 +127,8 @@ class Method : public Metadata { InvocationCounter _backedge_counter; // Incremented before each backedge taken - used to trigger frequencey-based optimizations #ifdef TIERED - jlong _prev_time; // Previous time the rate was acquired float _rate; // Events (invocation and backedge counter increments) per millisecond + jlong _prev_time; // Previous time the rate was acquired #endif #ifndef PRODUCT From 5288b84f0aeceba081a97e25314c92ece5322abd Mon Sep 17 00:00:00 2001 From: David Katleman Date: Thu, 24 Jan 2013 16:48:33 -0800 Subject: [PATCH 089/210] Added tag jdk8-b74 for changeset dde885cc8685 --- .hgtags-top-repo | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags-top-repo b/.hgtags-top-repo index 8555b3366ec..53096d3923b 100644 --- a/.hgtags-top-repo +++ b/.hgtags-top-repo @@ -195,3 +195,4 @@ cdb401a60cea6ad5ef3f498725ed1decf8dda1ea jdk8-b68 51ad2a34342055333eb5f36e2fb514b027895708 jdk8-b71 c1be681d80a1f1c848dc671d664fccb19e046a12 jdk8-b72 93b9664f97eeb6f89397a8842318ebacaac9feb9 jdk8-b73 +b43aa5bd8ca5c8121336495382d35ecfa7a71536 jdk8-b74 From ad11d38f92225e708f8bbecd30706a5c7587e87c Mon Sep 17 00:00:00 2001 From: David Katleman Date: Thu, 24 Jan 2013 16:48:39 -0800 Subject: [PATCH 090/210] Added tag jdk8-b74 for changeset 5a4f1fb4c6ef --- corba/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/corba/.hgtags b/corba/.hgtags index 1a3ee17d1bb..c01bb26f197 100644 --- a/corba/.hgtags +++ b/corba/.hgtags @@ -195,3 +195,4 @@ d54dc53e223ed9ce7d5f4d2cd02ad9d5def3c2db jdk8-b59 8171d23e914d758836527b80b06debcfdb718f2d jdk8-b71 cb40427f47145b01b7e53c3e02b38ff7625efbda jdk8-b72 191afde59e7be0e1a1d76d06f2a32ff17444f0ec jdk8-b73 +2132845cf5f717ff5c240a2431c0c0e03e66e3a5 jdk8-b74 From 86f89a0768cf6004a1a812b563f73aa7b14e24eb Mon Sep 17 00:00:00 2001 From: David Katleman Date: Thu, 24 Jan 2013 16:48:45 -0800 Subject: [PATCH 091/210] Added tag jdk8-b74 for changeset 8d54b69d4504 --- hotspot/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/hotspot/.hgtags b/hotspot/.hgtags index 617e00e138a..ad0530d1939 100644 --- a/hotspot/.hgtags +++ b/hotspot/.hgtags @@ -308,3 +308,4 @@ e94068d4ff52849c8aa0786a53a59b63d1312a39 jdk8-b70 d5cb5830f570d1304ea4b196dde672a291b55f29 jdk8-b72 1e129851479e4f5df439109fca2c7be1f1613522 hs25-b15 11619f33cd683c2f1d6ef72f1c6ff3dacf5a9f1c jdk8-b73 +1a3e54283c54aaa8b3437813e8507fbdc966e5b6 jdk8-b74 From 23ff2911e336618477b224006fc09a3445b3c76e Mon Sep 17 00:00:00 2001 From: David Katleman Date: Thu, 24 Jan 2013 16:48:57 -0800 Subject: [PATCH 092/210] Added tag jdk8-b74 for changeset 6ab75b6a0432 --- jaxp/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/jaxp/.hgtags b/jaxp/.hgtags index 4d8f24840a0..25b3727d9e6 100644 --- a/jaxp/.hgtags +++ b/jaxp/.hgtags @@ -195,3 +195,4 @@ b854e70084214e9dcf1b37373f6e4b1a68760e03 jdk8-b68 499be952a291cec1dc774a84a238941d6faf772d jdk8-b71 bdf2af722a6b54fca47d8c51d17a1b8f41dd7a3e jdk8-b72 84946404d1e1de003ed2bf218ef8d48906a90e37 jdk8-b73 +2087e24a4357eceb6432e94918e75fdc706a27d6 jdk8-b74 From bdd8df2f1b527287f39e0b2cea26fb909aa3276a Mon Sep 17 00:00:00 2001 From: David Katleman Date: Thu, 24 Jan 2013 16:49:01 -0800 Subject: [PATCH 093/210] Added tag jdk8-b74 for changeset f0f3e46c8780 --- jaxws/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/jaxws/.hgtags b/jaxws/.hgtags index f4bf9b21b81..1ae97b3df38 100644 --- a/jaxws/.hgtags +++ b/jaxws/.hgtags @@ -195,3 +195,4 @@ d3fe408f3a9ad250bc9a4e9365bdfc3f28c1d3f4 jdk8-b68 f577a39c9fb3d5820248c13c2cc74a192a9313e0 jdk8-b71 d9707230294d54e695e745a90de6112909100f12 jdk8-b72 c606f644a5d9118c14b5822738bf23c300f14f24 jdk8-b73 +12db3c5a3393b03eeb09ff26f418c4420c21aaab jdk8-b74 From 90c6fdd5060867be1f49e818b2f30822f983458c Mon Sep 17 00:00:00 2001 From: David Katleman Date: Thu, 24 Jan 2013 16:49:37 -0800 Subject: [PATCH 094/210] Added tag jdk8-b74 for changeset 2d74b1d7456b --- langtools/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/langtools/.hgtags b/langtools/.hgtags index cd611eef514..f4fbd85e67d 100644 --- a/langtools/.hgtags +++ b/langtools/.hgtags @@ -195,3 +195,4 @@ d7360bf35ee1f40ff78c2e83a22b5446ee464346 jdk8-b69 467e4d9281bcf119eaec42af1423c96bd401871c jdk8-b71 6f0986ed9b7e11d6eb06618f27e20b18f19fb797 jdk8-b72 8d0baee36c7184d55c80354b45704c37d6b7ac79 jdk8-b73 +56c97aff46bb577b8668874154c24115a7e8a3e8 jdk8-b74 From 020fe75e6778dbf5033ec7e965b42fc1de17a9e2 Mon Sep 17 00:00:00 2001 From: Serguei Spitsyn Date: Thu, 24 Jan 2013 22:13:32 -0800 Subject: [PATCH 095/210] 8005128: JSR 292: the mlvm redefineClassInBootstrap test crashes in ConstantPool::compare_entry_to When constant pool is copied in merge_constant_pools the invokedynamic operands must be copied before. Reviewed-by: coleenp, twisti --- hotspot/src/share/vm/oops/constantPool.cpp | 62 +++++++++++-------- hotspot/src/share/vm/oops/constantPool.hpp | 1 + .../share/vm/prims/jvmtiRedefineClasses.cpp | 13 +++- 3 files changed, 46 insertions(+), 30 deletions(-) diff --git a/hotspot/src/share/vm/oops/constantPool.cpp b/hotspot/src/share/vm/oops/constantPool.cpp index d4fa72032df..3dd91fed4fb 100644 --- a/hotspot/src/share/vm/oops/constantPool.cpp +++ b/hotspot/src/share/vm/oops/constantPool.cpp @@ -1098,32 +1098,9 @@ bool ConstantPool::compare_entry_to(int index1, constantPoolHandle cp2, } // end compare_entry_to() -// Copy this constant pool's entries at start_i to end_i (inclusive) -// to the constant pool to_cp's entries starting at to_i. A total of -// (end_i - start_i) + 1 entries are copied. -void ConstantPool::copy_cp_to_impl(constantPoolHandle from_cp, int start_i, int end_i, - constantPoolHandle to_cp, int to_i, TRAPS) { - - int dest_i = to_i; // leave original alone for debug purposes - - for (int src_i = start_i; src_i <= end_i; /* see loop bottom */ ) { - copy_entry_to(from_cp, src_i, to_cp, dest_i, CHECK); - - switch (from_cp->tag_at(src_i).value()) { - case JVM_CONSTANT_Double: - case JVM_CONSTANT_Long: - // double and long take two constant pool entries - src_i += 2; - dest_i += 2; - break; - - default: - // all others take one constant pool entry - src_i++; - dest_i++; - break; - } - } +void ConstantPool::copy_operands(constantPoolHandle from_cp, + constantPoolHandle to_cp, + TRAPS) { int from_oplen = operand_array_length(from_cp->operands()); int old_oplen = operand_array_length(to_cp->operands()); @@ -1179,8 +1156,39 @@ void ConstantPool::copy_cp_to_impl(constantPoolHandle from_cp, int start_i, int to_cp->set_operands(new_operands); } } +} // end copy_operands() -} // end copy_cp_to() + +// Copy this constant pool's entries at start_i to end_i (inclusive) +// to the constant pool to_cp's entries starting at to_i. A total of +// (end_i - start_i) + 1 entries are copied. +void ConstantPool::copy_cp_to_impl(constantPoolHandle from_cp, int start_i, int end_i, + constantPoolHandle to_cp, int to_i, TRAPS) { + + + int dest_i = to_i; // leave original alone for debug purposes + + for (int src_i = start_i; src_i <= end_i; /* see loop bottom */ ) { + copy_entry_to(from_cp, src_i, to_cp, dest_i, CHECK); + + switch (from_cp->tag_at(src_i).value()) { + case JVM_CONSTANT_Double: + case JVM_CONSTANT_Long: + // double and long take two constant pool entries + src_i += 2; + dest_i += 2; + break; + + default: + // all others take one constant pool entry + src_i++; + dest_i++; + break; + } + } + copy_operands(from_cp, to_cp, CHECK); + +} // end copy_cp_to_impl() // Copy this constant pool's entry at from_i to the constant pool diff --git a/hotspot/src/share/vm/oops/constantPool.hpp b/hotspot/src/share/vm/oops/constantPool.hpp index ea4b13f0f9d..de38d727b6b 100644 --- a/hotspot/src/share/vm/oops/constantPool.hpp +++ b/hotspot/src/share/vm/oops/constantPool.hpp @@ -781,6 +781,7 @@ class ConstantPool : public Metadata { } static void copy_cp_to_impl(constantPoolHandle from_cp, int start_i, int end_i, constantPoolHandle to_cp, int to_i, TRAPS); static void copy_entry_to(constantPoolHandle from_cp, int from_i, constantPoolHandle to_cp, int to_i, TRAPS); + static void copy_operands(constantPoolHandle from_cp, constantPoolHandle to_cp, TRAPS); int find_matching_entry(int pattern_i, constantPoolHandle search_cp, TRAPS); int version() const { return _saved._version; } void set_version(int version) { _saved._version = version; } diff --git a/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp b/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp index 7255579280b..bae742b535d 100644 --- a/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp +++ b/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp @@ -1122,6 +1122,8 @@ bool VM_RedefineClasses::merge_constant_pools(constantPoolHandle old_cp, } } // end for each old_cp entry + ConstantPool::copy_operands(old_cp, *merge_cp_p, CHECK_0); + // We don't need to sanity check that *merge_cp_length_p is within // *merge_cp_p bounds since we have the minimum on-entry check above. (*merge_cp_length_p) = old_i; @@ -1305,8 +1307,12 @@ jvmtiError VM_RedefineClasses::merge_cp_and_rewrite( _index_map_count = 0; _index_map_p = new intArray(scratch_cp->length(), -1); + // reference to the cp holder is needed for copy_operands() + merge_cp->set_pool_holder(scratch_class()); bool result = merge_constant_pools(old_cp, scratch_cp, &merge_cp, &merge_cp_length, THREAD); + merge_cp->set_pool_holder(NULL); + if (!result) { // The merge can fail due to memory allocation failure or due // to robustness checks. @@ -2380,13 +2386,14 @@ void VM_RedefineClasses::set_new_constant_pool( assert(version != 0, "sanity check"); smaller_cp->set_version(version); + // attach klass to new constant pool + // reference to the cp holder is needed for copy_operands() + smaller_cp->set_pool_holder(scratch_class()); + scratch_cp->copy_cp_to(1, scratch_cp_length - 1, smaller_cp, 1, THREAD); scratch_cp = smaller_cp; // attach new constant pool to klass - scratch_cp->set_pool_holder(scratch_class()); - - // attach klass to new constant pool scratch_class->set_constants(scratch_cp()); int i; // for portability From 19303cc71d772a97ac56d490ba220637597c3b56 Mon Sep 17 00:00:00 2001 From: Yunda Date: Thu, 24 Jan 2013 23:30:45 -0800 Subject: [PATCH 096/210] 8005278: Serviceability Agent: jmap -heap and jstack -m fail BinaryTreeDictionary is typedef'ed as AFLBinaryTreeDictionary in vmStructs and in SA we still use old name for that. FreeList now is a template based class which is not reflect in SA type library. When SA does calculation of heap for CMS, the former will cause failure to retrieve BinaryTreeDictionary sine the rename. The later will fail wherever it is used in SA. Reviewed-by: dholmes, sla, coleenp --- ...eeDictionary.java => AFLBinaryTreeDictionary.java} | 10 +++++----- .../jvm/hotspot/memory/CompactibleFreeListSpace.java | 6 +++--- .../classes/sun/jvm/hotspot/memory/FreeList.java | 4 ++-- .../concurrentMarkSweep/vmStructs_cms.hpp | 11 ++++++----- 4 files changed, 16 insertions(+), 15 deletions(-) rename hotspot/agent/src/share/classes/sun/jvm/hotspot/memory/{BinaryTreeDictionary.java => AFLBinaryTreeDictionary.java} (85%) diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/memory/BinaryTreeDictionary.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/memory/AFLBinaryTreeDictionary.java similarity index 85% rename from hotspot/agent/src/share/classes/sun/jvm/hotspot/memory/BinaryTreeDictionary.java rename to hotspot/agent/src/share/classes/sun/jvm/hotspot/memory/AFLBinaryTreeDictionary.java index 802af91bbc7..5b56cf5f815 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/memory/BinaryTreeDictionary.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/memory/AFLBinaryTreeDictionary.java @@ -1,6 +1,6 @@ /* * @(#)BinaryTreeDictionary.java - * Copyright (c) 2000, 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2013, 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 @@ -30,7 +30,7 @@ import sun.jvm.hotspot.debugger.*; import sun.jvm.hotspot.types.*; import sun.jvm.hotspot.runtime.*; -public class BinaryTreeDictionary extends VMObject { +public class AFLBinaryTreeDictionary extends VMObject { static { VM.registerVMInitializedObserver(new Observer() { public void update(Observable o, Object data) { @@ -40,8 +40,8 @@ public class BinaryTreeDictionary extends VMObject { } private static synchronized void initialize(TypeDataBase db) { - Type type = db.lookupType("BinaryTreeDictionary"); - totalSizeField = type.getCIntegerField("_totalSize"); + Type type = db.lookupType("AFLBinaryTreeDictionary"); + totalSizeField = type.getCIntegerField("_total_size"); } // Fields @@ -53,7 +53,7 @@ public class BinaryTreeDictionary extends VMObject { } // Constructor - public BinaryTreeDictionary(Address addr) { + public AFLBinaryTreeDictionary(Address addr) { super(addr); } } diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/memory/CompactibleFreeListSpace.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/memory/CompactibleFreeListSpace.java index c2e8200b694..f47f0e81127 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/memory/CompactibleFreeListSpace.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/memory/CompactibleFreeListSpace.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2013, 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 @@ -117,9 +117,9 @@ public class CompactibleFreeListSpace extends CompactibleSpace { } // large block - BinaryTreeDictionary bfbd = (BinaryTreeDictionary) VMObjectFactory.newObject(BinaryTreeDictionary.class, + AFLBinaryTreeDictionary aflbd = (AFLBinaryTreeDictionary) VMObjectFactory.newObject(AFLBinaryTreeDictionary.class, dictionaryField.getValue(addr)); - size += bfbd.size(); + size += aflbd.size(); // linear block in TLAB diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/memory/FreeList.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/memory/FreeList.java index 23d7c3d34ee..2d0024e1d2d 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/memory/FreeList.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/memory/FreeList.java @@ -1,7 +1,7 @@ /* * @(#)FreeList.java * - * Copyright (c) 2000, 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2013, 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 @@ -41,7 +41,7 @@ public class FreeList extends VMObject { } private static synchronized void initialize(TypeDataBase db) { - Type type = db.lookupType("FreeList"); + Type type = db.lookupType("FreeList"); sizeField = type.getCIntegerField("_size"); countField = type.getCIntegerField("_count"); headerSize = type.getSize(); diff --git a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/vmStructs_cms.hpp b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/vmStructs_cms.hpp index a67e19d89d2..cc0a33f4013 100644 --- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/vmStructs_cms.hpp +++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/vmStructs_cms.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2013, 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 @@ -34,16 +34,17 @@ typedef BinaryTreeDictionary AFLBinaryTreeDictionar nonstatic_field(CompactibleFreeListSpace, _bt, BlockOffsetArrayNonContigSpace) \ \ nonstatic_field(CMSBitMap, _bmWordSize, size_t) \ - nonstatic_field(CMSBitMap, _shifter, const int) \ - nonstatic_field(CMSBitMap, _bm, BitMap) \ - nonstatic_field(CMSBitMap, _virtual_space, VirtualSpace) \ + nonstatic_field(CMSBitMap, _shifter, const int) \ + nonstatic_field(CMSBitMap, _bm, BitMap) \ + nonstatic_field(CMSBitMap, _virtual_space, VirtualSpace) \ nonstatic_field(CMSCollector, _markBitMap, CMSBitMap) \ nonstatic_field(ConcurrentMarkSweepGeneration, _cmsSpace, CompactibleFreeListSpace*) \ static_field(ConcurrentMarkSweepThread, _collector, CMSCollector*) \ nonstatic_field(LinearAllocBlock, _word_size, size_t) \ nonstatic_field(AFLBinaryTreeDictionary, _total_size, size_t) \ nonstatic_field(CompactibleFreeListSpace, _indexedFreeList[0], FreeList) \ - nonstatic_field(CompactibleFreeListSpace, _smallLinearAllocBlock, LinearAllocBlock) + nonstatic_field(CompactibleFreeListSpace, _smallLinearAllocBlock, LinearAllocBlock) \ + nonstatic_field(CompactibleFreeListSpace, _dictionary, FreeBlockDictionary*) #define VM_TYPES_CMS(declare_type, \ From 25189c1a6a17cd7e8e3440d07803afa61f9d3a30 Mon Sep 17 00:00:00 2001 From: Christian Tornqvist Date: Fri, 25 Jan 2013 10:14:22 +0100 Subject: [PATCH 097/210] 8006413: Add utility classes for writing better multiprocess tests in jtreg Add a few utility classes to test/testlibrary to support multi process testing in jtreg tests. Added a test case for one of the utility classes. Also reviewed by Vitaly Davidovich Reviewed-by: brutisso, dholmes, vlivanov, nloodin, mgerdin --- .../test/testlibrary/OutputAnalyzerTest.java | 108 ++++++++++ .../java/testlibrary/JDKToolFinder.java | 50 +++++ .../java/testlibrary/OutputAnalyzer.java | 191 ++++++++++++++++++ .../oracle/java/testlibrary/OutputBuffer.java | 59 ++++++ .../oracle/java/testlibrary/ProcessTools.java | 141 +++++++++++++ .../oracle/java/testlibrary/StreamPumper.java | 76 +++++++ 6 files changed, 625 insertions(+) create mode 100644 hotspot/test/testlibrary/OutputAnalyzerTest.java create mode 100644 hotspot/test/testlibrary/com/oracle/java/testlibrary/JDKToolFinder.java create mode 100644 hotspot/test/testlibrary/com/oracle/java/testlibrary/OutputAnalyzer.java create mode 100644 hotspot/test/testlibrary/com/oracle/java/testlibrary/OutputBuffer.java create mode 100644 hotspot/test/testlibrary/com/oracle/java/testlibrary/ProcessTools.java create mode 100644 hotspot/test/testlibrary/com/oracle/java/testlibrary/StreamPumper.java diff --git a/hotspot/test/testlibrary/OutputAnalyzerTest.java b/hotspot/test/testlibrary/OutputAnalyzerTest.java new file mode 100644 index 00000000000..cc48fd3ff43 --- /dev/null +++ b/hotspot/test/testlibrary/OutputAnalyzerTest.java @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2013, 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. + * + * 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. + */ + +/* + * @test + * @summary Test the OutputAnalyzer utility class + * @library /testlibrary + */ + +import com.oracle.java.testlibrary.OutputAnalyzer; + +public class OutputAnalyzerTest { + + public static void main(String args[]) throws Exception { + + String stdout = "aaaaaa"; + String stderr = "bbbbbb"; + + OutputAnalyzer output = new OutputAnalyzer(stdout, stderr); + + if (!stdout.equals(output.getStdout())) { + throw new Exception("getStdout() returned '" + output.getStdout() + "', expected '" + stdout + "'"); + } + + if (!stderr.equals(output.getStderr())) { + throw new Exception("getStderr() returned '" + output.getStderr() + "', expected '" + stderr + "'"); + } + + try { + output.shouldContain(stdout); + output.stdoutShouldContain(stdout); + output.shouldContain(stderr); + output.stderrShouldContain(stderr); + } catch (RuntimeException e) { + throw new Exception("shouldContain() failed", e); + } + + try { + output.shouldContain("cccc"); + throw new Exception("shouldContain() failed to throw exception"); + } catch (RuntimeException e) { + // expected + } + + try { + output.stdoutShouldContain(stderr); + throw new Exception("stdoutShouldContain() failed to throw exception"); + } catch (RuntimeException e) { + // expected + } + + try { + output.stderrShouldContain(stdout); + throw new Exception("stdoutShouldContain() failed to throw exception"); + } catch (RuntimeException e) { + // expected + } + + try { + output.shouldNotContain("cccc"); + output.stdoutShouldNotContain("cccc"); + output.stderrShouldNotContain("cccc"); + } catch (RuntimeException e) { + throw new Exception("shouldNotContain() failed", e); + } + + try { + output.shouldNotContain(stdout); + throw new Exception("shouldContain() failed to throw exception"); + } catch (RuntimeException e) { + // expected + } + + try { + output.stdoutShouldNotContain(stdout); + throw new Exception("shouldContain() failed to throw exception"); + } catch (RuntimeException e) { + // expected + } + + try { + output.stderrShouldNotContain(stderr); + throw new Exception("shouldContain() failed to throw exception"); + } catch (RuntimeException e) { + // expected + } + } +} diff --git a/hotspot/test/testlibrary/com/oracle/java/testlibrary/JDKToolFinder.java b/hotspot/test/testlibrary/com/oracle/java/testlibrary/JDKToolFinder.java new file mode 100644 index 00000000000..91ad6a8c8a9 --- /dev/null +++ b/hotspot/test/testlibrary/com/oracle/java/testlibrary/JDKToolFinder.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2013, 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. + * + * 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. + */ + +package com.oracle.java.testlibrary; + +import java.io.File; + +public final class JDKToolFinder { + + private JDKToolFinder() { + } + + /** + * Returns the full path to an executable in jdk/bin based on System property + * test.jdk (set by jtreg test suite) + * + * @return Full path to an executable in jdk/bin + */ + public static String getJDKTool(String tool) { + String binPath = System.getProperty("test.jdk"); + if (binPath == null) { + throw new RuntimeException("System property 'test.jdk' not set. This property is normally set by jtreg. " + + "When running test separately, set this property using '-Dtest.jdk=/path/to/jdk'."); + } + + binPath += File.separatorChar + "bin" + File.separatorChar + tool; + + return binPath; + } +} diff --git a/hotspot/test/testlibrary/com/oracle/java/testlibrary/OutputAnalyzer.java b/hotspot/test/testlibrary/com/oracle/java/testlibrary/OutputAnalyzer.java new file mode 100644 index 00000000000..469d0c24a70 --- /dev/null +++ b/hotspot/test/testlibrary/com/oracle/java/testlibrary/OutputAnalyzer.java @@ -0,0 +1,191 @@ +/* + * Copyright (c) 2013, 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. + * + * 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. + */ + +package com.oracle.java.testlibrary; + +import java.io.IOException; + +public final class OutputAnalyzer { + + private final String stdout; + private final String stderr; + private final int exitValue; + + /** + * Create an OutputAnalyzer, a utility class for verifying output and exit + * value from a Process + * + * @param process Process to analyze + * @throws IOException If an I/O error occurs. + */ + public OutputAnalyzer(Process process) throws IOException { + OutputBuffer output = ProcessTools.getOutput(process); + exitValue = process.exitValue(); + this.stdout = output.getStdout(); + this.stderr = output.getStderr(); + } + + /** + * Create an OutputAnalyzer, a utility class for verifying output + * + * @param buf String buffer to analyze + */ + public OutputAnalyzer(String buf) { + this(buf, buf); + } + + /** + * Create an OutputAnalyzer, a utility class for verifying output + * + * @param stdout stdout buffer to analyze + * @param stderr stderr buffer to analyze + */ + public OutputAnalyzer(String stdout, String stderr) { + this.stdout = stdout; + this.stderr = stderr; + exitValue = -1; + } + + /** + * Verify that the stdout and stderr contents of output buffer contains the string + * + * @param expectedString String that buffer should contain + * @throws RuntimeException If the string was not found + */ + public void shouldContain(String expectedString) { + if (!stdout.contains(expectedString) && !stderr.contains(expectedString)) { + throw new RuntimeException("'" + expectedString + "' missing from stdout/stderr: [" + stdout + stderr + "]\n"); + } + } + + /** + * Verify that the stdout contents of output buffer contains the string + * + * @param expectedString String that buffer should contain + * @throws RuntimeException If the string was not found + */ + public void stdoutShouldContain(String expectedString) { + if (!stdout.contains(expectedString)) { + throw new RuntimeException("'" + expectedString + "' missing from stdout: [" + stdout + "]\n"); + } + } + + /** + * Verify that the stderr contents of output buffer contains the string + * + * @param expectedString String that buffer should contain + * @throws RuntimeException If the string was not found + */ + public void stderrShouldContain(String expectedString) { + if (!stderr.contains(expectedString)) { + throw new RuntimeException("'" + expectedString + "' missing from stderr: [" + stderr + "]\n"); + } + } + + /** + * Verify that the stdout and stderr contents of output buffer does not contain the string + * + * @param expectedString String that the buffer should not contain + * @throws RuntimeException If the string was found + */ + public void shouldNotContain(String notExpectedString) { + if (stdout.contains(notExpectedString)) { + throw new RuntimeException("'" + notExpectedString + "' found in stdout: [" + stdout + "]\n"); + } + if (stderr.contains(notExpectedString)) { + throw new RuntimeException("'" + notExpectedString + "' found in stderr: [" + stderr + "]\n"); + } + } + + /** + * Verify that the stdout contents of output buffer does not contain the string + * + * @param expectedString String that the buffer should not contain + * @throws RuntimeException If the string was found + */ + public void stdoutShouldNotContain(String notExpectedString) { + if (stdout.contains(notExpectedString)) { + throw new RuntimeException("'" + notExpectedString + "' found in stdout: [" + stdout + "]\n"); + } + } + + /** + * Verify that the stderr contents of output buffer does not contain the string + * + * @param expectedString String that the buffer should not contain + * @throws RuntimeException If the string was found + */ + public void stderrShouldNotContain(String notExpectedString) { + if (stderr.contains(notExpectedString)) { + throw new RuntimeException("'" + notExpectedString + "' found in stderr: [" + stderr + "]\n"); + } + } + + /** + * Verifiy the exit value of the process + * + * @param expectedExitValue Expected exit value from process + * @throws RuntimeException If the exit value from the process did not match the expected value + */ + public void shouldHaveExitValue(int expectedExitValue) { + if (getExitValue() != expectedExitValue) { + throw new RuntimeException("Exit value " + getExitValue() + " , expected to get " + expectedExitValue); + } + } + + /** + * Get the contents of the output buffer (stdout and stderr) + * + * @return Content of the output buffer + */ + public String getOutput() { + return stdout + stderr; + } + + /** + * Get the contents of the stdout buffer + * + * @return Content of the stdout buffer + */ + public String getStdout() { + return stdout; + } + + /** + * Get the contents of the stderr buffer + * + * @return Content of the stderr buffer + */ + public String getStderr() { + return stderr; + } + + /** + * Get the process exit value + * + * @return Process exit value + */ + public int getExitValue() { + return exitValue; + } +} diff --git a/hotspot/test/testlibrary/com/oracle/java/testlibrary/OutputBuffer.java b/hotspot/test/testlibrary/com/oracle/java/testlibrary/OutputBuffer.java new file mode 100644 index 00000000000..b98d05650f5 --- /dev/null +++ b/hotspot/test/testlibrary/com/oracle/java/testlibrary/OutputBuffer.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2013, 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. + * + * 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. + */ + +package com.oracle.java.testlibrary; + +public class OutputBuffer { + private final String stdout; + private final String stderr; + + /** + * Create an OutputBuffer, a class for storing and managing stdout and stderr + * results separately + * + * @param stdout stdout result + * @param stderr stderr result + */ + public OutputBuffer(String stdout, String stderr) { + this.stdout = stdout; + this.stderr = stderr; + } + + /** + * Returns the stdout result + * + * @return stdout result + */ + public String getStdout() { + return stdout; + } + + /** + * Returns the stderr result + * + * @return stderr result + */ + public String getStderr() { + return stderr; + } +} diff --git a/hotspot/test/testlibrary/com/oracle/java/testlibrary/ProcessTools.java b/hotspot/test/testlibrary/com/oracle/java/testlibrary/ProcessTools.java new file mode 100644 index 00000000000..42203d17ff0 --- /dev/null +++ b/hotspot/test/testlibrary/com/oracle/java/testlibrary/ProcessTools.java @@ -0,0 +1,141 @@ +/* + * Copyright (c) 2013, 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. + * + * 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. + */ + +package com.oracle.java.testlibrary; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.lang.management.ManagementFactory; +import java.lang.management.RuntimeMXBean; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Collections; + +import sun.management.VMManagement; + +public final class ProcessTools { + + private ProcessTools() { + } + + /** + * Pumps stdout and stderr from running the process into a String. + * + * @param processHandler ProcessHandler to run. + * @return Output from process. + * @throws IOException If an I/O error occurs. + */ + public static OutputBuffer getOutput(ProcessBuilder processBuilder) throws IOException { + return getOutput(processBuilder.start()); + } + + /** + * Pumps stdout and stderr the running process into a String. + * + * @param process Process to pump. + * @return Output from process. + * @throws IOException If an I/O error occurs. + */ + public static OutputBuffer getOutput(Process process) throws IOException { + ByteArrayOutputStream stderrBuffer = new ByteArrayOutputStream(); + ByteArrayOutputStream stdoutBuffer = new ByteArrayOutputStream(); + StreamPumper outPumper = new StreamPumper(process.getInputStream(), stdoutBuffer); + StreamPumper errPumper = new StreamPumper(process.getErrorStream(), stderrBuffer); + Thread outPumperThread = new Thread(outPumper); + Thread errPumperThread = new Thread(errPumper); + + outPumperThread.setDaemon(true); + errPumperThread.setDaemon(true); + + outPumperThread.start(); + errPumperThread.start(); + + try { + process.waitFor(); + outPumperThread.join(); + errPumperThread.join(); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + return null; + } + + return new OutputBuffer(stdoutBuffer.toString(), stderrBuffer.toString()); + } + + /** + * Get the process id of the current running Java process + * + * @return Process id + */ + public static int getProcessId() throws Exception { + + // Get the current process id using a reflection hack + RuntimeMXBean runtime = ManagementFactory.getRuntimeMXBean(); + Field jvm = runtime.getClass().getDeclaredField("jvm"); + + jvm.setAccessible(true); + VMManagement mgmt = (sun.management.VMManagement) jvm.get(runtime); + + Method pid_method = mgmt.getClass().getDeclaredMethod("getProcessId"); + + pid_method.setAccessible(true); + + int pid = (Integer) pid_method.invoke(mgmt); + + return pid; + } + + /** + * Get platform specific VM arguments (e.g. -d64 on 64bit Solaris) + * + * @return String[] with platform specific arguments, empty if there are none + */ + public static String[] getPlatformSpecificVMArgs() { + String osName = System.getProperty("os.name"); + String dataModel = System.getProperty("sun.arch.data.model"); + + if (osName.equals("SunOS") && dataModel.equals("64")) { + return new String[] { "-d64" }; + } + + return new String[] {}; + } + + /** + * Create ProcessBuilder using the java launcher from the jdk to be tested and + * with any platform specific arguments prepended + */ + public static ProcessBuilder createJavaProcessBuilder(String... command) throws Exception { + String javapath = JDKToolFinder.getJDKTool("java"); + + ArrayList args = new ArrayList<>(); + args.add(javapath); + Collections.addAll(args, getPlatformSpecificVMArgs()); + Collections.addAll(args, command); + + return new ProcessBuilder(args.toArray(new String[args.size()])); + + } + +} diff --git a/hotspot/test/testlibrary/com/oracle/java/testlibrary/StreamPumper.java b/hotspot/test/testlibrary/com/oracle/java/testlibrary/StreamPumper.java new file mode 100644 index 00000000000..4631bce6175 --- /dev/null +++ b/hotspot/test/testlibrary/com/oracle/java/testlibrary/StreamPumper.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2013, 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. + * + * 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. + */ + +package com.oracle.java.testlibrary; + +import java.io.OutputStream; +import java.io.InputStream; +import java.io.IOException; + +public final class StreamPumper implements Runnable { + + private static final int BUF_SIZE = 256; + + private final OutputStream out; + private final InputStream in; + + /** + * Create a StreamPumper that reads from in and writes to out. + * + * @param in The stream to read from. + * @param out The stream to write to. + */ + public StreamPumper(InputStream in, OutputStream out) { + this.in = in; + this.out = out; + } + + /** + * Implements Thread.run(). Continuously read from in and write + * to out until in has reached end of stream. Abort + * on interruption. Abort on IOExceptions. + */ + @Override + public void run() { + int length; + InputStream localIn = in; + OutputStream localOut = out; + byte[] buffer = new byte[BUF_SIZE]; + + try { + while (!Thread.interrupted() && (length = localIn.read(buffer)) > 0) { + localOut.write(buffer, 0, length); + } + } catch (IOException e) { + // Just abort if something like this happens. + e.printStackTrace(); + } finally { + try { + localOut.flush(); + in.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } +} From 6e9aeb35208ec7e95bafc1d75e2807c91024f6ef Mon Sep 17 00:00:00 2001 From: Alejandro Murillo Date: Fri, 25 Jan 2013 02:36:28 -0800 Subject: [PATCH 098/210] Added tag hs25-b17 for changeset f767fc368725 --- hotspot/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/hotspot/.hgtags b/hotspot/.hgtags index 54ddc0b1e90..d46eb646def 100644 --- a/hotspot/.hgtags +++ b/hotspot/.hgtags @@ -310,3 +310,4 @@ d5cb5830f570d1304ea4b196dde672a291b55f29 jdk8-b72 11619f33cd683c2f1d6ef72f1c6ff3dacf5a9f1c jdk8-b73 70c89bd6b895a10d25ca70e08093c09ff2005fda hs25-b16 1a3e54283c54aaa8b3437813e8507fbdc966e5b6 jdk8-b74 +b4391649e91ea8d37f66317a03d6d2573a93d10d hs25-b17 From 0c7d523859b5fb9ec6256599add317a6607de387 Mon Sep 17 00:00:00 2001 From: Alejandro Murillo Date: Fri, 25 Jan 2013 03:03:23 -0800 Subject: [PATCH 099/210] 8006827: new hotspot build - hs25-b18 Reviewed-by: jcoomes --- hotspot/make/hotspot_version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hotspot/make/hotspot_version b/hotspot/make/hotspot_version index c47d3d18289..6f09485a3a3 100644 --- a/hotspot/make/hotspot_version +++ b/hotspot/make/hotspot_version @@ -35,7 +35,7 @@ HOTSPOT_VM_COPYRIGHT=Copyright 2013 HS_MAJOR_VER=25 HS_MINOR_VER=0 -HS_BUILD_NUMBER=17 +HS_BUILD_NUMBER=18 JDK_MAJOR_VER=1 JDK_MINOR_VER=8 From fc0efc91c80fecca6e8ee15b4e6054f0af9eea6d Mon Sep 17 00:00:00 2001 From: Zhengyu Gu Date: Fri, 25 Jan 2013 10:04:08 -0500 Subject: [PATCH 100/210] 8000692: Remove old KERNEL code Removed depreciated kernel VM source code from hotspot VM Reviewed-by: dholmes, acorn --- hotspot/make/Makefile | 54 +----------- hotspot/make/bsd/makefiles/dtrace.make | 12 +-- hotspot/make/solaris/Makefile | 22 +---- hotspot/make/solaris/makefiles/dtrace.make | 12 +-- hotspot/make/solaris/makefiles/kernel.make | 32 ------- hotspot/make/windows/build.bat | 5 +- hotspot/make/windows/create_obj_files.sh | 7 +- hotspot/make/windows/makefiles/defs.make | 17 +--- .../windows/makefiles/projectcreator.make | 59 +------------ hotspot/make/windows/makefiles/vm.make | 6 +- hotspot/src/cpu/x86/vm/assembler_x86.hpp | 4 +- .../share/vm/classfile/systemDictionary.cpp | 83 +------------------ .../share/vm/classfile/systemDictionary.hpp | 6 +- hotspot/src/share/vm/classfile/vmSymbols.hpp | 3 +- hotspot/src/share/vm/prims/jniCheck.hpp | 4 +- hotspot/src/share/vm/prims/jvm.cpp | 4 - .../share/vm/prims/jvmtiCodeBlobEvents.hpp | 4 +- hotspot/src/share/vm/prims/jvmtiEnv.cpp | 6 +- hotspot/src/share/vm/prims/jvmtiEnvBase.cpp | 12 +-- hotspot/src/share/vm/prims/jvmtiExport.cpp | 6 +- .../src/share/vm/prims/jvmtiExtensions.hpp | 4 +- hotspot/src/share/vm/prims/jvmtiImpl.cpp | 6 +- hotspot/src/share/vm/prims/jvmtiImpl.hpp | 5 +- .../src/share/vm/prims/jvmtiRawMonitor.hpp | 4 +- .../share/vm/prims/jvmtiRedefineClasses.cpp | 2 - hotspot/src/share/vm/prims/jvmtiTagMap.hpp | 4 +- hotspot/src/share/vm/runtime/arguments.cpp | 35 +------- hotspot/src/share/vm/runtime/arguments.hpp | 7 +- hotspot/src/share/vm/runtime/thread.cpp | 24 +----- hotspot/src/share/vm/runtime/vmStructs.hpp | 4 +- hotspot/src/share/vm/runtime/vm_version.cpp | 6 +- .../src/share/vm/services/attachListener.cpp | 6 +- .../src/share/vm/services/attachListener.hpp | 5 +- 33 files changed, 40 insertions(+), 430 deletions(-) delete mode 100644 hotspot/make/solaris/makefiles/kernel.make diff --git a/hotspot/make/Makefile b/hotspot/make/Makefile index fe5a6b684d6..a1d8cb9dde6 100644 --- a/hotspot/make/Makefile +++ b/hotspot/make/Makefile @@ -1,5 +1,5 @@ # -# Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2005, 2013, 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 @@ -87,7 +87,6 @@ endif # Typical C1/C2 targets made available with this Makefile C1_VM_TARGETS=product1 fastdebug1 optimized1 jvmg1 C2_VM_TARGETS=product fastdebug optimized jvmg -KERNEL_VM_TARGETS=productkernel fastdebugkernel optimizedkernel jvmgkernel ZERO_VM_TARGETS=productzero fastdebugzero optimizedzero jvmgzero SHARK_VM_TARGETS=productshark fastdebugshark optimizedshark jvmgshark MINIMAL1_VM_TARGETS=productminimal1 fastdebugminimal1 jvmgminimal1 @@ -161,11 +160,6 @@ $(C2_VM_TARGETS): $(CD) $(GAMMADIR)/make; \ $(MAKE) BUILD_FLAVOR=$@ VM_TARGET=$@ generic_build2 $(ALT_OUT) -$(KERNEL_VM_TARGETS): - $(CD) $(GAMMADIR)/make; \ - $(MAKE) BUILD_FLAVOR=$(@:%kernel=%) VM_TARGET=$@ \ - generic_buildkernel $(ALT_OUT) - $(ZERO_VM_TARGETS): $(CD) $(GAMMADIR)/make; \ $(MAKE) BUILD_FLAVOR=$(@:%zero=%) VM_TARGET=$@ \ @@ -223,24 +217,6 @@ else $(MAKE_ARGS) $(VM_TARGET) endif -generic_buildkernel: - $(MKDIR) -p $(OUTPUTDIR) -ifeq ($(OSNAME),windows) - ifeq ($(ARCH_DATA_MODEL), 32) - $(CD) $(OUTPUTDIR); \ - $(NMAKE) -f $(ABS_OS_MAKEFILE) \ - Variant=kernel \ - WorkSpace=$(ABS_GAMMADIR) \ - BootStrapDir=$(ABS_BOOTDIR) \ - BuildUser=$(USERNAME) \ - $(MAKE_ARGS) $(VM_TARGET:%kernel=%) - else - @$(ECHO) "No kernel ($(VM_TARGET)) for ARCH_DATA_MODEL=$(ARCH_DATA_MODEL)" - endif -else - @$(ECHO) "No kernel ($(VM_TARGET)) for OS_NAME=$(OSNAME)" -endif - generic_buildzero: $(MKDIR) -p $(OUTPUTDIR) $(CD) $(OUTPUTDIR); \ @@ -314,12 +290,10 @@ XUSAGE=$(HS_SRC_DIR)/share/vm/Xusage.txt DOCS_DIR=$(OUTPUTDIR)/$(VM_PLATFORM)_docs C1_BASE_DIR=$(OUTPUTDIR)/$(VM_PLATFORM)_compiler1 C2_BASE_DIR=$(OUTPUTDIR)/$(VM_PLATFORM)_compiler2 -KERNEL_BASE_DIR=$(OUTPUTDIR)/$(VM_PLATFORM)_kernel ZERO_BASE_DIR=$(OUTPUTDIR)/$(VM_PLATFORM)_zero SHARK_BASE_DIR=$(OUTPUTDIR)/$(VM_PLATFORM)_shark C1_DIR=$(C1_BASE_DIR)/$(VM_SUBDIR) C2_DIR=$(C2_BASE_DIR)/$(VM_SUBDIR) -KERNEL_DIR=$(KERNEL_BASE_DIR)/$(VM_SUBDIR) ZERO_DIR=$(ZERO_BASE_DIR)/$(VM_SUBDIR) SHARK_DIR=$(SHARK_BASE_DIR)/$(VM_SUBDIR) MINIMAL1_BASE_DIR=$(OUTPUTDIR)/$(VM_PLATFORM)_minimal1 @@ -333,10 +307,6 @@ ifeq ($(JVM_VARIANT_CLIENT), true) MISC_DIR=$(C1_DIR) GEN_DIR=$(C1_BASE_DIR)/generated endif -ifeq ($(JVM_VARIANT_KERNEL), true) - MISC_DIR=$(C2_DIR) - GEN_DIR=$(C2_BASE_DIR)/generated -endif ifeq ($(JVM_VARIANT_ZEROSHARK), true) MISC_DIR=$(SHARK_DIR) GEN_DIR=$(SHARK_BASE_DIR)/generated @@ -386,16 +356,6 @@ $(EXPORT_SERVER_DIR)/%.pdb: $(C2_DIR)/%.pdb $(install-file) $(EXPORT_SERVER_DIR)/%.map: $(C2_DIR)/%.map $(install-file) - -# Kernel files always come from kernel area -$(EXPORT_KERNEL_DIR)/%.diz: $(KERNEL_DIR)/%.diz - $(install-file) -$(EXPORT_KERNEL_DIR)/%.dll: $(KERNEL_DIR)/%.dll - $(install-file) -$(EXPORT_KERNEL_DIR)/%.pdb: $(KERNEL_DIR)/%.pdb - $(install-file) -$(EXPORT_KERNEL_DIR)/%.map: $(KERNEL_DIR)/%.map - $(install-file) endif # Minimal JVM files always come from minimal area @@ -538,7 +498,7 @@ $(EXPORT_DOCS_DIR)/platform/jvmti/%: $(DOCS_DIR)/% $(install-file) # Xusage file -$(EXPORT_SERVER_DIR)/Xusage.txt $(EXPORT_CLIENT_DIR)/Xusage.txt $(EXPORT_KERNEL_DIR)/Xusage.txt $(EXPORT_MINIMAL_DIR)/Xusage.txt: $(XUSAGE) +$(EXPORT_SERVER_DIR)/Xusage.txt $(EXPORT_CLIENT_DIR)/Xusage.txt $(EXPORT_MINIMAL_DIR)/Xusage.txt: $(XUSAGE) $(prep-target) $(RM) $@.temp $(SED) 's/\(separated by \)[;:]/\1$(PATH_SEP)/g' $< > $@.temp @@ -551,7 +511,6 @@ clobber clean: clean_build clean_export clean_jdk clean_build: $(RM) -r $(C1_DIR) $(RM) -r $(C2_DIR) - $(RM) -r $(KERNEL_DIR) $(RM) -r $(ZERO_DIR) $(RM) -r $(SHARK_DIR) $(RM) -r $(MINIMAL1_DIR) @@ -586,10 +545,6 @@ test_jdk: $(JDK_IMAGE_DIR)/bin/java -d$(ARCH_DATA_MODEL) -server -Xinternalversion $(JDK_IMAGE_DIR)/bin/java -d$(ARCH_DATA_MODEL) -server -version endif - ifeq ($(JVM_VARIANT_KERNEL), true) - $(JDK_IMAGE_DIR)/bin/java -d$(ARCH_DATA_MODEL) -kernel -Xinternalversion - $(JDK_IMAGE_DIR)/bin/java -d$(ARCH_DATA_MODEL) -kernel -version - endif copy_product_jdk:: $(RM) -r $(JDK_IMAGE_DIR) @@ -665,7 +620,6 @@ target_help: @$(ECHO) "Other targets are:" @$(ECHO) " $(C1_VM_TARGETS)" @$(ECHO) " $(C2_VM_TARGETS)" - @$(ECHO) " $(KERNEL_VM_TARGETS)" @$(ECHO) " $(MINIMAL1_VM_TARGETS)" # Variable help (only common ones used by this workspace) @@ -761,8 +715,8 @@ endif include $(GAMMADIR)/make/jprt.gmk .PHONY: all world clobber clean help $(C1_VM_TARGETS) $(C2_VM_TARGETS) \ - $(KERNEL_VM_TARGETS) $(MINIMAL1_VM_TARGETS) \ - generic_build1 generic_build2 generic_buildkernel generic_buildminimal1 generic_export \ + $(MINIMAL1_VM_TARGETS) \ + generic_build1 generic_build2 generic_buildminimal1 generic_export \ export_product export_fastdebug export_debug export_optimized \ export_jdk_product export_jdk_fastdebug export_jdk_debug \ create_jdk copy_jdk update_jdk test_jdk \ diff --git a/hotspot/make/bsd/makefiles/dtrace.make b/hotspot/make/bsd/makefiles/dtrace.make index d325f2082dd..1c53841b56c 100644 --- a/hotspot/make/bsd/makefiles/dtrace.make +++ b/hotspot/make/bsd/makefiles/dtrace.make @@ -1,5 +1,5 @@ # -# Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2005, 2013, 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 @@ -25,10 +25,9 @@ # Rules to build jvm_db/dtrace, used by vm.make # We build libjvm_dtrace/libjvm_db/dtrace for COMPILER1 and COMPILER2 -# but not for CORE or KERNEL configurations. +# but not for CORE configuration. ifneq ("${TYPE}", "CORE") -ifneq ("${TYPE}", "KERNEL") ifeq ($(OS_VENDOR), Darwin) # we build dtrace for macosx using USDT2 probes @@ -280,13 +279,6 @@ endif # ifneq ("${dtraceFound}", "") endif # ifeq ($(OS_VENDOR), Darwin) -else # KERNEL build - -dtraceCheck: - $(QUIETLY) echo "**NOTICE** Dtrace support disabled for KERNEL builds" - -endif # ifneq ("${TYPE}", "KERNEL") - else # CORE build dtraceCheck: diff --git a/hotspot/make/solaris/Makefile b/hotspot/make/solaris/Makefile index 4a47cb93716..83e4df66579 100644 --- a/hotspot/make/solaris/Makefile +++ b/hotspot/make/solaris/Makefile @@ -1,5 +1,5 @@ # -# Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 1998, 2013, 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 @@ -157,13 +157,11 @@ SUBDIRS_C1 = $(addprefix $(OSNAME)_$(BUILDARCH)_compiler1/,$(TARGETS)) SUBDIRS_C2 = $(addprefix $(OSNAME)_$(BUILDARCH)_compiler2/,$(TARGETS)) SUBDIRS_TIERED = $(addprefix $(OSNAME)_$(BUILDARCH)_tiered/,$(TARGETS)) SUBDIRS_CORE = $(addprefix $(OSNAME)_$(BUILDARCH)_core/,$(TARGETS)) -SUBDIRS_KERNEL = $(addprefix $(OSNAME)_$(BUILDARCH)_kernel/,$(TARGETS)) TARGETS_C2 = $(TARGETS) TARGETS_C1 = $(addsuffix 1,$(TARGETS)) TARGETS_TIERED = $(addsuffix tiered,$(TARGETS)) TARGETS_CORE = $(addsuffix core,$(TARGETS)) -TARGETS_KERNEL = $(addsuffix kernel,$(TARGETS)) BUILDTREE_MAKE = $(GAMMADIR)/make/$(OSNAME)/makefiles/buildtree.make BUILDTREE_VARS = GAMMADIR=$(GAMMADIR) OS_FAMILY=$(OSNAME) ARCH=$(SRCARCH) BUILDARCH=$(BUILDARCH) LIBARCH=$(LIBARCH) @@ -229,10 +227,6 @@ $(SUBDIRS_CORE): $(BUILDTREE_MAKE) $(QUIETLY) $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/Makefile checks $(BUILDTREE) VARIANT=core -$(SUBDIRS_KERNEL): $(BUILDTREE_MAKE) - $(QUIETLY) $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/Makefile checks - $(BUILDTREE) VARIANT=kernel - # Define INSTALL=y at command line to automatically copy JVM into JAVA_HOME $(TARGETS_C2): $(SUBDIRS_C2) @@ -271,20 +265,10 @@ ifdef INSTALL cd $(OSNAME)_$(BUILDARCH)_core/$(patsubst %core,%,$@) && $(MAKE) $(MFLAGS) install endif -$(TARGETS_KERNEL): $(SUBDIRS_KERNEL) - cd $(OSNAME)_$(BUILDARCH)_kernel/$(patsubst %kernel,%,$@) && $(MAKE) $(MFLAGS) -ifeq ($(TEST_IN_BUILD),true) - cd $(OSNAME)_$(BUILDARCH)_kernel/$(patsubst %kernel,%,$@) && ./test_gamma -endif -ifdef INSTALL - cd $(OSNAME)_$(BUILDARCH)_kernel/$(patsubst %kernel,%,$@) && $(MAKE) $(MFLAGS) install -endif - # Just build the tree, and nothing else: tree: $(SUBDIRS_C2) tree1: $(SUBDIRS_C1) treecore: $(SUBDIRS_CORE) -treekernel: $(SUBDIRS_KERNEL) # Doc target. This is the same for all build options. # Hence create a docs directory beside ...$(ARCH)_[...] @@ -304,10 +288,10 @@ core: jvmgcore productcore clean_docs: rm -rf $(SUBDIR_DOCS) -clean_compiler1 clean_compiler2 clean_core clean_kernel: +clean_compiler1 clean_compiler2 clean_core: rm -rf $(OSNAME)_$(BUILDARCH)_$(subst clean_,,$@) -clean: clean_compiler2 clean_compiler1 clean_core clean_docs clean_kernel +clean: clean_compiler2 clean_compiler1 clean_core clean_docs include $(GAMMADIR)/make/cscope.make diff --git a/hotspot/make/solaris/makefiles/dtrace.make b/hotspot/make/solaris/makefiles/dtrace.make index 111acdb0d96..b57365b93dc 100644 --- a/hotspot/make/solaris/makefiles/dtrace.make +++ b/hotspot/make/solaris/makefiles/dtrace.make @@ -1,5 +1,5 @@ # -# Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2005, 2013, 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 @@ -25,10 +25,9 @@ # Rules to build jvm_db/dtrace, used by vm.make # We build libjvm_dtrace/libjvm_db/dtrace for COMPILER1 and COMPILER2 -# but not for CORE or KERNEL configurations. +# but not for CORE configuration. ifneq ("${TYPE}", "CORE") -ifneq ("${TYPE}", "KERNEL") ifdef USE_GCC @@ -362,13 +361,6 @@ endif # ifneq ("${dtraceFound}", "") endif # ifdef USE_GCC -else # KERNEL build - -dtraceCheck: - $(QUIETLY) echo "**NOTICE** Dtrace support disabled for KERNEL builds" - -endif # ifneq ("${TYPE}", "KERNEL") - else # CORE build dtraceCheck: diff --git a/hotspot/make/solaris/makefiles/kernel.make b/hotspot/make/solaris/makefiles/kernel.make deleted file mode 100644 index 40728e669f1..00000000000 --- a/hotspot/make/solaris/makefiles/kernel.make +++ /dev/null @@ -1,32 +0,0 @@ -# -# Copyright (c) 2007, 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. -# -# 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. -# -# -# -# Sets make macros for making kernel version of VM. -# This target on solaris is just tempoarily for debugging the kernel build. - -TYPE=KERNEL - -VM_SUBDIR = client - -CFLAGS += -DKERNEL diff --git a/hotspot/make/windows/build.bat b/hotspot/make/windows/build.bat index e4eab3abf0c..5df20dd4f1e 100644 --- a/hotspot/make/windows/build.bat +++ b/hotspot/make/windows/build.bat @@ -1,6 +1,6 @@ @echo off REM -REM Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. +REM Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. REM DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. REM REM This code is free software; you can redistribute it and/or modify it @@ -67,7 +67,6 @@ goto usage :test1 if "%2" == "core" goto test2 -if "%2" == "kernel" goto test2 if "%2" == "compiler1" goto test2 if "%2" == "compiler2" goto test2 if "%2" == "tiered" goto test2 @@ -109,7 +108,7 @@ echo Usage: build flavor version workspace bootstrap_dir [build_id] [windbg_home echo. echo where: echo flavor is "product", "debug" or "fastdebug", -echo version is "core", "kernel", "compiler1", "compiler2", or "tiered", +echo version is "core", "compiler1", "compiler2", or "tiered", echo workspace is source directory without trailing slash, echo bootstrap_dir is a full path to a JDK in which bin/java echo and bin/javac are present and working, and build_id is an diff --git a/hotspot/make/windows/create_obj_files.sh b/hotspot/make/windows/create_obj_files.sh index 78fabc06ddc..14a7087f2aa 100644 --- a/hotspot/make/windows/create_obj_files.sh +++ b/hotspot/make/windows/create_obj_files.sh @@ -1,5 +1,5 @@ # -# Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2010, 2013, 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 @@ -107,7 +107,6 @@ COMPILER2_PATHS="${COMPILER2_PATHS} ${GENERATED}/adfiles" # Include dirs per type. case "${TYPE}" in "core") Src_Dirs="${CORE_PATHS}" ;; - "kernel") Src_Dirs="${BASE_PATHS} ${COMPILER1_PATHS}" ;; "compiler1") Src_Dirs="${CORE_PATHS} ${COMPILER1_PATHS}" ;; "compiler2") Src_Dirs="${CORE_PATHS} ${COMPILER2_PATHS}" ;; "tiered") Src_Dirs="${CORE_PATHS} ${COMPILER1_PATHS} ${COMPILER2_PATHS}" ;; @@ -120,16 +119,12 @@ COMPILER1_SPECIFIC_FILES="c1_*" SHARK_SPECIFIC_FILES="shark" ZERO_SPECIFIC_FILES="zero" -# These files need to be excluded when building the kernel target. -KERNEL_EXCLUDED_FILES="attachListener.cpp attachListener_windows.cpp metaspaceShared_${Platform_arch_model}.cpp forte.cpp fprofiler.cpp heapDumper.cpp heapInspection.cpp jniCheck.cpp jvmtiCodeBlobEvents.cpp jvmtiExtensions.cpp jvmtiImpl.cpp jvmtiRawMonitor.cpp jvmtiTagMap.cpp jvmtiTrace.cpp vmStructs.cpp g1MemoryPool.cpp psMemoryPool.cpp gcAdaptivePolicyCounters.cpp concurrentGCThread.cpp metaspaceShared.cpp mutableNUMASpace.cpp allocationStats.cpp gSpaceCounters.cpp immutableSpace.cpp mutableSpace.cpp spaceCounters.cpp yieldingWorkgroup.cpp" - # Always exclude these. Src_Files_EXCLUDE="jsig.c jvmtiEnvRecommended.cpp jvmtiEnvStub.cpp" # Exclude per type. case "${TYPE}" in "core") Src_Files_EXCLUDE="${Src_Files_EXCLUDE} ${COMPILER1_SPECIFIC_FILES} ${COMPILER2_SPECIFIC_FILES} ${ZERO_SPECIFIC_FILES} ${SHARK_SPECIFIC_FILES} ciTypeFlow.cpp" ;; - "kernel") Src_Files_EXCLUDE="${Src_Files_EXCLUDE} ${COMPILER2_SPECIFIC_FILES} ${ZERO_SPECIFIC_FILES} ${SHARK_SPECIFIC_FILES} ${KERNEL_EXCLUDED_FILES} ciTypeFlow.cpp" ;; "compiler1") Src_Files_EXCLUDE="${Src_Files_EXCLUDE} ${COMPILER2_SPECIFIC_FILES} ${ZERO_SPECIFIC_FILES} ${SHARK_SPECIFIC_FILES} ciTypeFlow.cpp" ;; "compiler2") Src_Files_EXCLUDE="${Src_Files_EXCLUDE} ${COMPILER1_SPECIFIC_FILES} ${ZERO_SPECIFIC_FILES} ${SHARK_SPECIFIC_FILES}" ;; "tiered") Src_Files_EXCLUDE="${Src_Files_EXCLUDE} ${ZERO_SPECIFIC_FILES} ${SHARK_SPECIFIC_FILES}" ;; diff --git a/hotspot/make/windows/makefiles/defs.make b/hotspot/make/windows/makefiles/defs.make index e637c00335d..5d58e699bf2 100644 --- a/hotspot/make/windows/makefiles/defs.make +++ b/hotspot/make/windows/makefiles/defs.make @@ -1,5 +1,5 @@ # -# Copyright (c) 2006, 2012, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2006, 2013, 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 @@ -157,7 +157,7 @@ endif MAKE_ARGS += RM="$(RM)" MAKE_ARGS += ZIPEXE=$(ZIPEXE) -# On 32 bit windows we build server, client and kernel, on 64 bit just server. +# On 32 bit windows we build server and client, on 64 bit just server. ifeq ($(JVM_VARIANTS),) ifeq ($(ARCH_DATA_MODEL), 32) JVM_VARIANTS:=client,server @@ -250,7 +250,6 @@ endif EXPORT_SERVER_DIR = $(EXPORT_JRE_BIN_DIR)/server EXPORT_CLIENT_DIR = $(EXPORT_JRE_BIN_DIR)/client -EXPORT_KERNEL_DIR = $(EXPORT_JRE_BIN_DIR)/kernel ifeq ($(JVM_VARIANT_SERVER),true) EXPORT_LIST += $(EXPORT_SERVER_DIR)/Xusage.txt @@ -277,18 +276,6 @@ ifeq ($(JVM_VARIANT_CLIENT),true) endif endif endif -ifeq ($(JVM_VARIANT_KERNEL),true) - EXPORT_LIST += $(EXPORT_KERNEL_DIR)/Xusage.txt - EXPORT_LIST += $(EXPORT_KERNEL_DIR)/jvm.$(LIBRARY_SUFFIX) - ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1) - ifeq ($(ZIP_DEBUGINFO_FILES),1) - EXPORT_LIST += $(EXPORT_KERNEL_DIR)/jvm.diz - else - EXPORT_LIST += $(EXPORT_KERNEL_DIR)/jvm.pdb - EXPORT_LIST += $(EXPORT_KERNEL_DIR)/jvm.map - endif - endif -endif EXPORT_LIST += $(EXPORT_JRE_LIB_DIR)/wb.jar diff --git a/hotspot/make/windows/makefiles/projectcreator.make b/hotspot/make/windows/makefiles/projectcreator.make index 5d71de6618a..68d098d0de3 100644 --- a/hotspot/make/windows/makefiles/projectcreator.make +++ b/hotspot/make/windows/makefiles/projectcreator.make @@ -1,5 +1,5 @@ # -# Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 1999, 2013, 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 @@ -166,63 +166,6 @@ ProjectCreatorIDEOptions=$(ProjectCreatorIDEOptions) \ $(ProjectCreatorIDEOptionsIgnoreCompiler1:TARGET=core) \ $(ProjectCreatorIDEOptionsIgnoreCompiler2:TARGET=core) -################################################## -# JKERNEL specific options -################################################## -ProjectCreatorIDEOptions=$(ProjectCreatorIDEOptions) \ - -define_kernel KERNEL \ -$(ProjectCreatorIDEOptionsIgnoreCompiler2:TARGET=kernel) \ - -ignorePath_kernel src/share/vm/gc_implementation/parallelScavenge \ - -ignorePath_kernel src/share/vm/gc_implementation/parNew \ - -ignorePath_kernel src/share/vm/gc_implementation/concurrentMarkSweep \ - -ignorePath_kernel src/share/vm/gc_implementation/g1 \ - -ignoreFile_kernel attachListener.cpp \ - -ignoreFile_kernel attachListener_windows.cpp \ - -ignoreFile_kernel dump.cpp \ - -ignoreFile_kernel dump_$(Platform_arch_model).cpp \ - -ignoreFile_kernel forte.cpp \ - -ignoreFile_kernel fprofiler.cpp \ - -ignoreFile_kernel heapDumper.cpp \ - -ignoreFile_kernel heapInspection.cpp \ - -ignoreFile_kernel jniCheck.cpp \ - -ignoreFile_kernel jvmtiCodeBlobEvents.cpp \ - -ignoreFile_kernel jvmtiExtensions.cpp \ - -ignoreFile_kernel jvmtiImpl.cpp \ - -ignoreFile_kernel jvmtiRawMonitor.cpp \ - -ignoreFile_kernel jvmtiTagMap.cpp \ - -ignoreFile_kernel jvmtiTrace.cpp \ - -ignoreFile_kernel jvmtiTrace.hpp \ - -ignoreFile_kernel restore.cpp \ - -ignoreFile_kernel serialize.cpp \ - -ignoreFile_kernel vmStructs.cpp \ - -ignoreFile_kernel g1MemoryPool.cpp \ - -ignoreFile_kernel g1MemoryPool.hpp \ - -ignoreFile_kernel psMemoryPool.cpp \ - -ignoreFile_kernel psMemoryPool.hpp \ - -ignoreFile_kernel gcAdaptivePolicyCounters.cpp \ - -ignoreFile_kernel concurrentGCThread.cpp \ - -ignoreFile_kernel mutableNUMASpace.cpp \ - -ignoreFile_kernel ciTypeFlow.cpp \ - -ignoreFile_kernel ciTypeFlow.hpp \ - -ignoreFile_kernel oop.pcgc.inline.hpp \ - -ignoreFile_kernel oop.psgc.inline.hpp \ - -ignoreFile_kernel allocationStats.cpp \ - -ignoreFile_kernel allocationStats.hpp \ - -ignoreFile_kernel concurrentGCThread.hpp \ - -ignoreFile_kernel gSpaceCounters.cpp \ - -ignoreFile_kernel gSpaceCounters.hpp \ - -ignoreFile_kernel gcAdaptivePolicyCounters.hpp \ - -ignoreFile_kernel immutableSpace.cpp \ - -ignoreFile_kernel mutableNUMASpace.hpp \ - -ignoreFile_kernel mutableSpace.cpp \ - -ignoreFile_kernel spaceCounters.cpp \ - -ignoreFile_kernel spaceCounters.hpp \ - -ignoreFile_kernel yieldingWorkgroup.cpp \ - -ignoreFile_kernel yieldingWorkgroup.hpp \ - -ignorePath_kernel vmStructs_ \ - -ignoreFile_kernel $(Platform_arch_model).ad \ - -additionalFile_kernel gcTaskManager.hpp - ################################################## # Client(C1) compiler specific options ################################################## diff --git a/hotspot/make/windows/makefiles/vm.make b/hotspot/make/windows/makefiles/vm.make index b1e71de0e5a..2e501a7b9f7 100644 --- a/hotspot/make/windows/makefiles/vm.make +++ b/hotspot/make/windows/makefiles/vm.make @@ -1,5 +1,5 @@ # -# Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 1997, 2013, 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 @@ -44,10 +44,6 @@ CXX_FLAGS=$(CXX_FLAGS) /D "ASSERT" # No need to define anything, CORE is defined as !COMPILER1 && !COMPILER2 !endif -!if "$(Variant)" == "kernel" -CXX_FLAGS=$(CXX_FLAGS) /D "KERNEL" -!endif - !if "$(Variant)" == "compiler1" CXX_FLAGS=$(CXX_FLAGS) /D "COMPILER1" !endif diff --git a/hotspot/src/cpu/x86/vm/assembler_x86.hpp b/hotspot/src/cpu/x86/vm/assembler_x86.hpp index bcef330e4cf..ec4137c53d7 100644 --- a/hotspot/src/cpu/x86/vm/assembler_x86.hpp +++ b/hotspot/src/cpu/x86/vm/assembler_x86.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, 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 @@ -543,7 +543,7 @@ class Assembler : public AbstractAssembler { // of instructions are freely declared without the need for wrapping them an ifdef. // (Some dangerous instructions are ifdef's out of inappropriate jvm's.) // In the .cpp file the implementations are wrapped so that they are dropped out - // of the resulting jvm. This is done mostly to keep the footprint of KERNEL + // of the resulting jvm. This is done mostly to keep the footprint of MINIMAL // to the size it was prior to merging up the 32bit and 64bit assemblers. // // This does mean you'll get a linker/runtime error if you use a 64bit only instruction diff --git a/hotspot/src/share/vm/classfile/systemDictionary.cpp b/hotspot/src/share/vm/classfile/systemDictionary.cpp index 54601625056..a7370fcce29 100644 --- a/hotspot/src/share/vm/classfile/systemDictionary.cpp +++ b/hotspot/src/share/vm/classfile/systemDictionary.cpp @@ -1199,66 +1199,6 @@ instanceKlassHandle SystemDictionary::load_shared_class( return ik; } -#ifdef KERNEL -// Some classes on the bootstrap class path haven't been installed on the -// system yet. Call the DownloadManager method to make them appear in the -// bootstrap class path and try again to load the named class. -// Note that with delegation class loaders all classes in another loader will -// first try to call this so it'd better be fast!! -static instanceKlassHandle download_and_retry_class_load( - Symbol* class_name, - TRAPS) { - - Klass* dlm = SystemDictionary::DownloadManager_klass(); - instanceKlassHandle nk; - - // If download manager class isn't loaded just return. - if (dlm == NULL) return nk; - - { HandleMark hm(THREAD); - ResourceMark rm(THREAD); - Handle s = java_lang_String::create_from_symbol(class_name, CHECK_(nk)); - Handle class_string = java_lang_String::externalize_classname(s, CHECK_(nk)); - - // return value - JavaValue result(T_OBJECT); - - // Call the DownloadManager. We assume that it has a lock because - // multiple classes could be not found and downloaded at the same time. - // class sun.misc.DownloadManager; - // public static String getBootClassPathEntryForClass(String className); - JavaCalls::call_static(&result, - KlassHandle(THREAD, dlm), - vmSymbols::getBootClassPathEntryForClass_name(), - vmSymbols::string_string_signature(), - class_string, - CHECK_(nk)); - - // Get result.string and add to bootclasspath - assert(result.get_type() == T_OBJECT, "just checking"); - oop obj = (oop) result.get_jobject(); - if (obj == NULL) { return nk; } - - Handle h_obj(THREAD, obj); - char* new_class_name = java_lang_String::as_platform_dependent_str(h_obj, - CHECK_(nk)); - - // lock the loader - // we use this lock because JVMTI does. - Handle loader_lock(THREAD, SystemDictionary::system_loader_lock()); - - ObjectLocker ol(loader_lock, THREAD); - // add the file to the bootclasspath - ClassLoader::update_class_path_entry_list(new_class_name, true); - } // end HandleMark - - if (TraceClassLoading) { - ClassLoader::print_bootclasspath(); - } - return ClassLoader::load_classfile(class_name, CHECK_(nk)); -} -#endif // KERNEL - instanceKlassHandle SystemDictionary::load_instance_class(Symbol* class_name, Handle class_loader, TRAPS) { instanceKlassHandle nh = instanceKlassHandle(); // null Handle @@ -1278,15 +1218,6 @@ instanceKlassHandle SystemDictionary::load_instance_class(Symbol* class_name, Ha k = ClassLoader::load_classfile(class_name, CHECK_(nh)); } -#ifdef KERNEL - // If the VM class loader has failed to load the class, call the - // DownloadManager class to make it magically appear on the classpath - // and try again. This is only configured with the Kernel VM. - if (k.is_null()) { - k = download_and_retry_class_load(class_name, CHECK_(nh)); - } -#endif // KERNEL - // find_or_define_instance_class may return a different InstanceKlass if (!k.is_null()) { k = find_or_define_instance_class(class_name, class_loader, k, CHECK_(nh)); @@ -1822,13 +1753,7 @@ bool SystemDictionary::initialize_wk_klass(WKID id, int init_opt, TRAPS) { Symbol* symbol = vmSymbols::symbol_at((vmSymbols::SID)sid); Klass** klassp = &_well_known_klasses[id]; bool must_load = (init_opt < SystemDictionary::Opt); - bool try_load = true; - if (init_opt == SystemDictionary::Opt_Kernel) { -#ifndef KERNEL - try_load = false; -#endif //KERNEL - } - if ((*klassp) == NULL && try_load) { + if ((*klassp) == NULL) { if (must_load) { (*klassp) = resolve_or_fail(symbol, true, CHECK_0); // load required class } else { @@ -1918,12 +1843,6 @@ void SystemDictionary::initialize_preloaded_classes(TRAPS) { //_box_klasses[T_OBJECT] = WK_KLASS(object_klass); //_box_klasses[T_ARRAY] = WK_KLASS(object_klass); -#ifdef KERNEL - if (DownloadManager_klass() == NULL) { - warning("Cannot find sun/jkernel/DownloadManager"); - } -#endif // KERNEL - { // Compute whether we should use loadClass or loadClassInternal when loading classes. Method* method = InstanceKlass::cast(ClassLoader_klass())->find_method(vmSymbols::loadClassInternal_name(), vmSymbols::string_class_signature()); _has_loadClassInternal = (method != NULL); diff --git a/hotspot/src/share/vm/classfile/systemDictionary.hpp b/hotspot/src/share/vm/classfile/systemDictionary.hpp index e2f660ee171..d415c9b1e4f 100644 --- a/hotspot/src/share/vm/classfile/systemDictionary.hpp +++ b/hotspot/src/share/vm/classfile/systemDictionary.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, 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 @@ -168,8 +168,6 @@ class SymbolPropertyTable; /* It's okay if this turns out to be NULL in non-1.4 JDKs. */ \ do_klass(nio_Buffer_klass, java_nio_Buffer, Opt ) \ \ - do_klass(DownloadManager_klass, sun_jkernel_DownloadManager, Opt_Kernel ) \ - \ do_klass(PostVMInitHook_klass, sun_misc_PostVMInitHook, Opt ) \ \ /* Preload boxing klasses */ \ @@ -211,7 +209,6 @@ class SystemDictionary : AllStatic { Opt, // preload tried; NULL if not present Opt_Only_JDK14NewRef, // preload tried; use only with NewReflection Opt_Only_JDK15, // preload tried; use only with JDK1.5+ - Opt_Kernel, // preload tried only #ifdef KERNEL OPTION_LIMIT, CEIL_LG_OPTION_LIMIT = 4 // OPTION_LIMIT <= (1<is_attachable = AttachListener::is_attach_supported(); -#ifdef KERNEL - info->is_kernel_jvm = 1; // true; -#else // KERNEL info->is_kernel_jvm = 0; // false; -#endif // KERNEL } JVM_END diff --git a/hotspot/src/share/vm/prims/jvmtiCodeBlobEvents.hpp b/hotspot/src/share/vm/prims/jvmtiCodeBlobEvents.hpp index 92adaaf80e8..00da7ca6ca1 100644 --- a/hotspot/src/share/vm/prims/jvmtiCodeBlobEvents.hpp +++ b/hotspot/src/share/vm/prims/jvmtiCodeBlobEvents.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2013, 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 @@ -25,9 +25,7 @@ #ifndef SHARE_VM_PRIMS_JVMTICODEBLOBEVENTS_HPP #define SHARE_VM_PRIMS_JVMTICODEBLOBEVENTS_HPP -#ifndef JVMTI_KERNEL #include "jvmtifiles/jvmti.h" -#endif // forward declaration class JvmtiEnv; diff --git a/hotspot/src/share/vm/prims/jvmtiEnv.cpp b/hotspot/src/share/vm/prims/jvmtiEnv.cpp index cb3b3db1e1c..318fe4e0b7e 100644 --- a/hotspot/src/share/vm/prims/jvmtiEnv.cpp +++ b/hotspot/src/share/vm/prims/jvmtiEnv.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2013, 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 @@ -647,8 +647,6 @@ JvmtiEnv::GetJLocationFormat(jvmtiJlocationFormat* format_ptr) { return JVMTI_ERROR_NONE; } /* end GetJLocationFormat */ -#ifndef JVMTI_KERNEL - // // Thread functions // @@ -3436,5 +3434,3 @@ JvmtiEnv::SetSystemProperty(const char* property, const char* value_ptr) { } return err; } /* end SetSystemProperty */ - -#endif // !JVMTI_KERNEL diff --git a/hotspot/src/share/vm/prims/jvmtiEnvBase.cpp b/hotspot/src/share/vm/prims/jvmtiEnvBase.cpp index eed31268141..56387634179 100644 --- a/hotspot/src/share/vm/prims/jvmtiEnvBase.cpp +++ b/hotspot/src/share/vm/prims/jvmtiEnvBase.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2013, 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 @@ -74,10 +74,8 @@ JvmtiEnvBase::globally_initialize() { JvmtiManageCapabilities::initialize(); -#ifndef JVMTI_KERNEL // register extension functions and events JvmtiExtensions::register_extensions(); -#endif // !JVMTI_KERNEL #ifdef JVMTI_TRACE JvmtiTrace::initialize(); @@ -236,14 +234,12 @@ JvmtiEnvBase::env_dispose() { // Same situation as with events (see above) set_native_method_prefixes(0, NULL); -#ifndef JVMTI_KERNEL JvmtiTagMap* tag_map_to_deallocate = _tag_map; set_tag_map(NULL); // A tag map can be big, deallocate it now if (tag_map_to_deallocate != NULL) { delete tag_map_to_deallocate; } -#endif // !JVMTI_KERNEL _needs_clean_up = true; } @@ -255,14 +251,12 @@ JvmtiEnvBase::~JvmtiEnvBase() { // There is a small window of time during which the tag map of a // disposed environment could have been reallocated. // Make sure it is gone. -#ifndef JVMTI_KERNEL JvmtiTagMap* tag_map_to_deallocate = _tag_map; set_tag_map(NULL); // A tag map can be big, deallocate it now if (tag_map_to_deallocate != NULL) { delete tag_map_to_deallocate; } -#endif // !JVMTI_KERNEL _magic = BAD_MAGIC; } @@ -593,8 +587,6 @@ JvmtiEnvBase::get_jni_class_non_null(Klass* k) { return (jclass)jni_reference(k->java_mirror()); } -#ifndef JVMTI_KERNEL - // // Field Information // @@ -1482,5 +1474,3 @@ JvmtiMonitorClosure::do_monitor(ObjectMonitor* mon) { } } } - -#endif // !JVMTI_KERNEL diff --git a/hotspot/src/share/vm/prims/jvmtiExport.cpp b/hotspot/src/share/vm/prims/jvmtiExport.cpp index cb5a1f454d9..1b92193fd55 100644 --- a/hotspot/src/share/vm/prims/jvmtiExport.cpp +++ b/hotspot/src/share/vm/prims/jvmtiExport.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2013, 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 @@ -677,7 +677,6 @@ void JvmtiExport::report_unsupported(bool on) { } -#ifndef JVMTI_KERNEL static inline Klass* oop_to_klass(oop obj) { Klass* k = obj->klass(); @@ -2178,7 +2177,6 @@ extern "C" { typedef jint (JNICALL *OnAttachEntry_t)(JavaVM*, char *, void *); } -#ifndef SERVICES_KERNEL jint JvmtiExport::load_agent_library(AttachOperation* op, outputStream* st) { char ebuf[1024]; char buffer[JVM_MAXPATHLEN]; @@ -2259,7 +2257,6 @@ jint JvmtiExport::load_agent_library(AttachOperation* op, outputStream* st) { } return result; } -#endif // SERVICES_KERNEL //////////////////////////////////////////////////////////////////////////////////////////////// @@ -2457,4 +2454,3 @@ JvmtiGCMarker::~JvmtiGCMarker() { JvmtiExport::post_garbage_collection_finish(); } } -#endif // JVMTI_KERNEL diff --git a/hotspot/src/share/vm/prims/jvmtiExtensions.hpp b/hotspot/src/share/vm/prims/jvmtiExtensions.hpp index a5e3433315e..f85003f6bf6 100644 --- a/hotspot/src/share/vm/prims/jvmtiExtensions.hpp +++ b/hotspot/src/share/vm/prims/jvmtiExtensions.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2013, 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 @@ -25,11 +25,9 @@ #ifndef SHARE_VM_PRIMS_JVMTIEXTENSIONS_HPP #define SHARE_VM_PRIMS_JVMTIEXTENSIONS_HPP -#ifndef JVMTI_KERNEL #include "jvmtifiles/jvmti.h" #include "jvmtifiles/jvmtiEnv.hpp" #include "memory/allocation.hpp" -#endif // JvmtiExtensions // diff --git a/hotspot/src/share/vm/prims/jvmtiImpl.cpp b/hotspot/src/share/vm/prims/jvmtiImpl.cpp index bb7714d4932..4a1747e1bd2 100644 --- a/hotspot/src/share/vm/prims/jvmtiImpl.cpp +++ b/hotspot/src/share/vm/prims/jvmtiImpl.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2013, 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 @@ -905,8 +905,6 @@ void JvmtiSuspendControl::print() { #endif } -#ifndef KERNEL - JvmtiDeferredEvent JvmtiDeferredEvent::compiled_method_load_event( nmethod* nm) { JvmtiDeferredEvent event = JvmtiDeferredEvent(TYPE_COMPILED_METHOD_LOAD); @@ -1098,5 +1096,3 @@ void JvmtiDeferredEventQueue::process_pending_events() { } } } - -#endif // ndef KERNEL diff --git a/hotspot/src/share/vm/prims/jvmtiImpl.hpp b/hotspot/src/share/vm/prims/jvmtiImpl.hpp index d785930be0d..204bd83f124 100644 --- a/hotspot/src/share/vm/prims/jvmtiImpl.hpp +++ b/hotspot/src/share/vm/prims/jvmtiImpl.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2013, 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 @@ -25,8 +25,6 @@ #ifndef SHARE_VM_PRIMS_JVMTIIMPL_HPP #define SHARE_VM_PRIMS_JVMTIIMPL_HPP -#ifndef JVMTI_KERNEL - #include "classfile/systemDictionary.hpp" #include "jvmtifiles/jvmti.h" #include "oops/objArrayOop.hpp" @@ -435,7 +433,6 @@ public: static void print(); }; -#endif // !JVMTI_KERNEL /** * When a thread (such as the compiler thread or VM thread) cannot post a diff --git a/hotspot/src/share/vm/prims/jvmtiRawMonitor.hpp b/hotspot/src/share/vm/prims/jvmtiRawMonitor.hpp index e5b25fa3a82..8c182f318ec 100644 --- a/hotspot/src/share/vm/prims/jvmtiRawMonitor.hpp +++ b/hotspot/src/share/vm/prims/jvmtiRawMonitor.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2013, 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 @@ -25,10 +25,8 @@ #ifndef SHARE_VM_PRIMS_JVMTIRAWMONITOR_HPP #define SHARE_VM_PRIMS_JVMTIRAWMONITOR_HPP -#ifndef JVMTI_KERNEL #include "runtime/objectMonitor.hpp" #include "utilities/growableArray.hpp" -#endif // // class JvmtiRawMonitor diff --git a/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp b/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp index 7255579280b..01b92ade637 100644 --- a/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp +++ b/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp @@ -3104,11 +3104,9 @@ void VM_RedefineClasses::redefine_single_class(jclass the_jclass, Klass* the_class_oop = java_lang_Class::as_Klass(the_class_mirror); instanceKlassHandle the_class = instanceKlassHandle(THREAD, the_class_oop); -#ifndef JVMTI_KERNEL // Remove all breakpoints in methods of this class JvmtiBreakpoints& jvmti_breakpoints = JvmtiCurrentBreakpoints::get_jvmti_breakpoints(); jvmti_breakpoints.clearall_in_class_at_safepoint(the_class_oop); -#endif // !JVMTI_KERNEL if (the_class_oop == Universe::reflect_invoke_cache()->klass()) { // We are redefining java.lang.reflect.Method. Method.invoke() is diff --git a/hotspot/src/share/vm/prims/jvmtiTagMap.hpp b/hotspot/src/share/vm/prims/jvmtiTagMap.hpp index 6435f6251c7..89e3947807d 100644 --- a/hotspot/src/share/vm/prims/jvmtiTagMap.hpp +++ b/hotspot/src/share/vm/prims/jvmtiTagMap.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2013, 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 @@ -27,14 +27,12 @@ #ifndef SHARE_VM_PRIMS_JVMTITAGMAP_HPP #define SHARE_VM_PRIMS_JVMTITAGMAP_HPP -#ifndef JVMTI_KERNEL #include "gc_interface/collectedHeap.hpp" #include "jvmtifiles/jvmti.h" #include "jvmtifiles/jvmtiEnv.hpp" #include "memory/allocation.hpp" #include "memory/genCollectedHeap.hpp" #include "memory/universe.hpp" -#endif // forward references class JvmtiTagHashmap; diff --git a/hotspot/src/share/vm/runtime/arguments.cpp b/hotspot/src/share/vm/runtime/arguments.cpp index 9b5d7f9122d..5e6ad6e21bb 100644 --- a/hotspot/src/share/vm/runtime/arguments.cpp +++ b/hotspot/src/share/vm/runtime/arguments.cpp @@ -2472,10 +2472,7 @@ jint Arguments::parse_each_vm_init_arg(const JavaVMInitArgs* args, // -Xshare:dump } else if (match_option(option, "-Xshare:dump", &tail)) { -#if defined(KERNEL) - vm_exit_during_initialization( - "Dumping a shared archive is not supported on the Kernel JVM.", NULL); -#elif !INCLUDE_CDS +#if !INCLUDE_CDS vm_exit_during_initialization( "Dumping a shared archive is not supported in this VM.", NULL); #else @@ -3463,36 +3460,6 @@ void Arguments::PropertyList_unique_add(SystemProperty** plist, const char* k, c PropertyList_add(plist, k, v); } -#ifdef KERNEL -char *Arguments::get_kernel_properties() { - // Find properties starting with kernel and append them to string - // We need to find out how long they are first because the URL's that they - // might point to could get long. - int length = 0; - SystemProperty* prop; - for (prop = _system_properties; prop != NULL; prop = prop->next()) { - if (strncmp(prop->key(), "kernel.", 7 ) == 0) { - length += (strlen(prop->key()) + strlen(prop->value()) + 5); // "-D =" - } - } - // Add one for null terminator. - char *props = AllocateHeap(length + 1, mtInternal); - if (length != 0) { - int pos = 0; - for (prop = _system_properties; prop != NULL; prop = prop->next()) { - if (strncmp(prop->key(), "kernel.", 7 ) == 0) { - jio_snprintf(&props[pos], length-pos, - "-D%s=%s ", prop->key(), prop->value()); - pos = strlen(props); - } - } - } - // null terminate props in case of null - props[length] = '\0'; - return props; -} -#endif // KERNEL - // Copies src into buf, replacing "%%" with "%" and "%p" with pid // Returns true if all of the source pointed by src has been copied over to // the destination buffer pointed by buf. Otherwise, returns false. diff --git a/hotspot/src/share/vm/runtime/arguments.hpp b/hotspot/src/share/vm/runtime/arguments.hpp index 71e6e3001e9..c116e2028bb 100644 --- a/hotspot/src/share/vm/runtime/arguments.hpp +++ b/hotspot/src/share/vm/runtime/arguments.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, 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 @@ -540,11 +540,6 @@ class Arguments : AllStatic { // Utility: copies src into buf, replacing "%%" with "%" and "%p" with pid. static bool copy_expand_pid(const char* src, size_t srclen, char* buf, size_t buflen); - -#ifdef KERNEL - // For java kernel vm, return property string for kernel properties. - static char *get_kernel_properties(); -#endif // KERNEL }; #endif // SHARE_VM_RUNTIME_ARGUMENTS_HPP diff --git a/hotspot/src/share/vm/runtime/thread.cpp b/hotspot/src/share/vm/runtime/thread.cpp index ff6adde6eee..7fe01ae8555 100644 --- a/hotspot/src/share/vm/runtime/thread.cpp +++ b/hotspot/src/share/vm/runtime/thread.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, 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 @@ -3739,28 +3739,6 @@ static OnLoadEntry_t lookup_on_load(AgentLibrary* agent, const char *on_load_sym name)) { library = os::dll_load(buffer, ebuf, sizeof ebuf); } -#ifdef KERNEL - // Download instrument dll - if (library == NULL && strcmp(name, "instrument") == 0) { - char *props = Arguments::get_kernel_properties(); - char *home = Arguments::get_java_home(); - const char *fmt = "%s/bin/java %s -Dkernel.background.download=false" - " sun.jkernel.DownloadManager -download client_jvm"; - size_t length = strlen(props) + strlen(home) + strlen(fmt) + 1; - char *cmd = NEW_C_HEAP_ARRAY(char, length, mtThread); - jio_snprintf(cmd, length, fmt, home, props); - int status = os::fork_and_exec(cmd); - FreeHeap(props); - if (status == -1) { - warning(cmd); - vm_exit_during_initialization("fork_and_exec failed: %s", - strerror(errno)); - } - FREE_C_HEAP_ARRAY(char, cmd, mtThread); - // when this comes back the instrument.dll should be where it belongs. - library = os::dll_load(buffer, ebuf, sizeof ebuf); - } -#endif // KERNEL if (library == NULL) { // Try the local directory char ns[1] = {0}; if (os::dll_build_name(buffer, sizeof(buffer), ns, name)) { diff --git a/hotspot/src/share/vm/runtime/vmStructs.hpp b/hotspot/src/share/vm/runtime/vmStructs.hpp index b1070a406e2..5c4c93a1f77 100644 --- a/hotspot/src/share/vm/runtime/vmStructs.hpp +++ b/hotspot/src/share/vm/runtime/vmStructs.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2013, 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 @@ -25,9 +25,7 @@ #ifndef SHARE_VM_RUNTIME_VMSTRUCTS_HPP #define SHARE_VM_RUNTIME_VMSTRUCTS_HPP -#ifndef VM_STRUCTS_KERNEL #include "utilities/debug.hpp" -#endif #ifdef COMPILER1 #include "c1/c1_Runtime1.hpp" #endif diff --git a/hotspot/src/share/vm/runtime/vm_version.cpp b/hotspot/src/share/vm/runtime/vm_version.cpp index 2d105a97baf..ef03c76f62b 100644 --- a/hotspot/src/share/vm/runtime/vm_version.cpp +++ b/hotspot/src/share/vm/runtime/vm_version.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2013, 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 @@ -111,9 +111,6 @@ void Abstract_VM_Version::initialize() { #endif #ifndef VMTYPE - #ifdef KERNEL - #define VMTYPE "Kernel" - #else // KERNEL #ifdef TIERED #define VMTYPE "Server" #else // TIERED @@ -128,7 +125,6 @@ void Abstract_VM_Version::initialize() { COMPILER2_PRESENT("Server") #endif // ZERO #endif // TIERED - #endif // KERNEL #endif #ifndef HOTSPOT_VM_DISTRO diff --git a/hotspot/src/share/vm/services/attachListener.cpp b/hotspot/src/share/vm/services/attachListener.cpp index 80dfd7effd4..da93859bb94 100644 --- a/hotspot/src/share/vm/services/attachListener.cpp +++ b/hotspot/src/share/vm/services/attachListener.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2013, 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 @@ -170,7 +170,6 @@ static jint jcmd(AttachOperation* op, outputStream* out) { return JNI_OK; } -#ifndef SERVICES_KERNEL // Heap dumping not supported // Implementation of "dumpheap" command. // See also: HeapDumpDCmd class // @@ -212,7 +211,6 @@ jint dump_heap(AttachOperation* op, outputStream* out) { } return JNI_OK; } -#endif // SERVICES_KERNEL // Implementation of "inspectheap" command // See also: ClassHistogramDCmd class @@ -382,9 +380,7 @@ static jint print_flag(AttachOperation* op, outputStream* out) { static AttachOperationFunctionInfo funcs[] = { { "agentProperties", get_agent_properties }, { "datadump", data_dump }, -#ifndef SERVICES_KERNEL { "dumpheap", dump_heap }, -#endif // SERVICES_KERNEL { "load", JvmtiExport::load_agent_library }, { "properties", get_system_properties }, { "threaddump", thread_dump }, diff --git a/hotspot/src/share/vm/services/attachListener.hpp b/hotspot/src/share/vm/services/attachListener.hpp index 1916e8cacb8..c69ff1820e7 100644 --- a/hotspot/src/share/vm/services/attachListener.hpp +++ b/hotspot/src/share/vm/services/attachListener.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2013, 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 @@ -38,8 +38,6 @@ // complets the result value and any result data is returned to the client // tool. -#ifndef SERVICES_KERNEL - class AttachOperation; typedef jint (*AttachOperationFunction)(AttachOperation* op, outputStream* out); @@ -48,7 +46,6 @@ struct AttachOperationFunctionInfo { const char* name; AttachOperationFunction func; }; -#endif // SERVICES_KERNEL class AttachListener: AllStatic { public: From 93b845e21bcb991c3e6c05072db3fafc476d0e8a Mon Sep 17 00:00:00 2001 From: Ioi Lam Date: Fri, 25 Jan 2013 15:06:18 -0500 Subject: [PATCH 101/210] 6479360: PrintClassHistogram improvements Jcmd GC.class_stats (UnlockDiagnosticVMOptions) Reviewed-by: coleenp, hseigel, sla, acorn --- .../share/vm/classfile/classLoaderData.cpp | 4 +- .../share/vm/classfile/classLoaderData.hpp | 4 +- .../shared/vmGCOperations.cpp | 6 +- .../shared/vmGCOperations.hpp | 14 +- .../src/share/vm/memory/heapInspection.cpp | 279 ++++++++++++++++-- .../src/share/vm/memory/heapInspection.hpp | 235 ++++++++++++++- hotspot/src/share/vm/oops/annotations.cpp | 47 ++- hotspot/src/share/vm/oops/annotations.hpp | 10 +- hotspot/src/share/vm/oops/arrayKlass.hpp | 10 +- hotspot/src/share/vm/oops/constMethod.cpp | 15 +- hotspot/src/share/vm/oops/constMethod.hpp | 6 +- hotspot/src/share/vm/oops/constantPool.cpp | 15 + hotspot/src/share/vm/oops/constantPool.hpp | 5 + hotspot/src/share/vm/oops/instanceKlass.cpp | 49 ++- hotspot/src/share/vm/oops/instanceKlass.hpp | 5 +- hotspot/src/share/vm/oops/klass.cpp | 14 +- hotspot/src/share/vm/oops/klass.hpp | 6 +- hotspot/src/share/vm/oops/method.cpp | 17 ++ hotspot/src/share/vm/oops/method.hpp | 6 +- hotspot/src/share/vm/oops/methodData.cpp | 12 +- hotspot/src/share/vm/oops/methodData.hpp | 6 +- .../share/vm/services/diagnosticCommand.cpp | 70 ++++- .../share/vm/services/diagnosticCommand.hpp | 25 +- 23 files changed, 807 insertions(+), 53 deletions(-) diff --git a/hotspot/src/share/vm/classfile/classLoaderData.cpp b/hotspot/src/share/vm/classfile/classLoaderData.cpp index 0560d3f4886..e74a88d7d33 100644 --- a/hotspot/src/share/vm/classfile/classLoaderData.cpp +++ b/hotspot/src/share/vm/classfile/classLoaderData.cpp @@ -724,13 +724,13 @@ void ClassLoaderDataGraph::dump_on(outputStream * const out) { } MetaspaceAux::dump(out); } +#endif // PRODUCT void ClassLoaderData::print_value_on(outputStream* out) const { if (class_loader() == NULL) { - out->print_cr("NULL class_loader"); + out->print("NULL class_loader"); } else { out->print("class loader "PTR_FORMAT, this); class_loader()->print_value_on(out); } } -#endif // PRODUCT diff --git a/hotspot/src/share/vm/classfile/classLoaderData.hpp b/hotspot/src/share/vm/classfile/classLoaderData.hpp index 9525658e67a..f72645db1c4 100644 --- a/hotspot/src/share/vm/classfile/classLoaderData.hpp +++ b/hotspot/src/share/vm/classfile/classLoaderData.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2013, 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 @@ -220,7 +220,7 @@ class ClassLoaderData : public CHeapObj { void set_jmethod_ids(JNIMethodBlock* new_block) { _jmethod_ids = new_block; } void print_value() { print_value_on(tty); } - void print_value_on(outputStream* out) const PRODUCT_RETURN; + void print_value_on(outputStream* out) const; void dump(outputStream * const out) PRODUCT_RETURN; void verify(); const char* loader_name(); diff --git a/hotspot/src/share/vm/gc_implementation/shared/vmGCOperations.cpp b/hotspot/src/share/vm/gc_implementation/shared/vmGCOperations.cpp index ee1be4a6490..941811c358b 100644 --- a/hotspot/src/share/vm/gc_implementation/shared/vmGCOperations.cpp +++ b/hotspot/src/share/vm/gc_implementation/shared/vmGCOperations.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2013, 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 @@ -167,7 +167,9 @@ void VM_GC_HeapInspection::doit() { ch->collect_as_vm_thread(GCCause::_heap_inspection); } } - HeapInspection::heap_inspection(_out, _need_prologue /* need_prologue */); + HeapInspection inspect(_csv_format, _print_help, _print_class_stats, + _columns); + inspect.heap_inspection(_out, _need_prologue /* need_prologue */); } diff --git a/hotspot/src/share/vm/gc_implementation/shared/vmGCOperations.hpp b/hotspot/src/share/vm/gc_implementation/shared/vmGCOperations.hpp index 285ef97e378..2a416f22843 100644 --- a/hotspot/src/share/vm/gc_implementation/shared/vmGCOperations.hpp +++ b/hotspot/src/share/vm/gc_implementation/shared/vmGCOperations.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2013, 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 @@ -130,6 +130,10 @@ class VM_GC_HeapInspection: public VM_GC_Operation { outputStream* _out; bool _full_gc; bool _need_prologue; + bool _csv_format; // "comma separated values" format for spreadsheet. + bool _print_help; + bool _print_class_stats; + const char* _columns; public: VM_GC_HeapInspection(outputStream* out, bool request_full_gc, bool need_prologue) : @@ -140,6 +144,10 @@ class VM_GC_HeapInspection: public VM_GC_Operation { _out = out; _full_gc = request_full_gc; _need_prologue = need_prologue; + _csv_format = false; + _print_help = false; + _print_class_stats = false; + _columns = NULL; } ~VM_GC_HeapInspection() {} @@ -147,6 +155,10 @@ class VM_GC_HeapInspection: public VM_GC_Operation { virtual bool skip_operation() const; virtual bool doit_prologue(); virtual void doit(); + void set_csv_format(bool value) {_csv_format = value;} + void set_print_help(bool value) {_print_help = value;} + void set_print_class_stats(bool value) {_print_class_stats = value;} + void set_columns(const char* value) {_columns = value;} }; diff --git a/hotspot/src/share/vm/memory/heapInspection.cpp b/hotspot/src/share/vm/memory/heapInspection.cpp index 71674fcb2d5..9275fe5b999 100644 --- a/hotspot/src/share/vm/memory/heapInspection.cpp +++ b/hotspot/src/share/vm/memory/heapInspection.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2013, 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 @@ -23,6 +23,7 @@ */ #include "precompiled.hpp" +#include "classfile/classLoaderData.hpp" #include "gc_interface/collectedHeap.hpp" #include "memory/genCollectedHeap.hpp" #include "memory/heapInspection.hpp" @@ -41,12 +42,24 @@ int KlassInfoEntry::compare(KlassInfoEntry* e1, KlassInfoEntry* e2) { } else if(e1->_instance_words < e2->_instance_words) { return 1; } - return 0; + // Sort alphabetically, note 'Z' < '[' < 'a', but it's better to group + // the array classes before all the instance classes. + ResourceMark rm; + const char* name1 = e1->klass()->external_name(); + const char* name2 = e2->klass()->external_name(); + bool d1 = (name1[0] == '['); + bool d2 = (name2[0] == '['); + if (d1 && !d2) { + return -1; + } else if (d2 && !d1) { + return 1; + } else { + return strcmp(name1, name2); + } } -void KlassInfoEntry::print_on(outputStream* st) const { - ResourceMark rm; - const char* name;; +const char* KlassInfoEntry::name() const { + const char* name; if (_klass->name() != NULL) { name = _klass->external_name(); } else { @@ -60,11 +73,17 @@ void KlassInfoEntry::print_on(outputStream* st) const { if (_klass == Universe::longArrayKlassObj()) name = ""; else name = ""; } + return name; +} + +void KlassInfoEntry::print_on(outputStream* st) const { + ResourceMark rm; + // simplify the formatting (ILP32 vs LP64) - always cast the numbers to 64-bit st->print_cr(INT64_FORMAT_W(13) " " UINT64_FORMAT_W(13) " %s", (jlong) _instance_count, (julong) _instance_words * HeapWordSize, - name); + name()); } KlassInfoEntry* KlassInfoBucket::lookup(Klass* const k) { @@ -101,7 +120,14 @@ void KlassInfoBucket::empty() { } } -KlassInfoTable::KlassInfoTable(int size, HeapWord* ref) { +void KlassInfoTable::AllClassesFinder::do_klass(Klass* k) { + // This has the SIDE EFFECT of creating a KlassInfoEntry + // for , if one doesn't exist yet. + _table->lookup(k); +} + +KlassInfoTable::KlassInfoTable(int size, HeapWord* ref, + bool need_class_stats) { _size = 0; _ref = ref; _buckets = NEW_C_HEAP_ARRAY(KlassInfoBucket, size, mtInternal); @@ -110,6 +136,10 @@ KlassInfoTable::KlassInfoTable(int size, HeapWord* ref) { for (int index = 0; index < _size; index++) { _buckets[index].initialize(); } + if (need_class_stats) { + AllClassesFinder finder(this); + ClassLoaderDataGraph::classes_do(&finder); + } } } @@ -165,7 +195,8 @@ int KlassInfoHisto::sort_helper(KlassInfoEntry** e1, KlassInfoEntry** e2) { return (*e1)->compare(*e1,*e2); } -KlassInfoHisto::KlassInfoHisto(const char* title, int estimatedCount) : +KlassInfoHisto::KlassInfoHisto(KlassInfoTable* cit, const char* title, int estimatedCount) : + _cit(cit), _title(title) { _elements = new (ResourceObj::C_HEAP, mtInternal) GrowableArray(estimatedCount,true); } @@ -196,9 +227,205 @@ void KlassInfoHisto::print_elements(outputStream* st) const { total, totalw * HeapWordSize); } -void KlassInfoHisto::print_on(outputStream* st) const { - st->print_cr("%s",title()); - print_elements(st); +#define MAKE_COL_NAME(field, name, help) #name, +#define MAKE_COL_HELP(field, name, help) help, + +static const char *name_table[] = { + HEAP_INSPECTION_COLUMNS_DO(MAKE_COL_NAME) +}; + +static const char *help_table[] = { + HEAP_INSPECTION_COLUMNS_DO(MAKE_COL_HELP) +}; + +bool KlassInfoHisto::is_selected(const char *col_name) { + if (_selected_columns == NULL) { + return true; + } + if (strcmp(_selected_columns, col_name) == 0) { + return true; + } + + const char *start = strstr(_selected_columns, col_name); + if (start == NULL) { + return false; + } + + // The following must be true, because _selected_columns != col_name + if (start > _selected_columns && start[-1] != ',') { + return false; + } + char x = start[strlen(col_name)]; + if (x != ',' && x != '\0') { + return false; + } + + return true; +} + +void KlassInfoHisto::print_title(outputStream* st, bool csv_format, + bool selected[], int width_table[], + const char *name_table[]) { + if (csv_format) { + st->print("Index,Super"); + for (int c=0; cprint(",%s", name_table[c]);} + } + st->print(",ClassName"); + } else { + st->print("Index Super"); + for (int c=0; cprint(str_fmt(width_table[c]), name_table[c]);} + } + st->print(" ClassName"); + } + + if (is_selected("ClassLoader")) { + st->print(",ClassLoader"); + } + st->cr(); +} + +void KlassInfoHisto::print_class_stats(outputStream* st, + bool csv_format, const char *columns) { + ResourceMark rm; + KlassSizeStats sz, sz_sum; + int i; + julong *col_table = (julong*)(&sz); + julong *colsum_table = (julong*)(&sz_sum); + int width_table[KlassSizeStats::_num_columns]; + bool selected[KlassSizeStats::_num_columns]; + + _selected_columns = columns; + + memset(&sz_sum, 0, sizeof(sz_sum)); + for (int c=0; clength(); i++) { + elements()->at(i)->set_index(i+1); + } + + for (int pass=1; pass<=2; pass++) { + if (pass == 2) { + print_title(st, csv_format, selected, width_table, name_table); + } + for(i=0; i < elements()->length(); i++) { + KlassInfoEntry* e = (KlassInfoEntry*)elements()->at(i); + const Klass* k = e->klass(); + + memset(&sz, 0, sizeof(sz)); + sz._inst_count = e->count(); + sz._inst_bytes = HeapWordSize * e->words(); + k->collect_statistics(&sz); + sz._total_bytes = sz._ro_bytes + sz._rw_bytes; + + if (pass == 1) { + for (int c=0; coop_is_instance()) { + Klass* super = ((InstanceKlass*)k)->java_super(); + if (super) { + KlassInfoEntry* super_e = _cit->lookup(super); + if (super_e) { + super_index = super_e->index(); + } + } + } + + if (csv_format) { + st->print("%d,%d", e->index(), super_index); + for (int c=0; cprint("," JULONG_FORMAT, col_table[c]);} + } + st->print(",%s",e->name()); + } else { + st->print("%5d %5d", e->index(), super_index); + for (int c=0; cprint(" %s", e->name()); + } + if (is_selected("ClassLoader")) { + ClassLoaderData* loader_data = k->class_loader_data(); + st->print(","); + loader_data->print_value_on(st); + } + st->cr(); + } + } + + if (pass == 1) { + for (int c=0; cprint(","); + for (int c=0; cprint("," JULONG_FORMAT, colsum_table[c]);} + } + } else { + st->print(" "); + for (int c=0; cprint(" Total"); + if (sz_sum._total_bytes > 0) { + st->cr(); + st->print(" "); + for (int c=0; cprint(str_fmt(width_table[c]), "-"); + break; + default: + { + double perc = (double)(100) * (double)(colsum_table[c]) / (double)sz_sum._total_bytes; + st->print(perc_fmt(width_table[c]), perc); + } + } + } + } + } + } + st->cr(); + + if (!csv_format) { + print_title(st, csv_format, selected, width_table, name_table); + } +} + +julong KlassInfoHisto::annotations_bytes(Array* p) const { + julong bytes = 0; + if (p != NULL) { + for (int i = 0; i < p->length(); i++) { + bytes += count_bytes_array(p->at(i)); + } + bytes += count_bytes_array(p); + } + return bytes; +} + +void KlassInfoHisto::print_histo_on(outputStream* st, bool print_stats, + bool csv_format, const char *columns) { + if (print_stats) { + print_class_stats(st, csv_format, columns); + } else { + st->print_cr("%s",title()); + print_elements(st); + } } class HistoClosure : public KlassInfoClosure { @@ -236,8 +463,26 @@ void HeapInspection::heap_inspection(outputStream* st, bool need_prologue) { CollectedHeap* heap = Universe::heap(); bool is_shared_heap = false; + if (_print_help) { + for (int c=0; cprint("%s:\n\t", name_table[c]); + const int max_col = 60; + int col = 0; + for (const char *p = help_table[c]; *p; p++,col++) { + if (col >= max_col && *p == ' ') { + st->print("\n\t"); + col = 0; + } else { + st->print("%c", *p); + } + } + st->print_cr(".\n"); + } + return; + } + // Collect klass instance info - KlassInfoTable cit(KlassInfoTable::cit_size, ref); + KlassInfoTable cit(KlassInfoTable::cit_size, ref, _print_class_stats); if (!cit.allocation_failed()) { // Iterate over objects in the heap RecordInstanceClosure ric(&cit); @@ -252,14 +497,14 @@ void HeapInspection::heap_inspection(outputStream* st, bool need_prologue) { missed_count); } // Sort and print klass instance info - KlassInfoHisto histo("\n" - " num #instances #bytes class name\n" - "----------------------------------------------", - KlassInfoHisto::histo_initial_size); + const char *title = "\n" + " num #instances #bytes class name\n" + "----------------------------------------------"; + KlassInfoHisto histo(&cit, title, KlassInfoHisto::histo_initial_size); HistoClosure hc(&histo); cit.iterate(&hc); histo.sort(); - histo.print_on(st); + histo.print_histo_on(st, _print_class_stats, _csv_format, _columns); } else { st->print_cr("WARNING: Ran out of C-heap; histogram not generated"); } diff --git a/hotspot/src/share/vm/memory/heapInspection.hpp b/hotspot/src/share/vm/memory/heapInspection.hpp index 72e675850d4..388e04242af 100644 --- a/hotspot/src/share/vm/memory/heapInspection.hpp +++ b/hotspot/src/share/vm/memory/heapInspection.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2013, 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 @@ -27,6 +27,7 @@ #include "memory/allocation.inline.hpp" #include "oops/oop.inline.hpp" +#include "oops/annotations.hpp" #if INCLUDE_SERVICES @@ -44,16 +45,144 @@ // to KlassInfoEntry's and is used to sort // the entries. +#define HEAP_INSPECTION_COLUMNS_DO(f) \ + f(inst_size, InstSize, \ + "Size of each object instance of the Java class") \ + f(inst_count, InstCount, \ + "Number of object instances of the Java class") \ + f(inst_bytes, InstBytes, \ + "This is usually (InstSize * InstNum). The only exception is " \ + "java.lang.Class, whose InstBytes also includes the slots " \ + "used to store static fields. InstBytes is not counted in " \ + "ROAll, RWAll or Total") \ + f(mirror_bytes, Mirror, \ + "Size of the Klass::java_mirror() object") \ + f(klass_bytes, KlassBytes, \ + "Size of the InstanceKlass or ArrayKlass for this class. " \ + "Note that this includes VTab, ITab, OopMap") \ + f(secondary_supers_bytes, K_secondary_supers, \ + "Number of bytes used by the Klass::secondary_supers() array") \ + f(vtab_bytes, VTab, \ + "Size of the embedded vtable in InstanceKlass") \ + f(itab_bytes, ITab, \ + "Size of the embedded itable in InstanceKlass") \ + f(nonstatic_oopmap_bytes, OopMap, \ + "Size of the embedded nonstatic_oop_map in InstanceKlass") \ + f(methods_array_bytes, IK_methods, \ + "Number of bytes used by the InstanceKlass::methods() array") \ + f(method_ordering_bytes, IK_method_ordering, \ + "Number of bytes used by the InstanceKlass::method_ordering() array") \ + f(local_interfaces_bytes, IK_local_interfaces, \ + "Number of bytes used by the InstanceKlass::local_interfaces() array") \ + f(transitive_interfaces_bytes, IK_transitive_interfaces, \ + "Number of bytes used by the InstanceKlass::transitive_interfaces() array") \ + f(fields_bytes, IK_fields, \ + "Number of bytes used by the InstanceKlass::fields() array") \ + f(inner_classes_bytes, IK_inner_classes, \ + "Number of bytes used by the InstanceKlass::inner_classes() array") \ + f(signers_bytes, IK_signers, \ + "Number of bytes used by the InstanceKlass::singers() array") \ + f(class_annotations_bytes, class_annotations, \ + "Size of class annotations") \ + f(fields_annotations_bytes, fields_annotations, \ + "Size of field annotations") \ + f(methods_annotations_bytes, methods_annotations, \ + "Size of method annotations") \ + f(methods_parameter_annotations_bytes, methods_parameter_annotations, \ + "Size of method parameter annotations") \ + f(methods_default_annotations_bytes, methods_default_annotations, \ + "Size of methods default annotations") \ + f(type_annotations_bytes, type_annotations, \ + "Size of type annotations") \ + f(annotations_bytes, annotations, \ + "Size of all annotations") \ + f(cp_bytes, Cp, \ + "Size of InstanceKlass::constants()") \ + f(cp_tags_bytes, CpTags, \ + "Size of InstanceKlass::constants()->tags()") \ + f(cp_cache_bytes, CpCache, \ + "Size of InstanceKlass::constants()->cache()") \ + f(cp_operands_bytes, CpOperands, \ + "Size of InstanceKlass::constants()->operands()") \ + f(cp_refmap_bytes, CpRefMap, \ + "Size of InstanceKlass::constants()->reference_map()") \ + f(cp_all_bytes, CpAll, \ + "Sum of Cp + CpTags + CpCache + CpOperands + CpRefMap") \ + f(method_count, MethodCount, \ + "Number of methods in this class") \ + f(method_bytes, MethodBytes, \ + "Size of the Method object") \ + f(const_method_bytes, ConstMethod, \ + "Size of the ConstMethod object") \ + f(method_data_bytes, MethodData, \ + "Size of the MethodData object") \ + f(stackmap_bytes, StackMap, \ + "Size of the stackmap_data") \ + f(bytecode_bytes, Bytecodes, \ + "Of the MethodBytes column, how much are the space taken up by bytecodes") \ + f(method_all_bytes, MethodAll, \ + "Sum of MethodBytes + Constmethod + Stackmap + Methoddata") \ + f(ro_bytes, ROAll, \ + "Size of all class meta data that could (potentially) be placed " \ + "in read-only memory. (This could change with CDS design)") \ + f(rw_bytes, RWAll, \ + "Size of all class meta data that must be placed in read/write " \ + "memory. (This could change with CDS design) ") \ + f(total_bytes, Total, \ + "ROAll + RWAll. Note that this does NOT include InstBytes.") + +// Size statistics for a Klass - filled in by Klass::collect_statistics() +class KlassSizeStats { +public: +#define COUNT_KLASS_SIZE_STATS_FIELD(field, name, help) _index_ ## field, +#define DECLARE_KLASS_SIZE_STATS_FIELD(field, name, help) julong _ ## field; + + enum { + HEAP_INSPECTION_COLUMNS_DO(COUNT_KLASS_SIZE_STATS_FIELD) + _num_columns + }; + + HEAP_INSPECTION_COLUMNS_DO(DECLARE_KLASS_SIZE_STATS_FIELD) + + static int count(oop x) { + return (HeapWordSize * ((x) ? (x)->size() : 0)); + } + + static int count_array(objArrayOop x) { + return (HeapWordSize * ((x) ? (x)->size() : 0)); + } + + template static int count(T* x) { + return (HeapWordSize * ((x) ? (x)->size() : 0)); + } + + template static int count_array(T* x) { + if (x == NULL) { + return 0; + } + if (x->length() == 0) { + // This is a shared array, e.g., Universe::the_empty_int_array(). Don't + // count it to avoid double-counting. + return 0; + } + return HeapWordSize * x->size(); + } +}; + + + + class KlassInfoEntry: public CHeapObj { private: KlassInfoEntry* _next; Klass* _klass; long _instance_count; size_t _instance_words; + long _index; public: KlassInfoEntry(Klass* k, KlassInfoEntry* next) : - _klass(k), _instance_count(0), _instance_words(0), _next(next) + _klass(k), _instance_count(0), _instance_words(0), _next(next), _index(-1) {} KlassInfoEntry* next() { return _next; } bool is_equal(Klass* k) { return k == _klass; } @@ -62,8 +191,11 @@ class KlassInfoEntry: public CHeapObj { void set_count(long ct) { _instance_count = ct; } size_t words() { return _instance_words; } void set_words(size_t wds) { _instance_words = wds; } + void set_index(long index) { _index = index; } + long index() { return _index; } int compare(KlassInfoEntry* e1, KlassInfoEntry* e2); void print_on(outputStream* st) const; + const char* name() const; }; class KlassInfoClosure: public StackObj { @@ -95,45 +227,132 @@ class KlassInfoTable: public StackObj { KlassInfoBucket* _buckets; uint hash(Klass* p); - KlassInfoEntry* lookup(Klass* const k); + KlassInfoEntry* lookup(Klass* const k); // allocates if not found! + + class AllClassesFinder : public KlassClosure { + KlassInfoTable *_table; + public: + AllClassesFinder(KlassInfoTable* table) : _table(table) {} + virtual void do_klass(Klass* k); + }; public: // Table size enum { cit_size = 20011 }; - KlassInfoTable(int size, HeapWord* ref); + KlassInfoTable(int size, HeapWord* ref, bool need_class_stats); ~KlassInfoTable(); bool record_instance(const oop obj); void iterate(KlassInfoClosure* cic); bool allocation_failed() { return _buckets == NULL; } + + friend class KlassInfoHisto; }; class KlassInfoHisto : public StackObj { private: + KlassInfoTable *_cit; GrowableArray* _elements; GrowableArray* elements() const { return _elements; } const char* _title; const char* title() const { return _title; } static int sort_helper(KlassInfoEntry** e1, KlassInfoEntry** e2); void print_elements(outputStream* st) const; + void print_class_stats(outputStream* st, bool csv_format, const char *columns); + julong annotations_bytes(Array* p) const; + const char *_selected_columns; + bool is_selected(const char *col_name); + void print_title(outputStream* st, bool csv_format, + bool selected_columns_table[], int width_table[], + const char *name_table[]); + + template static int count_bytes(T* x) { + return (HeapWordSize * ((x) ? (x)->size() : 0)); + } + + template static int count_bytes_array(T* x) { + if (x == NULL) { + return 0; + } + if (x->length() == 0) { + // This is a shared array, e.g., Universe::the_empty_int_array(). Don't + // count it to avoid double-counting. + return 0; + } + return HeapWordSize * x->size(); + } + + // returns a format string to print a julong with the given width. E.g, + // printf(num_fmt(6), julong(10)) would print out the number 10 with 4 + // leading spaces. + static void print_julong(outputStream* st, int width, julong n) { + int num_spaces = width - julong_width(n); + if (num_spaces > 0) { + st->print(str_fmt(num_spaces), ""); + } + st->print(JULONG_FORMAT, n); + } + + static char* perc_fmt(int width) { + static char buf[32]; + jio_snprintf(buf, sizeof(buf), "%%%d.1f%%%%", width-1); + return buf; + } + + static char* str_fmt(int width) { + static char buf[32]; + jio_snprintf(buf, sizeof(buf), "%%%ds", width); + return buf; + } + + static int julong_width(julong n) { + if (n == 0) { + return 1; + } + int w = 0; + while (n > 0) { + n /= 10; + w += 1; + } + return w; + } + + static int col_width(julong n, const char *name) { + int w = julong_width(n); + int min = (int)(strlen(name)); + if (w < min) { + w = min; + } + // add a leading space for separation. + return w + 1; + } + public: enum { histo_initial_size = 1000 }; - KlassInfoHisto(const char* title, + KlassInfoHisto(KlassInfoTable* cit, const char* title, int estimatedCount); ~KlassInfoHisto(); void add(KlassInfoEntry* cie); - void print_on(outputStream* st) const; + void print_histo_on(outputStream* st, bool print_class_stats, bool csv_format, const char *columns); void sort(); }; #endif // INCLUDE_SERVICES -class HeapInspection : public AllStatic { +class HeapInspection : public StackObj { + bool _csv_format; // "comma separated values" format for spreadsheet. + bool _print_help; + bool _print_class_stats; + const char* _columns; public: - static void heap_inspection(outputStream* st, bool need_prologue) NOT_SERVICES_RETURN; + HeapInspection(bool csv_format, bool print_help, + bool print_class_stats, const char *columns) : + _csv_format(csv_format), _print_help(print_help), + _print_class_stats(print_class_stats), _columns(columns) {} + void heap_inspection(outputStream* st, bool need_prologue) NOT_SERVICES_RETURN; static void find_instances_at_safepoint(Klass* k, GrowableArray* result) NOT_SERVICES_RETURN; }; diff --git a/hotspot/src/share/vm/oops/annotations.cpp b/hotspot/src/share/vm/oops/annotations.cpp index 72c5737f056..9e5d6ef3701 100644 --- a/hotspot/src/share/vm/oops/annotations.cpp +++ b/hotspot/src/share/vm/oops/annotations.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2013, 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 @@ -24,6 +24,7 @@ #include "precompiled.hpp" #include "classfile/classLoaderData.hpp" +#include "memory/heapInspection.hpp" #include "memory/metadataFactory.hpp" #include "memory/oopFactory.hpp" #include "oops/annotations.hpp" @@ -114,6 +115,50 @@ void Annotations::print_value_on(outputStream* st) const { st->print("Anotations(" INTPTR_FORMAT ")", this); } +#if INCLUDE_SERVICES +// Size Statistics + +julong Annotations::count_bytes(Array* p) { + julong bytes = 0; + if (p != NULL) { + for (int i = 0; i < p->length(); i++) { + bytes += KlassSizeStats::count_array(p->at(i)); + } + bytes += KlassSizeStats::count_array(p); + } + return bytes; +} + +void Annotations::collect_statistics(KlassSizeStats *sz) const { + sz->_annotations_bytes = sz->count(this); + sz->_class_annotations_bytes = sz->count(class_annotations()); + sz->_fields_annotations_bytes = count_bytes(fields_annotations()); + sz->_methods_annotations_bytes = count_bytes(methods_annotations()); + sz->_methods_parameter_annotations_bytes = + count_bytes(methods_parameter_annotations()); + sz->_methods_default_annotations_bytes = + count_bytes(methods_default_annotations()); + + const Annotations* type_anno = type_annotations(); + if (type_anno != NULL) { + sz->_type_annotations_bytes = sz->count(type_anno); + sz->_type_annotations_bytes += sz->count(type_anno->class_annotations()); + sz->_type_annotations_bytes += count_bytes(type_anno->fields_annotations()); + sz->_type_annotations_bytes += count_bytes(type_anno->methods_annotations()); + } + + sz->_annotations_bytes += + sz->_class_annotations_bytes + + sz->_fields_annotations_bytes + + sz->_methods_annotations_bytes + + sz->_methods_parameter_annotations_bytes + + sz->_methods_default_annotations_bytes + + sz->_type_annotations_bytes; + + sz->_ro_bytes += sz->_annotations_bytes; +} +#endif // INCLUDE_SERVICES + #define BULLET " - " #ifndef PRODUCT diff --git a/hotspot/src/share/vm/oops/annotations.hpp b/hotspot/src/share/vm/oops/annotations.hpp index 07d05467ba1..82d701ac584 100644 --- a/hotspot/src/share/vm/oops/annotations.hpp +++ b/hotspot/src/share/vm/oops/annotations.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2013, 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 @@ -34,6 +34,7 @@ class ClassLoaderData; class outputStream; +class KlassSizeStats; typedef Array AnnotationArray; @@ -82,7 +83,12 @@ class Annotations: public MetaspaceObj { Array* mda, TRAPS); void deallocate_contents(ClassLoaderData* loader_data); DEBUG_ONLY(bool on_stack() { return false; }) // for template + + // Sizing (in words) static int size() { return sizeof(Annotations) / wordSize; } +#if INCLUDE_SERVICES + void collect_statistics(KlassSizeStats *sz) const; +#endif // Constructor to initialize to null Annotations() : _class_annotations(NULL), @@ -142,7 +148,7 @@ class Annotations: public MetaspaceObj { void set_methods_annotations_of(instanceKlassHandle ik, int idnum, AnnotationArray* anno, Array** md_p, TRAPS); - + static julong count_bytes(Array* p); public: const char* internal_name() const { return "{constant pool}"; } #ifndef PRODUCT diff --git a/hotspot/src/share/vm/oops/arrayKlass.hpp b/hotspot/src/share/vm/oops/arrayKlass.hpp index 38a5340e366..f37a4d500ae 100644 --- a/hotspot/src/share/vm/oops/arrayKlass.hpp +++ b/hotspot/src/share/vm/oops/arrayKlass.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, 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 @@ -106,6 +106,14 @@ class ArrayKlass: public Klass { static int header_size() { return sizeof(ArrayKlass)/HeapWordSize; } static int static_size(int header_size); +#if INCLUDE_SERVICES + virtual void collect_statistics(KlassSizeStats *sz) const { + Klass::collect_statistics(sz); + // Do nothing for now, but remember to modify if you add new + // stuff to ArrayKlass. + } +#endif + // Java vtable klassVtable* vtable() const; // return new klassVtable int vtable_length() const { return _vtable_len; } diff --git a/hotspot/src/share/vm/oops/constMethod.cpp b/hotspot/src/share/vm/oops/constMethod.cpp index 79c10c0e62a..3358d225e2a 100644 --- a/hotspot/src/share/vm/oops/constMethod.cpp +++ b/hotspot/src/share/vm/oops/constMethod.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2013, 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 @@ -25,6 +25,7 @@ #include "precompiled.hpp" #include "interpreter/interpreter.hpp" #include "memory/gcLocker.hpp" +#include "memory/heapInspection.hpp" #include "memory/metadataFactory.hpp" #include "oops/constMethod.hpp" #include "oops/method.hpp" @@ -330,6 +331,18 @@ void ConstMethod::print_value_on(outputStream* st) const { method()->print_value_on(st); } +#if INCLUDE_SERVICES +// Size Statistics +void ConstMethod::collect_statistics(KlassSizeStats *sz) const { + int n1, n2, n3; + sz->_const_method_bytes += (n1 = sz->count(this)); + sz->_bytecode_bytes += (n2 = code_size()); + sz->_stackmap_bytes += (n3 = sz->count_array(stackmap_data())); + + sz->_method_all_bytes += n1 + n3; // note: n2 is part of n3 + sz->_ro_bytes += n1 + n3; +} +#endif // INCLUDE_SERVICES // Verification diff --git a/hotspot/src/share/vm/oops/constMethod.hpp b/hotspot/src/share/vm/oops/constMethod.hpp index 8b593982140..bd3acd23188 100644 --- a/hotspot/src/share/vm/oops/constMethod.hpp +++ b/hotspot/src/share/vm/oops/constMethod.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2013, 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 @@ -130,6 +130,7 @@ class MethodParametersElement VALUE_OBJ_CLASS_SPEC { u2 flags_lo; }; +class KlassSizeStats; class ConstMethod : public MetaspaceObj { friend class VMStructs; @@ -320,6 +321,9 @@ public: int size() const { return _constMethod_size;} void set_constMethod_size(int size) { _constMethod_size = size; } +#if INCLUDE_SERVICES + void collect_statistics(KlassSizeStats *sz) const; +#endif // code size int code_size() const { return _code_size; } diff --git a/hotspot/src/share/vm/oops/constantPool.cpp b/hotspot/src/share/vm/oops/constantPool.cpp index d4fa72032df..09c870a74ea 100644 --- a/hotspot/src/share/vm/oops/constantPool.cpp +++ b/hotspot/src/share/vm/oops/constantPool.cpp @@ -30,6 +30,7 @@ #include "classfile/systemDictionary.hpp" #include "classfile/vmSymbols.hpp" #include "interpreter/linkResolver.hpp" +#include "memory/heapInspection.hpp" #include "memory/metadataFactory.hpp" #include "memory/oopFactory.hpp" #include "oops/constantPool.hpp" @@ -1946,6 +1947,20 @@ void ConstantPool::print_value_on(outputStream* st) const { } } +#if INCLUDE_SERVICES +// Size Statistics +void ConstantPool::collect_statistics(KlassSizeStats *sz) const { + sz->_cp_all_bytes += (sz->_cp_bytes = sz->count(this)); + sz->_cp_all_bytes += (sz->_cp_tags_bytes = sz->count_array(tags())); + sz->_cp_all_bytes += (sz->_cp_cache_bytes = sz->count(cache())); + sz->_cp_all_bytes += (sz->_cp_operands_bytes = sz->count_array(operands())); + sz->_cp_all_bytes += (sz->_cp_refmap_bytes = sz->count_array(reference_map())); + + sz->_ro_bytes += sz->_cp_operands_bytes + sz->_cp_tags_bytes + + sz->_cp_refmap_bytes; + sz->_rw_bytes += sz->_cp_bytes + sz->_cp_cache_bytes; +} +#endif // INCLUDE_SERVICES // Verification diff --git a/hotspot/src/share/vm/oops/constantPool.hpp b/hotspot/src/share/vm/oops/constantPool.hpp index ea4b13f0f9d..0d1f18878ff 100644 --- a/hotspot/src/share/vm/oops/constantPool.hpp +++ b/hotspot/src/share/vm/oops/constantPool.hpp @@ -80,6 +80,7 @@ class CPSlot VALUE_OBJ_CLASS_SPEC { } }; +class KlassSizeStats; class ConstantPool : public Metadata { friend class VMStructs; friend class BytecodeInterpreter; // Directly extracts an oop in the pool for fast instanceof/checkcast @@ -684,9 +685,13 @@ class ConstantPool : public Metadata { return 0 <= index && index < length(); } + // Sizing (in words) static int header_size() { return sizeof(ConstantPool)/HeapWordSize; } static int size(int length) { return align_object_size(header_size() + length); } int size() const { return size(length()); } +#if INCLUDE_SERVICES + void collect_statistics(KlassSizeStats *sz) const; +#endif friend class ClassFileParser; friend class SystemDictionary; diff --git a/hotspot/src/share/vm/oops/instanceKlass.cpp b/hotspot/src/share/vm/oops/instanceKlass.cpp index b0b7038e35b..c79378658e6 100644 --- a/hotspot/src/share/vm/oops/instanceKlass.cpp +++ b/hotspot/src/share/vm/oops/instanceKlass.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, 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 @@ -34,6 +34,7 @@ #include "interpreter/rewriter.hpp" #include "jvmtifiles/jvmti.h" #include "memory/genOopClosures.inline.hpp" +#include "memory/heapInspection.hpp" #include "memory/metadataFactory.hpp" #include "memory/oopFactory.hpp" #include "oops/fieldStreams.hpp" @@ -2960,6 +2961,52 @@ const char* InstanceKlass::internal_name() const { return external_name(); } +#if INCLUDE_SERVICES +// Size Statistics +void InstanceKlass::collect_statistics(KlassSizeStats *sz) const { + Klass::collect_statistics(sz); + + sz->_inst_size = HeapWordSize * size_helper(); + sz->_vtab_bytes = HeapWordSize * align_object_offset(vtable_length()); + sz->_itab_bytes = HeapWordSize * align_object_offset(itable_length()); + sz->_nonstatic_oopmap_bytes = HeapWordSize * + ((is_interface() || is_anonymous()) ? + align_object_offset(nonstatic_oop_map_size()) : + nonstatic_oop_map_size()); + + int n = 0; + n += (sz->_methods_array_bytes = sz->count_array(methods())); + n += (sz->_method_ordering_bytes = sz->count_array(method_ordering())); + n += (sz->_local_interfaces_bytes = sz->count_array(local_interfaces())); + n += (sz->_transitive_interfaces_bytes = sz->count_array(transitive_interfaces())); + n += (sz->_signers_bytes = sz->count_array(signers())); + n += (sz->_fields_bytes = sz->count_array(fields())); + n += (sz->_inner_classes_bytes = sz->count_array(inner_classes())); + sz->_ro_bytes += n; + + const ConstantPool* cp = constants(); + if (cp) { + cp->collect_statistics(sz); + } + + const Annotations* anno = annotations(); + if (anno) { + anno->collect_statistics(sz); + } + + const Array* methods_array = methods(); + if (methods()) { + for (int i = 0; i < methods_array->length(); i++) { + Method* method = methods_array->at(i); + if (method) { + sz->_method_count ++; + method->collect_statistics(sz); + } + } + } +} +#endif // INCLUDE_SERVICES + // Verification class VerifyFieldClosure: public OopClosure { diff --git a/hotspot/src/share/vm/oops/instanceKlass.hpp b/hotspot/src/share/vm/oops/instanceKlass.hpp index 97b3dd23313..ba45aa4b039 100644 --- a/hotspot/src/share/vm/oops/instanceKlass.hpp +++ b/hotspot/src/share/vm/oops/instanceKlass.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, 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 @@ -826,6 +826,9 @@ class InstanceKlass: public Klass { is_interface(), is_anonymous()); } +#if INCLUDE_SERVICES + virtual void collect_statistics(KlassSizeStats *sz) const; +#endif static int vtable_start_offset() { return header_size(); } static int vtable_length_offset() { return offset_of(InstanceKlass, _vtable_len) / HeapWordSize; } diff --git a/hotspot/src/share/vm/oops/klass.cpp b/hotspot/src/share/vm/oops/klass.cpp index 21bfb6bda69..4b33e36bf87 100644 --- a/hotspot/src/share/vm/oops/klass.cpp +++ b/hotspot/src/share/vm/oops/klass.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, 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 @@ -29,6 +29,7 @@ #include "classfile/vmSymbols.hpp" #include "gc_implementation/shared/markSweep.inline.hpp" #include "gc_interface/collectedHeap.inline.hpp" +#include "memory/heapInspection.hpp" #include "memory/metadataFactory.hpp" #include "memory/oopFactory.hpp" #include "memory/resourceArea.hpp" @@ -624,6 +625,17 @@ void Klass::oop_print_value_on(oop obj, outputStream* st) { obj->print_address_on(st); } +#if INCLUDE_SERVICES +// Size Statistics +void Klass::collect_statistics(KlassSizeStats *sz) const { + sz->_klass_bytes = sz->count(this); + sz->_mirror_bytes = sz->count(java_mirror()); + sz->_secondary_supers_bytes = sz->count_array(secondary_supers()); + + sz->_ro_bytes += sz->_secondary_supers_bytes; + sz->_rw_bytes += sz->_klass_bytes + sz->_mirror_bytes; +} +#endif // INCLUDE_SERVICES // Verification diff --git a/hotspot/src/share/vm/oops/klass.hpp b/hotspot/src/share/vm/oops/klass.hpp index be5d0c5293d..ac4e84221cd 100644 --- a/hotspot/src/share/vm/oops/klass.hpp +++ b/hotspot/src/share/vm/oops/klass.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, 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 @@ -91,6 +91,7 @@ template class GrowableArray; class ClassLoaderData; class klassVtable; class ParCompactionManager; +class KlassSizeStats; class Klass : public Metadata { friend class VMStructs; @@ -477,6 +478,9 @@ class Klass : public Metadata { // Size of klass in word size. virtual int size() const = 0; +#if INCLUDE_SERVICES + virtual void collect_statistics(KlassSizeStats *sz) const; +#endif // Returns the Java name for a class (Resource allocated) // For arrays, this returns the name of the element with a leading '['. diff --git a/hotspot/src/share/vm/oops/method.cpp b/hotspot/src/share/vm/oops/method.cpp index 88645cb15e7..c2e7993c065 100644 --- a/hotspot/src/share/vm/oops/method.cpp +++ b/hotspot/src/share/vm/oops/method.cpp @@ -34,6 +34,7 @@ #include "interpreter/oopMapCache.hpp" #include "memory/gcLocker.hpp" #include "memory/generation.hpp" +#include "memory/heapInspection.hpp" #include "memory/metadataFactory.hpp" #include "memory/oopFactory.hpp" #include "oops/constMethod.hpp" @@ -1954,6 +1955,22 @@ void Method::print_value_on(outputStream* st) const { if (WizardMode && code() != NULL) st->print(" ((nmethod*)%p)", code()); } +#if INCLUDE_SERVICES +// Size Statistics +void Method::collect_statistics(KlassSizeStats *sz) const { + int mysize = sz->count(this); + sz->_method_bytes += mysize; + sz->_method_all_bytes += mysize; + sz->_rw_bytes += mysize; + + if (constMethod()) { + constMethod()->collect_statistics(sz); + } + if (method_data()) { + method_data()->collect_statistics(sz); + } +} +#endif // INCLUDE_SERVICES // Verification diff --git a/hotspot/src/share/vm/oops/method.hpp b/hotspot/src/share/vm/oops/method.hpp index 72a4faf11d7..1b16435696e 100644 --- a/hotspot/src/share/vm/oops/method.hpp +++ b/hotspot/src/share/vm/oops/method.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, 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 @@ -101,6 +101,7 @@ class LocalVariableTableElement; class AdapterHandlerEntry; class MethodData; class ConstMethod; +class KlassSizeStats; class Method : public Metadata { friend class VMStructs; @@ -593,6 +594,9 @@ class Method : public Metadata { static int header_size() { return sizeof(Method)/HeapWordSize; } static int size(bool is_native); int size() const { return method_size(); } +#if INCLUDE_SERVICES + void collect_statistics(KlassSizeStats *sz) const; +#endif // interpreter support static ByteSize const_offset() { return byte_offset_of(Method, _constMethod ); } diff --git a/hotspot/src/share/vm/oops/methodData.cpp b/hotspot/src/share/vm/oops/methodData.cpp index 71d9649c268..c7a200f9e47 100644 --- a/hotspot/src/share/vm/oops/methodData.cpp +++ b/hotspot/src/share/vm/oops/methodData.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2013, 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 @@ -27,6 +27,7 @@ #include "interpreter/bytecode.hpp" #include "interpreter/bytecodeStream.hpp" #include "interpreter/linkResolver.hpp" +#include "memory/heapInspection.hpp" #include "oops/methodData.hpp" #include "prims/jvmtiRedefineClasses.hpp" #include "runtime/compilationPolicy.hpp" @@ -859,6 +860,15 @@ void MethodData::print_data_on(outputStream* st) const { } #endif +#if INCLUDE_SERVICES +// Size Statistics +void MethodData::collect_statistics(KlassSizeStats *sz) const { + int n = sz->count(this); + sz->_method_data_bytes += n; + sz->_method_all_bytes += n; + sz->_rw_bytes += n; +} +#endif // INCLUDE_SERVICES // Verification diff --git a/hotspot/src/share/vm/oops/methodData.hpp b/hotspot/src/share/vm/oops/methodData.hpp index 133278878ef..1ad58cbb207 100644 --- a/hotspot/src/share/vm/oops/methodData.hpp +++ b/hotspot/src/share/vm/oops/methodData.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2013, 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 @@ -32,6 +32,7 @@ #include "runtime/orderAccess.hpp" class BytecodeStream; +class KlassSizeStats; // The MethodData object collects counts and other profile information // during zeroth-tier (interpretive) and first-tier execution. @@ -1289,6 +1290,9 @@ public: // My size int size_in_bytes() const { return _size; } int size() const { return align_object_size(align_size_up(_size, BytesPerWord)/BytesPerWord); } +#if INCLUDE_SERVICES + void collect_statistics(KlassSizeStats *sz) const; +#endif int creation_mileage() const { return _creation_mileage; } void set_creation_mileage(int x) { _creation_mileage = x; } diff --git a/hotspot/src/share/vm/services/diagnosticCommand.cpp b/hotspot/src/share/vm/services/diagnosticCommand.cpp index 52a098a2613..6bdc059f35b 100644 --- a/hotspot/src/share/vm/services/diagnosticCommand.cpp +++ b/hotspot/src/share/vm/services/diagnosticCommand.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2013, 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 @@ -43,12 +43,12 @@ void DCmdRegistrant::register_dcmds(){ DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(true, false)); DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(true, false)); DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(true, false)); -#if INCLUDE_SERVICES // Heap dumping supported +#if INCLUDE_SERVICES // Heap dumping/inspection supported DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(true, false)); -#endif // INCLUDE_SERVICES DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(true, false)); + DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(true, false)); +#endif // INCLUDE_SERVICES DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(true, false)); - //Enhanced JMX Agent Support DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(true,false)); DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(true,false)); @@ -252,7 +252,7 @@ void RunFinalizationDCmd::execute(TRAPS) { vmSymbols::void_method_signature(), CHECK); } -#if INCLUDE_SERVICES // Heap dumping supported +#if INCLUDE_SERVICES // Heap dumping/inspection supported HeapDumpDCmd::HeapDumpDCmd(outputStream* output, bool heap) : DCmdWithParser(output, heap), _filename("filename","Name of the dump file", "STRING",true), @@ -292,7 +292,6 @@ int HeapDumpDCmd::num_arguments() { return 0; } } -#endif // INCLUDE_SERVICES ClassHistogramDCmd::ClassHistogramDCmd(outputStream* output, bool heap) : DCmdWithParser(output, heap), @@ -319,6 +318,65 @@ int ClassHistogramDCmd::num_arguments() { } } +#define DEFAULT_COLUMNS "InstBytes,KlassBytes,CpAll,annotations,MethodCount,Bytecodes,MethodAll,ROAll,RWAll,Total" +ClassStatsDCmd::ClassStatsDCmd(outputStream* output, bool heap) : + DCmdWithParser(output, heap), + _csv("-csv", "Print in CSV (comma-separated values) format for spreadsheets", + "BOOLEAN", false, "false"), + _all("-all", "Show all columns", + "BOOLEAN", false, "false"), + _help("-help", "Show meaning of all the columns", + "BOOLEAN", false, "false"), + _columns("columns", "Comma-separated list of all the columns to show. " + "If not specified, the following columns are shown: " DEFAULT_COLUMNS, + "STRING", false) { + _dcmdparser.add_dcmd_option(&_all); + _dcmdparser.add_dcmd_option(&_csv); + _dcmdparser.add_dcmd_option(&_help); + _dcmdparser.add_dcmd_argument(&_columns); +} + +void ClassStatsDCmd::execute(TRAPS) { + if (!UnlockDiagnosticVMOptions) { + output()->print_cr("GC.class_stats command requires -XX:+UnlockDiagnosticVMOptions"); + return; + } + + VM_GC_HeapInspection heapop(output(), + true, /* request_full_gc */ + true /* need_prologue */); + heapop.set_csv_format(_csv.value()); + heapop.set_print_help(_help.value()); + heapop.set_print_class_stats(true); + if (_all.value()) { + if (_columns.has_value()) { + output()->print_cr("Cannot specify -all and individual columns at the same time"); + return; + } else { + heapop.set_columns(NULL); + } + } else { + if (_columns.has_value()) { + heapop.set_columns(_columns.value()); + } else { + heapop.set_columns(DEFAULT_COLUMNS); + } + } + VMThread::execute(&heapop); +} + +int ClassStatsDCmd::num_arguments() { + ResourceMark rm; + ClassStatsDCmd* dcmd = new ClassStatsDCmd(NULL, false); + if (dcmd != NULL) { + DCmdMark mark(dcmd); + return dcmd->_dcmdparser.num_arguments(); + } else { + return 0; + } +} +#endif // INCLUDE_SERVICES + ThreadDumpDCmd::ThreadDumpDCmd(outputStream* output, bool heap) : DCmdWithParser(output, heap), _locks("-l", "print java.util.concurrent locks", "BOOLEAN", false, "false") { diff --git a/hotspot/src/share/vm/services/diagnosticCommand.hpp b/hotspot/src/share/vm/services/diagnosticCommand.hpp index 99d75a92f33..10b7214f17a 100644 --- a/hotspot/src/share/vm/services/diagnosticCommand.hpp +++ b/hotspot/src/share/vm/services/diagnosticCommand.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2013, 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 @@ -178,7 +178,7 @@ public: }; #endif // INCLUDE_SERVICES -// See also: inspeactheap in attachListener.cpp +// See also: inspectheap in attachListener.cpp class ClassHistogramDCmd : public DCmdWithParser { protected: DCmdArgument _all; @@ -197,6 +197,27 @@ public: virtual void execute(TRAPS); }; +class ClassStatsDCmd : public DCmdWithParser { +protected: + DCmdArgument _all; + DCmdArgument _csv; + DCmdArgument _help; + DCmdArgument _columns; +public: + ClassStatsDCmd(outputStream* output, bool heap); + static const char* name() { + return "GC.class_stats"; + } + static const char* description() { + return "Provide statistics about Java class meta data. Requires -XX:+UnlockDiagnosticVMOptions."; + } + static const char* impact() { + return "High: Depends on Java heap size and content."; + } + static int num_arguments(); + virtual void execute(TRAPS); +}; + // See also: thread_dump in attachListener.cpp class ThreadDumpDCmd : public DCmdWithParser { protected: From a25db953cc4116d5161b994e1379573ca4de6675 Mon Sep 17 00:00:00 2001 From: Igor Ignatyev Date: Fri, 1 Feb 2013 02:50:23 -0800 Subject: [PATCH 102/210] 8006410: allocating without ResourceMark when CompileCommand was specified Reviewed-by: kvn, vlivanov --- hotspot/src/share/vm/ci/ciEnv.cpp | 2 +- hotspot/src/share/vm/ci/ciInstanceKlass.cpp | 3 +++ hotspot/src/share/vm/ci/ciMethod.cpp | 1 + hotspot/src/share/vm/ci/ciMethodData.cpp | 1 + hotspot/src/share/vm/oops/symbol.cpp | 1 + 5 files changed, 7 insertions(+), 1 deletion(-) diff --git a/hotspot/src/share/vm/ci/ciEnv.cpp b/hotspot/src/share/vm/ci/ciEnv.cpp index bb51f88c7b9..de0bd082555 100644 --- a/hotspot/src/share/vm/ci/ciEnv.cpp +++ b/hotspot/src/share/vm/ci/ciEnv.cpp @@ -1168,7 +1168,7 @@ void ciEnv::dump_replay_data() { void ciEnv::dump_replay_data(outputStream* out) { ASSERT_IN_VM; - + ResourceMark rm; #if INCLUDE_JVMTI out->print_cr("JvmtiExport can_access_local_variables %d", _jvmti_can_access_local_variables); out->print_cr("JvmtiExport can_hotswap_or_post_breakpoint %d", _jvmti_can_hotswap_or_post_breakpoint); diff --git a/hotspot/src/share/vm/ci/ciInstanceKlass.cpp b/hotspot/src/share/vm/ci/ciInstanceKlass.cpp index de5e973bfbf..d74e3693ae1 100644 --- a/hotspot/src/share/vm/ci/ciInstanceKlass.cpp +++ b/hotspot/src/share/vm/ci/ciInstanceKlass.cpp @@ -580,6 +580,7 @@ class StaticFinalFieldPrinter : public FieldClosure { } void do_field(fieldDescriptor* fd) { if (fd->is_final() && !fd->has_initial_value()) { + ResourceMark rm; oop mirror = fd->field_holder()->java_mirror(); _out->print("staticfield %s %s %s ", _holder, fd->name()->as_quoted_ascii(), fd->signature()->as_quoted_ascii()); switch (fd->field_type()) { @@ -643,6 +644,8 @@ class StaticFinalFieldPrinter : public FieldClosure { void ciInstanceKlass::dump_replay_data(outputStream* out) { ASSERT_IN_VM; + ResourceMark rm; + InstanceKlass* ik = get_instanceKlass(); ConstantPool* cp = ik->constants(); diff --git a/hotspot/src/share/vm/ci/ciMethod.cpp b/hotspot/src/share/vm/ci/ciMethod.cpp index 8ad9ecb1199..e5c5e72de9b 100644 --- a/hotspot/src/share/vm/ci/ciMethod.cpp +++ b/hotspot/src/share/vm/ci/ciMethod.cpp @@ -1178,6 +1178,7 @@ ciMethodBlocks *ciMethod::get_method_blocks() { void ciMethod::dump_replay_data(outputStream* st) { ASSERT_IN_VM; + ResourceMark rm; Method* method = get_Method(); Klass* holder = method->method_holder(); st->print_cr("ciMethod %s %s %s %d %d %d %d %d", diff --git a/hotspot/src/share/vm/ci/ciMethodData.cpp b/hotspot/src/share/vm/ci/ciMethodData.cpp index ee5490be877..c30c6c36437 100644 --- a/hotspot/src/share/vm/ci/ciMethodData.cpp +++ b/hotspot/src/share/vm/ci/ciMethodData.cpp @@ -374,6 +374,7 @@ void ciMethodData::print_impl(outputStream* st) { void ciMethodData::dump_replay_data(outputStream* out) { ASSERT_IN_VM; + ResourceMark rm; MethodData* mdo = get_MethodData(); Method* method = mdo->method(); Klass* holder = method->method_holder(); diff --git a/hotspot/src/share/vm/oops/symbol.cpp b/hotspot/src/share/vm/oops/symbol.cpp index f2253dbcce0..54601899287 100644 --- a/hotspot/src/share/vm/oops/symbol.cpp +++ b/hotspot/src/share/vm/oops/symbol.cpp @@ -152,6 +152,7 @@ char* Symbol::as_C_string_flexible_buffer(Thread* t, } void Symbol::print_symbol_on(outputStream* st) const { + ResourceMark rm; st = st ? st : tty; st->print("%s", as_quoted_ascii()); } From 1a9e6be809a6b6c5f9149b99f43b1c7b56617690 Mon Sep 17 00:00:00 2001 From: Igor Ignatyev Date: Fri, 1 Feb 2013 03:02:01 -0800 Subject: [PATCH 103/210] 8005439: no message about inline method if it specifed by CompileCommand Reviewed-by: kvn, vlivanov --- hotspot/src/share/vm/c1/c1_GraphBuilder.cpp | 9 ++-- hotspot/src/share/vm/opto/bytecodeInfo.cpp | 52 ++++++++++++--------- hotspot/src/share/vm/opto/parse.hpp | 3 +- 3 files changed, 38 insertions(+), 26 deletions(-) diff --git a/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp b/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp index cbaf83b8fea..9491607adfa 100644 --- a/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp +++ b/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp @@ -3667,11 +3667,12 @@ bool GraphBuilder::try_inline_full(ciMethod* callee, bool holder_known, Bytecode } // now perform tests that are based on flag settings - if (callee->force_inline() || callee->should_inline()) { - // ignore heuristic controls on inlining - if (callee->force_inline()) - print_inlining(callee, "force inline by annotation"); + if (callee->force_inline()) { + print_inlining(callee, "force inline by annotation"); + } else if (callee->should_inline()) { + print_inlining(callee, "force inline by CompileOracle"); } else { + // use heuristic controls on inlining if (inline_level() > MaxInlineLevel ) INLINE_BAILOUT("inlining too deep"); if (recursive_inline_level(callee) > MaxRecursiveInlineLevel) INLINE_BAILOUT("recursive inlining too deep"); if (callee->code_size_for_inlining() > max_inline_size() ) INLINE_BAILOUT("callee is too large"); diff --git a/hotspot/src/share/vm/opto/bytecodeInfo.cpp b/hotspot/src/share/vm/opto/bytecodeInfo.cpp index 5b80bd75c4b..3da308c27b2 100644 --- a/hotspot/src/share/vm/opto/bytecodeInfo.cpp +++ b/hotspot/src/share/vm/opto/bytecodeInfo.cpp @@ -420,14 +420,24 @@ const char* InlineTree::check_can_parse(ciMethod* callee) { } //------------------------------print_inlining--------------------------------- -// Really, the failure_msg can be a success message also. -void InlineTree::print_inlining(ciMethod* callee_method, int caller_bci, const char* failure_msg) const { - C->print_inlining(callee_method, inline_level(), caller_bci, failure_msg ? failure_msg : "inline"); - if (callee_method == NULL) tty->print(" callee not monotonic or profiled"); - if (Verbose && callee_method) { - const InlineTree *top = this; - while( top->caller_tree() != NULL ) { top = top->caller_tree(); } - //tty->print(" bcs: %d+%d invoked: %d", top->count_inline_bcs(), callee_method->code_size(), callee_method->interpreter_invocation_count()); +void InlineTree::print_inlining(ciMethod* callee_method, int caller_bci, + const char* msg, bool success) const { + assert(msg != NULL, "just checking"); + if (C->log() != NULL) { + if (success) { + C->log()->inline_success(msg); + } else { + C->log()->inline_fail(msg); + } + } + if (PrintInlining) { + C->print_inlining(callee_method, inline_level(), caller_bci, msg); + if (callee_method == NULL) tty->print(" callee not monotonic or profiled"); + if (Verbose && callee_method) { + const InlineTree *top = this; + while( top->caller_tree() != NULL ) { top = top->caller_tree(); } + //tty->print(" bcs: %d+%d invoked: %d", top->count_inline_bcs(), callee_method->code_size(), callee_method->interpreter_invocation_count()); + } } } @@ -451,23 +461,23 @@ WarmCallInfo* InlineTree::ok_to_inline(ciMethod* callee_method, JVMState* jvms, // Do some initial checks. if (!pass_initial_checks(caller_method, caller_bci, callee_method)) { - if (PrintInlining) print_inlining(callee_method, caller_bci, "failed initial checks"); + print_inlining(callee_method, caller_bci, "failed initial checks", + false /* !success */); return NULL; } // Do some parse checks. failure_msg = check_can_parse(callee_method); if (failure_msg != NULL) { - if (PrintInlining) print_inlining(callee_method, caller_bci, failure_msg); + print_inlining(callee_method, caller_bci, failure_msg, + false /* !success */); return NULL; } // Check if inlining policy says no. WarmCallInfo wci = *(initial_wci); - failure_msg = try_to_inline(callee_method, caller_method, caller_bci, profile, &wci, should_delay); - if (failure_msg != NULL && C->log() != NULL) { - C->log()->inline_fail(failure_msg); - } + failure_msg = try_to_inline(callee_method, caller_method, caller_bci, profile, + &wci, should_delay); #ifndef PRODUCT if (UseOldInlining && InlineWarmCalls @@ -487,7 +497,7 @@ WarmCallInfo* InlineTree::ok_to_inline(ciMethod* callee_method, JVMState* jvms, wci = *(WarmCallInfo::always_hot()); else wci = *(WarmCallInfo::always_cold()); - } + } if (!InlineWarmCalls) { if (!wci.is_cold() && !wci.is_hot()) { // Do not inline the warm calls. @@ -496,11 +506,10 @@ WarmCallInfo* InlineTree::ok_to_inline(ciMethod* callee_method, JVMState* jvms, } if (!wci.is_cold()) { - // In -UseOldInlining, the failure_msg may also be a success message. - if (failure_msg == NULL) failure_msg = "inline (hot)"; - // Inline! - if (PrintInlining) print_inlining(callee_method, caller_bci, failure_msg); + print_inlining(callee_method, caller_bci, + failure_msg ? failure_msg : "inline (hot)", + true /* success */); if (UseOldInlining) build_inline_tree_for_callee(callee_method, jvms, caller_bci); if (InlineWarmCalls && !wci.is_hot()) @@ -509,8 +518,9 @@ WarmCallInfo* InlineTree::ok_to_inline(ciMethod* callee_method, JVMState* jvms, } // Do not inline - if (failure_msg == NULL) failure_msg = "too cold to inline"; - if (PrintInlining) print_inlining(callee_method, caller_bci, failure_msg); + print_inlining(callee_method, caller_bci, + failure_msg ? failure_msg : "too cold to inline", + false /* !success */ ); return NULL; } diff --git a/hotspot/src/share/vm/opto/parse.hpp b/hotspot/src/share/vm/opto/parse.hpp index c880832a446..2cf487f8ad6 100644 --- a/hotspot/src/share/vm/opto/parse.hpp +++ b/hotspot/src/share/vm/opto/parse.hpp @@ -73,7 +73,8 @@ protected: const char* try_to_inline(ciMethod* callee_method, ciMethod* caller_method, int caller_bci, ciCallProfile& profile, WarmCallInfo* wci_result, bool& should_delay); const char* should_inline(ciMethod* callee_method, ciMethod* caller_method, int caller_bci, ciCallProfile& profile, WarmCallInfo* wci_result) const; const char* should_not_inline(ciMethod* callee_method, ciMethod* caller_method, WarmCallInfo* wci_result) const; - void print_inlining(ciMethod *callee_method, int caller_bci, const char *failure_msg) const; + void print_inlining(ciMethod* callee_method, int caller_bci, + const char* msg, bool success) const; InlineTree *caller_tree() const { return _caller_tree; } InlineTree* callee_at(int bci, ciMethod* m) const; From 6c80586b400c46f570cb248e4e5b67f095498cb6 Mon Sep 17 00:00:00 2001 From: Morris Meyer Date: Fri, 25 Jan 2013 16:31:47 -0800 Subject: [PATCH 104/210] 8005811: Turn off TierdCompilation in JDK8 trunk for all platforms Disable tiered compilation in jdk8 because of CodeCache and performance anomalies Reviewed-by: kvn, twisti --- hotspot/src/cpu/sparc/vm/c2_globals_sparc.hpp | 2 +- hotspot/src/cpu/x86/vm/c2_globals_x86.hpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/hotspot/src/cpu/sparc/vm/c2_globals_sparc.hpp b/hotspot/src/cpu/sparc/vm/c2_globals_sparc.hpp index 0dcdea0567b..c642e915fe1 100644 --- a/hotspot/src/cpu/sparc/vm/c2_globals_sparc.hpp +++ b/hotspot/src/cpu/sparc/vm/c2_globals_sparc.hpp @@ -42,7 +42,7 @@ define_pd_global(bool, ProfileInterpreter, false); #else define_pd_global(bool, ProfileInterpreter, true); #endif // CC_INTERP -define_pd_global(bool, TieredCompilation, trueInTiered); +define_pd_global(bool, TieredCompilation, false); define_pd_global(intx, CompileThreshold, 10000); define_pd_global(intx, BackEdgeThreshold, 140000); diff --git a/hotspot/src/cpu/x86/vm/c2_globals_x86.hpp b/hotspot/src/cpu/x86/vm/c2_globals_x86.hpp index 5ad08b0f158..f63b8c46d58 100644 --- a/hotspot/src/cpu/x86/vm/c2_globals_x86.hpp +++ b/hotspot/src/cpu/x86/vm/c2_globals_x86.hpp @@ -44,7 +44,7 @@ define_pd_global(bool, ProfileInterpreter, false); #else define_pd_global(bool, ProfileInterpreter, true); #endif // CC_INTERP -define_pd_global(bool, TieredCompilation, trueInTiered); +define_pd_global(bool, TieredCompilation, false); define_pd_global(intx, CompileThreshold, 10000); define_pd_global(intx, BackEdgeThreshold, 100000); From 89b8658977324cd452469532b19a324e30531936 Mon Sep 17 00:00:00 2001 From: David Chase Date: Fri, 25 Jan 2013 16:09:14 -0800 Subject: [PATCH 105/210] 8006500: compiler/8004741/Test8004741.java fails intermediately Rewrote the test to be more reliable, add test for invalid size exception Reviewed-by: kvn --- .../test/compiler/8004741/Test8004741.java | 162 ++++++++++++++---- 1 file changed, 126 insertions(+), 36 deletions(-) diff --git a/hotspot/test/compiler/8004741/Test8004741.java b/hotspot/test/compiler/8004741/Test8004741.java index 95e63b9c0c1..baacc34763d 100644 --- a/hotspot/test/compiler/8004741/Test8004741.java +++ b/hotspot/test/compiler/8004741/Test8004741.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2013, 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 @@ -25,70 +25,160 @@ * @test Test8004741.java * @bug 8004741 * @summary Missing compiled exception handle table entry for multidimensional array allocation + * @run main/othervm -Xmx64m -Xbatch -XX:+IgnoreUnrecognizedVMOptions -XX:-TieredCompilation -XX:+StressCompiledExceptionHandlers -XX:+SafepointALot -XX:GuaranteedSafepointInterval=100 Test8004741 * @run main/othervm -Xmx64m -Xbatch -XX:+IgnoreUnrecognizedVMOptions -XX:-TieredCompilation -XX:+StressCompiledExceptionHandlers Test8004741 - * */ import java.util.*; public class Test8004741 extends Thread { + static int passed = 0; + + /** + * Loop forever allocating 2-d arrays. + * Catches and rethrows all exceptions; in the case of ThreadDeath, increments passed. + * Note that passed is incremented here because this is the exception handler with + * the smallest scope; we only want to declare success in the case where it is highly + * likely that the test condition + * (exception in 2-d array alloc interrupted by ThreadDeath) + * actually occurs. + */ static int[][] test(int a, int b) throws Exception { - int[][] ar = null; + int[][] ar; try { ar = new int[a][b]; - } catch (Error e) { - System.out.println("test got Error"); - passed = true; - throw(e); - } catch (Exception e) { - System.out.println("test got Exception"); + } catch (ThreadDeath e) { + System.out.println("test got ThreadDeath"); + passed++; throw(e); } return ar; } - static boolean passed = false; + /* Cookbook wait-notify to track progress of test thread. */ + Object progressLock = new Object(); + private static final int NOT_STARTED = 0; + private static final int RUNNING = 1; + private static final int STOPPING = 2; - public void run() { - System.out.println("test started"); - try { - while(true) { - test(2,20000); + int progressState = NOT_STARTED; + + void toState(int state) { + synchronized (progressLock) { + progressState = state; + progressLock.notify(); + } + } + + void waitFor(int state) { + synchronized (progressLock) { + while (progressState < state) { + try { + progressLock.wait(); + } catch (InterruptedException e) { + e.printStackTrace(); + System.out.println("unexpected InterruptedException"); + fail(); } - } catch (ThreadDeath e) { - System.out.println("test got ThreadDeath"); - passed = true; - } catch (Error e) { - e.printStackTrace(); - System.out.println("test got Error"); - } catch (Exception e) { - e.printStackTrace(); - System.out.println("test got Exception"); } + if (progressState > state) { + System.out.println("unexpected test state change, expected " + + state + " but saw " + progressState); + fail(); + } + } + } + + /** + * Loops running test until some sort of an exception or error, + * expects to see ThreadDeath. + */ + public void run() { + try { + // Print before state change, so that other thread is most likely + // to see this thread executing calls to test() in a loop. + System.out.println("thread running"); + toState(RUNNING); + while (true) { + // (2,2) (2,10) (2,100) were observed to tickle the bug; + test(2, 100); + } + } catch (ThreadDeath e) { + // nothing to say, passing was incremented by the test. + } catch (Throwable e) { + e.printStackTrace(); + System.out.println("unexpected Throwable " + e); + fail(); + } + toState(STOPPING); + } + + /** + * Runs a single trial of the test in a thread. + * No single trial is definitive, since the ThreadDeath + * exception might not land in the tested region of code. + */ + public static void threadTest() throws InterruptedException { + Test8004741 t = new Test8004741(); + t.start(); + t.waitFor(RUNNING); + Thread.sleep(100); + System.out.println("stopping thread"); + t.stop(); + t.waitFor(STOPPING); + t.join(); } public static void main(String[] args) throws Exception { + // Warm up "test" + // t will never be started. for (int n = 0; n < 11000; n++) { - test(2, 20); + test(2, 100); } - // First test exception catch - Test8004741 t = new Test8004741(); + // Will this sleep help ensure that the compiler is run? + Thread.sleep(500); + passed = 0; - passed = false; - t.start(); - Thread.sleep(1000); - t.stop(); + try { + test(-1, 100); + System.out.println("Missing NegativeArraySizeException #1"); + fail(); + } catch ( java.lang.NegativeArraySizeException e ) { + System.out.println("Saw expected NegativeArraySizeException #1"); + } - Thread.sleep(5000); - t.join(); - if (passed) { + try { + test(100, -1); + fail(); + System.out.println("Missing NegativeArraySizeException #2"); + fail(); + } catch ( java.lang.NegativeArraySizeException e ) { + System.out.println("Saw expected NegativeArraySizeException #2"); + } + + /* Test repetitions. If the test succeeds-mostly, it succeeds, + * as long as it does not crash (the outcome if the exception range + * table entry for the array allocation is missing). + */ + int N = 12; + for (int n = 0; n < N; n++) { + threadTest(); + } + + if (passed > N/2) { + System.out.println("Saw " + passed + " out of " + N + " possible ThreadDeath hits"); System.out.println("PASSED"); } else { - System.out.println("FAILED"); - System.exit(97); + System.out.println("Too few ThreadDeath hits; expected at least " + N/2 + + " but saw only " + passed); + fail(); } } + static void fail() { + System.out.println("FAILED"); + System.exit(97); + } }; From 7d8f623180613a6473b64d6db146f1ac4b19cc20 Mon Sep 17 00:00:00 2001 From: Morris Meyer Date: Fri, 25 Jan 2013 16:50:33 -0800 Subject: [PATCH 106/210] 6518907: cleanup IA64 specific code in Hotspot Removed unused IA64 specific code Reviewed-by: twisti, kvn, dholmes --- .../agent/src/os/linux/LinuxDebuggerLocal.c | 12 +- hotspot/agent/src/os/linux/libproc.h | 8 - .../agent/src/os/win32/windbg/sawindbg.cpp | 92 +------- hotspot/src/os/linux/vm/os_linux.cpp | 12 +- hotspot/src/os/windows/vm/os_windows.cpp | 200 ++++++++++++------ .../vm/interpreter/bytecodeInterpreter.cpp | 4 +- .../src/share/vm/opto/generateOptoStub.cpp | 17 +- hotspot/src/share/vm/runtime/os.cpp | 30 ++- .../src/share/vm/runtime/sharedRuntime.cpp | 4 - hotspot/src/share/vm/runtime/synchronizer.cpp | 2 +- hotspot/src/share/vm/runtime/vframeArray.cpp | 2 - 11 files changed, 171 insertions(+), 212 deletions(-) diff --git a/hotspot/agent/src/os/linux/LinuxDebuggerLocal.c b/hotspot/agent/src/os/linux/LinuxDebuggerLocal.c index 5b49294e975..1d3c3bbd027 100644 --- a/hotspot/agent/src/os/linux/LinuxDebuggerLocal.c +++ b/hotspot/agent/src/os/linux/LinuxDebuggerLocal.c @@ -280,7 +280,7 @@ JNIEXPORT jbyteArray JNICALL Java_sun_jvm_hotspot_debugger_linux_LinuxDebuggerLo return (err == PS_OK)? array : 0; } -#if defined(i386) || defined(ia64) || defined(amd64) || defined(sparc) || defined(sparcv9) +#if defined(i386) || defined(amd64) || defined(sparc) || defined(sparcv9) JNIEXPORT jlongArray JNICALL Java_sun_jvm_hotspot_debugger_linux_LinuxDebuggerLocal_getThreadIntegerRegisterSet0 (JNIEnv *env, jobject this_obj, jint lwp_id) { @@ -299,9 +299,6 @@ JNIEXPORT jlongArray JNICALL Java_sun_jvm_hotspot_debugger_linux_LinuxDebuggerLo #ifdef i386 #define NPRGREG sun_jvm_hotspot_debugger_x86_X86ThreadContext_NPRGREG #endif -#ifdef ia64 -#define NPRGREG IA64_REG_COUNT -#endif #ifdef amd64 #define NPRGREG sun_jvm_hotspot_debugger_amd64_AMD64ThreadContext_NPRGREG #endif @@ -336,13 +333,6 @@ JNIEXPORT jlongArray JNICALL Java_sun_jvm_hotspot_debugger_linux_LinuxDebuggerLo #endif /* i386 */ -#if ia64 - regs = (*env)->GetLongArrayElements(env, array, &isCopy); - for (i = 0; i < NPRGREG; i++ ) { - regs[i] = 0xDEADDEAD; - } -#endif /* ia64 */ - #ifdef amd64 #define REG_INDEX(reg) sun_jvm_hotspot_debugger_amd64_AMD64ThreadContext_##reg diff --git a/hotspot/agent/src/os/linux/libproc.h b/hotspot/agent/src/os/linux/libproc.h index 5f583631c08..4cde0c19d76 100644 --- a/hotspot/agent/src/os/linux/libproc.h +++ b/hotspot/agent/src/os/linux/libproc.h @@ -79,14 +79,6 @@ combination of ptrace and /proc calls. *************************************************************************************/ -#ifdef ia64 -struct user_regs_struct { -/* copied from user.h which doesn't define this in a struct */ - -#define IA64_REG_COUNT (EF_SIZE/8+32) /* integer and fp regs */ -unsigned long regs[IA64_REG_COUNT]; /* integer and fp regs */ -}; -#endif #if defined(sparc) || defined(sparcv9) #define user_regs_struct pt_regs diff --git a/hotspot/agent/src/os/win32/windbg/sawindbg.cpp b/hotspot/agent/src/os/win32/windbg/sawindbg.cpp index c0a1e66965e..2ee4a2a02f1 100644 --- a/hotspot/agent/src/os/win32/windbg/sawindbg.cpp +++ b/hotspot/agent/src/os/win32/windbg/sawindbg.cpp @@ -27,10 +27,7 @@ #include "sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal.h" -#ifdef _M_IA64 - #include "sun_jvm_hotspot_debugger_ia64_IA64ThreadContext.h" - #define NPRGREG sun_jvm_hotspot_debugger_ia64_IA64ThreadContext_NPRGREG -#elif _M_IX86 +#ifdef _M_IX86 #include "sun_jvm_hotspot_debugger_x86_X86ThreadContext.h" #define NPRGREG sun_jvm_hotspot_debugger_x86_X86ThreadContext_NPRGREG #elif _M_AMD64 @@ -491,92 +488,7 @@ static bool addThreads(JNIEnv* env, jobject obj) { memset(&context, 0, sizeof(CONTEXT)); #undef REG_INDEX -#ifdef _M_IA64 - #define REG_INDEX(x) sun_jvm_hotspot_debugger_ia64_IA64ThreadContext_##x - - context.ContextFlags = CONTEXT_FULL | CONTEXT_DEBUG; - ptrIDebugAdvanced->GetThreadContext(&context, sizeof(CONTEXT)); - - ptrRegs[REG_INDEX(GR0)] = 0; // always 0 - ptrRegs[REG_INDEX(GR1)] = context.IntGp; // r1 - ptrRegs[REG_INDEX(GR2)] = context.IntT0; // r2-r3 - ptrRegs[REG_INDEX(GR3)] = context.IntT1; - ptrRegs[REG_INDEX(GR4)] = context.IntS0; // r4-r7 - ptrRegs[REG_INDEX(GR5)] = context.IntS1; - ptrRegs[REG_INDEX(GR6)] = context.IntS2; - ptrRegs[REG_INDEX(GR7)] = context.IntS3; - ptrRegs[REG_INDEX(GR8)] = context.IntV0; // r8 - ptrRegs[REG_INDEX(GR9)] = context.IntT2; // r9-r11 - ptrRegs[REG_INDEX(GR10)] = context.IntT3; - ptrRegs[REG_INDEX(GR11)] = context.IntT4; - ptrRegs[REG_INDEX(GR12)] = context.IntSp; // r12 stack pointer - ptrRegs[REG_INDEX(GR13)] = context.IntTeb; // r13 teb - ptrRegs[REG_INDEX(GR14)] = context.IntT5; // r14-r31 - ptrRegs[REG_INDEX(GR15)] = context.IntT6; - ptrRegs[REG_INDEX(GR16)] = context.IntT7; - ptrRegs[REG_INDEX(GR17)] = context.IntT8; - ptrRegs[REG_INDEX(GR18)] = context.IntT9; - ptrRegs[REG_INDEX(GR19)] = context.IntT10; - ptrRegs[REG_INDEX(GR20)] = context.IntT11; - ptrRegs[REG_INDEX(GR21)] = context.IntT12; - ptrRegs[REG_INDEX(GR22)] = context.IntT13; - ptrRegs[REG_INDEX(GR23)] = context.IntT14; - ptrRegs[REG_INDEX(GR24)] = context.IntT15; - ptrRegs[REG_INDEX(GR25)] = context.IntT16; - ptrRegs[REG_INDEX(GR26)] = context.IntT17; - ptrRegs[REG_INDEX(GR27)] = context.IntT18; - ptrRegs[REG_INDEX(GR28)] = context.IntT19; - ptrRegs[REG_INDEX(GR29)] = context.IntT20; - ptrRegs[REG_INDEX(GR30)] = context.IntT21; - ptrRegs[REG_INDEX(GR31)] = context.IntT22; - - ptrRegs[REG_INDEX(INT_NATS)] = context.IntNats; - ptrRegs[REG_INDEX(PREDS)] = context.Preds; - - ptrRegs[REG_INDEX(BR_RP)] = context.BrRp; - ptrRegs[REG_INDEX(BR1)] = context.BrS0; // b1-b5 - ptrRegs[REG_INDEX(BR2)] = context.BrS1; - ptrRegs[REG_INDEX(BR3)] = context.BrS2; - ptrRegs[REG_INDEX(BR4)] = context.BrS3; - ptrRegs[REG_INDEX(BR5)] = context.BrS4; - ptrRegs[REG_INDEX(BR6)] = context.BrT0; // b6-b7 - ptrRegs[REG_INDEX(BR7)] = context.BrT1; - - ptrRegs[REG_INDEX(AP_UNAT)] = context.ApUNAT; - ptrRegs[REG_INDEX(AP_LC)] = context.ApLC; - ptrRegs[REG_INDEX(AP_EC)] = context.ApEC; - ptrRegs[REG_INDEX(AP_CCV)] = context.ApCCV; - ptrRegs[REG_INDEX(AP_DCR)] = context.ApDCR; - - ptrRegs[REG_INDEX(RS_PFS)] = context.RsPFS; - ptrRegs[REG_INDEX(RS_BSP)] = context.RsBSP; - ptrRegs[REG_INDEX(RS_BSPSTORE)] = context.RsBSPSTORE; - ptrRegs[REG_INDEX(RS_RSC)] = context.RsRSC; - ptrRegs[REG_INDEX(RS_RNAT)] = context.RsRNAT; - - ptrRegs[REG_INDEX(ST_IPSR)] = context.StIPSR; - ptrRegs[REG_INDEX(ST_IIP)] = context.StIIP; - ptrRegs[REG_INDEX(ST_IFS)] = context.StIFS; - - ptrRegs[REG_INDEX(DB_I0)] = context.DbI0; - ptrRegs[REG_INDEX(DB_I1)] = context.DbI1; - ptrRegs[REG_INDEX(DB_I2)] = context.DbI2; - ptrRegs[REG_INDEX(DB_I3)] = context.DbI3; - ptrRegs[REG_INDEX(DB_I4)] = context.DbI4; - ptrRegs[REG_INDEX(DB_I5)] = context.DbI5; - ptrRegs[REG_INDEX(DB_I6)] = context.DbI6; - ptrRegs[REG_INDEX(DB_I7)] = context.DbI7; - - ptrRegs[REG_INDEX(DB_D0)] = context.DbD0; - ptrRegs[REG_INDEX(DB_D1)] = context.DbD1; - ptrRegs[REG_INDEX(DB_D2)] = context.DbD2; - ptrRegs[REG_INDEX(DB_D3)] = context.DbD3; - ptrRegs[REG_INDEX(DB_D4)] = context.DbD4; - ptrRegs[REG_INDEX(DB_D5)] = context.DbD5; - ptrRegs[REG_INDEX(DB_D6)] = context.DbD6; - ptrRegs[REG_INDEX(DB_D7)] = context.DbD7; - -#elif _M_IX86 +#ifdef _M_IX86 #define REG_INDEX(x) sun_jvm_hotspot_debugger_x86_X86ThreadContext_##x context.ContextFlags = CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS; diff --git a/hotspot/src/os/linux/vm/os_linux.cpp b/hotspot/src/os/linux/vm/os_linux.cpp index 8ff3c786b8b..537b48cdbc9 100644 --- a/hotspot/src/os/linux/vm/os_linux.cpp +++ b/hotspot/src/os/linux/vm/os_linux.cpp @@ -1155,13 +1155,9 @@ void os::Linux::capture_initial_stack(size_t max_size) { // for initial thread if its stack size exceeds 6M. Cap it at 2M, // in case other parts in glibc still assumes 2M max stack size. // FIXME: alt signal stack is gone, maybe we can relax this constraint? -#ifndef IA64 - if (stack_size > 2 * K * K) stack_size = 2 * K * K; -#else // Problem still exists RH7.2 (IA64 anyway) but 2MB is a little small - if (stack_size > 4 * K * K) stack_size = 4 * K * K; -#endif - + if (stack_size > 2 * K * K IA64_ONLY(*2)) + stack_size = 2 * K * K IA64_ONLY(*2); // Try to figure out where the stack base (top) is. This is harder. // // When an application is started, glibc saves the initial stack pointer in @@ -4367,16 +4363,12 @@ int os::Linux::safe_cond_timedwait(pthread_cond_t *_cond, pthread_mutex_t *_mute if (is_NPTL()) { return pthread_cond_timedwait(_cond, _mutex, _abstime); } else { -#ifndef IA64 // 6292965: LinuxThreads pthread_cond_timedwait() resets FPU control // word back to default 64bit precision if condvar is signaled. Java // wants 53bit precision. Save and restore current value. int fpu = get_fpu_control_word(); -#endif // IA64 int status = pthread_cond_timedwait(_cond, _mutex, _abstime); -#ifndef IA64 set_fpu_control_word(fpu); -#endif // IA64 return status; } } diff --git a/hotspot/src/os/windows/vm/os_windows.cpp b/hotspot/src/os/windows/vm/os_windows.cpp index 98b3077d1fa..eb16478ab8b 100644 --- a/hotspot/src/os/windows/vm/os_windows.cpp +++ b/hotspot/src/os/windows/vm/os_windows.cpp @@ -349,6 +349,33 @@ address os::current_stack_base() { #ifdef _M_IA64 // IA64 has memory and register stacks + // + // This is the stack layout you get on NT/IA64 if you specify 1MB stack limit + // at thread creation (1MB backing store growing upwards, 1MB memory stack + // growing downwards, 2MB summed up) + // + // ... + // ------- top of stack (high address) ----- + // | + // | 1MB + // | Backing Store (Register Stack) + // | + // | / \ + // | | + // | | + // | | + // ------------------------ stack base ----- + // | 1MB + // | Memory Stack + // | + // | | + // | | + // | | + // | \ / + // | + // ----- bottom of stack (low address) ----- + // ... + stack_size = stack_size / 2; #endif return stack_bottom + stack_size; @@ -2005,17 +2032,34 @@ LONG Handle_Exception(struct _EXCEPTION_POINTERS* exceptionInfo, address handler JavaThread* thread = JavaThread::current(); // Save pc in thread #ifdef _M_IA64 - thread->set_saved_exception_pc((address)exceptionInfo->ContextRecord->StIIP); + // Do not blow up if no thread info available. + if (thread) { + // Saving PRECISE pc (with slot information) in thread. + uint64_t precise_pc = (uint64_t) exceptionInfo->ExceptionRecord->ExceptionAddress; + // Convert precise PC into "Unix" format + precise_pc = (precise_pc & 0xFFFFFFFFFFFFFFF0) | ((precise_pc & 0xF) >> 2); + thread->set_saved_exception_pc((address)precise_pc); + } // Set pc to handler exceptionInfo->ContextRecord->StIIP = (DWORD64)handler; + // Clear out psr.ri (= Restart Instruction) in order to continue + // at the beginning of the target bundle. + exceptionInfo->ContextRecord->StIPSR &= 0xFFFFF9FFFFFFFFFF; + assert(((DWORD64)handler & 0xF) == 0, "Target address must point to the beginning of a bundle!"); #elif _M_AMD64 - thread->set_saved_exception_pc((address)exceptionInfo->ContextRecord->Rip); + // Do not blow up if no thread info available. + if (thread) { + thread->set_saved_exception_pc((address)(DWORD_PTR)exceptionInfo->ContextRecord->Rip); + } // Set pc to handler exceptionInfo->ContextRecord->Rip = (DWORD64)handler; #else - thread->set_saved_exception_pc((address)exceptionInfo->ContextRecord->Eip); + // Do not blow up if no thread info available. + if (thread) { + thread->set_saved_exception_pc((address)(DWORD_PTR)exceptionInfo->ContextRecord->Eip); + } // Set pc to handler - exceptionInfo->ContextRecord->Eip = (LONG)handler; + exceptionInfo->ContextRecord->Eip = (DWORD)(DWORD_PTR)handler; #endif // Continue the execution @@ -2040,6 +2084,14 @@ extern "C" void events(); // included or copied here. #define EXCEPTION_INFO_EXEC_VIOLATION 0x08 +// Handle NAT Bit consumption on IA64. +#ifdef _M_IA64 +#define EXCEPTION_REG_NAT_CONSUMPTION STATUS_REG_NAT_CONSUMPTION +#endif + +// Windows Vista/2008 heap corruption check +#define EXCEPTION_HEAP_CORRUPTION 0xC0000374 + #define def_excpt(val) #val, val struct siglabel { @@ -2082,6 +2134,10 @@ struct siglabel exceptlabels[] = { def_excpt(EXCEPTION_GUARD_PAGE), def_excpt(EXCEPTION_INVALID_HANDLE), def_excpt(EXCEPTION_UNCAUGHT_CXX_EXCEPTION), + def_excpt(EXCEPTION_HEAP_CORRUPTION), +#ifdef _M_IA64 + def_excpt(EXCEPTION_REG_NAT_CONSUMPTION), +#endif NULL, 0 }; @@ -2206,7 +2262,14 @@ LONG WINAPI topLevelExceptionFilter(struct _EXCEPTION_POINTERS* exceptionInfo) { if (InterceptOSException) return EXCEPTION_CONTINUE_SEARCH; DWORD exception_code = exceptionInfo->ExceptionRecord->ExceptionCode; #ifdef _M_IA64 - address pc = (address) exceptionInfo->ContextRecord->StIIP; + // On Itanium, we need the "precise pc", which has the slot number coded + // into the least 4 bits: 0000=slot0, 0100=slot1, 1000=slot2 (Windows format). + address pc = (address) exceptionInfo->ExceptionRecord->ExceptionAddress; + // Convert the pc to "Unix format", which has the slot number coded + // into the least 2 bits: 0000=slot0, 0001=slot1, 0010=slot2 + // This is needed for IA64 because "relocation" / "implicit null check" / "poll instruction" + // information is saved in the Unix format. + address pc_unix_format = (address) ((((uint64_t)pc) & 0xFFFFFFFFFFFFFFF0) | ((((uint64_t)pc) & 0xF) >> 2)); #elif _M_AMD64 address pc = (address) exceptionInfo->ContextRecord->Rip; #else @@ -2321,29 +2384,40 @@ LONG WINAPI topLevelExceptionFilter(struct _EXCEPTION_POINTERS* exceptionInfo) { if (exception_code == EXCEPTION_STACK_OVERFLOW) { if (os::uses_stack_guard_pages()) { #ifdef _M_IA64 - // - // If it's a legal stack address continue, Windows will map it in. - // + // Use guard page for register stack. PEXCEPTION_RECORD exceptionRecord = exceptionInfo->ExceptionRecord; address addr = (address) exceptionRecord->ExceptionInformation[1]; - if (addr > thread->stack_yellow_zone_base() && addr < thread->stack_base() ) - return EXCEPTION_CONTINUE_EXECUTION; + // Check for a register stack overflow on Itanium + if (thread->addr_inside_register_stack_red_zone(addr)) { + // Fatal red zone violation happens if the Java program + // catches a StackOverflow error and does so much processing + // that it runs beyond the unprotected yellow guard zone. As + // a result, we are out of here. + fatal("ERROR: Unrecoverable stack overflow happened. JVM will exit."); + } else if(thread->addr_inside_register_stack(addr)) { + // Disable the yellow zone which sets the state that + // we've got a stack overflow problem. + if (thread->stack_yellow_zone_enabled()) { + thread->disable_stack_yellow_zone(); + } + // Give us some room to process the exception. + thread->disable_register_stack_guard(); + // Tracing with +Verbose. + if (Verbose) { + tty->print_cr("SOF Compiled Register Stack overflow at " INTPTR_FORMAT " (SIGSEGV)", pc); + tty->print_cr("Register Stack access at " INTPTR_FORMAT, addr); + tty->print_cr("Register Stack base " INTPTR_FORMAT, thread->register_stack_base()); + tty->print_cr("Register Stack [" INTPTR_FORMAT "," INTPTR_FORMAT "]", + thread->register_stack_base(), + thread->register_stack_base() + thread->stack_size()); + } - // The register save area is the same size as the memory stack - // and starts at the page just above the start of the memory stack. - // If we get a fault in this area, we've run out of register - // stack. If we are in java, try throwing a stack overflow exception. - if (addr > thread->stack_base() && - addr <= (thread->stack_base()+thread->stack_size()) ) { - char buf[256]; - jio_snprintf(buf, sizeof(buf), - "Register stack overflow, addr:%p, stack_base:%p\n", - addr, thread->stack_base() ); - tty->print_raw_cr(buf); - // If not in java code, return and hope for the best. - return in_java ? Handle_Exception(exceptionInfo, - SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::STACK_OVERFLOW)) - : EXCEPTION_CONTINUE_EXECUTION; + // Reguard the permanent register stack red zone just to be sure. + // We saw Windows silently disabling this without telling us. + thread->enable_register_stack_red_zone(); + + return Handle_Exception(exceptionInfo, + SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::STACK_OVERFLOW)); } #endif if (thread->stack_yellow_zone_enabled()) { @@ -2418,50 +2492,33 @@ LONG WINAPI topLevelExceptionFilter(struct _EXCEPTION_POINTERS* exceptionInfo) { { // Null pointer exception. #ifdef _M_IA64 - // We catch register stack overflows in compiled code by doing - // an explicit compare and executing a st8(G0, G0) if the - // BSP enters into our guard area. We test for the overflow - // condition and fall into the normal null pointer exception - // code if BSP hasn't overflowed. - if ( in_java ) { - if(thread->register_stack_overflow()) { - assert((address)exceptionInfo->ContextRecord->IntS3 == - thread->register_stack_limit(), - "GR7 doesn't contain register_stack_limit"); - // Disable the yellow zone which sets the state that - // we've got a stack overflow problem. - if (thread->stack_yellow_zone_enabled()) { - thread->disable_stack_yellow_zone(); + // Process implicit null checks in compiled code. Note: Implicit null checks + // can happen even if "ImplicitNullChecks" is disabled, e.g. in vtable stubs. + if (CodeCache::contains((void*) pc_unix_format) && !MacroAssembler::needs_explicit_null_check((intptr_t) addr)) { + CodeBlob *cb = CodeCache::find_blob_unsafe(pc_unix_format); + // Handle implicit null check in UEP method entry + if (cb && (cb->is_frame_complete_at(pc) || + (cb->is_nmethod() && ((nmethod *)cb)->inlinecache_check_contains(pc)))) { + if (Verbose) { + intptr_t *bundle_start = (intptr_t*) ((intptr_t) pc_unix_format & 0xFFFFFFFFFFFFFFF0); + tty->print_cr("trap: null_check at " INTPTR_FORMAT " (SIGSEGV)", pc_unix_format); + tty->print_cr(" to addr " INTPTR_FORMAT, addr); + tty->print_cr(" bundle is " INTPTR_FORMAT " (high), " INTPTR_FORMAT " (low)", + *(bundle_start + 1), *bundle_start); } - // Give us some room to process the exception - thread->disable_register_stack_guard(); - // Update GR7 with the new limit so we can continue running - // compiled code. - exceptionInfo->ContextRecord->IntS3 = - (ULONGLONG)thread->register_stack_limit(); return Handle_Exception(exceptionInfo, - SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::STACK_OVERFLOW)); - } else { - // - // Check for implicit null - // We only expect null pointers in the stubs (vtable) - // the rest are checked explicitly now. - // - if (((uintptr_t)addr) < os::vm_page_size() ) { - // an access to the first page of VM--assume it is a null pointer - address stub = SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::IMPLICIT_NULL); - if (stub != NULL) return Handle_Exception(exceptionInfo, stub); - } + SharedRuntime::continuation_for_implicit_exception(thread, pc_unix_format, SharedRuntime::IMPLICIT_NULL)); } - } // in_java + } - // IA64 doesn't use implicit null checking yet. So we shouldn't - // get here. - tty->print_raw_cr("Access violation, possible null pointer exception"); + // Implicit null checks were processed above. Hence, we should not reach + // here in the usual case => die! + if (Verbose) tty->print_raw_cr("Access violation, possible null pointer exception"); report_error(t, exception_code, pc, exceptionInfo->ExceptionRecord, exceptionInfo->ContextRecord); return EXCEPTION_CONTINUE_SEARCH; -#else /* !IA64 */ + +#else // !IA64 // Windows 98 reports faulting addresses incorrectly if (!MacroAssembler::needs_explicit_null_check((intptr_t)addr) || @@ -2493,7 +2550,24 @@ LONG WINAPI topLevelExceptionFilter(struct _EXCEPTION_POINTERS* exceptionInfo) { report_error(t, exception_code, pc, exceptionInfo->ExceptionRecord, exceptionInfo->ContextRecord); return EXCEPTION_CONTINUE_SEARCH; - } + } // /EXCEPTION_ACCESS_VIOLATION + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +#if defined _M_IA64 + else if ((exception_code == EXCEPTION_ILLEGAL_INSTRUCTION || + exception_code == EXCEPTION_ILLEGAL_INSTRUCTION_2)) { + M37 handle_wrong_method_break(0, NativeJump::HANDLE_WRONG_METHOD, PR0); + + // Compiled method patched to be non entrant? Following conditions must apply: + // 1. must be first instruction in bundle + // 2. must be a break instruction with appropriate code + if((((uint64_t) pc & 0x0F) == 0) && + (((IPF_Bundle*) pc)->get_slot0() == handle_wrong_method_break.bits())) { + return Handle_Exception(exceptionInfo, + (address)SharedRuntime::get_handle_wrong_method_stub()); + } + } // /EXCEPTION_ILLEGAL_INSTRUCTION +#endif + if (in_java) { switch (exception_code) { diff --git a/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp b/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp index 0d139fdf71c..55ef63ee9d0 100644 --- a/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp +++ b/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp @@ -3099,9 +3099,9 @@ BytecodeInterpreter::print() { tty->print_cr("&native_fresult: " INTPTR_FORMAT, (uintptr_t) &this->_native_fresult); tty->print_cr("native_lresult: " INTPTR_FORMAT, (uintptr_t) this->_native_lresult); #endif -#if defined(IA64) && !defined(ZERO) +#if !defined(ZERO) tty->print_cr("last_Java_fp: " INTPTR_FORMAT, (uintptr_t) this->_last_Java_fp); -#endif // IA64 && !ZERO +#endif // !ZERO tty->print_cr("self_link: " INTPTR_FORMAT, (uintptr_t) this->_self_link); } diff --git a/hotspot/src/share/vm/opto/generateOptoStub.cpp b/hotspot/src/share/vm/opto/generateOptoStub.cpp index 56fc759f2d2..c5ebd5ad524 100644 --- a/hotspot/src/share/vm/opto/generateOptoStub.cpp +++ b/hotspot/src/share/vm/opto/generateOptoStub.cpp @@ -88,12 +88,12 @@ void GraphKit::gen_stub(address C_function, thread, in_bytes(JavaThread::frame_anchor_offset()) + in_bytes(JavaFrameAnchor::last_Java_pc_offset())); -#if defined(SPARC) || defined(IA64) +#if defined(SPARC) Node* adr_flags = basic_plus_adr(top(), thread, in_bytes(JavaThread::frame_anchor_offset()) + in_bytes(JavaFrameAnchor::flags_offset())); -#endif /* defined(SPARC) || defined(IA64) */ +#endif /* defined(SPARC) */ // Drop in the last_Java_sp. last_Java_fp is not touched. @@ -102,10 +102,8 @@ void GraphKit::gen_stub(address C_function, // users will look at the other fields. // Node *adr_sp = basic_plus_adr(top(), thread, in_bytes(JavaThread::last_Java_sp_offset())); -#ifndef IA64 Node *last_sp = basic_plus_adr(top(), frameptr(), (intptr_t) STACK_BIAS); store_to_memory(NULL, adr_sp, last_sp, T_ADDRESS, NoAlias); -#endif // Set _thread_in_native // The order of stores into TLS is critical! Setting _thread_in_native MUST @@ -210,19 +208,12 @@ void GraphKit::gen_stub(address C_function, //----------------------------- // Clear last_Java_sp -#ifdef IA64 - if( os::is_MP() ) insert_mem_bar(Op_MemBarRelease); -#endif - store_to_memory(NULL, adr_sp, null(), T_ADDRESS, NoAlias); -#ifdef IA64 - if (os::is_MP() && UseMembar) insert_mem_bar(new MemBarVolatileNode()); -#endif // def IA64 // Clear last_Java_pc and (optionally)_flags store_to_memory(NULL, adr_last_Java_pc, null(), T_ADDRESS, NoAlias); -#if defined(SPARC) || defined(IA64) +#if defined(SPARC) store_to_memory(NULL, adr_flags, intcon(0), T_INT, NoAlias); -#endif /* defined(SPARC) || defined(IA64) */ +#endif /* defined(SPARC) */ #ifdef IA64 Node* adr_last_Java_fp = basic_plus_adr(top(), thread, in_bytes(JavaThread::last_Java_fp_offset())); if( os::is_MP() ) insert_mem_bar(Op_MemBarRelease); diff --git a/hotspot/src/share/vm/runtime/os.cpp b/hotspot/src/share/vm/runtime/os.cpp index 649ce4fcc5c..b4090680395 100644 --- a/hotspot/src/share/vm/runtime/os.cpp +++ b/hotspot/src/share/vm/runtime/os.cpp @@ -985,15 +985,28 @@ void os::print_location(outputStream* st, intptr_t x, bool verbose) { // if C stack is walkable beyond current frame. The check for fp() is not // necessary on Sparc, but it's harmless. bool os::is_first_C_frame(frame* fr) { -#ifdef IA64 - // In order to walk native frames on Itanium, we need to access the unwind - // table, which is inside ELF. We don't want to parse ELF after fatal error, - // so return true for IA64. If we need to support C stack walking on IA64, - // this function needs to be moved to CPU specific files, as fp() on IA64 - // is register stack, which grows towards higher memory address. +#if defined(IA64) && !defined(_WIN32) + // On IA64 we have to check if the callers bsp is still valid + // (i.e. within the register stack bounds). + // Notice: this only works for threads created by the VM and only if + // we walk the current stack!!! If we want to be able to walk + // arbitrary other threads, we'll have to somehow store the thread + // object in the frame. + Thread *thread = Thread::current(); + if ((address)fr->fp() <= + thread->register_stack_base() HPUX_ONLY(+ 0x0) LINUX_ONLY(+ 0x50)) { + // This check is a little hacky, because on Linux the first C + // frame's ('start_thread') register stack frame starts at + // "register_stack_base + 0x48" while on HPUX, the first C frame's + // ('__pthread_bound_body') register stack frame seems to really + // start at "register_stack_base". + return true; + } else { + return false; + } +#elif defined(IA64) && defined(_WIN32) return true; -#endif - +#else // Load up sp, fp, sender sp and sender fp, check for reasonable values. // Check usp first, because if that's bad the other accessors may fault // on some architectures. Ditto ufp second, etc. @@ -1023,6 +1036,7 @@ bool os::is_first_C_frame(frame* fr) { if (old_fp - ufp > 64 * K) return true; return false; +#endif } #ifdef ASSERT diff --git a/hotspot/src/share/vm/runtime/sharedRuntime.cpp b/hotspot/src/share/vm/runtime/sharedRuntime.cpp index 7d2b816fe63..53234bc7820 100644 --- a/hotspot/src/share/vm/runtime/sharedRuntime.cpp +++ b/hotspot/src/share/vm/runtime/sharedRuntime.cpp @@ -2816,10 +2816,6 @@ VMRegPair *SharedRuntime::find_callee_arguments(Symbol* sig, bool has_receiver, JRT_LEAF(intptr_t*, SharedRuntime::OSR_migration_begin( JavaThread *thread) ) -#ifdef IA64 - ShouldNotReachHere(); // NYI -#endif /* IA64 */ - // // This code is dependent on the memory layout of the interpreter local // array and the monitors. On all of our platforms the layout is identical diff --git a/hotspot/src/share/vm/runtime/synchronizer.cpp b/hotspot/src/share/vm/runtime/synchronizer.cpp index 667066e7f17..bdf416275dc 100644 --- a/hotspot/src/share/vm/runtime/synchronizer.cpp +++ b/hotspot/src/share/vm/runtime/synchronizer.cpp @@ -53,7 +53,7 @@ # include "os_bsd.inline.hpp" #endif -#if defined(__GNUC__) && !defined(IA64) +#if defined(__GNUC__) // Need to inhibit inlining for older versions of GCC to avoid build-time failures #define ATTR __attribute__((noinline)) #else diff --git a/hotspot/src/share/vm/runtime/vframeArray.cpp b/hotspot/src/share/vm/runtime/vframeArray.cpp index 2c9aa0f3adb..d00e9f00954 100644 --- a/hotspot/src/share/vm/runtime/vframeArray.cpp +++ b/hotspot/src/share/vm/runtime/vframeArray.cpp @@ -233,8 +233,6 @@ void vframeArrayElement::unpack_on_stack(int caller_actual_parameters, // Force early return from top frame after deoptimization #ifndef CC_INTERP pc = Interpreter::remove_activation_early_entry(state->earlyret_tos()); -#else - // TBD: Need to implement ForceEarlyReturn for CC_INTERP (ia64) #endif } else { // Possibly override the previous pc computation of the top (youngest) frame From b5148d30e2e132556aecdc3d07353274aca9af66 Mon Sep 17 00:00:00 2001 From: Vicente Romero Date: Sun, 27 Jan 2013 19:38:44 +0000 Subject: [PATCH 107/210] 8006944: javac, combo tests should print out the number of threads used Reviewed-by: mcimadamore --- .../lib/JavacTestingAbstractThreadedTest.java | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/langtools/test/tools/javac/lib/JavacTestingAbstractThreadedTest.java b/langtools/test/tools/javac/lib/JavacTestingAbstractThreadedTest.java index edb2aac3111..34029854351 100644 --- a/langtools/test/tools/javac/lib/JavacTestingAbstractThreadedTest.java +++ b/langtools/test/tools/javac/lib/JavacTestingAbstractThreadedTest.java @@ -41,14 +41,20 @@ import javax.tools.ToolProvider; * * If the property is not set the class will use a heuristic to determine the * maximum number of threads that can be fired to execute a given test. + * + * This code will have to be revisited if jprt starts using concurrency for + * for running jtreg tests. */ public abstract class JavacTestingAbstractThreadedTest { + protected static AtomicInteger numberOfThreads = new AtomicInteger(); + protected static int getThreadPoolSize() { Integer testConc = Integer.getInteger("test.concurrency"); if (testConc != null) return testConc; int cores = Runtime.getRuntime().availableProcessors(); - return Math.max(2, Math.min(8, cores / 2)); + numberOfThreads.set(Math.max(2, Math.min(8, cores / 2))); + return numberOfThreads.get(); } protected static void checkAfterExec() throws InterruptedException { @@ -82,11 +88,18 @@ public abstract class JavacTestingAbstractThreadedTest { } else if (printCheckCount) { outWriter.println("Total check executed: " + checkCount.get()); } + /* + * This output is for supporting debugging. It does not mean that a given + * test had executed that number of threads concurrently. The value printed + * here is the maximum possible amount. + */ closePrinters(); if (printAll) { System.out.println(errSWriter.toString()); System.out.println(outSWriter.toString()); } + System.out.println("Total number of threads in thread pool: " + + numberOfThreads.get()); } protected static void closePrinters() { From 2447f369f6765d8281c827b72c13acd0f98689b7 Mon Sep 17 00:00:00 2001 From: Jesper Wilhelmsson Date: Mon, 28 Jan 2013 15:41:45 +0100 Subject: [PATCH 108/210] 6348447: Specifying -XX:OldSize crashes 64-bit VMs Heap size will be set to allow for OldSize to fit. Also reviewed by vitalyd@gmail.com Reviewed-by: ehelin, jmasa --- .../src/share/vm/memory/collectorPolicy.cpp | 27 ++++++++++++++----- .../src/share/vm/memory/collectorPolicy.hpp | 4 +-- 2 files changed, 22 insertions(+), 9 deletions(-) diff --git a/hotspot/src/share/vm/memory/collectorPolicy.cpp b/hotspot/src/share/vm/memory/collectorPolicy.cpp index b13d9761120..9f83af62260 100644 --- a/hotspot/src/share/vm/memory/collectorPolicy.cpp +++ b/hotspot/src/share/vm/memory/collectorPolicy.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2013, 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 @@ -235,6 +235,18 @@ void TwoGenerationCollectorPolicy::initialize_flags() { if (NewSize + OldSize > MaxHeapSize) { MaxHeapSize = NewSize + OldSize; } + + if (FLAG_IS_CMDLINE(OldSize) && FLAG_IS_DEFAULT(NewSize)) { + // NewRatio will be used later to set the young generation size so we use + // it to calculate how big the heap should be based on the requested OldSize + // and NewRatio. + assert(NewRatio > 0, "NewRatio should have been set up earlier"); + size_t calculated_heapsize = (OldSize / NewRatio) * (NewRatio + 1); + + calculated_heapsize = align_size_up(calculated_heapsize, max_alignment()); + MaxHeapSize = calculated_heapsize; + InitialHeapSize = calculated_heapsize; + } MaxHeapSize = align_size_up(MaxHeapSize, max_alignment()); always_do_update_barrier = UseConcMarkSweepGC; @@ -384,14 +396,15 @@ void GenCollectorPolicy::initialize_size_info() { // keeping it simple also seems a worthwhile goal. bool TwoGenerationCollectorPolicy::adjust_gen0_sizes(size_t* gen0_size_ptr, size_t* gen1_size_ptr, - size_t heap_size, - size_t min_gen0_size) { + const size_t heap_size, + const size_t min_gen1_size) { bool result = false; + if ((*gen1_size_ptr + *gen0_size_ptr) > heap_size) { - if (((*gen0_size_ptr + OldSize) > heap_size) && - (heap_size - min_gen0_size) >= min_alignment()) { - // Adjust gen0 down to accomodate OldSize - *gen0_size_ptr = heap_size - min_gen0_size; + if ((heap_size < (*gen0_size_ptr + min_gen1_size)) && + (heap_size >= min_gen1_size + min_alignment())) { + // Adjust gen0 down to accommodate min_gen1_size + *gen0_size_ptr = heap_size - min_gen1_size; *gen0_size_ptr = MAX2((uintx)align_size_down(*gen0_size_ptr, min_alignment()), min_alignment()); diff --git a/hotspot/src/share/vm/memory/collectorPolicy.hpp b/hotspot/src/share/vm/memory/collectorPolicy.hpp index a079f71b95b..6403f5e3bb7 100644 --- a/hotspot/src/share/vm/memory/collectorPolicy.hpp +++ b/hotspot/src/share/vm/memory/collectorPolicy.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2013, 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 @@ -321,7 +321,7 @@ class TwoGenerationCollectorPolicy : public GenCollectorPolicy { // Returns true is gen0 sizes were adjusted bool adjust_gen0_sizes(size_t* gen0_size_ptr, size_t* gen1_size_ptr, - size_t heap_size, size_t min_gen1_size); + const size_t heap_size, const size_t min_gen1_size); }; class MarkSweepPolicy : public TwoGenerationCollectorPolicy { From cb255a0269e7fa78d5ba4d98f8512596f2d8b3b7 Mon Sep 17 00:00:00 2001 From: Bharadwaj Yadavelli Date: Mon, 28 Jan 2013 10:55:30 -0500 Subject: [PATCH 109/210] 8004967: Default method cause VerifyError: Illegal use of nonvirtual Recognize VM generated method in old verifier Reviewed-by: acorn, coleenp --- hotspot/make/bsd/makefiles/mapfile-vers-debug | 1 + hotspot/make/bsd/makefiles/mapfile-vers-product | 1 + hotspot/make/linux/makefiles/mapfile-vers-debug | 1 + hotspot/make/linux/makefiles/mapfile-vers-product | 1 + hotspot/make/solaris/makefiles/mapfile-vers | 1 + hotspot/src/share/vm/prims/jvm.cpp | 9 +++++++++ hotspot/src/share/vm/prims/jvm.h | 7 +++++++ 7 files changed, 21 insertions(+) diff --git a/hotspot/make/bsd/makefiles/mapfile-vers-debug b/hotspot/make/bsd/makefiles/mapfile-vers-debug index ef827302c54..24144fe9b70 100644 --- a/hotspot/make/bsd/makefiles/mapfile-vers-debug +++ b/hotspot/make/bsd/makefiles/mapfile-vers-debug @@ -188,6 +188,7 @@ SUNWprivate_1.1 { JVM_IsSilentCompiler; JVM_IsSupportedJNIVersion; JVM_IsThreadAlive; + JVM_IsVMGeneratedMethodIx; JVM_LatestUserDefinedLoader; JVM_Listen; JVM_LoadClass0; diff --git a/hotspot/make/bsd/makefiles/mapfile-vers-product b/hotspot/make/bsd/makefiles/mapfile-vers-product index 0d2b04ca774..c165c16e2d8 100644 --- a/hotspot/make/bsd/makefiles/mapfile-vers-product +++ b/hotspot/make/bsd/makefiles/mapfile-vers-product @@ -188,6 +188,7 @@ SUNWprivate_1.1 { JVM_IsSilentCompiler; JVM_IsSupportedJNIVersion; JVM_IsThreadAlive; + JVM_IsVMGeneratedMethodIx; JVM_LatestUserDefinedLoader; JVM_Listen; JVM_LoadClass0; diff --git a/hotspot/make/linux/makefiles/mapfile-vers-debug b/hotspot/make/linux/makefiles/mapfile-vers-debug index ae4e2f9bcc3..27238f5720a 100644 --- a/hotspot/make/linux/makefiles/mapfile-vers-debug +++ b/hotspot/make/linux/makefiles/mapfile-vers-debug @@ -184,6 +184,7 @@ SUNWprivate_1.1 { JVM_IsSilentCompiler; JVM_IsSupportedJNIVersion; JVM_IsThreadAlive; + JVM_IsVMGeneratedMethodIx; JVM_LatestUserDefinedLoader; JVM_Listen; JVM_LoadClass0; diff --git a/hotspot/make/linux/makefiles/mapfile-vers-product b/hotspot/make/linux/makefiles/mapfile-vers-product index 9a3028d2a09..04531fa15aa 100644 --- a/hotspot/make/linux/makefiles/mapfile-vers-product +++ b/hotspot/make/linux/makefiles/mapfile-vers-product @@ -184,6 +184,7 @@ SUNWprivate_1.1 { JVM_IsSilentCompiler; JVM_IsSupportedJNIVersion; JVM_IsThreadAlive; + JVM_IsVMGeneratedMethodIx; JVM_LatestUserDefinedLoader; JVM_Listen; JVM_LoadClass0; diff --git a/hotspot/make/solaris/makefiles/mapfile-vers b/hotspot/make/solaris/makefiles/mapfile-vers index bf21253062e..d58807b046d 100644 --- a/hotspot/make/solaris/makefiles/mapfile-vers +++ b/hotspot/make/solaris/makefiles/mapfile-vers @@ -184,6 +184,7 @@ SUNWprivate_1.1 { JVM_IsSilentCompiler; JVM_IsSupportedJNIVersion; JVM_IsThreadAlive; + JVM_IsVMGeneratedMethodIx; JVM_LatestUserDefinedLoader; JVM_Listen; JVM_LoadClass0; diff --git a/hotspot/src/share/vm/prims/jvm.cpp b/hotspot/src/share/vm/prims/jvm.cpp index e1167924c49..7fffe0020c2 100644 --- a/hotspot/src/share/vm/prims/jvm.cpp +++ b/hotspot/src/share/vm/prims/jvm.cpp @@ -2302,6 +2302,15 @@ JVM_QUICK_ENTRY(jboolean, JVM_IsConstructorIx(JNIEnv *env, jclass cls, int metho JVM_END +JVM_QUICK_ENTRY(jboolean, JVM_IsVMGeneratedMethodIx(JNIEnv *env, jclass cls, int method_index)) + JVMWrapper("JVM_IsVMGeneratedMethodIx"); + ResourceMark rm(THREAD); + Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(cls)); + k = JvmtiThreadState::class_to_verify_considering_redefinition(k, thread); + Method* method = InstanceKlass::cast(k)->methods()->at(method_index); + return method->is_overpass(); +JVM_END + JVM_ENTRY(const char*, JVM_GetMethodIxNameUTF(JNIEnv *env, jclass cls, jint method_index)) JVMWrapper("JVM_GetMethodIxIxUTF"); Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(cls)); diff --git a/hotspot/src/share/vm/prims/jvm.h b/hotspot/src/share/vm/prims/jvm.h index c081f872afa..dea46d126eb 100644 --- a/hotspot/src/share/vm/prims/jvm.h +++ b/hotspot/src/share/vm/prims/jvm.h @@ -859,6 +859,13 @@ JVM_GetMethodIxMaxStack(JNIEnv *env, jclass cb, int index); JNIEXPORT jboolean JNICALL JVM_IsConstructorIx(JNIEnv *env, jclass cb, int index); +/* + * Is the given method generated by the VM. + * The method is identified by method_index. + */ +JNIEXPORT jboolean JNICALL +JVM_IsVMGeneratedMethodIx(JNIEnv *env, jclass cb, int index); + /* * Returns the name of a given method in UTF format. * The result remains valid until JVM_ReleaseUTF is called. From b29b4794613a2aca125c2a6e9f8ed1d0f01a4ce2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joel=20Borggr=C3=A9n-Franck?= Date: Tue, 29 Jan 2013 10:32:49 +0100 Subject: [PATCH 110/210] 8004698: Implement Core Reflection for Type Annotations Reviewed-by: darcy --- jdk/src/share/classes/java/lang/Class.java | 56 ++ jdk/src/share/classes/java/lang/System.java | 9 +- .../java/lang/reflect/AnnotatedArrayType.java | 43 ++ .../reflect/AnnotatedParameterizedType.java | 42 ++ .../java/lang/reflect/AnnotatedType.java | 44 ++ .../lang/reflect/AnnotatedTypeVariable.java | 43 ++ .../lang/reflect/AnnotatedWildcardType.java | 49 ++ .../java/lang/reflect/Constructor.java | 12 + .../classes/java/lang/reflect/Executable.java | 87 +++- .../classes/java/lang/reflect/Field.java | 21 +- .../classes/java/lang/reflect/Method.java | 12 + .../java/lang/reflect/ReflectAccess.java | 6 +- .../java/lang/reflect/TypeVariable.java | 14 +- .../classes/sun/misc/JavaLangAccess.java | 15 +- .../sun/reflect/LangReflectAccess.java | 5 +- .../sun/reflect/ReflectionFactory.java | 9 +- .../annotation/AnnotatedTypeFactory.java | 320 ++++++++++++ .../reflect/annotation/AnnotationParser.java | 4 +- .../reflect/annotation/TypeAnnotation.java | 227 ++++++++ .../annotation/TypeAnnotationParser.java | 491 ++++++++++++++++++ .../reflectiveObjects/TypeVariableImpl.java | 67 ++- jdk/src/share/javavm/export/jvm.h | 6 + jdk/src/share/native/java/lang/Class.c | 5 +- .../annotation/TypeAnnotationReflection.java | 428 +++++++++++++++ .../lang/annotation/TypeParamAnnotation.java | 120 +++++ 25 files changed, 2106 insertions(+), 29 deletions(-) create mode 100644 jdk/src/share/classes/java/lang/reflect/AnnotatedArrayType.java create mode 100644 jdk/src/share/classes/java/lang/reflect/AnnotatedParameterizedType.java create mode 100644 jdk/src/share/classes/java/lang/reflect/AnnotatedType.java create mode 100644 jdk/src/share/classes/java/lang/reflect/AnnotatedTypeVariable.java create mode 100644 jdk/src/share/classes/java/lang/reflect/AnnotatedWildcardType.java create mode 100644 jdk/src/share/classes/sun/reflect/annotation/AnnotatedTypeFactory.java create mode 100644 jdk/src/share/classes/sun/reflect/annotation/TypeAnnotation.java create mode 100644 jdk/src/share/classes/sun/reflect/annotation/TypeAnnotationParser.java create mode 100644 jdk/test/java/lang/annotation/TypeAnnotationReflection.java create mode 100644 jdk/test/java/lang/annotation/TypeParamAnnotation.java diff --git a/jdk/src/share/classes/java/lang/Class.java b/jdk/src/share/classes/java/lang/Class.java index 094f0cf26d6..87f78530899 100644 --- a/jdk/src/share/classes/java/lang/Class.java +++ b/jdk/src/share/classes/java/lang/Class.java @@ -29,12 +29,14 @@ import java.lang.reflect.Array; import java.lang.reflect.GenericArrayType; import java.lang.reflect.Member; import java.lang.reflect.Field; +import java.lang.reflect.Executable; import java.lang.reflect.Method; import java.lang.reflect.Constructor; import java.lang.reflect.Modifier; import java.lang.reflect.Type; import java.lang.reflect.TypeVariable; import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.AnnotatedType; import java.lang.ref.SoftReference; import java.io.InputStream; import java.io.ObjectStreamField; @@ -2325,6 +2327,11 @@ public final // Annotations handling private native byte[] getRawAnnotations(); + // Since 1.8 + native byte[] getRawTypeAnnotations(); + static byte[] getExecutableTypeAnnotationBytes(Executable ex) { + return getReflectionFactory().getExecutableTypeAnnotationBytes(ex); + } native ConstantPool getConstantPool(); @@ -3196,4 +3203,53 @@ public final * Maintained by the ClassValue class. */ transient ClassValue.ClassValueMap classValueMap; + + /** + * Returns an AnnotatedType object that represents the use of a type to specify + * the superclass of the entity represented by this Class. (The use of type + * Foo to specify the superclass in '... extends Foo' is distinct from the + * declaration of type Foo.) + * + * If this Class represents a class type whose declaration does not explicitly + * indicate an annotated superclass, the return value is null. + * + * If this Class represents either the Object class, an interface type, an + * array type, a primitive type, or void, the return value is null. + * + * @since 1.8 + */ + public AnnotatedType getAnnotatedSuperclass() { + return TypeAnnotationParser.buildAnnotatedSuperclass(getRawTypeAnnotations(), getConstantPool(), this); +} + + /** + * Returns an array of AnnotatedType objects that represent the use of types to + * specify superinterfaces of the entity represented by this Class. (The use + * of type Foo to specify a superinterface in '... implements Foo' is + * distinct from the declaration of type Foo.) + * + * If this Class represents a class, the return value is an array + * containing objects representing the uses of interface types to specify + * interfaces implemented by the class. The order of the objects in the + * array corresponds to the order of the interface types used in the + * 'implements' clause of the declaration of this Class. + * + * If this Class represents an interface, the return value is an array + * containing objects representing the uses of interface types to specify + * interfaces directly extended by the interface. The order of the objects in + * the array corresponds to the order of the interface types used in the + * 'extends' clause of the declaration of this Class. + * + * If this Class represents a class or interface whose declaration does not + * explicitly indicate any annotated superinterfaces, the return value is an + * array of length 0. + * + * If this Class represents either the Object class, an array type, a + * primitive type, or void, the return value is an array of length 0. + * + * @since 1.8 + */ + public AnnotatedType[] getAnnotatedInterfaces() { + return TypeAnnotationParser.buildAnnotatedInterfaces(getRawTypeAnnotations(), getConstantPool(), this); + } } diff --git a/jdk/src/share/classes/java/lang/System.java b/jdk/src/share/classes/java/lang/System.java index a6206e60391..d901e992b9a 100644 --- a/jdk/src/share/classes/java/lang/System.java +++ b/jdk/src/share/classes/java/lang/System.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1994, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1994, 2013, 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 @@ -26,6 +26,7 @@ package java.lang; import java.io.*; import java.lang.annotation.Annotation; +import java.lang.reflect.Executable; import java.util.Properties; import java.util.PropertyPermission; import java.util.StringTokenizer; @@ -1199,6 +1200,12 @@ public final class System { public A getDirectDeclaredAnnotation(Class klass, Class anno) { return klass.getDirectDeclaredAnnotation(anno); } + public byte[] getRawClassTypeAnnotations(Class klass) { + return klass.getRawTypeAnnotations(); + } + public byte[] getRawExecutableTypeAnnotations(Executable executable) { + return Class.getExecutableTypeAnnotationBytes(executable); + } public > E[] getEnumConstantsShared(Class klass) { return klass.getEnumConstantsShared(); diff --git a/jdk/src/share/classes/java/lang/reflect/AnnotatedArrayType.java b/jdk/src/share/classes/java/lang/reflect/AnnotatedArrayType.java new file mode 100644 index 00000000000..e84a3360fdd --- /dev/null +++ b/jdk/src/share/classes/java/lang/reflect/AnnotatedArrayType.java @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2012, 2013, 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. + */ + +package java.lang.reflect; + + +/** + * AnnotatedArrayType represents the use of an array type, whose component + * type may itself represent the annotated use of a type. + * + * @since 1.8 + */ +public interface AnnotatedArrayType extends AnnotatedType { + + /** + * Returns the annotated generic component type of this array type. + * + * @return the annotated generic component type of this array type + */ + AnnotatedType getAnnotatedGenericComponentType(); +} diff --git a/jdk/src/share/classes/java/lang/reflect/AnnotatedParameterizedType.java b/jdk/src/share/classes/java/lang/reflect/AnnotatedParameterizedType.java new file mode 100644 index 00000000000..4fa089e318c --- /dev/null +++ b/jdk/src/share/classes/java/lang/reflect/AnnotatedParameterizedType.java @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2012, 2013, 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. + */ + +package java.lang.reflect; + +/** + * AnnotatedParameterizedType represents the use of a parameterized type, + * whose type arguments may themselves represent annotated uses of types. + * + * @since 1.8 + */ +public interface AnnotatedParameterizedType extends AnnotatedType { + + /** + * Returns the annotated actual type arguments of this parameterized type. + * + * @return the annotated actual type arguments of this parameterized type + */ + AnnotatedType[] getAnnotatedActualTypeArguments(); +} diff --git a/jdk/src/share/classes/java/lang/reflect/AnnotatedType.java b/jdk/src/share/classes/java/lang/reflect/AnnotatedType.java new file mode 100644 index 00000000000..d1ee79f14f4 --- /dev/null +++ b/jdk/src/share/classes/java/lang/reflect/AnnotatedType.java @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2012, 2013, 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. + */ + +package java.lang.reflect; + +/** + * AnnotatedType represents the annotated use of a type in the program + * currently running in this VM. The use may be of any type in the Java + * programming language, including an array type, a parameterized type, a type + * variable, or a wildcard type. + * + * @since 1.8 + */ +public interface AnnotatedType extends AnnotatedElement { + + /** + * Returns the underlying type that this annotated type represents. + * + * @return the type this annotated type represents + */ + public Type getType(); +} diff --git a/jdk/src/share/classes/java/lang/reflect/AnnotatedTypeVariable.java b/jdk/src/share/classes/java/lang/reflect/AnnotatedTypeVariable.java new file mode 100644 index 00000000000..3580a14442f --- /dev/null +++ b/jdk/src/share/classes/java/lang/reflect/AnnotatedTypeVariable.java @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2012, 2013, 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. + */ + +package java.lang.reflect; + +/** + * AnnotatedTypeVariable represents the use of a type variable, whose + * declaration may have bounds which themselves represent annotated uses of + * types. + * + * @since 1.8 + */ +public interface AnnotatedTypeVariable extends AnnotatedType { + + /** + * Returns the annotated bounds of this type variable. + * + * @return the annotated bounds of this type variable + */ + AnnotatedType[] getAnnotatedBounds(); +} diff --git a/jdk/src/share/classes/java/lang/reflect/AnnotatedWildcardType.java b/jdk/src/share/classes/java/lang/reflect/AnnotatedWildcardType.java new file mode 100644 index 00000000000..c357eb9d0bc --- /dev/null +++ b/jdk/src/share/classes/java/lang/reflect/AnnotatedWildcardType.java @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2012, 2013, 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. + */ + +package java.lang.reflect; + +/** + * AnnotatedWildcardType represents the use of a wildcard type argument, whose + * upper or lower bounds may themselves represent annotated uses of types. + * + * @since 1.8 + */ +public interface AnnotatedWildcardType extends AnnotatedType { + + /** + * Returns the annotated lower bounds of this wildcard type. + * + * @return the annotated lower bounds of this wildcard type + */ + AnnotatedType[] getAnnotatedLowerBounds(); + + /** + * Returns the annotated upper bounds of this wildcard type. + * + * @return the annotated upper bounds of this wildcard type + */ + AnnotatedType[] getAnnotatedUpperBounds(); +} diff --git a/jdk/src/share/classes/java/lang/reflect/Constructor.java b/jdk/src/share/classes/java/lang/reflect/Constructor.java index 1973e820950..bbfd1d5ab9d 100644 --- a/jdk/src/share/classes/java/lang/reflect/Constructor.java +++ b/jdk/src/share/classes/java/lang/reflect/Constructor.java @@ -154,6 +154,10 @@ public final class Constructor extends Executable { byte[] getAnnotationBytes() { return annotations; } + @Override + byte[] getTypeAnnotationBytes() { + return typeAnnotations; + } /** * {@inheritDoc} @@ -523,4 +527,12 @@ public final class Constructor extends Executable { } } } + + /** + * {@inheritDoc} + * @since 1.8 + */ + public AnnotatedType getAnnotatedReturnType() { + return getAnnotatedReturnType0(getDeclaringClass()); + } } diff --git a/jdk/src/share/classes/java/lang/reflect/Executable.java b/jdk/src/share/classes/java/lang/reflect/Executable.java index f2befd2dcdd..b9ed7310a4d 100644 --- a/jdk/src/share/classes/java/lang/reflect/Executable.java +++ b/jdk/src/share/classes/java/lang/reflect/Executable.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2013, 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 @@ -31,6 +31,8 @@ import java.util.Map; import java.util.Objects; import sun.reflect.annotation.AnnotationParser; import sun.reflect.annotation.AnnotationSupport; +import sun.reflect.annotation.TypeAnnotationParser; +import sun.reflect.annotation.TypeAnnotation; import sun.reflect.generics.repository.ConstructorRepository; /** @@ -50,6 +52,7 @@ public abstract class Executable extends AccessibleObject * Accessor method to allow code sharing */ abstract byte[] getAnnotationBytes(); + abstract byte[] getTypeAnnotationBytes(); /** * Does the Executable have generic information. @@ -470,4 +473,86 @@ public abstract class Executable extends AccessibleObject return declaredAnnotations; } + + /* Helper for subclasses of Executable. + * + * Returns an AnnotatedType object that represents the use of a type to + * specify the return type of the method/constructor represented by this + * Executable. + * + * @since 1.8 + */ + AnnotatedType getAnnotatedReturnType0(Type returnType) { + return TypeAnnotationParser.buildAnnotatedType(getTypeAnnotationBytes(), + sun.misc.SharedSecrets.getJavaLangAccess(). + getConstantPool(getDeclaringClass()), + this, + getDeclaringClass(), + returnType, + TypeAnnotation.TypeAnnotationTarget.METHOD_RETURN_TYPE); + } + + /** + * Returns an AnnotatedType object that represents the use of a type to + * specify the receiver type of the method/constructor represented by this + * Executable. The receiver type of a method/constructor is available only + * if the method/constructor declares a formal parameter called 'this'. + * + * Returns null if this Executable represents a constructor or instance + * method that either declares no formal parameter called 'this', or + * declares a formal parameter called 'this' with no annotations on its + * type. + * + * Returns null if this Executable represents a static method. + * + * @since 1.8 + */ + public AnnotatedType getAnnotatedReceiverType() { + return TypeAnnotationParser.buildAnnotatedType(getTypeAnnotationBytes(), + sun.misc.SharedSecrets.getJavaLangAccess(). + getConstantPool(getDeclaringClass()), + this, + getDeclaringClass(), + getDeclaringClass(), + TypeAnnotation.TypeAnnotationTarget.METHOD_RECEIVER_TYPE); + } + + /** + * Returns an array of AnnotatedType objects that represent the use of + * types to specify formal parameter types of the method/constructor + * represented by this Executable. The order of the objects in the array + * corresponds to the order of the formal parameter types in the + * declaration of the method/constructor. + * + * Returns an array of length 0 if the method/constructor declares no + * parameters. + * + * @since 1.8 + */ + public AnnotatedType[] getAnnotatedParameterTypes() { + throw new UnsupportedOperationException("Not yet"); + } + + /** + * Returns an array of AnnotatedType objects that represent the use of + * types to specify the declared exceptions of the method/constructor + * represented by this Executable. The order of the objects in the array + * corresponds to the order of the exception types in the declaration of + * the method/constructor. + * + * Returns an array of length 0 if the method/constructor declares no + * exceptions. + * + * @since 1.8 + */ + public AnnotatedType[] getAnnotatedExceptionTypes() { + return TypeAnnotationParser.buildAnnotatedTypes(getTypeAnnotationBytes(), + sun.misc.SharedSecrets.getJavaLangAccess(). + getConstantPool(getDeclaringClass()), + this, + getDeclaringClass(), + getGenericExceptionTypes(), + TypeAnnotation.TypeAnnotationTarget.THROWS); + } + } diff --git a/jdk/src/share/classes/java/lang/reflect/Field.java b/jdk/src/share/classes/java/lang/reflect/Field.java index e5471459586..d2502efb4dd 100644 --- a/jdk/src/share/classes/java/lang/reflect/Field.java +++ b/jdk/src/share/classes/java/lang/reflect/Field.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2013, 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 @@ -36,7 +36,8 @@ import java.util.Map; import java.util.Objects; import sun.reflect.annotation.AnnotationParser; import sun.reflect.annotation.AnnotationSupport; - +import sun.reflect.annotation.TypeAnnotation; +import sun.reflect.annotation.TypeAnnotationParser; /** * A {@code Field} provides information about, and dynamic access to, a @@ -1053,4 +1054,20 @@ class Field extends AccessibleObject implements Member { } return declaredAnnotations; } + + /** + * Returns an AnnotatedType object that represents the use of a type to specify + * the declared type of the field represented by this Field. + * + * @since 1.8 + */ + public AnnotatedType getAnnotatedType() { + return TypeAnnotationParser.buildAnnotatedType(typeAnnotations, + sun.misc.SharedSecrets.getJavaLangAccess(). + getConstantPool(getDeclaringClass()), + this, + getDeclaringClass(), + getGenericType(), + TypeAnnotation.TypeAnnotationTarget.FIELD_TYPE); +} } diff --git a/jdk/src/share/classes/java/lang/reflect/Method.java b/jdk/src/share/classes/java/lang/reflect/Method.java index a7beb011400..1507c77194a 100644 --- a/jdk/src/share/classes/java/lang/reflect/Method.java +++ b/jdk/src/share/classes/java/lang/reflect/Method.java @@ -165,6 +165,10 @@ public final class Method extends Executable { byte[] getAnnotationBytes() { return annotations; } + @Override + byte[] getTypeAnnotationBytes() { + return typeAnnotations; + } /** * {@inheritDoc} @@ -621,6 +625,14 @@ public final class Method extends Executable { return sharedGetParameterAnnotations(parameterTypes, parameterAnnotations); } + /** + * {@inheritDoc} + * @since 1.8 + */ + public AnnotatedType getAnnotatedReturnType() { + return getAnnotatedReturnType0(getGenericReturnType()); + } + @Override void handleParameterNumberMismatch(int resultLength, int numParameters) { throw new AnnotationFormatError("Parameter annotations don't match number of parameters"); diff --git a/jdk/src/share/classes/java/lang/reflect/ReflectAccess.java b/jdk/src/share/classes/java/lang/reflect/ReflectAccess.java index 80311d240e6..c3ac1557b85 100644 --- a/jdk/src/share/classes/java/lang/reflect/ReflectAccess.java +++ b/jdk/src/share/classes/java/lang/reflect/ReflectAccess.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2013, 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 @@ -128,6 +128,10 @@ class ReflectAccess implements sun.reflect.LangReflectAccess { return c.getRawParameterAnnotations(); } + public byte[] getExecutableTypeAnnotationBytes(Executable ex) { + return ex.getTypeAnnotationBytes(); + } + // // Copying routines, needed to quickly fabricate new Field, // Method, and Constructor objects from templates diff --git a/jdk/src/share/classes/java/lang/reflect/TypeVariable.java b/jdk/src/share/classes/java/lang/reflect/TypeVariable.java index b0ff7880cda..42027e0041c 100644 --- a/jdk/src/share/classes/java/lang/reflect/TypeVariable.java +++ b/jdk/src/share/classes/java/lang/reflect/TypeVariable.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2013, 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 @@ -86,4 +86,16 @@ public interface TypeVariable extends Type, Annota * @return the name of this type variable, as it appears in the source code */ String getName(); + + /** + * Returns an array of AnnotatedType objects that represent the use of + * types to denote the upper bounds of the type parameter represented by + * this TypeVariable. The order of the objects in the array corresponds to + * the order of the bounds in the declaration of the type parameter. + * + * Returns an array of length 0 if the type parameter declares no bounds. + * + * @since 1.8 + */ + AnnotatedType[] getAnnotatedBounds(); } diff --git a/jdk/src/share/classes/sun/misc/JavaLangAccess.java b/jdk/src/share/classes/sun/misc/JavaLangAccess.java index 9506194c707..1624d67f4a9 100644 --- a/jdk/src/share/classes/sun/misc/JavaLangAccess.java +++ b/jdk/src/share/classes/sun/misc/JavaLangAccess.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2013, 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 @@ -26,6 +26,7 @@ package sun.misc; import java.lang.annotation.Annotation; +import java.lang.reflect.Executable; import sun.reflect.ConstantPool; import sun.reflect.annotation.AnnotationType; import sun.nio.ch.Interruptible; @@ -46,6 +47,18 @@ public interface JavaLangAccess { */ AnnotationType getAnnotationType(Class klass); + /** + * Get the array of bytes that is the class-file representation + * of this Class' type annotations. + */ + byte[] getRawClassTypeAnnotations(Class klass); + + /** + * Get the array of bytes that is the class-file representation + * of this Executable's type annotations. + */ + byte[] getRawExecutableTypeAnnotations(Executable executable); + /** * Returns the elements of an enum class or null if the * Class object does not represent an enum type; diff --git a/jdk/src/share/classes/sun/reflect/LangReflectAccess.java b/jdk/src/share/classes/sun/reflect/LangReflectAccess.java index fba1d318086..3c3b2757410 100644 --- a/jdk/src/share/classes/sun/reflect/LangReflectAccess.java +++ b/jdk/src/share/classes/sun/reflect/LangReflectAccess.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2004, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2013, 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 @@ -81,6 +81,9 @@ public interface LangReflectAccess { public void setConstructorAccessor(Constructor c, ConstructorAccessor accessor); + /** Gets the byte[] that encodes TypeAnnotations on an Executable. */ + public byte[] getExecutableTypeAnnotationBytes(Executable ex); + /** Gets the "slot" field from a Constructor (used for serialization) */ public int getConstructorSlot(Constructor c); diff --git a/jdk/src/share/classes/sun/reflect/ReflectionFactory.java b/jdk/src/share/classes/sun/reflect/ReflectionFactory.java index ea5323b8b9a..de97dfc7001 100644 --- a/jdk/src/share/classes/sun/reflect/ReflectionFactory.java +++ b/jdk/src/share/classes/sun/reflect/ReflectionFactory.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2013, 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 @@ -26,6 +26,7 @@ package sun.reflect; import java.lang.reflect.Field; +import java.lang.reflect.Executable; import java.lang.reflect.Method; import java.lang.reflect.Constructor; import java.lang.reflect.Modifier; @@ -314,6 +315,12 @@ public class ReflectionFactory { return langReflectAccess().copyConstructor(arg); } + /** Gets the byte[] that encodes TypeAnnotations on an executable. + */ + public byte[] getExecutableTypeAnnotationBytes(Executable ex) { + return langReflectAccess().getExecutableTypeAnnotationBytes(ex); + } + //-------------------------------------------------------------------------- // // Routines used by serialization diff --git a/jdk/src/share/classes/sun/reflect/annotation/AnnotatedTypeFactory.java b/jdk/src/share/classes/sun/reflect/annotation/AnnotatedTypeFactory.java new file mode 100644 index 00000000000..afb4c4865e7 --- /dev/null +++ b/jdk/src/share/classes/sun/reflect/annotation/AnnotatedTypeFactory.java @@ -0,0 +1,320 @@ +/* + * Copyright (c) 2013, 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. + */ + +package sun.reflect.annotation; + +import java.lang.annotation.*; +import java.lang.reflect.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +import static sun.reflect.annotation.TypeAnnotation.*; + +public class AnnotatedTypeFactory { + /** + * Create an AnnotatedType. + * + * @param type the type this AnnotatedType corresponds to + * @param currentLoc the location this AnnotatedType corresponds to + * @param actualTypeAnnos the type annotations this AnnotatedType has + * @param allOnSameTarget all type annotation on the same TypeAnnotationTarget + * as the AnnotatedType being built + * @param decl the declaration having the type use this AnnotatedType + * corresponds to + */ + public static AnnotatedType buildAnnotatedType(Type type, + LocationInfo currentLoc, + TypeAnnotation[] actualTypeAnnos, + TypeAnnotation[] allOnSameTarget, + AnnotatedElement decl) { + if (type == null) { + return EMPTY_ANNOTATED_TYPE; + } + if (isArray(type)) + return new AnnotatedArrayTypeImpl(type, + currentLoc, + actualTypeAnnos, + allOnSameTarget, + decl); + if (type instanceof Class) { + return new AnnotatedTypeBaseImpl(type, + addNesting(type, currentLoc), + actualTypeAnnos, + allOnSameTarget, + decl); + } else if (type instanceof TypeVariable) { + return new AnnotatedTypeVariableImpl((TypeVariable)type, + currentLoc, + actualTypeAnnos, + allOnSameTarget, + decl); + } else if (type instanceof ParameterizedType) { + return new AnnotatedParameterizedTypeImpl((ParameterizedType)type, + addNesting(type, currentLoc), + actualTypeAnnos, + allOnSameTarget, + decl); + } else if (type instanceof WildcardType) { + return new AnnotatedWildcardTypeImpl((WildcardType) type, + currentLoc, + actualTypeAnnos, + allOnSameTarget, + decl); + } + throw new AssertionError("Unknown instance of Type: " + type + "\nThis should not happen."); + } + + private static LocationInfo addNesting(Type type, LocationInfo addTo) { + if (isArray(type)) + return addTo; + if (type instanceof Class) { + Class clz = (Class)type; + if (clz.getEnclosingClass() == null) + return addTo; + return addNesting(clz.getEnclosingClass(), addTo.pushInner()); + } else if (type instanceof ParameterizedType) { + ParameterizedType t = (ParameterizedType)type; + if (t.getOwnerType() == null) + return addTo; + return addNesting(t.getOwnerType(), addTo.pushInner()); + } + return addTo; + } + + private static boolean isArray(Type t) { + if (t instanceof Class) { + Class c = (Class)t; + if (c.isArray()) + return true; + } else if (t instanceof GenericArrayType) { + return true; + } + return false; + } + + static final AnnotatedType EMPTY_ANNOTATED_TYPE = new AnnotatedTypeBaseImpl(null, LocationInfo.BASE_LOCATION, + new TypeAnnotation[0], new TypeAnnotation[0], null); + + private static class AnnotatedTypeBaseImpl implements AnnotatedType { + private final Type type; + private final AnnotatedElement decl; + private final LocationInfo location; + private final TypeAnnotation[] allOnSameTargetTypeAnnotations; + private final Map, Annotation> annotations; + + AnnotatedTypeBaseImpl(Type type, LocationInfo location, + TypeAnnotation[] actualTypeAnnotations, TypeAnnotation[] allOnSameTargetTypeAnnotations, + AnnotatedElement decl) { + this.type = type; + this.decl = decl; + this.location = location; + this.allOnSameTargetTypeAnnotations = allOnSameTargetTypeAnnotations; + this.annotations = TypeAnnotationParser.mapTypeAnnotations(location.filter(actualTypeAnnotations)); + } + + // AnnotatedElement + @Override + public final boolean isAnnotationPresent(Class annotation) { + return annotations.get(annotation) != null; + } + + @Override + public final Annotation[] getAnnotations() { + return getDeclaredAnnotations(); + } + + @Override + public final T getAnnotation(Class annotation) { + return getDeclaredAnnotation(annotation); + } + + @Override + public final T[] getAnnotations(Class annotation) { + return getDeclaredAnnotations(annotation); + } + + @Override + public Annotation[] getDeclaredAnnotations() { + return annotations.values().toArray(new Annotation[0]); + } + + @Override + @SuppressWarnings("unchecked") + public T getDeclaredAnnotation(Class annotation) { + return (T)annotations.get(annotation); + } + + @Override + public T[] getDeclaredAnnotations(Class annotation) { + return AnnotationSupport.getMultipleAnnotations(annotations, annotation); + } + + // AnnotatedType + @Override + public Type getType() { + return type; + } + + // Implementation details + LocationInfo getLocation() { + return location; + } + TypeAnnotation[] getTypeAnnotations() { + return allOnSameTargetTypeAnnotations; + } + AnnotatedElement getDecl() { + return decl; + } + } + + private static class AnnotatedArrayTypeImpl extends AnnotatedTypeBaseImpl implements AnnotatedArrayType { + AnnotatedArrayTypeImpl(Type type, LocationInfo location, + TypeAnnotation[] actualTypeAnnotations, TypeAnnotation[] allOnSameTargetTypeAnnotations, + AnnotatedElement decl) { + super(type, location, actualTypeAnnotations, allOnSameTargetTypeAnnotations, decl); + } + + @Override + public AnnotatedType getAnnotatedGenericComponentType() { + return AnnotatedTypeFactory.buildAnnotatedType(getComponentType(), + getLocation().pushArray(), + getTypeAnnotations(), + getTypeAnnotations(), + getDecl()); + } + + private Type getComponentType() { + Type t = getType(); + if (t instanceof Class) { + Class c = (Class)t; + return c.getComponentType(); + } + return ((GenericArrayType)t).getGenericComponentType(); + } + } + + private static class AnnotatedTypeVariableImpl extends AnnotatedTypeBaseImpl implements AnnotatedTypeVariable { + AnnotatedTypeVariableImpl(TypeVariable type, LocationInfo location, + TypeAnnotation[] actualTypeAnnotations, TypeAnnotation[] allOnSameTargetTypeAnnotations, + AnnotatedElement decl) { + super(type, location, actualTypeAnnotations, allOnSameTargetTypeAnnotations, decl); + } + + @Override + public AnnotatedType[] getAnnotatedBounds() { + return getTypeVariable().getAnnotatedBounds(); + } + + private TypeVariable getTypeVariable() { + return (TypeVariable)getType(); + } + } + + private static class AnnotatedParameterizedTypeImpl extends AnnotatedTypeBaseImpl implements AnnotatedParameterizedType { + AnnotatedParameterizedTypeImpl(ParameterizedType type, LocationInfo location, + TypeAnnotation[] actualTypeAnnotations, TypeAnnotation[] allOnSameTargetTypeAnnotations, + AnnotatedElement decl) { + super(type, location, actualTypeAnnotations, allOnSameTargetTypeAnnotations, decl); + } + + @Override + public AnnotatedType[] getAnnotatedActualTypeArguments() { + Type[] arguments = getParameterizedType().getActualTypeArguments(); + AnnotatedType[] res = new AnnotatedType[arguments.length]; + Arrays.fill(res, EMPTY_ANNOTATED_TYPE); + int initialCapacity = getTypeAnnotations().length; + for (int i = 0; i < res.length; i++) { + List l = new ArrayList<>(initialCapacity); + LocationInfo newLoc = getLocation().pushTypeArg((byte)i); + for (TypeAnnotation t : getTypeAnnotations()) + if (t.getLocationInfo().isSameLocationInfo(newLoc)) + l.add(t); + res[i] = buildAnnotatedType(arguments[i], + newLoc, + l.toArray(new TypeAnnotation[0]), + getTypeAnnotations(), + getDecl()); + } + return res; + } + + private ParameterizedType getParameterizedType() { + return (ParameterizedType)getType(); + } + } + + private static class AnnotatedWildcardTypeImpl extends AnnotatedTypeBaseImpl implements AnnotatedWildcardType { + private final boolean hasUpperBounds; + AnnotatedWildcardTypeImpl(WildcardType type, LocationInfo location, + TypeAnnotation[] actualTypeAnnotations, TypeAnnotation[] allOnSameTargetTypeAnnotations, + AnnotatedElement decl) { + super(type, location, actualTypeAnnotations, allOnSameTargetTypeAnnotations, decl); + hasUpperBounds = (type.getLowerBounds().length == 0); + } + + @Override + public AnnotatedType[] getAnnotatedUpperBounds() { + if (!hasUpperBounds()) + return new AnnotatedType[0]; + return getAnnotatedBounds(getWildcardType().getUpperBounds()); + } + + @Override + public AnnotatedType[] getAnnotatedLowerBounds() { + if (hasUpperBounds) + return new AnnotatedType[0]; + return getAnnotatedBounds(getWildcardType().getLowerBounds()); + } + + private AnnotatedType[] getAnnotatedBounds(Type[] bounds) { + AnnotatedType[] res = new AnnotatedType[bounds.length]; + Arrays.fill(res, EMPTY_ANNOTATED_TYPE); + LocationInfo newLoc = getLocation().pushWildcard(); + int initialCapacity = getTypeAnnotations().length; + for (int i = 0; i < res.length; i++) { + List l = new ArrayList<>(initialCapacity); + for (TypeAnnotation t : getTypeAnnotations()) + if (t.getLocationInfo().isSameLocationInfo(newLoc)) + l.add(t); + res[i] = buildAnnotatedType(bounds[i], + newLoc, + l.toArray(new TypeAnnotation[0]), + getTypeAnnotations(), + getDecl()); + } + return res; + } + + private WildcardType getWildcardType() { + return (WildcardType)getType(); + } + + private boolean hasUpperBounds() { + return hasUpperBounds; + } + } +} diff --git a/jdk/src/share/classes/sun/reflect/annotation/AnnotationParser.java b/jdk/src/share/classes/sun/reflect/annotation/AnnotationParser.java index 6f26ec368b7..a980a9126ef 100644 --- a/jdk/src/share/classes/sun/reflect/annotation/AnnotationParser.java +++ b/jdk/src/share/classes/sun/reflect/annotation/AnnotationParser.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2013, 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 @@ -188,7 +188,7 @@ public class AnnotationParser { * available at runtime */ @SuppressWarnings("unchecked") - private static Annotation parseAnnotation(ByteBuffer buf, + static Annotation parseAnnotation(ByteBuffer buf, ConstantPool constPool, Class container, boolean exceptionOnMissingAnnotationClass) { diff --git a/jdk/src/share/classes/sun/reflect/annotation/TypeAnnotation.java b/jdk/src/share/classes/sun/reflect/annotation/TypeAnnotation.java new file mode 100644 index 00000000000..c5399725e8b --- /dev/null +++ b/jdk/src/share/classes/sun/reflect/annotation/TypeAnnotation.java @@ -0,0 +1,227 @@ +/* + * Copyright (c) 2013, 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. + */ +package sun.reflect.annotation; + +import java.lang.annotation.Annotation; +import java.lang.annotation.AnnotationFormatError; +import java.lang.reflect.AnnotatedElement; +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; + +/** + * A TypeAnnotation contains all the information needed to transform type + * annotations on declarations in the class file to actual Annotations in + * AnnotatedType instances. + * + * TypeAnnotaions contain a base Annotation, location info (which lets you + * distinguish between '@A Inner.@B Outer' in for example nested types), + * target info and the declaration the TypeAnnotaiton was parsed from. + */ +public class TypeAnnotation { + private final TypeAnnotationTargetInfo targetInfo; + private final LocationInfo loc; + private final Annotation annotation; + private final AnnotatedElement baseDeclaration; + + public TypeAnnotation(TypeAnnotationTargetInfo targetInfo, + LocationInfo loc, + Annotation annotation, + AnnotatedElement baseDeclaration) { + this.targetInfo = targetInfo; + this.loc = loc; + this.annotation = annotation; + this.baseDeclaration = baseDeclaration; + } + + public TypeAnnotationTargetInfo getTargetInfo() { + return targetInfo; + } + public Annotation getAnnotation() { + return annotation; + } + public AnnotatedElement getBaseDeclaration() { + return baseDeclaration; + } + public LocationInfo getLocationInfo() { + return loc; + } + + public static List filter(TypeAnnotation[] typeAnnotations, + TypeAnnotationTarget predicate) { + ArrayList typeAnnos = new ArrayList<>(typeAnnotations.length); + for (TypeAnnotation t : typeAnnotations) + if (t.getTargetInfo().getTarget() == predicate) + typeAnnos.add(t); + typeAnnos.trimToSize(); + return typeAnnos; + } + + public static enum TypeAnnotationTarget { + CLASS_TYPE_PARAMETER, + METHOD_TYPE_PARAMETER, + CLASS_EXTENDS, + CLASS_IMPLEMENTS, + CLASS_PARAMETER_BOUND, + METHOD_PARAMETER_BOUND, + METHOD_RETURN_TYPE, + METHOD_RECEIVER_TYPE, + FIELD_TYPE, + THROWS; + } + public static class TypeAnnotationTargetInfo { + private final TypeAnnotationTarget target; + private final int count; + private final int secondaryIndex; + private static final int UNUSED_INDEX = -2; // this is not a valid index in the 308 spec + + public TypeAnnotationTargetInfo(TypeAnnotationTarget target) { + this(target, UNUSED_INDEX, UNUSED_INDEX); + } + + public TypeAnnotationTargetInfo(TypeAnnotationTarget target, + int count) { + this(target, count, UNUSED_INDEX); + } + + public TypeAnnotationTargetInfo(TypeAnnotationTarget target, + int count, + int secondaryIndex) { + this.target = target; + this.count = count; + this.secondaryIndex = secondaryIndex; + } + + public TypeAnnotationTarget getTarget() { + return target; + } + public int getCount() { + return count; + } + public int getSecondaryIndex() { + return secondaryIndex; + } + + @Override + public String toString() { + return "" + target + ": " + count + ", " + secondaryIndex; + } + } + + public static class LocationInfo { + private final int depth; + private final Location[] locations; + + private LocationInfo() { + this(0, new Location[0]); + } + private LocationInfo(int depth, Location[] locations) { + this.depth = depth; + this.locations = locations; + } + + public static final LocationInfo BASE_LOCATION = new LocationInfo(); + + public static LocationInfo parseLocationInfo(ByteBuffer buf) { + int depth = buf.get(); + if (depth == 0) + return BASE_LOCATION; + Location[] locations = new Location[depth]; + for (int i = 0; i < depth; i++) { + byte tag = buf.get(); + byte index = buf.get(); + if (!(tag == 0 || tag == 1 | tag == 2 || tag == 3)) + throw new AnnotationFormatError("Bad Location encoding in Type Annotation"); + if (tag != 3 && index != 0) + throw new AnnotationFormatError("Bad Location encoding in Type Annotation"); + locations[i] = new Location(tag, index); + } + return new LocationInfo(depth, locations); + } + + public LocationInfo pushArray() { + return pushLocation((byte)0, (byte)0); + } + + public LocationInfo pushInner() { + return pushLocation((byte)1, (byte)0); + } + + public LocationInfo pushWildcard() { + return pushLocation((byte) 2, (byte) 0); + } + + public LocationInfo pushTypeArg(byte index) { + return pushLocation((byte) 3, index); + } + + public LocationInfo pushLocation(byte tag, byte index) { + int newDepth = this.depth + 1; + Location[] res = new Location[newDepth]; + System.arraycopy(this.locations, 0, res, 0, depth); + res[newDepth - 1] = new Location(tag, index); + return new LocationInfo(newDepth, res); + } + + public TypeAnnotation[] filter(TypeAnnotation[] ta) { + ArrayList l = new ArrayList<>(ta.length); + for (TypeAnnotation t : ta) { + if (isSameLocationInfo(t.getLocationInfo())) + l.add(t); + } + return l.toArray(new TypeAnnotation[0]); + } + + boolean isSameLocationInfo(LocationInfo other) { + if (depth != other.depth) + return false; + for (int i = 0; i < depth; i++) + if (!locations[i].isSameLocation(other.locations[i])) + return false; + return true; + } + + public static class Location { + public final byte tag; + public final byte index; + + boolean isSameLocation(Location other) { + return tag == other.tag && index == other.index; + } + + public Location(byte tag, byte index) { + this.tag = tag; + this.index = index; + } + } + } + + @Override + public String toString() { + return annotation.toString() + " with Targetnfo: " + + targetInfo.toString() + " on base declaration: " + + baseDeclaration.toString(); + } +} diff --git a/jdk/src/share/classes/sun/reflect/annotation/TypeAnnotationParser.java b/jdk/src/share/classes/sun/reflect/annotation/TypeAnnotationParser.java new file mode 100644 index 00000000000..12abe28b4d5 --- /dev/null +++ b/jdk/src/share/classes/sun/reflect/annotation/TypeAnnotationParser.java @@ -0,0 +1,491 @@ +/* + * Copyright (c) 2013, 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. + */ + +package sun.reflect.annotation; + +import java.lang.annotation.*; +import java.lang.reflect.*; +import java.nio.ByteBuffer; +import java.nio.BufferUnderflowException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.Map; +import sun.misc.JavaLangAccess; +import sun.reflect.ConstantPool; +import static sun.reflect.annotation.TypeAnnotation.*; + +/** + * TypeAnnotationParser implements the logic needed to parse + * TypeAnnotations from an array of bytes. + */ +public class TypeAnnotationParser { + private static final TypeAnnotation[] EMPTY_TYPE_ANNOTATION_ARRAY = new TypeAnnotation[0]; + + /** + * Build an AnnotatedType from the parameters supplied. + * + * This method and {@code buildAnnotatedTypes} are probably + * the entry points you are looking for. + * + * @param rawAnnotations the byte[] encoding of all type annotations on this declaration + * @param cp the ConstantPool needed to parse the embedded Annotation + * @param decl the dclaration this type annotation is on + * @param container the Class this type annotation is on (may be the same as decl) + * @param type the type the AnnotatedType corresponds to + * @param filter the type annotation targets included in this AnnotatedType + */ + public static AnnotatedType buildAnnotatedType(byte[] rawAnnotations, + ConstantPool cp, + AnnotatedElement decl, + Class container, + Type type, + TypeAnnotationTarget filter) { + TypeAnnotation[] tas = parseTypeAnnotations(rawAnnotations, + cp, + decl, + container); + List l = new ArrayList<>(tas.length); + for (TypeAnnotation t : tas) { + TypeAnnotationTargetInfo ti = t.getTargetInfo(); + if (ti.getTarget() == filter) + l.add(t); + } + TypeAnnotation[] typeAnnotations = l.toArray(new TypeAnnotation[0]); + return AnnotatedTypeFactory.buildAnnotatedType(type, + LocationInfo.BASE_LOCATION, + typeAnnotations, + typeAnnotations, + decl); + } + + /** + * Build an array of AnnotatedTypes from the parameters supplied. + * + * This method and {@code buildAnnotatedType} are probably + * the entry points you are looking for. + * + * @param rawAnnotations the byte[] encoding of all type annotations on this declaration + * @param cp the ConstantPool needed to parse the embedded Annotation + * @param decl the declaration this type annotation is on + * @param container the Class this type annotation is on (may be the same as decl) + * @param types the Types the AnnotatedTypes corresponds to + * @param filter the type annotation targets that included in this AnnotatedType + */ + public static AnnotatedType[] buildAnnotatedTypes(byte[] rawAnnotations, + ConstantPool cp, + AnnotatedElement decl, + Class container, + Type[] types, + TypeAnnotationTarget filter) { + int size = types.length; + AnnotatedType[] result = new AnnotatedType[size]; + Arrays.fill(result, AnnotatedTypeFactory.EMPTY_ANNOTATED_TYPE); + @SuppressWarnings("rawtypes") + ArrayList[] l = new ArrayList[size]; // array of ArrayList + + TypeAnnotation[] tas = parseTypeAnnotations(rawAnnotations, + cp, + decl, + container); + for (TypeAnnotation t : tas) { + TypeAnnotationTargetInfo ti = t.getTargetInfo(); + if (ti.getTarget() == filter) { + int pos = ti.getCount(); + if (l[pos] == null) { + ArrayList tmp = new ArrayList<>(tas.length); + l[pos] = tmp; + } + @SuppressWarnings("unchecked") + ArrayList tmp = l[pos]; + tmp.add(t); + } + } + for (int i = 0; i < size; i++) { + @SuppressWarnings("unchecked") + ArrayList list = l[i]; + if (list != null) { + TypeAnnotation[] typeAnnotations = list.toArray(new TypeAnnotation[0]); + result[i] = AnnotatedTypeFactory.buildAnnotatedType(types[i], + LocationInfo.BASE_LOCATION, + typeAnnotations, + typeAnnotations, + decl); + } + } + return result; + } + + // Class helpers + + /** + * Build an AnnotatedType for the class decl's supertype. + * + * @param rawAnnotations the byte[] encoding of all type annotations on this declaration + * @param cp the ConstantPool needed to parse the embedded Annotation + * @param decl the Class which annotated supertype is being built + */ + public static AnnotatedType buildAnnotatedSuperclass(byte[] rawAnnotations, + ConstantPool cp, + Class decl) { + Type supertype = decl.getGenericSuperclass(); + if (supertype == null) + return AnnotatedTypeFactory.EMPTY_ANNOTATED_TYPE; + return buildAnnotatedType(rawAnnotations, + cp, + decl, + decl, + supertype, + TypeAnnotationTarget.CLASS_EXTENDS); + } + + /** + * Build an array of AnnotatedTypes for the class decl's implemented + * interfaces. + * + * @param rawAnnotations the byte[] encoding of all type annotations on this declaration + * @param cp the ConstantPool needed to parse the embedded Annotation + * @param decl the Class whose annotated implemented interfaces is being built + */ + public static AnnotatedType[] buildAnnotatedInterfaces(byte[] rawAnnotations, + ConstantPool cp, + Class decl) { + return buildAnnotatedTypes(rawAnnotations, + cp, + decl, + decl, + decl.getGenericInterfaces(), + TypeAnnotationTarget.CLASS_IMPLEMENTS); + } + + // TypeVariable helpers + + /** + * Parse regular annotations on a TypeVariable declared on genericDecl. + * + * Regular Annotations on TypeVariables are stored in the type + * annotation byte[] in the class file. + * + * @param genericsDecl the declaration declaring the type variable + * @param typeVarIndex the 0-based index of this type variable in the declaration + */ + public static Annotation[] parseTypeVariableAnnotations(D genericDecl, + int typeVarIndex) { + AnnotatedElement decl; + TypeAnnotationTarget predicate; + if (genericDecl instanceof Class) { + decl = (Class)genericDecl; + predicate = TypeAnnotationTarget.CLASS_TYPE_PARAMETER; + } else if (genericDecl instanceof Executable) { + decl = (Executable)genericDecl; + predicate = TypeAnnotationTarget.METHOD_TYPE_PARAMETER; + } else { + throw new AssertionError("Unknown GenericDeclaration " + genericDecl + "\nthis should not happen."); + } + List typeVarAnnos = TypeAnnotation.filter(parseAllTypeAnnotations(decl), + predicate); + List res = new ArrayList<>(typeVarAnnos.size()); + for (TypeAnnotation t : typeVarAnnos) + if (t.getTargetInfo().getCount() == typeVarIndex) + res.add(t.getAnnotation()); + return res.toArray(new Annotation[0]); + } + + /** + * Build an array of AnnotatedTypes for the declaration decl's bounds. + * + * @param bounds the bounds corresponding to the annotated bounds + * @param decl the declaration whose annotated bounds is being built + * @param typeVarIndex the index of this type variable on the decl + */ + public static AnnotatedType[] parseAnnotatedBounds(Type[] bounds, + D decl, + int typeVarIndex) { + return parseAnnotatedBounds(bounds, decl, typeVarIndex, LocationInfo.BASE_LOCATION); + } + //helper for above + static AnnotatedType[] parseAnnotatedBounds(Type[] bounds, + D decl, + int typeVarIndex, + LocationInfo loc) { + List candidates = fetchBounds(decl); + if (bounds != null) { + int startIndex = 0; + AnnotatedType[] res = new AnnotatedType[bounds.length]; + Arrays.fill(res, AnnotatedTypeFactory.EMPTY_ANNOTATED_TYPE); + + // Adjust bounds index + // + // Figure out if the type annotations for this bound starts with 0 + // or 1. The spec says within a bound the 0:th type annotation will + // always be on an bound of a Class type (not Interface type). So + // if the programmer starts with an Interface type for the first + // (and following) bound(s) the implicit Object bound is considered + // the first (that is 0:th) bound and type annotations start on + // index 1. + if (bounds.length > 0) { + Type b0 = bounds[0]; + if (!(b0 instanceof Class)) { + startIndex = 1; + } else { + Class c = (Class)b0; + if (c.isInterface()) { + startIndex = 1; + } + } + } + + for (int i = 0; i < bounds.length; i++) { + List l = new ArrayList<>(candidates.size()); + for (TypeAnnotation t : candidates) { + TypeAnnotationTargetInfo tInfo = t.getTargetInfo(); + if (tInfo.getSecondaryIndex() == i + startIndex && + tInfo.getCount() == typeVarIndex) { + l.add(t); + } + res[i] = AnnotatedTypeFactory.buildAnnotatedType(bounds[i], + loc, + l.toArray(new TypeAnnotation[0]), + candidates.toArray(new TypeAnnotation[0]), + (AnnotatedElement)decl); + } + } + return res; + } + return new AnnotatedType[0]; + } + private static List fetchBounds(D decl) { + AnnotatedElement boundsDecl; + TypeAnnotationTarget target; + if (decl instanceof Class) { + target = TypeAnnotationTarget.CLASS_PARAMETER_BOUND; + boundsDecl = (Class)decl; + } else { + target = TypeAnnotationTarget.METHOD_PARAMETER_BOUND; + boundsDecl = (Executable)decl; + } + return TypeAnnotation.filter(TypeAnnotationParser.parseAllTypeAnnotations(boundsDecl), target); + } + + /* + * Parse all type annotations on the declaration supplied. This is needed + * when you go from for example an annotated return type on a method that + * is a type variable declared on the class. In this case you need to + * 'jump' to the decl of the class and parse all type annotations there to + * find the ones that are applicable to the type variable. + */ + static TypeAnnotation[] parseAllTypeAnnotations(AnnotatedElement decl) { + Class container; + byte[] rawBytes; + JavaLangAccess javaLangAccess = sun.misc.SharedSecrets.getJavaLangAccess(); + if (decl instanceof Class) { + container = (Class)decl; + rawBytes = javaLangAccess.getRawClassTypeAnnotations(container); + } else if (decl instanceof Executable) { + container = ((Executable)decl).getDeclaringClass(); + rawBytes = javaLangAccess.getRawExecutableTypeAnnotations((Executable)decl); + } else { + // Should not reach here. Assert? + return EMPTY_TYPE_ANNOTATION_ARRAY; + } + return parseTypeAnnotations(rawBytes, javaLangAccess.getConstantPool(container), + decl, container); + } + + /* Parse type annotations encoded as an array of bytes */ + private static TypeAnnotation[] parseTypeAnnotations(byte[] rawAnnotations, + ConstantPool cp, + AnnotatedElement baseDecl, + Class container) { + if (rawAnnotations == null) + return EMPTY_TYPE_ANNOTATION_ARRAY; + + ByteBuffer buf = ByteBuffer.wrap(rawAnnotations); + int annotationCount = buf.getShort() & 0xFFFF; + List typeAnnotations = new ArrayList<>(annotationCount); + + // Parse each TypeAnnotation + for (int i = 0; i < annotationCount; i++) { + TypeAnnotation ta = parseTypeAnnotation(buf, cp, baseDecl, container); + if (ta != null) + typeAnnotations.add(ta); + } + + return typeAnnotations.toArray(EMPTY_TYPE_ANNOTATION_ARRAY); + } + + + // Helper + static Map, Annotation> mapTypeAnnotations(TypeAnnotation[] typeAnnos) { + Map, Annotation> result = + new LinkedHashMap<>(); + for (TypeAnnotation t : typeAnnos) { + Annotation a = t.getAnnotation(); + Class klass = a.annotationType(); + AnnotationType type = AnnotationType.getInstance(klass); + if (type.retention() == RetentionPolicy.RUNTIME) + if (result.put(klass, a) != null) + throw new AnnotationFormatError("Duplicate annotation for class: "+klass+": " + a); + } + return result; + } + + // Position codes + // Regular type parameter annotations + private static final byte CLASS_TYPE_PARAMETER = 0x00; + private static final byte METHOD_TYPE_PARAMETER = 0x01; + // Type Annotations outside method bodies + private static final byte CLASS_EXTENDS = 0x10; + private static final byte CLASS_TYPE_PARAMETER_BOUND = 0x11; + private static final byte METHOD_TYPE_PARAMETER_BOUND = 0x12; + private static final byte FIELD = 0x13; + private static final byte METHOD_RETURN = 0x14; + private static final byte METHOD_RECEIVER = 0x15; + private static final byte METHOD_FORMAL_PARAMETER = 0x16; + private static final byte THROWS = 0x17; + // Type Annotations inside method bodies + private static final byte LOCAL_VARIABLE = (byte)0x40; + private static final byte RESOURCE_VARIABLE = (byte)0x41; + private static final byte EXCEPTION_PARAMETER = (byte)0x42; + private static final byte CAST = (byte)0x43; + private static final byte INSTANCEOF = (byte)0x44; + private static final byte NEW = (byte)0x45; + private static final byte CONSTRUCTOR_REFERENCE_RECEIVER = (byte)0x46; + private static final byte METHOD_REFERENCE_RECEIVER = (byte)0x47; + private static final byte LAMBDA_FORMAL_PARAMETER = (byte)0x48; + private static final byte METHOD_REFERENCE = (byte)0x49; + private static final byte METHOD_REFERENCE_TYPE_ARGUMENT = (byte)0x50; + + private static TypeAnnotation parseTypeAnnotation(ByteBuffer buf, + ConstantPool cp, + AnnotatedElement baseDecl, + Class container) { + TypeAnnotationTargetInfo ti = parseTargetInfo(buf); + LocationInfo locationInfo = LocationInfo.parseLocationInfo(buf); + Annotation a = AnnotationParser.parseAnnotation(buf, cp, container, false); + if (ti == null) // Inside a method for example + return null; + return new TypeAnnotation(ti, locationInfo, a, baseDecl); + } + + private static TypeAnnotationTargetInfo parseTargetInfo(ByteBuffer buf) { + byte posCode = buf.get(); + switch(posCode) { + case CLASS_TYPE_PARAMETER: + case METHOD_TYPE_PARAMETER: { + byte index = buf.get(); + TypeAnnotationTargetInfo res; + if (posCode == CLASS_TYPE_PARAMETER) + res = new TypeAnnotationTargetInfo(TypeAnnotationTarget.CLASS_TYPE_PARAMETER, + index); + else + res = new TypeAnnotationTargetInfo(TypeAnnotationTarget.METHOD_TYPE_PARAMETER, + index); + return res; + } // unreachable break; + case CLASS_EXTENDS: { + short index = buf.getShort(); + if (index == -1) { + return new TypeAnnotationTargetInfo(TypeAnnotationTarget.CLASS_EXTENDS); + } else if (index >= 0) { + TypeAnnotationTargetInfo res = new TypeAnnotationTargetInfo(TypeAnnotationTarget.CLASS_IMPLEMENTS, + index); + return res; + }} break; + case CLASS_TYPE_PARAMETER_BOUND: + return parse2ByteTarget(TypeAnnotationTarget.CLASS_PARAMETER_BOUND, buf); + case METHOD_TYPE_PARAMETER_BOUND: + return parse2ByteTarget(TypeAnnotationTarget.METHOD_PARAMETER_BOUND, buf); + case FIELD: + return new TypeAnnotationTargetInfo(TypeAnnotationTarget.FIELD_TYPE); + case METHOD_RETURN: + return new TypeAnnotationTargetInfo(TypeAnnotationTarget.METHOD_RETURN_TYPE); + case METHOD_RECEIVER: + return new TypeAnnotationTargetInfo(TypeAnnotationTarget.METHOD_RECEIVER_TYPE); + case METHOD_FORMAL_PARAMETER: { + // Todo + byte index = buf.get(); + } break; + case THROWS: + return parseShortTarget(TypeAnnotationTarget.THROWS, buf); + + /* + * The ones below are inside method bodies, we don't care about them for core reflection + * other than adjusting for them in the byte stream. + */ + case LOCAL_VARIABLE: + case RESOURCE_VARIABLE: + short length = buf.getShort(); + for (int i = 0; i < length; ++i) { + short offset = buf.getShort(); + short varLength = buf.getShort(); + short index = buf.getShort(); + } + break; + case EXCEPTION_PARAMETER: { + byte index = buf.get(); + } break; + case CAST: + case INSTANCEOF: + case NEW: { + short offset = buf.getShort(); + } break; + case CONSTRUCTOR_REFERENCE_RECEIVER: + case METHOD_REFERENCE_RECEIVER: { + short offset = buf.getShort(); + byte index = buf.get(); + } break; + case LAMBDA_FORMAL_PARAMETER: { + byte index = buf.get(); + } break; + case METHOD_REFERENCE: + // This one isn't in the spec yet + break; + case METHOD_REFERENCE_TYPE_ARGUMENT: { + short offset = buf.getShort(); + byte index = buf.get(); + } break; + + default: + // will throw error below + break; + } + throw new AnnotationFormatError("Could not parse bytes for type annotations"); + } + + private static TypeAnnotationTargetInfo parseShortTarget(TypeAnnotationTarget target, ByteBuffer buf) { + short index = buf.getShort(); + return new TypeAnnotationTargetInfo(target, index); + } + private static TypeAnnotationTargetInfo parse2ByteTarget(TypeAnnotationTarget target, ByteBuffer buf) { + byte count = buf.get(); + byte secondaryIndex = buf.get(); + return new TypeAnnotationTargetInfo(target, + count, + secondaryIndex); + } +} diff --git a/jdk/src/share/classes/sun/reflect/generics/reflectiveObjects/TypeVariableImpl.java b/jdk/src/share/classes/sun/reflect/generics/reflectiveObjects/TypeVariableImpl.java index 021b84891f1..4bc3356278b 100644 --- a/jdk/src/share/classes/sun/reflect/generics/reflectiveObjects/TypeVariableImpl.java +++ b/jdk/src/share/classes/sun/reflect/generics/reflectiveObjects/TypeVariableImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2013, 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 @@ -25,13 +25,18 @@ package sun.reflect.generics.reflectiveObjects; -import java.lang.annotation.Annotation; +import java.lang.annotation.*; +import java.lang.reflect.AnnotatedType; import java.lang.reflect.Array; import java.lang.reflect.GenericDeclaration; import java.lang.reflect.Type; import java.lang.reflect.TypeVariable; +import java.util.LinkedHashMap; +import java.util.Map; import java.util.Objects; - +import sun.reflect.annotation.AnnotationSupport; +import sun.reflect.annotation.TypeAnnotationParser; +import sun.reflect.annotation.AnnotationType; import sun.reflect.generics.factory.GenericsFactory; import sun.reflect.generics.tree.FieldTypeSignature; import sun.reflect.generics.visitor.Reifier; @@ -182,45 +187,75 @@ public class TypeVariableImpl return genericDeclaration.hashCode() ^ name.hashCode(); } - // Currently vacuous implementations of AnnotatedElement methods. + // Implementations of AnnotatedElement methods. public boolean isAnnotationPresent(Class annotationClass) { Objects.requireNonNull(annotationClass); return false; } + @SuppressWarnings("unchecked") public T getAnnotation(Class annotationClass) { Objects.requireNonNull(annotationClass); - return null; + // T is an Annotation type, the return value of get will be an annotation + return (T)mapAnnotations(getAnnotations()).get(annotationClass); } public T getDeclaredAnnotation(Class annotationClass) { Objects.requireNonNull(annotationClass); - return null; + return getAnnotation(annotationClass); } - @SuppressWarnings("unchecked") public T[] getAnnotations(Class annotationClass) { Objects.requireNonNull(annotationClass); - // safe because annotationClass is the class for T - return (T[])Array.newInstance(annotationClass, 0); + return AnnotationSupport.getMultipleAnnotations(mapAnnotations(getAnnotations()), annotationClass); } - @SuppressWarnings("unchecked") public T[] getDeclaredAnnotations(Class annotationClass) { Objects.requireNonNull(annotationClass); - // safe because annotationClass is the class for T - return (T[])Array.newInstance(annotationClass, 0); + return getAnnotations(annotationClass); } public Annotation[] getAnnotations() { - // Since zero-length, don't need defensive clone - return EMPTY_ANNOTATION_ARRAY; + int myIndex = typeVarIndex(); + if (myIndex < 0) + throw new AssertionError("Index must be non-negative."); + return TypeAnnotationParser.parseTypeVariableAnnotations(getGenericDeclaration(), myIndex); } public Annotation[] getDeclaredAnnotations() { - // Since zero-length, don't need defensive clone - return EMPTY_ANNOTATION_ARRAY; + return getAnnotations(); + } + + public AnnotatedType[] getAnnotatedBounds() { + return TypeAnnotationParser.parseAnnotatedBounds(getBounds(), + getGenericDeclaration(), + typeVarIndex()); } private static final Annotation[] EMPTY_ANNOTATION_ARRAY = new Annotation[0]; + + // Helpers for annotation methods + private int typeVarIndex() { + TypeVariable[] tVars = getGenericDeclaration().getTypeParameters(); + int i = -1; + for (TypeVariable v : tVars) { + i++; + if (equals(v)) + return i; + } + return -1; + } + + private static Map, Annotation> mapAnnotations(Annotation[] annos) { + Map, Annotation> result = + new LinkedHashMap<>(); + for (Annotation a : annos) { + Class klass = a.annotationType(); + AnnotationType type = AnnotationType.getInstance(klass); + if (type.retention() == RetentionPolicy.RUNTIME) + if (result.put(klass, a) != null) + throw new AnnotationFormatError("Duplicate annotation for class: "+klass+": " + a); + } + return result; + } } diff --git a/jdk/src/share/javavm/export/jvm.h b/jdk/src/share/javavm/export/jvm.h index 28885cfb14d..56a8abb03cc 100644 --- a/jdk/src/share/javavm/export/jvm.h +++ b/jdk/src/share/javavm/export/jvm.h @@ -465,6 +465,12 @@ JVM_GetClassSignature(JNIEnv *env, jclass cls); JNIEXPORT jbyteArray JNICALL JVM_GetClassAnnotations(JNIEnv *env, jclass cls); +/* Type use annotations support (JDK 1.8) */ + +JNIEXPORT jbyteArray JNICALL +JVM_GetClassTypeAnnotations(JNIEnv *env, jclass cls); + + /* * New (JDK 1.4) reflection implementation */ diff --git a/jdk/src/share/native/java/lang/Class.c b/jdk/src/share/native/java/lang/Class.c index 3e595e726af..20d03060101 100644 --- a/jdk/src/share/native/java/lang/Class.c +++ b/jdk/src/share/native/java/lang/Class.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1994, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1994, 2013, 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 @@ -75,7 +75,8 @@ static JNINativeMethod methods[] = { {"getRawAnnotations", "()" BA, (void *)&JVM_GetClassAnnotations}, {"getConstantPool", "()" CPL, (void *)&JVM_GetClassConstantPool}, {"desiredAssertionStatus0","("CLS")Z",(void *)&JVM_DesiredAssertionStatus}, - {"getEnclosingMethod0", "()[" OBJ, (void *)&JVM_GetEnclosingMethodInfo} + {"getEnclosingMethod0", "()[" OBJ, (void *)&JVM_GetEnclosingMethodInfo}, + {"getRawTypeAnnotations", "()" BA, (void *)&JVM_GetClassTypeAnnotations}, }; #undef OBJ diff --git a/jdk/test/java/lang/annotation/TypeAnnotationReflection.java b/jdk/test/java/lang/annotation/TypeAnnotationReflection.java new file mode 100644 index 00000000000..b3aad9726a9 --- /dev/null +++ b/jdk/test/java/lang/annotation/TypeAnnotationReflection.java @@ -0,0 +1,428 @@ +/* + * Copyright (c) 2013, 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. + * + * 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. + */ + +/* + * @test + * @bug 8004698 + * @summary Unit test for type annotations + */ + +import java.util.*; +import java.lang.annotation.*; +import java.lang.reflect.*; +import java.io.Serializable; + +public class TypeAnnotationReflection { + public static void main(String[] args) throws Exception { + testSuper(); + testInterfaces(); + testReturnType(); + testNested(); + testArray(); + testRunException(); + testClassTypeVarBounds(); + testMethodTypeVarBounds(); + testFields(); + testClassTypeVar(); + testMethodTypeVar(); + testParameterizedType(); + testNestedParameterizedType(); + testWildcardType(); + } + + private static void check(boolean b) { + if (!b) + throw new RuntimeException(); + } + + private static void testSuper() throws Exception { + check(Object.class.getAnnotatedSuperclass().getAnnotations().length == 0); + check(Class.class.getAnnotatedSuperclass().getAnnotations().length == 0); + + AnnotatedType a; + a = TestClassArray.class.getAnnotatedSuperclass(); + Annotation[] annos = a.getAnnotations(); + check(annos.length == 2); + check(annos[0].annotationType().equals(TypeAnno.class)); + check(annos[1].annotationType().equals(TypeAnno2.class)); + check(((TypeAnno)annos[0]).value().equals("extends")); + check(((TypeAnno2)annos[1]).value().equals("extends2")); + } + + private static void testInterfaces() throws Exception { + AnnotatedType[] as; + as = TestClassArray.class.getAnnotatedInterfaces(); + check(as.length == 3); + check(as[1].getAnnotations().length == 0); + + Annotation[] annos; + annos = as[0].getAnnotations(); + check(annos.length == 2); + check(annos[0].annotationType().equals(TypeAnno.class)); + check(annos[1].annotationType().equals(TypeAnno2.class)); + check(((TypeAnno)annos[0]).value().equals("implements serializable")); + check(((TypeAnno2)annos[1]).value().equals("implements2 serializable")); + + annos = as[2].getAnnotations(); + check(annos.length == 2); + check(annos[0].annotationType().equals(TypeAnno.class)); + check(annos[1].annotationType().equals(TypeAnno2.class)); + check(((TypeAnno)annos[0]).value().equals("implements cloneable")); + check(((TypeAnno2)annos[1]).value().equals("implements2 cloneable")); + } + + private static void testReturnType() throws Exception { + Method m = TestClassArray.class.getDeclaredMethod("foo", (Class[])null); + Annotation[] annos = m.getAnnotatedReturnType().getAnnotations(); + check(annos.length == 1); + check(annos[0].annotationType().equals(TypeAnno.class)); + check(((TypeAnno)annos[0]).value().equals("return1")); + } + + private static void testNested() throws Exception { + Method m = TestClassNested.class.getDeclaredMethod("foo", (Class[])null); + Annotation[] annos = m.getAnnotatedReturnType().getAnnotations(); + check(annos.length == 1); + check(annos[0].annotationType().equals(TypeAnno.class)); + check(((TypeAnno)annos[0]).value().equals("array")); + + AnnotatedType t = m.getAnnotatedReturnType(); + t = ((AnnotatedArrayType)t).getAnnotatedGenericComponentType(); + annos = t.getAnnotations(); + check(annos.length == 1); + check(annos[0].annotationType().equals(TypeAnno.class)); + check(((TypeAnno)annos[0]).value().equals("Inner")); + } + + private static void testArray() throws Exception { + Method m = TestClassArray.class.getDeclaredMethod("foo", (Class[])null); + AnnotatedArrayType t = (AnnotatedArrayType) m.getAnnotatedReturnType(); + Annotation[] annos = t.getAnnotations(); + check(annos.length == 1); + check(annos[0].annotationType().equals(TypeAnno.class)); + check(((TypeAnno)annos[0]).value().equals("return1")); + + t = (AnnotatedArrayType)t.getAnnotatedGenericComponentType(); + annos = t.getAnnotations(); + check(annos.length == 0); + + t = (AnnotatedArrayType)t.getAnnotatedGenericComponentType(); + annos = t.getAnnotations(); + check(annos.length == 1); + check(annos[0].annotationType().equals(TypeAnno.class)); + check(((TypeAnno)annos[0]).value().equals("return3")); + + AnnotatedType tt = t.getAnnotatedGenericComponentType(); + check(!(tt instanceof AnnotatedArrayType)); + annos = tt.getAnnotations(); + check(annos.length == 1); + check(annos[0].annotationType().equals(TypeAnno.class)); + check(((TypeAnno)annos[0]).value().equals("return4")); + } + + private static void testRunException() throws Exception { + Method m = TestClassException.class.getDeclaredMethod("foo", (Class[])null); + AnnotatedType[] ts = m.getAnnotatedExceptionTypes(); + check(ts.length == 3); + + AnnotatedType t; + Annotation[] annos; + t = ts[0]; + annos = t.getAnnotations(); + check(annos.length == 2); + check(annos[0].annotationType().equals(TypeAnno.class)); + check(annos[1].annotationType().equals(TypeAnno2.class)); + check(((TypeAnno)annos[0]).value().equals("RE")); + check(((TypeAnno2)annos[1]).value().equals("RE2")); + + t = ts[1]; + annos = t.getAnnotations(); + check(annos.length == 0); + + t = ts[2]; + annos = t.getAnnotations(); + check(annos.length == 1); + check(annos[0].annotationType().equals(TypeAnno.class)); + check(((TypeAnno)annos[0]).value().equals("AIOOBE")); + } + + private static void testClassTypeVarBounds() throws Exception { + Method m = TestClassTypeVarAndField.class.getDeclaredMethod("foo", (Class[])null); + AnnotatedType ret = m.getAnnotatedReturnType(); + Annotation[] annos = ret.getAnnotations(); + check(annos.length == 2); + + AnnotatedType[] annotatedBounds = ((AnnotatedTypeVariable)ret).getAnnotatedBounds(); + check(annotatedBounds.length == 2); + + annos = annotatedBounds[0].getAnnotations(); + check(annos.length == 1); + check(annos[0].annotationType().equals(TypeAnno.class)); + check(((TypeAnno)annos[0]).value().equals("Object1")); + + annos = annotatedBounds[1].getAnnotations(); + check(annos.length == 2); + check(annos[0].annotationType().equals(TypeAnno.class)); + check(annos[1].annotationType().equals(TypeAnno2.class)); + check(((TypeAnno)annos[0]).value().equals("Runnable1")); + check(((TypeAnno2)annos[1]).value().equals("Runnable2")); + } + + private static void testMethodTypeVarBounds() throws Exception { + Method m2 = TestClassTypeVarAndField.class.getDeclaredMethod("foo2", (Class[])null); + AnnotatedType ret2 = m2.getAnnotatedReturnType(); + AnnotatedType[] annotatedBounds2 = ((AnnotatedTypeVariable)ret2).getAnnotatedBounds(); + check(annotatedBounds2.length == 1); + + Annotation[] annos = annotatedBounds2[0].getAnnotations(); + check(annos.length == 1); + check(annos[0].annotationType().equals(TypeAnno.class)); + check(((TypeAnno)annos[0]).value().equals("M Runnable")); + } + + private static void testFields() throws Exception { + Field f1 = TestClassTypeVarAndField.class.getDeclaredField("field1"); + AnnotatedType at; + Annotation[] annos; + + at = f1.getAnnotatedType(); + annos = at.getAnnotations(); + check(annos.length == 2); + check(annos[0].annotationType().equals(TypeAnno.class)); + check(annos[1].annotationType().equals(TypeAnno2.class)); + check(((TypeAnno)annos[0]).value().equals("T1 field")); + check(((TypeAnno2)annos[1]).value().equals("T2 field")); + + Field f2 = TestClassTypeVarAndField.class.getDeclaredField("field2"); + at = f2.getAnnotatedType(); + annos = at.getAnnotations(); + check(annos.length == 0); + + Field f3 = TestClassTypeVarAndField.class.getDeclaredField("field3"); + at = f3.getAnnotatedType(); + annos = at.getAnnotations(); + check(annos.length == 1); + check(annos[0].annotationType().equals(TypeAnno.class)); + check(((TypeAnno)annos[0]).value().equals("Object field")); + } + + private static void testClassTypeVar() throws Exception { + TypeVariable[] typeVars = TestClassTypeVarAndField.class.getTypeParameters(); + Annotation[] annos; + check(typeVars.length == 2); + + // First TypeVar + AnnotatedType[] annotatedBounds = typeVars[0].getAnnotatedBounds(); + check(annotatedBounds.length == 2); + + annos = annotatedBounds[0].getAnnotations(); + check(annos.length == 1); + check(annos[0].annotationType().equals(TypeAnno.class)); + check(((TypeAnno)annos[0]).value().equals("Object1")); + + annos = annotatedBounds[1].getAnnotations(); + check(annos.length == 2); + check(annos[0].annotationType().equals(TypeAnno.class)); + check(annos[1].annotationType().equals(TypeAnno2.class)); + check(((TypeAnno)annos[0]).value().equals("Runnable1")); + check(((TypeAnno2)annos[1]).value().equals("Runnable2")); + + // second TypeVar regular anno + Annotation[] regularAnnos = typeVars[1].getAnnotations(); + check(regularAnnos.length == 1); + check(typeVars[1].getAnnotation(TypeAnno.class).value().equals("EE")); + + // second TypeVar + annotatedBounds = typeVars[1].getAnnotatedBounds(); + check(annotatedBounds.length == 1); + + annos = annotatedBounds[0].getAnnotations(); + check(annos.length == 1); + check(annos[0].annotationType().equals(TypeAnno2.class)); + check(((TypeAnno2)annos[0]).value().equals("EEBound")); + } + + private static void testMethodTypeVar() throws Exception { + Method m2 = TestClassTypeVarAndField.class.getDeclaredMethod("foo2", (Class[])null); + TypeVariable[] t = m2.getTypeParameters(); + check(t.length == 1); + Annotation[] annos = t[0].getAnnotations(); + check(annos.length == 0); + + AnnotatedType[] annotatedBounds2 = t[0].getAnnotatedBounds(); + check(annotatedBounds2.length == 1); + + annos = annotatedBounds2[0].getAnnotations(); + check(annos.length == 1); + check(annos[0].annotationType().equals(TypeAnno.class)); + check(((TypeAnno)annos[0]).value().equals("M Runnable")); + + // Second method + m2 = TestClassTypeVarAndField.class.getDeclaredMethod("foo3", (Class[])null); + t = m2.getTypeParameters(); + check(t.length == 1); + annos = t[0].getAnnotations(); + check(annos.length == 1); + check(annos[0].annotationType().equals(TypeAnno.class)); + check(((TypeAnno)annos[0]).value().equals("K")); + + annotatedBounds2 = t[0].getAnnotatedBounds(); + check(annotatedBounds2.length == 1); + + annos = annotatedBounds2[0].getAnnotations(); + check(annos.length == 0); + } + + private static void testParameterizedType() { + // Base + AnnotatedType[] as; + as = TestParameterizedType.class.getAnnotatedInterfaces(); + check(as.length == 1); + check(as[0].getAnnotations().length == 1); + check(as[0].getAnnotation(TypeAnno.class).value().equals("M")); + + Annotation[] annos; + as = ((AnnotatedParameterizedType)as[0]).getAnnotatedActualTypeArguments(); + check(as.length == 2); + annos = as[0].getAnnotations(); + check(annos.length == 1); + check(as[0].getAnnotation(TypeAnno.class).value().equals("S")); + check(as[0].getAnnotation(TypeAnno2.class) == null); + + annos = as[1].getAnnotations(); + check(annos.length == 2); + check(((TypeAnno)annos[0]).value().equals("I")); + check(as[1].getAnnotation(TypeAnno2.class).value().equals("I2")); + } + + private static void testNestedParameterizedType() throws Exception { + Method m = TestParameterizedType.class.getDeclaredMethod("foo2", (Class[])null); + AnnotatedType ret = m.getAnnotatedReturnType(); + Annotation[] annos; + annos = ret.getAnnotations(); + check(annos.length == 1); + check(((TypeAnno)annos[0]).value().equals("I")); + + AnnotatedType[] args = ((AnnotatedParameterizedType)ret).getAnnotatedActualTypeArguments(); + check(args.length == 1); + annos = args[0].getAnnotations(); + check(annos.length == 2); + check(((TypeAnno)annos[0]).value().equals("I1")); + check(args[0].getAnnotation(TypeAnno2.class).value().equals("I2")); + } + + private static void testWildcardType() throws Exception { + Method m = TestWildcardType.class.getDeclaredMethod("foo", (Class[])null); + AnnotatedType ret = m.getAnnotatedReturnType(); + AnnotatedType[] t; + t = ((AnnotatedParameterizedType)ret).getAnnotatedActualTypeArguments(); + check(t.length == 1); + ret = t[0]; + + Field f = TestWildcardType.class.getDeclaredField("f1"); + AnnotatedWildcardType w = (AnnotatedWildcardType)((AnnotatedParameterizedType)f + .getAnnotatedType()).getAnnotatedActualTypeArguments()[0]; + t = w.getAnnotatedLowerBounds(); + check(t.length == 0); + t = w.getAnnotatedUpperBounds(); + check(t.length == 1); + Annotation[] annos; + annos = t[0].getAnnotations(); + check(annos.length == 1); + check(((TypeAnno)annos[0]).value().equals("2")); + + f = TestWildcardType.class.getDeclaredField("f2"); + w = (AnnotatedWildcardType)((AnnotatedParameterizedType)f + .getAnnotatedType()).getAnnotatedActualTypeArguments()[0]; + t = w.getAnnotatedUpperBounds(); + check(t.length == 0); + t = w.getAnnotatedLowerBounds(); + check(t.length == 1); + } +} + +abstract class TestWildcardType { + public List foo() { return null;} + public Class<@TypeAnno("1") ? extends @TypeAnno("2") Annotation> f1; + public Class<@TypeAnno("3") ? super @TypeAnno("4") Annotation> f2; +} + +abstract class TestParameterizedType implements @TypeAnno("M") Map<@TypeAnno("S")String, @TypeAnno("I") @TypeAnno2("I2")Integer> { + public ParameterizedOuter.ParameterizedInner foo() {return null;} + public @TypeAnno("O") ParameterizedOuter<@TypeAnno("S1") @TypeAnno2("S2") String>. + @TypeAnno("I") ParameterizedInner<@TypeAnno("I1") @TypeAnno2("I2")Integer> foo2() { + return null; + } +} + +class ParameterizedOuter { + class ParameterizedInner {} +} + +abstract class TestClassArray extends @TypeAnno("extends") @TypeAnno2("extends2") Object + implements @TypeAnno("implements serializable") @TypeAnno2("implements2 serializable") Serializable, + Readable, + @TypeAnno("implements cloneable") @TypeAnno2("implements2 cloneable") Cloneable { + public @TypeAnno("return4") Object @TypeAnno("return1") [][] @TypeAnno("return3")[] foo() { return null; } +} + +abstract class TestClassNested { + public @TypeAnno("Outer") Outer.@TypeAnno("Inner")Inner @TypeAnno("array")[] foo() { return null; } +} + +class Outer { + class Inner { + } +} + +abstract class TestClassException { + public Object foo() throws @TypeAnno("RE") @TypeAnno2("RE2") RuntimeException, + NullPointerException, + @TypeAnno("AIOOBE") ArrayIndexOutOfBoundsException { + return null; + } +} + +abstract class TestClassTypeVarAndField { + @TypeAnno("T1 field") @TypeAnno2("T2 field") T field1; + T field2; + @TypeAnno("Object field") Object field3; + + public @TypeAnno("t1") @TypeAnno2("t2") T foo(){ return null; } + public M foo2() {return null;} + public <@TypeAnno("K") K extends Cloneable> K foo3() {return null;} +} + +@Target(ElementType.TYPE_USE) +@Retention(RetentionPolicy.RUNTIME) +@interface TypeAnno { + String value(); +} + +@Target(ElementType.TYPE_USE) +@Retention(RetentionPolicy.RUNTIME) +@interface TypeAnno2 { + String value(); +} diff --git a/jdk/test/java/lang/annotation/TypeParamAnnotation.java b/jdk/test/java/lang/annotation/TypeParamAnnotation.java new file mode 100644 index 00000000000..50457ec46b1 --- /dev/null +++ b/jdk/test/java/lang/annotation/TypeParamAnnotation.java @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2013, 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. + * + * 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. + */ + +/* + * @test + * @bug 8004698 + * @summary Unit test for annotations on TypeVariables + */ + +import java.util.*; +import java.lang.annotation.*; +import java.lang.reflect.*; +import java.io.Serializable; + +public class TypeParamAnnotation { + public static void main(String[] args) throws Exception { + testOnClass(); + testOnMethod(); + testGetAnno(); + testGetAnnos(); + } + + private static void check(boolean b) { + if (!b) + throw new RuntimeException(); + } + + private static void testOnClass() { + TypeVariable[] ts = TypeParam.class.getTypeParameters(); + check(ts.length == 3); + + Annotation[] as; + + as = ts[0].getAnnotations(); + check(as.length == 2); + check(((ParamAnno)as[0]).value().equals("t")); + check(((ParamAnno2)as[1]).value() == 1); + + as = ts[1].getAnnotations(); + check(as.length == 0); + + as = ts[2].getAnnotations(); + check(as.length == 2); + check(((ParamAnno)as[0]).value().equals("v")); + check(((ParamAnno2)as[1]).value() == 2); + } + private static void testOnMethod() throws Exception { + TypeVariable[] ts = TypeParam.class.getDeclaredMethod("foo").getTypeParameters(); + check(ts.length == 3); + + Annotation[] as; + + as = ts[0].getAnnotations(); + check(as.length == 2); + check(((ParamAnno)as[0]).value().equals("x")); + check(((ParamAnno2)as[1]).value() == 3); + + as = ts[1].getAnnotations(); + check(as.length == 0); + + as = ts[2].getAnnotations(); + check(as.length == 2); + check(((ParamAnno)as[0]).value().equals("z")); + check(((ParamAnno2)as[1]).value() == 4); + } + + private static void testGetAnno() { + TypeVariable[] ts = TypeParam.class.getTypeParameters(); + ParamAnno a; + a = ts[0].getAnnotation(ParamAnno.class); + check(a.value().equals("t")); + } + private static void testGetAnnos() throws Exception { + TypeVariable[] ts = TypeParam.class.getDeclaredMethod("foo").getTypeParameters(); + ParamAnno2[] as; + as = ts[0].getAnnotations(ParamAnno2.class); + check(as.length == 1); + check(as[0].value() == 3); + } +} + +class TypeParam <@ParamAnno("t") @ParamAnno2(1) T, + U, + @ParamAnno("v") @ParamAnno2(2) V extends Runnable> { + public <@ParamAnno("x") @ParamAnno2(3) X, + Y, + @ParamAnno("z") @ParamAnno2(4) Z extends Cloneable> void foo() {} +} + +@Target(ElementType.TYPE_PARAMETER) +@Retention(RetentionPolicy.RUNTIME) +@interface ParamAnno { + String value(); +} + +@Target(ElementType.TYPE_PARAMETER) +@Retention(RetentionPolicy.RUNTIME) +@interface ParamAnno2 { + int value(); +} From e8860a177b428810f30ffcfe911a22bb717239f5 Mon Sep 17 00:00:00 2001 From: Stefan Karlsson Date: Tue, 29 Jan 2013 10:51:33 +0100 Subject: [PATCH 111/210] 8004710: NPG: jmap could throw sun.jvm.hotspot.types.WrongTypeException after PermGen removal When calculating live object regions, make sure that the alignment reserve, at the end of a TLAB, is excluded. Reviewed-by: jmasa, brutisso --- .../sun/jvm/hotspot/oops/ObjectHeap.java | 2 +- .../runtime/ThreadLocalAllocBuffer.java | 20 ++++++++++++++++--- .../classes/sun/jvm/hotspot/runtime/VM.java | 9 +++++++++ hotspot/src/share/vm/runtime/vmStructs.cpp | 1 + 4 files changed, 28 insertions(+), 4 deletions(-) diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/ObjectHeap.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/ObjectHeap.java index 59923078d3d..f944188f4d1 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/ObjectHeap.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/ObjectHeap.java @@ -467,7 +467,7 @@ public class ObjectHeap { liveRegions.add(tlab.start()); liveRegions.add(tlab.start()); liveRegions.add(tlab.top()); - liveRegions.add(tlab.end()); + liveRegions.add(tlab.hardEnd()); } } } diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/ThreadLocalAllocBuffer.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/ThreadLocalAllocBuffer.java index 381b53deded..738dc94fa91 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/ThreadLocalAllocBuffer.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/ThreadLocalAllocBuffer.java @@ -27,6 +27,7 @@ package sun.jvm.hotspot.runtime; import java.io.*; import java.util.*; import sun.jvm.hotspot.debugger.*; +import sun.jvm.hotspot.oops.*; import sun.jvm.hotspot.types.*; /**

ThreadLocalAllocBuffer: a descriptor for thread-local storage @@ -62,9 +63,22 @@ public class ThreadLocalAllocBuffer extends VMObject { super(addr); } - public Address start() { return startField.getValue(addr); } - public Address end() { return endField.getValue(addr); } - public Address top() { return topField.getValue(addr); } + public Address start() { return startField.getValue(addr); } + public Address end() { return endField.getValue(addr); } + public Address top() { return topField.getValue(addr); } + public Address hardEnd() { return end().addOffsetTo(alignmentReserve()); } + + private long alignmentReserve() { + return Oop.alignObjectSize(endReserve()); + } + + private long endReserve() { + long minFillerArraySize = Array.baseOffsetInBytes(BasicType.T_INT); + long reserveForAllocationPrefetch = VM.getVM().getReserveForAllocationPrefetch(); + long heapWordSize = VM.getVM().getHeapWordSize(); + + return Math.max(minFillerArraySize, reserveForAllocationPrefetch * heapWordSize); + } /** Support for iteration over heap -- not sure how this will interact with GC in reflective system, but necessary for the diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/VM.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/VM.java index 5531980b1f8..80464a10bb0 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/VM.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/VM.java @@ -114,6 +114,7 @@ public class VM { private int invalidOSREntryBCI; private ReversePtrs revPtrs; private VMRegImpl vmregImpl; + private int reserveForAllocationPrefetch; // System.getProperties from debuggee VM private Properties sysProps; @@ -293,6 +294,10 @@ public class VM { vmRelease = CStringUtilities.getString(releaseAddr); Address vmInternalInfoAddr = vmVersion.getAddressField("_s_internal_vm_info_string").getValue(); vmInternalInfo = CStringUtilities.getString(vmInternalInfoAddr); + + CIntegerType intType = (CIntegerType) db.lookupType("int"); + CIntegerField reserveForAllocationPrefetchField = vmVersion.getCIntegerField("_reserve_for_allocation_prefetch"); + reserveForAllocationPrefetch = (int)reserveForAllocationPrefetchField.getCInteger(intType); } catch (Exception exp) { throw new RuntimeException("can't determine target's VM version : " + exp.getMessage()); } @@ -778,6 +783,10 @@ public class VM { return vmInternalInfo; } + public int getReserveForAllocationPrefetch() { + return reserveForAllocationPrefetch; + } + public boolean isSharingEnabled() { if (sharingEnabled == null) { Flag flag = getCommandLineFlag("UseSharedSpaces"); diff --git a/hotspot/src/share/vm/runtime/vmStructs.cpp b/hotspot/src/share/vm/runtime/vmStructs.cpp index 70e5d2b9281..1a30f7554e7 100644 --- a/hotspot/src/share/vm/runtime/vmStructs.cpp +++ b/hotspot/src/share/vm/runtime/vmStructs.cpp @@ -1161,6 +1161,7 @@ typedef BinaryTreeDictionary MetablockTreeDictionary; static_field(Abstract_VM_Version, _vm_major_version, int) \ static_field(Abstract_VM_Version, _vm_minor_version, int) \ static_field(Abstract_VM_Version, _vm_build_number, int) \ + static_field(Abstract_VM_Version, _reserve_for_allocation_prefetch, int) \ \ static_field(JDK_Version, _current, JDK_Version) \ nonstatic_field(JDK_Version, _partially_initialized, bool) \ From a1d7653c193af77712492373eb05615afd084c30 Mon Sep 17 00:00:00 2001 From: Erik Joelsson Date: Tue, 29 Jan 2013 16:35:24 +0100 Subject: [PATCH 112/210] 8006873: SWAT-b74 msvcr100.dll does not have the permission for all Reviewed-by: alanb, tbell --- jdk/makefiles/CopyFiles.gmk | 2 ++ 1 file changed, 2 insertions(+) diff --git a/jdk/makefiles/CopyFiles.gmk b/jdk/makefiles/CopyFiles.gmk index 8f99a113d3d..7de946c88e3 100644 --- a/jdk/makefiles/CopyFiles.gmk +++ b/jdk/makefiles/CopyFiles.gmk @@ -267,10 +267,12 @@ endif ifeq ($(OPENJDK_TARGET_OS),windows) MSVCR_TARGET := $(JDK_OUTPUTDIR)/bin/$(notdir $(MSVCR_DLL)) + # Chmod to avoid permission issues if bundles are unpacked on unix platforms. $(MSVCR_TARGET): $(MSVCR_DLL) $(MKDIR) -p $(@D) $(RM) $@ $(CP) $< $@ + $(CHMOD) a+rx $@ COPY_FILES += $(MSVCR_TARGET) endif From ebc0ebf54d6e83f2b609ec0bccf9dcfd89ab28b0 Mon Sep 17 00:00:00 2001 From: Jonathan Gibbons Date: Wed, 30 Jan 2013 09:40:54 -0800 Subject: [PATCH 113/210] 8007096: DocLint parsing problems with some comments Reviewed-by: mcimadamore --- .../tools/javac/parser/DocCommentParser.java | 86 +++++++------------ .../tools/javac/parser/JavadocTokenizer.java | 4 +- .../tools/doclint/EndWithIdentifierTest.java | 32 +++++++ .../tools/doclint/EndWithIdentifierTest.out | 20 +++++ .../doclint/UnfinishedInlineTagTest.java | 17 ++++ .../tools/doclint/UnfinishedInlineTagTest.out | 5 ++ 6 files changed, 108 insertions(+), 56 deletions(-) create mode 100644 langtools/test/tools/doclint/EndWithIdentifierTest.java create mode 100644 langtools/test/tools/doclint/EndWithIdentifierTest.out create mode 100644 langtools/test/tools/doclint/UnfinishedInlineTagTest.java create mode 100644 langtools/test/tools/doclint/UnfinishedInlineTagTest.out diff --git a/langtools/src/share/classes/com/sun/tools/javac/parser/DocCommentParser.java b/langtools/src/share/classes/com/sun/tools/javac/parser/DocCommentParser.java index 989e42d066e..bbc4d81d5c7 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/parser/DocCommentParser.java +++ b/langtools/src/share/classes/com/sun/tools/javac/parser/DocCommentParser.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2013, 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 @@ -279,13 +279,7 @@ public class DocCommentParser { try { nextChar(); if (isIdentifierStart(ch)) { - int namePos = bp; - nextChar(); - while (isIdentifierPart(ch)) - nextChar(); - int nameLen = bp - namePos; - - Name name = names.fromChars(buf, namePos, nameLen); + Name name = readIdentifier(); TagParser tp = tagParsers.get(name); if (tp == null) { List content = blockContent(); @@ -334,14 +328,9 @@ public class DocCommentParser { try { nextChar(); if (isIdentifierStart(ch)) { - int namePos = bp; - nextChar(); - while (isIdentifierPart(ch)) - nextChar(); - int nameLen = bp - namePos; + Name name = readIdentifier(); skipWhitespace(); - Name name = names.fromChars(buf, namePos, nameLen); TagParser tp = tagParsers.get(name); if (tp == null) { DCTree text = inlineText(); @@ -575,10 +564,8 @@ public class DocCommentParser { int pos = bp; if (isJavaIdentifierStart(ch)) { - nextChar(); - while (isJavaIdentifierPart(ch)) - nextChar(); - return m.at(pos).Identifier(names.fromChars(buf, pos, bp - pos)); + Name name = readJavaIdentifier(); + return m.at(pos).Identifier(name); } throw new ParseException("dc.identifier.expected"); @@ -703,39 +690,36 @@ public class DocCommentParser { protected DCTree entity() { int p = bp; nextChar(); - int namep = bp; + Name name = null; boolean checkSemi = false; if (ch == '#') { + int namep = bp; nextChar(); if (isDecimalDigit(ch)) { nextChar(); while (isDecimalDigit(ch)) nextChar(); - checkSemi = true; + name = names.fromChars(buf, namep, bp - namep); } else if (ch == 'x' || ch == 'X') { nextChar(); if (isHexDigit(ch)) { nextChar(); while (isHexDigit(ch)) nextChar(); - checkSemi = true; + name = names.fromChars(buf, namep, bp - namep); } } } else if (isIdentifierStart(ch)) { - nextChar(); - while (isIdentifierPart(ch)) - nextChar(); - checkSemi = true; + name = readIdentifier(); } - if (checkSemi && ch == ';') { + if (name == null) + return erroneous("dc.bad.entity", p); + else { + if (ch != ';') + return erroneous("dc.missing.semicolon", p); nextChar(); - return m.at(p).Entity(names.fromChars(buf, namep, bp - namep - 1)); - } else { - String code = checkSemi - ? "dc.missing.semicolon" - : "dc.bad.entity"; - return erroneous(code, p); + return m.at(p).Entity(name); } } @@ -747,11 +731,7 @@ public class DocCommentParser { int p = bp; nextChar(); if (isIdentifierStart(ch)) { - int namePos = bp; - nextChar(); - while (isIdentifierPart(ch)) - nextChar(); - int nameLen = bp - namePos; + Name name = readIdentifier(); List attrs = htmlAttrs(); if (attrs != null) { boolean selfClosing = false; @@ -761,22 +741,16 @@ public class DocCommentParser { } if (ch == '>') { nextChar(); - Name name = names.fromChars(buf, namePos, nameLen); return m.at(p).StartElement(name, attrs, selfClosing); } } } else if (ch == '/') { nextChar(); if (isIdentifierStart(ch)) { - int namePos = bp; - nextChar(); - while (isIdentifierPart(ch)) - nextChar(); - int nameLen = bp - namePos; + Name name = readIdentifier(); skipWhitespace(); if (ch == '>') { nextChar(); - Name name = names.fromChars(buf, namePos, nameLen); return m.at(p).EndElement(name); } } @@ -822,10 +796,7 @@ public class DocCommentParser { loop: while (isIdentifierStart(ch)) { int namePos = bp; - nextChar(); - while (isIdentifierPart(ch)) - nextChar(); - int nameLen = bp - namePos; + Name name = readIdentifier(); skipWhitespace(); List value = null; ValueKind vkind = ValueKind.EMPTY; @@ -862,7 +833,6 @@ public class DocCommentParser { skipWhitespace(); value = v.toList(); } - Name name = names.fromChars(buf, namePos, nameLen); DCAttribute attr = m.at(namePos).Attribute(name, vkind, value); attrs.add(attr); } @@ -897,7 +867,7 @@ public class DocCommentParser { protected DCErroneous erroneous(String code, int pos) { int i = bp - 1; loop: - while (i > 0) { + while (i > pos) { switch (buf[i]) { case '\f': case '\n': case '\r': newline = true; @@ -926,16 +896,24 @@ public class DocCommentParser { return Character.isUnicodeIdentifierStart(ch); } - protected boolean isIdentifierPart(char ch) { - return Character.isUnicodeIdentifierPart(ch); + protected Name readIdentifier() { + int start = bp; + nextChar(); + while (bp < buflen && Character.isUnicodeIdentifierPart(ch)) + nextChar(); + return names.fromChars(buf, start, bp - start); } protected boolean isJavaIdentifierStart(char ch) { return Character.isJavaIdentifierStart(ch); } - protected boolean isJavaIdentifierPart(char ch) { - return Character.isJavaIdentifierPart(ch); + protected Name readJavaIdentifier() { + int start = bp; + nextChar(); + while (bp < buflen && Character.isJavaIdentifierPart(ch)) + nextChar(); + return names.fromChars(buf, start, bp - start); } protected boolean isDecimalDigit(char ch) { diff --git a/langtools/src/share/classes/com/sun/tools/javac/parser/JavadocTokenizer.java b/langtools/src/share/classes/com/sun/tools/javac/parser/JavadocTokenizer.java index d52a62ef704..847a42b17c8 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/parser/JavadocTokenizer.java +++ b/langtools/src/share/classes/com/sun/tools/javac/parser/JavadocTokenizer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2013, 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 @@ -236,7 +236,7 @@ public class JavadocTokenizer extends JavaTokenizer { // relative to the best match found in the array. if (pos == Position.NOPOS) return Position.NOPOS; - if (pos < 0 || pos >= docComment.length()) + if (pos < 0 || pos > docComment.length()) throw new StringIndexOutOfBoundsException(String.valueOf(pos)); if (docPosns == null) return Position.NOPOS; diff --git a/langtools/test/tools/doclint/EndWithIdentifierTest.java b/langtools/test/tools/doclint/EndWithIdentifierTest.java new file mode 100644 index 00000000000..afd20a3353c --- /dev/null +++ b/langtools/test/tools/doclint/EndWithIdentifierTest.java @@ -0,0 +1,32 @@ +/* + * @test /nodynamiccopyright/ + * @bug 8007096 + * @summary DocLint parsing problems with some comments + * @build DocLintTester + * @run main DocLintTester -Xmsgs:-html EndWithIdentifierTest.java + * @run main DocLintTester -Xmsgs -ref EndWithIdentifierTest.out EndWithIdentifierTest.java + * @author jlahoda + */ + +/**@deprecated*/ +public class EndWithIdentifierTest { + + /**{@link*/ + private void unfinishedInlineTagName() {} + + /**@see List*/ + private void endsWithIdentifier() {} + + /**&*/ + private void entityName() {} + + /** Date: Wed, 30 Jan 2013 09:47:12 -0800 Subject: [PATCH 114/210] 8007034: debug printer for javac internals Reviewed-by: mcimadamore --- langtools/test/tools/javac/lib/DPrinter.java | 1326 ++++++++++++++++++ 1 file changed, 1326 insertions(+) create mode 100644 langtools/test/tools/javac/lib/DPrinter.java diff --git a/langtools/test/tools/javac/lib/DPrinter.java b/langtools/test/tools/javac/lib/DPrinter.java new file mode 100644 index 00000000000..e05b9a8ad16 --- /dev/null +++ b/langtools/test/tools/javac/lib/DPrinter.java @@ -0,0 +1,1326 @@ +/* + * Copyright (c) 2013, 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. + * + * 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. + */ + +import java.io.File; +import java.io.IOException; +import java.io.PrintWriter; +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.EnumSet; +import java.util.HashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Set; + +import javax.lang.model.element.Name; +import javax.lang.model.element.TypeElement; +import javax.tools.FileObject; +import javax.tools.JavaCompiler; +import javax.tools.JavaFileObject; +import javax.tools.StandardJavaFileManager; +import javax.tools.StandardLocation; +import javax.tools.ToolProvider; + +import com.sun.source.util.JavacTask; +import com.sun.source.util.TaskEvent; +import com.sun.source.util.TaskListener; +import com.sun.source.util.Trees; +import com.sun.tools.javac.api.JavacTrees; +import com.sun.tools.javac.code.Annotations; +import com.sun.tools.javac.code.Attribute; +import com.sun.tools.javac.code.Flags; +import com.sun.tools.javac.code.Kinds; +import com.sun.tools.javac.code.Printer; +import com.sun.tools.javac.code.Scope; +import com.sun.tools.javac.code.Scope.CompoundScope; +import com.sun.tools.javac.code.Symbol; +import com.sun.tools.javac.code.Symbol.*; +import com.sun.tools.javac.code.Type; +import com.sun.tools.javac.code.Type.*; +import com.sun.tools.javac.code.TypeTag; +import com.sun.tools.javac.tree.JCTree; +import com.sun.tools.javac.tree.JCTree.*; +import com.sun.tools.javac.tree.Pretty; +import com.sun.tools.javac.tree.TreeInfo; +import com.sun.tools.javac.tree.TreeScanner; +import com.sun.tools.javac.util.Assert; +import com.sun.tools.javac.util.Context; +import com.sun.tools.javac.util.Log; + + +/** + * Debug printer for javac internals, for when toString() just isn't enough. + * + *

+ * The printer provides an API to generate structured views of javac objects, + * such as AST nodes, symbol, types and annotations. Various aspects of the + * output can be configured, such as whether to show nulls, empty lists, or + * a compressed representation of the source code. Visitors are used to walk + * object hierarchies, and can be replaced with custom visitors if the default + * visitors are not flexible enough. + * + *

+ * In general, nodes are printed with an initial line identifying the node + * followed by indented lines for the child nodes. Currently, graphs are + * represented by printing a spanning subtree. + * + *

+ * The printer can be accessed via a simple command-line utility, + * which makes it easy to see the internal representation of source code, + * such as simple test programs, during the compilation pipeline. + * + *

This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own risk. + * This code and its internal interfaces are subject to change or + * deletion without notice. + */ + +public class DPrinter { + protected final PrintWriter out; + protected final Trees trees; + protected Printer printer; + protected boolean showEmptyItems = true; + protected boolean showNulls = true; + protected boolean showPositions = false; + protected boolean showSrc; + protected boolean showTreeSymbols; + protected boolean showTreeTypes; + protected int maxSrcLength = 32; + protected Locale locale = Locale.getDefault(); + protected static final String NULL = "#null"; + + // + + public static DPrinter instance(Context context) { + DPrinter dp = context.get(DPrinter.class); + if (dp == null) { + dp = new DPrinter(context); + } + return dp; + + } + + protected DPrinter(Context context) { + context.put(DPrinter.class, this); + out = context.get(Log.outKey); + trees = JavacTrees.instance(context); + } + + public DPrinter(PrintWriter out, Trees trees) { + this.out = out; + this.trees = trees; + } + + public DPrinter emptyItems(boolean showEmptyItems) { + this.showEmptyItems = showEmptyItems; + return this; + } + + public DPrinter nulls(boolean showNulls) { + this.showNulls = showNulls; + return this; + } + + public DPrinter positions(boolean showPositions) { + this.showPositions = showPositions; + return this; + } + + public DPrinter source(boolean showSrc) { + this.showSrc = showSrc; + return this; + } + + public DPrinter source(int maxSrcLength) { + this.showSrc = true; + this.maxSrcLength = maxSrcLength; + return this; + } + + public DPrinter treeSymbols(boolean showTreeSymbols) { + this.showTreeSymbols = showTreeSymbols; + return this; + } + + public DPrinter treeTypes(boolean showTreeTypes) { + this.showTreeTypes = showTreeTypes; + return this; + } + + public DPrinter typeSymbolPrinter(Printer p) { + printer = p; + return this; + } + + // + + // + + protected enum Details { + /** A one-line non-recursive summary */ + SUMMARY, + /** Multi-line, possibly recursive. */ + FULL + }; + + public void printAnnotations(String label, Annotations annotations) { + printAnnotations(label, annotations, Details.FULL); + } + + protected void printAnnotations(String label, Annotations annotations, Details details) { + if (annotations == null) { + printNull(label); + } else { + // no SUMMARY format currently available to use + + // use reflection to get at private fields + Object DECL_NOT_STARTED = getField(null, Annotations.class, "DECL_NOT_STARTED"); + Object DECL_IN_PROGRESS = getField(null, Annotations.class, "DECL_IN_PROGRESS"); + Object attributes = getField(annotations, Annotations.class, "attributes"); + Object type_attributes = getField(annotations, Annotations.class, "type_attributes"); + + if (!showEmptyItems) { + if (attributes instanceof List && ((List) attributes).isEmpty() + && attributes != DECL_NOT_STARTED + && attributes != DECL_IN_PROGRESS + && type_attributes instanceof List && ((List) type_attributes).isEmpty()) + return; + } + + printString(label, ""); + + indent(+1); + if (attributes == DECL_NOT_STARTED) + printString("attributes", "DECL_NOT_STARTED"); + else if (attributes == DECL_IN_PROGRESS) + printString("attributes", "DECL_IN_PROGRESS"); + else if (attributes instanceof List) + printList("attributes", (List) attributes); + else + printObject("attributes", attributes, Details.SUMMARY); + + if (attributes instanceof List) + printList("type_attributes", (List) type_attributes); + else + printObject("type_attributes", type_attributes, Details.SUMMARY); + indent(-1); + } + } + + public void printAttribute(String label, Attribute attr) { + if (attr == null) { + printNull(label); + } else { + printString(label, attr.getClass().getSimpleName()); + + indent(+1); + attr.accept(attrVisitor); + indent(-1); + } + } + + public void printFileObject(String label, FileObject fo) { + if (fo == null) { + printNull(label); + } else { + printString(label, fo.getName()); + } + } + + protected void printImplClass(T item, Class stdImplClass) { + if (item.getClass() != stdImplClass) + printString("impl", item.getClass().getName()); + } + + public void printInt(String label, int i) { + printString(label, String.valueOf(i)); + } + + public void printList(String label, List list) { + if (list == null) { + printNull(label); + } else if (!list.isEmpty() || showEmptyItems) { + printString(label, "[" + list.size() + "]"); + + indent(+1); + int i = 0; + for (Object item: list) { + printObject(String.valueOf(i++), item, Details.FULL); + } + indent(-1); + } + } + + public void printName(String label, Name name) { + if (name == null) { + printNull(label); + } else { + printString(label, name.toString()); + } + } + + public void printNull(String label) { + if (showNulls) + printString(label, NULL); + } + + protected void printObject(String label, Object item, Details details) { + if (item == null) { + printNull(label); + } else if (item instanceof Attribute) { + printAttribute(label, (Attribute) item); + } else if (item instanceof Symbol) { + printSymbol(label, (Symbol) item, details); + } else if (item instanceof Type) { + printType(label, (Type) item, details); + } else if (item instanceof JCTree) { + printTree(label, (JCTree) item); + } else if (item instanceof List) { + printList(label, (List) item); + } else if (item instanceof Name) { + printName(label, (Name) item); + } else { + printString(label, String.valueOf(item)); + } + } + + public void printScope(String label, Scope scope) { + printScope(label, scope, Details.FULL); + } + + public void printScope(String label, Scope scope, Details details) { + if (scope == null) { + printNull(label); + } else { + switch (details) { + case SUMMARY: { + indent(); + out.print(label); + out.print(": ["); + String sep = ""; + for (Symbol sym: scope.getElements()) { + out.print(sep); + out.print(sym.name); + sep = ","; + } + out.println("]"); + break; + } + + case FULL: { + indent(); + out.println(label); + + indent(+1); + printImplClass(scope, Scope.class); + printSymbol("owner", scope.owner, Details.SUMMARY); + printScope("next", scope.next, Details.SUMMARY); + printObject("shared", getField(scope, Scope.class, "shared"), Details.SUMMARY); + if (scope instanceof CompoundScope) { + printObject("subScopes", + getField(scope, CompoundScope.class, "subScopes"), + Details.FULL); + } else { + for (Symbol sym : scope.getElements()) { + printSymbol(sym.name.toString(), sym, Details.SUMMARY); + } + } + indent(-1); + break; + } + } + } + } + + public void printSource(String label, JCTree tree) { + printString(label, Pretty.toSimpleString(tree, maxSrcLength)); + } + + public void printString(String label, String text) { + indent(); + out.print(label); + out.print(": "); + out.print(text); + out.println(); + } + + public void printSymbol(String label, Symbol symbol) { + printSymbol(label, symbol, Details.FULL); + } + + protected void printSymbol(String label, Symbol sym, Details details) { + if (sym == null) { + printNull(label); + } else { + switch (details) { + case SUMMARY: + printString(label, toString(sym)); + break; + + case FULL: + indent(); + out.print(label); + out.println(": " + String.format("0x%x", sym.kind) + + "--" + Kinds.kindName(sym).name() + + " " + sym.getKind() + + " " + sym.name + + " " + String.format("#%x", sym.hashCode())); + + indent(+1); + if (showSrc) { + JCTree tree = (JCTree) trees.getTree(sym); + if (tree != null) + printSource("src", tree); + } + printString("flags", String.format("0x%x--%s", + sym.flags_field, Flags.toString(sym.flags_field))); + printObject("completer", sym.completer, Details.SUMMARY); // what if too long? + printSymbol("owner", sym.owner, Details.SUMMARY); + printType("type", sym.type, Details.SUMMARY); + printType("erasure", sym.erasure_field, Details.SUMMARY); + sym.accept(symVisitor, true); + printAnnotations("annotations", sym.annotations, Details.SUMMARY); + indent(-1); + } + } + } + + protected String toString(Symbol sym) { + return (printer != null) ? printer.visit(sym, locale) : String.valueOf(sym); + } + + protected void printTree(String label, JCTree tree) { + if (tree == null) { + printNull(label); + } else { + indent(); + out.print(label + ": " + tree.getTag()); + if (showPositions) { + // We can always get start position, but to get end position + // and/or line+offset, we would need a JCCompilationUnit + out.print(" pos:" + tree.pos); + } + if (showTreeTypes && tree.type != null) + out.print(" type:" + toString(tree.type)); + Symbol sym; + if (showTreeSymbols && (sym = TreeInfo.symbolFor(tree)) != null) + out.print(" sym:" + toString(sym)); + out.println(); + + indent(+1); + if (showSrc) { + indent(); + out.println("src: " + Pretty.toSimpleString(tree, maxSrcLength)); + } + tree.accept(treeVisitor); + indent(-1); + } + } + + public void printType(String label, Type type) { + printType(label, type, Details.FULL); + } + + protected void printType(String label, Type type, Details details) { + if (type == null) + printNull(label); + else { + switch (details) { + case SUMMARY: + printString(label, toString(type)); + break; + + case FULL: + indent(); + out.print(label); + out.println(": " + type.getTag() + + " " + String.format("#%x", type.hashCode())); + + indent(+1); + printSymbol("tsym", type.tsym, Details.SUMMARY); + printObject("constValue", type.constValue(), Details.SUMMARY); + type.accept(typeVisitor, true); + indent(-1); + } + } + } + + protected String toString(Type type) { + return (printer != null) ? printer.visit(type, locale) : String.valueOf(type); + } + + private int indent = 0; + + protected void indent() { + for (int i = 0; i < indent; i++) { + out.print(" "); + } + } + + protected void indent(int n) { + indent += n; + } + + protected Object getField(Object o, Class clazz, String name) { + try { + Field f = clazz.getDeclaredField(name); + boolean prev = f.isAccessible(); + f.setAccessible(true); + try { + return f.get(o); + } finally { + f.setAccessible(prev); + } + } catch (ReflectiveOperationException e) { + return e; + } catch (SecurityException e) { + return e; + } + } + + // + + // + + protected JCTree.Visitor treeVisitor = new TreeVisitor(); + + /** + * Default visitor class for JCTree (AST) objects. + */ + public class TreeVisitor extends JCTree.Visitor { + @Override + public void visitTopLevel(JCCompilationUnit tree) { + printList("packageAnnotations", tree.packageAnnotations); + printTree("pid", tree.pid); + printList("defs", tree.defs); + } + + @Override + public void visitImport(JCImport tree) { + printTree("qualid", tree.qualid); + } + + @Override + public void visitClassDef(JCClassDecl tree) { + printName("name", tree.name); + printTree("mods", tree.mods); + printList("typarams", tree.typarams); + printTree("extending", tree.extending); + printList("implementing", tree.implementing); + printList("defs", tree.defs); + } + + @Override + public void visitMethodDef(JCMethodDecl tree) { + printName("name", tree.name); + printTree("mods", tree.mods); + printTree("restype", tree.restype); + printList("typarams", tree.typarams); + printTree("recvparam", tree.recvparam); + printList("params", tree.params); + printList("thrown", tree.thrown); + printTree("defaultValue", tree.defaultValue); + printTree("body", tree.body); + } + + @Override + public void visitVarDef(JCVariableDecl tree) { + printName("name", tree.name); + printTree("mods", tree.mods); + printTree("vartype", tree.vartype); + printTree("init", tree.init); + } + + @Override + public void visitSkip(JCSkip tree) { + } + + @Override + public void visitBlock(JCBlock tree) { + printList("stats", tree.stats); + } + + @Override + public void visitDoLoop(JCDoWhileLoop tree) { + printTree("body", tree.body); + printTree("cond", tree.cond); + } + + @Override + public void visitWhileLoop(JCWhileLoop tree) { + printTree("cond", tree.cond); + printTree("body", tree.body); + } + + @Override + public void visitForLoop(JCForLoop tree) { + printList("init", tree.init); + printTree("cond", tree.cond); + printList("step", tree.step); + printTree("body", tree.body); + } + + @Override + public void visitForeachLoop(JCEnhancedForLoop tree) { + printTree("var", tree.var); + printTree("expr", tree.expr); + printTree("body", tree.body); + } + + @Override + public void visitLabelled(JCLabeledStatement tree) { + printTree("body", tree.body); + } + + @Override + public void visitSwitch(JCSwitch tree) { + printTree("selector", tree.selector); + printList("cases", tree.cases); + } + + @Override + public void visitCase(JCCase tree) { + printTree("pat", tree.pat); + printList("stats", tree.stats); + } + + @Override + public void visitSynchronized(JCSynchronized tree) { + printTree("lock", tree.lock); + printTree("body", tree.body); + } + + @Override + public void visitTry(JCTry tree) { + printList("resources", tree.resources); + printTree("body", tree.body); + printList("catchers", tree.catchers); + printTree("finalizer", tree.finalizer); + } + + @Override + public void visitCatch(JCCatch tree) { + printTree("param", tree.param); + printTree("body", tree.body); + } + + @Override + public void visitConditional(JCConditional tree) { + printTree("cond", tree.cond); + printTree("truepart", tree.truepart); + printTree("falsepart", tree.falsepart); + } + + @Override + public void visitIf(JCIf tree) { + printTree("cond", tree.cond); + printTree("thenpart", tree.thenpart); + printTree("elsepart", tree.elsepart); + } + + @Override + public void visitExec(JCExpressionStatement tree) { + printTree("expr", tree.expr); + } + + @Override + public void visitBreak(JCBreak tree) { + printName("label", tree.label); + } + + @Override + public void visitContinue(JCContinue tree) { + printName("label", tree.label); + } + + @Override + public void visitReturn(JCReturn tree) { + printTree("expr", tree.expr); + } + + @Override + public void visitThrow(JCThrow tree) { + printTree("expr", tree.expr); + } + + @Override + public void visitAssert(JCAssert tree) { + printTree("cond", tree.cond); + printTree("detail", tree.detail); + } + + @Override + public void visitApply(JCMethodInvocation tree) { + printList("typeargs", tree.typeargs); + printTree("meth", tree.meth); + printList("args", tree.args); + } + + @Override + public void visitNewClass(JCNewClass tree) { + printTree("encl", tree.encl); + printList("typeargs", tree.typeargs); + printTree("clazz", tree.clazz); + printList("args", tree.args); + printTree("def", tree.def); + } + + @Override + public void visitNewArray(JCNewArray tree) { + printList("annotations", tree.annotations); + printTree("elemtype", tree.elemtype); + printList("dims", tree.dims); + printList("dimAnnotations", tree.dimAnnotations); + printList("elems", tree.elems); + } + + @Override + public void visitLambda(JCLambda tree) { + printTree("body", tree.body); + printList("params", tree.params); + } + + @Override + public void visitParens(JCParens tree) { + printTree("expr", tree.expr); + } + + @Override + public void visitAssign(JCAssign tree) { + printTree("lhs", tree.lhs); + printTree("rhs", tree.rhs); + } + + @Override + public void visitAssignop(JCAssignOp tree) { + printTree("lhs", tree.lhs); + printTree("rhs", tree.rhs); + } + + @Override + public void visitUnary(JCUnary tree) { + printTree("arg", tree.arg); + } + + @Override + public void visitBinary(JCBinary tree) { + printTree("lhs", tree.lhs); + printTree("rhs", tree.rhs); + } + + @Override + public void visitTypeCast(JCTypeCast tree) { + printTree("clazz", tree.clazz); + printTree("expr", tree.expr); + } + + @Override + public void visitTypeTest(JCInstanceOf tree) { + printTree("expr", tree.expr); + printTree("clazz", tree.clazz); + } + + @Override + public void visitIndexed(JCArrayAccess tree) { + printTree("indexed", tree.indexed); + printTree("index", tree.index); + } + + @Override + public void visitSelect(JCFieldAccess tree) { + printTree("selected", tree.selected); + } + + @Override + public void visitReference(JCMemberReference tree) { + printTree("expr", tree.expr); + printList("typeargs", tree.typeargs); + } + + @Override + public void visitIdent(JCIdent tree) { + printName("name", tree.name); + } + + @Override + public void visitLiteral(JCLiteral tree) { + printString("value", Pretty.toSimpleString(tree, 32)); + } + + @Override + public void visitTypeIdent(JCPrimitiveTypeTree tree) { + printString("typetag", tree.typetag.name()); + } + + @Override + public void visitTypeArray(JCArrayTypeTree tree) { + printTree("elemtype", tree.elemtype); + } + + @Override + public void visitTypeApply(JCTypeApply tree) { + printTree("clazz", tree.clazz); + printList("arguments", tree.arguments); + } + + @Override + public void visitTypeUnion(JCTypeUnion tree) { + printList("alternatives", tree.alternatives); + } + + @Override + public void visitTypeIntersection(JCTypeIntersection tree) { + printList("bounds", tree.bounds); + } + + @Override + public void visitTypeParameter(JCTypeParameter tree) { + printName("name", tree.name); + printList("annotations", tree.annotations); + printList("bounds", tree.bounds); + } + + @Override + public void visitWildcard(JCWildcard tree) { + printTree("kind", tree.kind); + printTree("inner", tree.inner); + } + + @Override + public void visitTypeBoundKind(TypeBoundKind tree) { + printString("kind", tree.kind.name()); + } + + @Override + public void visitModifiers(JCModifiers tree) { + printList("annotations", tree.annotations); + printString("flags", String.valueOf(Flags.asFlagSet(tree.flags))); + } + + @Override + public void visitAnnotation(JCAnnotation tree) { + printTree("annotationType", tree.annotationType); + printList("args", tree.args); + } + + @Override + public void visitAnnotatedType(JCAnnotatedType tree) { + printList("annotations", tree.annotations); + printTree("underlyingType", tree.underlyingType); + } + + @Override + public void visitErroneous(JCErroneous tree) { + printList("errs", tree.errs); + } + + @Override + public void visitLetExpr(LetExpr tree) { + printList("defs", tree.defs); + printTree("expr", tree.expr); + } + + @Override + public void visitTree(JCTree tree) { + Assert.error(); + } + } + + // + + // + + protected Symbol.Visitor symVisitor = new SymbolVisitor(); + + /** + * Default visitor class for Symbol objects. + * Note: each visitXYZ method ends by calling the corresponding + * visit method for its superclass. + */ + class SymbolVisitor implements Symbol.Visitor { + @Override + public Void visitClassSymbol(ClassSymbol sym, Boolean impl) { + if (impl) printImplClass(sym, ClassSymbol.class); + printName("fullname", sym.fullname); + printName("flatname", sym.flatname); + printScope("members", sym.members_field); + printFileObject("sourcefile", sym.sourcefile); + printFileObject("classfile", sym.classfile); + // trans-local? + // pool? + return visitTypeSymbol(sym, false); + } + + @Override + public Void visitMethodSymbol(MethodSymbol sym, Boolean impl) { + if (impl) printImplClass(sym, MethodSymbol.class); + // code + printList("params", sym.params); + printList("savedParameterNames", sym.savedParameterNames); + return visitSymbol(sym, false); + } + + @Override + public Void visitPackageSymbol(PackageSymbol sym, Boolean impl) { + if (impl) printImplClass(sym, PackageSymbol.class); + printName("fullname", sym.fullname); + printScope("members", sym.members_field); + printSymbol("package-info", sym.package_info, Details.SUMMARY); + return visitTypeSymbol(sym, false); + } + + @Override + public Void visitOperatorSymbol(OperatorSymbol sym, Boolean impl) { + if (impl) printImplClass(sym, OperatorSymbol.class); + printInt("opcode", sym.opcode); + return visitMethodSymbol(sym, false); + } + + @Override + public Void visitVarSymbol(VarSymbol sym, Boolean impl) { + if (impl) printImplClass(sym, VarSymbol.class); + printInt("pos", sym.pos); + printInt("adm", sym.adr); + // data is a private field, and the standard accessors may + // mutate it as part of lazy evaluation. Therefore, use + // reflection to get the raw data. + printObject("data", getField(sym, VarSymbol.class, "data"), Details.SUMMARY); + return visitSymbol(sym, false); + } + + @Override + public Void visitTypeSymbol(TypeSymbol sym, Boolean impl) { + if (impl) printImplClass(sym, TypeSymbol.class); + return visitSymbol(sym, false); + } + + @Override + public Void visitSymbol(Symbol sym, Boolean impl) { + if (impl) printImplClass(sym, Symbol.class); + return null; + } + } + + // + + // + + protected Type.Visitor typeVisitor = new TypeVisitor(); + + /** + * Default visitor class for Type objects. + * Note: each visitXYZ method ends by calling the corresponding + * visit method for its superclass. + */ + public class TypeVisitor implements Type.Visitor { + public Void visitAnnotatedType(AnnotatedType type, Boolean impl) { + if (impl) printImplClass(type, AnnotatedType.class); + printList("typeAnnotations", type.typeAnnotations); + printType("underlyingType", type.underlyingType, Details.FULL); + return visitType(type, false); + } + + public Void visitArrayType(ArrayType type, Boolean impl) { + if (impl) printImplClass(type, ArrayType.class); + printType("elemType", type.elemtype, Details.FULL); + return visitType(type, false); + } + + public Void visitCapturedType(CapturedType type, Boolean impl) { + if (impl) printImplClass(type, CapturedType.class); + printType("wildcard", type.wildcard, Details.FULL); + return visitTypeVar(type, false); + } + + public Void visitClassType(ClassType type, Boolean impl) { + if (impl) printImplClass(type, ClassType.class); + printType("outer", type.getEnclosingType(), Details.SUMMARY); + printList("typarams", type.typarams_field); + printList("allparams", type.allparams_field); + printType("supertype", type.supertype_field, Details.SUMMARY); + printList("interfaces", type.interfaces_field); + printList("allinterfaces", type.all_interfaces_field); + return visitType(type, false); + } + + public Void visitErrorType(ErrorType type, Boolean impl) { + if (impl) printImplClass(type, ErrorType.class); + printType("originalType", type.getOriginalType(), Details.FULL); + return visitClassType(type, false); + } + + public Void visitForAll(ForAll type, Boolean impl) { + if (impl) printImplClass(type, ForAll.class); + printList("tvars", type.tvars); + return visitDelegatedType(type); + } + + public Void visitMethodType(MethodType type, Boolean impl) { + if (impl) printImplClass(type, MethodType.class); + printList("argtypes", type.argtypes); + printType("restype", type.restype, Details.FULL); + printList("thrown", type.thrown); + return visitType(type, false); + } + + public Void visitPackageType(PackageType type, Boolean impl) { + if (impl) printImplClass(type, PackageType.class); + return visitType(type, false); + } + + public Void visitTypeVar(TypeVar type, Boolean impl) { + if (impl) printImplClass(type, TypeVar.class); + // For TypeVars (and not subtypes), the bound should always be + // null or bot. So, only print the bound for subtypes of TypeVar, + // or if the bound is (erroneously) not null or bot. + if (!type.hasTag(TypeTag.TYPEVAR) + || !(type.bound == null || type.bound.hasTag(TypeTag.BOT))) { + printType("bound", type.bound, Details.FULL); + } + printType("lower", type.lower, Details.FULL); + return visitType(type, false); + } + + public Void visitUndetVar(UndetVar type, Boolean impl) { + if (impl) printImplClass(type, UndetVar.class); + for (UndetVar.InferenceBound ib: UndetVar.InferenceBound.values()) + printList("bounds." + ib, type.getBounds(ib)); + printType("inst", type.inst, Details.SUMMARY); + return visitDelegatedType(type); + } + + public Void visitWildcardType(WildcardType type, Boolean impl) { + if (impl) printImplClass(type, WildcardType.class); + printType("type", type.type, Details.SUMMARY); + printString("kind", type.kind.name()); + printType("bound", type.bound, Details.SUMMARY); + return visitType(type, false); + } + + protected Void visitDelegatedType(DelegatedType type) { + printType("qtype", type.qtype, Details.FULL); + return visitType(type, false); + } + + public Void visitType(Type type, Boolean impl) { + if (impl) printImplClass(type, Type.class); + return null; + } + } + + // + + // + + protected Attribute.Visitor attrVisitor = new AttributeVisitor(); + + /** + * Default visitor class for Attribute (annotation) objects. + */ + public class AttributeVisitor implements Attribute.Visitor { + + public void visitConstant(Attribute.Constant a) { + printObject("value", a.value, Details.SUMMARY); + visitAttribute(a); + } + + public void visitClass(Attribute.Class a) { + printObject("classType", a.classType, Details.SUMMARY); + visitAttribute(a); + } + + public void visitCompound(Attribute.Compound a) { + if (a instanceof Attribute.TypeCompound) { + Attribute.TypeCompound ta = (Attribute.TypeCompound) a; + // consider a custom printer? + printObject("position", ta.position, Details.SUMMARY); + } + printObject("synthesized", a.isSynthesized(), Details.SUMMARY); + printList("values", a.values); + visitAttribute(a); + } + + public void visitArray(Attribute.Array a) { + printList("values", Arrays.asList(a.values)); + visitAttribute(a); + } + + public void visitEnum(Attribute.Enum a) { + printSymbol("value", a.value, Details.SUMMARY); + visitAttribute(a); + } + + public void visitError(Attribute.Error a) { + visitAttribute(a); + } + + public void visitAttribute(Attribute a) { + printType("type", a.type, Details.SUMMARY); + } + + } + // + + // + + /** + * Utility class to invoke DPrinter from the command line. + */ + static class Main { + public static void main(String... args) throws IOException { + PrintWriter out = new PrintWriter(System.out); + try { + if (args.length == 0) + usage(out); + else + new Main().run(out, args); + } finally { + out.flush(); + } + } + + static void usage(PrintWriter out) { + out.println("Usage:"); + out.println(" java " + Main.class.getName() + " mode [options] [javac-options]"); + out.println("where options include:"); + out.println(" -before PARSE|ENTER|ANALYZE|GENERATE|ANNOTATION_PROCESSING|ANNOTATION_PROCESSING_ROUND"); + out.println(" -after PARSE|ENTER|ANALYZE|GENERATE|ANNOTATION_PROCESSING|ANNOTATION_PROCESSING_ROUND"); + out.println(" -showPositions"); + out.println(" -showSource"); + out.println(" -showTreeSymbols"); + out.println(" -showTreeTypes"); + out.println(" -hideEmptyItems"); + out.println(" -hideNulls"); + } + + void run(PrintWriter out, String... args) throws IOException { + JavaCompiler c = ToolProvider.getSystemJavaCompiler(); + StandardJavaFileManager fm = c.getStandardFileManager(null, null, null); + + // DPrinter options + final Set before = EnumSet.noneOf(TaskEvent.Kind.class); + final Set after = EnumSet.noneOf(TaskEvent.Kind.class); + boolean showPositions = false; + boolean showSource = false; + boolean showTreeSymbols = false; + boolean showTreeTypes = false; + boolean showEmptyItems = true; + boolean showNulls = true; + + // javac options + Collection options = new ArrayList(); + Collection files = new ArrayList(); + String classpath = null; + String classoutdir = null; + + final Handler h = getHandlers().get(args[0]); + if (h == null) + throw new IllegalArgumentException(args[0]); + + for (int i = 1; i < args.length; i++) { + String arg = args[i]; + if (arg.equals("-before") && i + 1 < args.length) { + before.add(getKind(args[++i])); + } else if (arg.equals("-after") && i + 1 < args.length) { + after.add(getKind(args[++i])); + } else if (arg.equals("-showPositions")) { + showPositions = true; + } else if (arg.equals("-showSource")) { + showSource = true; + } else if (arg.equals("-showTreeSymbols")) { + showTreeSymbols = true; + } else if (arg.equals("-showTreeTypes")) { + showTreeTypes = true; + } else if (arg.equals("-hideEmptyLists")) { + showEmptyItems = false; + } else if (arg.equals("-hideNulls")) { + showNulls = false; + } else if (arg.equals("-classpath") && i + 1 < args.length) { + classpath = args[++i]; + } else if (arg.equals("-d") && i + 1 < args.length) { + classoutdir = args[++i]; + } else if (arg.startsWith("-")) { + int n = c.isSupportedOption(arg); + if (n < 0) throw new IllegalArgumentException(arg); + options.add(arg); + while (n > 0) options.add(args[++i]); + } else if (arg.endsWith(".java")) { + files.add(new File(arg)); + } + } + + if (classoutdir != null) { + fm.setLocation(StandardLocation.CLASS_OUTPUT, Arrays.asList(new File(classoutdir))); + } + + if (classpath != null) { + Collection path = new ArrayList(); + for (String p: classpath.split(File.pathSeparator)) { + if (p.isEmpty()) continue; + File f = new File(p); + if (f.exists()) path.add(f); + } + fm.setLocation(StandardLocation.CLASS_PATH, path); + } + Iterable fos = fm.getJavaFileObjectsFromFiles(files); + + JavacTask task = (JavacTask) c.getTask(out, fm, null, options, null, fos); + final Trees trees = Trees.instance(task); + + final DPrinter dprinter = new DPrinter(out, trees); + dprinter.source(showSource) + .emptyItems(showEmptyItems) + .nulls(showNulls) + .positions(showPositions) + .treeSymbols(showTreeSymbols) + .treeTypes(showTreeTypes); + + if (before.isEmpty() && after.isEmpty()) { + if (h.name.equals("trees") && !showTreeSymbols && !showTreeTypes) + after.add(TaskEvent.Kind.PARSE); + else + after.add(TaskEvent.Kind.ANALYZE); + } + + task.addTaskListener(new TaskListener() { + public void started(TaskEvent e) { + if (before.contains(e.getKind())) + handle(e); + } + + public void finished(TaskEvent e) { + if (after.contains(e.getKind())) + handle(e); + } + + private void handle(TaskEvent e) { + switch (e.getKind()) { + case PARSE: + case ENTER: + h.handle(e.getSourceFile().getName(), + (JCTree) e.getCompilationUnit(), + dprinter); + break; + + default: + TypeElement elem = e.getTypeElement(); + h.handle(elem.toString(), + (JCTree) trees.getTree(elem), + dprinter); + break; + } + } + }); + + task.call(); + } + + TaskEvent.Kind getKind(String s) { + return TaskEvent.Kind.valueOf(s.toUpperCase()); + } + + static protected abstract class Handler { + final String name; + Handler(String name) { + this.name = name; + } + abstract void handle(String label, JCTree tree, DPrinter dprinter); + } + + Map getHandlers() { + Map map = new HashMap(); + for (Handler h: defaultHandlers) { + map.put(h.name, h); + } + return map; + } + + protected final Handler[] defaultHandlers = { + new Handler("trees") { + @Override + void handle(String name, JCTree tree, DPrinter dprinter) { + dprinter.printTree(name, tree); + dprinter.out.println(); + } + }, + + new Handler("symbols") { + @Override + void handle(String name, JCTree tree, final DPrinter dprinter) { + TreeScanner ds = new TreeScanner() { + @Override + public void visitClassDef(JCClassDecl tree) { + visitDecl(tree, tree.sym); + super.visitClassDef(tree); + } + + @Override + public void visitMethodDef(JCMethodDecl tree) { + visitDecl(tree, tree.sym); + super.visitMethodDef(tree); + } + + @Override + public void visitVarDef(JCVariableDecl tree) { + visitDecl(tree, tree.sym); + super.visitVarDef(tree); + } + + void visitDecl(JCTree tree, Symbol sym) { + dprinter.printSymbol(sym.name.toString(), sym); + dprinter.out.println(); + } + }; + ds.scan(tree); + } + }, + + new Handler("types") { + @Override + void handle(String name, JCTree tree, final DPrinter dprinter) { + TreeScanner ts = new TreeScanner() { + @Override + public void scan(JCTree tree) { + if (tree == null) { + return; + } + if (tree.type != null) { + String label = Pretty.toSimpleString(tree); + dprinter.printType(label, tree.type); + dprinter.out.println(); + } + super.scan(tree); + } + }; + ts.scan(tree); + } + } + }; + } + + // + +} From 34e17268605994c714d5e02c25da4d5b37df96f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joel=20Borggr=C3=A9n-Franck?= Date: Thu, 31 Jan 2013 10:10:34 +0100 Subject: [PATCH 115/210] 8005712: Simplify support for repeating annotations in j.l.r.AnnotatedElement 8004919: AnnotationSupport uses possibly half-constructed AnnotationType instances Implements the simplified semantics for repeating annotations and removes the incorrect obtaining of an AnnotationType Reviewed-by: darcy, abuckley --- jdk/src/share/classes/java/lang/Class.java | 20 +-- jdk/src/share/classes/java/lang/System.java | 4 - .../java/lang/reflect/AnnotatedElement.java | 54 +++++-- .../classes/java/lang/reflect/Executable.java | 6 +- .../classes/java/lang/reflect/Field.java | 5 +- .../classes/java/lang/reflect/Parameter.java | 3 +- .../classes/sun/misc/JavaLangAccess.java | 5 - .../reflect/annotation/AnnotationSupport.java | 143 ++++-------------- .../RepeatedUnitTest.java | 23 ++- .../subpackage/Containee.java | 3 +- .../subpackage/Container.java | 3 +- .../subpackage/InheritedContainee.java | 3 +- .../subpackage/InheritedContainer.java | 3 +- 13 files changed, 98 insertions(+), 177 deletions(-) diff --git a/jdk/src/share/classes/java/lang/Class.java b/jdk/src/share/classes/java/lang/Class.java index 87f78530899..31e2294ebf6 100644 --- a/jdk/src/share/classes/java/lang/Class.java +++ b/jdk/src/share/classes/java/lang/Class.java @@ -3075,11 +3075,12 @@ public final * @throws NullPointerException {@inheritDoc} * @since 1.5 */ + @SuppressWarnings("unchecked") public A getAnnotation(Class annotationClass) { Objects.requireNonNull(annotationClass); initAnnotationsIfNecessary(); - return AnnotationSupport.getOneAnnotation(annotations, annotationClass); + return (A) annotations.get(annotationClass); } /** @@ -3108,18 +3109,19 @@ public final */ public Annotation[] getAnnotations() { initAnnotationsIfNecessary(); - return AnnotationSupport.unpackToArray(annotations); + return AnnotationParser.toArray(annotations); } /** * @throws NullPointerException {@inheritDoc} * @since 1.8 */ + @SuppressWarnings("unchecked") public A getDeclaredAnnotation(Class annotationClass) { Objects.requireNonNull(annotationClass); initAnnotationsIfNecessary(); - return AnnotationSupport.getOneAnnotation(declaredAnnotations, annotationClass); + return (A) declaredAnnotations.get(annotationClass); } /** @@ -3138,17 +3140,7 @@ public final */ public Annotation[] getDeclaredAnnotations() { initAnnotationsIfNecessary(); - return AnnotationSupport.unpackToArray(declaredAnnotations); - } - - /** Returns one "directly" present annotation or null */ - A getDirectDeclaredAnnotation(Class annotationClass) { - Objects.requireNonNull(annotationClass); - - initAnnotationsIfNecessary(); - @SuppressWarnings("unchecked") // TODO check safe - A ret = (A)declaredAnnotations.get(annotationClass); - return ret; + return AnnotationParser.toArray(declaredAnnotations); } // Annotations cache diff --git a/jdk/src/share/classes/java/lang/System.java b/jdk/src/share/classes/java/lang/System.java index d901e992b9a..45ea7190ae8 100644 --- a/jdk/src/share/classes/java/lang/System.java +++ b/jdk/src/share/classes/java/lang/System.java @@ -25,7 +25,6 @@ package java.lang; import java.io.*; -import java.lang.annotation.Annotation; import java.lang.reflect.Executable; import java.util.Properties; import java.util.PropertyPermission; @@ -1197,9 +1196,6 @@ public final class System { public AnnotationType getAnnotationType(Class klass) { return klass.getAnnotationType(); } - public A getDirectDeclaredAnnotation(Class klass, Class anno) { - return klass.getDirectDeclaredAnnotation(anno); - } public byte[] getRawClassTypeAnnotations(Class klass) { return klass.getRawTypeAnnotations(); } diff --git a/jdk/src/share/classes/java/lang/reflect/AnnotatedElement.java b/jdk/src/share/classes/java/lang/reflect/AnnotatedElement.java index 58a07350f36..e7de9429b0c 100644 --- a/jdk/src/share/classes/java/lang/reflect/AnnotatedElement.java +++ b/jdk/src/share/classes/java/lang/reflect/AnnotatedElement.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2013, 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 @@ -35,6 +35,24 @@ import java.lang.annotation.Annotation; * arrays returned by accessors for array-valued enum members; it will * have no affect on the arrays returned to other callers. * + *

An annotation A is directly present on an element E if the + * RuntimeVisibleAnnotations or RuntimeVisibleParameterAnnotations attribute + * associated with E either: + *

+ * + *

An annotation A is present on an element E if either: + *

    + *
  • A is directly present on E; or + *
  • There are no annotations of A's type which are directly present + * on E, and E is a class, and A's type is inheritable (JLS 9.6.3.3), and A is + * present on the superclass of E + *
+ * *

If an annotation returned by a method in this interface contains * (directly or indirectly) a {@link Class}-valued member referring to * a class that is not accessible in this VM, attempting to read the class @@ -50,7 +68,7 @@ import java.lang.annotation.Annotation; * containing annotation type of T will result in an * InvalidContainerAnnotationError. * - *

Finally, Attempting to read a member whose definition has evolved + *

Finally, attempting to read a member whose definition has evolved * incompatibly will result in a {@link * java.lang.annotation.AnnotationTypeMismatchException} or an * {@link java.lang.annotation.IncompleteAnnotationException}. @@ -70,6 +88,9 @@ public interface AnnotatedElement { * is present on this element, else false. This method * is designed primarily for convenient access to marker annotations. * + *

The truth value returned by this method is equivalent to: + * {@code getAnnotation(annotationClass) != null} + * * @param annotationClass the Class object corresponding to the * annotation type * @return true if an annotation for the specified annotation @@ -110,12 +131,15 @@ public interface AnnotatedElement { T[] getAnnotations(Class annotationClass); /** - * Returns all annotations present on this element. (Returns an array - * of length zero if this element has no annotations.) The caller of - * this method is free to modify the returned array; it will have no - * effect on the arrays returned to other callers. + * Returns annotations that are present on this element. * - * @return all annotations present on this element + * If there are no annotations present on this element, the return + * value is an array of length 0. + * + * The caller of this method is free to modify the returned array; it will + * have no effect on the arrays returned to other callers. + * + * @return annotations present on this element * @since 1.5 */ Annotation[] getAnnotations(); @@ -157,14 +181,16 @@ public interface AnnotatedElement { T[] getDeclaredAnnotations(Class annotationClass); /** - * Returns all annotations that are directly present on this - * element. This method ignores inherited annotations. (Returns - * an array of length zero if no annotations are directly present - * on this element.) The caller of this method is free to modify - * the returned array; it will have no effect on the arrays - * returned to other callers. + * Returns annotations that are directly present on this element. + * This method ignores inherited annotations. * - * @return All annotations directly present on this element + * If there are no annotations directly present on this element, + * the return value is an array of length 0. + * + * The caller of this method is free to modify the returned array; it will + * have no effect on the arrays returned to other callers. + * + * @return annotations directly present on this element * @since 1.5 */ Annotation[] getDeclaredAnnotations(); diff --git a/jdk/src/share/classes/java/lang/reflect/Executable.java b/jdk/src/share/classes/java/lang/reflect/Executable.java index b9ed7310a4d..ad1a5808632 100644 --- a/jdk/src/share/classes/java/lang/reflect/Executable.java +++ b/jdk/src/share/classes/java/lang/reflect/Executable.java @@ -26,7 +26,6 @@ package java.lang.reflect; import java.lang.annotation.*; -import java.util.Collections; import java.util.Map; import java.util.Objects; import sun.reflect.annotation.AnnotationParser; @@ -438,8 +437,7 @@ public abstract class Executable extends AccessibleObject */ public T getAnnotation(Class annotationClass) { Objects.requireNonNull(annotationClass); - - return AnnotationSupport.getOneAnnotation(declaredAnnotations(), annotationClass); + return annotationClass.cast(declaredAnnotations().get(annotationClass)); } /** @@ -457,7 +455,7 @@ public abstract class Executable extends AccessibleObject * {@inheritDoc} */ public Annotation[] getDeclaredAnnotations() { - return AnnotationSupport.unpackToArray(declaredAnnotations()); + return AnnotationParser.toArray(declaredAnnotations()); } private transient Map, Annotation> declaredAnnotations; diff --git a/jdk/src/share/classes/java/lang/reflect/Field.java b/jdk/src/share/classes/java/lang/reflect/Field.java index d2502efb4dd..df38832eb15 100644 --- a/jdk/src/share/classes/java/lang/reflect/Field.java +++ b/jdk/src/share/classes/java/lang/reflect/Field.java @@ -1021,8 +1021,7 @@ class Field extends AccessibleObject implements Member { */ public T getAnnotation(Class annotationClass) { Objects.requireNonNull(annotationClass); - - return AnnotationSupport.getOneAnnotation(declaredAnnotations(), annotationClass); + return annotationClass.cast(declaredAnnotations().get(annotationClass)); } /** @@ -1040,7 +1039,7 @@ class Field extends AccessibleObject implements Member { * {@inheritDoc} */ public Annotation[] getDeclaredAnnotations() { - return AnnotationSupport.unpackToArray(declaredAnnotations()); + return AnnotationParser.toArray(declaredAnnotations()); } private transient Map, Annotation> declaredAnnotations; diff --git a/jdk/src/share/classes/java/lang/reflect/Parameter.java b/jdk/src/share/classes/java/lang/reflect/Parameter.java index 6eed6926be0..4fda579c5fc 100644 --- a/jdk/src/share/classes/java/lang/reflect/Parameter.java +++ b/jdk/src/share/classes/java/lang/reflect/Parameter.java @@ -233,8 +233,7 @@ public final class Parameter implements AnnotatedElement { */ public T getAnnotation(Class annotationClass) { Objects.requireNonNull(annotationClass); - - return AnnotationSupport.getOneAnnotation(declaredAnnotations(), annotationClass); + return annotationClass.cast(declaredAnnotations().get(annotationClass)); } /** diff --git a/jdk/src/share/classes/sun/misc/JavaLangAccess.java b/jdk/src/share/classes/sun/misc/JavaLangAccess.java index 1624d67f4a9..db8d8213179 100644 --- a/jdk/src/share/classes/sun/misc/JavaLangAccess.java +++ b/jdk/src/share/classes/sun/misc/JavaLangAccess.java @@ -97,9 +97,4 @@ public interface JavaLangAccess { * Returns the ith StackTraceElement for the given throwable. */ StackTraceElement getStackTraceElement(Throwable t, int i); - - /** - * Returns a directly present annotation. - */ - public A getDirectDeclaredAnnotation(Class klass, Class anno); } diff --git a/jdk/src/share/classes/sun/reflect/annotation/AnnotationSupport.java b/jdk/src/share/classes/sun/reflect/annotation/AnnotationSupport.java index 3046792b161..5ca88f90202 100644 --- a/jdk/src/share/classes/sun/reflect/annotation/AnnotationSupport.java +++ b/jdk/src/share/classes/sun/reflect/annotation/AnnotationSupport.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2013, 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 @@ -27,63 +27,29 @@ package sun.reflect.annotation; import java.lang.annotation.*; import java.lang.reflect.*; -import java.util.Arrays; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Map; -import java.util.Objects; -import sun.reflect.Reflection; -import sun.misc.JavaLangAccess; public final class AnnotationSupport { - private static final JavaLangAccess javaLangAccess = sun.misc.SharedSecrets.getJavaLangAccess(); - - /** - * Finds and returns _one_ annotation of the type indicated by - * {@code annotationClass} from the {@code Map} {@code - * annotationMap}. Looks into containers of the {@code - * annotationClass} (as specified by an the {@code - * annotationClass} type being meta-annotated with an {@code - * ContainedBy} annotation). - * - * @param annotationMap the {@code Map} used to store annotations and indexed by their type - * @param annotationClass the type of annotation to search for - * - * @return in instance of {@code annotationClass} or {@code null} if none were found - */ - public static A getOneAnnotation(final Map, Annotation> annotationMap, - final Class annotationClass) { - @SuppressWarnings("unchecked") - final A candidate = (A)annotationMap.get(annotationClass); - if (candidate != null) { - return candidate; - } - - final Class containerClass = getContainer(annotationClass); - if (containerClass != null) { - return unpackOne(annotationMap.get(containerClass), annotationClass); - } - - return null; // found none - } - /** * Finds and returns all annotation of the type indicated by * {@code annotationClass} from the {@code Map} {@code * annotationMap}. Looks into containers of the {@code * annotationClass} (as specified by an the {@code * annotationClass} type being meta-annotated with an {@code - * ContainedBy} annotation). + * Repeatable} annotation). * * @param annotationMap the {@code Map} used to store annotations indexed by their type * @param annotationClass the type of annotation to search for * * @return an array of instances of {@code annotationClass} or an empty array if none were found */ - public static A[] getMultipleAnnotations(final Map, Annotation> annotationMap, - final Class annotationClass) { - final ArrayList res = new ArrayList(); + public static A[] getMultipleAnnotations( + final Map, Annotation> annotationMap, + final Class annotationClass) { + final List res = new ArrayList(); @SuppressWarnings("unchecked") final A candidate = (A)annotationMap.get(annotationClass); @@ -101,49 +67,10 @@ public final class AnnotationSupport { return res.isEmpty() ? emptyTemplateArray : res.toArray(emptyTemplateArray); } - /** - * Unpacks the {@code annotationMap} parameter into an array of - * {@code Annotation}s. This method will unpack all repeating - * annotations containers (once). An annotation type is marked as a - * container by meta-annotating it the with the {@code - * ContainerFor} annotation. - * - * @param annotationMap the {@code Map} from where the annotations are unpacked - * - * @return an array of Annotation - */ - public static Annotation[] unpackToArray(Map, Annotation> annotationMap) { - List res = new ArrayList<>(); - for (Map.Entry, Annotation> e : annotationMap.entrySet()) { - Class annotationClass = e.getKey(); - Annotation annotationInstance = e.getValue(); - Class containee = getContainee(e.getKey()); - boolean isContainer = javaLangAccess.getDirectDeclaredAnnotation(annotationClass, ContainerFor.class) != null; - - if (isContainer) { - res.addAll(unpackAll(annotationInstance, containee)); - } else { - res.add(annotationInstance); - } - } - - return res.isEmpty() - ? AnnotationParser.getEmptyAnnotationArray() - : res.toArray(AnnotationParser.getEmptyAnnotationArray()); - } - /** Helper to get the container, or null if none, of an annotation. */ private static Class getContainer(Class annotationClass) { - ContainedBy containerAnnotation = - javaLangAccess.getDirectDeclaredAnnotation(annotationClass, ContainedBy.class); - return (containerAnnotation == null) ? null : containerAnnotation.value(); - } - - /** Helper to get the containee, or null if this isn't a container, of a possible container annotation. */ - private static Class getContainee(Class annotationClass) { - ContainerFor containerAnnotation = - javaLangAccess.getDirectDeclaredAnnotation(annotationClass, ContainerFor.class); - return (containerAnnotation == null) ? null : containerAnnotation.value(); + Repeatable containingAnnotation = annotationClass.getDeclaredAnnotation(Repeatable.class); + return (containingAnnotation == null) ? null : containingAnnotation.value(); } /** Reflectively look up and get the returned array from the the @@ -156,14 +83,15 @@ public final class AnnotationSupport { // value element. Get the AnnotationType, get the "value" element // and invoke it to get the contents. - Class containerClass = containerInstance.annotationType(); - AnnotationType annoType = javaLangAccess.getAnnotationType(containerClass); + Class containerClass = containerInstance.annotationType(); + AnnotationType annoType = AnnotationType.getInstance(containerClass); if (annoType == null) throw new InvalidContainerAnnotationError(containerInstance + " is an invalid container for repeating annotations"); Method m = annoType.members().get("value"); if (m == null) - throw new InvalidContainerAnnotationError(containerInstance + " is an invalid container for repeating annotations"); + throw new InvalidContainerAnnotationError(containerInstance + + " is an invalid container for repeating annotations"); m.setAccessible(true); @SuppressWarnings("unchecked") // not provably safe, but we catch the ClassCastException @@ -175,32 +103,11 @@ public final class AnnotationSupport { IllegalArgumentException | // parameters doesn't match InvocationTargetException | // the value method threw an exception ClassCastException e) { // well, a cast failed ... - throw new InvalidContainerAnnotationError(containerInstance + " is an invalid container for repeating annotations", - e, - containerInstance, - null); - } - } - - /* Sanity check type of and return the first annotation instance - * of type {@code annotationClass} from {@code - * containerInstance}. - */ - private static A unpackOne(Annotation containerInstance, Class annotationClass) { - if (containerInstance == null) { - return null; - } - - try { - return annotationClass.cast(getValueArray(containerInstance)[0]); - } catch (ArrayIndexOutOfBoundsException | // empty array - ClassCastException | // well, a cast failed ... - NullPointerException e) { // can this NP? for good meassure - throw new InvalidContainerAnnotationError(String.format("%s is an invalid container for repeating annotations of type: %s", - containerInstance, annotationClass), - e, - containerInstance, - annotationClass); + throw new InvalidContainerAnnotationError( + containerInstance + " is an invalid container for repeating annotations", + e, + containerInstance, + null); } } @@ -208,24 +115,26 @@ public final class AnnotationSupport { * instances of type {@code annotationClass} from {@code * containerInstance}. */ - private static List unpackAll(Annotation containerInstance, Class annotationClass) { + private static List unpackAll(Annotation containerInstance, + Class annotationClass) { if (containerInstance == null) { return Collections.emptyList(); // container not present } try { A[] a = getValueArray(containerInstance); - ArrayList l = new ArrayList<>(a.length); + List l = new ArrayList<>(a.length); for (int i = 0; i < a.length; i++) l.add(annotationClass.cast(a[i])); return l; } catch (ClassCastException | NullPointerException e) { - throw new InvalidContainerAnnotationError(String.format("%s is an invalid container for repeating annotations of type: %s", - containerInstance, annotationClass), - e, - containerInstance, - annotationClass); + throw new InvalidContainerAnnotationError( + String.format("%s is an invalid container for repeating annotations of type: %s", + containerInstance, annotationClass), + e, + containerInstance, + annotationClass); } } } diff --git a/jdk/test/java/lang/annotation/repeatingAnnotations/RepeatedUnitTest.java b/jdk/test/java/lang/annotation/repeatingAnnotations/RepeatedUnitTest.java index 0d9cb59d1c4..10e3d746261 100644 --- a/jdk/test/java/lang/annotation/repeatingAnnotations/RepeatedUnitTest.java +++ b/jdk/test/java/lang/annotation/repeatingAnnotations/RepeatedUnitTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2013, 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 @@ -23,7 +23,7 @@ /* * @test - * @bug 7154390 + * @bug 7154390 8005712 * @summary Unit test for repeated annotation reflection * * @compile RepeatedUnitTest.java subpackage/package-info.java subpackage/Container.java subpackage/Containee.java subpackage/NonRepeated.java subpackage/InheritedContainee.java subpackage/InheritedContainer.java subpackage/InheritedNonRepeated.java @@ -58,7 +58,7 @@ public class RepeatedUnitTest { checkMultiplier(Me1.class.getField("foo"), 1); // METHOD - checkMultiplier(Me1.class.getDeclaredMethod("mee", null), 100); + checkMultiplier(Me1.class.getDeclaredMethod("mee", (Class[])null), 100); // INNER CLASS checkMultiplier(Me1.MiniMee.class, 1000); @@ -84,8 +84,7 @@ public class RepeatedUnitTest { static void packageRepeated(AnnotatedElement e) { Containee c = e.getAnnotation(Containee.class); - check(c.value() == 1); - + check(c == null); check(2 == countAnnotation(e, Containee.class)); c = e.getAnnotations(Containee.class)[0]; @@ -93,7 +92,7 @@ public class RepeatedUnitTest { c = e.getAnnotations(Containee.class)[1]; check(c.value() == 2); - check(2 == containsAnnotationOfType(e.getAnnotations(), Containee.class)); + check(0 == containsAnnotationOfType(e.getAnnotations(), Containee.class)); } static void packageContainer(AnnotatedElement e) { @@ -161,14 +160,26 @@ public class RepeatedUnitTest { } static void checkMultiplier(AnnotatedElement e, int m) { + // Basic sanity of non-repeating getAnnotation(Class) check(e.getAnnotation(NonRepeated.class).value() == 5 * m); + // Check count of annotations returned from getAnnotations(Class) check(4 == countAnnotation(e, Containee.class)); check(1 == countAnnotation(e, Container.class)); check(1 == countAnnotation(e, NonRepeated.class)); + // Check contents of array returned from getAnnotations(Class) check(e.getAnnotations(Containee.class)[2].value() == 3 * m); check(e.getAnnotations(NonRepeated.class)[0].value() == 5 * m); + + // Check getAnnotation(Class) + check(e.getAnnotation(Containee.class) == null); + check(e.getAnnotation(Container.class) != null); + + // Check count of annotations returned from getAnnotations() + check(0 == containsAnnotationOfType(e.getAnnotations(), Containee.class)); + check(1 == containsAnnotationOfType(e.getAnnotations(), Container.class)); + check(1 == containsAnnotationOfType(e.getAnnotations(), NonRepeated.class)); } static void check(Boolean b) { diff --git a/jdk/test/java/lang/annotation/repeatingAnnotations/subpackage/Containee.java b/jdk/test/java/lang/annotation/repeatingAnnotations/subpackage/Containee.java index c977b2e5c2d..cca790696d6 100644 --- a/jdk/test/java/lang/annotation/repeatingAnnotations/subpackage/Containee.java +++ b/jdk/test/java/lang/annotation/repeatingAnnotations/subpackage/Containee.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2013, 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 @@ -26,7 +26,6 @@ package subpackage; import java.lang.annotation.*; @Retention(RetentionPolicy.RUNTIME) -@ContainedBy(Container.class) @Repeatable(Container.class) public @interface Containee { int value(); diff --git a/jdk/test/java/lang/annotation/repeatingAnnotations/subpackage/Container.java b/jdk/test/java/lang/annotation/repeatingAnnotations/subpackage/Container.java index e8e2f05ab55..f4d370b7add 100644 --- a/jdk/test/java/lang/annotation/repeatingAnnotations/subpackage/Container.java +++ b/jdk/test/java/lang/annotation/repeatingAnnotations/subpackage/Container.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2013, 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 @@ -26,7 +26,6 @@ package subpackage; import java.lang.annotation.*; @Retention(RetentionPolicy.RUNTIME) -@ContainerFor(Containee.class) public @interface Container { Containee[] value(); } diff --git a/jdk/test/java/lang/annotation/repeatingAnnotations/subpackage/InheritedContainee.java b/jdk/test/java/lang/annotation/repeatingAnnotations/subpackage/InheritedContainee.java index 080d12ce3f5..37f44932a86 100644 --- a/jdk/test/java/lang/annotation/repeatingAnnotations/subpackage/InheritedContainee.java +++ b/jdk/test/java/lang/annotation/repeatingAnnotations/subpackage/InheritedContainee.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2013, 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 @@ -27,7 +27,6 @@ import java.lang.annotation.*; @Inherited @Retention(RetentionPolicy.RUNTIME) -@ContainedBy(InheritedContainer.class) @Repeatable(InheritedContainer.class) public @interface InheritedContainee { int value(); diff --git a/jdk/test/java/lang/annotation/repeatingAnnotations/subpackage/InheritedContainer.java b/jdk/test/java/lang/annotation/repeatingAnnotations/subpackage/InheritedContainer.java index a66af4f6ed8..bff3082520e 100644 --- a/jdk/test/java/lang/annotation/repeatingAnnotations/subpackage/InheritedContainer.java +++ b/jdk/test/java/lang/annotation/repeatingAnnotations/subpackage/InheritedContainer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2013, 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 @@ -27,7 +27,6 @@ import java.lang.annotation.*; @Inherited @Retention(RetentionPolicy.RUNTIME) -@ContainerFor(InheritedContainee.class) public @interface InheritedContainer { InheritedContainee[] value(); } From 9f5b40123d77bd6327c01f5aa16734d88107d7db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20=C3=96hrstr=C3=B6m?= Date: Thu, 31 Jan 2013 14:00:09 +0100 Subject: [PATCH 116/210] 8006872: Stop creating four jars with identical content in the new build system Reviewed-by: erikj --- common/autoconf/spec.gmk.in | 6 ++++++ common/makefiles/JavaCompilation.gmk | 12 ++++++------ common/makefiles/javadoc/Javadoc.gmk | 9 +++------ 3 files changed, 15 insertions(+), 12 deletions(-) diff --git a/common/autoconf/spec.gmk.in b/common/autoconf/spec.gmk.in index 5fde9e7cf16..ad882958d9d 100644 --- a/common/autoconf/spec.gmk.in +++ b/common/autoconf/spec.gmk.in @@ -434,6 +434,12 @@ NATIVE2ASCII=@FIXPATH@ $(BOOT_JDK)/bin/native2ascii JARSIGNER=@FIXPATH@ $(BOOT_JDK)/bin/jarsigner +# You run the new javac using the boot jdk with $(BOOT_JDK)/bin/java $(NEW_JAVAC) ... +BOOTSTRAP_JAVAC_JAR:=$(LANGTOOLS_OUTPUTDIR)/dist/bootstrap/lib/javac.jar +BOOTSTRAP_JAVAC_ARGS:="-Xbootclasspath/p:$(BOOTSTRAP_JAVAC_JAR)" -cp $(BOOTSTRAP_JAVAC_JAR) +NEW_JAVAC = $(BOOTSTRAP_JAVAC_ARGS) com.sun.tools.javac.Main +NEW_JAVADOC = $(BOOTSTRAP_JAVAC_ARGS) com.sun.tools.javadoc.Main + # Base flags for RC # Guarding this against resetting value. Legacy make files include spec multiple # times. diff --git a/common/makefiles/JavaCompilation.gmk b/common/makefiles/JavaCompilation.gmk index 59adc339779..22c199ad5b5 100644 --- a/common/makefiles/JavaCompilation.gmk +++ b/common/makefiles/JavaCompilation.gmk @@ -42,8 +42,8 @@ endif FALSE_FIND_PATTERN:=-name FILE_NAME_THAT_DOESNT_EXIST define SetupJavaCompiler - # param 1 is for example BOOT_JAVAC or NEW_JAVAC - # This is the name later used to decide which java compiler to use. + # param 1 is for example GENERATE_OLD_BYTECODE or GENERATE_NEW_JDKBYTECODE + # This is the name of the compiler setup. # param 2-9 are named args. # JVM:=The jvm used to run the javac/javah command # JAVAC:=The javac jar and bootstrap classpath changes, or just bin/javac if JVM is left out @@ -487,10 +487,10 @@ define SetupJavaCompilation # Using sjavac to compile. $1 := $$($1_ALL_COPY_TARGETS) $$($1_ALL_COPY_CLEAN_TARGETS) $$($1_BIN)/javac_state - # Create SJAVAC variable, - # expects $1_JAVAC to be "bootclasspathprepend -jar ...javac.jar" - # and it is rewritten into "bootclasspathprepend com.sun.tools.sjavac.Main" - $1_SJAVAC:=$$(word 1,$$($1_JAVAC)) -cp $$(word 3,$$($1_JAVAC)) com.sun.tools.sjavac.Main + # Create SJAVAC variable form JAVAC variable. Expects $1_JAVAC to be + # "bootclasspathprepend -cp .../javac.jar com.sun.tools.javac.Main" + # and javac is simply replaced with sjavac. + $1_SJAVAC:=$$(subst com.sun.tools.javac.Main,com.sun.tools.sjavac.Main,$$($1_JAVAC)) # Set the $1_REMOTE to spawn a background javac server. $1_REMOTE:=--server:portfile=$$($1_SJAVAC_PORTFILE),id=$1,sjavac=$$(subst $$(SPACE),%20,$$(subst $$(COMMA),%2C,$$(strip $$($1_SERVER_JVM) $$($1_SJAVAC)))) diff --git a/common/makefiles/javadoc/Javadoc.gmk b/common/makefiles/javadoc/Javadoc.gmk index 6b88a06d748..1d798120708 100644 --- a/common/makefiles/javadoc/Javadoc.gmk +++ b/common/makefiles/javadoc/Javadoc.gmk @@ -46,14 +46,11 @@ HOTSPOT_DOCS_IMPORT_PATH=$(HOTSPOT_OUTPUTDIR)/docs BUILD_NUMBER=$(JDK_BUILD_NUMBER) -BOOT_JAVA_CMD=$(JAVA) - -JAVADOC_JAR = $(LANGTOOLS_DIST)/bootstrap/lib/javadoc.jar -JAVADOC_CMD = $(BOOT_JAVA_CMD) \ +JAVADOC_CMD = $(JAVA) \ -Xmx1024m \ -Djava.awt.headless=true \ - "-Xbootclasspath/p:$(JAVADOC_JAR)" \ - -jar $(JAVADOC_JAR) -bootclasspath $(JDK_OUTPUTDIR)/classes + $(NEW_JAVADOC) \ + -bootclasspath $(JDK_OUTPUTDIR)/classes # Copyright year for beginning of Java and some of the apis # (Needed when creating the javadocs) From 45c58805e70180974a0b159732a876b8ac836e3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20=C3=96hrstr=C3=B6m?= Date: Thu, 31 Jan 2013 14:01:45 +0100 Subject: [PATCH 117/210] 8006872: Stop creating four jars with identical content in the new build system Reviewed-by: erikj --- langtools/makefiles/BuildLangtools.gmk | 27 ++++---------------------- 1 file changed, 4 insertions(+), 23 deletions(-) diff --git a/langtools/makefiles/BuildLangtools.gmk b/langtools/makefiles/BuildLangtools.gmk index 833c8654442..cd96a601e00 100644 --- a/langtools/makefiles/BuildLangtools.gmk +++ b/langtools/makefiles/BuildLangtools.gmk @@ -112,23 +112,7 @@ ifeq ($(PROPS_ARE_CREATED),yes) $(eval $(call SetupArchive,ARCHIVE_BOOTSTRAP_JAVAC,$(BUILD_BOOTSTRAP_LANGTOOLS),\ SRCS:=$(LANGTOOLS_OUTPUTDIR)/btclasses/bootstrap,\ JAR:=$(LANGTOOLS_OUTPUTDIR)/dist/bootstrap/lib/javac.jar,\ - JARMAIN:=com.sun.tools.javac.Main)) - - $(eval $(call SetupArchive,ARCHIVE_BOOTSTRAP_JAVAH,$(BUILD_BOOTSTRAP_LANGTOOLS),\ - SRCS:=$(LANGTOOLS_OUTPUTDIR)/btclasses/bootstrap,\ - JAR:=$(LANGTOOLS_OUTPUTDIR)/dist/bootstrap/lib/javah.jar,\ - JARMAIN:=com.sun.tools.javah.Main)) - - $(eval $(call SetupArchive,ARCHIVE_BOOTSTRAP_JAVAP,$(BUILD_BOOTSTRAP_LANGTOOLS),\ - SRCS:=$(LANGTOOLS_OUTPUTDIR)/btclasses/bootstrap,\ - JAR:=$(LANGTOOLS_OUTPUTDIR)/dist/bootstrap/lib/javap.jar,\ - JARMAIN:=com.sun.tools.javap.Main)) - - $(eval $(call SetupArchive,ARCHIVE_BOOTSTRAP_JAVADOC,$(BUILD_BOOTSTRAP_LANGTOOLS),\ - SRCS:=$(LANGTOOLS_OUTPUTDIR)/btclasses/bootstrap,\ - JAR:=$(LANGTOOLS_OUTPUTDIR)/dist/bootstrap/lib/javadoc.jar,\ - SUFFIXES:=.class $(RESOURCE_SUFFIXES),\ - JARMAIN:=com.sun.tools.javadoc.Main)) + SUFFIXES:=.class $(RESOURCE_SUFFIXES))) # GenStubs is used to bootstrap any dependencies from javac to the new JDK that is not # yet built. It is currently not needed but might be again in the future. The following @@ -176,7 +160,8 @@ ifeq ($(PROPS_ARE_CREATED),yes) $(eval $(call SetupJavaCompiler,GENERATE_NEWBYTECODE,\ JVM:=$(JAVA),\ JAVAC:="-Xbootclasspath/p:$(LANGTOOLS_OUTPUTDIR)/dist/bootstrap/lib/javac.jar" \ - -jar $(LANGTOOLS_OUTPUTDIR)/dist/bootstrap/lib/javac.jar,\ + -cp $(LANGTOOLS_OUTPUTDIR)/dist/bootstrap/lib/javac.jar \ + com.sun.tools.javac.Main,\ FLAGS:=-XDignore.symbol.file=true -Xlint:all$(COMMA)-deprecation -Werror,\ SERVER_DIR:=$(SJAVAC_SERVER_DIR),\ SERVER_JVM:=$(SJAVAC_SERVER_JAVA))) @@ -201,11 +186,7 @@ ifeq ($(PROPS_ARE_CREATED),yes) all: $(LANGTOOLS_OUTPUTDIR)/dist/lib/classes.jar \ $(LANGTOOLS_OUTPUTDIR)/dist/lib/src.zip \ - $(LANGTOOLS_OUTPUTDIR)/dist/bootstrap/lib/javac.jar \ - $(LANGTOOLS_OUTPUTDIR)/dist/bootstrap/lib/javah.jar \ - $(LANGTOOLS_OUTPUTDIR)/dist/bootstrap/lib/javap.jar \ - $(LANGTOOLS_OUTPUTDIR)/dist/bootstrap/lib/javadoc.jar - + $(LANGTOOLS_OUTPUTDIR)/dist/bootstrap/lib/javac.jar endif endif From 676769c08f6fec8a41af06ef97d445ffc3fbeb60 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20=C3=96hrstr=C3=B6m?= Date: Thu, 31 Jan 2013 14:02:29 +0100 Subject: [PATCH 118/210] 8006872: Stop creating four jars with identical content in the new build system Reviewed-by: erikj --- corba/makefiles/BuildCorba.gmk | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/corba/makefiles/BuildCorba.gmk b/corba/makefiles/BuildCorba.gmk index 246c5b9bcec..b177ff2d212 100644 --- a/corba/makefiles/BuildCorba.gmk +++ b/corba/makefiles/BuildCorba.gmk @@ -35,8 +35,6 @@ include MakeBase.gmk include JavaCompilation.gmk include IdlCompilation.gmk -JAVAC_JARS ?= "-Xbootclasspath/p:$(LANGTOOLS_OUTPUTDIR)/dist/bootstrap/lib/javac.jar" \ - -jar $(LANGTOOLS_OUTPUTDIR)/dist/bootstrap/lib/javac.jar # The Corba sources are old and generates a LOT of warnings. # Disable these using Xlint, until someone cares to fix them. DISABLE_CORBA_WARNINGS:=-Xlint:all,-deprecation,-unchecked,-serial,-fallthrough,-cast,-rawtypes,-static,-dep-ann @@ -46,7 +44,7 @@ DISABLE_CORBA_WARNINGS:=-Xlint:all,-deprecation,-unchecked,-serial,-fallthrough, # Thus we force the target bytecode to the boot jdk bytecode. $(eval $(call SetupJavaCompiler,GENERATE_OLDBYTECODE,\ JVM:=$(JAVA),\ - JAVAC:=$(JAVAC_JARS),\ + JAVAC:=$(NEW_JAVAC),\ FLAGS:=$(BOOT_JDK_SOURCETARGET) -bootclasspath $(BOOT_RTJAR) $(DISABLE_CORBA_WARNINGS),\ SERVER_DIR:=$(SJAVAC_SERVER_DIR),\ SERVER_JVM:=$(SJAVAC_SERVER_JAVA))) @@ -56,7 +54,7 @@ $(eval $(call SetupJavaCompiler,GENERATE_OLDBYTECODE,\ # cannot necessarily be run with the boot jdk. $(eval $(call SetupJavaCompiler,GENERATE_NEWBYTECODE,\ JVM:=$(JAVA),\ - JAVAC:=$(JAVAC_JARS),\ + JAVAC:=$(NEW_JAVAC),\ FLAGS:=-cp $(BOOT_TOOLSJAR) -XDignore.symbol.file=true $(DISABLE_CORBA_WARNINGS),\ SERVER_DIR:=$(SJAVAC_SERVER_DIR),\ SERVER_JVM:=$(SJAVAC_SERVER_JAVA))) From ba0917c5314c3318ad49b1d753a3544629824265 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20=C3=96hrstr=C3=B6m?= Date: Thu, 31 Jan 2013 14:02:44 +0100 Subject: [PATCH 119/210] 8006872: Stop creating four jars with identical content in the new build system Reviewed-by: erikj --- jaxp/makefiles/BuildJaxp.gmk | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/jaxp/makefiles/BuildJaxp.gmk b/jaxp/makefiles/BuildJaxp.gmk index e28cdf890c3..749046481a3 100644 --- a/jaxp/makefiles/BuildJaxp.gmk +++ b/jaxp/makefiles/BuildJaxp.gmk @@ -30,8 +30,6 @@ default: all include MakeBase.gmk include JavaCompilation.gmk -JAVAC_JARS ?= "-Xbootclasspath/p:$(LANGTOOLS_OUTPUTDIR)/dist/bootstrap/lib/javac.jar" \ - -jar $(LANGTOOLS_OUTPUTDIR)/dist/bootstrap/lib/javac.jar DISABLE_JAXP_WARNINGS:=-Xlint:all,-deprecation,-unchecked,-rawtypes,-cast,-serial,-dep-ann,-static,-fallthrough # The generate new bytecode uses the new compiler for to generate bytecode @@ -39,7 +37,7 @@ DISABLE_JAXP_WARNINGS:=-Xlint:all,-deprecation,-unchecked,-rawtypes,-cast,-seria # cannot necessarily be run with the boot jdk. $(eval $(call SetupJavaCompiler,GENERATE_NEWBYTECODE_DEBUG,\ JVM:=$(JAVA),\ - JAVAC:=$(JAVAC_JARS),\ + JAVAC:=$(NEW_JAVAC),\ FLAGS:=-XDignore.symbol.file=true $(DISABLE_JAXP_WARNINGS) -g,\ SERVER_DIR:=$(SJAVAC_SERVER_DIR),\ SERVER_JVM:=$(SJAVAC_SERVER_JAVA))) From c2b707c559442da77fff44e86b1849eb1032e715 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20=C3=96hrstr=C3=B6m?= Date: Thu, 31 Jan 2013 14:02:58 +0100 Subject: [PATCH 120/210] 8006872: Stop creating four jars with identical content in the new build system Reviewed-by: erikj --- jaxws/makefiles/BuildJaxws.gmk | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/jaxws/makefiles/BuildJaxws.gmk b/jaxws/makefiles/BuildJaxws.gmk index c1b092d64bc..348cba90780 100644 --- a/jaxws/makefiles/BuildJaxws.gmk +++ b/jaxws/makefiles/BuildJaxws.gmk @@ -30,8 +30,6 @@ include $(SPEC) include MakeBase.gmk include JavaCompilation.gmk -JAVAC_JARS ?= -Xbootclasspath/p:$(LANGTOOLS_OUTPUTDIR)/dist/bootstrap/lib/javac.jar \ - -jar $(LANGTOOLS_OUTPUTDIR)/dist/bootstrap/lib/javac.jar DISABLE_JAXWS_WARNINGS:=-Xlint:all,-varargs,-rawtypes,-deprecation,-unchecked,-serial,-dep-ann,-cast,-fallthrough,-static # The generate new bytecode uses the new compiler for to generate bytecode @@ -39,7 +37,7 @@ DISABLE_JAXWS_WARNINGS:=-Xlint:all,-varargs,-rawtypes,-deprecation,-unchecked,-s # cannot necessarily be run with the boot jdk. $(eval $(call SetupJavaCompiler,GENERATE_NEWBYTECODE_DEBUG,\ JVM:=$(JAVA),\ - JAVAC:=$(JAVAC_JARS),\ + JAVAC:=$(NEW_JAVAC),\ FLAGS:=-XDignore.symbol.file=true $(DISABLE_JAXWS_WARNINGS) -g,\ SERVER_DIR:=$(SJAVAC_SERVER_DIR),\ SERVER_JVM:=$(SJAVAC_SERVER_JAVA))) From 2b389730e23eb0ddc72709b25ee53228e20488c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20=C3=96hrstr=C3=B6m?= Date: Thu, 31 Jan 2013 14:03:42 +0100 Subject: [PATCH 121/210] 8006872: Stop creating four jars with identical content in the new build system Reviewed-by: erikj --- jdk/makefiles/CreateJars.gmk | 2 +- jdk/makefiles/GensrcSwing.gmk | 2 +- jdk/makefiles/Setup.gmk | 11 +++-------- 3 files changed, 5 insertions(+), 10 deletions(-) diff --git a/jdk/makefiles/CreateJars.gmk b/jdk/makefiles/CreateJars.gmk index dc93edb7e6a..fae6d52d441 100644 --- a/jdk/makefiles/CreateJars.gmk +++ b/jdk/makefiles/CreateJars.gmk @@ -836,7 +836,7 @@ EXPORTED_PRIVATE_PKGS = com.sun.servicetag \ $(IMAGES_OUTPUTDIR)/symbols/_the.symbols: $(IMAGES_OUTPUTDIR)/lib/rt.jar $(RM) -r $(IMAGES_OUTPUTDIR)/symbols/META-INF/sym $(MKDIR) -p $(IMAGES_OUTPUTDIR)/symbols/META-INF/sym - $(JAVA) $(JAVAC_JARS) \ + $(JAVA) $(NEW_JAVAC) \ -bootclasspath $(JDK_OUTPUTDIR)/classes \ -XDprocess.packages -proc:only \ -processor com.sun.tools.javac.sym.CreateSymbols \ diff --git a/jdk/makefiles/GensrcSwing.gmk b/jdk/makefiles/GensrcSwing.gmk index 7a554f26da6..9f3bff1ba41 100644 --- a/jdk/makefiles/GensrcSwing.gmk +++ b/jdk/makefiles/GensrcSwing.gmk @@ -71,7 +71,7 @@ SWINGBEAN_DEBUG_FLAG = false $(JDK_OUTPUTDIR)/gensrc_no_srczip/_the.generated_beaninfo: $(BEANS_SRC) $(JDK_OUTPUTDIR)/gensrc_no_srczip/javax/swing/SwingBeanInfoBase.java $(JDK_OUTPUTDIR)/gensrc/sun/swing/BeanInfoUtils.java $(BUILD_TOOLS) $(ECHO) Generating beaninfo $(MKDIR) -p $(JDK_OUTPUTDIR)/gensrc_no_srczip/javax/swing - $(JAVA) -Djava.awt.headless=true -jar $(JAVADOC_JARS) -doclet GenDocletBeanInfo \ + $(JAVA) -Djava.awt.headless=true $(NEW_JAVADOC) -doclet GenDocletBeanInfo \ -x $(SWINGBEAN_DEBUG_FLAG) -d $(JDK_OUTPUTDIR)/gensrc_no_srczip/javax/swing \ -t $(DOCLETSRC_DIR)/SwingBeanInfo.template -docletpath $(JDK_OUTPUTDIR)/btclasses \ -XDignore.symbol.file=true \ diff --git a/jdk/makefiles/Setup.gmk b/jdk/makefiles/Setup.gmk index 5ca687f5a1d..95e7b20f39c 100644 --- a/jdk/makefiles/Setup.gmk +++ b/jdk/makefiles/Setup.gmk @@ -23,10 +23,6 @@ # questions. # -JAVAC_JARS ?= "-Xbootclasspath/p:$(LANGTOOLS_OUTPUTDIR)/dist/bootstrap/lib/javac.jar" -jar $(LANGTOOLS_OUTPUTDIR)/dist/bootstrap/lib/javac.jar -JAVAH_JARS ?= "-Xbootclasspath/p:$(LANGTOOLS_OUTPUTDIR)/dist/bootstrap/lib/javah.jar" -jar $(LANGTOOLS_OUTPUTDIR)/dist/bootstrap/lib/javah.jar -JAVADOC_JARS ?= "-Xbootclasspath/p:$(LANGTOOLS_OUTPUTDIR)/dist/bootstrap/lib/javadoc.jar" -jar $(LANGTOOLS_OUTPUTDIR)/dist/bootstrap/lib/javadoc.jar - DISABLE_WARNINGS:=-Xlint:all,-deprecation,-unchecked,-rawtypes,-cast,-serial,-dep-ann,-static,-fallthrough,-try,-varargs,-empty,-finally # The generate old bytecode javac setup uses the new compiler to compile for the @@ -34,7 +30,7 @@ DISABLE_WARNINGS:=-Xlint:all,-deprecation,-unchecked,-rawtypes,-cast,-serial,-de # Thus we force the target bytecode to 7. $(eval $(call SetupJavaCompiler,GENERATE_OLDBYTECODE,\ JVM:=$(JAVA),\ - JAVAC:=$(JAVAC_JARS),\ + JAVAC:=$(NEW_JAVAC),\ FLAGS:=-source 7 -target 7 -bootclasspath $(BOOT_RTJAR) $(DISABLE_WARNINGS),\ SERVER_DIR:=$(SJAVAC_SERVER_DIR),\ SERVER_JVM:=$(SJAVAC_SERVER_JAVA))) @@ -43,8 +39,7 @@ $(eval $(call SetupJavaCompiler,GENERATE_OLDBYTECODE,\ # new jdk. This new bytecode might only be possible to run using the new jvm. $(eval $(call SetupJavaCompiler,GENERATE_JDKBYTECODE,\ JVM:=$(JAVA),\ - JAVAC:=$(JAVAC_JARS),\ - JAVAH:=$(JAVAH_JARS),\ + JAVAC:=$(NEW_JAVAC),\ FLAGS:=-bootclasspath $(JDK_OUTPUTDIR)/classes -source 8 -target 8 -encoding ascii -XDignore.symbol.file=true $(DISABLE_WARNINGS),\ SERVER_DIR:=$(SJAVAC_SERVER_DIR),\ SERVER_JVM:=$(SJAVAC_SERVER_JAVA))) @@ -55,7 +50,7 @@ $(eval $(call SetupJavaCompiler,GENERATE_JDKBYTECODE,\ # (it will be in "make images") therefore we use classes instead. $(eval $(call SetupJavaCompiler,GENERATE_USINGJDKBYTECODE,\ JVM:=$(JAVA),\ - JAVAC:=$(JAVAC_JARS),\ + JAVAC:=$(NEW_JAVAC),\ FLAGS:=-bootclasspath $(JDK_OUTPUTDIR)/classes $(DISABLE_WARNINGS),\ SERVER_DIR:=$(SJAVAC_SERVER_DIR),\ SERVER_JVM:=$(SJAVAC_SERVER_JAVA))) From 7d2ccf3a21a3676fbb357b52354047ced5607a73 Mon Sep 17 00:00:00 2001 From: John Cuthbertson Date: Thu, 31 Jan 2013 10:45:09 -0800 Subject: [PATCH 122/210] 8005875: G1: Kitchensink fails with ParallelGCThreads=0 Check that the concurrent marking worker gang exists in ConcurrentMark::print_worker_threads_on(). Changes were also reviewed by Vitaly Davidovich . Reviewed-by: brutisso --- .../gc_implementation/g1/concurrentMark.cpp | 8 +++-- .../gc_implementation/g1/concurrentMark.hpp | 29 ++++++++++++------- 2 files changed, 24 insertions(+), 13 deletions(-) diff --git a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp index 50821ac0cfb..b77cd155e74 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp @@ -1190,7 +1190,7 @@ void ConcurrentMark::scanRootRegions() { uint active_workers = MAX2(1U, parallel_marking_threads()); CMRootRegionScanTask task(this); - if (parallel_marking_threads() > 0) { + if (use_parallel_marking_threads()) { _parallel_workers->set_active_workers((int) active_workers); _parallel_workers->run_task(&task); } else { @@ -1226,7 +1226,7 @@ void ConcurrentMark::markFromRoots() { set_phase(active_workers, true /* concurrent */); CMConcurrentMarkingTask markingTask(this, cmThread()); - if (parallel_marking_threads() > 0) { + if (use_parallel_marking_threads()) { _parallel_workers->set_active_workers((int)active_workers); // Don't set _n_par_threads because it affects MT in proceess_strong_roots() // and the decisions on that MT processing is made elsewhere. @@ -3242,7 +3242,9 @@ void ConcurrentMark::print_summary_info() { } void ConcurrentMark::print_worker_threads_on(outputStream* st) const { - _parallel_workers->print_worker_threads_on(st); + if (use_parallel_marking_threads()) { + _parallel_workers->print_worker_threads_on(st); + } } // We take a break if someone is trying to stop the world. diff --git a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.hpp b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.hpp index 34c5601e050..6701e9f4171 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.hpp @@ -499,17 +499,26 @@ protected: } // accessor methods - uint parallel_marking_threads() { return _parallel_marking_threads; } - uint max_parallel_marking_threads() { return _max_parallel_marking_threads;} - double sleep_factor() { return _sleep_factor; } - double marking_task_overhead() { return _marking_task_overhead;} - double cleanup_sleep_factor() { return _cleanup_sleep_factor; } - double cleanup_task_overhead() { return _cleanup_task_overhead;} + uint parallel_marking_threads() const { return _parallel_marking_threads; } + uint max_parallel_marking_threads() const { return _max_parallel_marking_threads;} + double sleep_factor() { return _sleep_factor; } + double marking_task_overhead() { return _marking_task_overhead;} + double cleanup_sleep_factor() { return _cleanup_sleep_factor; } + double cleanup_task_overhead() { return _cleanup_task_overhead;} - HeapWord* finger() { return _finger; } - bool concurrent() { return _concurrent; } - uint active_tasks() { return _active_tasks; } - ParallelTaskTerminator* terminator() { return &_terminator; } + bool use_parallel_marking_threads() const { + assert(parallel_marking_threads() <= + max_parallel_marking_threads(), "sanity"); + assert((_parallel_workers == NULL && parallel_marking_threads() == 0) || + parallel_marking_threads() > 0, + "parallel workers not set up correctly"); + return _parallel_workers != NULL; + } + + HeapWord* finger() { return _finger; } + bool concurrent() { return _concurrent; } + uint active_tasks() { return _active_tasks; } + ParallelTaskTerminator* terminator() { return &_terminator; } // It claims the next available region to be scanned by a marking // task/thread. It might return NULL if the next region is empty or From b3fa7187ae4430440189921e23c59e849c56b93c Mon Sep 17 00:00:00 2001 From: David Buck Date: Thu, 31 Jan 2013 10:55:15 -0800 Subject: [PATCH 123/210] 7042126: (alt-rt) HashMap.clone implementation should be re-examined Test case for cr7042126. Issue only found in OracleJDK, but test case is valid for OpenJDK as well Reviewed-by: mduigou --- .../java/util/HashMap/HashMapCloneLeak.java | 70 +++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 jdk/test/java/util/HashMap/HashMapCloneLeak.java diff --git a/jdk/test/java/util/HashMap/HashMapCloneLeak.java b/jdk/test/java/util/HashMap/HashMapCloneLeak.java new file mode 100644 index 00000000000..2a5fcaa4f1c --- /dev/null +++ b/jdk/test/java/util/HashMap/HashMapCloneLeak.java @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2013, 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. + * + * 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. + */ + +/** + * @test + * @bug 7042126 + * @summary Verify that we do not leak contents when we clone a HashMap + * @author david.buck@oracle.com + * @run main/othervm HashMapCloneLeak + * @run main/othervm -XX:+AggressiveOpts HashMapCloneLeak + */ + +import java.util.HashMap; +import java.lang.ref.WeakReference; + +public class HashMapCloneLeak { + + static WeakReference wr = null; + + // helper method to keep testObject and map out of main method's scope + private static HashMap makeMap() { + HashMap map = new HashMap(); + Object testObject = new Object(); + wr = new WeakReference(testObject); + map.put(42, testObject); + return map; + } + + public static void main(String[] args) throws Exception { + HashMap hm = makeMap(); + hm = (HashMap)hm.clone(); + hm.clear(); + // There should no longer be a strong reference to testObject + // the WeakReference should be nulled out by GC. If not, + // we will hang here until timed out by the test harness. + Object[] chain = null; + while (wr.get() != null) { + try { + Object[] allocate = new Object[1000000]; + allocate[0] = chain; + chain = allocate; + } catch (OutOfMemoryError oome) { + chain = null; + } + System.gc(); + Thread.sleep(100); + } + } + +} From 907f0724ce28cc7a6753f1f103b9e8d30f2d5893 Mon Sep 17 00:00:00 2001 From: Xueming Shen Date: Thu, 31 Jan 2013 11:09:36 -0800 Subject: [PATCH 124/210] 8005394: Base64.Decoder/Encoder.wrap(XStream) don't throw NPE for null args passed To check null for dec/enc.wrap methods Reviewed-by: alanb --- jdk/src/share/classes/java/util/Base64.java | 2 ++ jdk/test/java/util/Base64/TestBase64.java | 4 +++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/jdk/src/share/classes/java/util/Base64.java b/jdk/src/share/classes/java/util/Base64.java index f5ff211f8d4..7a01c05e653 100644 --- a/jdk/src/share/classes/java/util/Base64.java +++ b/jdk/src/share/classes/java/util/Base64.java @@ -413,6 +413,7 @@ public class Base64 { * specified Base64 encoded format */ public OutputStream wrap(OutputStream os) { + Objects.requireNonNull(os); return new EncOutputStream(os, isURL ? toBase64URL : toBase64, newline, linemax); } @@ -866,6 +867,7 @@ public class Base64 { * byte stream */ public InputStream wrap(InputStream is) { + Objects.requireNonNull(is); return new DecInputStream(is, isURL ? fromBase64URL : fromBase64, isMIME); } diff --git a/jdk/test/java/util/Base64/TestBase64.java b/jdk/test/java/util/Base64/TestBase64.java index 6b37772d7f6..645f570b0f3 100644 --- a/jdk/test/java/util/Base64/TestBase64.java +++ b/jdk/test/java/util/Base64/TestBase64.java @@ -22,7 +22,7 @@ */ /** - * @test 4235519 8004212 + * @test 4235519 8004212 8005394 * @summary tests java.util.Base64 */ @@ -295,6 +295,7 @@ public class TestBase64 { checkNull(new Runnable() { public void run() { enc.encode(bb_null); }}); checkNull(new Runnable() { public void run() { enc.encode(bb_null, ByteBuffer.allocate(10), 0); }}); checkNull(new Runnable() { public void run() { enc.encode(ByteBuffer.allocate(10), bb_null, 0); }}); + checkNull(new Runnable() { public void run() { enc.wrap(null); }}); } private static void testNull(final Base64.Decoder dec) { @@ -305,6 +306,7 @@ public class TestBase64 { checkNull(new Runnable() { public void run() { dec.decode(bb_null); }}); checkNull(new Runnable() { public void run() { dec.decode(bb_null, ByteBuffer.allocate(10)); }}); checkNull(new Runnable() { public void run() { dec.decode(ByteBuffer.allocate(10), bb_null); }}); + checkNull(new Runnable() { public void run() { dec.wrap(null); }}); } private static interface Testable { From 9101ca61f5fb2707a4caf94dec32bbb0c7f4728e Mon Sep 17 00:00:00 2001 From: Joe Darcy Date: Thu, 31 Jan 2013 12:13:21 -0800 Subject: [PATCH 125/210] 8005832: Remove java.lang.annotation.{ContainedBy, ContainerFor} annotation types Reviewed-by: mduigou --- .../java/lang/annotation/ContainedBy.java | 71 ------------------ .../java/lang/annotation/ContainerFor.java | 73 ------------------- .../InvalidContainerAnnotationError.java | 9 +-- 3 files changed, 4 insertions(+), 149 deletions(-) delete mode 100644 jdk/src/share/classes/java/lang/annotation/ContainedBy.java delete mode 100644 jdk/src/share/classes/java/lang/annotation/ContainerFor.java diff --git a/jdk/src/share/classes/java/lang/annotation/ContainedBy.java b/jdk/src/share/classes/java/lang/annotation/ContainedBy.java deleted file mode 100644 index 4f032863791..00000000000 --- a/jdk/src/share/classes/java/lang/annotation/ContainedBy.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (c) 2012, 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. - */ - -package java.lang.annotation; - -/** - * The annotation type {@code java.lang.annotation.ContainedBy} is - * used to indicate that the annotation type whose declaration it - * (meta-)annotates is repeatable. The value of - * {@code @ContainedBy} indicates the containing annotation - * type for the repeatable annotation type. - * - *

The pair of annotation types {@code @ContainedBy} and - * {@link java.lang.annotation.ContainerFor @ContainerFor} are used to - * indicate that annotation types are repeatable. Specifically: - * - *

    - *
  • The annotation type {@code @ContainedBy} is used on the - * declaration of a repeatable annotation type (JLS 9.6) to indicate - * its containing annotation type. - * - *
  • The annotation type {@code @ContainerFor} is used on the - * declaration of a containing annotation type (JLS 9.6) to indicate - * the repeatable annotation type for which it serves as the - * containing annotation type. - *
- * - *

- * An inconsistent pair of {@code @ContainedBy} and - * {@code @ContainerFor} annotations on a repeatable annotation type - * and its containing annotation type (JLS 9.6) will lead to - * compile-time errors and runtime exceptions when using reflection to - * read annotations of a repeatable type. - * - * @see java.lang.annotation.ContainerFor - * @since 1.8 - * @jls 9.6 Annotation Types - * @jls 9.7 Annotations - */ -@Documented -@Retention(RetentionPolicy.RUNTIME) -@Target(ElementType.ANNOTATION_TYPE) -public @interface ContainedBy { - /** - * Indicates the containing annotation type for the - * repeatable annotation type. - */ - Class value(); -} diff --git a/jdk/src/share/classes/java/lang/annotation/ContainerFor.java b/jdk/src/share/classes/java/lang/annotation/ContainerFor.java deleted file mode 100644 index 62f3446e021..00000000000 --- a/jdk/src/share/classes/java/lang/annotation/ContainerFor.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright (c) 2012, 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. - */ - -package java.lang.annotation; - -/** - * The annotation type {@code java.lang.annotation.ContainerFor} is - * used to indicate that the annotation type whose declaration it - * (meta-)annotates is a containing annotation type. The - * value of {@code @ContainerFor} indicates the repeatable - * annotation type for the containing annotation type. - * - *

The pair of annotation types {@link - * java.lang.annotation.ContainedBy @ContainedBy} and - * {@code @ContainerFor} are used to indicate that annotation types - * are repeatable. Specifically: - * - *

    - *
  • The annotation type {@code @ContainedBy} is used on the - * declaration of a repeatable annotation type (JLS 9.6) to indicate - * its containing annotation type. - * - *
  • The annotation type {@code @ContainerFor} is used on the - * declaration of a containing annotation type (JLS 9.6) to indicate - * the repeatable annotation type for which it serves as the - * containing annotation type. - *
- * - *

- * An inconsistent pair of {@code @ContainedBy} and - * {@code @ContainerFor} annotations on a repeatable annotation type - * and its containing annotation type (JLS 9.6) will lead to - * compile-time errors and runtime exceptions when using reflection to - * read annotations of a repeatable type. - * - * @see java.lang.annotation.ContainedBy - * @since 1.8 - * @jls 9.6 Annotation Types - * @jls 9.7 Annotations - */ -@Documented -@Retention(RetentionPolicy.RUNTIME) -@Target(ElementType.ANNOTATION_TYPE) -public @interface ContainerFor { - - /** - * Indicates the repeatable annotation type for the containing - * annotation type. - */ - Class value(); -} diff --git a/jdk/src/share/classes/java/lang/annotation/InvalidContainerAnnotationError.java b/jdk/src/share/classes/java/lang/annotation/InvalidContainerAnnotationError.java index b24e3034179..37d00a98b40 100644 --- a/jdk/src/share/classes/java/lang/annotation/InvalidContainerAnnotationError.java +++ b/jdk/src/share/classes/java/lang/annotation/InvalidContainerAnnotationError.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2013, 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 @@ -27,10 +27,9 @@ package java.lang.annotation; import java.util.Objects; /** - * Thrown to indicate that an annotation type whose declaration is - * (meta-)annotated with a {@link ContainerFor} annotation is not, in - * fact, the containing annotation type of the type named by {@link - * ContainerFor}. + * Thrown to indicate that an annotation type expected to act as a + * container for another annotation type by virture of an @Repeatable + * annotation, does not act as a container. * * @see java.lang.reflect.AnnotatedElement * @since 1.8 From 4484857b5058b889f8c226a518c6f0f2b22aa099 Mon Sep 17 00:00:00 2001 From: Joe Darcy Date: Thu, 31 Jan 2013 12:16:03 -0800 Subject: [PATCH 126/210] 8007313: Remove use of {ContainerFor/ContainedBy} from langtools Reviewed-by: jjg --- .../classfile/CombinationsTargetTest1.java | 9 +++------ .../classfile/CombinationsTargetTest2.java | 9 +++------ .../newlocations/RepeatingTypeAnnotations.java | 1 - .../typeAnnotations/referenceinfos/Driver.java | 6 +++--- 4 files changed, 9 insertions(+), 16 deletions(-) diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/classfile/CombinationsTargetTest1.java b/langtools/test/tools/javac/annotations/typeAnnotations/classfile/CombinationsTargetTest1.java index 0041dd35f61..dfab97807c2 100644 --- a/langtools/test/tools/javac/annotations/typeAnnotations/classfile/CombinationsTargetTest1.java +++ b/langtools/test/tools/javac/annotations/typeAnnotations/classfile/CombinationsTargetTest1.java @@ -174,22 +174,20 @@ public class CombinationsTargetTest1 extends ClassfileTestHelper { String sourceBase = new String("@Retention("+retentn+")\n" + "@Target({TYPE_USE,_OTHER_})\n" + - "@ContainedBy( AC.class )\n" + + "@Repeatable( AC.class )\n" + "@interface A { }\n\n" + "@Retention("+retentn+")\n" + "@Target({TYPE_USE,_OTHER_})\n" + - "@ContainerFor(A.class)\n" + "@interface AC { A[] value(); }\n\n" + "@Retention("+retentn+")\n" + "@Target({TYPE_USE,_OTHER_})\n" + - "@ContainedBy( BC.class )\n" + + "@Repeatable( BC.class )\n" + "@interface B { }\n\n" + "@Retention("+retentn+")\n" + "@Target({TYPE_USE,_OTHER_})\n" + - "@ContainerFor(B.class)\n" + "@interface BC { B[] value(); } \n\n" + "@Retention("+retentn+")\n" + @@ -198,12 +196,11 @@ public class CombinationsTargetTest1 extends ClassfileTestHelper { "@Retention("+retentn+")\n" + "@Target({TYPE_USE,TYPE_PARAMETER,_OTHER_})\n" + - "@ContainedBy(DC.class)\n" + + "@Repeatable(DC.class)\n" + "@interface D { }\n\n" + "@Retention("+retentn+")\n" + "@Target({TYPE_USE,TYPE_PARAMETER,_OTHER_})\n" + - "@ContainerFor(D.class) \n" + "@interface DC { D[] value(); }\n\n"); // Test case sources with sample generated source. diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/classfile/CombinationsTargetTest2.java b/langtools/test/tools/javac/annotations/typeAnnotations/classfile/CombinationsTargetTest2.java index a0308a38975..77fb9a8aa1e 100644 --- a/langtools/test/tools/javac/annotations/typeAnnotations/classfile/CombinationsTargetTest2.java +++ b/langtools/test/tools/javac/annotations/typeAnnotations/classfile/CombinationsTargetTest2.java @@ -171,32 +171,29 @@ public class CombinationsTargetTest2 extends ClassfileTestHelper { String sourceBase = new String("@Retention("+retentn+")\n" + "@Target({TYPE_USE,_OTHER_})\n" + - "@ContainedBy( AC.class )\n" + + "@Repeatable( AC.class )\n" + "@interface A { }\n\n" + "@Retention("+retentn+")\n" + "@Target({TYPE_USE,_OTHER_})\n" + - "@ContainerFor(A.class)\n" + "@interface AC { A[] value(); }\n\n" + "@Retention("+retentn+")\n" + "@Target({TYPE_USE,_OTHER_})\n" + - "@ContainedBy( BC.class )\n" + + "@Repeatable( BC.class )\n" + "@interface B { }\n\n" + "@Retention("+retentn+")\n" + "@Target({TYPE_USE,_OTHER_})\n" + - "@ContainerFor(B.class)\n" + "@interface BC { B[] value(); } \n\n" + "@Retention("+retentn+")\n" + "@Target({TYPE_USE,TYPE_PARAMETER,_OTHER_})\n" + - "@ContainedBy(DC.class)\n" + + "@Repeatable(DC.class)\n" + "@interface D { }\n\n" + "@Retention("+retentn+")\n" + "@Target({TYPE_USE,TYPE_PARAMETER,_OTHER_})\n" + - "@ContainerFor(D.class) \n" + "@interface DC { D[] value(); }\n\n"); // Test case sources with sample generated source diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/RepeatingTypeAnnotations.java b/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/RepeatingTypeAnnotations.java index db227cb56f6..3aecc7a9219 100644 --- a/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/RepeatingTypeAnnotations.java +++ b/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/RepeatingTypeAnnotations.java @@ -120,7 +120,6 @@ class MyList { } @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) @interface RTA { } -@ContainerFor(RTA.class) @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) @interface RTAs { RTA[] value(); diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/Driver.java b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/Driver.java index 5986fa95de8..052d11a77a2 100644 --- a/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/Driver.java +++ b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/Driver.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2013 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 @@ -241,8 +241,8 @@ public class Driver { sb.append("\n@Repeatable(RTAs.class) @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) @interface RTA {}"); sb.append("\n@Repeatable(RTBs.class) @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) @interface RTB {}"); - sb.append("\n@ContainerFor(RTA.class) @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) @interface RTAs { RTA[] value(); }"); - sb.append("\n@ContainerFor(RTB.class) @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) @interface RTBs { RTB[] value(); }"); + sb.append("\n@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) @interface RTAs { RTA[] value(); }"); + sb.append("\n@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) @interface RTBs { RTB[] value(); }"); sb.append("\n@Target(value={ElementType.TYPE,ElementType.FIELD,ElementType.METHOD,ElementType.PARAMETER,ElementType.CONSTRUCTOR,ElementType.LOCAL_VARIABLE})"); sb.append("\n@interface Decl {}"); From 757d9cdeb9c5cac2cf99a8a29f53ef68448964c4 Mon Sep 17 00:00:00 2001 From: Joe Darcy Date: Thu, 31 Jan 2013 12:23:04 -0800 Subject: [PATCH 127/210] 8007115: Refactor regression tests for java.lang.reflect.Parameter Reviewed-by: emc --- .../reflect/Parameter/WithoutParameters.java | 249 +++++++++--------- 1 file changed, 119 insertions(+), 130 deletions(-) diff --git a/jdk/test/java/lang/reflect/Parameter/WithoutParameters.java b/jdk/test/java/lang/reflect/Parameter/WithoutParameters.java index 39be21471aa..50254fd9d6b 100644 --- a/jdk/test/java/lang/reflect/Parameter/WithoutParameters.java +++ b/jdk/test/java/lang/reflect/Parameter/WithoutParameters.java @@ -23,163 +23,152 @@ /* * @test + * @bug 8004729 * @summary javac should generate method parameters correctly. */ import java.lang.*; import java.lang.reflect.*; +import java.lang.annotation.*; import java.util.List; +import java.util.Objects; + +import static java.lang.annotation.ElementType.*; public class WithoutParameters { + int errors = 0; - private static final Class[] qux_types = { - int.class, - Foo.class, - List.class, - List.class, - List.class, - String[].class - }; + private WithoutParameters() {} public static void main(String argv[]) throws Exception { - int error = 0; - Method[] methods = Foo.class.getMethods(); - for(Method m : methods) { - System.err.println("Inspecting method " + m); - Parameter[] parameters = m.getParameters(); - if(parameters == null) - throw new Exception("getParameters should never be null"); - for(int i = 0; i < parameters.length; i++) { - Parameter p = parameters[i]; - if(!p.getDeclaringExecutable().equals(m)) { - System.err.println(p + ".getDeclaringExecutable != " + m); - error++; - } - if(null == p.getType()) { - System.err.println(p + ".getType() == null"); - error++; - } - if(null == p.getParameterizedType()) { - System.err.println(p + ".getParameterizedType == null"); - error++; - } - } - if(m.getName().equals("qux")) { - if(6 != parameters.length) { - System.err.println("Wrong number of parameters for qux"); - error++; - } - for(int i = 0; i < parameters.length; i++) { - Parameter p = parameters[i]; - // The getType family work with or without - // parameter attributes compiled in. - if(!parameters[i].getType().equals(qux_types[i])) { - System.err.println("Wrong parameter type for " + parameters[0] + ": expected " + qux_types[i] + ", but got " + parameters[i].getType()); - error++; - } - } - if(!parameters[0].getParameterizedType().equals(int.class)) { - System.err.println("getParameterizedType for quux is wrong"); - error++; - } - if(!parameters[1].getParameterizedType().equals(Foo.class)) { - System.err.println("getParameterizedType for quux is wrong"); - error++; - } - if(!(parameters[2].getParameterizedType() instanceof - ParameterizedType)) { - System.err.println("getParameterizedType for l is wrong"); - error++; - } else { - ParameterizedType pt = - (ParameterizedType) parameters[2].getParameterizedType(); - if(!pt.getRawType().equals(List.class)) { - System.err.println("Raw type for l is wrong"); - error++; - } - if(1 != pt.getActualTypeArguments().length) { - System.err.println("Number of type parameters for l is wrong"); - error++; - } - if(!(pt.getActualTypeArguments()[0] instanceof WildcardType)) { - System.err.println("Type parameter for l is wrong"); - error++; - } - } - if(!(parameters[3].getParameterizedType() instanceof - ParameterizedType)) { - System.err.println("getParameterizedType for l2 is wrong"); - error++; - } else { - ParameterizedType pt = - (ParameterizedType) parameters[3].getParameterizedType(); - if(!pt.getRawType().equals(List.class)) { - System.err.println("Raw type for l2 is wrong"); - error++; - } - if(1 != pt.getActualTypeArguments().length) { - System.err.println("Number of type parameters for l2 is wrong"); - error++; - } - if(!(pt.getActualTypeArguments()[0].equals(Foo.class))) { - System.err.println("Type parameter for l2 is wrong"); - error++; - } - } - if(!(parameters[4].getParameterizedType() instanceof - ParameterizedType)) { - System.err.println("getParameterizedType for l3 is wrong"); - error++; - } else { - ParameterizedType pt = - (ParameterizedType) parameters[4].getParameterizedType(); - if(!pt.getRawType().equals(List.class)) { - System.err.println("Raw type for l3 is wrong"); - error++; - } - if(1 != pt.getActualTypeArguments().length) { - System.err.println("Number of type parameters for l3 is wrong"); - error++; - } - if(!(pt.getActualTypeArguments()[0] instanceof WildcardType)) { - System.err.println("Type parameter for l3 is wrong"); - error++; - } else { - WildcardType wt = (WildcardType) - pt.getActualTypeArguments()[0]; - if(!wt.getUpperBounds()[0].equals(Foo.class)) { - System.err.println("Upper bounds on type parameter fol l3 is wrong"); - error++; - } - } - } - if(!parameters[5].isVarArgs()) { - System.err.println("isVarArg for rest is wrong"); - error++; - } - if(!(parameters[5].getParameterizedType().equals(String[].class))) { - System.err.println("getParameterizedType for rest is wrong"); - error++; - } + WithoutParameters wp = new WithoutParameters(); + wp.runTests(Foo.class.getMethods()); + wp.runTests(Foo.Inner.class.getConstructors()); + wp.checkForErrors(); + } + void runTests(Method[] methods) throws Exception { + for(Method m : methods) {runTest(m);} + } + + void runTests(Constructor[] constructors) throws Exception { + for(Constructor c : constructors) {runTest(c);} + } + + void runTest(Executable e) throws Exception { + System.err.println("Inspecting executable " + e); + Parameter[] parameters = e.getParameters(); + Objects.requireNonNull(parameters, "getParameters should never be null"); + + ExpectedParameterInfo epi = e.getAnnotation(ExpectedParameterInfo.class); + if (epi != null) { + abortIfTrue(epi.parameterCount() != e.getParameterCount(), "Bad parameter count for "+ e); + abortIfTrue(epi.isVarArgs() != e.isVarArgs(),"Bad varargs value for "+ e); + } + abortIfTrue(e.getParameterCount() != parameters.length, "Mismatched of parameter counts."); + + for(int i = 0; i < parameters.length; i++) { + Parameter p = parameters[i]; + errorIfTrue(!p.getDeclaringExecutable().equals(e), p + ".getDeclaringExecutable != " + e); + Objects.requireNonNull(p.getType(), "getType() should not be null"); + Objects.requireNonNull(p.getParameterizedType(), "getParameterizedType() should not be null"); + + if (epi != null) { + Class expectedParameterType = epi.parameterTypes()[i]; + errorIfTrue(!p.getType().equals(expectedParameterType), + "Wrong parameter type for " + p + ": expected " + expectedParameterType + + ", but got " + p.getType()); + + ParameterizedInfo[] expectedParameterizedTypes = epi.parameterizedTypes(); + if (expectedParameterizedTypes.length > 0) { + Type parameterizedType = p.getParameterizedType(); + Class expectedParameterziedTypeType = expectedParameterizedTypes[i].value(); + errorIfTrue(!expectedParameterziedTypeType.isAssignableFrom(parameterizedType.getClass()), + "Wrong class of parameteried type of " + p + ": expected " + expectedParameterziedTypeType + + ", but got " + parameterizedType.getClass()); + + if (expectedParameterziedTypeType.equals(Class.class)) { + errorIfTrue(!parameterizedType.equals(expectedParameterType), + "Wrong parameteried type for " + p + ": expected " + expectedParameterType + + ", but got " + parameterizedType); + } else { + if (expectedParameterziedTypeType.equals(ParameterizedType.class)) { + ParameterizedType ptype = (ParameterizedType)parameterizedType; + errorIfTrue(!ptype.getRawType().equals(expectedParameterType), + "Wrong raw type for " + p + ": expected " + expectedParameterType + + ", but got " + ptype.getRawType()); + } + + // Check string representation + String expectedStringOfType = epi.parameterizedTypes()[i].string(); + errorIfTrue(!expectedStringOfType.equals(parameterizedType.toString()), + "Bad type string" + p + ": expected " + expectedStringOfType + + ", but got " + parameterizedType.toString()); + } + } } } - if(0 != error) - throw new Exception("Failed " + error + " tests"); + } + + private void checkForErrors() { + if (errors > 0) + throw new RuntimeException("Failed " + errors + " tests"); + } + + private void errorIfTrue(boolean predicate, String errMessage) { + if (predicate) { + errors++; + System.err.println(errMessage); + } + } + + private void abortIfTrue(boolean predicate, String errMessage) { + if (predicate) { + throw new RuntimeException(errMessage); + } + } + + @Retention(RetentionPolicy.RUNTIME) + @Target({METHOD, CONSTRUCTOR}) + @interface ExpectedParameterInfo { + int parameterCount() default 0; + Class[] parameterTypes() default {}; + ParameterizedInfo[] parameterizedTypes() default {}; + boolean isVarArgs() default false; + } + + @Target({}) + @interface ParameterizedInfo { + Class value() default Class.class; + String string() default ""; } public class Foo { int thing; + @ExpectedParameterInfo(parameterCount = 6, + parameterTypes = + {int.class, Foo.class, + List.class, List.class, + List.class, String[].class}, + parameterizedTypes = + {@ParameterizedInfo(Class.class), + @ParameterizedInfo(Class.class), + @ParameterizedInfo(value=ParameterizedType.class, string="java.util.List"), + @ParameterizedInfo(value=ParameterizedType.class, string="java.util.List"), + @ParameterizedInfo(value=ParameterizedType.class, string="java.util.List"), + @ParameterizedInfo(Class.class)}, + isVarArgs = true) public void qux(int quux, Foo quuux, List l, List l2, List l3, String... rest) {} public class Inner { int thang; + @ExpectedParameterInfo(parameterCount = 2, + parameterTypes = {Foo.class, int.class}) public Inner(int theng) { thang = theng + thing; } } } - } From 320ce960ce44832016963f7356269e3ae6b63677 Mon Sep 17 00:00:00 2001 From: Xueming Shen Date: Thu, 31 Jan 2013 13:13:14 -0800 Subject: [PATCH 128/210] 8007298: Base64.getMimeDecoder().decode() throws IAE for a single non-base64 character 8006526: Base64.Decoder.decode(String) spec contains a copy-paste mistake To ignore single non-base64 char in mime decoding Reviewed-by: alanb --- jdk/src/share/classes/java/util/Base64.java | 7 +++++-- jdk/test/java/util/Base64/TestBase64.java | 18 +++++++++++++++++- 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/jdk/src/share/classes/java/util/Base64.java b/jdk/src/share/classes/java/util/Base64.java index 7a01c05e653..471b4e28620 100644 --- a/jdk/src/share/classes/java/util/Base64.java +++ b/jdk/src/share/classes/java/util/Base64.java @@ -696,7 +696,7 @@ public class Base64 { * using the {@link Base64} encoding scheme. * *

An invocation of this method has exactly the same effect as invoking - * {@code return decode(src.getBytes(StandardCharsets.ISO_8859_1))} + * {@code decode(src.getBytes(StandardCharsets.ISO_8859_1))} * * @param src * the string to decode @@ -1014,9 +1014,12 @@ public class Base64 { int len = sl - sp; if (len == 0) return 0; - if (len < 2) + if (len < 2) { + if (isMIME && base64[0] == -1) + return 0; throw new IllegalArgumentException( "Input byte[] should at least have 2 bytes for base64 bytes"); + } if (src[sl - 1] == '=') { paddings++; if (src[sl - 2] == '=') diff --git a/jdk/test/java/util/Base64/TestBase64.java b/jdk/test/java/util/Base64/TestBase64.java index 645f570b0f3..0a8eea6e4aa 100644 --- a/jdk/test/java/util/Base64/TestBase64.java +++ b/jdk/test/java/util/Base64/TestBase64.java @@ -22,7 +22,7 @@ */ /** - * @test 4235519 8004212 8005394 + * @test 4235519 8004212 8005394 8007298 * @summary tests java.util.Base64 */ @@ -109,6 +109,9 @@ public class TestBase64 { // test return value from decode(ByteBuffer, ByteBuffer) testDecBufRet(); + + // test single-non-base64 character for mime decoding + testSingleNonBase64MimeDec(); } private static sun.misc.BASE64Encoder sunmisc = new sun.misc.BASE64Encoder(); @@ -356,6 +359,19 @@ public class TestBase64 { } catch (IllegalArgumentException iae) {} } + // single-non-base64-char should be ignored for mime decoding, but + // iae for basic decoding + private static void testSingleNonBase64MimeDec() throws Throwable { + for (String nonBase64 : new String[] {"#", "(", "!", "\\", "-", "_"}) { + if (Base64.getMimeDecoder().decode(nonBase64).length != 0) { + throw new RuntimeException("non-base64 char is not ignored"); + } + try { + Base64.getDecoder().decode(nonBase64); + throw new RuntimeException("No IAE for single non-base64 char"); + } catch (IllegalArgumentException iae) {} + } + } private static void testDecBufRet() throws Throwable { Random rnd = new java.util.Random(); From 665fca9d60704d2dad7b0611f4b73adabd0e659a Mon Sep 17 00:00:00 2001 From: Mike Duigou Date: Thu, 31 Jan 2013 13:27:04 -0800 Subject: [PATCH 129/210] 8006709: Add minimal support of MacOSX platform for NetBeans Projects Adds support for MacOSX platform and architecture detection. Other minor updates (-source/target 1.8) Reviewed-by: ohair --- .../architectures/arch-x86_64.properties | 32 +++++++++++++++++++ .../architectures/name-Macosx.properties | 32 +++++++++++++++++++ jdk/make/netbeans/common/java-data-native.ent | 4 +-- .../netbeans/common/java-data-no-native.ent | 4 +-- jdk/make/netbeans/common/make.xml | 7 +++- jdk/make/netbeans/common/shared.xml | 7 ++-- 6 files changed, 77 insertions(+), 9 deletions(-) create mode 100644 jdk/make/netbeans/common/architectures/arch-x86_64.properties create mode 100644 jdk/make/netbeans/common/architectures/name-Macosx.properties diff --git a/jdk/make/netbeans/common/architectures/arch-x86_64.properties b/jdk/make/netbeans/common/architectures/arch-x86_64.properties new file mode 100644 index 00000000000..eac11240e57 --- /dev/null +++ b/jdk/make/netbeans/common/architectures/arch-x86_64.properties @@ -0,0 +1,32 @@ +# +# Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# - Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# - Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# - Neither the name of Oracle nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +arch=x86_64 diff --git a/jdk/make/netbeans/common/architectures/name-Macosx.properties b/jdk/make/netbeans/common/architectures/name-Macosx.properties new file mode 100644 index 00000000000..05744c7f05c --- /dev/null +++ b/jdk/make/netbeans/common/architectures/name-Macosx.properties @@ -0,0 +1,32 @@ +# +# Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# - Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# - Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# - Neither the name of Oracle nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +platform=macosx diff --git a/jdk/make/netbeans/common/java-data-native.ent b/jdk/make/netbeans/common/java-data-native.ent index a801e821db6..8db2a86d618 100644 --- a/jdk/make/netbeans/common/java-data-native.ent +++ b/jdk/make/netbeans/common/java-data-native.ent @@ -39,11 +39,11 @@ ${bootstrap.jdk}/jre/lib/rt.jar ${root}/build/${platform}-${arch}/classes ${root}/build/${platform}-${arch}/docs/api - 1.7 + 1.8 ${root}/test - 1.7 + 1.8 diff --git a/jdk/make/netbeans/common/java-data-no-native.ent b/jdk/make/netbeans/common/java-data-no-native.ent index a204f3a6f17..240ec4aadc9 100644 --- a/jdk/make/netbeans/common/java-data-no-native.ent +++ b/jdk/make/netbeans/common/java-data-no-native.ent @@ -37,11 +37,11 @@ ${bootstrap.jdk}/jre/lib/rt.jar ${root}/build/${platform}-${arch}/classes ${root}/build/${platform}-${arch}/docs/api - 1.7 + 1.8 ${root}/test - 1.7 + 1.8 diff --git a/jdk/make/netbeans/common/make.xml b/jdk/make/netbeans/common/make.xml index a61f04f07db..ee1a47a4fe1 100644 --- a/jdk/make/netbeans/common/make.xml +++ b/jdk/make/netbeans/common/make.xml @@ -33,7 +33,7 @@ - + @@ -42,6 +42,11 @@ + + + + + diff --git a/jdk/make/netbeans/common/shared.xml b/jdk/make/netbeans/common/shared.xml index 7c2b8095f79..ba104445273 100644 --- a/jdk/make/netbeans/common/shared.xml +++ b/jdk/make/netbeans/common/shared.xml @@ -85,6 +85,9 @@ + + + @@ -126,10 +129,6 @@ - - - - From 6b6febce981413881bccfd238c456a0bdbd63352 Mon Sep 17 00:00:00 2001 From: Tim Bell Date: Thu, 31 Jan 2013 13:31:30 -0800 Subject: [PATCH 130/210] 8006933: Need to use nawk on Solaris to avoid awk limitations Reviewed-by: erikj, dholmes, dsamersoff --- common/makefiles/IdlCompilation.gmk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/makefiles/IdlCompilation.gmk b/common/makefiles/IdlCompilation.gmk index 6dc5fee2999..2eb77dd3beb 100644 --- a/common/makefiles/IdlCompilation.gmk +++ b/common/makefiles/IdlCompilation.gmk @@ -71,7 +71,7 @@ define add_idl_package $4 $(RM) -f $$(addprefix $3/$$($4_TMPDIR)/,$6) $(CP) -rp $3/$$($4_TMPDIR)/* $3 - ($(CD) $3/$$($4_TMPDIR); find . -type f | sed 's!\./!$3/!g' | awk '{ print $$$$1 ": $4" }' > $5) + ($(CD) $3/$$($4_TMPDIR) && $(FIND) . -type f | $(SED) 's!\./!$3/!g' | $(NAWK) '{ print $$$$1 ": $4" }' > $5) $(RM) -rf $3/$$($4_TMPDIR) endef From f7f0768c22be02b8e88f44c7b023bbe079f083a4 Mon Sep 17 00:00:00 2001 From: Brian Burkhalter Date: Thu, 31 Jan 2013 14:29:19 -0800 Subject: [PATCH 131/210] 6355704: (fmt) %f formatting of BigDecimals is incorrect Reviewed-by: darcy --- jdk/test/java/util/Formatter/Basic-X.java.template | 9 +++++++++ jdk/test/java/util/Formatter/BasicBigDecimal.java | 9 +++++++++ 2 files changed, 18 insertions(+) diff --git a/jdk/test/java/util/Formatter/Basic-X.java.template b/jdk/test/java/util/Formatter/Basic-X.java.template index 55b24097f6e..831c49212f0 100644 --- a/jdk/test/java/util/Formatter/Basic-X.java.template +++ b/jdk/test/java/util/Formatter/Basic-X.java.template @@ -1103,6 +1103,15 @@ public class Basic$Type$ extends Basic { test("%.5f", "1.99999", val); test("%.6f", "1.999990", val); + val = new BigDecimal(0.9996); + test("%.0f", "1", val); + test("%.1f", "1.0", val); + test("%.2f", "1.00", val); + test("%.3f", "1.000", val); + test("%.4f", "0.9996", val); + test("%.5f", "0.99960", val); + test("%.6f", "0.999600", val); + #end[BigDecimal] #if[float] diff --git a/jdk/test/java/util/Formatter/BasicBigDecimal.java b/jdk/test/java/util/Formatter/BasicBigDecimal.java index afc446ae4b0..6f36201aa34 100644 --- a/jdk/test/java/util/Formatter/BasicBigDecimal.java +++ b/jdk/test/java/util/Formatter/BasicBigDecimal.java @@ -1102,6 +1102,15 @@ public class BasicBigDecimal extends Basic { test("%.4f", "2.0000", val); test("%.5f", "1.99999", val); test("%.6f", "1.999990", val); + + val = new BigDecimal(0.9996); + test("%.0f", "1", val); + test("%.1f", "1.0", val); + test("%.2f", "1.00", val); + test("%.3f", "1.000", val); + test("%.4f", "0.9996", val); + test("%.5f", "0.99960", val); + test("%.6f", "0.999600", val); From 0c6cb9cdc2f088b887efdf3599213f39208f191c Mon Sep 17 00:00:00 2001 From: Weijun Wang Date: Fri, 1 Feb 2013 07:39:41 +0800 Subject: [PATCH 132/210] 8006564: Test sun/security/util/Oid/S11N.sh fails with timeout on Linux 32-bit Reviewed-by: alanb --- jdk/test/sun/security/util/Oid/S11N.java | 246 ++++++++++++++++++ jdk/test/sun/security/util/Oid/S11N.sh | 188 ------------- .../sun/security/util/Oid/SerialTest.java | 66 ----- 3 files changed, 246 insertions(+), 254 deletions(-) create mode 100644 jdk/test/sun/security/util/Oid/S11N.java delete mode 100644 jdk/test/sun/security/util/Oid/S11N.sh delete mode 100644 jdk/test/sun/security/util/Oid/SerialTest.java diff --git a/jdk/test/sun/security/util/Oid/S11N.java b/jdk/test/sun/security/util/Oid/S11N.java new file mode 100644 index 00000000000..a5595d10112 --- /dev/null +++ b/jdk/test/sun/security/util/Oid/S11N.java @@ -0,0 +1,246 @@ +/* + * Copyright (c) 2013, 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. + * + * 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. + */ + +/* + * @test + * @bug 4811968 6908628 8006564 + * @run main S11N check + * @summary Serialization compatibility with old versions (and fixes) + */ + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.util.HashMap; +import java.util.Map; +import sun.misc.BASE64Encoder; +import sun.security.util.ObjectIdentifier; + +public class S11N { + static String[] SMALL= { + "0.0", + "1.1", + "2.2", + "1.2.3456", + "1.2.2147483647.4", + "1.2.268435456.4", + }; + + static String[] HUGE = { + "2.16.764.1.3101555394.1.0.100.2.1", + "1.2.2147483648.4", + "2.3.4444444444444444444444", + "1.2.8888888888888888.33333333333333333.44444444444444", + }; + + // Do not use j.u.Base64, the test needs to run in jdk6 + static BASE64Encoder encoder = new BASE64Encoder() { + @Override + protected int bytesPerLine() { + return 48; + } + }; + + public static void main(String[] args) throws Exception { + if (args[0].equals("check")) { + int version = Integer.valueOf(System.getProperty("java.version") + .split("\\.")[1]); + System.out.println("version is " + version); + if (version >= 7) { + for (String oid: SMALL) { + // 7 -> 7 + check(out(oid), oid); + // 6 -> 7 + check(out6(oid), oid); + } + for (String oid: HUGE) { + // 7 -> 7 + check(out(oid), oid); + } + } else { + for (String oid: SMALL) { + // 6 -> 6 + check(out(oid), oid); + // 7 -> 6 + check(out7(oid), oid); + } + for (String oid: HUGE) { + // 7 -> 6 fails for HUGE oids + boolean ok = false; + try { + check(out7(oid), oid); + ok = true; + } catch (Exception e) { + System.out.println(e); + } + if (ok) { + throw new Exception(); + } + } + } + } else { + // Generates the JDK6 serialized string inside this test, call + // $JDK7/bin/java S11N dump7 + // $JDK6/bin/java S11N dump6 + // and paste the output at the end of this test. + dump(args[0], SMALL); + // For jdk6, the following line will throw an exception, ignore it + dump(args[0], HUGE); + } + } + + // Gets the serialized form for jdk6 + private static byte[] out6(String oid) throws Exception { + return new sun.misc.BASE64Decoder().decodeBuffer(dump6.get(oid)); + } + + // Gets the serialized form for jdk7 + private static byte[] out7(String oid) throws Exception { + return new sun.misc.BASE64Decoder().decodeBuffer(dump7.get(oid)); + } + + // Gets the serialized form for this java + private static byte[] out(String oid) throws Exception { + ByteArrayOutputStream bout = new ByteArrayOutputStream(); + new ObjectOutputStream(bout).writeObject(new ObjectIdentifier(oid)); + return bout.toByteArray(); + } + + // Makes sure serialized form can be deserialized + private static void check(byte[] in, String oid) throws Exception { + ObjectIdentifier o = (ObjectIdentifier) ( + new ObjectInputStream(new ByteArrayInputStream(in)).readObject()); + if (!o.toString().equals(oid)) { + throw new Exception("Read Fail " + o + ", not " + oid); + } + } + + // dump serialized form to java code style text + private static void dump(String title, String[] oids) throws Exception { + for (String oid: oids) { + String[] base64 = encoder.encodeBuffer(out(oid)).split("\n"); + System.out.println(" " + title + ".put(\"" + oid + "\","); + for (int i = 0; i dump7 = new HashMap(); + private static Map dump6 = new HashMap(); + + static { + ////////////// PASTE BEGIN ////////////// + dump7.put("0.0", + "rO0ABXNyACJzdW4uc2VjdXJpdHkudXRpbC5PYmplY3RJZGVudGlmaWVyeLIO7GQX" + + "fy4DAANJAAxjb21wb25lbnRMZW5MAApjb21wb25lbnRzdAASTGphdmEvbGFuZy9P" + + "YmplY3Q7WwAIZW5jb2Rpbmd0AAJbQnhwAAAAAnVyAAJbSU26YCZ26rKlAgAAeHAA" + + "AAACAAAAAAAAAAB1cgACW0Ks8xf4BghU4AIAAHhwAAAAAQB4"); + dump7.put("1.1", + "rO0ABXNyACJzdW4uc2VjdXJpdHkudXRpbC5PYmplY3RJZGVudGlmaWVyeLIO7GQX" + + "fy4DAANJAAxjb21wb25lbnRMZW5MAApjb21wb25lbnRzdAASTGphdmEvbGFuZy9P" + + "YmplY3Q7WwAIZW5jb2Rpbmd0AAJbQnhwAAAAAnVyAAJbSU26YCZ26rKlAgAAeHAA" + + "AAACAAAAAQAAAAF1cgACW0Ks8xf4BghU4AIAAHhwAAAAASl4"); + dump7.put("2.2", + "rO0ABXNyACJzdW4uc2VjdXJpdHkudXRpbC5PYmplY3RJZGVudGlmaWVyeLIO7GQX" + + "fy4DAANJAAxjb21wb25lbnRMZW5MAApjb21wb25lbnRzdAASTGphdmEvbGFuZy9P" + + "YmplY3Q7WwAIZW5jb2Rpbmd0AAJbQnhwAAAAAnVyAAJbSU26YCZ26rKlAgAAeHAA" + + "AAACAAAAAgAAAAJ1cgACW0Ks8xf4BghU4AIAAHhwAAAAAVJ4"); + dump7.put("1.2.3456", + "rO0ABXNyACJzdW4uc2VjdXJpdHkudXRpbC5PYmplY3RJZGVudGlmaWVyeLIO7GQX" + + "fy4DAANJAAxjb21wb25lbnRMZW5MAApjb21wb25lbnRzdAASTGphdmEvbGFuZy9P" + + "YmplY3Q7WwAIZW5jb2Rpbmd0AAJbQnhwAAAAA3VyAAJbSU26YCZ26rKlAgAAeHAA" + + "AAADAAAAAQAAAAIAAA2AdXIAAltCrPMX+AYIVOACAAB4cAAAAAMqmwB4"); + dump7.put("1.2.2147483647.4", + "rO0ABXNyACJzdW4uc2VjdXJpdHkudXRpbC5PYmplY3RJZGVudGlmaWVyeLIO7GQX" + + "fy4DAANJAAxjb21wb25lbnRMZW5MAApjb21wb25lbnRzdAASTGphdmEvbGFuZy9P" + + "YmplY3Q7WwAIZW5jb2Rpbmd0AAJbQnhwAAAABHVyAAJbSU26YCZ26rKlAgAAeHAA" + + "AAAEAAAAAQAAAAJ/////AAAABHVyAAJbQqzzF/gGCFTgAgAAeHAAAAAHKof///9/" + + "BHg="); + dump7.put("1.2.268435456.4", + "rO0ABXNyACJzdW4uc2VjdXJpdHkudXRpbC5PYmplY3RJZGVudGlmaWVyeLIO7GQX" + + "fy4DAANJAAxjb21wb25lbnRMZW5MAApjb21wb25lbnRzdAASTGphdmEvbGFuZy9P" + + "YmplY3Q7WwAIZW5jb2Rpbmd0AAJbQnhwAAAABHVyAAJbSU26YCZ26rKlAgAAeHAA" + + "AAAEAAAAAQAAAAIQAAAAAAAABHVyAAJbQqzzF/gGCFTgAgAAeHAAAAAHKoGAgIAA" + + "BHg="); + dump7.put("2.16.764.1.3101555394.1.0.100.2.1", + "rO0ABXNyACJzdW4uc2VjdXJpdHkudXRpbC5PYmplY3RJZGVudGlmaWVyeLIO7GQX" + + "fy4DAANJAAxjb21wb25lbnRMZW5MAApjb21wb25lbnRzdAASTGphdmEvbGFuZy9P" + + "YmplY3Q7WwAIZW5jb2Rpbmd0AAJbQnhw/////3NyAD5zdW4uc2VjdXJpdHkudXRp" + + "bC5PYmplY3RJZGVudGlmaWVyJEh1Z2VPaWROb3RTdXBwb3J0ZWRCeU9sZEpESwAA" + + "AAAAAAABAgAAeHB1cgACW0Ks8xf4BghU4AIAAHhwAAAADmCFfAGLxvf1QgEAZAIB" + + "eA=="); + dump7.put("1.2.2147483648.4", + "rO0ABXNyACJzdW4uc2VjdXJpdHkudXRpbC5PYmplY3RJZGVudGlmaWVyeLIO7GQX" + + "fy4DAANJAAxjb21wb25lbnRMZW5MAApjb21wb25lbnRzdAASTGphdmEvbGFuZy9P" + + "YmplY3Q7WwAIZW5jb2Rpbmd0AAJbQnhw/////3NyAD5zdW4uc2VjdXJpdHkudXRp" + + "bC5PYmplY3RJZGVudGlmaWVyJEh1Z2VPaWROb3RTdXBwb3J0ZWRCeU9sZEpESwAA" + + "AAAAAAABAgAAeHB1cgACW0Ks8xf4BghU4AIAAHhwAAAAByqIgICAAAR4"); + dump7.put("2.3.4444444444444444444444", + "rO0ABXNyACJzdW4uc2VjdXJpdHkudXRpbC5PYmplY3RJZGVudGlmaWVyeLIO7GQX" + + "fy4DAANJAAxjb21wb25lbnRMZW5MAApjb21wb25lbnRzdAASTGphdmEvbGFuZy9P" + + "YmplY3Q7WwAIZW5jb2Rpbmd0AAJbQnhw/////3NyAD5zdW4uc2VjdXJpdHkudXRp" + + "bC5PYmplY3RJZGVudGlmaWVyJEh1Z2VPaWROb3RTdXBwb3J0ZWRCeU9sZEpESwAA" + + "AAAAAAABAgAAeHB1cgACW0Ks8xf4BghU4AIAAHhwAAAADFOD4e+HpNG968eOHHg="); + dump7.put("1.2.8888888888888888.33333333333333333.44444444444444", + "rO0ABXNyACJzdW4uc2VjdXJpdHkudXRpbC5PYmplY3RJZGVudGlmaWVyeLIO7GQX" + + "fy4DAANJAAxjb21wb25lbnRMZW5MAApjb21wb25lbnRzdAASTGphdmEvbGFuZy9P" + + "YmplY3Q7WwAIZW5jb2Rpbmd0AAJbQnhw/////3NyAD5zdW4uc2VjdXJpdHkudXRp" + + "bC5PYmplY3RJZGVudGlmaWVyJEh1Z2VPaWROb3RTdXBwb3J0ZWRCeU9sZEpESwAA" + + "AAAAAAABAgAAeHB1cgACW0Ks8xf4BghU4AIAAHhwAAAAGCqP5Yzbxa6cOLubj9ek" + + "japVio3AusuOHHg="); + + dump6.put("0.0", + "rO0ABXNyACJzdW4uc2VjdXJpdHkudXRpbC5PYmplY3RJZGVudGlmaWVyeLIO7GQX" + + "fy4CAAJJAAxjb21wb25lbnRMZW5bAApjb21wb25lbnRzdAACW0l4cAAAAAJ1cgAC" + + "W0lNumAmduqypQIAAHhwAAAAAgAAAAAAAAAA"); + dump6.put("1.1", + "rO0ABXNyACJzdW4uc2VjdXJpdHkudXRpbC5PYmplY3RJZGVudGlmaWVyeLIO7GQX" + + "fy4CAAJJAAxjb21wb25lbnRMZW5bAApjb21wb25lbnRzdAACW0l4cAAAAAJ1cgAC" + + "W0lNumAmduqypQIAAHhwAAAAAgAAAAEAAAAB"); + dump6.put("2.2", + "rO0ABXNyACJzdW4uc2VjdXJpdHkudXRpbC5PYmplY3RJZGVudGlmaWVyeLIO7GQX" + + "fy4CAAJJAAxjb21wb25lbnRMZW5bAApjb21wb25lbnRzdAACW0l4cAAAAAJ1cgAC" + + "W0lNumAmduqypQIAAHhwAAAAAgAAAAIAAAAC"); + dump6.put("1.2.3456", + "rO0ABXNyACJzdW4uc2VjdXJpdHkudXRpbC5PYmplY3RJZGVudGlmaWVyeLIO7GQX" + + "fy4CAAJJAAxjb21wb25lbnRMZW5bAApjb21wb25lbnRzdAACW0l4cAAAAAN1cgAC" + + "W0lNumAmduqypQIAAHhwAAAAAwAAAAEAAAACAAANgA=="); + dump6.put("1.2.2147483647.4", + "rO0ABXNyACJzdW4uc2VjdXJpdHkudXRpbC5PYmplY3RJZGVudGlmaWVyeLIO7GQX" + + "fy4CAAJJAAxjb21wb25lbnRMZW5bAApjb21wb25lbnRzdAACW0l4cAAAAAR1cgAC" + + "W0lNumAmduqypQIAAHhwAAAABAAAAAEAAAACf////wAAAAQ="); + dump6.put("1.2.268435456.4", + "rO0ABXNyACJzdW4uc2VjdXJpdHkudXRpbC5PYmplY3RJZGVudGlmaWVyeLIO7GQX" + + "fy4CAAJJAAxjb21wb25lbnRMZW5bAApjb21wb25lbnRzdAACW0l4cAAAAAR1cgAC" + + "W0lNumAmduqypQIAAHhwAAAABAAAAAEAAAACEAAAAAAAAAQ="); + ////////////// PASTE END ////////////// + } +} diff --git a/jdk/test/sun/security/util/Oid/S11N.sh b/jdk/test/sun/security/util/Oid/S11N.sh deleted file mode 100644 index a19af17be5f..00000000000 --- a/jdk/test/sun/security/util/Oid/S11N.sh +++ /dev/null @@ -1,188 +0,0 @@ -# -# Copyright (c) 2004, 2012, 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. -# -# 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. -# -# @test -# @bug 4811968 6908628 -# @summary Serialization compatibility with old versions (and fix) -# @author Weijun Wang -# -# set a few environment variables so that the shell-script can run stand-alone -# in the source directory - -if [ "${TESTSRC}" = "" ] ; then - TESTSRC="." -fi -if [ "${TESTCLASSES}" = "" ] ; then - TESTCLASSES="." -fi -if [ "${TESTJAVA}" = "" ] ; then - echo "TESTJAVA not set. Test cannot execute." - echo "FAILED!!!" - exit 1 -fi -if [ "${COMPILEJAVA}" = "" ]; then - COMPILEJAVA="${TESTJAVA}" -fi - -# set platform-dependent variables -PF="" - -OS=`uname -s` -case "$OS" in - SunOS ) - FS="/" - ARCH=`isainfo` - case "$ARCH" in - sparc* ) - PF="solaris-sparc" - ;; - i[3-6]86 ) - PF="solaris-i586" - ;; - amd64* ) - PF="solaris-amd64" - ;; - * ) - echo "Unsupported System: Solaris ${ARCH}" - exit 0; - ;; - esac - ;; - Linux ) - ARCH=`uname -m` - FS="/" - case "$ARCH" in - i[3-6]86 ) - PF="linux-i586" - ;; - amd64* | x86_64 ) - PF="linux-amd64" - ;; - * ) - echo "Unsupported System: Linux ${ARCH}" - exit 0; - ;; - esac - ;; - Windows* ) - FS="\\" - PF="windows-i586" - - # 'uname -m' does not give us enough information - - # should rely on $PROCESSOR_IDENTIFIER (as is done in Defs-windows.gmk), - # but JTREG does not pass this env variable when executing a shell script. - # - # execute test program - rely on it to exit if platform unsupported - - ;; - * ) - echo "Unsupported System: ${OS}" - exit 0; - ;; -esac - -echo "===================================================" -echo "Try to set ALT_JAVA_RE_JDK if you see timeout error" -echo "===================================================" - -# the test code - -${COMPILEJAVA}${FS}bin${FS}javac -target 1.4 -source 1.4 \ - -d . ${TESTSRC}${FS}SerialTest.java || exit 10 - -# You can set ALT_JAVA_RE_JDK to another location that contains the -# binaries for older JDK releases. You can set it to a non-existent -# directory to skip the interop tests between different versions. - -if [ "$ALT_JAVA_RE_JDK" = "" ]; then - JAVA_RE_JDK=/java/re/j2se -else - JAVA_RE_JDK=$ALT_JAVA_RE_JDK -fi - -OLDJAVA=" - $JAVA_RE_JDK/1.6.0/latest/binaries/${PF} - $JAVA_RE_JDK/1.5.0/latest/binaries/${PF} - $JAVA_RE_JDK/1.4.2/latest/binaries/${PF} -" - -SMALL=" - 0.0 - 1.1 - 2.2 - 1.2.3456 - 1.2.2147483647.4 - 1.2.268435456.4 -" - -HUGE=" - 2.16.764.1.3101555394.1.0.100.2.1 - 1.2.2147483648.4 - 2.3.4444444444444444444444 - 1.2.888888888888888888.111111111111111.2222222222222.33333333333333333.44444444444444 -" - -for oid in ${SMALL}; do - echo ${oid} - # new -> - ${TESTJAVA}${FS}bin${FS}java SerialTest out ${oid} > tmp.oid.serial || exit 1 - # -> new - ${TESTJAVA}${FS}bin${FS}java SerialTest in ${oid} < tmp.oid.serial || exit 2 - for oldj in ${OLDJAVA}; do - if [ -d ${oldj} ]; then - echo ${oldj} - # -> old - ${oldj}${FS}bin${FS}java SerialTest in ${oid} < tmp.oid.serial || exit 3 - # old -> - ${oldj}${FS}bin${FS}java SerialTest out ${oid} > tmp.oid.serial.old || exit 4 - # -> new - ${TESTJAVA}${FS}bin${FS}java SerialTest in ${oid} < tmp.oid.serial.old || exit 5 - fi - done -done - -for oid in ${HUGE}; do - echo ${oid} - # new -> - ${TESTJAVA}${FS}bin${FS}java SerialTest out ${oid} > tmp.oid.serial || exit 1 - # -> new - ${TESTJAVA}${FS}bin${FS}java SerialTest in ${oid} < tmp.oid.serial || exit 2 - for oldj in ${OLDJAVA}; do - if [ -d ${oldj} ]; then - echo ${oldj} - # -> old - ${oldj}${FS}bin${FS}java SerialTest badin < tmp.oid.serial || exit 3 - fi - done -done - -rm -f tmp.oid.serial -rm -f tmp.oid.serial.old -rm -f SerialTest.class - -for oldj in ${OLDJAVA}; do - if [ ! -d ${oldj} ]; then - echo WARNING: ${oldj} is missing. Test incomplete! > /dev/stderr - fi -done - -exit 0 diff --git a/jdk/test/sun/security/util/Oid/SerialTest.java b/jdk/test/sun/security/util/Oid/SerialTest.java deleted file mode 100644 index ba127441cad..00000000000 --- a/jdk/test/sun/security/util/Oid/SerialTest.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (c) 2004, 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. - * - * 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. - */ - -/* - * read S11.sh - */ -import java.io.*; -import sun.security.util.*; - -/** - * Test OID serialization between versions - * - * java SerialTest out oid // write a OID into System.out - * java SerialTest in oid // read from System.in and compare it with oid - * java SerialTest badin // make sure *cannot* read from System.in - */ -class SerialTest { - public static void main(String[] args) throws Exception { - if (args[0].equals("out")) - out(args[1]); - else if (args[0].equals("in")) - in(args[1]); - else - badin(); - } - - static void in(String oid) throws Exception { - ObjectIdentifier o = (ObjectIdentifier) (new ObjectInputStream(System.in).readObject()); - if (!o.toString().equals(oid)) - throw new Exception("Read Fail " + o + ", not " + oid); - } - - static void badin() throws Exception { - boolean pass = true; - try { - new ObjectInputStream(System.in).readObject(); - } catch (Exception e) { - pass = false; - } - if (pass) throw new Exception("Should fail but not"); - } - - static void out(String oid) throws Exception { - new ObjectOutputStream(System.out).writeObject(new ObjectIdentifier(oid)); - } -} From f9329eb66f344eda820d8d4034bdbbe9af68f982 Mon Sep 17 00:00:00 2001 From: David Katleman Date: Thu, 31 Jan 2013 17:04:19 -0800 Subject: [PATCH 133/210] Added tag jdk8-b75 for changeset a86f171d15a1 --- .hgtags-top-repo | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags-top-repo b/.hgtags-top-repo index 53096d3923b..4b6644480b7 100644 --- a/.hgtags-top-repo +++ b/.hgtags-top-repo @@ -196,3 +196,4 @@ cdb401a60cea6ad5ef3f498725ed1decf8dda1ea jdk8-b68 c1be681d80a1f1c848dc671d664fccb19e046a12 jdk8-b72 93b9664f97eeb6f89397a8842318ebacaac9feb9 jdk8-b73 b43aa5bd8ca5c8121336495382d35ecfa7a71536 jdk8-b74 +2a713921952cbd77a1e699626976cb6cdfe3e57e jdk8-b75 From 7ecc657cee4e28a89e4a06334dae901dd8cc9533 Mon Sep 17 00:00:00 2001 From: David Katleman Date: Thu, 31 Jan 2013 17:04:24 -0800 Subject: [PATCH 134/210] Added tag jdk8-b75 for changeset 5aa96ebbc95e --- corba/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/corba/.hgtags b/corba/.hgtags index c01bb26f197..294902d0bc8 100644 --- a/corba/.hgtags +++ b/corba/.hgtags @@ -196,3 +196,4 @@ d54dc53e223ed9ce7d5f4d2cd02ad9d5def3c2db jdk8-b59 cb40427f47145b01b7e53c3e02b38ff7625efbda jdk8-b72 191afde59e7be0e1a1d76d06f2a32ff17444f0ec jdk8-b73 2132845cf5f717ff5c240a2431c0c0e03e66e3a5 jdk8-b74 +d4e68ce17795601017ac2f952baad7272942c36e jdk8-b75 From 545ef0e5fe5a1ac74e95c5beeb8218c89a94c57f Mon Sep 17 00:00:00 2001 From: David Katleman Date: Thu, 31 Jan 2013 17:04:28 -0800 Subject: [PATCH 135/210] Added tag jdk8-b75 for changeset 3b129a5ff9fd --- hotspot/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/hotspot/.hgtags b/hotspot/.hgtags index d46eb646def..494b1c8a523 100644 --- a/hotspot/.hgtags +++ b/hotspot/.hgtags @@ -311,3 +311,4 @@ d5cb5830f570d1304ea4b196dde672a291b55f29 jdk8-b72 70c89bd6b895a10d25ca70e08093c09ff2005fda hs25-b16 1a3e54283c54aaa8b3437813e8507fbdc966e5b6 jdk8-b74 b4391649e91ea8d37f66317a03d6d2573a93d10d hs25-b17 +6778d0b1659323a506ca47600ca29a9d9f8b383d jdk8-b75 From 34d99c6b392a2598cf8fc1d3b8f115fe00f8e0fc Mon Sep 17 00:00:00 2001 From: David Katleman Date: Thu, 31 Jan 2013 17:04:37 -0800 Subject: [PATCH 136/210] Added tag jdk8-b75 for changeset 504959da18bb --- jaxp/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/jaxp/.hgtags b/jaxp/.hgtags index 25b3727d9e6..172530e8a1a 100644 --- a/jaxp/.hgtags +++ b/jaxp/.hgtags @@ -196,3 +196,4 @@ b854e70084214e9dcf1b37373f6e4b1a68760e03 jdk8-b68 bdf2af722a6b54fca47d8c51d17a1b8f41dd7a3e jdk8-b72 84946404d1e1de003ed2bf218ef8d48906a90e37 jdk8-b73 2087e24a4357eceb6432e94918e75fdc706a27d6 jdk8-b74 +ff0b73a6b3f6cea644d37d56d746a37743419fa7 jdk8-b75 From 7c22c50e9e69743403dcea82aecf0ea05744b7c6 Mon Sep 17 00:00:00 2001 From: David Katleman Date: Thu, 31 Jan 2013 17:04:40 -0800 Subject: [PATCH 137/210] Added tag jdk8-b75 for changeset bef9d985cc1c --- jaxws/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/jaxws/.hgtags b/jaxws/.hgtags index 1ae97b3df38..5811938d611 100644 --- a/jaxws/.hgtags +++ b/jaxws/.hgtags @@ -196,3 +196,4 @@ f577a39c9fb3d5820248c13c2cc74a192a9313e0 jdk8-b71 d9707230294d54e695e745a90de6112909100f12 jdk8-b72 c606f644a5d9118c14b5822738bf23c300f14f24 jdk8-b73 12db3c5a3393b03eeb09ff26f418c4420c21aaab jdk8-b74 +966bf9f3c41a59ff5d86ff4275291c52f329f984 jdk8-b75 From 79896f3eafe913fff55222f58f107cc90cd36017 Mon Sep 17 00:00:00 2001 From: David Katleman Date: Thu, 31 Jan 2013 17:04:47 -0800 Subject: [PATCH 138/210] Added tag jdk8-b75 for changeset cfe93cb07f19 --- jdk/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/jdk/.hgtags b/jdk/.hgtags index dbc8d128f1f..ac37d19a025 100644 --- a/jdk/.hgtags +++ b/jdk/.hgtags @@ -196,3 +196,4 @@ a996b57e554198f4592a5f3c30f2f9f4075e545d jdk8-b70 32a57e645e012a1f0665c075969ca598e0dbb948 jdk8-b72 733885f57e14cc27f5a5ff0dffe641d2fa3c704a jdk8-b73 57d5d954462831ac353a1f40d3bb05ddb4620952 jdk8-b74 +4a67fdb752b7d6329d9be9c28d3f9d6cf7eb9a3c jdk8-b75 From 2ccecb9e10d1375305ccf142352c47907c3b640c Mon Sep 17 00:00:00 2001 From: David Katleman Date: Thu, 31 Jan 2013 17:04:55 -0800 Subject: [PATCH 139/210] Added tag jdk8-b75 for changeset dbafd8b0d8a2 --- langtools/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/langtools/.hgtags b/langtools/.hgtags index f4fbd85e67d..b29a3af53a1 100644 --- a/langtools/.hgtags +++ b/langtools/.hgtags @@ -196,3 +196,4 @@ d7360bf35ee1f40ff78c2e83a22b5446ee464346 jdk8-b69 6f0986ed9b7e11d6eb06618f27e20b18f19fb797 jdk8-b72 8d0baee36c7184d55c80354b45704c37d6b7ac79 jdk8-b73 56c97aff46bb577b8668874154c24115a7e8a3e8 jdk8-b74 +c2e11e2ec4a3682513e566849e5562f31ded8c65 jdk8-b75 From b543c19bac8cece7e4ad6b4f82077fd255dae76b Mon Sep 17 00:00:00 2001 From: Yumin Qi Date: Thu, 31 Jan 2013 17:43:01 -0800 Subject: [PATCH 140/210] 8000973: SA on windows thread inspection is broken After bug 7161732, On Windows SA could not find correct address of thread_id of OSThread since _thread_id moved to end of the class . The presupposition of the address is following thread handle no longer stands. Fix by adding thread_id field to OSThread and getting the address directly from OSThread. Reviewed-by: nloodin, sspitsyn --- .../windbg/amd64/WindbgAMD64Thread.java | 18 ++++-------------- .../debugger/windbg/x86/WindbgX86Thread.java | 18 ++++-------------- .../sun/jvm/hotspot/runtime/OSThread.java | 9 ++++++++- .../Win32AMD64JavaThreadPDAccess.java | 14 +++++++------- .../win32_x86/Win32X86JavaThreadPDAccess.java | 14 +++++++------- 5 files changed, 30 insertions(+), 43 deletions(-) diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/windbg/amd64/WindbgAMD64Thread.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/windbg/amd64/WindbgAMD64Thread.java index bf30dd0a5bf..ec5aea35e8c 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/windbg/amd64/WindbgAMD64Thread.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/windbg/amd64/WindbgAMD64Thread.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2013, 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 @@ -34,21 +34,11 @@ class WindbgAMD64Thread implements ThreadProxy { private boolean gotID; private long id; - /** The address argument must be the address of the HANDLE of the - desired thread in the target process. */ + // The address argument must be the address of the OSThread::_thread_id WindbgAMD64Thread(WindbgDebugger debugger, Address addr) { this.debugger = debugger; - // FIXME: size of data fetched here should be configurable. - // However, making it so would produce a dependency on the "types" - // package from the debugger package, which is not desired. - - // another hack here is that we use sys thread id instead of handle. - // windbg can't get details based on handles it seems. - // I assume that osThread_win32 thread struct has _thread_id (which - // sys thread id) just after handle field. - - this.sysId = (int) addr.addOffsetTo(debugger.getAddressSize()).getCIntegerAt(0, 4, true); - gotID = false; + this.sysId = (long)addr.getCIntegerAt(0, 4, true); + gotID = false; } WindbgAMD64Thread(WindbgDebugger debugger, long sysId) { diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/windbg/x86/WindbgX86Thread.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/windbg/x86/WindbgX86Thread.java index 84d19e03bc0..e5417972b13 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/windbg/x86/WindbgX86Thread.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/windbg/x86/WindbgX86Thread.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2003, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2013, 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 @@ -34,21 +34,11 @@ class WindbgX86Thread implements ThreadProxy { private boolean gotID; private long id; - /** The address argument must be the address of the HANDLE of the - desired thread in the target process. */ + // The address argument must be the address of OSThread::_thread_id WindbgX86Thread(WindbgDebugger debugger, Address addr) { this.debugger = debugger; - // FIXME: size of data fetched here should be configurable. - // However, making it so would produce a dependency on the "types" - // package from the debugger package, which is not desired. - - // another hack here is that we use sys thread id instead of handle. - // windbg can't get details based on handles it seems. - // I assume that osThread_win32 thread struct has _thread_id (which - // sys thread id) just after handle field. - - this.sysId = (int) addr.addOffsetTo(debugger.getAddressSize()).getCIntegerAt(0, 4, true); - gotID = false; + this.sysId = (long)addr.getCIntegerAt(0, 4, true); + gotID = false; } WindbgX86Thread(WindbgDebugger debugger, long sysId) { diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/OSThread.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/OSThread.java index cdcbf113871..fb17c53d329 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/OSThread.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/OSThread.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2013, 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 @@ -32,6 +32,7 @@ import sun.jvm.hotspot.types.*; // to the sys_thread_t structure of the classic JVM implementation. public class OSThread extends VMObject { private static JIntField interruptedField; + private static JIntField threadIdField; static { VM.registerVMInitializedObserver(new Observer() { public void update(Observable o, Object data) { @@ -43,6 +44,7 @@ public class OSThread extends VMObject { private static synchronized void initialize(TypeDataBase db) { Type type = db.lookupType("OSThread"); interruptedField = type.getJIntField("_interrupted"); + threadIdField = type.getJIntField("_thread_id"); } public OSThread(Address addr) { @@ -52,4 +54,9 @@ public class OSThread extends VMObject { public boolean interrupted() { return ((int)interruptedField.getValue(addr)) != 0; } + + public int threadId() { + return (int)threadIdField.getValue(addr); + } + } diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/win32_amd64/Win32AMD64JavaThreadPDAccess.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/win32_amd64/Win32AMD64JavaThreadPDAccess.java index e18dd4f8053..86255a48f6e 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/win32_amd64/Win32AMD64JavaThreadPDAccess.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/win32_amd64/Win32AMD64JavaThreadPDAccess.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2013, 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 @@ -43,7 +43,7 @@ public class Win32AMD64JavaThreadPDAccess implements JavaThreadPDAccess { private static AddressField osThreadField; // Field from OSThread - private static Field osThreadThreadHandleField; + private static Field osThreadThreadIdField; // This is currently unneeded but is being kept in case we change // the currentFrameGuess algorithm @@ -64,7 +64,7 @@ public class Win32AMD64JavaThreadPDAccess implements JavaThreadPDAccess { osThreadField = type.getAddressField("_osthread"); type = db.lookupType("OSThread"); - osThreadThreadHandleField = type.getField("_thread_handle"); + osThreadThreadIdField = type.getField("_thread_id"); } public Address getLastJavaFP(Address addr) { @@ -128,10 +128,10 @@ public class Win32AMD64JavaThreadPDAccess implements JavaThreadPDAccess { // Fetch the OSThread (for now and for simplicity, not making a // separate "OSThread" class in this package) Address osThreadAddr = osThreadField.getValue(addr); - // Get the address of the HANDLE within the OSThread - Address threadHandleAddr = - osThreadAddr.addOffsetTo(osThreadThreadHandleField.getOffset()); + // Get the address of the thread_id within the OSThread + Address threadIdAddr = + osThreadAddr.addOffsetTo(osThreadThreadIdField.getOffset()); JVMDebugger debugger = VM.getVM().getDebugger(); - return debugger.getThreadForIdentifierAddress(threadHandleAddr); + return debugger.getThreadForIdentifierAddress(threadIdAddr); } } diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/win32_x86/Win32X86JavaThreadPDAccess.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/win32_x86/Win32X86JavaThreadPDAccess.java index dff6615a008..435e4762335 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/win32_x86/Win32X86JavaThreadPDAccess.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/win32_x86/Win32X86JavaThreadPDAccess.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2013, 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 @@ -42,7 +42,7 @@ public class Win32X86JavaThreadPDAccess implements JavaThreadPDAccess { private static AddressField osThreadField; // Field from OSThread - private static Field osThreadThreadHandleField; + private static Field osThreadThreadIdField; // This is currently unneeded but is being kept in case we change // the currentFrameGuess algorithm @@ -63,7 +63,7 @@ public class Win32X86JavaThreadPDAccess implements JavaThreadPDAccess { osThreadField = type.getAddressField("_osthread"); type = db.lookupType("OSThread"); - osThreadThreadHandleField = type.getField("_thread_handle"); + osThreadThreadIdField = type.getField("_thread_id"); } public Address getLastJavaFP(Address addr) { @@ -127,10 +127,10 @@ public class Win32X86JavaThreadPDAccess implements JavaThreadPDAccess { // Fetch the OSThread (for now and for simplicity, not making a // separate "OSThread" class in this package) Address osThreadAddr = osThreadField.getValue(addr); - // Get the address of the HANDLE within the OSThread - Address threadHandleAddr = - osThreadAddr.addOffsetTo(osThreadThreadHandleField.getOffset()); + // Get the address of the thread_id within the OSThread + Address threadIdAddr = + osThreadAddr.addOffsetTo(osThreadThreadIdField.getOffset()); JVMDebugger debugger = VM.getVM().getDebugger(); - return debugger.getThreadForIdentifierAddress(threadHandleAddr); + return debugger.getThreadForIdentifierAddress(threadIdAddr); } } From 71b457cb970e0bb791bf79a9f2707f453f861eab Mon Sep 17 00:00:00 2001 From: Joe Darcy Date: Thu, 31 Jan 2013 18:58:17 -0800 Subject: [PATCH 141/210] 8007351: Malformed copyright statements in typeAnnotations test directory Reviewed-by: jjg --- .../typeAnnotations/TargetTypes.java | 2 +- .../typeAnnotations/TypeProcOnly.java | 2 +- .../api/AnnotatedArrayOrder.java | 2 +- .../typeAnnotations/api/ArrayCreationTree.java | 2 +- .../api/ArrayPositionConsistency.java | 2 +- .../classfile/ClassfileTestHelper.java | 2 +- .../classfile/CombinationsTargetTest1.java | 2 +- .../classfile/CombinationsTargetTest2.java | 2 +- .../classfile/NewTypeArguments.java | 2 +- .../classfile/NoTargetAnnotations.java | 2 +- .../typeAnnotations/classfile/TypeCasts.java | 2 +- .../typeAnnotations/classfile/Wildcards.java | 2 +- .../failures/target/DotClass.java | 18 +++++++++--------- .../typeAnnotations/newlocations/Varargs.java | 7 +++---- .../packageanno/PackageProcessor.java | 2 +- .../packageanno/mypackage/Anno.java | 2 +- .../packageanno/mypackage/MyClass.java | 2 +- .../packageanno/mypackage/package-info.java | 2 +- .../referenceinfos/ClassExtends.java | 2 +- .../referenceinfos/ClassTypeParam.java | 2 +- .../referenceinfos/Constructors.java | 2 +- .../typeAnnotations/referenceinfos/Driver.java | 2 +- .../referenceinfos/ExceptionParameters.java | 2 +- .../typeAnnotations/referenceinfos/Fields.java | 2 +- .../referenceinfos/FromSpecification.java | 2 +- .../referenceinfos/MethodParameters.java | 2 +- .../referenceinfos/MethodReceivers.java | 2 +- .../referenceinfos/MethodReturns.java | 2 +- .../referenceinfos/MethodThrows.java | 2 +- .../referenceinfos/MethodTypeParam.java | 2 +- .../referenceinfos/MultiCatch.java | 2 +- .../referenceinfos/NestedTypes.java | 2 +- .../referenceinfos/NewObjects.java | 2 +- .../referenceinfos/ReferenceInfoUtil.java | 2 +- .../RepeatingTypeAnnotations.java | 2 +- .../referenceinfos/TypeCasts.java | 2 +- .../referenceinfos/TypeTests.java | 2 +- 37 files changed, 47 insertions(+), 48 deletions(-) diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/TargetTypes.java b/langtools/test/tools/javac/annotations/typeAnnotations/TargetTypes.java index f808a8d4cda..8ffa7e5b53c 100644 --- a/langtools/test/tools/javac/annotations/typeAnnotations/TargetTypes.java +++ b/langtools/test/tools/javac/annotations/typeAnnotations/TargetTypes.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 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 diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/TypeProcOnly.java b/langtools/test/tools/javac/annotations/typeAnnotations/TypeProcOnly.java index 73d28971ee0..31ec31adceb 100644 --- a/langtools/test/tools/javac/annotations/typeAnnotations/TypeProcOnly.java +++ b/langtools/test/tools/javac/annotations/typeAnnotations/TypeProcOnly.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 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 diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/api/AnnotatedArrayOrder.java b/langtools/test/tools/javac/annotations/typeAnnotations/api/AnnotatedArrayOrder.java index 947b46536cc..68f11f5e64c 100644 --- a/langtools/test/tools/javac/annotations/typeAnnotations/api/AnnotatedArrayOrder.java +++ b/langtools/test/tools/javac/annotations/typeAnnotations/api/AnnotatedArrayOrder.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 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 diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/api/ArrayCreationTree.java b/langtools/test/tools/javac/annotations/typeAnnotations/api/ArrayCreationTree.java index 55f81eb7cf6..952f37c2b92 100644 --- a/langtools/test/tools/javac/annotations/typeAnnotations/api/ArrayCreationTree.java +++ b/langtools/test/tools/javac/annotations/typeAnnotations/api/ArrayCreationTree.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 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 diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/api/ArrayPositionConsistency.java b/langtools/test/tools/javac/annotations/typeAnnotations/api/ArrayPositionConsistency.java index 7d00ef3aa19..1b73d918a03 100644 --- a/langtools/test/tools/javac/annotations/typeAnnotations/api/ArrayPositionConsistency.java +++ b/langtools/test/tools/javac/annotations/typeAnnotations/api/ArrayPositionConsistency.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 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 diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/classfile/ClassfileTestHelper.java b/langtools/test/tools/javac/annotations/typeAnnotations/classfile/ClassfileTestHelper.java index a06407e0144..b02621639aa 100644 --- a/langtools/test/tools/javac/annotations/typeAnnotations/classfile/ClassfileTestHelper.java +++ b/langtools/test/tools/javac/annotations/typeAnnotations/classfile/ClassfileTestHelper.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2013 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2013, 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 diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/classfile/CombinationsTargetTest1.java b/langtools/test/tools/javac/annotations/typeAnnotations/classfile/CombinationsTargetTest1.java index dfab97807c2..ed3c094685c 100644 --- a/langtools/test/tools/javac/annotations/typeAnnotations/classfile/CombinationsTargetTest1.java +++ b/langtools/test/tools/javac/annotations/typeAnnotations/classfile/CombinationsTargetTest1.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 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 diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/classfile/CombinationsTargetTest2.java b/langtools/test/tools/javac/annotations/typeAnnotations/classfile/CombinationsTargetTest2.java index 77fb9a8aa1e..e3414db9f98 100644 --- a/langtools/test/tools/javac/annotations/typeAnnotations/classfile/CombinationsTargetTest2.java +++ b/langtools/test/tools/javac/annotations/typeAnnotations/classfile/CombinationsTargetTest2.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 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 diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/classfile/NewTypeArguments.java b/langtools/test/tools/javac/annotations/typeAnnotations/classfile/NewTypeArguments.java index 84b9a85b3ae..f39857cada1 100644 --- a/langtools/test/tools/javac/annotations/typeAnnotations/classfile/NewTypeArguments.java +++ b/langtools/test/tools/javac/annotations/typeAnnotations/classfile/NewTypeArguments.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 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 diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/classfile/NoTargetAnnotations.java b/langtools/test/tools/javac/annotations/typeAnnotations/classfile/NoTargetAnnotations.java index 6458d54234b..a5dc098811b 100644 --- a/langtools/test/tools/javac/annotations/typeAnnotations/classfile/NoTargetAnnotations.java +++ b/langtools/test/tools/javac/annotations/typeAnnotations/classfile/NoTargetAnnotations.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 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 diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/classfile/TypeCasts.java b/langtools/test/tools/javac/annotations/typeAnnotations/classfile/TypeCasts.java index 18f8e3b36bd..5529fa5a664 100644 --- a/langtools/test/tools/javac/annotations/typeAnnotations/classfile/TypeCasts.java +++ b/langtools/test/tools/javac/annotations/typeAnnotations/classfile/TypeCasts.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 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 diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/classfile/Wildcards.java b/langtools/test/tools/javac/annotations/typeAnnotations/classfile/Wildcards.java index d4621047ac5..e0301520d74 100644 --- a/langtools/test/tools/javac/annotations/typeAnnotations/classfile/Wildcards.java +++ b/langtools/test/tools/javac/annotations/typeAnnotations/classfile/Wildcards.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 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 diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/target/DotClass.java b/langtools/test/tools/javac/annotations/typeAnnotations/failures/target/DotClass.java index 9aaa99e7e99..6363da0a301 100644 --- a/langtools/test/tools/javac/annotations/typeAnnotations/failures/target/DotClass.java +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/target/DotClass.java @@ -1,13 +1,5 @@ -import static java.lang.annotation.ElementType.TYPE; -import static java.lang.annotation.ElementType.TYPE_PARAMETER; -import static java.lang.annotation.ElementType.TYPE_USE; - -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - /* - * Copyright (c) 2009 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 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 @@ -36,6 +28,14 @@ import java.lang.annotation.Target; * @compile/fail/ref=DotClass.out -XDrawDiagnostics DotClass.java */ +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import static java.lang.annotation.ElementType.TYPE; +import static java.lang.annotation.ElementType.TYPE_PARAMETER; +import static java.lang.annotation.ElementType.TYPE_USE; + @Target({TYPE_USE, TYPE_PARAMETER, TYPE}) @Retention(RetentionPolicy.RUNTIME) @interface A {} diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/Varargs.java b/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/Varargs.java index d28c108a6c6..e0c3082ebb6 100644 --- a/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/Varargs.java +++ b/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/Varargs.java @@ -1,6 +1,5 @@ - /* - * Copyright (c) 2008 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 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 @@ -22,8 +21,6 @@ * questions. */ -import java.lang.annotation.*; - /* * @test * @summary test acceptance of varargs annotations @@ -31,6 +28,8 @@ import java.lang.annotation.*; * @compile Varargs.java */ +import java.lang.annotation.*; + @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) @interface A {} diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/packageanno/PackageProcessor.java b/langtools/test/tools/javac/annotations/typeAnnotations/packageanno/PackageProcessor.java index 4f0d56522f9..02e20ad3b19 100644 --- a/langtools/test/tools/javac/annotations/typeAnnotations/packageanno/PackageProcessor.java +++ b/langtools/test/tools/javac/annotations/typeAnnotations/packageanno/PackageProcessor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 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 diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/packageanno/mypackage/Anno.java b/langtools/test/tools/javac/annotations/typeAnnotations/packageanno/mypackage/Anno.java index 25f05341fbc..901cb6c9850 100644 --- a/langtools/test/tools/javac/annotations/typeAnnotations/packageanno/mypackage/Anno.java +++ b/langtools/test/tools/javac/annotations/typeAnnotations/packageanno/mypackage/Anno.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 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 diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/packageanno/mypackage/MyClass.java b/langtools/test/tools/javac/annotations/typeAnnotations/packageanno/mypackage/MyClass.java index e955ffc825e..98f9e433880 100644 --- a/langtools/test/tools/javac/annotations/typeAnnotations/packageanno/mypackage/MyClass.java +++ b/langtools/test/tools/javac/annotations/typeAnnotations/packageanno/mypackage/MyClass.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 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 diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/packageanno/mypackage/package-info.java b/langtools/test/tools/javac/annotations/typeAnnotations/packageanno/mypackage/package-info.java index f80bd8afa53..bcd7fb672e8 100644 --- a/langtools/test/tools/javac/annotations/typeAnnotations/packageanno/mypackage/package-info.java +++ b/langtools/test/tools/javac/annotations/typeAnnotations/packageanno/mypackage/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 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 diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/ClassExtends.java b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/ClassExtends.java index 5fd9751879a..4d5f2db0a12 100644 --- a/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/ClassExtends.java +++ b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/ClassExtends.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 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 diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/ClassTypeParam.java b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/ClassTypeParam.java index 0d82706984f..2fca8089824 100644 --- a/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/ClassTypeParam.java +++ b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/ClassTypeParam.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 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 diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/Constructors.java b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/Constructors.java index 2ad8b31badc..bbdcba3f319 100644 --- a/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/Constructors.java +++ b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/Constructors.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/Driver.java b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/Driver.java index 052d11a77a2..042b7b0b1db 100644 --- a/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/Driver.java +++ b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/Driver.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2013 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2013, 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 diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/ExceptionParameters.java b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/ExceptionParameters.java index 70ca77aa560..a7c2818cf5d 100644 --- a/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/ExceptionParameters.java +++ b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/ExceptionParameters.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 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 diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/Fields.java b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/Fields.java index d352fa79b23..91bc6496a98 100644 --- a/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/Fields.java +++ b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/Fields.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 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 diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/FromSpecification.java b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/FromSpecification.java index e8e111d8c30..c3006390219 100644 --- a/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/FromSpecification.java +++ b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/FromSpecification.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/MethodParameters.java b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/MethodParameters.java index cfe36ed9ae2..c23636c2f82 100644 --- a/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/MethodParameters.java +++ b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/MethodParameters.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 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 diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/MethodReceivers.java b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/MethodReceivers.java index c834d0cef56..dc19f8d12fd 100644 --- a/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/MethodReceivers.java +++ b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/MethodReceivers.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 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 diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/MethodReturns.java b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/MethodReturns.java index 07fc9f23742..b6946817666 100644 --- a/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/MethodReturns.java +++ b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/MethodReturns.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 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 diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/MethodThrows.java b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/MethodThrows.java index 155e4bbfb71..457ca5b0a10 100644 --- a/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/MethodThrows.java +++ b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/MethodThrows.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 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 diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/MethodTypeParam.java b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/MethodTypeParam.java index 4b7b521904f..5798eaa9b49 100644 --- a/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/MethodTypeParam.java +++ b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/MethodTypeParam.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 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 diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/MultiCatch.java b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/MultiCatch.java index d62d52ff158..69694e453be 100644 --- a/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/MultiCatch.java +++ b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/MultiCatch.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 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 diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/NestedTypes.java b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/NestedTypes.java index 476e23f05ce..e98df7bd0c2 100644 --- a/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/NestedTypes.java +++ b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/NestedTypes.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/NewObjects.java b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/NewObjects.java index b56dbb74d23..fb3e3f55eeb 100644 --- a/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/NewObjects.java +++ b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/NewObjects.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 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 diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/ReferenceInfoUtil.java b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/ReferenceInfoUtil.java index 0a94ee07de3..33ae4edaabf 100644 --- a/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/ReferenceInfoUtil.java +++ b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/ReferenceInfoUtil.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 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 diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/RepeatingTypeAnnotations.java b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/RepeatingTypeAnnotations.java index 2755b4871c7..22982ae4d27 100644 --- a/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/RepeatingTypeAnnotations.java +++ b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/RepeatingTypeAnnotations.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/TypeCasts.java b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/TypeCasts.java index c77dcdc5857..84e5e01b358 100644 --- a/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/TypeCasts.java +++ b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/TypeCasts.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 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 diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/TypeTests.java b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/TypeTests.java index 5aa07b88db6..3b319197afe 100644 --- a/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/TypeTests.java +++ b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/TypeTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 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 From 64ef3bfccc0e26860369c1a3c2af293846c1f5f3 Mon Sep 17 00:00:00 2001 From: Jonathan Gibbons Date: Thu, 31 Jan 2013 19:19:40 -0800 Subject: [PATCH 142/210] 8007329: minor issues in impl class hierarchry for DCTree.* classes Reviewed-by: darcy --- .../share/classes/com/sun/tools/javac/tree/DCTree.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/langtools/src/share/classes/com/sun/tools/javac/tree/DCTree.java b/langtools/src/share/classes/com/sun/tools/javac/tree/DCTree.java index e49cabe0838..c2ca23caf4b 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/tree/DCTree.java +++ b/langtools/src/share/classes/com/sun/tools/javac/tree/DCTree.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2013, 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 @@ -119,7 +119,7 @@ public abstract class DCTree implements DocTree { } - public static abstract class DCBlockTag extends DCTree implements InlineTagTree { + public static abstract class DCBlockTag extends DCTree implements BlockTagTree { public String getTagName() { return getKind().tagName; } @@ -169,7 +169,7 @@ public abstract class DCTree implements DocTree { } } - public static class DCAuthor extends DCInlineTag implements AuthorTree { + public static class DCAuthor extends DCBlockTag implements AuthorTree { public final List name; DCAuthor(List name) { @@ -640,7 +640,7 @@ public abstract class DCTree implements DocTree { } } - public static class DCSince extends DCInlineTag implements SinceTree { + public static class DCSince extends DCBlockTag implements SinceTree { public final List body; DCSince(List body) { From 9bf4d2f978334791faf107a406870e1316b18cb2 Mon Sep 17 00:00:00 2001 From: Roger Riggs Date: Thu, 31 Jan 2013 19:31:37 -0800 Subject: [PATCH 143/210] 8004353: Generated html is wrong for overview.html; content has incorrect css footer class Reviewed-by: jjg --- .../tools/doclets/formats/html/PackageIndexWriter.java | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/PackageIndexWriter.java b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/PackageIndexWriter.java index 77d2bae2fe4..c5df5f3413a 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/PackageIndexWriter.java +++ b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/PackageIndexWriter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, 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 @@ -196,10 +196,7 @@ public class PackageIndexWriter extends AbstractPackageIndexWriter { protected void addOverviewComment(Content htmltree) { if (root.inlineTags().length > 0) { htmltree.addContent(getMarkerAnchor("overview_description")); - HtmlTree div = new HtmlTree(HtmlTag.DIV); - div.addStyle(HtmlStyle.subTitle); - addInlineComment(root, div); - htmltree.addContent(div); + addInlineComment(root, htmltree); } } @@ -211,7 +208,7 @@ public class PackageIndexWriter extends AbstractPackageIndexWriter { */ protected void addOverview(Content body) throws IOException { HtmlTree div = new HtmlTree(HtmlTag.DIV); - div.addStyle(HtmlStyle.footer); + div.addStyle(HtmlStyle.contentContainer); addOverviewComment(div); addTagsInfo(root, div); body.addContent(div); From 823c749bd14cd3e956ad34d8f29ac43cdaacecef Mon Sep 17 00:00:00 2001 From: Serguei Spitsyn Date: Thu, 31 Jan 2013 20:07:18 -0800 Subject: [PATCH 144/210] 8006542: JSR 292: the VM_RedefineClasses::append_entry() must support invokedynamic entry kinds Need a support for invokedynamic entry kinds when new and old constant pools are merged. Reviewed-by: coleenp, twisti --- .../share/vm/prims/jvmtiRedefineClasses.cpp | 236 ++++++++---------- .../share/vm/prims/jvmtiRedefineClasses.hpp | 5 +- 2 files changed, 110 insertions(+), 131 deletions(-) diff --git a/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp b/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp index 97799b9ad30..a09fa16ed0c 100644 --- a/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp +++ b/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp @@ -278,76 +278,23 @@ void VM_RedefineClasses::append_entry(constantPoolHandle scratch_cp, case JVM_CONSTANT_NameAndType: { int name_ref_i = scratch_cp->name_ref_index_at(scratch_i); - int new_name_ref_i = 0; - bool match = (name_ref_i < *merge_cp_length_p) && - scratch_cp->compare_entry_to(name_ref_i, *merge_cp_p, name_ref_i, - THREAD); - if (!match) { - // forward reference in *merge_cp_p or not a direct match - - int found_i = scratch_cp->find_matching_entry(name_ref_i, *merge_cp_p, - THREAD); - if (found_i != 0) { - guarantee(found_i != name_ref_i, - "compare_entry_to() and find_matching_entry() do not agree"); - - // Found a matching entry somewhere else in *merge_cp_p so - // just need a mapping entry. - new_name_ref_i = found_i; - map_index(scratch_cp, name_ref_i, found_i); - } else { - // no match found so we have to append this entry to *merge_cp_p - append_entry(scratch_cp, name_ref_i, merge_cp_p, merge_cp_length_p, - THREAD); - // The above call to append_entry() can only append one entry - // so the post call query of *merge_cp_length_p is only for - // the sake of consistency. - new_name_ref_i = *merge_cp_length_p - 1; - } - } + int new_name_ref_i = find_or_append_indirect_entry(scratch_cp, name_ref_i, merge_cp_p, + merge_cp_length_p, THREAD); int signature_ref_i = scratch_cp->signature_ref_index_at(scratch_i); - int new_signature_ref_i = 0; - match = (signature_ref_i < *merge_cp_length_p) && - scratch_cp->compare_entry_to(signature_ref_i, *merge_cp_p, - signature_ref_i, THREAD); - if (!match) { - // forward reference in *merge_cp_p or not a direct match - - int found_i = scratch_cp->find_matching_entry(signature_ref_i, - *merge_cp_p, THREAD); - if (found_i != 0) { - guarantee(found_i != signature_ref_i, - "compare_entry_to() and find_matching_entry() do not agree"); - - // Found a matching entry somewhere else in *merge_cp_p so - // just need a mapping entry. - new_signature_ref_i = found_i; - map_index(scratch_cp, signature_ref_i, found_i); - } else { - // no match found so we have to append this entry to *merge_cp_p - append_entry(scratch_cp, signature_ref_i, merge_cp_p, - merge_cp_length_p, THREAD); - // The above call to append_entry() can only append one entry - // so the post call query of *merge_cp_length_p is only for - // the sake of consistency. - new_signature_ref_i = *merge_cp_length_p - 1; - } - } + int new_signature_ref_i = find_or_append_indirect_entry(scratch_cp, signature_ref_i, + merge_cp_p, merge_cp_length_p, + THREAD); // If the referenced entries already exist in *merge_cp_p, then // both new_name_ref_i and new_signature_ref_i will both be 0. // In that case, all we are appending is the current entry. - if (new_name_ref_i == 0) { - new_name_ref_i = name_ref_i; - } else { + if (new_name_ref_i != name_ref_i) { RC_TRACE(0x00080000, ("NameAndType entry@%d name_ref_index change: %d to %d", *merge_cp_length_p, name_ref_i, new_name_ref_i)); } - if (new_signature_ref_i == 0) { - new_signature_ref_i = signature_ref_i; - } else { + if (new_signature_ref_i != signature_ref_i) { RC_TRACE(0x00080000, ("NameAndType entry@%d signature_ref_index change: %d to %d", *merge_cp_length_p, signature_ref_i, new_signature_ref_i)); @@ -369,76 +316,12 @@ void VM_RedefineClasses::append_entry(constantPoolHandle scratch_cp, case JVM_CONSTANT_Methodref: { int klass_ref_i = scratch_cp->uncached_klass_ref_index_at(scratch_i); - int new_klass_ref_i = 0; - bool match = (klass_ref_i < *merge_cp_length_p) && - scratch_cp->compare_entry_to(klass_ref_i, *merge_cp_p, klass_ref_i, - THREAD); - if (!match) { - // forward reference in *merge_cp_p or not a direct match + int new_klass_ref_i = find_or_append_indirect_entry(scratch_cp, klass_ref_i, + merge_cp_p, merge_cp_length_p, THREAD); - int found_i = scratch_cp->find_matching_entry(klass_ref_i, *merge_cp_p, - THREAD); - if (found_i != 0) { - guarantee(found_i != klass_ref_i, - "compare_entry_to() and find_matching_entry() do not agree"); - - // Found a matching entry somewhere else in *merge_cp_p so - // just need a mapping entry. - new_klass_ref_i = found_i; - map_index(scratch_cp, klass_ref_i, found_i); - } else { - // no match found so we have to append this entry to *merge_cp_p - append_entry(scratch_cp, klass_ref_i, merge_cp_p, merge_cp_length_p, - THREAD); - // The above call to append_entry() can only append one entry - // so the post call query of *merge_cp_length_p is only for - // the sake of consistency. Without the optimization where we - // use JVM_CONSTANT_UnresolvedClass, then up to two entries - // could be appended. - new_klass_ref_i = *merge_cp_length_p - 1; - } - } - - int name_and_type_ref_i = - scratch_cp->uncached_name_and_type_ref_index_at(scratch_i); - int new_name_and_type_ref_i = 0; - match = (name_and_type_ref_i < *merge_cp_length_p) && - scratch_cp->compare_entry_to(name_and_type_ref_i, *merge_cp_p, - name_and_type_ref_i, THREAD); - if (!match) { - // forward reference in *merge_cp_p or not a direct match - - int found_i = scratch_cp->find_matching_entry(name_and_type_ref_i, - *merge_cp_p, THREAD); - if (found_i != 0) { - guarantee(found_i != name_and_type_ref_i, - "compare_entry_to() and find_matching_entry() do not agree"); - - // Found a matching entry somewhere else in *merge_cp_p so - // just need a mapping entry. - new_name_and_type_ref_i = found_i; - map_index(scratch_cp, name_and_type_ref_i, found_i); - } else { - // no match found so we have to append this entry to *merge_cp_p - append_entry(scratch_cp, name_and_type_ref_i, merge_cp_p, - merge_cp_length_p, THREAD); - // The above call to append_entry() can append more than - // one entry so the post call query of *merge_cp_length_p - // is required in order to get the right index for the - // JVM_CONSTANT_NameAndType entry. - new_name_and_type_ref_i = *merge_cp_length_p - 1; - } - } - - // If the referenced entries already exist in *merge_cp_p, then - // both new_klass_ref_i and new_name_and_type_ref_i will both be - // 0. In that case, all we are appending is the current entry. - if (new_klass_ref_i == 0) { - new_klass_ref_i = klass_ref_i; - } - if (new_name_and_type_ref_i == 0) { - new_name_and_type_ref_i = name_and_type_ref_i; - } + int name_and_type_ref_i = scratch_cp->uncached_name_and_type_ref_index_at(scratch_i); + int new_name_and_type_ref_i = find_or_append_indirect_entry(scratch_cp, name_and_type_ref_i, + merge_cp_p, merge_cp_length_p, THREAD); const char *entry_name; switch (scratch_cp->tag_at(scratch_i).value()) { @@ -481,6 +364,72 @@ void VM_RedefineClasses::append_entry(constantPoolHandle scratch_cp, (*merge_cp_length_p)++; } break; + // this is an indirect CP entry so it needs special handling + case JVM_CONSTANT_MethodType: + { + int ref_i = scratch_cp->method_type_index_at(scratch_i); + int new_ref_i = find_or_append_indirect_entry(scratch_cp, ref_i, merge_cp_p, + merge_cp_length_p, THREAD); + if (new_ref_i != ref_i) { + RC_TRACE(0x00080000, + ("MethodType entry@%d ref_index change: %d to %d", + *merge_cp_length_p, ref_i, new_ref_i)); + } + (*merge_cp_p)->method_type_index_at_put(*merge_cp_length_p, new_ref_i); + if (scratch_i != *merge_cp_length_p) { + // The new entry in *merge_cp_p is at a different index than + // the new entry in scratch_cp so we need to map the index values. + map_index(scratch_cp, scratch_i, *merge_cp_length_p); + } + (*merge_cp_length_p)++; + } break; + + // this is an indirect CP entry so it needs special handling + case JVM_CONSTANT_MethodHandle: + { + int ref_kind = scratch_cp->method_handle_ref_kind_at(scratch_i); + int ref_i = scratch_cp->method_handle_index_at(scratch_i); + int new_ref_i = find_or_append_indirect_entry(scratch_cp, ref_i, merge_cp_p, + merge_cp_length_p, THREAD); + if (new_ref_i != ref_i) { + RC_TRACE(0x00080000, + ("MethodHandle entry@%d ref_index change: %d to %d", + *merge_cp_length_p, ref_i, new_ref_i)); + } + (*merge_cp_p)->method_handle_index_at_put(*merge_cp_length_p, ref_kind, new_ref_i); + if (scratch_i != *merge_cp_length_p) { + // The new entry in *merge_cp_p is at a different index than + // the new entry in scratch_cp so we need to map the index values. + map_index(scratch_cp, scratch_i, *merge_cp_length_p); + } + (*merge_cp_length_p)++; + } break; + + // this is an indirect CP entry so it needs special handling + case JVM_CONSTANT_InvokeDynamic: + { + // TBD: cross-checks and possible extra appends into CP and bsm operands + // are needed as well. This issue is tracked by a separate bug 8007037. + int bss_idx = scratch_cp->invoke_dynamic_bootstrap_specifier_index(scratch_i); + + int ref_i = scratch_cp->invoke_dynamic_name_and_type_ref_index_at(scratch_i); + int new_ref_i = find_or_append_indirect_entry(scratch_cp, ref_i, merge_cp_p, + merge_cp_length_p, THREAD); + if (new_ref_i != ref_i) { + RC_TRACE(0x00080000, + ("InvokeDynamic entry@%d name_and_type ref_index change: %d to %d", + *merge_cp_length_p, ref_i, new_ref_i)); + } + + (*merge_cp_p)->invoke_dynamic_at_put(*merge_cp_length_p, bss_idx, new_ref_i); + if (scratch_i != *merge_cp_length_p) { + // The new entry in *merge_cp_p is at a different index than + // the new entry in scratch_cp so we need to map the index values. + map_index(scratch_cp, scratch_i, *merge_cp_length_p); + } + (*merge_cp_length_p)++; + } break; + // At this stage, Class or UnresolvedClass could be here, but not // ClassIndex case JVM_CONSTANT_ClassIndex: // fall through @@ -507,6 +456,35 @@ void VM_RedefineClasses::append_entry(constantPoolHandle scratch_cp, } // end append_entry() +int VM_RedefineClasses::find_or_append_indirect_entry(constantPoolHandle scratch_cp, + int ref_i, constantPoolHandle *merge_cp_p, int *merge_cp_length_p, TRAPS) { + + int new_ref_i = ref_i; + bool match = (ref_i < *merge_cp_length_p) && + scratch_cp->compare_entry_to(ref_i, *merge_cp_p, ref_i, THREAD); + + if (!match) { + // forward reference in *merge_cp_p or not a direct match + int found_i = scratch_cp->find_matching_entry(ref_i, *merge_cp_p, THREAD); + if (found_i != 0) { + guarantee(found_i != ref_i, "compare_entry_to() and find_matching_entry() do not agree"); + // Found a matching entry somewhere else in *merge_cp_p so just need a mapping entry. + new_ref_i = found_i; + map_index(scratch_cp, ref_i, found_i); + } else { + // no match found so we have to append this entry to *merge_cp_p + append_entry(scratch_cp, ref_i, merge_cp_p, merge_cp_length_p, THREAD); + // The above call to append_entry() can only append one entry + // so the post call query of *merge_cp_length_p is only for + // the sake of consistency. + new_ref_i = *merge_cp_length_p - 1; + } + } + + return new_ref_i; +} // end find_or_append_indirect_entry() + + void VM_RedefineClasses::swap_all_method_annotations(int i, int j, instanceKlassHandle scratch_class, TRAPS) { AnnotationArray* save; diff --git a/hotspot/src/share/vm/prims/jvmtiRedefineClasses.hpp b/hotspot/src/share/vm/prims/jvmtiRedefineClasses.hpp index 23839670d98..d348ed2c759 100644 --- a/hotspot/src/share/vm/prims/jvmtiRedefineClasses.hpp +++ b/hotspot/src/share/vm/prims/jvmtiRedefineClasses.hpp @@ -421,10 +421,11 @@ class VM_RedefineClasses: public VM_Operation { // and in all direct and indirect subclasses. void increment_class_counter(InstanceKlass *ik, TRAPS); - // Support for constant pool merging (these routines are in alpha - // order): + // Support for constant pool merging (these routines are in alpha order): void append_entry(constantPoolHandle scratch_cp, int scratch_i, constantPoolHandle *merge_cp_p, int *merge_cp_length_p, TRAPS); + int find_or_append_indirect_entry(constantPoolHandle scratch_cp, int scratch_i, + constantPoolHandle *merge_cp_p, int *merge_cp_length_p, TRAPS); int find_new_index(int old_index); bool is_unresolved_class_mismatch(constantPoolHandle cp1, int index1, constantPoolHandle cp2, int index2); From da8ccb93758007d70384beff761b60c69dfc0414 Mon Sep 17 00:00:00 2001 From: Serguei Spitsyn Date: Thu, 31 Jan 2013 20:09:16 -0800 Subject: [PATCH 145/210] 8006546: JSR 292: typos in the ConstantPool::copy_cp_impl() Simple typos that need to be fixed Reviewed-by: coleenp, twisti --- hotspot/src/share/vm/oops/constantPool.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hotspot/src/share/vm/oops/constantPool.cpp b/hotspot/src/share/vm/oops/constantPool.cpp index b65d9bc7f35..1c21420c29a 100644 --- a/hotspot/src/share/vm/oops/constantPool.cpp +++ b/hotspot/src/share/vm/oops/constantPool.cpp @@ -1129,7 +1129,7 @@ void ConstantPool::copy_operands(constantPoolHandle from_cp, (len = old_off) * sizeof(u2)); fillp += len; // first part of src - Copy::conjoint_memory_atomic(to_cp->operands()->adr_at(0), + Copy::conjoint_memory_atomic(from_cp->operands()->adr_at(0), new_operands->adr_at(fillp), (len = from_off) * sizeof(u2)); fillp += len; @@ -1139,7 +1139,7 @@ void ConstantPool::copy_operands(constantPoolHandle from_cp, (len = old_len - old_off) * sizeof(u2)); fillp += len; // second part of src - Copy::conjoint_memory_atomic(to_cp->operands()->adr_at(from_off), + Copy::conjoint_memory_atomic(from_cp->operands()->adr_at(from_off), new_operands->adr_at(fillp), (len = from_len - from_off) * sizeof(u2)); fillp += len; From 932c29e08e8a352e7c6a745c1b768a85536ef9f1 Mon Sep 17 00:00:00 2001 From: Serguei Spitsyn Date: Thu, 31 Jan 2013 20:11:14 -0800 Subject: [PATCH 146/210] 8006731: JSR 292: the VM_RedefineClasses::rewrite_cp_refs_in_method() must support invokedynamic The invokedynamic bytecode ref to a CP entry needs to be checked and fixed as well. Reviewed-by: coleenp, twisti --- hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp b/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp index a09fa16ed0c..ce1ec56ef65 100644 --- a/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp +++ b/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp @@ -1542,6 +1542,7 @@ void VM_RedefineClasses::rewrite_cp_refs_in_method(methodHandle method, case Bytecodes::_getfield : // fall through case Bytecodes::_getstatic : // fall through case Bytecodes::_instanceof : // fall through + case Bytecodes::_invokedynamic : // fall through case Bytecodes::_invokeinterface: // fall through case Bytecodes::_invokespecial : // fall through case Bytecodes::_invokestatic : // fall through From d0830009e80631e78a3a776954143194bab97530 Mon Sep 17 00:00:00 2001 From: Chris Hegarty Date: Fri, 1 Feb 2013 06:51:37 +0000 Subject: [PATCH 147/210] 8006395: Race in async socket close on Linux Reviewed-by: alanb, dsamersoff --- jdk/src/solaris/native/java/net/linux_close.c | 21 +++-- jdk/test/java/net/Socket/asyncClose/Race.java | 77 +++++++++++++++++++ 2 files changed, 87 insertions(+), 11 deletions(-) create mode 100644 jdk/test/java/net/Socket/asyncClose/Race.java diff --git a/jdk/src/solaris/native/java/net/linux_close.c b/jdk/src/solaris/native/java/net/linux_close.c index 5665e85e09c..51f9cb2ee70 100644 --- a/jdk/src/solaris/native/java/net/linux_close.c +++ b/jdk/src/solaris/native/java/net/linux_close.c @@ -191,17 +191,6 @@ static int closefd(int fd1, int fd2) { pthread_mutex_lock(&(fdEntry->lock)); { - /* - * Send a wakeup signal to all threads blocked on this - * file descriptor. - */ - threadEntry_t *curr = fdEntry->threads; - while (curr != NULL) { - curr->intr = 1; - pthread_kill( curr->thr, sigWakeup ); - curr = curr->next; - } - /* * And close/dup the file descriptor * (restart if interrupted by signal) @@ -214,6 +203,16 @@ static int closefd(int fd1, int fd2) { } } while (rv == -1 && errno == EINTR); + /* + * Send a wakeup signal to all threads blocked on this + * file descriptor. + */ + threadEntry_t *curr = fdEntry->threads; + while (curr != NULL) { + curr->intr = 1; + pthread_kill( curr->thr, sigWakeup ); + curr = curr->next; + } } /* diff --git a/jdk/test/java/net/Socket/asyncClose/Race.java b/jdk/test/java/net/Socket/asyncClose/Race.java new file mode 100644 index 00000000000..f8869394b3d --- /dev/null +++ b/jdk/test/java/net/Socket/asyncClose/Race.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2013, 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. + * + * 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. + */ + +/* + * @test + * @bug 8006395 + * @summary Race in async socket close on Linux + */ + +import java.io.InputStream; +import java.net.ServerSocket; +import java.net.Socket; +import java.net.SocketException; +import java.util.concurrent.Phaser; + +// Racey test, will not always fail, but if it does then we have a problem. + +public class Race { + final static int THREADS = 100; + + public static void main(String[] args) throws Exception { + try (ServerSocket ss = new ServerSocket(0)) { + final int port = ss.getLocalPort(); + final Phaser phaser = new Phaser(THREADS + 1); + for (int i=0; i<100; i++) { + final Socket s = new Socket("localhost", port); + s.setSoLinger(false, 0); + try (Socket sa = ss.accept()) { + sa.setSoLinger(false, 0); + final InputStream is = s.getInputStream(); + Thread[] threads = new Thread[THREADS]; + for (int j=0; j Date: Fri, 1 Feb 2013 07:25:51 -0800 Subject: [PATCH 148/210] 8006536: [launcher] removes trailing slashes on arguments Reviewed-by: ksrini, akhil --- jdk/src/windows/bin/cmdtoargs.c | 13 ++++++++++++- jdk/test/tools/launcher/Arrrghs.java | 3 ++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/jdk/src/windows/bin/cmdtoargs.c b/jdk/src/windows/bin/cmdtoargs.c index 4e92d18708c..669f3683bfe 100644 --- a/jdk/src/windows/bin/cmdtoargs.c +++ b/jdk/src/windows/bin/cmdtoargs.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2013, 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 @@ -104,6 +104,11 @@ static char* next_arg(char* cmdline, char* arg, jboolean* wildcard) { case ' ': case '\t': + if (prev == '\\') { + for (i = 0 ; i < slashes; i++) { + *dest++ = prev; + } + } if (quotes % 2 == 1) { *dest++ = ch; } else { @@ -591,6 +596,12 @@ int main(int argc, char* argv[]) { // v->disable(); vectors[i++] = v; + v= new Vector(argv[0], "a b\\\\ d"); + v->add("a", FALSE); + v->add("b\\\\", FALSE); + v->add("d", FALSE); + vectors[i++] = v; + dotest(vectors); printf("All tests pass [%d]\n", i); doexit(0); diff --git a/jdk/test/tools/launcher/Arrrghs.java b/jdk/test/tools/launcher/Arrrghs.java index 9bf9f21b465..cf0dfbf7410 100644 --- a/jdk/test/tools/launcher/Arrrghs.java +++ b/jdk/test/tools/launcher/Arrrghs.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2013, 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 @@ -309,6 +309,7 @@ public class Arrrghs extends TestHelper { checkArgumentParsing("../../*", "../../*"); checkArgumentParsing("..\\..\\", "..\\..\\"); checkArgumentParsing("../../", "../../"); + checkArgumentParsing("a b\\ c", "a", "b\\", "c"); } private void initEmptyDir(File emptyDir) throws IOException { From 01ea5d17ec5f6fe542636d0fa12f16b4da9caab4 Mon Sep 17 00:00:00 2001 From: Andrew Brygin Date: Fri, 1 Feb 2013 20:06:27 +0400 Subject: [PATCH 149/210] 8004801: The image of BufferedImage.TYPE_INT_ARGB is blank Reviewed-by: prr --- .../native/sun/awt/image/awt_parseImage.c | 65 ++++++++++++ jdk/src/solaris/native/sun/awt/awt_Mlib.c | 46 --------- jdk/src/solaris/native/sun/awt/awt_Mlib.h | 1 - .../windows/native/sun/windows/awt_Mlib.cpp | 46 --------- jdk/src/windows/native/sun/windows/awt_Mlib.h | 1 - .../image/LookupOp/IntImageReverseTest.java | 99 +++++++++++++++++++ 6 files changed, 164 insertions(+), 94 deletions(-) create mode 100644 jdk/test/java/awt/image/LookupOp/IntImageReverseTest.java diff --git a/jdk/src/share/native/sun/awt/image/awt_parseImage.c b/jdk/src/share/native/sun/awt/image/awt_parseImage.c index 264a02f1642..d6f6d60d356 100644 --- a/jdk/src/share/native/sun/awt/image/awt_parseImage.c +++ b/jdk/src/share/native/sun/awt/image/awt_parseImage.c @@ -489,6 +489,71 @@ void awt_freeParsedImage(BufImageS_t *imageP, int freeImageP) { } } +static void +awt_getBIColorOrder(int type, int *colorOrder) { + switch(type) { + case java_awt_image_BufferedImage_TYPE_INT_ARGB: + case java_awt_image_BufferedImage_TYPE_INT_ARGB_PRE: +#ifdef _LITTLE_ENDIAN + colorOrder[0] = 2; + colorOrder[1] = 1; + colorOrder[2] = 0; + colorOrder[3] = 3; +#else + colorOrder[0] = 1; + colorOrder[1] = 2; + colorOrder[2] = 3; + colorOrder[3] = 0; +#endif + break; + case java_awt_image_BufferedImage_TYPE_INT_BGR: +#ifdef _LITTLE_ENDIAN + colorOrder[0] = 0; + colorOrder[1] = 1; + colorOrder[2] = 2; +#else + colorOrder[0] = 3; + colorOrder[1] = 2; + colorOrder[2] = 1; +#endif + break; + case java_awt_image_BufferedImage_TYPE_INT_RGB: +#ifdef _LITTLE_ENDIAN + colorOrder[0] = 2; + colorOrder[1] = 1; + colorOrder[2] = 0; +#else + colorOrder[0] = 1; + colorOrder[1] = 2; + colorOrder[2] = 3; +#endif + break; + case java_awt_image_BufferedImage_TYPE_4BYTE_ABGR: + case java_awt_image_BufferedImage_TYPE_4BYTE_ABGR_PRE: + colorOrder[0] = 3; + colorOrder[1] = 2; + colorOrder[2] = 1; + colorOrder[3] = 0; + break; + case java_awt_image_BufferedImage_TYPE_3BYTE_BGR: + colorOrder[0] = 2; + colorOrder[1] = 1; + colorOrder[2] = 0; + break; + case java_awt_image_BufferedImage_TYPE_USHORT_565_RGB: + case java_awt_image_BufferedImage_TYPE_USHORT_555_RGB: + colorOrder[0] = 0; + colorOrder[1] = 1; + colorOrder[2] = 2; + break; + case java_awt_image_BufferedImage_TYPE_BYTE_GRAY: + case java_awt_image_BufferedImage_TYPE_USHORT_GRAY: + case java_awt_image_BufferedImage_TYPE_BYTE_BINARY: + case java_awt_image_BufferedImage_TYPE_BYTE_INDEXED: + colorOrder[0] = 0; + break; + } +} static int setHints(JNIEnv *env, BufImageS_t *imageP) { diff --git a/jdk/src/solaris/native/sun/awt/awt_Mlib.c b/jdk/src/solaris/native/sun/awt/awt_Mlib.c index fb00d4d9f12..0b7c291c811 100644 --- a/jdk/src/solaris/native/sun/awt/awt_Mlib.c +++ b/jdk/src/solaris/native/sun/awt/awt_Mlib.c @@ -145,52 +145,6 @@ mlib_stop_timer awt_setMlibStopTimer() { return stop_timer; } -void awt_getBIColorOrder(int type, int *colorOrder) { - switch(type) { - case java_awt_image_BufferedImage_TYPE_INT_ARGB: - case java_awt_image_BufferedImage_TYPE_INT_ARGB_PRE: - colorOrder[0] = 1; - colorOrder[1] = 2; - colorOrder[2] = 3; - colorOrder[3] = 0; - break; - case java_awt_image_BufferedImage_TYPE_INT_BGR: - colorOrder[0] = 2; - colorOrder[1] = 1; - colorOrder[2] = 0; - break; - case java_awt_image_BufferedImage_TYPE_4BYTE_ABGR: - case java_awt_image_BufferedImage_TYPE_4BYTE_ABGR_PRE: - colorOrder[0] = 3; - colorOrder[1] = 2; - colorOrder[2] = 1; - colorOrder[3] = 0; - break; - case java_awt_image_BufferedImage_TYPE_3BYTE_BGR: - colorOrder[0] = 2; - colorOrder[1] = 1; - colorOrder[2] = 0; - break; - case java_awt_image_BufferedImage_TYPE_INT_RGB: - colorOrder[0] = 1; - colorOrder[1] = 2; - colorOrder[2] = 3; - break; - case java_awt_image_BufferedImage_TYPE_USHORT_565_RGB: - case java_awt_image_BufferedImage_TYPE_USHORT_555_RGB: - colorOrder[0] = 0; - colorOrder[1] = 1; - colorOrder[2] = 2; - break; - case java_awt_image_BufferedImage_TYPE_BYTE_GRAY: - case java_awt_image_BufferedImage_TYPE_USHORT_GRAY: - case java_awt_image_BufferedImage_TYPE_BYTE_BINARY: - case java_awt_image_BufferedImage_TYPE_BYTE_INDEXED: - colorOrder[0] = 0; - break; - } -} - /*************************************************************************** * Static Functions * ***************************************************************************/ diff --git a/jdk/src/solaris/native/sun/awt/awt_Mlib.h b/jdk/src/solaris/native/sun/awt/awt_Mlib.h index 03d65868994..cbaf38d1de6 100644 --- a/jdk/src/solaris/native/sun/awt/awt_Mlib.h +++ b/jdk/src/solaris/native/sun/awt/awt_Mlib.h @@ -33,6 +33,5 @@ typedef void (*mlib_stop_timer)(int, int); mlib_status awt_getImagingLib(JNIEnv *, mlibFnS_t *, mlibSysFnS_t *); mlib_start_timer awt_setMlibStartTimer(); mlib_stop_timer awt_setMlibStopTimer(); -void awt_getBIColorOrder(int type, int *colorOrder); #endif /* _AWT_MLIB_H */ diff --git a/jdk/src/windows/native/sun/windows/awt_Mlib.cpp b/jdk/src/windows/native/sun/windows/awt_Mlib.cpp index 022ebd0419a..308b2823e4c 100644 --- a/jdk/src/windows/native/sun/windows/awt_Mlib.cpp +++ b/jdk/src/windows/native/sun/windows/awt_Mlib.cpp @@ -105,50 +105,4 @@ extern "C" mlib_stop_timer awt_setMlibStopTimer() { return NULL; } - - void awt_getBIColorOrder(int type, int *colorOrder) { - switch(type) { - case java_awt_image_BufferedImage_TYPE_INT_ARGB: - case java_awt_image_BufferedImage_TYPE_INT_ARGB_PRE: - colorOrder[0] = 2; - colorOrder[1] = 1; - colorOrder[2] = 0; - colorOrder[3] = 3; - break; - case java_awt_image_BufferedImage_TYPE_INT_BGR: - colorOrder[0] = 0; - colorOrder[1] = 1; - colorOrder[2] = 2; - break; - case java_awt_image_BufferedImage_TYPE_INT_RGB: - colorOrder[0] = 2; - colorOrder[1] = 1; - colorOrder[2] = 0; - break; - case java_awt_image_BufferedImage_TYPE_4BYTE_ABGR: - case java_awt_image_BufferedImage_TYPE_4BYTE_ABGR_PRE: - colorOrder[0] = 3; - colorOrder[1] = 2; - colorOrder[2] = 1; - colorOrder[3] = 0; - break; - case java_awt_image_BufferedImage_TYPE_3BYTE_BGR: - colorOrder[0] = 2; - colorOrder[1] = 1; - colorOrder[2] = 0; - break; - case java_awt_image_BufferedImage_TYPE_USHORT_565_RGB: - case java_awt_image_BufferedImage_TYPE_USHORT_555_RGB: - colorOrder[0] = 0; - colorOrder[1] = 1; - colorOrder[2] = 2; - break; - case java_awt_image_BufferedImage_TYPE_BYTE_GRAY: - case java_awt_image_BufferedImage_TYPE_USHORT_GRAY: - case java_awt_image_BufferedImage_TYPE_BYTE_BINARY: - case java_awt_image_BufferedImage_TYPE_BYTE_INDEXED: - colorOrder[0] = 0; - break; - } - } } diff --git a/jdk/src/windows/native/sun/windows/awt_Mlib.h b/jdk/src/windows/native/sun/windows/awt_Mlib.h index f9b63d900bb..9ebee32a932 100644 --- a/jdk/src/windows/native/sun/windows/awt_Mlib.h +++ b/jdk/src/windows/native/sun/windows/awt_Mlib.h @@ -38,7 +38,6 @@ JNIEXPORT mlib_status awt_getImagingLib(JNIEnv *env, mlibFnS_t *sMlibFns, mlibSysFnS_t *sMlibSysFns); JNIEXPORT mlib_start_timer awt_setMlibStartTimer(); JNIEXPORT mlib_stop_timer awt_setMlibStopTimer(); -JNIEXPORT void awt_getBIColorOrder(int type, int *colorOrder); #ifdef __cplusplus }; /* end of extern "C" */ diff --git a/jdk/test/java/awt/image/LookupOp/IntImageReverseTest.java b/jdk/test/java/awt/image/LookupOp/IntImageReverseTest.java new file mode 100644 index 00000000000..62de1683827 --- /dev/null +++ b/jdk/test/java/awt/image/LookupOp/IntImageReverseTest.java @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2013, 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. + * + * 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. + */ + +/* + * @test + * @bug 8004801 + * @summary Test verifies that byte lookup table with single lookup + * affects only color components in buffered images with + * integer data type, and that this operation does not distort + * colors in the destination image. + * @run main IntImageReverseTest + */ + +import java.awt.image.BufferedImage; +import java.awt.image.ByteLookupTable; +import java.awt.image.LookupOp; +import java.awt.image.LookupTable; + +public class IntImageReverseTest { + + public static void main(String[] args) { + LookupTable tbl = createReverseTable(); + LookupOp op = new LookupOp(tbl, null); + + for (ImageType t : ImageType.values()) { + System.out.print(t); + + BufferedImage src = createSourceImage(t); + + BufferedImage dst = op.filter(src, null); + + int rgb = dst.getRGB(0, 0); + + System.out.printf(" Result: 0x%X ", rgb); + + if (rgb != argbReverse) { + throw new RuntimeException("Test failed."); + } + System.out.println("Passed."); + } + } + + /** + * Reverse image color components, leave alpha unchanged. + */ + private static LookupTable createReverseTable() { + byte[] data = new byte[256]; + + for (int i = 0; i < 256; i++) { + data[i] = (byte) (255 - i); + } + + + return new ByteLookupTable(0, data); + } + + private static BufferedImage createSourceImage(ImageType type) { + BufferedImage img = new BufferedImage(1, 1, type.bi_type); + + img.setRGB(0, 0, argbTest); + + return img; + } + private static final int argbTest = 0xFFDDAA77; + private static final int argbReverse = 0xFF225588; + + private static enum ImageType { + + INT_ARGB(BufferedImage.TYPE_INT_ARGB), + INT_ARGB_PRE(BufferedImage.TYPE_INT_ARGB_PRE), + INT_RGB(BufferedImage.TYPE_INT_BGR), + INT_BGR(BufferedImage.TYPE_INT_BGR); + + private ImageType(int bi_type) { + this.bi_type = bi_type; + } + public final int bi_type; + } +} From 81e9d881ca343719c38bf10b19f6a3231bbc6b84 Mon Sep 17 00:00:00 2001 From: Jonathan Gibbons Date: Fri, 1 Feb 2013 08:33:48 -0800 Subject: [PATCH 150/210] 8007306: DPrinter: improve display of impl-class, internal tag/kind, and external tag/kind Reviewed-by: mcimadamore --- langtools/test/tools/javac/lib/DPrinter.java | 132 +++++++++---------- 1 file changed, 64 insertions(+), 68 deletions(-) diff --git a/langtools/test/tools/javac/lib/DPrinter.java b/langtools/test/tools/javac/lib/DPrinter.java index e05b9a8ad16..ea747acb26d 100644 --- a/langtools/test/tools/javac/lib/DPrinter.java +++ b/langtools/test/tools/javac/lib/DPrinter.java @@ -210,7 +210,7 @@ public class DPrinter { return; } - printString(label, ""); + printString(label, hashString(annotations)); indent(+1); if (attributes == DECL_NOT_STARTED) @@ -383,11 +383,12 @@ public class DPrinter { case FULL: indent(); out.print(label); - out.println(": " + String.format("0x%x", sym.kind) - + "--" + Kinds.kindName(sym).name() - + " " + sym.getKind() + out.println(": " + + info(sym.getClass(), + String.format("0x%x--%s", sym.kind, Kinds.kindName(sym)), + sym.getKind()) + " " + sym.name - + " " + String.format("#%x", sym.hashCode())); + + " " + hashString(sym)); indent(+1); if (showSrc) { @@ -401,7 +402,7 @@ public class DPrinter { printSymbol("owner", sym.owner, Details.SUMMARY); printType("type", sym.type, Details.SUMMARY); printType("erasure", sym.erasure_field, Details.SUMMARY); - sym.accept(symVisitor, true); + sym.accept(symVisitor, null); printAnnotations("annotations", sym.annotations, Details.SUMMARY); indent(-1); } @@ -417,7 +418,13 @@ public class DPrinter { printNull(label); } else { indent(); - out.print(label + ": " + tree.getTag()); + String ext; + try { + ext = tree.getKind().name(); + } catch (Throwable t) { + ext = "n/a"; + } + out.print(label + ": " + info(tree.getClass(), tree.getTag(), ext)); if (showPositions) { // We can always get start position, but to get end position // and/or line+offset, we would need a JCCompilationUnit @@ -456,13 +463,13 @@ public class DPrinter { case FULL: indent(); out.print(label); - out.println(": " + type.getTag() - + " " + String.format("#%x", type.hashCode())); + out.println(": " + info(type.getClass(), type.getTag(), type.getKind()) + + " " + hashString(type)); indent(+1); printSymbol("tsym", type.tsym, Details.SUMMARY); printObject("constValue", type.constValue(), Details.SUMMARY); - type.accept(typeVisitor, true); + type.accept(typeVisitor, null); indent(-1); } } @@ -472,6 +479,14 @@ public class DPrinter { return (printer != null) ? printer.visit(type, locale) : String.valueOf(type); } + protected String hashString(Object obj) { + return String.format("#%x", obj.hashCode()); + } + + protected String info(Class clazz, Object internal, Object external) { + return String.format("%s,%s,%s", clazz.getSimpleName(), internal, external); + } + private int indent = 0; protected void indent() { @@ -853,17 +868,16 @@ public class DPrinter { // - protected Symbol.Visitor symVisitor = new SymbolVisitor(); + protected Symbol.Visitor symVisitor = new SymbolVisitor(); /** * Default visitor class for Symbol objects. * Note: each visitXYZ method ends by calling the corresponding * visit method for its superclass. */ - class SymbolVisitor implements Symbol.Visitor { + class SymbolVisitor implements Symbol.Visitor { @Override - public Void visitClassSymbol(ClassSymbol sym, Boolean impl) { - if (impl) printImplClass(sym, ClassSymbol.class); + public Void visitClassSymbol(ClassSymbol sym, Void ignore) { printName("fullname", sym.fullname); printName("flatname", sym.flatname); printScope("members", sym.members_field); @@ -871,55 +885,49 @@ public class DPrinter { printFileObject("classfile", sym.classfile); // trans-local? // pool? - return visitTypeSymbol(sym, false); + return visitTypeSymbol(sym, null); } @Override - public Void visitMethodSymbol(MethodSymbol sym, Boolean impl) { - if (impl) printImplClass(sym, MethodSymbol.class); + public Void visitMethodSymbol(MethodSymbol sym, Void ignore) { // code printList("params", sym.params); printList("savedParameterNames", sym.savedParameterNames); - return visitSymbol(sym, false); + return visitSymbol(sym, null); } @Override - public Void visitPackageSymbol(PackageSymbol sym, Boolean impl) { - if (impl) printImplClass(sym, PackageSymbol.class); + public Void visitPackageSymbol(PackageSymbol sym, Void ignore) { printName("fullname", sym.fullname); printScope("members", sym.members_field); printSymbol("package-info", sym.package_info, Details.SUMMARY); - return visitTypeSymbol(sym, false); + return visitTypeSymbol(sym, null); } @Override - public Void visitOperatorSymbol(OperatorSymbol sym, Boolean impl) { - if (impl) printImplClass(sym, OperatorSymbol.class); + public Void visitOperatorSymbol(OperatorSymbol sym, Void ignore) { printInt("opcode", sym.opcode); - return visitMethodSymbol(sym, false); + return visitMethodSymbol(sym, null); } @Override - public Void visitVarSymbol(VarSymbol sym, Boolean impl) { - if (impl) printImplClass(sym, VarSymbol.class); + public Void visitVarSymbol(VarSymbol sym, Void ignore) { printInt("pos", sym.pos); printInt("adm", sym.adr); // data is a private field, and the standard accessors may // mutate it as part of lazy evaluation. Therefore, use // reflection to get the raw data. printObject("data", getField(sym, VarSymbol.class, "data"), Details.SUMMARY); - return visitSymbol(sym, false); + return visitSymbol(sym, null); } @Override - public Void visitTypeSymbol(TypeSymbol sym, Boolean impl) { - if (impl) printImplClass(sym, TypeSymbol.class); - return visitSymbol(sym, false); + public Void visitTypeSymbol(TypeSymbol sym, Void ignore) { + return visitSymbol(sym, null); } @Override - public Void visitSymbol(Symbol sym, Boolean impl) { - if (impl) printImplClass(sym, Symbol.class); + public Void visitSymbol(Symbol sym, Void ignore) { return null; } } @@ -928,71 +936,62 @@ public class DPrinter { // - protected Type.Visitor typeVisitor = new TypeVisitor(); + protected Type.Visitor typeVisitor = new TypeVisitor(); /** * Default visitor class for Type objects. * Note: each visitXYZ method ends by calling the corresponding * visit method for its superclass. */ - public class TypeVisitor implements Type.Visitor { - public Void visitAnnotatedType(AnnotatedType type, Boolean impl) { - if (impl) printImplClass(type, AnnotatedType.class); + public class TypeVisitor implements Type.Visitor { + public Void visitAnnotatedType(AnnotatedType type, Void ignore) { printList("typeAnnotations", type.typeAnnotations); printType("underlyingType", type.underlyingType, Details.FULL); - return visitType(type, false); + return visitType(type, null); } - public Void visitArrayType(ArrayType type, Boolean impl) { - if (impl) printImplClass(type, ArrayType.class); + public Void visitArrayType(ArrayType type, Void ignore) { printType("elemType", type.elemtype, Details.FULL); - return visitType(type, false); + return visitType(type, null); } - public Void visitCapturedType(CapturedType type, Boolean impl) { - if (impl) printImplClass(type, CapturedType.class); + public Void visitCapturedType(CapturedType type, Void ignore) { printType("wildcard", type.wildcard, Details.FULL); - return visitTypeVar(type, false); + return visitTypeVar(type, null); } - public Void visitClassType(ClassType type, Boolean impl) { - if (impl) printImplClass(type, ClassType.class); + public Void visitClassType(ClassType type, Void ignore) { printType("outer", type.getEnclosingType(), Details.SUMMARY); printList("typarams", type.typarams_field); printList("allparams", type.allparams_field); printType("supertype", type.supertype_field, Details.SUMMARY); printList("interfaces", type.interfaces_field); printList("allinterfaces", type.all_interfaces_field); - return visitType(type, false); + return visitType(type, null); } - public Void visitErrorType(ErrorType type, Boolean impl) { - if (impl) printImplClass(type, ErrorType.class); + public Void visitErrorType(ErrorType type, Void ignore) { printType("originalType", type.getOriginalType(), Details.FULL); - return visitClassType(type, false); + return visitClassType(type, null); } - public Void visitForAll(ForAll type, Boolean impl) { - if (impl) printImplClass(type, ForAll.class); + public Void visitForAll(ForAll type, Void ignore) { printList("tvars", type.tvars); return visitDelegatedType(type); } - public Void visitMethodType(MethodType type, Boolean impl) { - if (impl) printImplClass(type, MethodType.class); + public Void visitMethodType(MethodType type, Void ignore) { printList("argtypes", type.argtypes); printType("restype", type.restype, Details.FULL); printList("thrown", type.thrown); - return visitType(type, false); + return visitType(type, null); } - public Void visitPackageType(PackageType type, Boolean impl) { - if (impl) printImplClass(type, PackageType.class); - return visitType(type, false); + public Void visitPackageType(PackageType type, Void ignore) { + return visitType(type, null); } - public Void visitTypeVar(TypeVar type, Boolean impl) { - if (impl) printImplClass(type, TypeVar.class); + public Void visitTypeVar(TypeVar type, Void ignore) { // For TypeVars (and not subtypes), the bound should always be // null or bot. So, only print the bound for subtypes of TypeVar, // or if the bound is (erroneously) not null or bot. @@ -1001,32 +1000,29 @@ public class DPrinter { printType("bound", type.bound, Details.FULL); } printType("lower", type.lower, Details.FULL); - return visitType(type, false); + return visitType(type, null); } - public Void visitUndetVar(UndetVar type, Boolean impl) { - if (impl) printImplClass(type, UndetVar.class); + public Void visitUndetVar(UndetVar type, Void ignore) { for (UndetVar.InferenceBound ib: UndetVar.InferenceBound.values()) printList("bounds." + ib, type.getBounds(ib)); printType("inst", type.inst, Details.SUMMARY); return visitDelegatedType(type); } - public Void visitWildcardType(WildcardType type, Boolean impl) { - if (impl) printImplClass(type, WildcardType.class); + public Void visitWildcardType(WildcardType type, Void ignore) { printType("type", type.type, Details.SUMMARY); printString("kind", type.kind.name()); printType("bound", type.bound, Details.SUMMARY); - return visitType(type, false); + return visitType(type, null); } protected Void visitDelegatedType(DelegatedType type) { printType("qtype", type.qtype, Details.FULL); - return visitType(type, false); + return visitType(type, null); } - public Void visitType(Type type, Boolean impl) { - if (impl) printImplClass(type, Type.class); + public Void visitType(Type type, Void ignore) { return null; } } From 7ee6242d0c6526c637d31632e9fd4276a0acec99 Mon Sep 17 00:00:00 2001 From: Jonathan Gibbons Date: Fri, 1 Feb 2013 08:36:15 -0800 Subject: [PATCH 151/210] 8007305: DPrinter: provide better usage message Reviewed-by: mcimadamore --- langtools/test/tools/javac/lib/DPrinter.java | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/langtools/test/tools/javac/lib/DPrinter.java b/langtools/test/tools/javac/lib/DPrinter.java index ea747acb26d..45d1296cdda 100644 --- a/langtools/test/tools/javac/lib/DPrinter.java +++ b/langtools/test/tools/javac/lib/DPrinter.java @@ -1087,21 +1087,30 @@ public class DPrinter { */ static class Main { public static void main(String... args) throws IOException { + Main m = new Main(); PrintWriter out = new PrintWriter(System.out); try { if (args.length == 0) - usage(out); + m.usage(out); else - new Main().run(out, args); + m.run(out, args); } finally { out.flush(); } } - static void usage(PrintWriter out) { + void usage(PrintWriter out) { out.println("Usage:"); out.println(" java " + Main.class.getName() + " mode [options] [javac-options]"); - out.println("where options include:"); + out.print("where mode is one of: "); + String sep = ""; + for (Handler h: getHandlers().values()) { + out.print(sep); + out.print(h.name); + sep = ", "; + } + out.println(); + out.println("and where options include:"); out.println(" -before PARSE|ENTER|ANALYZE|GENERATE|ANNOTATION_PROCESSING|ANNOTATION_PROCESSING_ROUND"); out.println(" -after PARSE|ENTER|ANALYZE|GENERATE|ANNOTATION_PROCESSING|ANNOTATION_PROCESSING_ROUND"); out.println(" -showPositions"); From 6b4b68a14569740aa4ff3d095ad5286b3923c260 Mon Sep 17 00:00:00 2001 From: Tim Bell Date: Fri, 1 Feb 2013 09:16:19 -0800 Subject: [PATCH 152/210] 8006808: mapfile use check in jdk/make/common/shared/Defs-solaris.gmk is throwing 'egrep: syntax error' Use a valid egrep expression in the non-SPARC case Reviewed-by: dholmes --- jdk/make/common/shared/Defs-solaris.gmk | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/jdk/make/common/shared/Defs-solaris.gmk b/jdk/make/common/shared/Defs-solaris.gmk index 4bbc5b77a8c..c888a98a5da 100644 --- a/jdk/make/common/shared/Defs-solaris.gmk +++ b/jdk/make/common/shared/Defs-solaris.gmk @@ -211,7 +211,9 @@ ifeq ($(ARCH_FAMILY),sparc) MAPFILE_EXCEPTIONS = \ (libjdgaSUNWafb|libjdgaSUNWcg6|libjdgaSUNWffb|libjdgaSUNWm64|libxinerama) else - MAPFILE_EXCEPTIONS = () + # At present there are no exceptions for non + # SPARC. Use a harmless value. + MAPFILE_EXCEPTIONS = (NO_EXCEPTIONS) endif # Macro to check it's input file for banned dependencies and verify the From a2966dd62d93b4759585a89123d68f364ad31472 Mon Sep 17 00:00:00 2001 From: Harold Seigel Date: Fri, 1 Feb 2013 14:14:54 -0500 Subject: [PATCH 153/210] 8006298: Specifying malformed JFR options (-XX:+FlightRecorderOptions) outputs non-sensical error Change error messages for malformed options so the messages are more useful. Reviewed-by: mikael, kvn, nloodin --- hotspot/src/share/vm/runtime/arguments.cpp | 29 +++++++++++++++++----- 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/hotspot/src/share/vm/runtime/arguments.cpp b/hotspot/src/share/vm/runtime/arguments.cpp index 5e6ad6e21bb..47851058cd9 100644 --- a/hotspot/src/share/vm/runtime/arguments.cpp +++ b/hotspot/src/share/vm/runtime/arguments.cpp @@ -827,7 +827,8 @@ bool Arguments::process_argument(const char* arg, return true; } - const char * const argname = *arg == '+' || *arg == '-' ? arg + 1 : arg; + bool has_plus_minus = (*arg == '+' || *arg == '-'); + const char* const argname = has_plus_minus ? arg + 1 : arg; if (is_newly_obsolete(arg, &since)) { char version[256]; since.to_string(version, sizeof(version)); @@ -838,13 +839,29 @@ bool Arguments::process_argument(const char* arg, // For locked flags, report a custom error message if available. // Otherwise, report the standard unrecognized VM option. - Flag* locked_flag = Flag::find_flag((char*)argname, strlen(argname), true); - if (locked_flag != NULL) { + size_t arg_len; + const char* equal_sign = strchr(argname, '='); + if (equal_sign == NULL) { + arg_len = strlen(argname); + } else { + arg_len = equal_sign - argname; + } + + Flag* found_flag = Flag::find_flag((char*)argname, arg_len, true); + if (found_flag != NULL) { char locked_message_buf[BUFLEN]; - locked_flag->get_locked_message(locked_message_buf, BUFLEN); + found_flag->get_locked_message(locked_message_buf, BUFLEN); if (strlen(locked_message_buf) == 0) { - jio_fprintf(defaultStream::error_stream(), - "Unrecognized VM option '%s'\n", argname); + if (found_flag->is_bool() && !has_plus_minus) { + jio_fprintf(defaultStream::error_stream(), + "Missing +/- setting for VM option '%s'\n", argname); + } else if (!found_flag->is_bool() && has_plus_minus) { + jio_fprintf(defaultStream::error_stream(), + "Unexpected +/- setting in VM option '%s'\n", argname); + } else { + jio_fprintf(defaultStream::error_stream(), + "Improperly specified VM option '%s'\n", argname); + } } else { jio_fprintf(defaultStream::error_stream(), "%s", locked_message_buf); } From 8f90cd00254e20c2b58a8fe330acf8911a6514e2 Mon Sep 17 00:00:00 2001 From: Jonathan Gibbons Date: Fri, 1 Feb 2013 12:01:03 -0800 Subject: [PATCH 154/210] 8007344: javac may not make tree end positions and/or doc comments available to processors and listeners Reviewed-by: darcy --- .../sun/tools/javac/main/JavaCompiler.java | 2 + .../test/tools/javac/api/8007344/Test.java | 227 ++++++++++++++++++ 2 files changed, 229 insertions(+) create mode 100644 langtools/test/tools/javac/api/8007344/Test.java diff --git a/langtools/src/share/classes/com/sun/tools/javac/main/JavaCompiler.java b/langtools/src/share/classes/com/sun/tools/javac/main/JavaCompiler.java index 5bf9d276872..fc4786a2a60 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/main/JavaCompiler.java +++ b/langtools/src/share/classes/com/sun/tools/javac/main/JavaCompiler.java @@ -629,6 +629,8 @@ public class JavaCompiler implements ClassReader.SourceCompleter { if (!taskListener.isEmpty()) { TaskEvent e = new TaskEvent(TaskEvent.Kind.PARSE, filename); taskListener.started(e); + keepComments = true; + genEndPos = true; } Parser parser = parserFactory.newParser(content, keepComments(), genEndPos, lineDebugInfo); tree = parser.parseCompilationUnit(); diff --git a/langtools/test/tools/javac/api/8007344/Test.java b/langtools/test/tools/javac/api/8007344/Test.java new file mode 100644 index 00000000000..871faa70617 --- /dev/null +++ b/langtools/test/tools/javac/api/8007344/Test.java @@ -0,0 +1,227 @@ +/* + * Copyright (c) 2010, 2013, 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. + * + * 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. + */ + +/* + * @test + * @bug 8007344 + * @summary javac may not make tree end positions and/or doc comments + * available to processors and listeners + * @library /tools/javac/lib + * @build JavacTestingAbstractProcessor + * @run main Test + */ + +import java.io.File; +import java.io.PrintWriter; +import java.util.Arrays; +import java.util.Set; + +import javax.annotation.processing.RoundEnvironment; +import javax.lang.model.element.Element; +import javax.lang.model.element.TypeElement; +import javax.tools.JavaFileObject; +import javax.tools.StandardJavaFileManager; + +import com.sun.source.doctree.DocCommentTree; +import com.sun.source.tree.*; +import com.sun.source.util.DocTrees; +import com.sun.source.util.JavacTask; +import com.sun.source.util.SourcePositions; +import com.sun.source.util.TaskEvent; +import com.sun.source.util.TaskListener; +import com.sun.source.util.TreePath; +import com.sun.source.util.TreePathScanner; +import com.sun.tools.javac.api.JavacTool; +import com.sun.tools.javac.tree.JCTree; +import com.sun.tools.javac.tree.Pretty; +import com.sun.tools.javac.util.Position; + +/** Doc comment: Test */ +public class Test { + public static final int EXPECT_DOC_COMMENTS = 3; + + /** Doc comment: main */ + public static void main(String... args) throws Exception { + PrintWriter out = new PrintWriter(System.err); + try { + new Test(out).run(); + } finally { + out.flush(); + } + } + + PrintWriter out; + int errors; + + Test(PrintWriter out) { + this.out = out; + } + + /** Doc comment: run */ + void run() throws Exception { + File testSrc = new File(System.getProperty("test.src")); + File thisFile = new File(testSrc, getClass().getName() + ".java"); + JavacTool javac = JavacTool.create(); + StandardJavaFileManager fm = javac.getStandardFileManager(null, null, null); + Iterable fos = fm.getJavaFileObjects(thisFile); + testAnnoProcessor(javac, fm, fos, out, EXPECT_DOC_COMMENTS); + testTaskListener(javac, fm, fos, out, EXPECT_DOC_COMMENTS); + + if (errors > 0) + throw new Exception(errors + " errors occurred"); + } + + void testAnnoProcessor(JavacTool javac, StandardJavaFileManager fm, + Iterable files, PrintWriter out, + int expectedDocComments) { + out.println("Test annotation processor"); + JavacTask task = javac.getTask(out, fm, null, null, null, files); + AnnoProc ap = new AnnoProc(DocTrees.instance(task)); + task.setProcessors(Arrays.asList(ap)); + task.call(); + ap.checker.checkDocComments(expectedDocComments); + } + + void testTaskListener(JavacTool javac, StandardJavaFileManager fm, + Iterable files, PrintWriter out, + int expectedDocComments) { + out.println("Test task listener"); + JavacTask task = javac.getTask(out, fm, null, null, null, files); + TaskListnr tl = new TaskListnr(DocTrees.instance(task)); + task.addTaskListener(tl); + task.call(); + tl.checker.checkDocComments(expectedDocComments); + } + + void error(String msg) { + out.println("Error: " + msg); + errors++; + } + + class AnnoProc extends JavacTestingAbstractProcessor { + Checker checker; + + AnnoProc(DocTrees trees) { + checker = new Checker(trees); + } + + @Override + public boolean process(Set annotations, RoundEnvironment roundEnv) { + for (Element e : roundEnv.getRootElements()) { + checker.scan(checker.trees.getPath(e), null); + } + return true; + } + } + + class TaskListnr implements TaskListener { + Checker checker; + + TaskListnr(DocTrees trees) { + checker = new Checker(trees); + } + + public void started(TaskEvent e) { + if (e.getKind() == TaskEvent.Kind.ANALYZE) + checker.scan(new TreePath(e.getCompilationUnit()), null); + } + + public void finished(TaskEvent e) { + } + } + + class Checker extends TreePathScanner { + DocTrees trees; + SourcePositions srcPosns; + + int docComments = 0; + + Checker(DocTrees trees) { + this.trees = trees; + srcPosns = trees.getSourcePositions(); + } + + @Override + public Void scan(Tree tree, Void ignore) { + if (tree != null) { + switch (tree.getKind()) { + // HACK: Workaround 8007350 + // Some tree nodes do not have endpos set + case ASSIGNMENT: + case BLOCK: + case IDENTIFIER: + case METHOD_INVOCATION: + break; + + default: + checkEndPos(getCurrentPath().getCompilationUnit(), tree); + } + } + return super.scan(tree, ignore); + } + + @Override + public Void visitClass(ClassTree tree, Void ignore) { + checkComment(); + return super.visitClass(tree, ignore); + } + + @Override + public Void visitMethod(MethodTree tree, Void ignore) { + checkComment(); + return super.visitMethod(tree, ignore); + } + + @Override + public Void visitVariable(VariableTree tree, Void ignore) { + checkComment(); + return super.visitVariable(tree, ignore); + } + + void checkComment() { + DocCommentTree dc = trees.getDocCommentTree(getCurrentPath()); + if (dc != null) { + out.println("comment: " + dc.toString().replaceAll("\\s+", " ")); + docComments++; + } + } + + void checkEndPos(CompilationUnitTree unit, Tree tree) { + long sp = srcPosns.getStartPosition(unit, tree); + long ep = srcPosns.getEndPosition(unit, tree); + if (sp >= 0 && ep == Position.NOPOS) { + error("endpos not set for " + tree.getKind() + + " " + Pretty.toSimpleString(((JCTree) tree)) + +", start:" + sp); + } + } + + void checkDocComments(int expected) { + if (docComments != expected) { + error("Unexpected number of doc comments received: " + + docComments + ", expected: " + expected); + } + } + + } +} From c2e77030a1e91c6047ddac4ce3ba8a6f959a9d12 Mon Sep 17 00:00:00 2001 From: Joe Darcy Date: Fri, 1 Feb 2013 13:01:26 -0800 Subject: [PATCH 155/210] 8001614: Include annotation type to documented supported-ness Reviewed-by: alanb, jjg, tbell --- langtools/make/Makefile-classic | 1 + langtools/make/build.properties | 1 + .../src/share/classes/jdk/Supported.java | 53 +++++++++++++++++++ 3 files changed, 55 insertions(+) create mode 100644 langtools/src/share/classes/jdk/Supported.java diff --git a/langtools/make/Makefile-classic b/langtools/make/Makefile-classic index f0693b7216b..c253ee8949b 100644 --- a/langtools/make/Makefile-classic +++ b/langtools/make/Makefile-classic @@ -241,6 +241,7 @@ JAVAC_DIRS = \ javax/annotation/processing \ javax/lang/model \ javax/tools \ + jdk/ \ com/sun/source \ com/sun/tools/javac diff --git a/langtools/make/build.properties b/langtools/make/build.properties index 72ae8793c24..7fd5ffcb371 100644 --- a/langtools/make/build.properties +++ b/langtools/make/build.properties @@ -116,6 +116,7 @@ javac.includes = \ javax/annotation/processing/ \ javax/lang/model/ \ javax/tools/ \ + jdk/ \ com/sun/source/ \ com/sun/tools/javac/ \ com/sun/tools/doclint/ diff --git a/langtools/src/share/classes/jdk/Supported.java b/langtools/src/share/classes/jdk/Supported.java new file mode 100644 index 00000000000..f5bf1c54ba6 --- /dev/null +++ b/langtools/src/share/classes/jdk/Supported.java @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2013, 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. + */ + +package jdk; + +import java.lang.annotation.*; + +/** + * Indicates whether or not a JDK specific type or package is a + * supported part of the JDK. + * + * This annotation should only be applied to types and packages + * outside of the Java SE namespaces of {@code java.*} and + * {@code javax.*} packages. For example, certain portions of {@code + * com.sun.*} are official parts of the JDK meant to be generally + * usable while other portions of {@code com.sun.*} are not. This + * annotation type allows those portions to be easily and + * programmaticly distinguished. + * + * @since 1.8 + */ +@Documented +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.TYPE, ElementType.PACKAGE}) +@Supported +public @interface Supported { + /** + * Whether or not this package or type is a supported part of the JDK. + */ + boolean value() default true; +} From 854e269f2070cb04422933225eff9841837a553e Mon Sep 17 00:00:00 2001 From: Brian Burkhalter Date: Fri, 1 Feb 2013 21:01:44 +0000 Subject: [PATCH 156/210] 5035569: Formatter should document that %a conversion unsupported for BigDecimal args Reviewed-by: darcy --- jdk/src/share/classes/java/util/Formatter.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/jdk/src/share/classes/java/util/Formatter.java b/jdk/src/share/classes/java/util/Formatter.java index f5f479588c1..03a58004918 100644 --- a/jdk/src/share/classes/java/util/Formatter.java +++ b/jdk/src/share/classes/java/util/Formatter.java @@ -351,7 +351,9 @@ import sun.misc.FormattedFloatingDecimal; * {@code 'a'}, {@code 'A'} * floating point * The result is formatted as a hexadecimal floating-point number with - * a significand and an exponent + * a significand and an exponent. This conversion is not supported + * for the {@code BigDecimal} type despite the latter's being in the + * floating point argument category. * * {@code 't'}, {@code 'T'} * date/time From d701ede8bbdc597bbf4dd9cdffbd4c1903531735 Mon Sep 17 00:00:00 2001 From: John Cuthbertson Date: Fri, 1 Feb 2013 13:17:04 -0800 Subject: [PATCH 157/210] 8006894: G1: Number of marking threads missing from PrintFlagsFinal output Set ConcGCThreads to the calculated number of marking threads. Reviewed-by: jmasa, ysr --- .../gc_implementation/g1/concurrentMark.cpp | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp index 3199cbf5a60..50821ac0cfb 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp @@ -571,19 +571,14 @@ ConcurrentMark::ConcurrentMark(G1CollectedHeap* g1h, ReservedSpace heap_rs) : _sleep_factor = 0.0; _marking_task_overhead = 1.0; } else { - if (ConcGCThreads > 0) { - // notice that ConcGCThreads overwrites G1MarkingOverheadPercent + if (!FLAG_IS_DEFAULT(ConcGCThreads) && ConcGCThreads > 0) { + // Note: ConcGCThreads has precedence over G1MarkingOverheadPercent // if both are set - - _parallel_marking_threads = (uint) ConcGCThreads; - _max_parallel_marking_threads = _parallel_marking_threads; _sleep_factor = 0.0; _marking_task_overhead = 1.0; } else if (G1MarkingOverheadPercent > 0) { - // we will calculate the number of parallel marking threads - // based on a target overhead with respect to the soft real-time - // goal - + // We will calculate the number of parallel marking threads based + // on a target overhead with respect to the soft real-time goal double marking_overhead = (double) G1MarkingOverheadPercent / 100.0; double overall_cm_overhead = (double) MaxGCPauseMillis * marking_overhead / @@ -596,17 +591,22 @@ ConcurrentMark::ConcurrentMark(G1CollectedHeap* g1h, ReservedSpace heap_rs) : double sleep_factor = (1.0 - marking_task_overhead) / marking_task_overhead; - _parallel_marking_threads = (uint) marking_thread_num; - _max_parallel_marking_threads = _parallel_marking_threads; + FLAG_SET_ERGO(uintx, ConcGCThreads, (uint) marking_thread_num); _sleep_factor = sleep_factor; _marking_task_overhead = marking_task_overhead; } else { - _parallel_marking_threads = scale_parallel_threads((uint)ParallelGCThreads); - _max_parallel_marking_threads = _parallel_marking_threads; + // Calculate the number of parallel marking threads by scaling + // the number of parallel GC threads. + uint marking_thread_num = scale_parallel_threads((uint) ParallelGCThreads); + FLAG_SET_ERGO(uintx, ConcGCThreads, marking_thread_num); _sleep_factor = 0.0; _marking_task_overhead = 1.0; } + assert(ConcGCThreads > 0, "Should have been set"); + _parallel_marking_threads = (uint) ConcGCThreads; + _max_parallel_marking_threads = _parallel_marking_threads; + if (parallel_marking_threads() > 1) { _cleanup_task_overhead = 1.0; } else { From 111ddcc8274fa81649917b2c61558baab97507c7 Mon Sep 17 00:00:00 2001 From: Christian Tornqvist Date: Fri, 1 Feb 2013 23:48:08 +0100 Subject: [PATCH 158/210] 8005012: Add WB APIs to better support NMT testing Add WB API functions to enable better NMT testing Reviewed-by: dholmes, zgu --- .../tools/whitebox/sun/hotspot/WhiteBox.java | 5 ++ hotspot/src/share/vm/memory/allocation.hpp | 5 +- hotspot/src/share/vm/prims/whitebox.cpp | 63 +++++++++++++++++++ hotspot/src/share/vm/services/memBaseline.cpp | 1 + hotspot/src/share/vm/services/memPtr.cpp | 2 +- hotspot/src/share/vm/services/memPtr.hpp | 10 +-- hotspot/src/share/vm/services/memRecorder.cpp | 5 +- hotspot/src/share/vm/services/memRecorder.hpp | 6 +- .../src/share/vm/services/memTrackWorker.cpp | 11 ++++ .../src/share/vm/services/memTrackWorker.hpp | 1 + hotspot/src/share/vm/services/memTracker.cpp | 50 ++++++++++++++- hotspot/src/share/vm/services/memTracker.hpp | 26 +++++++- 12 files changed, 171 insertions(+), 14 deletions(-) diff --git a/hotspot/src/share/tools/whitebox/sun/hotspot/WhiteBox.java b/hotspot/src/share/tools/whitebox/sun/hotspot/WhiteBox.java index 3a8592dec58..ecc5085896f 100644 --- a/hotspot/src/share/tools/whitebox/sun/hotspot/WhiteBox.java +++ b/hotspot/src/share/tools/whitebox/sun/hotspot/WhiteBox.java @@ -76,4 +76,9 @@ public class WhiteBox { public native long g1NumFreeRegions(); public native int g1RegionSize(); public native Object[] parseCommandLine(String commandline, DiagnosticCommand[] args); + + // NMT + public native boolean NMTAllocTest(); + public native boolean NMTFreeTestMemory(); + public native boolean NMTWaitForDataMerge(); } diff --git a/hotspot/src/share/vm/memory/allocation.hpp b/hotspot/src/share/vm/memory/allocation.hpp index 3cade72c260..e1e266ec5cf 100644 --- a/hotspot/src/share/vm/memory/allocation.hpp +++ b/hotspot/src/share/vm/memory/allocation.hpp @@ -145,9 +145,10 @@ enum MemoryType { mtChunk = 0x0B00, // chunk that holds content of arenas mtJavaHeap = 0x0C00, // Java heap mtClassShared = 0x0D00, // class data sharing - mt_number_of_types = 0x000D, // number of memory types (mtDontTrack + mtTest = 0x0E00, // Test type for verifying NMT + mt_number_of_types = 0x000E, // number of memory types (mtDontTrack // is not included as validate type) - mtDontTrack = 0x0E00, // memory we do not or cannot track + mtDontTrack = 0x0F00, // memory we do not or cannot track mt_masks = 0x7F00, // object type mask diff --git a/hotspot/src/share/vm/prims/whitebox.cpp b/hotspot/src/share/vm/prims/whitebox.cpp index 6c60be19f10..c93b4a2149a 100644 --- a/hotspot/src/share/vm/prims/whitebox.cpp +++ b/hotspot/src/share/vm/prims/whitebox.cpp @@ -43,6 +43,10 @@ #include "gc_implementation/g1/heapRegionRemSet.hpp" #endif // !SERIALGC +#ifdef INCLUDE_NMT +#include "services/memTracker.hpp" +#endif // INCLUDE_NMT + bool WhiteBox::_used = false; WB_ENTRY(jlong, WB_GetObjectAddress(JNIEnv* env, jobject o, jobject obj)) @@ -110,6 +114,60 @@ WB_ENTRY(jint, WB_G1RegionSize(JNIEnv* env, jobject o)) WB_END #endif // !SERIALGC +#ifdef INCLUDE_NMT +// Keep track of the 3 allocations in NMTAllocTest so we can free them later +// on and verify that they're not visible anymore +static void* nmtMtTest1 = NULL, *nmtMtTest2 = NULL, *nmtMtTest3 = NULL; + +// Alloc memory using the test memory type so that we can use that to see if +// NMT picks it up correctly +WB_ENTRY(jboolean, WB_NMTAllocTest(JNIEnv* env)) + void *mem; + + if (!MemTracker::is_on() || MemTracker::shutdown_in_progress()) { + return false; + } + + // Allocate 2 * 128k + 256k + 1024k and free the 1024k one to make sure we track + // everything correctly. Total should be 512k held alive. + nmtMtTest1 = os::malloc(128 * 1024, mtTest); + mem = os::malloc(1024 * 1024, mtTest); + nmtMtTest2 = os::malloc(256 * 1024, mtTest); + os::free(mem, mtTest); + nmtMtTest3 = os::malloc(128 * 1024, mtTest); + + return true; +WB_END + +// Free the memory allocated by NMTAllocTest +WB_ENTRY(jboolean, WB_NMTFreeTestMemory(JNIEnv* env)) + + if (nmtMtTest1 == NULL || nmtMtTest2 == NULL || nmtMtTest3 == NULL) { + return false; + } + + os::free(nmtMtTest1, mtTest); + nmtMtTest1 = NULL; + os::free(nmtMtTest2, mtTest); + nmtMtTest2 = NULL; + os::free(nmtMtTest3, mtTest); + nmtMtTest3 = NULL; + + return true; +WB_END + +// Block until the current generation of NMT data to be merged, used to reliably test the NMT feature +WB_ENTRY(jboolean, WB_NMTWaitForDataMerge(JNIEnv* env)) + + if (!MemTracker::is_on() || MemTracker::shutdown_in_progress()) { + return false; + } + + return MemTracker::wbtest_wait_for_data_merge(); +WB_END + +#endif // INCLUDE_NMT + //Some convenience methods to deal with objects from java int WhiteBox::offset_for_field(const char* field_name, oop object, Symbol* signature_symbol) { @@ -177,6 +235,11 @@ static JNINativeMethod methods[] = { {CC"g1NumFreeRegions", CC"()J", (void*)&WB_G1NumFreeRegions }, {CC"g1RegionSize", CC"()I", (void*)&WB_G1RegionSize }, #endif // !SERIALGC +#ifdef INCLUDE_NMT + {CC"NMTAllocTest", CC"()Z", (void*)&WB_NMTAllocTest }, + {CC"NMTFreeTestMemory", CC"()Z", (void*)&WB_NMTFreeTestMemory }, + {CC"NMTWaitForDataMerge",CC"()Z", (void*)&WB_NMTWaitForDataMerge}, +#endif // INCLUDE_NMT }; #undef CC diff --git a/hotspot/src/share/vm/services/memBaseline.cpp b/hotspot/src/share/vm/services/memBaseline.cpp index 9d9832e8601..681b4d7d9d1 100644 --- a/hotspot/src/share/vm/services/memBaseline.cpp +++ b/hotspot/src/share/vm/services/memBaseline.cpp @@ -40,6 +40,7 @@ MemType2Name MemBaseline::MemType2NameMap[NUMBER_OF_MEMORY_TYPE] = { {mtNMT, "Memory Tracking"}, {mtChunk, "Pooled Free Chunks"}, {mtClassShared,"Shared spaces for classes"}, + {mtTest, "Test"}, {mtNone, "Unknown"} // It can happen when type tagging records are lagging // behind }; diff --git a/hotspot/src/share/vm/services/memPtr.cpp b/hotspot/src/share/vm/services/memPtr.cpp index 5d0fbf5bf57..3e124e2bde2 100644 --- a/hotspot/src/share/vm/services/memPtr.cpp +++ b/hotspot/src/share/vm/services/memPtr.cpp @@ -27,8 +27,8 @@ #include "services/memTracker.hpp" volatile jint SequenceGenerator::_seq_number = 1; +volatile unsigned long SequenceGenerator::_generation = 1; NOT_PRODUCT(jint SequenceGenerator::_max_seq_number = 1;) -DEBUG_ONLY(volatile unsigned long SequenceGenerator::_generation = 0;) jint SequenceGenerator::next() { jint seq = Atomic::add(1, &_seq_number); diff --git a/hotspot/src/share/vm/services/memPtr.hpp b/hotspot/src/share/vm/services/memPtr.hpp index a27c3eb4a10..e1c852ac7ba 100644 --- a/hotspot/src/share/vm/services/memPtr.hpp +++ b/hotspot/src/share/vm/services/memPtr.hpp @@ -47,16 +47,16 @@ class SequenceGenerator : AllStatic { static void reset() { assert(SafepointSynchronize::is_at_safepoint(), "Safepoint required"); _seq_number = 1; - DEBUG_ONLY(_generation ++;) + _generation ++; }; - DEBUG_ONLY(static unsigned long current_generation() { return (unsigned long)_generation; }) + static unsigned long current_generation() { return _generation; } NOT_PRODUCT(static jint max_seq_num() { return _max_seq_number; }) private: - static volatile jint _seq_number; - NOT_PRODUCT(static jint _max_seq_number; ) - DEBUG_ONLY(static volatile unsigned long _generation; ) + static volatile jint _seq_number; + static volatile unsigned long _generation; + NOT_PRODUCT(static jint _max_seq_number; ) }; /* diff --git a/hotspot/src/share/vm/services/memRecorder.cpp b/hotspot/src/share/vm/services/memRecorder.cpp index 93703269ede..776ad223c00 100644 --- a/hotspot/src/share/vm/services/memRecorder.cpp +++ b/hotspot/src/share/vm/services/memRecorder.cpp @@ -55,7 +55,7 @@ volatile jint MemRecorder::_instance_count = 0; MemRecorder::MemRecorder() { assert(MemTracker::is_on(), "Native memory tracking is off"); Atomic::inc(&_instance_count); - debug_only(set_generation();) + set_generation(); if (MemTracker::track_callsite()) { _pointer_records = new (std::nothrow)FixedSizeMemPointerArray { // used for linked list MemRecorder* _next; // active recorder can only record a certain generation data - debug_only(unsigned long _generation;) + unsigned long _generation; protected: _NOINLINE_ MemRecorder(); @@ -251,6 +251,8 @@ class MemRecorder : public CHeapObj { SequencedRecordIterator pointer_itr(); + // return the generation of this recorder which it belongs to + unsigned long get_generation() const { return _generation; } protected: // number of MemRecorder instance static volatile jint _instance_count; @@ -263,7 +265,7 @@ class MemRecorder : public CHeapObj { static int sort_record_fn(const void* e1, const void* e2); debug_only(void check_dup_seq(jint seq) const;) - debug_only(void set_generation();) + void set_generation(); }; #endif // SHARE_VM_SERVICES_MEM_RECORDER_HPP diff --git a/hotspot/src/share/vm/services/memTrackWorker.cpp b/hotspot/src/share/vm/services/memTrackWorker.cpp index 19b375d4085..8c38d1a3731 100644 --- a/hotspot/src/share/vm/services/memTrackWorker.cpp +++ b/hotspot/src/share/vm/services/memTrackWorker.cpp @@ -91,6 +91,8 @@ void MemTrackWorker::run() { MemSnapshot* snapshot = MemTracker::get_snapshot(); assert(snapshot != NULL, "Worker should not be started"); MemRecorder* rec; + unsigned long processing_generation = 0; + bool worker_idle = false; while (!MemTracker::shutdown_in_progress()) { NOT_PRODUCT(_last_gen_in_use = generations_in_use();) @@ -100,6 +102,12 @@ void MemTrackWorker::run() { rec = _gen[_head].next_recorder(); } if (rec != NULL) { + if (rec->get_generation() != processing_generation || worker_idle) { + processing_generation = rec->get_generation(); + worker_idle = false; + MemTracker::set_current_processing_generation(processing_generation); + } + // merge the recorder into staging area if (!snapshot->merge(rec)) { MemTracker::shutdown(MemTracker::NMT_out_of_memory); @@ -129,6 +137,9 @@ void MemTrackWorker::run() { MemTracker::shutdown(MemTracker::NMT_out_of_memory); } } else { + // worker thread is idle + worker_idle = true; + MemTracker::report_worker_idle(); snapshot->wait(1000); ThreadCritical tc; // check if more data arrived diff --git a/hotspot/src/share/vm/services/memTrackWorker.hpp b/hotspot/src/share/vm/services/memTrackWorker.hpp index 9a2d52802e2..be80e294d58 100644 --- a/hotspot/src/share/vm/services/memTrackWorker.hpp +++ b/hotspot/src/share/vm/services/memTrackWorker.hpp @@ -107,6 +107,7 @@ class MemTrackWorker : public NamedThread { NOT_PRODUCT(int _merge_count;) NOT_PRODUCT(int _last_gen_in_use;) + // how many generations are queued inline int generations_in_use() const { return (_tail >= _head ? (_tail - _head + 1) : (MAX_GENERATIONS - (_head - _tail) + 1)); } diff --git a/hotspot/src/share/vm/services/memTracker.cpp b/hotspot/src/share/vm/services/memTracker.cpp index c8032d8fd1a..4c110d584ac 100644 --- a/hotspot/src/share/vm/services/memTracker.cpp +++ b/hotspot/src/share/vm/services/memTracker.cpp @@ -29,6 +29,7 @@ #include "runtime/mutexLocker.hpp" #include "runtime/safepoint.hpp" #include "runtime/threadCritical.hpp" +#include "runtime/vm_operations.hpp" #include "services/memPtr.hpp" #include "services/memReporter.hpp" #include "services/memTracker.hpp" @@ -65,6 +66,8 @@ volatile MemTracker::NMTStates MemTracker::_state = NMT_uninited; MemTracker::ShutdownReason MemTracker::_reason = NMT_shutdown_none; int MemTracker::_thread_count = 255; volatile jint MemTracker::_pooled_recorder_count = 0; +volatile unsigned long MemTracker::_processing_generation = 0; +volatile bool MemTracker::_worker_thread_idle = false; debug_only(intx MemTracker::_main_thread_tid = 0;) NOT_PRODUCT(volatile jint MemTracker::_pending_recorder_count = 0;) @@ -279,7 +282,7 @@ MemRecorder* MemTracker::get_new_or_pooled_instance() { } cur_head->set_next(NULL); Atomic::dec(&_pooled_recorder_count); - debug_only(cur_head->set_generation();) + cur_head->set_generation(); return cur_head; } } @@ -570,6 +573,51 @@ bool MemTracker::print_memory_usage(BaselineOutputer& out, size_t unit, bool sum return false; } +// Whitebox API for blocking until the current generation of NMT data has been merged +bool MemTracker::wbtest_wait_for_data_merge() { + // NMT can't be shutdown while we're holding _query_lock + MutexLockerEx lock(_query_lock, true); + assert(_worker_thread != NULL, "Invalid query"); + // the generation at query time, so NMT will spin till this generation is processed + unsigned long generation_at_query_time = SequenceGenerator::current_generation(); + unsigned long current_processing_generation = _processing_generation; + // if generation counter overflown + bool generation_overflown = (generation_at_query_time < current_processing_generation); + long generations_to_wrap = MAX_UNSIGNED_LONG - current_processing_generation; + // spin + while (!shutdown_in_progress()) { + if (!generation_overflown) { + if (current_processing_generation > generation_at_query_time) { + return true; + } + } else { + assert(generations_to_wrap >= 0, "Sanity check"); + long current_generations_to_wrap = MAX_UNSIGNED_LONG - current_processing_generation; + assert(current_generations_to_wrap >= 0, "Sanity check"); + // to overflow an unsigned long should take long time, so to_wrap check should be sufficient + if (current_generations_to_wrap > generations_to_wrap && + current_processing_generation > generation_at_query_time) { + return true; + } + } + + // if worker thread is idle, but generation is not advancing, that means + // there is not safepoint to let NMT advance generation, force one. + if (_worker_thread_idle) { + VM_ForceSafepoint vfs; + VMThread::execute(&vfs); + } + MemSnapshot* snapshot = get_snapshot(); + if (snapshot == NULL) { + return false; + } + snapshot->wait(1000); + current_processing_generation = _processing_generation; + } + // We end up here if NMT is shutting down before our data has been merged + return false; +} + // compare memory usage between current snapshot and baseline bool MemTracker::compare_memory_usage(BaselineOutputer& out, size_t unit, bool summary_only) { MutexLockerEx lock(_query_lock, true); diff --git a/hotspot/src/share/vm/services/memTracker.hpp b/hotspot/src/share/vm/services/memTracker.hpp index 538195c0c75..764b2950543 100644 --- a/hotspot/src/share/vm/services/memTracker.hpp +++ b/hotspot/src/share/vm/services/memTracker.hpp @@ -91,9 +91,10 @@ class MemTracker : AllStatic { static bool compare_memory_usage(BaselineOutputer& out, size_t unit, bool summary_only = true) { } + static bool wbtest_wait_for_data_merge() { } + static inline void sync() { } static inline void thread_exiting(JavaThread* thread) { } - }; @@ -111,6 +112,10 @@ class MemTracker : AllStatic { extern bool NMT_track_callsite; +#ifndef MAX_UNSIGNED_LONG +#define MAX_UNSIGNED_LONG (unsigned long)(-1) +#endif + #ifdef ASSERT #define DEBUG_CALLER_PC (NMT_track_callsite ? os::get_caller_pc(2) : 0) #else @@ -380,6 +385,11 @@ class MemTracker : AllStatic { static bool compare_memory_usage(BaselineOutputer& out, size_t unit, bool summary_only = true); + // the version for whitebox testing support, it ensures that all memory + // activities before this method call, are reflected in the snapshot + // database. + static bool wbtest_wait_for_data_merge(); + // sync is called within global safepoint to synchronize nmt data static void sync(); @@ -432,6 +442,15 @@ class MemTracker : AllStatic { static void create_record_in_recorder(address addr, MEMFLAGS type, size_t size, address pc, JavaThread* thread); + static void set_current_processing_generation(unsigned long generation) { + _worker_thread_idle = false; + _processing_generation = generation; + } + + static void report_worker_idle() { + _worker_thread_idle = true; + } + private: // global memory snapshot static MemSnapshot* _snapshot; @@ -483,6 +502,11 @@ class MemTracker : AllStatic { static volatile enum NMTStates _state; // the reason for shutting down nmt static enum ShutdownReason _reason; + // the generation that NMT is processing + static volatile unsigned long _processing_generation; + // although NMT is still procesing current generation, but + // there is not more recorder to process, set idle state + static volatile bool _worker_thread_idle; }; #endif // !INCLUDE_NMT From 26b2bbe306ae927f698322e245e232bf96dbfabf Mon Sep 17 00:00:00 2001 From: Mikael Vidstedt Date: Fri, 1 Feb 2013 17:21:53 -0800 Subject: [PATCH 159/210] 8007257: NPG: metaspace.cpp: Incorrect arguments in calls to err_msg Fix size checks in assert and corrected some print formats. Also reviewed by vitalyd@gmail.com. Reviewed-by: coleenp, sspitsyn --- hotspot/src/share/vm/memory/metaspace.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/hotspot/src/share/vm/memory/metaspace.cpp b/hotspot/src/share/vm/memory/metaspace.cpp index f54803a190f..c629e175f09 100644 --- a/hotspot/src/share/vm/memory/metaspace.cpp +++ b/hotspot/src/share/vm/memory/metaspace.cpp @@ -1737,10 +1737,10 @@ void SpaceManager::get_initial_chunk_sizes(Metaspace::MetaspaceType type, *class_chunk_word_size = ClassSmallChunk; break; } - assert(chunk_word_size != 0 && class_chunk_word_size != 0, + assert(*chunk_word_size != 0 && *class_chunk_word_size != 0, err_msg("Initial chunks sizes bad: data " SIZE_FORMAT " class " SIZE_FORMAT, - chunk_word_size, class_chunk_word_size)); + *chunk_word_size, *class_chunk_word_size)); } size_t SpaceManager::sum_free_in_chunks_in_use() const { @@ -2040,7 +2040,7 @@ SpaceManager::~SpaceManager() { align_size_up(humongous_chunks->word_size(), HumongousChunkGranularity), err_msg("Humongous chunk size is wrong: word size " SIZE_FORMAT - " granularity " SIZE_FORMAT, + " granularity %d", humongous_chunks->word_size(), HumongousChunkGranularity)); Metachunk* next_humongous_chunks = humongous_chunks->next(); chunk_manager->humongous_dictionary()->return_chunk(humongous_chunks); @@ -2264,7 +2264,8 @@ void SpaceManager::verify_allocation_total() { } MutexLockerEx cl(lock(), Mutex::_no_safepoint_check_flag); assert(allocation_total() == sum_used_in_chunks_in_use(), - err_msg("allocation total is not consistent %d vs %d", + err_msg("allocation total is not consistent " SIZE_FORMAT + " vs " SIZE_FORMAT, allocation_total(), sum_used_in_chunks_in_use())); } @@ -2578,7 +2579,8 @@ void Metaspace::global_initialize() { // argument passed in is at the top of the compressed space void Metaspace::initialize_class_space(ReservedSpace rs) { // The reserved space size may be bigger because of alignment, esp with UseLargePages - assert(rs.size() >= ClassMetaspaceSize, err_msg("%d != %d", rs.size(), ClassMetaspaceSize)); + assert(rs.size() >= ClassMetaspaceSize, + err_msg(SIZE_FORMAT " != " UINTX_FORMAT, rs.size(), ClassMetaspaceSize)); _class_space_list = new VirtualSpaceList(rs); } From 0050c5b4fbec24b46fb46c5d070a98a4e86c2174 Mon Sep 17 00:00:00 2001 From: Joe Darcy Date: Fri, 1 Feb 2013 19:30:02 -0800 Subject: [PATCH 160/210] 6964528: Double.toHexString(double d) String manipulation with + in an append of StringBuilder Reviewed-by: shade --- jdk/src/share/classes/java/lang/Double.java | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/jdk/src/share/classes/java/lang/Double.java b/jdk/src/share/classes/java/lang/Double.java index f79980f4bb8..9bdb0ca4679 100644 --- a/jdk/src/share/classes/java/lang/Double.java +++ b/jdk/src/share/classes/java/lang/Double.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1994, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1994, 2013, 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 @@ -289,7 +289,7 @@ public final class Double extends Number implements Comparable { return Double.toString(d); else { // Initialized to maximum size of output. - StringBuffer answer = new StringBuffer(24); + StringBuilder answer = new StringBuilder(24); if (Math.copySign(1.0, d) == -1.0) // value is negative, answer.append("-"); // so append sign info @@ -300,8 +300,7 @@ public final class Double extends Number implements Comparable { if(d == 0.0) { answer.append("0.0p0"); - } - else { + } else { boolean subnormal = (d < DoubleConsts.MIN_NORMAL); // Isolate significand bits and OR in a high-order bit @@ -324,13 +323,14 @@ public final class Double extends Number implements Comparable { "0": signif.replaceFirst("0{1,12}$", "")); + answer.append('p'); // If the value is subnormal, use the E_min exponent // value for double; otherwise, extract and report d's // exponent (the representation of a subnormal uses // E_min -1). - answer.append("p" + (subnormal ? - DoubleConsts.MIN_EXPONENT: - Math.getExponent(d) )); + answer.append(subnormal ? + DoubleConsts.MIN_EXPONENT: + Math.getExponent(d)); } return answer.toString(); } From 81a6d7fb0112e56b07f00075f5602eac0595140e Mon Sep 17 00:00:00 2001 From: Kumar Srinivasan Date: Fri, 1 Feb 2013 22:12:52 -0800 Subject: [PATCH 161/210] 8003549: (pack200) assertion errors when processing lambda class files with IMethods Add more check for opcode, sketch provided by jrose Reviewed-by: jrose --- .../com/sun/java/util/jar/pack/Attribute.java | 23 +++-- .../sun/java/util/jar/pack/ClassReader.java | 53 +++++++--- .../sun/java/util/jar/pack/ConstantPool.java | 30 +++++- .../sun/java/util/jar/pack/Instruction.java | 14 ++- .../sun/java/util/jar/pack/PackageWriter.java | 10 ++ .../sun/java/util/jar/pack/PackerImpl.java | 14 ++- .../com/sun/java/util/jar/pack/PropMap.java | 7 +- .../com/sun/java/util/jar/pack/Utils.java | 8 +- jdk/test/ProblemList.txt | 3 - jdk/test/tools/pack200/InstructionTests.java | 99 +++++++++++++++++++ .../src/xmlkit/ClassReader.java | 17 ++++ 11 files changed, 241 insertions(+), 37 deletions(-) create mode 100644 jdk/test/tools/pack200/InstructionTests.java diff --git a/jdk/src/share/classes/com/sun/java/util/jar/pack/Attribute.java b/jdk/src/share/classes/com/sun/java/util/jar/pack/Attribute.java index 9e891fc7c87..f6ff030263e 100644 --- a/jdk/src/share/classes/com/sun/java/util/jar/pack/Attribute.java +++ b/jdk/src/share/classes/com/sun/java/util/jar/pack/Attribute.java @@ -1287,19 +1287,24 @@ class Attribute implements Comparable { if (localRef == 0) { globalRef = null; // N.B. global null reference is -1 } else { - globalRef = holder.getCPMap()[localRef]; - if (e.refKind == CONSTANT_Signature + Entry[] cpMap = holder.getCPMap(); + globalRef = (localRef >= 0 && localRef < cpMap.length + ? cpMap[localRef] + : null); + byte tag = e.refKind; + if (globalRef != null && tag == CONSTANT_Signature && globalRef.getTag() == CONSTANT_Utf8) { // Cf. ClassReader.readSignatureRef. String typeName = globalRef.stringValue(); globalRef = ConstantPool.getSignatureEntry(typeName); - } else if (e.refKind == CONSTANT_FieldSpecific) { - assert(globalRef.getTag() >= CONSTANT_Integer); - assert(globalRef.getTag() <= CONSTANT_String || - globalRef.getTag() >= CONSTANT_MethodHandle); - assert(globalRef.getTag() <= CONSTANT_MethodType); - } else if (e.refKind < CONSTANT_GroupFirst) { - assert(e.refKind == globalRef.getTag()); + } + String got = (globalRef == null + ? "invalid CP index" + : "type=" + ConstantPool.tagName(globalRef.tag)); + if (globalRef == null || !globalRef.tagMatches(tag)) { + throw new IllegalArgumentException( + "Bad constant, expected type=" + + ConstantPool.tagName(tag) + " got " + got); } } out.putRef(bandIndex, globalRef); diff --git a/jdk/src/share/classes/com/sun/java/util/jar/pack/ClassReader.java b/jdk/src/share/classes/com/sun/java/util/jar/pack/ClassReader.java index 2ca2d0926c6..3df8706da37 100644 --- a/jdk/src/share/classes/com/sun/java/util/jar/pack/ClassReader.java +++ b/jdk/src/share/classes/com/sun/java/util/jar/pack/ClassReader.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2013, 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 @@ -54,6 +54,7 @@ class ClassReader { Package pkg; Class cls; long inPos; + long constantPoolLimit = -1; DataInputStream in; Map attrDefs; Map attrCommands; @@ -117,15 +118,33 @@ class ClassReader { private Entry readRef(byte tag) throws IOException { Entry e = readRef(); - assert(e != null); assert(!(e instanceof UnresolvedEntry)); - assert(e.tagMatches(tag)); + checkTag(e, tag); return e; } + /** Throw a ClassFormatException if the entry does not match the expected tag type. */ + private Entry checkTag(Entry e, byte tag) throws ClassFormatException { + if (e == null || !e.tagMatches(tag)) { + String where = (inPos == constantPoolLimit + ? " in constant pool" + : " at pos: " + inPos); + String got = (e == null + ? "null CP index" + : "type=" + ConstantPool.tagName(e.tag)); + throw new ClassFormatException("Bad constant, expected type=" + + ConstantPool.tagName(tag) + + " got "+ got + ", in File: " + cls.file.nameString + where); + } + return e; + } + private Entry checkTag(Entry e, byte tag, boolean nullOK) throws ClassFormatException { + return nullOK && e == null ? null : checkTag(e, tag); + } + private Entry readRefOrNull(byte tag) throws IOException { Entry e = readRef(); - assert(e == null || e.tagMatches(tag)); + checkTag(e, tag, true); return e; } @@ -143,8 +162,10 @@ class ClassReader { private SignatureEntry readSignatureRef() throws IOException { // The class file stores a Utf8, but we want a Signature. - Entry e = readRef(CONSTANT_Utf8); - return ConstantPool.getSignatureEntry(e.stringValue()); + Entry e = readRef(CONSTANT_Signature); + return (e != null && e.getTag() == CONSTANT_Utf8) + ? ConstantPool.getSignatureEntry(e.stringValue()) + : (SignatureEntry) e; } void read() throws IOException { @@ -279,6 +300,7 @@ class ClassReader { " at pos: " + inPos); } } + constantPoolLimit = inPos; // Fix up refs, which might be out of order. while (fptr > 0) { @@ -311,25 +333,25 @@ class ClassReader { case CONSTANT_Fieldref: case CONSTANT_Methodref: case CONSTANT_InterfaceMethodref: - ClassEntry mclass = (ClassEntry) cpMap[ref]; - DescriptorEntry mdescr = (DescriptorEntry) cpMap[ref2]; + ClassEntry mclass = (ClassEntry) checkTag(cpMap[ref], CONSTANT_Class); + DescriptorEntry mdescr = (DescriptorEntry) checkTag(cpMap[ref2], CONSTANT_NameandType); cpMap[cpi] = ConstantPool.getMemberEntry((byte)tag, mclass, mdescr); break; case CONSTANT_NameandType: - Utf8Entry mname = (Utf8Entry) cpMap[ref]; - Utf8Entry mtype = (Utf8Entry) cpMap[ref2]; + Utf8Entry mname = (Utf8Entry) checkTag(cpMap[ref], CONSTANT_Utf8); + Utf8Entry mtype = (Utf8Entry) checkTag(cpMap[ref2], CONSTANT_Signature); cpMap[cpi] = ConstantPool.getDescriptorEntry(mname, mtype); break; case CONSTANT_MethodType: - cpMap[cpi] = ConstantPool.getMethodTypeEntry((Utf8Entry) cpMap[ref]); + cpMap[cpi] = ConstantPool.getMethodTypeEntry((Utf8Entry) checkTag(cpMap[ref], CONSTANT_Signature)); break; case CONSTANT_MethodHandle: byte refKind = (byte)(-1 ^ ref); - MemberEntry memRef = (MemberEntry) cpMap[ref2]; + MemberEntry memRef = (MemberEntry) checkTag(cpMap[ref2], CONSTANT_AnyMember); cpMap[cpi] = ConstantPool.getMethodHandleEntry(refKind, memRef); break; case CONSTANT_InvokeDynamic: - DescriptorEntry idescr = (DescriptorEntry) cpMap[ref2]; + DescriptorEntry idescr = (DescriptorEntry) checkTag(cpMap[ref2], CONSTANT_NameandType); cpMap[cpi] = new UnresolvedEntry((byte)tag, (-1 ^ ref), idescr); // Note that ref must be resolved later, using the BootstrapMethods attribute. break; @@ -541,7 +563,8 @@ class ClassReader { code.max_locals = readUnsignedShort(); code.bytes = new byte[readInt()]; in.readFully(code.bytes); - Instruction.opcodeChecker(code.bytes); + Entry[] cpMap = cls.getCPMap(); + Instruction.opcodeChecker(code.bytes, cpMap); int nh = readUnsignedShort(); code.setHandlerCount(nh); for (int i = 0; i < nh; i++) { @@ -559,7 +582,7 @@ class ClassReader { MethodHandleEntry bsmRef = (MethodHandleEntry) readRef(CONSTANT_MethodHandle); Entry[] argRefs = new Entry[readUnsignedShort()]; for (int j = 0; j < argRefs.length; j++) { - argRefs[j] = readRef(); + argRefs[j] = readRef(CONSTANT_LoadableValue); } bsms[i] = ConstantPool.getBootstrapMethodEntry(bsmRef, argRefs); } diff --git a/jdk/src/share/classes/com/sun/java/util/jar/pack/ConstantPool.java b/jdk/src/share/classes/com/sun/java/util/jar/pack/ConstantPool.java index be4da54d247..ad2175f9993 100644 --- a/jdk/src/share/classes/com/sun/java/util/jar/pack/ConstantPool.java +++ b/jdk/src/share/classes/com/sun/java/util/jar/pack/ConstantPool.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2013, 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 @@ -243,8 +243,32 @@ class ConstantPool { return tag == CONSTANT_Double || tag == CONSTANT_Long; } - public final boolean tagMatches(int tag) { - return (this.tag == tag); + public final boolean tagMatches(int matchTag) { + if (tag == matchTag) + return true; + byte[] allowedTags; + switch (matchTag) { + case CONSTANT_All: + return true; + case CONSTANT_Signature: + return tag == CONSTANT_Utf8; // format check also? + case CONSTANT_LoadableValue: + allowedTags = LOADABLE_VALUE_TAGS; + break; + case CONSTANT_AnyMember: + allowedTags = ANY_MEMBER_TAGS; + break; + case CONSTANT_FieldSpecific: + allowedTags = FIELD_SPECIFIC_TAGS; + break; + default: + return false; + } + for (byte b : allowedTags) { + if (b == tag) + return true; + } + return false; } public String toString() { diff --git a/jdk/src/share/classes/com/sun/java/util/jar/pack/Instruction.java b/jdk/src/share/classes/com/sun/java/util/jar/pack/Instruction.java index f488bede323..31ee22b059d 100644 --- a/jdk/src/share/classes/com/sun/java/util/jar/pack/Instruction.java +++ b/jdk/src/share/classes/com/sun/java/util/jar/pack/Instruction.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2013, 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 @@ -647,7 +647,7 @@ class Instruction { } } - public static void opcodeChecker(byte[] code) throws FormatException { + public static void opcodeChecker(byte[] code, ConstantPool.Entry[] cpMap) throws FormatException { Instruction i = at(code, 0); while (i != null) { int opcode = i.getBC(); @@ -655,6 +655,16 @@ class Instruction { String message = "illegal opcode: " + opcode + " " + i; throw new FormatException(message); } + ConstantPool.Entry e = i.getCPRef(cpMap); + if (e != null) { + byte tag = i.getCPTag(); + if (!e.tagMatches(tag)) { + String message = "illegal reference, expected type=" + + ConstantPool.tagName(tag) + ": " + + i.toString(cpMap); + throw new FormatException(message); + } + } i = i.next(); } } diff --git a/jdk/src/share/classes/com/sun/java/util/jar/pack/PackageWriter.java b/jdk/src/share/classes/com/sun/java/util/jar/pack/PackageWriter.java index e6990451135..47959294fd2 100644 --- a/jdk/src/share/classes/com/sun/java/util/jar/pack/PackageWriter.java +++ b/jdk/src/share/classes/com/sun/java/util/jar/pack/PackageWriter.java @@ -1618,6 +1618,16 @@ class PackageWriter extends BandStructure { bc_which = null; assert(false); } + if (ref != null && bc_which.index != null && !bc_which.index.contains(ref)) { + // Crash and burn with a complaint if there are funny + // references for this bytecode instruction. + // Example: invokestatic of a CONSTANT_InterfaceMethodref. + String complaint = code.getMethod() + + " contains a bytecode " + i + + " with an unsupported constant reference; please use the pass-file option on this class."; + Utils.log.warning(complaint); + throw new IOException(complaint); + } bc_codes.putByte(vbc); bc_which.putRef(ref); // handle trailing junk diff --git a/jdk/src/share/classes/com/sun/java/util/jar/pack/PackerImpl.java b/jdk/src/share/classes/com/sun/java/util/jar/pack/PackerImpl.java index c7ef4ee2013..0dc88a108c7 100644 --- a/jdk/src/share/classes/com/sun/java/util/jar/pack/PackerImpl.java +++ b/jdk/src/share/classes/com/sun/java/util/jar/pack/PackerImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2013, 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 @@ -180,6 +180,15 @@ public class PackerImpl extends TLGlobals implements Pack200.Packer { } unknownAttrCommand = uaMode.intern(); } + final String classFormatCommand; + { + String fmtMode = props.getProperty(Utils.CLASS_FORMAT_ERROR, Pack200.Packer.PASS); + if (!(Pack200.Packer.PASS.equals(fmtMode) || + Pack200.Packer.ERROR.equals(fmtMode))) { + throw new RuntimeException("Bad option: " + Utils.CLASS_FORMAT_ERROR + " = " + fmtMode); + } + classFormatCommand = fmtMode.intern(); + } final Map attrDefs; final Map attrCommands; @@ -505,8 +514,7 @@ public class PackerImpl extends TLGlobals implements Pack200.Packer { } } else if (ioe instanceof ClassReader.ClassFormatException) { ClassReader.ClassFormatException ce = (ClassReader.ClassFormatException) ioe; - // %% TODO: Do we invent a new property for this or reuse %% - if (unknownAttrCommand.equals(Pack200.Packer.PASS)) { + if (classFormatCommand.equals(Pack200.Packer.PASS)) { Utils.log.info(ce.toString()); Utils.log.warning(message + " unknown class format: " + fname); diff --git a/jdk/src/share/classes/com/sun/java/util/jar/pack/PropMap.java b/jdk/src/share/classes/com/sun/java/util/jar/pack/PropMap.java index 6199c77b51d..24485040378 100644 --- a/jdk/src/share/classes/com/sun/java/util/jar/pack/PropMap.java +++ b/jdk/src/share/classes/com/sun/java/util/jar/pack/PropMap.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2013, 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 @@ -112,6 +112,11 @@ final class PropMap implements SortedMap { // Pass through files with unrecognized attributes by default. props.put(Pack200.Packer.UNKNOWN_ATTRIBUTE, Pack200.Packer.PASS); + // Pass through files with unrecognized format by default, also + // allow system property to be set + props.put(Utils.CLASS_FORMAT_ERROR, + System.getProperty(Utils.CLASS_FORMAT_ERROR, Pack200.Packer.PASS)); + // Default effort is 5, midway between 1 and 9. props.put(Pack200.Packer.EFFORT, "5"); diff --git a/jdk/src/share/classes/com/sun/java/util/jar/pack/Utils.java b/jdk/src/share/classes/com/sun/java/util/jar/pack/Utils.java index 5edd73e21cb..ebe0960dba0 100644 --- a/jdk/src/share/classes/com/sun/java/util/jar/pack/Utils.java +++ b/jdk/src/share/classes/com/sun/java/util/jar/pack/Utils.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2013, 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 @@ -122,6 +122,12 @@ class Utils { */ static final String PACK_ZIP_ARCHIVE_MARKER_COMMENT = "PACK200"; + /* + * behaviour when we hit a class format error, but not necessarily + * an unknown attribute, by default it is allowed to PASS. + */ + static final String CLASS_FORMAT_ERROR = COM_PREFIX+"class.format.error"; + // Keep a TLS point to the global data and environment. // This makes it simpler to supply environmental options // to the engine code, especially the native code. diff --git a/jdk/test/ProblemList.txt b/jdk/test/ProblemList.txt index 5e181ac7e03..7b763477192 100644 --- a/jdk/test/ProblemList.txt +++ b/jdk/test/ProblemList.txt @@ -321,9 +321,6 @@ sun/jvmstat/monitor/MonitoredVm/CR6672135.java generic-all tools/pack200/CommandLineTests.java generic-all tools/pack200/Pack200Test.java generic-all -# 8001163 -tools/pack200/AttributeTests.java generic-all - # 7150569 tools/launcher/UnicodeTest.java macosx-all diff --git a/jdk/test/tools/pack200/InstructionTests.java b/jdk/test/tools/pack200/InstructionTests.java new file mode 100644 index 00000000000..ce92c0ed558 --- /dev/null +++ b/jdk/test/tools/pack200/InstructionTests.java @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2013, 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. + * + * 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. + */ +import java.io.File; +import java.nio.charset.Charset; +import java.nio.file.Files; +import java.util.ArrayList; +import java.util.List; +import static java.nio.file.StandardOpenOption.*; +import java.util.regex.Pattern; + +/* + * @test + * @bug 8003549 + * @summary tests class files instruction formats introduced in JSR-335 + * @compile -XDignore.symbol.file Utils.java InstructionTests.java + * @run main InstructionTests + * @author ksrini + */ +public class InstructionTests { + public static void main(String... args) throws Exception { + testInvokeOpCodes(); + } + /* + * the following should produce invokestatic and invokespecial + * on InterfaceMethodRefs vs. MethodRefs, packer/unpacker should work + */ + static void testInvokeOpCodes() throws Exception { + List scratch = new ArrayList<>(); + final String fname = "A"; + String javaFileName = fname + Utils.JAVA_FILE_EXT; + scratch.add("interface IntIterator {"); + scratch.add(" default void forEach(){}"); + scratch.add(" static void next() {}"); + scratch.add("}"); + scratch.add("class A implements IntIterator {"); + scratch.add("public void forEach(Object o){"); + scratch.add("IntIterator.super.forEach();"); + scratch.add("IntIterator.next();"); + scratch.add("}"); + scratch.add("}"); + File cwd = new File("."); + File javaFile = new File(cwd, javaFileName); + Files.write(javaFile.toPath(), scratch, Charset.defaultCharset(), + CREATE, TRUNCATE_EXISTING); + + // make sure we have -g so that we compare LVT and LNT entries + Utils.compiler("-g", javaFile.getName()); + + // jar the file up + File testjarFile = new File(cwd, "test" + Utils.JAR_FILE_EXT); + Utils.jar("cvf", testjarFile.getName(), "."); + + // pack using --repack + File outjarFile = new File(cwd, "out" + Utils.JAR_FILE_EXT); + scratch.clear(); + scratch.add(Utils.getPack200Cmd()); + scratch.add("-J-ea"); + scratch.add("-J-esa"); + scratch.add("--repack"); + scratch.add(outjarFile.getName()); + scratch.add(testjarFile.getName()); + List output = Utils.runExec(scratch); + // TODO remove this when we get bc escapes working correctly + // this test anyhow would fail at that time + findString("WARNING: Passing.*" + fname + Utils.CLASS_FILE_EXT, + output); + + Utils.doCompareVerify(testjarFile, outjarFile); + } + + static boolean findString(String str, List list) { + Pattern p = Pattern.compile(str); + for (String x : list) { + if (p.matcher(x).matches()) + return true; + } + throw new RuntimeException("Error: " + str + " not found in output"); + } +} diff --git a/jdk/test/tools/pack200/pack200-verifier/src/xmlkit/ClassReader.java b/jdk/test/tools/pack200/pack200-verifier/src/xmlkit/ClassReader.java index 177849872a9..db7d0465777 100644 --- a/jdk/test/tools/pack200/pack200-verifier/src/xmlkit/ClassReader.java +++ b/jdk/test/tools/pack200/pack200-verifier/src/xmlkit/ClassReader.java @@ -57,8 +57,10 @@ import com.sun.tools.classfile.MethodParameters_attribute; import com.sun.tools.classfile.Opcode; import com.sun.tools.classfile.RuntimeInvisibleAnnotations_attribute; import com.sun.tools.classfile.RuntimeInvisibleParameterAnnotations_attribute; +import com.sun.tools.classfile.RuntimeInvisibleTypeAnnotations_attribute; import com.sun.tools.classfile.RuntimeVisibleAnnotations_attribute; import com.sun.tools.classfile.RuntimeVisibleParameterAnnotations_attribute; +import com.sun.tools.classfile.RuntimeVisibleTypeAnnotations_attribute; import com.sun.tools.classfile.Signature_attribute; import com.sun.tools.classfile.SourceDebugExtension_attribute; import com.sun.tools.classfile.SourceFile_attribute; @@ -1214,6 +1216,21 @@ class AttributeVisitor implements Attribute.Visitor { p.add(e); return null; } + + /* + * TODO + * add these two for now to keep the compiler happy, we will implement + * these along with the JSR-308 changes. + */ + @Override + public Element visitRuntimeVisibleTypeAnnotations(RuntimeVisibleTypeAnnotations_attribute rvta, Element p) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public Element visitRuntimeInvisibleTypeAnnotations(RuntimeInvisibleTypeAnnotations_attribute rita, Element p) { + throw new UnsupportedOperationException("Not supported yet."); + } } class StackMapVisitor implements StackMapTable_attribute.stack_map_frame.Visitor { From 8da1d4a40c9b4827e2fdb3cbe7488c5cb991c9ae Mon Sep 17 00:00:00 2001 From: Kumar Srinivasan Date: Fri, 1 Feb 2013 22:18:18 -0800 Subject: [PATCH 162/210] 8007428: [launcher] add tools/launcher/FXLauncherTest.java to ProblemList.txt Reviewed-by: mchung --- jdk/test/ProblemList.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/jdk/test/ProblemList.txt b/jdk/test/ProblemList.txt index 7b763477192..1870b0b9219 100644 --- a/jdk/test/ProblemList.txt +++ b/jdk/test/ProblemList.txt @@ -324,6 +324,9 @@ tools/pack200/Pack200Test.java generic-all # 7150569 tools/launcher/UnicodeTest.java macosx-all +# 8007410 +tools/launcher/FXLauncherTest.java linux-all + ############################################################################ # jdk_jdi From 8734c66d55d0f84d42d701fe243e7f57cc621c74 Mon Sep 17 00:00:00 2001 From: Christian Tornqvist Date: Sat, 2 Feb 2013 16:34:10 +0100 Subject: [PATCH 163/210] 8005013: Add NMT tests Add tests for the Native Memory Tracking feature, includes regression tests for 8005936 and 8004802 Reviewed-by: zgu, coleenp --- hotspot/test/TEST.ROOT | 2 +- hotspot/test/runtime/NMT/AllocTestType.java | 72 +++++++++++ .../runtime/NMT/BaselineWithParameter.java | 54 ++++++++ .../test/runtime/NMT/CommandLineDetail.java | 45 +++++++ .../runtime/NMT/CommandLineEmptyArgument.java | 41 ++++++ .../NMT/CommandLineInvalidArgument.java | 41 ++++++ .../test/runtime/NMT/CommandLineSummary.java | 45 +++++++ .../runtime/NMT/CommandLineTurnOffNMT.java | 44 +++++++ hotspot/test/runtime/NMT/JcmdScale.java | 67 ++++++++++ .../test/runtime/NMT/JcmdWithNMTDisabled.java | 63 ++++++++++ .../test/runtime/NMT/PrintNMTStatistics.java | 66 ++++++++++ .../PrintNMTStatisticsWithNMTDisabled.java | 44 +++++++ hotspot/test/runtime/NMT/ShutdownTwice.java | 56 +++++++++ .../runtime/NMT/SummaryAfterShutdown.java | 56 +++++++++ .../test/runtime/NMT/SummarySanityCheck.java | 119 ++++++++++++++++++ 15 files changed, 814 insertions(+), 1 deletion(-) create mode 100644 hotspot/test/runtime/NMT/AllocTestType.java create mode 100644 hotspot/test/runtime/NMT/BaselineWithParameter.java create mode 100644 hotspot/test/runtime/NMT/CommandLineDetail.java create mode 100644 hotspot/test/runtime/NMT/CommandLineEmptyArgument.java create mode 100644 hotspot/test/runtime/NMT/CommandLineInvalidArgument.java create mode 100644 hotspot/test/runtime/NMT/CommandLineSummary.java create mode 100644 hotspot/test/runtime/NMT/CommandLineTurnOffNMT.java create mode 100644 hotspot/test/runtime/NMT/JcmdScale.java create mode 100644 hotspot/test/runtime/NMT/JcmdWithNMTDisabled.java create mode 100644 hotspot/test/runtime/NMT/PrintNMTStatistics.java create mode 100644 hotspot/test/runtime/NMT/PrintNMTStatisticsWithNMTDisabled.java create mode 100644 hotspot/test/runtime/NMT/ShutdownTwice.java create mode 100644 hotspot/test/runtime/NMT/SummaryAfterShutdown.java create mode 100644 hotspot/test/runtime/NMT/SummarySanityCheck.java diff --git a/hotspot/test/TEST.ROOT b/hotspot/test/TEST.ROOT index 24014f68209..629bb54ddb4 100644 --- a/hotspot/test/TEST.ROOT +++ b/hotspot/test/TEST.ROOT @@ -28,4 +28,4 @@ # DO NOT EDIT without first contacting hotspot-regtest@sun.com # The list of keywords supported in this test suite -keys=cte_test +keys=cte_test jcmd nmt regression diff --git a/hotspot/test/runtime/NMT/AllocTestType.java b/hotspot/test/runtime/NMT/AllocTestType.java new file mode 100644 index 00000000000..7644884445d --- /dev/null +++ b/hotspot/test/runtime/NMT/AllocTestType.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2013, 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. + * + * 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. + */ + +/* + * @test + * @summary Test consistency of NMT by leaking a few select allocations of the Test type and then verify visibility with jcmd + * @key nmt jcmd + * @library /testlibrary + * @run compile -J-XX:+UnlockDiagnosticVMOptions -J-XX:+WhiteBoxAPI AllocTestType.java + * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:NativeMemoryTracking=detail AllocTestType + */ + +import com.oracle.java.testlibrary.*; +import sun.hotspot.WhiteBox; + +public class AllocTestType { + + public static void main(String args[]) throws Exception { + OutputAnalyzer output; + + // Grab my own PID + String pid = Integer.toString(ProcessTools.getProcessId()); + ProcessBuilder pb = new ProcessBuilder(); + + // Use WB API to alloc with the mtTest type + if (!WhiteBox.getWhiteBox().NMTAllocTest()) { + throw new Exception("Call to WB API NMTAllocTest() failed"); + } + + // Use WB API to ensure that all data has been merged before we continue + if (!WhiteBox.getWhiteBox().NMTWaitForDataMerge()) { + throw new Exception("Call to WB API NMTWaitForDataMerge() failed"); + } + + // Run 'jcmd VM.native_memory summary' + pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "summary"}); + output = new OutputAnalyzer(pb.start()); + output.shouldContain("Test (reserved=512KB, committed=512KB)"); + + // Free the memory allocated by NMTAllocTest + if (!WhiteBox.getWhiteBox().NMTFreeTestMemory()) { + throw new Exception("Call to WB API NMTFreeTestMemory() failed"); + } + + // Use WB API to ensure that all data has been merged before we continue + if (!WhiteBox.getWhiteBox().NMTWaitForDataMerge()) { + throw new Exception("Call to WB API NMTWaitForDataMerge() failed"); + } + output = new OutputAnalyzer(pb.start()); + output.shouldNotContain("Test (reserved="); + } +} diff --git a/hotspot/test/runtime/NMT/BaselineWithParameter.java b/hotspot/test/runtime/NMT/BaselineWithParameter.java new file mode 100644 index 00000000000..594bd7165ed --- /dev/null +++ b/hotspot/test/runtime/NMT/BaselineWithParameter.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2013, 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. + * + * 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. + */ + +/* + * @test + * @bug 8004802 + * @key nmt jcmd regression + * @summary Regression test for invoking a jcmd with baseline=false, result was that the target VM crashed + * @library /testlibrary + * @run main/othervm -XX:NativeMemoryTracking=detail BaselineWithParameter + */ + +import com.oracle.java.testlibrary.*; + +public class BaselineWithParameter { + + public static void main(String args[]) throws Exception { + // Grab my own PID + String pid = Integer.toString(ProcessTools.getProcessId()); + OutputAnalyzer output; + + ProcessBuilder pb = new ProcessBuilder(); + + // Run 'jcmd VM.native_memory baseline=false' + pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "baseline=false"}); + pb.start(); + + // Run 'jcmd VM.native_memory summary=false' + pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "summary=false"}); + output = new OutputAnalyzer(pb.start()); + output.shouldContain("No command to execute"); + + } +} diff --git a/hotspot/test/runtime/NMT/CommandLineDetail.java b/hotspot/test/runtime/NMT/CommandLineDetail.java new file mode 100644 index 00000000000..d993316ba9c --- /dev/null +++ b/hotspot/test/runtime/NMT/CommandLineDetail.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2013, 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. + * + * 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. + */ + + /* + * @test + * @key nmt + * @summary Running with NMT detail should not result in an error or warning + * @library /testlibrary + */ + +import com.oracle.java.testlibrary.*; + +public class CommandLineDetail { + + public static void main(String args[]) throws Exception { + + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( + "-XX:NativeMemoryTracking=detail", + "-version"); + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + output.shouldNotContain("error"); + output.shouldNotContain("warning"); + output.shouldHaveExitValue(0); + } +} diff --git a/hotspot/test/runtime/NMT/CommandLineEmptyArgument.java b/hotspot/test/runtime/NMT/CommandLineEmptyArgument.java new file mode 100644 index 00000000000..956cdd26006 --- /dev/null +++ b/hotspot/test/runtime/NMT/CommandLineEmptyArgument.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2013, 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. + * + * 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. + */ + + /* + * @test + * @key nmt + * @summary Empty argument to NMT should result in an informative error message + * @library /testlibrary + */ + +import com.oracle.java.testlibrary.*; + +public class CommandLineEmptyArgument { + + public static void main(String args[]) throws Exception { + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-XX:NativeMemoryTracking="); + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + output.shouldContain("Syntax error, expecting -XX:NativeMemoryTracking=[off|summary|detail]"); + output.shouldHaveExitValue(1); + } +} diff --git a/hotspot/test/runtime/NMT/CommandLineInvalidArgument.java b/hotspot/test/runtime/NMT/CommandLineInvalidArgument.java new file mode 100644 index 00000000000..79cc2de9442 --- /dev/null +++ b/hotspot/test/runtime/NMT/CommandLineInvalidArgument.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2013, 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. + * + * 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. + */ + + /* + * @test + * @key nmt + * @summary Invalid argument to NMT should result in an informative error message + * @library /testlibrary + */ + +import com.oracle.java.testlibrary.*; + +public class CommandLineInvalidArgument { + + public static void main(String args[]) throws Exception { + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-XX:NativeMemoryTracking=apa"); + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + output.shouldContain("Syntax error, expecting -XX:NativeMemoryTracking=[off|summary|detail]"); + output.shouldHaveExitValue(1); + } +} diff --git a/hotspot/test/runtime/NMT/CommandLineSummary.java b/hotspot/test/runtime/NMT/CommandLineSummary.java new file mode 100644 index 00000000000..b8415d1bde9 --- /dev/null +++ b/hotspot/test/runtime/NMT/CommandLineSummary.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2013, 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. + * + * 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. + */ + + /* + * @test + * @key nmt + * @summary Running with NMT summary should not result in an error or warning + * @library /testlibrary + */ + +import com.oracle.java.testlibrary.*; + +public class CommandLineSummary { + + public static void main(String args[]) throws Exception { + + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( + "-XX:NativeMemoryTracking=summary", + "-version"); + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + output.shouldNotContain("error"); + output.shouldNotContain("warning"); + output.shouldHaveExitValue(0); + } +} diff --git a/hotspot/test/runtime/NMT/CommandLineTurnOffNMT.java b/hotspot/test/runtime/NMT/CommandLineTurnOffNMT.java new file mode 100644 index 00000000000..e8d950cba0a --- /dev/null +++ b/hotspot/test/runtime/NMT/CommandLineTurnOffNMT.java @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2013, 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. + * + * 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. + */ + + /* + * @test + * @key nmt + * @summary Turning off NMT should not result in an error or warning + * @library /testlibrary + */ + +import com.oracle.java.testlibrary.*; + +public class CommandLineTurnOffNMT { + + public static void main(String args[]) throws Exception { + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( + "-XX:NativeMemoryTracking=off", + "-version"); + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + output.shouldNotContain("error"); + output.shouldNotContain("warning"); + output.shouldHaveExitValue(0); + } +} diff --git a/hotspot/test/runtime/NMT/JcmdScale.java b/hotspot/test/runtime/NMT/JcmdScale.java new file mode 100644 index 00000000000..e57d27b59a3 --- /dev/null +++ b/hotspot/test/runtime/NMT/JcmdScale.java @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2013, 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. + * + * 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. + */ + +/* + * @test + * @key nmt jcmd + * @summary Test the NMT scale parameter + * @library /testlibrary + * @run main/othervm -XX:NativeMemoryTracking=summary JcmdScale + */ + +import com.oracle.java.testlibrary.*; + +public class JcmdScale { + + public static void main(String args[]) throws Exception { + ProcessBuilder pb = new ProcessBuilder(); + OutputAnalyzer output; + // Grab my own PID + String pid = Integer.toString(ProcessTools.getProcessId()); + + pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "scale=KB"}); + output = new OutputAnalyzer(pb.start()); + output.shouldContain("KB, committed="); + + pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "scale=MB"}); + output = new OutputAnalyzer(pb.start()); + output.shouldContain("MB, committed="); + + pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "scale=GB"}); + output = new OutputAnalyzer(pb.start()); + output.shouldContain("GB, committed="); + + pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "scale=apa"}); + output = new OutputAnalyzer(pb.start()); + output.shouldContain("Incorrect scale value: apa"); + + pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "summary", "scale=GB"}); + output = new OutputAnalyzer(pb.start()); + output.shouldContain("GB, committed="); + + pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "summary", "scale=apa"}); + output = new OutputAnalyzer(pb.start()); + output.shouldContain("Incorrect scale value: apa"); + + } +} diff --git a/hotspot/test/runtime/NMT/JcmdWithNMTDisabled.java b/hotspot/test/runtime/NMT/JcmdWithNMTDisabled.java new file mode 100644 index 00000000000..7b58a841315 --- /dev/null +++ b/hotspot/test/runtime/NMT/JcmdWithNMTDisabled.java @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2013, 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. + * + * 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. + */ + +/* + * @test + * @key nmt jcmd + * @summary Verify that jcmd correctly reports that NMT is not enabled + * @library /testlibrary + * First run without enabling NMT + * @run main/othervm JcmdWithNMTDisabled + * Then run with explicitly disabling NMT, should not be any difference + * @run main/othervm -XX:NativeMemoryTracking=off JcmdWithNMTDisabled + */ + +import com.oracle.java.testlibrary.*; + +public class JcmdWithNMTDisabled { + static ProcessBuilder pb = new ProcessBuilder(); + static String pid; + + public static void main(String args[]) throws Exception { + // Grab my own PID + pid = Integer.toString(ProcessTools.getProcessId()); + + jcmdCommand("summary"); + jcmdCommand("detail"); + jcmdCommand("baseline"); + jcmdCommand("summary.diff"); + jcmdCommand("detail.diff"); + jcmdCommand("scale=GB"); + jcmdCommand("shutdown"); + } + + // Helper method for invoking different jcmd calls, all should fail with the same message saying NMT is not enabled + public static void jcmdCommand(String command) throws Exception { + + pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", command}); + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + + // Verify that jcmd reports that NMT is not enabled + output.shouldContain("Native memory tracking is not enabled"); + } +} diff --git a/hotspot/test/runtime/NMT/PrintNMTStatistics.java b/hotspot/test/runtime/NMT/PrintNMTStatistics.java new file mode 100644 index 00000000000..307ab948abd --- /dev/null +++ b/hotspot/test/runtime/NMT/PrintNMTStatistics.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2013, 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. + * + * 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. + */ + +/* + * @test + * @key nmt regression + * @bug 8005936 + * @summary Make sure PrintNMTStatistics works on normal JVM exit + * @library /testlibrary + * @run compile -J-XX:+UnlockDiagnosticVMOptions -J-XX:+WhiteBoxAPI PrintNMTStatistics.java + */ + +import com.oracle.java.testlibrary.*; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import sun.hotspot.WhiteBox; + +public class PrintNMTStatistics { + + public static void main(String args[]) throws Exception { + + // We start a new java process running with an argument and use WB API to ensure + // we have data for NMT on VM exit + if (args.length > 0) { + // Use WB API to ensure that all data has been merged before we continue + if (!WhiteBox.getWhiteBox().NMTWaitForDataMerge()) { + throw new Exception("Call to WB API NMTWaitForDataMerge() failed"); + } + return; + } + + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( + "-XX:+UnlockDiagnosticVMOptions", + "-XX:NativeMemoryTracking=summary", + "+XX:+PrintNMTStatistics", + "PrintNMTStatistics", + "test"); + + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + output.shouldContain("Java Heap (reserved="); + output.shouldNotContain("error"); + output.shouldNotContain("warning"); + output.shouldHaveExitValue(0); + } +} diff --git a/hotspot/test/runtime/NMT/PrintNMTStatisticsWithNMTDisabled.java b/hotspot/test/runtime/NMT/PrintNMTStatisticsWithNMTDisabled.java new file mode 100644 index 00000000000..1c25f284d4b --- /dev/null +++ b/hotspot/test/runtime/NMT/PrintNMTStatisticsWithNMTDisabled.java @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2013, 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. + * + * 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. + */ + + /* + * @test + * @key nmt + * @summary Trying to enable PrintNMTStatistics should result in a warning + * @library /testlibrary + */ + +import com.oracle.java.testlibrary.*; + +public class PrintNMTStatisticsWithNMTDisabled { + + public static void main(String args[]) throws Exception { + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( + "-XX:+UnlockDiagnosticVMOptions", + "-XX:+PrintNMTStatistics", + "-version"); + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + output.shouldContain("warning: PrintNMTStatistics is disabled, because native memory tracking is not enabled"); + output.shouldHaveExitValue(0); + } +} diff --git a/hotspot/test/runtime/NMT/ShutdownTwice.java b/hotspot/test/runtime/NMT/ShutdownTwice.java new file mode 100644 index 00000000000..1bb327aedb1 --- /dev/null +++ b/hotspot/test/runtime/NMT/ShutdownTwice.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2013, 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. + * + * 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. + */ + +/* + * @test + * @key nmt jcmd + * @summary Run shutdown twice + * @library /testlibrary + * @run main/othervm -XX:NativeMemoryTracking=detail ShutdownTwice + */ + +import com.oracle.java.testlibrary.*; + +public class ShutdownTwice { + + public static void main(String args[]) throws Exception { + // Grab my own PID + String pid = Integer.toString(ProcessTools.getProcessId()); + OutputAnalyzer output; + + ProcessBuilder pb = new ProcessBuilder(); + + // Run 'jcmd VM.native_memory shutdown' + pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "shutdown"}); + output = new OutputAnalyzer(pb.start()); + + // Verify that jcmd reports that NMT is shutting down + output.shouldContain("Shutdown is in progress, it will take a few moments to completely shutdown"); + + // Run shutdown again + output = new OutputAnalyzer(pb.start()); + + // Verify that jcmd reports that NMT has been shutdown already + output.shouldContain("Native memory tracking has been shutdown by user"); + } +} diff --git a/hotspot/test/runtime/NMT/SummaryAfterShutdown.java b/hotspot/test/runtime/NMT/SummaryAfterShutdown.java new file mode 100644 index 00000000000..96061f3f004 --- /dev/null +++ b/hotspot/test/runtime/NMT/SummaryAfterShutdown.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2013, 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. + * + * 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. + */ + +/* + * @test + * @key nmt jcmd + * @summary Verify that jcmd correctly reports that NMT is not enabled after a shutdown + * @library /testlibrary + * @run main/othervm -XX:NativeMemoryTracking=detail SummaryAfterShutdown + */ + +import com.oracle.java.testlibrary.*; + +public class SummaryAfterShutdown { + + public static void main(String args[]) throws Exception { + OutputAnalyzer output; + // Grab my own PID + String pid = Integer.toString(ProcessTools.getProcessId()); + ProcessBuilder pb = new ProcessBuilder(); + + // Run 'jcmd VM.native_memory shutdown' + pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "shutdown"}); + output = new OutputAnalyzer(pb.start()); + + // Verify that jcmd reports that NMT is shutting down + output.shouldContain("Shutdown is in progress, it will take a few moments to completely shutdown"); + + // Run 'jcmd VM.native_memory summary' + pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "summary"}); + output = new OutputAnalyzer(pb.start()); + + // Verify that jcmd reports that NMT has been shutdown + output.shouldContain("Native memory tracking has been shutdown by user"); + } +} diff --git a/hotspot/test/runtime/NMT/SummarySanityCheck.java b/hotspot/test/runtime/NMT/SummarySanityCheck.java new file mode 100644 index 00000000000..cf81d5b35af --- /dev/null +++ b/hotspot/test/runtime/NMT/SummarySanityCheck.java @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2013, 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. + * + * 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. + */ + +/* + * @test + * @key nmt jcmd + * @summary Sanity check the output of NMT + * @library /testlibrary + * @run compile -J-XX:+UnlockDiagnosticVMOptions -J-XX:+WhiteBoxAPI SummarySanityCheck.java + * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:NativeMemoryTracking=summary -XX:+WhiteBoxAPI SummarySanityCheck + */ + +import com.oracle.java.testlibrary.*; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import sun.hotspot.WhiteBox; + +public class SummarySanityCheck { + + private static String jcmdout; + public static void main(String args[]) throws Exception { + // Grab my own PID + String pid = Integer.toString(ProcessTools.getProcessId()); + + // Use WB API to ensure that all data has been merged before we continue + if (!WhiteBox.getWhiteBox().NMTWaitForDataMerge()) { + throw new Exception("Call to WB API NMTWaitForDataMerge() failed"); + } + + ProcessBuilder pb = new ProcessBuilder(); + + // Run 'jcmd VM.native_memory summary scale=KB' + pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "summary", "scale=KB"}); + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + + jcmdout = output.getOutput(); + // Split by '-' to get the 'groups' + String[] lines = jcmdout.split("\n"); + + if (lines.length == 0) { + throwTestException("Failed to parse jcmd output"); + } + + int totalCommitted = 0, totalReserved = 0; + int totalCommittedSum = 0, totalReservedSum = 0; + + // Match '- (reserved=KB, committed=KB) + Pattern mtTypePattern = Pattern.compile("-\\s+(?[\\w\\s]+)\\(reserved=(?\\d+)KB,\\scommitted=(?\\d+)KB\\)"); + // Match 'Total: reserved=KB, committed=KB' + Pattern totalMemoryPattern = Pattern.compile("Total\\:\\s\\sreserved=(?\\d+)KB,\\s\\scommitted=(?\\d+)KB"); + + for (int i = 0; i < lines.length; i++) { + if (lines[i].startsWith("Total")) { + Matcher totalMemoryMatcher = totalMemoryPattern.matcher(lines[i]); + + if (totalMemoryMatcher.matches() && totalMemoryMatcher.groupCount() == 2) { + totalCommitted = Integer.parseInt(totalMemoryMatcher.group("committed")); + totalReserved = Integer.parseInt(totalMemoryMatcher.group("reserved")); + } else { + throwTestException("Failed to match the expected groups in 'Total' memory part"); + } + } else if (lines[i].startsWith("-")) { + Matcher typeMatcher = mtTypePattern.matcher(lines[i]); + if (typeMatcher.matches()) { + int typeCommitted = Integer.parseInt(typeMatcher.group("committed")); + int typeReserved = Integer.parseInt(typeMatcher.group("reserved")); + + // Make sure reserved is always less or equals + if (typeCommitted > typeReserved) { + throwTestException("Committed (" + typeCommitted + ") was more than Reserved (" + + typeReserved + ") for mtType: " + typeMatcher.group("typename")); + } + + // Add to total and compare them in the end + totalCommittedSum += typeCommitted; + totalReservedSum += typeReserved; + } else { + throwTestException("Failed to match the group on line " + i); + } + } + } + + // See if they add up correctly, rounding is a problem so make sure we're within +/- 8KB + int committedDiff = totalCommitted - totalCommittedSum; + if (committedDiff > 8 || committedDiff < -8) { + throwTestException("Total committed (" + totalCommitted + ") did not match the summarized committed (" + totalCommittedSum + ")" ); + } + + int reservedDiff = totalReserved - totalReservedSum; + if (reservedDiff > 8 || reservedDiff < -8) { + throwTestException("Total reserved (" + totalReserved + ") did not match the summarized reserved (" + totalReservedSum + ")" ); + } + } + + private static void throwTestException(String reason) throws Exception { + throw new Exception(reason + " . Stdout is :\n" + jcmdout); + } +} From b61bb15030d4c205949f3663bc6d60e41bce3c6c Mon Sep 17 00:00:00 2001 From: Chris Hegarty Date: Sat, 2 Feb 2013 17:15:13 +0000 Subject: [PATCH 164/210] 8007322: untangle ftp protocol from general networking URL tests Reviewed-by: alanb --- jdk/test/java/net/URL/Constructor.java | 260 ++++++++++++++---- jdk/test/java/net/URL/HandlerLoop.java | 2 +- jdk/test/java/net/URL/Test.java | 19 +- jdk/test/java/net/URL/URIToURLTest.java | 31 ++- jdk/test/java/net/URL/abnormal_http_urls | 43 --- jdk/test/java/net/URL/ftp_urls | 27 -- jdk/test/java/net/URL/jar_urls | 75 ----- jdk/test/java/net/URL/normal_http_urls | 83 ------ jdk/test/java/net/URL/runconstructor.sh | 67 ----- jdk/test/java/net/URL/share_file_urls | 51 ---- jdk/test/java/net/URL/win32_file_urls | 15 - .../net/URLConnection/RequestProperties.java | 129 ++++----- .../URLConnection/RequestPropertyValues.java | 30 +- jdk/test/sun/net/{www => ftp}/EncDec.doc | Bin .../sun/net/{www => ftp}/MarkResetTest.java | 0 .../sun/net/{www => ftp}/MarkResetTest.sh | 0 .../net/www/http/HttpClient/ProxyTest.java | 12 +- 17 files changed, 327 insertions(+), 517 deletions(-) delete mode 100644 jdk/test/java/net/URL/abnormal_http_urls delete mode 100644 jdk/test/java/net/URL/ftp_urls delete mode 100644 jdk/test/java/net/URL/jar_urls delete mode 100644 jdk/test/java/net/URL/normal_http_urls delete mode 100644 jdk/test/java/net/URL/runconstructor.sh delete mode 100644 jdk/test/java/net/URL/share_file_urls delete mode 100644 jdk/test/java/net/URL/win32_file_urls rename jdk/test/sun/net/{www => ftp}/EncDec.doc (100%) rename jdk/test/sun/net/{www => ftp}/MarkResetTest.java (100%) rename jdk/test/sun/net/{www => ftp}/MarkResetTest.sh (100%) diff --git a/jdk/test/java/net/URL/Constructor.java b/jdk/test/java/net/URL/Constructor.java index 2930db2fa4c..13eae40d6d4 100644 --- a/jdk/test/java/net/URL/Constructor.java +++ b/jdk/test/java/net/URL/Constructor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2002, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2013, 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 @@ -21,71 +21,235 @@ * questions. */ -/* This is no longer run directly. See runconstructor.sh - * - * - * +/* + * @test + * @bug 4393671 + * @summary URL constructor URL(URL context, String spec) FAILED with specific input + */ + +/* * This program tests the URL parser in the URL constructor. It * tries to construct a variety of valid URLs with a given context * (which may be null) and a variety of specs. It then compares the * result with an expected value. - * - * It expects that a data file named "urls" be available in the - * current directory, from which it will get its testing data. The - * format of the file is: - * - * URL: null - * spec: jar:http://www.foo.com/dir1/jar.jar!/ - * expected: jar:http://www.foo.com/dir1/jar.jar!/ - * - * where URL is the context, spec is the spec and expected is the - * expected result. The first : must be followed by a space. Each test - * entry should be followed by a blank line. */ -import java.io.*; +import java.net.MalformedURLException; import java.net.URL; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; public class Constructor { public static void main(String[] args) throws Exception { - URL url = null; - String urls = "jar_urls"; - if (args.length > 0 && args[0] != null) { - urls = args[0]; - } + List entries = new ArrayList<>(); + entries.addAll(Arrays.asList(fileURLs)); + entries.addAll(Arrays.asList(jarURLs)); + entries.addAll(Arrays.asList(normalHttpURLs)); + entries.addAll(Arrays.asList(abnormalHttpURLs)); + if (hasFtp()) + entries.addAll(Arrays.asList(ftpURLs)); + URL url; - File f = new File(urls); - InputStream file = new FileInputStream(f); - BufferedReader in = new BufferedReader(new InputStreamReader(file)); - while(true) { - String context = in.readLine(); - if (context == null) { - break; - } - context = getValue(context); - String spec = getValue(in.readLine()); - String expected = getValue(in.readLine()); + for (Entry e : entries) { + if (e.context == null) + url = new URL(e.spec); + else + url = new URL(new URL(e.context), e.spec); - if (context.equals("null")) { - url = new URL(spec); - } else { - url = new URL(new URL(context), spec); - } - if (!(url.toString().equals(expected))) { - throw new RuntimeException("error for: \n\tURL:" + context + - "\n\tspec: " + spec + - "\n\texpected: " + expected + + if (!(url.toString().equals(e.expected))) { + throw new RuntimeException("error for: \n\tURL:" + e.context + + "\n\tspec: " + e.spec + + "\n\texpected: " + e.expected + "\n\tactual: " + url.toString()); } else { - System.out.println("success for: " + url + "\n"); + //debug + //System.out.println("success for: " + url); } - in.readLine(); } - in.close(); } - private static String getValue(String value) { - return value.substring(value.indexOf(':') + 2); + private static boolean hasFtp() { + try { + return new java.net.URL("ftp://") != null; + } catch (java.net.MalformedURLException x) { + System.out.println("FTP not supported by this runtime."); + return false; + } } + + static class Entry { + final String context; + final String spec; + final String expected; + Entry(String context, String spec, String expected) { + this.context = context; + this.spec =spec; + this.expected = expected; + } + } + + static Entry[] fileURLs = new Entry[] { + new Entry(null, + "file://JavaSoft/Test", + "file://JavaSoft/Test"), + new Entry(null, + "file:///JavaSoft/Test", + "file:/JavaSoft/Test"), + new Entry(null, + "file:/JavaSoft/Test", + "file:/JavaSoft/Test"), + new Entry(null, + "file:/c:/JavaSoft/Test", + "file:/c:/JavaSoft/Test"), + new Entry(null, + "file:/c:/JavaSoft/Test:something", + "file:/c:/JavaSoft/Test:something"), + new Entry(null, + "file:/c:/JavaSoft/Test#anchor", + "file:/c:/JavaSoft/Test#anchor"), + new Entry("file://JavaSoft/Test", + "Test#bar", + "file://JavaSoft/Test#bar"), + new Entry("file://codrus/c:/jdk/eng/index.html", + "pulsar.html", + "file://codrus/c:/jdk/eng/pulsar.html"), + new Entry("file:///c:/jdk/eng/index.html", + "pulsar.html", + "file:/c:/jdk/eng/pulsar.html"), + new Entry("file:///jdk/eng/index.html", + "pulsar.html", + "file:/jdk/eng/pulsar.html"), + new Entry("file://JavaSoft/Test", + "file://radartoad.com/Test#bar", + "file://radartoad.com/Test#bar"), + new Entry("file://JavaSoft/Test", + "/c:/Test#bar", + "file://JavaSoft/c:/Test#bar"), + }; + + static Entry[] jarURLs = new Entry[] { + new Entry(null, + "jar:http://www.foo.com/dir1/jar.jar!/dir2/entry.txt", + "jar:http://www.foo.com/dir1/jar.jar!/dir2/entry.txt"), + new Entry(null, + "jar:http://www.foo.com/dir1/jar.jar!/", + "jar:http://www.foo.com/dir1/jar.jar!/"), + new Entry(null, + "jar:http://www.foo.com/dir1/jar.jar!/", + "jar:http://www.foo.com/dir1/jar.jar!/"), + new Entry("jar:http://www.foo.com/dir1/jar.jar!/", + "entry.txt", + "jar:http://www.foo.com/dir1/jar.jar!/entry.txt"), + new Entry("jar:http://www.foo.com/dir1/jar.jar!/", + "/entry.txt", + "jar:http://www.foo.com/dir1/jar.jar!/entry.txt"), + new Entry("jar:http://www.foo.com/dir1/jar.jar!/", + "dir1/entry.txt", + "jar:http://www.foo.com/dir1/jar.jar!/dir1/entry.txt"), + new Entry("jar:http://www.foo.com/dir1/jar.jar!/", + "/dir1/entry.txt", + "jar:http://www.foo.com/dir1/jar.jar!/dir1/entry.txt"), + new Entry("jar:http://www.foo.com/dir1/jar.jar!/", + "entry.txt", + "jar:http://www.foo.com/dir1/jar.jar!/entry.txt"), + new Entry("jar:http://www.foo.com/dir1/jar.jar!/", + "/entry.txt", + "jar:http://www.foo.com/dir1/jar.jar!/entry.txt"), + new Entry("jar:http://www.foo.com/dir1/jar.jar!/", + "/entry.txt", + "jar:http://www.foo.com/dir1/jar.jar!/entry.txt"), + new Entry("jar:http://www.foo.com/dir1/jar.jar!/dir1/", + "entry.txt", + "jar:http://www.foo.com/dir1/jar.jar!/dir1/entry.txt"), + new Entry("jar:http://www.foo.com/dir1/jar.jar!/dir2/dir3/entry2.txt", + "/dir1/entry.txt", + "jar:http://www.foo.com/dir1/jar.jar!/dir1/entry.txt"), + new Entry("jar:http://www.foo.com/dir1/jar.jar!/", + "/dir1/foo/entry.txt", + "jar:http://www.foo.com/dir1/jar.jar!/dir1/foo/entry.txt"), + new Entry("jar:http://www.foo.com/dir1/jar.jar!/dir1/dir2/dir3/", + "dir4/foo/entry.txt", + "jar:http://www.foo.com/dir1/jar.jar!/dir1/dir2/dir3/dir4/foo/entry.txt"), + new Entry("jar:http://www.foo.com/dir1/jar.jar!/", + "/dir1/foo/entry.txt", + "jar:http://www.foo.com/dir1/jar.jar!/dir1/foo/entry.txt"), + new Entry(null, + "jar:http://www.foo.com/dir1/jar.jar!/foo.txt#anchor", + "jar:http://www.foo.com/dir1/jar.jar!/foo.txt#anchor"), + new Entry("jar:http://www.foo.com/dir1/jar.jar!/foo.txt", + "#anchor", + "jar:http://www.foo.com/dir1/jar.jar!/foo.txt#anchor"), + new Entry("jar:http://www.foo.com/dir1/jar.jar!/foo/bar/", + "baz/quux#anchor", + "jar:http://www.foo.com/dir1/jar.jar!/foo/bar/baz/quux#anchor"), + new Entry("jar:http://balloo.com/olle.jar!/", + "p2", + "jar:http://balloo.com/olle.jar!/p2") + }; + + static Entry[] normalHttpURLs = new Entry[] { + new Entry("http://a/b/c/d;p?q", "g", "http://a/b/c/g"), + new Entry("http://a/b/c/d;p?q", "./g", "http://a/b/c/g"), + new Entry("http://a/b/c/d;p?q", "g/", "http://a/b/c/g/"), + new Entry("http://a/b/c/d;p?q", "/g", "http://a/g"), + new Entry("http://a/b/c/d;p?q", "//g", "http://g"), + new Entry("http://a/b/c/d;p?q", "?y", "http://a/b/c/?y"), + new Entry("http://a/b/c/d;p?q", "g?y", "http://a/b/c/g?y"), + new Entry("http://a/b/c/d;p?q", "g#s", "http://a/b/c/g#s"), + new Entry("http://a/b/c/d;p?q", "g?y#s", "http://a/b/c/g?y#s"), + new Entry("http://a/b/c/d;p?q", ";x", "http://a/b/c/;x"), + new Entry("http://a/b/c/d;p?q", "g;x", "http://a/b/c/g;x"), + new Entry("http://a/b/c/d;p?q", "g;x?y#s", "http://a/b/c/g;x?y#s"), + new Entry("http://a/b/c/d;p?q", ".", "http://a/b/c/"), + new Entry("http://a/b/c/d;p?q", "./", "http://a/b/c/"), + new Entry("http://a/b/c/d;p?q", "..", "http://a/b/"), + new Entry("http://a/b/c/d;p?q", "../", "http://a/b/"), + new Entry("http://a/b/c/d;p?q", "../g", "http://a/b/g"), + new Entry("http://a/b/c/d;p?q", "../..", "http://a/"), + new Entry("http://a/b/c/d;p?q", "../../", "http://a/"), + new Entry("http://a/b/c/d;p?q", "../../g", "http://a/g"), + new Entry(null, + "http://www.javasoft.com/jdc/community/chat/index.html#javalive?frontpage-jdc", + "http://www.javasoft.com/jdc/community/chat/index.html#javalive?frontpage-jdc") + }; + + static Entry[] abnormalHttpURLs = new Entry[] { + new Entry("http://a/b/c/d;p?q", "../../../g", "http://a/../g"), + new Entry("http://a/b/c/d;p?q", "../../../../g", "http://a/../../g"), + new Entry("http://a/b/c/d;p?q", "/./g", "http://a/./g"), + new Entry("http://a/b/c/d;p?q", "/../g", "http://a/../g"), + new Entry("http://a/b/c/d;p?q", ".g", "http://a/b/c/.g"), + new Entry("http://a/b/c/d;p?q", "g.", "http://a/b/c/g."), + new Entry("http://a/b/c/d;p?q", "./../g", "http://a/b/g"), + new Entry("http://a/b/c/d;p?q", "./g/.", "http://a/b/c/g/"), + new Entry("http://a/b/c/d;p?q", "g/./h", "http://a/b/c/g/h"), + new Entry("http://a/b/c/d;p?q", "g;x=1/./y", "http://a/b/c/g;x=1/y"), + new Entry("http://a/b/c/d;p?q", "g;x=1/../y", "http://a/b/c/y") + }; + + static Entry[] ftpURLs = new Entry[] { + new Entry(null, + "ftp://ftp.foo.com/dir1/entry.txt", + "ftp://ftp.foo.com/dir1/entry.txt"), + new Entry(null, + "ftp://br:pwd@ftp.foo.com/dir1/jar.jar", + "ftp://br:pwd@ftp.foo.com/dir1/jar.jar"), + new Entry("ftp://ftp.foo.com/dir1/foo.txt", + "bar.txt", + "ftp://ftp.foo.com/dir1/bar.txt"), + new Entry("ftp://ftp.foo.com/dir1/jar.jar", + "/entry.txt", + "ftp://ftp.foo.com/entry.txt"), + new Entry("ftp://ftp.foo.com/dir1/jar.jar", + "dir1/entry.txt", + "ftp://ftp.foo.com/dir1/dir1/entry.txt"), + new Entry("ftp://ftp.foo.com/dir1/jar.jar", + "/dir1/entry.txt", + "ftp://ftp.foo.com/dir1/entry.txt"), + new Entry("ftp://br:pwd@ftp.foo.com/dir1/jar.jar", + "/dir1/entry.txt", + "ftp://br:pwd@ftp.foo.com/dir1/entry.txt") + }; } diff --git a/jdk/test/java/net/URL/HandlerLoop.java b/jdk/test/java/net/URL/HandlerLoop.java index 69ca4e523b5..df02891b038 100644 --- a/jdk/test/java/net/URL/HandlerLoop.java +++ b/jdk/test/java/net/URL/HandlerLoop.java @@ -36,7 +36,7 @@ public class HandlerLoop { public static void main(String args[]) throws Exception { URL.setURLStreamHandlerFactory( new HandlerFactory("sun.net.www.protocol")); - URL url = new URL("file://bogus/index.html"); + URL url = new URL("file:///bogus/index.html"); System.out.println("url = " + url); url.openConnection(); } diff --git a/jdk/test/java/net/URL/Test.java b/jdk/test/java/net/URL/Test.java index 4ea4bd7c634..1e44ffe8b03 100644 --- a/jdk/test/java/net/URL/Test.java +++ b/jdk/test/java/net/URL/Test.java @@ -310,7 +310,14 @@ public class Test { throw new RuntimeException("Test failed"); } - + private static boolean hasFtp() { + try { + return new java.net.URL("ftp://") != null; + } catch (java.net.MalformedURLException x) { + System.out.println("FTP not supported by this runtime."); + return false; + } + } // -- Tests -- @@ -319,8 +326,9 @@ public class Test { header("RFC2396: Basic examples"); - test("ftp://ftp.is.co.za/rfc/rfc1808.txt") - .s("ftp").h("ftp.is.co.za").p("/rfc/rfc1808.txt").z(); + if (hasFtp()) + test("ftp://ftp.is.co.za/rfc/rfc1808.txt") + .s("ftp").h("ftp.is.co.za").p("/rfc/rfc1808.txt").z(); test("http://www.math.uio.no/faq/compression-faq/part1.html") .s("http").h("www.math.uio.no").p("/faq/compression-faq/part1.html").z(); @@ -328,8 +336,9 @@ public class Test { test("http://www.w3.org/Addressing/") .s("http").h("www.w3.org").p("/Addressing/").z(); - test("ftp://ds.internic.net/rfc/") - .s("ftp").h("ds.internic.net").p("/rfc/").z(); + if (hasFtp()) + test("ftp://ds.internic.net/rfc/") + .s("ftp").h("ds.internic.net").p("/rfc/").z(); test("http://www.ics.uci.edu/pub/ietf/url/historical.html#WARNING") .s("http").h("www.ics.uci.edu").p("/pub/ietf/url/historical.html") diff --git a/jdk/test/java/net/URL/URIToURLTest.java b/jdk/test/java/net/URL/URIToURLTest.java index 8ae07b36b12..79273b246c5 100644 --- a/jdk/test/java/net/URL/URIToURLTest.java +++ b/jdk/test/java/net/URL/URIToURLTest.java @@ -28,20 +28,22 @@ */ import java.net.*; +import java.util.ArrayList; +import java.util.List; public class URIToURLTest { public static void main(String args[]) throws Exception { - String[] uris = { - "http://jag:cafebabe@java.sun.com:94/b/c/d?q#g", - "http://[1080:0:0:0:8:800:200C:417A]/index.html", - "http://a/b/c/d;p?q", - "ftp://ftp.is.co.za/rfc/rfc1808.txt", - "mailto:mduerst@ifi.unizh.ch", // opaque url - "http:comp.infosystems.www.servers.unix" //opaque url - }; + List uris = new ArrayList<>(); + uris.add("http://jag:cafebabe@java.sun.com:94/b/c/d?q#g"); + uris.add("http://[1080:0:0:0:8:800:200C:417A]/index.html"); + uris.add("http://a/b/c/d;p?q"); + uris.add("mailto:mduerst@ifi.unizh.ch"); + uris.add("http:comp.infosystems.www.servers.unix"); + if (hasFtp()) + uris.add("ftp://ftp.is.co.za/rfc/rfc1808.txt"); - for (int i = 0; i < uris.length; i++) { - URI uri = new URI(uris[i]); + for (String uriStr : uris) { + URI uri = new URI(uriStr); URL url = uri.toURL(); String scheme = uri.getScheme(); boolean schemeCheck = scheme == null? url.getProtocol() == null : @@ -111,4 +113,13 @@ public class URIToURLTest { url.getRef()); } } + + private static boolean hasFtp() { + try { + return new java.net.URL("ftp://") != null; + } catch (java.net.MalformedURLException x) { + System.out.println("FTP not supported by this runtime."); + return false; + } + } } diff --git a/jdk/test/java/net/URL/abnormal_http_urls b/jdk/test/java/net/URL/abnormal_http_urls deleted file mode 100644 index 1fbf57d37a5..00000000000 --- a/jdk/test/java/net/URL/abnormal_http_urls +++ /dev/null @@ -1,43 +0,0 @@ -URL: http://a/b/c/d;p?q -spec: ../../../g -expected: http://a/../g - -URL: http://a/b/c/d;p?q -spec: ../../../../g -expected: http://a/../../g - -URL: http://a/b/c/d;p?q -spec: /./g -expected: http://a/./g - -URL: http://a/b/c/d;p?q -spec: /../g -expected: http://a/../g - -URL: http://a/b/c/d;p?q -spec: .g -expected: http://a/b/c/.g - -URL: http://a/b/c/d;p?q -spec: g. -expected: http://a/b/c/g. - -URL: http://a/b/c/d;p?q -spec: ./../g -expected: http://a/b/g - -URL: http://a/b/c/d;p?q -spec: ./g/. -expected: http://a/b/c/g/ - -URL: http://a/b/c/d;p?q -spec: g/./h -expected: http://a/b/c/g/h - -URL: http://a/b/c/d;p?q -spec: g;x=1/./y -expected: http://a/b/c/g;x=1/y - -URL: http://a/b/c/d;p?q -spec: g;x=1/../y -expected: http://a/b/c/y diff --git a/jdk/test/java/net/URL/ftp_urls b/jdk/test/java/net/URL/ftp_urls deleted file mode 100644 index 1f8d6fc6fa6..00000000000 --- a/jdk/test/java/net/URL/ftp_urls +++ /dev/null @@ -1,27 +0,0 @@ -URL: null -spec: ftp://ftp.foo.com/dir1/entry.txt -expected: ftp://ftp.foo.com/dir1/entry.txt - -URL: null -spec: ftp://br:pwd@ftp.foo.com/dir1/jar.jar -expected: ftp://br:pwd@ftp.foo.com/dir1/jar.jar - -URL: ftp://ftp.foo.com/dir1/foo.txt -spec: bar.txt -expected: ftp://ftp.foo.com/dir1/bar.txt - -URL: ftp://ftp.foo.com/dir1/jar.jar -spec: /entry.txt -expected: ftp://ftp.foo.com/entry.txt - -URL: ftp://ftp.foo.com/dir1/jar.jar -spec: dir1/entry.txt -expected: ftp://ftp.foo.com/dir1/dir1/entry.txt - -URL: ftp://ftp.foo.com/dir1/jar.jar -spec: /dir1/entry.txt -expected: ftp://ftp.foo.com/dir1/entry.txt - -URL: ftp://br:pwd@ftp.foo.com/dir1/jar.jar -spec: /dir1/entry.txt -expected: ftp://br:pwd@ftp.foo.com/dir1/entry.txt diff --git a/jdk/test/java/net/URL/jar_urls b/jdk/test/java/net/URL/jar_urls deleted file mode 100644 index ebd888450fa..00000000000 --- a/jdk/test/java/net/URL/jar_urls +++ /dev/null @@ -1,75 +0,0 @@ -URL: null -spec: jar:http://www.foo.com/dir1/jar.jar!/dir2/entry.txt -expected: jar:http://www.foo.com/dir1/jar.jar!/dir2/entry.txt - -URL: null -spec: jar:http://www.foo.com/dir1/jar.jar!/ -expected: jar:http://www.foo.com/dir1/jar.jar!/ - -URL: null -spec: jar:http://www.foo.com/dir1/jar.jar!/ -expected: jar:http://www.foo.com/dir1/jar.jar!/ - -URL: jar:http://www.foo.com/dir1/jar.jar!/ -spec: entry.txt -expected: jar:http://www.foo.com/dir1/jar.jar!/entry.txt - -URL: jar:http://www.foo.com/dir1/jar.jar!/ -spec: /entry.txt -expected: jar:http://www.foo.com/dir1/jar.jar!/entry.txt - -URL: jar:http://www.foo.com/dir1/jar.jar!/ -spec: dir1/entry.txt -expected: jar:http://www.foo.com/dir1/jar.jar!/dir1/entry.txt - -URL: jar:http://www.foo.com/dir1/jar.jar!/ -spec: /dir1/entry.txt -expected: jar:http://www.foo.com/dir1/jar.jar!/dir1/entry.txt - -URL: jar:http://www.foo.com/dir1/jar.jar!/ -spec: entry.txt -expected: jar:http://www.foo.com/dir1/jar.jar!/entry.txt - -URL: jar:http://www.foo.com/dir1/jar.jar!/ -spec: /entry.txt -expected: jar:http://www.foo.com/dir1/jar.jar!/entry.txt - -URL: jar:http://www.foo.com/dir1/jar.jar!/ -spec: /entry.txt -expected: jar:http://www.foo.com/dir1/jar.jar!/entry.txt - -URL: jar:http://www.foo.com/dir1/jar.jar!/dir1/ -spec: entry.txt -expected: jar:http://www.foo.com/dir1/jar.jar!/dir1/entry.txt - -URL: jar:http://www.foo.com/dir1/jar.jar!/dir2/dir3/entry2.txt -spec: /dir1/entry.txt -expected: jar:http://www.foo.com/dir1/jar.jar!/dir1/entry.txt - -URL: jar:http://www.foo.com/dir1/jar.jar!/ -spec: /dir1/foo/entry.txt -expected: jar:http://www.foo.com/dir1/jar.jar!/dir1/foo/entry.txt - -URL: jar:http://www.foo.com/dir1/jar.jar!/dir1/dir2/dir3/ -spec: dir4/foo/entry.txt -expected: jar:http://www.foo.com/dir1/jar.jar!/dir1/dir2/dir3/dir4/foo/entry.txt - -URL: jar:http://www.foo.com/dir1/jar.jar!/ -spec: /dir1/foo/entry.txt -expected: jar:http://www.foo.com/dir1/jar.jar!/dir1/foo/entry.txt - -URL: null -spec: jar:http://www.foo.com/dir1/jar.jar!/foo.txt#anchor -expected: jar:http://www.foo.com/dir1/jar.jar!/foo.txt#anchor - -URL: jar:http://www.foo.com/dir1/jar.jar!/foo.txt -spec: #anchor -expected: jar:http://www.foo.com/dir1/jar.jar!/foo.txt#anchor - -URL: jar:http://www.foo.com/dir1/jar.jar!/foo/bar/ -spec: baz/quux#anchor -expected: jar:http://www.foo.com/dir1/jar.jar!/foo/bar/baz/quux#anchor - -URL: jar:http://balloo.com/olle.jar!/ -spec: p2 -expected: jar:http://balloo.com/olle.jar!/p2 diff --git a/jdk/test/java/net/URL/normal_http_urls b/jdk/test/java/net/URL/normal_http_urls deleted file mode 100644 index 52d332057dd..00000000000 --- a/jdk/test/java/net/URL/normal_http_urls +++ /dev/null @@ -1,83 +0,0 @@ -URL: http://a/b/c/d;p?q -spec: g -expected: http://a/b/c/g - -URL: http://a/b/c/d;p?q -spec: ./g -expected: http://a/b/c/g - -URL: http://a/b/c/d;p?q -spec: g/ -expected: http://a/b/c/g/ - -URL: http://a/b/c/d;p?q -spec: /g -expected: http://a/g - -URL: http://a/b/c/d;p?q -spec: //g -expected: http://g - -URL: http://a/b/c/d;p?q -spec: ?y -expected: http://a/b/c/?y - -URL: http://a/b/c/d;p?q -spec: g?y -expected: http://a/b/c/g?y - -URL: http://a/b/c/d;p?q -spec: g#s -expected: http://a/b/c/g#s - -URL: http://a/b/c/d;p?q -spec: g?y#s -expected: http://a/b/c/g?y#s - -URL: http://a/b/c/d;p?q -spec: ;x -expected: http://a/b/c/;x - -URL: http://a/b/c/d;p?q -spec: g;x -expected: http://a/b/c/g;x - -URL: http://a/b/c/d;p?q -spec: g;x?y#s -expected: http://a/b/c/g;x?y#s - -URL: http://a/b/c/d;p?q -spec: . -expected: http://a/b/c/ - -URL: http://a/b/c/d;p?q -spec: ./ -expected: http://a/b/c/ - -URL: http://a/b/c/d;p?q -spec: .. -expected: http://a/b/ - -URL: http://a/b/c/d;p?q -spec: ../ -expected: http://a/b/ - -URL: http://a/b/c/d;p?q -spec: ../g -expected: http://a/b/g - -URL: http://a/b/c/d;p?q -spec: ../.. -expected: http://a/ - -URL: http://a/b/c/d;p?q -spec: ../../ -expected: http://a/ - -URL: http://a/b/c/d;p?q -spec: ../../g -expected: http://a/g - -URL: null -spec: http://www.javasoft.com/jdc/community/chat/index.html#javalive?frontpage-jdc -expected: http://www.javasoft.com/jdc/community/chat/index.html#javalive?frontpage-jdc diff --git a/jdk/test/java/net/URL/runconstructor.sh b/jdk/test/java/net/URL/runconstructor.sh deleted file mode 100644 index f64fd8509d1..00000000000 --- a/jdk/test/java/net/URL/runconstructor.sh +++ /dev/null @@ -1,67 +0,0 @@ -# -# Copyright (c) 2000, 2012, 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. -# -# 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. -# - -# @test -# @bug 4393671 -# @summary URL constructor URL(URL context, String spec) FAILED with specific input in merlin -# -OS=`uname -s` -case "$OS" in - SunOS | Linux | Darwin ) - PS=":" - FS="/" - ;; - CYGWIN* ) - PS=";" - FS="/" - ;; - Windows* ) - PS=";" - FS="\\" - ;; - * ) - echo "Unrecognized system!" - exit 1; - ;; -esac -${COMPILEJAVA}${FS}bin${FS}javac ${TESTJAVACOPTS} ${TESTTOOLVMOPTS} -d . \ - ${TESTSRC}${FS}Constructor.java - -failures=0 - -go() { - echo '' - ${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} Constructor $1 - if [ $? != 0 ]; then failures=`expr $failures + 1`; fi -} - -go ${TESTSRC}${FS}share_file_urls -go ${TESTSRC}${FS}jar_urls -go ${TESTSRC}${FS}normal_http_urls -go ${TESTSRC}${FS}ftp_urls -go ${TESTSRC}${FS}abnormal_http_urls - -if [ "$failures" != "0" ]; then - echo $failures tests failed - exit 1; -fi diff --git a/jdk/test/java/net/URL/share_file_urls b/jdk/test/java/net/URL/share_file_urls deleted file mode 100644 index 48451b45db4..00000000000 --- a/jdk/test/java/net/URL/share_file_urls +++ /dev/null @@ -1,51 +0,0 @@ -URL: null -spec: file://JavaSoft/Test -expected: file://JavaSoft/Test - -URL: null -spec: file:///JavaSoft/Test -expected: file:/JavaSoft/Test - -URL: null -spec: file:/JavaSoft/Test -expected: file:/JavaSoft/Test - -URL: null -spec: file:/c:/JavaSoft/Test -expected: file:/c:/JavaSoft/Test - -URL: null -spec: file:/c:/JavaSoft/Test:something -expected: file:/c:/JavaSoft/Test:something - -URL: null -spec: file:/c:/JavaSoft/Test#anchor -expected: file:/c:/JavaSoft/Test#anchor - -URL: null -spec: file:/JavaSoft/Test -expected: file:/JavaSoft/Test - -URL: file://JavaSoft/Test -spec: Test#bar -expected: file://JavaSoft/Test#bar - -URL: file://codrus/c:/jdk/eng/index.html -spec: pulsar.html -expected: file://codrus/c:/jdk/eng/pulsar.html - -URL: file:///c:/jdk/eng/index.html -spec: pulsar.html -expected: file:/c:/jdk/eng/pulsar.html - -URL: file:///jdk/eng/index.html -spec: pulsar.html -expected: file:/jdk/eng/pulsar.html - -URL: file://JavaSoft/Test -spec: file://radartoad.com/Test#bar -expected: file://radartoad.com/Test#bar - -URL: file://JavaSoft/Test -spec: /c:/Test#bar -expected: file://JavaSoft/c:/Test#bar \ No newline at end of file diff --git a/jdk/test/java/net/URL/win32_file_urls b/jdk/test/java/net/URL/win32_file_urls deleted file mode 100644 index 7e3981c1490..00000000000 --- a/jdk/test/java/net/URL/win32_file_urls +++ /dev/null @@ -1,15 +0,0 @@ -URL: null -spec: file://c:\JavaSoft\Test -expected: file://c:/JavaSoft/Test - -URL: null -spec: file:/c:\JavaSoft\Test -expected: file:/c:/JavaSoft/Test - -URL: null -spec: file:/c:\JavaSoft\Test:something#anchor -expected: file:/c:/JavaSoft/Test:something#anchor - -URL: file:///c:\jdk\eng\index.html -spec: pulsar.html -expected: file:/c:/jdk/eng/pulsar.html \ No newline at end of file diff --git a/jdk/test/java/net/URLConnection/RequestProperties.java b/jdk/test/java/net/URLConnection/RequestProperties.java index 74fd558ddbe..af549e22e54 100644 --- a/jdk/test/java/net/URLConnection/RequestProperties.java +++ b/jdk/test/java/net/URLConnection/RequestProperties.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2013 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 @@ -28,90 +28,55 @@ */ import java.net.*; +import java.util.ArrayList; +import java.util.List; public class RequestProperties { - public static void main (String args[]) throws Exception { - URL url0 = new URL ("http://foo.com/bar/"); - URL url1 = new URL ("file:/etc/passwd"); - URL url2 = new URL ("ftp://foo:bar@foobar.com/etc/passwd"); - URL url3 = new URL ("jar:http://foo.com/bar.html!/foo/bar"); - URLConnection urlc0 = url0.openConnection (); - URLConnection urlc1 = url1.openConnection (); - URLConnection urlc2 = url2.openConnection (); - URLConnection urlc3 = url3.openConnection (); - int count = 0; - String s = null; - try { - urlc0.setRequestProperty (null, null); - System.out.println ("http: setRequestProperty (null,) did not throw NPE"); - } catch (NullPointerException e) { - count ++; - } - try { - urlc0.addRequestProperty (null, null); - System.out.println ("http: addRequestProperty (null,) did not throw NPE"); - } catch (NullPointerException e) { - count ++; - } - try { - urlc1.setRequestProperty (null, null); - System.out.println ("file: setRequestProperty (null,) did not throw NPE"); - } catch (NullPointerException e) { - count ++; - } - try { - urlc1.addRequestProperty (null, null); - System.out.println ("file: addRequestProperty (null,) did not throw NPE"); - } catch (NullPointerException e) { - count ++; - } - try { - urlc2.setRequestProperty (null, null); - System.out.println ("ftp: setRequestProperty (null,) did not throw NPE"); - } catch (NullPointerException e) { - count ++; - } - try { - urlc2.addRequestProperty (null, null); - System.out.println ("ftp: addRequestProperty (null,) did not throw NPE"); - } catch (NullPointerException e) { - count ++; - } - try { - urlc3.setRequestProperty (null, null); - System.out.println ("jar: setRequestProperty (null,) did not throw NPE"); - } catch (NullPointerException e) { - count ++; - } - try { - urlc3.addRequestProperty (null, null); - System.out.println ("jar: addRequestProperty (null,) did not throw NPE"); - } catch (NullPointerException e) { - count ++; - } - if (urlc0.getRequestProperty (null) != null) { - System.out.println ("http: getRequestProperty (null,) did not return null"); - } else { - count ++; - } - if (urlc1.getRequestProperty (null) != null) { - System.out.println ("file: getRequestProperty (null,) did not return null"); - } else { - count ++; - } - if (urlc2.getRequestProperty (null) != null) { - System.out.println ("ftp: getRequestProperty (null,) did not return null"); - } else { - count ++; - } - if (urlc2.getRequestProperty (null) != null) { - System.out.println ("jar: getRequestProperty (null,) did not return null"); - } else { - count ++; - } + static int failed; - if (count != 12) { - throw new RuntimeException ((12 -count) + " errors") ; + public static void main (String args[]) throws Exception { + List urls = new ArrayList<>(); + urls.add("http://foo.com/bar/"); + urls.add("jar:http://foo.com/bar.html!/foo/bar"); + urls.add("file:/etc/passwd"); + if (hasFtp()) + urls.add("ftp://foo:bar@foobar.com/etc/passwd"); + + for (String urlStr : urls) + test(new URL(urlStr)); + + if (failed != 0) + throw new RuntimeException(failed + " errors") ; + } + + static void test(URL url) throws Exception { + URLConnection urlc = url.openConnection(); + try { + urlc.setRequestProperty(null, null); + System.out.println(url.getProtocol() + + ": setRequestProperty(null,) did not throw NPE"); + failed++; + } catch (NullPointerException e) { /* Expected */ } + try { + urlc.addRequestProperty(null, null); + System.out.println(url.getProtocol() + + ": addRequestProperty(null,) did not throw NPE"); + failed++; + } catch (NullPointerException e) { /* Expected */ } + + if (urlc.getRequestProperty(null) != null) { + System.out.println(url.getProtocol() + + ": getRequestProperty(null,) did not return null"); + failed++; + } + } + + private static boolean hasFtp() { + try { + return new java.net.URL("ftp://") != null; + } catch (java.net.MalformedURLException x) { + System.out.println("FTP not supported by this runtime."); + return false; } } } diff --git a/jdk/test/java/net/URLConnection/RequestPropertyValues.java b/jdk/test/java/net/URLConnection/RequestPropertyValues.java index 77bb469e672..6874063ca1d 100644 --- a/jdk/test/java/net/URLConnection/RequestPropertyValues.java +++ b/jdk/test/java/net/URLConnection/RequestPropertyValues.java @@ -27,8 +27,11 @@ * @summary Test URLConnection Request Proterties */ +import java.net.MalformedURLException; import java.net.URL; import java.net.URLConnection; +import java.util.ArrayList; +import java.util.List; /** * Part1: @@ -45,28 +48,29 @@ public class RequestPropertyValues { } public static void part1() throws Exception { - URL[] urls = { new URL("http://localhost:8088"), - new URL("file:/etc/passwd"), - new URL("ftp://foo:bar@foobar.com/etc/passwd"), - new URL("jar:http://foo.com/bar.html!/foo/bar") - }; + List urls = new ArrayList<>(); + urls.add(new URL("http://localhost:8088")); + urls.add(new URL("file:/etc/passwd")); + urls.add(new URL("jar:http://foo.com/bar.html!/foo/bar")); + if (hasFtp()) + urls.add(new URL("ftp://foo:bar@foobar.com/etc/passwd")); boolean failed = false; - for (int proto = 0; proto < urls.length; proto++) { - URLConnection uc = (URLConnection) urls[proto].openConnection(); + for (URL url : urls) { + URLConnection uc = url.openConnection(); try { uc.setRequestProperty("TestHeader", null); } catch (NullPointerException npe) { System.out.println("setRequestProperty is throwing NPE" + - " for url: " + urls[proto]); + " for url: " + url); failed = true; } try { uc.addRequestProperty("TestHeader", null); } catch (NullPointerException npe) { System.out.println("addRequestProperty is throwing NPE" + - " for url: " + urls[proto]); + " for url: " + url); failed = true; } } @@ -110,4 +114,12 @@ public class RequestPropertyValues { } } + private static boolean hasFtp() { + try { + return new java.net.URL("ftp://") != null; + } catch (java.net.MalformedURLException x) { + System.out.println("FTP not supported by this runtime."); + return false; + } + } } diff --git a/jdk/test/sun/net/www/EncDec.doc b/jdk/test/sun/net/ftp/EncDec.doc similarity index 100% rename from jdk/test/sun/net/www/EncDec.doc rename to jdk/test/sun/net/ftp/EncDec.doc diff --git a/jdk/test/sun/net/www/MarkResetTest.java b/jdk/test/sun/net/ftp/MarkResetTest.java similarity index 100% rename from jdk/test/sun/net/www/MarkResetTest.java rename to jdk/test/sun/net/ftp/MarkResetTest.java diff --git a/jdk/test/sun/net/www/MarkResetTest.sh b/jdk/test/sun/net/ftp/MarkResetTest.sh similarity index 100% rename from jdk/test/sun/net/www/MarkResetTest.sh rename to jdk/test/sun/net/ftp/MarkResetTest.sh diff --git a/jdk/test/sun/net/www/http/HttpClient/ProxyTest.java b/jdk/test/sun/net/www/http/HttpClient/ProxyTest.java index 18c2e1f0840..5d13a58d8cb 100644 --- a/jdk/test/sun/net/www/http/HttpClient/ProxyTest.java +++ b/jdk/test/sun/net/www/http/HttpClient/ProxyTest.java @@ -161,8 +161,18 @@ public class ProxyTest { } } + private static boolean hasFtp() { + try { + return new java.net.URL("ftp://") != null; + } catch (java.net.MalformedURLException x) { + System.out.println("FTP not supported by this runtime."); + return false; + } + } + public static void main(String[] args) throws Exception { - ProxyTest test = new ProxyTest(); + if (hasFtp()) + new ProxyTest(); } public ProxyTest() throws Exception { From 898965f4587e4d256fb1345720a8ab719dfadbda Mon Sep 17 00:00:00 2001 From: Christian Tornqvist Date: Sat, 2 Feb 2013 20:13:27 +0100 Subject: [PATCH 165/210] 8000363: runtime/7158988/FieldMonitor.java fails with exception Removed unnecessary shell script in the test. Reviewed-by: coleenp, sla --- .../test/runtime/7158988/FieldMonitor.java | 4 +- .../test/runtime/7158988/TestFieldMonitor.sh | 75 ------------------- 2 files changed, 3 insertions(+), 76 deletions(-) delete mode 100644 hotspot/test/runtime/7158988/TestFieldMonitor.sh diff --git a/hotspot/test/runtime/7158988/FieldMonitor.java b/hotspot/test/runtime/7158988/FieldMonitor.java index 584d39d20ca..5421f626278 100644 --- a/hotspot/test/runtime/7158988/FieldMonitor.java +++ b/hotspot/test/runtime/7158988/FieldMonitor.java @@ -24,8 +24,10 @@ /* * @test FieldMonitor.java * @bug 7158988 + * @key regression * @summary verify jvm does not crash while debugging - * @run shell TestFieldMonitor.sh + * @run compile TestPostFieldModification.java + * @run main/othervm FieldMonitor * @author axel.siebenborn@sap.com */ import java.io.BufferedReader; diff --git a/hotspot/test/runtime/7158988/TestFieldMonitor.sh b/hotspot/test/runtime/7158988/TestFieldMonitor.sh deleted file mode 100644 index aa18c1609ba..00000000000 --- a/hotspot/test/runtime/7158988/TestFieldMonitor.sh +++ /dev/null @@ -1,75 +0,0 @@ -#!/bin/sh - -if [ "${TESTSRC}" = "" ] -then TESTSRC=. -fi - -if [ "${TESTJAVA}" = "" ] -then - PARENT=`dirname \`which java\`` - TESTJAVA=`dirname ${PARENT}` - echo "TESTJAVA not set, selecting " ${TESTJAVA} - echo "If this is incorrect, try setting the variable manually." -fi - -if [ "${TESTCLASSES}" = "" ] -then - echo "TESTCLASSES not set. Test cannot execute. Failed." - exit 1 -fi - -# set platform-dependent variables -OS=`uname -s` -case "$OS" in - SunOS | Linux | Darwin) - NULL=/dev/null - PS=":" - FS="/" - ;; - Windows_95 | Windows_98 | Windows_ME ) - NULL=NUL - PS=";" - FS="\\" - echo "Test skipped, only for WinNT" - exit 0 - ;; - Windows_NT ) - NULL=NUL - PS=";" - FS="\\" - ;; - CYGWIN_NT* ) - NULL=/dev/null - PS=";" - FS="/" - ;; - CYGWIN_* ) - NULL=/dev/null - PS=";" - FS="/" - echo "Test skipped, only for WinNT" - exit 0 - ;; - * ) - echo "Unrecognized system!" - exit 1; - ;; -esac - -#CLASSPATH=.${PS}${TESTCLASSES} ; export CLASSPATH - -cp ${TESTSRC}${FS}*.java . - -${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} -fullversion - -${TESTJAVA}${FS}bin${FS}javac -classpath .${PS}$TESTJAVA${FS}lib${FS}tools.jar *.java - -${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} -classpath .${PS}$TESTJAVA${FS}lib${FS}tools.jar FieldMonitor > test.out - -grep "A fatal error has been detected" test.out > ${NULL} -if [ $? = 0 ]; then - cat test.out - STATUS=1 -fi - -exit $STATUS From e618b1556c93d5dec1c30b236a46f22f0e6f756e Mon Sep 17 00:00:00 2001 From: Ragini Prasad Date: Sat, 2 Feb 2013 12:08:43 -0800 Subject: [PATCH 166/210] 8007135: tools/launcher/VersionCheck.java failing with new tool jabswitch Reviewed-by: ksrini, mduigou --- jdk/test/tools/launcher/VersionCheck.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/jdk/test/tools/launcher/VersionCheck.java b/jdk/test/tools/launcher/VersionCheck.java index c30ef424011..11f65cb2e9a 100644 --- a/jdk/test/tools/launcher/VersionCheck.java +++ b/jdk/test/tools/launcher/VersionCheck.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2013, 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 @@ -42,6 +42,7 @@ public class VersionCheck extends TestHelper { // tools that do not accept -J-option static final String[] BLACKLIST_JOPTION = { "controlpanel", + "jabswitch", "java-rmi", "java-rmi.cgi", "java", From a9f424c887883bb9e9bd10deb93e657321313f80 Mon Sep 17 00:00:00 2001 From: Vicente Romero Date: Sat, 2 Feb 2013 21:04:56 +0000 Subject: [PATCH 167/210] 8005075: Pool.Method, and Pool.Variable redundant Symbol field should be removed Reviewed-by: jjg --- .../com/sun/tools/javac/code/Symbol.java | 10 +++-- .../com/sun/tools/javac/jvm/ClassWriter.java | 6 +-- .../classes/com/sun/tools/javac/jvm/Pool.java | 44 +++++++++---------- 3 files changed, 31 insertions(+), 29 deletions(-) diff --git a/langtools/src/share/classes/com/sun/tools/javac/code/Symbol.java b/langtools/src/share/classes/com/sun/tools/javac/code/Symbol.java index a970da60530..0bc115e1041 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/code/Symbol.java +++ b/langtools/src/share/classes/com/sun/tools/javac/code/Symbol.java @@ -496,9 +496,9 @@ public abstract class Symbol implements Element { return l.toList(); } - public static class DelegatedSymbol extends Symbol { - protected Symbol other; - public DelegatedSymbol(Symbol other) { + public static class DelegatedSymbol extends Symbol { + protected T other; + public DelegatedSymbol(T other) { super(other.kind, other.flags_field, other.name, other.type, other.owner); this.other = other; } @@ -532,6 +532,10 @@ public abstract class Symbol implements Element { public R accept(Symbol.Visitor v, P p) { return v.visitSymbol(other, p); } + + public T getUnderlyingSymbol() { + return other; + } } /** A class for type symbols. Type variables are represented by instances diff --git a/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassWriter.java b/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassWriter.java index b48701ee37c..8c1e3204c5d 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassWriter.java +++ b/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassWriter.java @@ -482,10 +482,8 @@ public class ClassWriter extends ClassFile { while (i < pool.pp) { Object value = pool.pool[i]; Assert.checkNonNull(value); - if (value instanceof Method) - value = ((Method)value).m; - else if (value instanceof Variable) - value = ((Variable)value).v; + if (value instanceof Method || value instanceof Variable) + value = ((DelegatedSymbol)value).getUnderlyingSymbol(); if (value instanceof MethodSymbol) { MethodSymbol m = (MethodSymbol)value; diff --git a/langtools/src/share/classes/com/sun/tools/javac/jvm/Pool.java b/langtools/src/share/classes/com/sun/tools/javac/jvm/Pool.java index 08a5d57d87f..553cc3ae1a1 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/jvm/Pool.java +++ b/langtools/src/share/classes/com/sun/tools/javac/jvm/Pool.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2013, 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 @@ -140,23 +140,23 @@ public class Pool { return n == null ? -1 : n.intValue(); } - static class Method extends DelegatedSymbol { - MethodSymbol m; + static class Method extends DelegatedSymbol { UniqueType uniqueType; Method(MethodSymbol m, Types types) { super(m); - this.m = m; this.uniqueType = new UniqueType(m.type, types); } - public boolean equals(Object other) { - if (!(other instanceof Method)) return false; - MethodSymbol o = ((Method)other).m; + public boolean equals(Object any) { + if (!(any instanceof Method)) return false; + MethodSymbol o = ((Method)any).other; + MethodSymbol m = this.other; return o.name == m.name && o.owner == m.owner && - ((Method)other).uniqueType.equals(uniqueType); + ((Method)any).uniqueType.equals(uniqueType); } public int hashCode() { + MethodSymbol m = this.other; return m.name.hashCode() * 33 + m.owner.hashCode() * 9 + @@ -173,21 +173,21 @@ public class Pool { } @Override - public boolean equals(Object other) { - if (!super.equals(other)) return false; - if (!(other instanceof DynamicMethod)) return false; - DynamicMethodSymbol dm1 = (DynamicMethodSymbol)m; - DynamicMethodSymbol dm2 = (DynamicMethodSymbol)((DynamicMethod)other).m; + public boolean equals(Object any) { + if (!super.equals(any)) return false; + if (!(any instanceof DynamicMethod)) return false; + DynamicMethodSymbol dm1 = (DynamicMethodSymbol)other; + DynamicMethodSymbol dm2 = (DynamicMethodSymbol)((DynamicMethod)any).other; return dm1.bsm == dm2.bsm && dm1.bsmKind == dm2.bsmKind && Arrays.equals(uniqueStaticArgs, - ((DynamicMethod)other).uniqueStaticArgs); + ((DynamicMethod)any).uniqueStaticArgs); } @Override public int hashCode() { int hash = super.hashCode(); - DynamicMethodSymbol dm = (DynamicMethodSymbol)m; + DynamicMethodSymbol dm = (DynamicMethodSymbol)other; hash += dm.bsmKind * 7 + dm.bsm.hashCode() * 11; for (int i = 0; i < dm.staticArgs.length; i++) { @@ -209,23 +209,23 @@ public class Pool { } } - static class Variable extends DelegatedSymbol { - VarSymbol v; + static class Variable extends DelegatedSymbol { UniqueType uniqueType; Variable(VarSymbol v, Types types) { super(v); - this.v = v; this.uniqueType = new UniqueType(v.type, types); } - public boolean equals(Object other) { - if (!(other instanceof Variable)) return false; - VarSymbol o = ((Variable)other).v; + public boolean equals(Object any) { + if (!(any instanceof Variable)) return false; + VarSymbol o = ((Variable)any).other; + VarSymbol v = other; return o.name == v.name && o.owner == v.owner && - ((Variable)other).uniqueType.equals(uniqueType); + ((Variable)any).uniqueType.equals(uniqueType); } public int hashCode() { + VarSymbol v = other; return v.name.hashCode() * 33 + v.owner.hashCode() * 9 + From a4a897ce527e42523783f5fc46b7b1f80342d25a Mon Sep 17 00:00:00 2001 From: Vicente Romero Date: Sun, 3 Feb 2013 02:31:30 +0000 Subject: [PATCH 168/210] 7199823: javac generates inner class that can't be verified Reviewed-by: jjg, mcimadamore --- .../com/sun/tools/javac/comp/Lower.java | 49 +++++--- .../7199823/InnerClassCannotBeVerified.java | 110 ++++++++++++++++++ 2 files changed, 143 insertions(+), 16 deletions(-) create mode 100644 langtools/test/tools/javac/7199823/InnerClassCannotBeVerified.java diff --git a/langtools/src/share/classes/com/sun/tools/javac/comp/Lower.java b/langtools/src/share/classes/com/sun/tools/javac/comp/Lower.java index bb3e913c33d..fb5202dffcb 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/comp/Lower.java +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Lower.java @@ -570,10 +570,19 @@ public class Lower extends TreeTranslator { * @param flags The class symbol's flags * @param owner The class symbol's owner */ - ClassSymbol makeEmptyClass(long flags, ClassSymbol owner) { + JCClassDecl makeEmptyClass(long flags, ClassSymbol owner) { + return makeEmptyClass(flags, owner, null, true); + } + + JCClassDecl makeEmptyClass(long flags, ClassSymbol owner, Name flatname, + boolean addToDefs) { // Create class symbol. ClassSymbol c = reader.defineClass(names.empty, owner); - c.flatname = chk.localClassName(c); + if (flatname != null) { + c.flatname = flatname; + } else { + c.flatname = chk.localClassName(c); + } c.sourcefile = owner.sourcefile; c.completer = null; c.members_field = new Scope(c); @@ -597,9 +606,8 @@ public class Lower extends TreeTranslator { cdef.type = c.type; // Append class definition tree to owner's definitions. - odef.defs = odef.defs.prepend(cdef); - - return c; + if (addToDefs) odef.defs = odef.defs.prepend(cdef); + return cdef; } /************************************************************************** @@ -706,7 +714,7 @@ public class Lower extends TreeTranslator { * and synthethise a class (with makeEmptyClass) if one is not available. * However, there is a small possibility that an existing class will not * be generated as expected if it is inside a conditional with a constant - * expression. If that is found to be the case, create an empty class here. + * expression. If that is found to be the case, create an empty class tree here. */ private void checkAccessConstructorTags() { for (List l = accessConstrTags; l.nonEmpty(); l = l.tail) { @@ -714,14 +722,10 @@ public class Lower extends TreeTranslator { if (isTranslatedClassAvailable(c)) continue; // Create class definition tree. - JCClassDecl cdef = make.ClassDef( - make.Modifiers(STATIC | SYNTHETIC), names.empty, - List.nil(), - null, List.nil(), List.nil()); - cdef.sym = c; - cdef.type = c.type; - // add it to the list of classes to be generated - translated.append(cdef); + JCClassDecl cdec = makeEmptyClass(STATIC | SYNTHETIC, + c.outermostClass(), c.flatname, false); + swapAccessConstructorTag(c, cdec.sym); + translated.append(cdec); } } // where @@ -735,6 +739,19 @@ public class Lower extends TreeTranslator { return false; } + void swapAccessConstructorTag(ClassSymbol oldCTag, ClassSymbol newCTag) { + for (MethodSymbol methodSymbol : accessConstrs.values()) { + Assert.check(methodSymbol.type.hasTag(METHOD)); + MethodType oldMethodType = + (MethodType)methodSymbol.type; + if (oldMethodType.argtypes.head.tsym == oldCTag) + methodSymbol.type = + types.createMethodTypeWithParameters(oldMethodType, + oldMethodType.getParameterTypes().tail + .prepend(newCTag.erasure(types))); + } + } + /************************************************************************** * Access methods *************************************************************************/ @@ -1211,7 +1228,7 @@ public class Lower extends TreeTranslator { "1"); ClassSymbol ctag = chk.compiled.get(flatname); if (ctag == null) - ctag = makeEmptyClass(STATIC | SYNTHETIC, topClass); + ctag = makeEmptyClass(STATIC | SYNTHETIC, topClass).sym; // keep a record of all tags, to verify that all are generated as required accessConstrTags = accessConstrTags.prepend(ctag); return ctag; @@ -1778,7 +1795,7 @@ public class Lower extends TreeTranslator { if (e.sym.kind == TYP && e.sym.name == names.empty && (e.sym.flags() & INTERFACE) == 0) return (ClassSymbol) e.sym; - return makeEmptyClass(STATIC | SYNTHETIC, clazz); + return makeEmptyClass(STATIC | SYNTHETIC, clazz).sym; } /** Return symbol for "class$" method. If there is no method definition diff --git a/langtools/test/tools/javac/7199823/InnerClassCannotBeVerified.java b/langtools/test/tools/javac/7199823/InnerClassCannotBeVerified.java new file mode 100644 index 00000000000..c30927484ab --- /dev/null +++ b/langtools/test/tools/javac/7199823/InnerClassCannotBeVerified.java @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2012, 2013, 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. + * + * 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. + */ + +/* + * @test + * @bug 7199823 + * @summary javac generates inner class that can't be verified + * @run main InnerClassCannotBeVerified + */ + +import java.util.Arrays; +import javax.tools.JavaFileObject; +import java.net.URI; +import javax.tools.SimpleJavaFileObject; +import javax.tools.ToolProvider; +import javax.tools.JavaCompiler; +import com.sun.source.util.JavacTask; +import com.sun.tools.classfile.ClassFile; +import com.sun.tools.classfile.ConstantPoolException; +import java.io.File; +import java.io.IOException; + +public class InnerClassCannotBeVerified { + + private static final String errorMessage = + "Compile error while compiling the following source:\n"; + + public static void main(String... args) throws Exception { + new InnerClassCannotBeVerified().run(); + } + + void run() throws Exception { + JavaCompiler comp = ToolProvider.getSystemJavaCompiler(); + JavaSource source = new JavaSource(); + JavacTask ct = (JavacTask)comp.getTask(null, null, null, + null, null, Arrays.asList(source)); + try { + if (!ct.call()) { + throw new AssertionError(errorMessage + + source.getCharContent(true)); + } + } catch (Throwable ex) { + throw new AssertionError(errorMessage + + source.getCharContent(true)); + } + check(); + } + + private void check() throws IOException, ConstantPoolException { + File file = new File("Test$1.class"); + ClassFile classFile = ClassFile.read(file); + boolean inheritsFromObject = + classFile.getSuperclassName().equals("java/lang/Object"); + boolean implementsNoInterface = classFile.interfaces.length == 0; + boolean noMethods = classFile.methods.length == 0; + if (!(inheritsFromObject && + implementsNoInterface && + noMethods)) { + throw new AssertionError("The inner classes reused as " + + "access constructor tag for this code must be empty"); + } + } + + class JavaSource extends SimpleJavaFileObject { + + String internalSource = + "public class Test {\n" + + " private static class Foo {}\n" + + " public static void main(String[] args){ \n" + + " new Foo();\n" + + " if(false) {\n" + + " new Runnable() {\n" + + " @Override\n" + + " public void run() {\n" + + " System.out.println();\n" + + " }\n" + + " }.run();\n" + + " }\n" + + " }\n" + + "}"; + public JavaSource() { + super(URI.create("Test.java"), JavaFileObject.Kind.SOURCE); + } + + @Override + public CharSequence getCharContent(boolean ignoreEncodingErrors) { + return internalSource; + } + } +} From 3f02516d3e67f8cd452bdd95cecb5667752abc81 Mon Sep 17 00:00:00 2001 From: Brian Burkhalter Date: Sun, 3 Feb 2013 18:20:24 +0400 Subject: [PATCH 169/210] 6471906: java.lang.NegativeArraySizeException in tenToThe Reviewed-by: darcy --- .../share/classes/java/math/BigDecimal.java | 26 ++++++++++++++----- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/jdk/src/share/classes/java/math/BigDecimal.java b/jdk/src/share/classes/java/math/BigDecimal.java index d95b1cb27b3..b7f6380948e 100644 --- a/jdk/src/share/classes/java/math/BigDecimal.java +++ b/jdk/src/share/classes/java/math/BigDecimal.java @@ -3537,13 +3537,25 @@ public class BigDecimal extends Number implements Comparable { else return expandBigIntegerTenPowers(n); } - // BigInteger.pow is slow, so make 10**n by constructing a - // BigInteger from a character string (still not very fast) - char tenpow[] = new char[n + 1]; - tenpow[0] = '1'; - for (int i = 1; i <= n; i++) - tenpow[i] = '0'; - return new BigInteger(tenpow,1, tenpow.length); + + if (n < 1024*524288) { + // BigInteger.pow is slow, so make 10**n by constructing a + // BigInteger from a character string (still not very fast) + // which occupies no more than 1GB (!) of memory. + char tenpow[] = new char[n + 1]; + tenpow[0] = '1'; + for (int i = 1; i <= n; i++) { + tenpow[i] = '0'; + } + return new BigInteger(tenpow, 1, tenpow.length); + } + + if ((n & 0x1) == 0x1) { + return BigInteger.TEN.multiply(bigTenToThe(n - 1)); + } else { + BigInteger tmp = bigTenToThe(n/2); + return tmp.multiply(tmp); + } } /** From eea117f3e5a46f6183ccf36fe87f5cfb3eb8fb0e Mon Sep 17 00:00:00 2001 From: Dmitry Samersoff Date: Sun, 3 Feb 2013 21:39:58 +0400 Subject: [PATCH 170/210] 8002048: Protocol to discovery of manageable Java processes on a network Introduce a protocol to discover manageble Java instances across a network subnet, JDP Reviewed-by: sla, dfuchs --- .../share/classes/sun/management/Agent.java | 218 ++++++++---- .../sun/management/jdp/JdpBroadcaster.java | 124 +++++++ .../sun/management/jdp/JdpController.java | 196 +++++++++++ .../sun/management/jdp/JdpException.java | 40 +++ .../sun/management/jdp/JdpGenericPacket.java | 95 ++++++ .../sun/management/jdp/JdpJmxPacket.java | 196 +++++++++++ .../classes/sun/management/jdp/JdpPacket.java | 63 ++++ .../sun/management/jdp/JdpPacketReader.java | 139 ++++++++ .../sun/management/jdp/JdpPacketWriter.java | 93 +++++ .../sun/management/jdp/package-info.java | 55 +++ jdk/test/sun/management/jdp/JdpClient.java | 160 +++++++++ .../sun/management/jdp/JdpDoSomething.java | 103 ++++++ jdk/test/sun/management/jdp/JdpTest.sh | 323 ++++++++++++++++++ jdk/test/sun/management/jdp/JdpUnitTest.java | 90 +++++ 14 files changed, 1824 insertions(+), 71 deletions(-) create mode 100644 jdk/src/share/classes/sun/management/jdp/JdpBroadcaster.java create mode 100644 jdk/src/share/classes/sun/management/jdp/JdpController.java create mode 100644 jdk/src/share/classes/sun/management/jdp/JdpException.java create mode 100644 jdk/src/share/classes/sun/management/jdp/JdpGenericPacket.java create mode 100644 jdk/src/share/classes/sun/management/jdp/JdpJmxPacket.java create mode 100644 jdk/src/share/classes/sun/management/jdp/JdpPacket.java create mode 100644 jdk/src/share/classes/sun/management/jdp/JdpPacketReader.java create mode 100644 jdk/src/share/classes/sun/management/jdp/JdpPacketWriter.java create mode 100644 jdk/src/share/classes/sun/management/jdp/package-info.java create mode 100644 jdk/test/sun/management/jdp/JdpClient.java create mode 100644 jdk/test/sun/management/jdp/JdpDoSomething.java create mode 100644 jdk/test/sun/management/jdp/JdpTest.sh create mode 100644 jdk/test/sun/management/jdp/JdpUnitTest.java diff --git a/jdk/src/share/classes/sun/management/Agent.java b/jdk/src/share/classes/sun/management/Agent.java index 19d2dedb5b4..feef02ad6be 100644 --- a/jdk/src/share/classes/sun/management/Agent.java +++ b/jdk/src/share/classes/sun/management/Agent.java @@ -22,7 +22,6 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ - package sun.management; import java.io.BufferedInputStream; @@ -31,49 +30,55 @@ import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; - +import java.lang.management.ManagementFactory; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; -import java.lang.management.ManagementFactory; - +import java.net.InetAddress; +import java.net.Socket; +import java.net.UnknownHostException; import java.text.MessageFormat; - import java.util.MissingResourceException; import java.util.Properties; import java.util.ResourceBundle; import javax.management.remote.JMXConnectorServer; +import javax.management.remote.JMXServiceURL; import static sun.management.AgentConfigurationError.*; import sun.management.jmxremote.ConnectorBootstrap; +import sun.management.jdp.JdpController; +import sun.management.jdp.JdpException; import sun.misc.VMSupport; /** - * This Agent is started by the VM when -Dcom.sun.management.snmp - * or -Dcom.sun.management.jmxremote is set. This class will be - * loaded by the system class loader. Also jmx framework could - * be started by jcmd + * This Agent is started by the VM when -Dcom.sun.management.snmp or + * -Dcom.sun.management.jmxremote is set. This class will be loaded by the + * system class loader. Also jmx framework could be started by jcmd */ public class Agent { // management properties + private static Properties mgmtProps; private static ResourceBundle messageRB; - private static final String CONFIG_FILE = - "com.sun.management.config.file"; + "com.sun.management.config.file"; private static final String SNMP_PORT = - "com.sun.management.snmp.port"; + "com.sun.management.snmp.port"; private static final String JMXREMOTE = - "com.sun.management.jmxremote"; + "com.sun.management.jmxremote"; private static final String JMXREMOTE_PORT = - "com.sun.management.jmxremote.port"; + "com.sun.management.jmxremote.port"; + private static final String RMI_PORT = + "com.sun.management.jmxremote.rmi.port"; private static final String ENABLE_THREAD_CONTENTION_MONITORING = - "com.sun.management.enableThreadContentionMonitoring"; + "com.sun.management.enableThreadContentionMonitoring"; private static final String LOCAL_CONNECTOR_ADDRESS_PROP = - "com.sun.management.jmxremote.localConnectorAddress"; - + "com.sun.management.jmxremote.localConnectorAddress"; private static final String SNMP_ADAPTOR_BOOTSTRAP_CLASS_NAME = - "sun.management.snmp.AdaptorBootstrap"; + "sun.management.snmp.AdaptorBootstrap"; + + private static final String JDP_DEFAULT_ADDRESS = "239.255.255.225"; + private static final int JDP_DEFAULT_PORT = 7095; // The only active agent allowed private static JMXConnectorServer jmxServer = null; @@ -81,26 +86,25 @@ public class Agent { // Parse string com.sun.management.prop=xxx,com.sun.management.prop=yyyy // and return property set if args is null or empty // return empty property set - private static Properties parseString(String args){ + private static Properties parseString(String args) { Properties argProps = new Properties(); if (args != null) { - for (String option : args.split(",")) { - String s[] = option.split("=", 2); - String name = s[0].trim(); - String value = (s.length > 1) ? s[1].trim() : ""; + for (String option : args.split(",")) { + String s[] = option.split("=", 2); + String name = s[0].trim(); + String value = (s.length > 1) ? s[1].trim() : ""; - if (!name.startsWith("com.sun.management.")) { - error(INVALID_OPTION, name); - } + if (!name.startsWith("com.sun.management.")) { + error(INVALID_OPTION, name); + } - argProps.setProperty(name, value); - } + argProps.setProperty(name, value); + } } return argProps; } - // invoked by -javaagent or -Dcom.sun.management.agent.class public static void premain(String args) throws Exception { agentmain(args); @@ -115,18 +119,18 @@ public class Agent { Properties arg_props = parseString(args); // Read properties from the config file - Properties config_props = new Properties(); - String fname = arg_props.getProperty(CONFIG_FILE); - readConfiguration(fname, config_props); + Properties config_props = new Properties(); + String fname = arg_props.getProperty(CONFIG_FILE); + readConfiguration(fname, config_props); - // Arguments override config file - config_props.putAll(arg_props); - startAgent(config_props); + // Arguments override config file + config_props.putAll(arg_props); + startAgent(config_props); } // jcmd ManagementAgent.start_local entry point // Also called due to command-line via startAgent() - private static synchronized void startLocalManagementAgent(){ + private static synchronized void startLocalManagementAgent() { Properties agentProps = VMSupport.getAgentProperties(); // start local connector if not started @@ -156,7 +160,7 @@ public class Agent { throw new RuntimeException(getText(INVALID_STATE, "Agent already started")); } - Properties argProps = parseString(args); + Properties argProps = parseString(args); Properties configProps = new Properties(); // Load the management properties from the config file @@ -169,7 +173,7 @@ public class Agent { // management properties can be overridden by system properties // which take precedence Properties sysProps = System.getProperties(); - synchronized(sysProps){ + synchronized (sysProps) { configProps.putAll(sysProps); } @@ -190,21 +194,26 @@ public class Agent { // can specify this property inside config file, so enable optional // monitoring functionality if this property is set final String enableThreadContentionMonitoring = - configProps.getProperty(ENABLE_THREAD_CONTENTION_MONITORING); + configProps.getProperty(ENABLE_THREAD_CONTENTION_MONITORING); if (enableThreadContentionMonitoring != null) { ManagementFactory.getThreadMXBean(). - setThreadContentionMonitoringEnabled(true); + setThreadContentionMonitoringEnabled(true); } String jmxremotePort = configProps.getProperty(JMXREMOTE_PORT); if (jmxremotePort != null) { jmxServer = ConnectorBootstrap. - startRemoteConnectorServer(jmxremotePort, configProps); + startRemoteConnectorServer(jmxremotePort, configProps); + + startDiscoveryService(configProps); } } private static synchronized void stopRemoteManagementAgent() throws Exception { + + JdpController.stopDiscoveryService(); + if (jmxServer != null) { ConnectorBootstrap.unexportRegistry(); @@ -222,15 +231,15 @@ public class Agent { // Enable optional monitoring functionality if requested final String enableThreadContentionMonitoring = - props.getProperty(ENABLE_THREAD_CONTENTION_MONITORING); + props.getProperty(ENABLE_THREAD_CONTENTION_MONITORING); if (enableThreadContentionMonitoring != null) { ManagementFactory.getThreadMXBean(). - setThreadContentionMonitoringEnabled(true); + setThreadContentionMonitoringEnabled(true); } try { if (snmpPort != null) { - loadSnmpAgent(snmpPort, props); + loadSnmpAgent(snmpPort, props); } /* @@ -242,13 +251,14 @@ public class Agent { * of this "local" server is exported as a counter to the jstat * instrumentation buffer. */ - if (jmxremote != null || jmxremotePort != null) { + if (jmxremote != null || jmxremotePort != null) { if (jmxremotePort != null) { - jmxServer = ConnectorBootstrap. - startRemoteConnectorServer(jmxremotePort, props); + jmxServer = ConnectorBootstrap. + startRemoteConnectorServer(jmxremotePort, props); + startDiscoveryService(props); } startLocalManagementAgent(); - } + } } catch (AgentConfigurationError e) { error(e.getError(), e.getParams()); @@ -257,6 +267,73 @@ public class Agent { } } + private static void startDiscoveryService(Properties props) + throws IOException { + // Start discovery service if requested + String discoveryPort = props.getProperty("com.sun.management.jdp.port"); + String discoveryAddress = props.getProperty("com.sun.management.jdp.address"); + String discoveryShouldStart = props.getProperty("com.sun.management.jmxremote.autodiscovery"); + + // Decide whether we should start autodicovery service. + // To start autodiscovery following conditions should be met: + // autodiscovery==true OR (autodicovery==null AND jdp.port != NULL) + + boolean shouldStart = false; + if (discoveryShouldStart == null){ + shouldStart = (discoveryPort != null); + } + else{ + try{ + shouldStart = Boolean.parseBoolean(discoveryShouldStart); + } catch (NumberFormatException e) { + throw new AgentConfigurationError("Couldn't parse autodiscovery argument"); + } + } + + if (shouldStart) { + // port and address are required arguments and have no default values + InetAddress address; + try { + address = (discoveryAddress == null) ? + InetAddress.getByName(JDP_DEFAULT_ADDRESS) : InetAddress.getByName(discoveryAddress); + } catch (UnknownHostException e) { + throw new AgentConfigurationError("Unable to broadcast to requested address", e); + } + + int port = JDP_DEFAULT_PORT; + if (discoveryPort != null) { + try { + port = Integer.parseInt(discoveryPort); + } catch (NumberFormatException e) { + throw new AgentConfigurationError("Couldn't parse JDP port argument"); + } + } + + // Rebuilding service URL to broadcast it + String jmxremotePort = props.getProperty(JMXREMOTE_PORT); + String rmiPort = props.getProperty(RMI_PORT); + + JMXServiceURL url = jmxServer.getAddress(); + String hostname = url.getHost(); + + String jmxUrlStr = (rmiPort != null) + ? String.format( + "service:jmx:rmi://%s:%s/jndi/rmi://%s:%s/jmxrmi", + hostname, rmiPort, hostname, jmxremotePort) + : String.format( + "service:jmx:rmi:///jndi/rmi://%s:%s/jmxrmi", hostname, jmxremotePort); + + String instanceName = System.getProperty("com.sun.management.jdp.name"); + + try{ + JdpController.startDiscoveryService(address, port, instanceName, jmxUrlStr); + } + catch(JdpException e){ + throw new AgentConfigurationError("Couldn't start JDP service", e); + } + } + } + public static Properties loadManagementProperties() { Properties props = new Properties(); @@ -268,22 +345,22 @@ public class Agent { // management properties can be overridden by system properties // which take precedence Properties sysProps = System.getProperties(); - synchronized(sysProps){ + synchronized (sysProps) { props.putAll(sysProps); } return props; - } + } - public static synchronized Properties getManagementProperties() { + public static synchronized Properties getManagementProperties() { if (mgmtProps == null) { String configFile = System.getProperty(CONFIG_FILE); String snmpPort = System.getProperty(SNMP_PORT); String jmxremote = System.getProperty(JMXREMOTE); String jmxremotePort = System.getProperty(JMXREMOTE_PORT); - if (configFile == null && snmpPort == null && - jmxremote == null && jmxremotePort == null) { + if (configFile == null && snmpPort == null + && jmxremote == null && jmxremotePort == null) { // return if out-of-the-management option is not specified return null; } @@ -297,22 +374,23 @@ public class Agent { // invoke the following through reflection: // AdaptorBootstrap.initialize(snmpPort, props); final Class adaptorClass = - Class.forName(SNMP_ADAPTOR_BOOTSTRAP_CLASS_NAME,true,null); + Class.forName(SNMP_ADAPTOR_BOOTSTRAP_CLASS_NAME, true, null); final Method initializeMethod = adaptorClass.getMethod("initialize", - String.class, Properties.class); - initializeMethod.invoke(null,snmpPort,props); + String.class, Properties.class); + initializeMethod.invoke(null, snmpPort, props); } catch (ClassNotFoundException | NoSuchMethodException | IllegalAccessException x) { // snmp runtime doesn't exist - initialization fails - throw new UnsupportedOperationException("Unsupported management property: " + SNMP_PORT,x); + throw new UnsupportedOperationException("Unsupported management property: " + SNMP_PORT, x); } catch (InvocationTargetException x) { final Throwable cause = x.getCause(); - if (cause instanceof RuntimeException) + if (cause instanceof RuntimeException) { throw (RuntimeException) cause; - else if (cause instanceof Error) + } else if (cause instanceof Error) { throw (Error) cause; + } // should not happen... - throw new UnsupportedOperationException("Unsupported management property: " + SNMP_PORT,cause); + throw new UnsupportedOperationException("Unsupported management property: " + SNMP_PORT, cause); } } @@ -353,8 +431,8 @@ public class Agent { } catch (IOException e) { error(CONFIG_FILE_CLOSE_FAILED, fname); } - } - } + } + } } public static void startAgent() throws Exception { @@ -389,9 +467,9 @@ public class Agent { // invoke the premain(String args) method Class clz = ClassLoader.getSystemClassLoader().loadClass(cname); Method premain = clz.getMethod("premain", - new Class[] { String.class }); + new Class[]{String.class}); premain.invoke(null, /* static */ - new Object[] { args }); + new Object[]{args}); } catch (ClassNotFoundException ex) { error(AGENT_CLASS_NOT_FOUND, "\"" + cname + "\""); } catch (NoSuchMethodException ex) { @@ -400,8 +478,8 @@ public class Agent { error(AGENT_CLASS_ACCESS_DENIED); } catch (Exception ex) { String msg = (ex.getCause() == null - ? ex.getMessage() - : ex.getCause().getMessage()); + ? ex.getMessage() + : ex.getCause().getMessage()); error(AGENT_CLASS_FAILED, msg); } } @@ -425,7 +503,6 @@ public class Agent { } } - public static void error(String key, String message) { String keyText = getText(key); System.err.print(getText("agent.err.error") + ": " + keyText); @@ -447,7 +524,7 @@ public class Agent { private static void initResource() { try { messageRB = - ResourceBundle.getBundle("sun.management.resources.agent"); + ResourceBundle.getBundle("sun.management.resources.agent"); } catch (MissingResourceException e) { throw new Error("Fatal: Resource for management agent is missing"); } @@ -470,10 +547,9 @@ public class Agent { } String format = messageRB.getString(key); if (format == null) { - format = "missing resource key: key = \"" + key + "\", " + - "arguments = \"{0}\", \"{1}\", \"{2}\""; + format = "missing resource key: key = \"" + key + "\", " + + "arguments = \"{0}\", \"{1}\", \"{2}\""; } return MessageFormat.format(format, (Object[]) args); } - } diff --git a/jdk/src/share/classes/sun/management/jdp/JdpBroadcaster.java b/jdk/src/share/classes/sun/management/jdp/JdpBroadcaster.java new file mode 100644 index 00000000000..df5f23458e5 --- /dev/null +++ b/jdk/src/share/classes/sun/management/jdp/JdpBroadcaster.java @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2012, 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. + * + * 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. + */ +package sun.management.jdp; + +import java.io.IOException; +import java.net.Inet6Address; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.NetworkInterface; +import java.net.ProtocolFamily; +import java.net.StandardProtocolFamily; +import java.net.StandardSocketOptions; +import java.nio.ByteBuffer; +import java.nio.channels.DatagramChannel; +import java.nio.channels.UnsupportedAddressTypeException; + +/** + * JdpBroadcaster is responsible for sending pre-built JDP packet across a Net + * + *

Multicast group address, port number and ttl have to be chosen on upper + * level and passed to broadcaster constructor. Also it's possible to specify + * source address to broadcast from.

+ * + *

JdpBradcaster doesn't perform any validation on a supplied {@code port} and {@code ttl} because + * the allowed values depend on an operating system setup

+ * + */ +public final class JdpBroadcaster { + + private final InetAddress addr; + private final int port; + private final DatagramChannel channel; + + /** + * Create a new broadcaster + * + * @param address - multicast group address + * @param srcAddress - address of interface we should use to broadcast. + * @param port - udp port to use + * @param ttl - packet ttl + * @throws IOException + */ + public JdpBroadcaster(InetAddress address, InetAddress srcAddress, int port, int ttl) + throws IOException, JdpException { + this.addr = address; + this.port = port; + + ProtocolFamily family = (address instanceof Inet6Address) + ? StandardProtocolFamily.INET6 : StandardProtocolFamily.INET; + + channel = DatagramChannel.open(family); + channel.setOption(StandardSocketOptions.SO_REUSEADDR, true); + channel.setOption(StandardSocketOptions.IP_MULTICAST_TTL, ttl); + + // with srcAddress equal to null, this constructor do exactly the same as + // if srcAddress is not passed + if (srcAddress != null) { + // User requests particular interface to bind to + NetworkInterface interf = NetworkInterface.getByInetAddress(srcAddress); + try { + channel.bind(new InetSocketAddress(srcAddress, 0)); + } catch (UnsupportedAddressTypeException ex) { + throw new JdpException("Unable to bind to source address"); + } + channel.setOption(StandardSocketOptions.IP_MULTICAST_IF, interf); + } + } + + /** + * Create a new broadcaster + * + * @param address - multicast group address + * @param port - udp port to use + * @param ttl - packet ttl + * @throws IOException + */ + public JdpBroadcaster(InetAddress address, int port, int ttl) + throws IOException, JdpException { + this(address, null, port, ttl); + } + + /** + * Broadcast pre-built packet + * + * @param packet - instance of JdpPacket + * @throws IOException + */ + public void sendPacket(JdpPacket packet) + throws IOException { + byte[] data = packet.getPacketData(); + // Unlike allocate/put wrap don't need a flip afterward + ByteBuffer b = ByteBuffer.wrap(data); + channel.send(b, new InetSocketAddress(addr, port)); + } + + /** + * Shutdown broadcaster and close underlying socket channel + * + * @throws IOException + */ + public void shutdown() throws IOException { + channel.close(); + } +} diff --git a/jdk/src/share/classes/sun/management/jdp/JdpController.java b/jdk/src/share/classes/sun/management/jdp/JdpController.java new file mode 100644 index 00000000000..d8d0ed46930 --- /dev/null +++ b/jdk/src/share/classes/sun/management/jdp/JdpController.java @@ -0,0 +1,196 @@ +/* + * Copyright (c) 2012, 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. + * + * 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. + */ +package sun.management.jdp; + +import java.io.IOException; +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.util.UUID; + +/** + * JdpController is responsible to create and manage a broadcast loop + * + *

Other part of code has no access to broadcast loop and have to use + * provided static methods + * {@link #startDiscoveryService(InetAddress,int,String,String) startDiscoveryService} + * and {@link #stopDiscoveryService() stopDiscoveryService}

+ *

{@link #startDiscoveryService(InetAddress,int,String,String) startDiscoveryService} could be called multiple + * times as it stops the running service if it is necessary. Call to {@link #stopDiscoveryService() stopDiscoveryService} + * ignored if service isn't run

+ * + * + *

+ * + *

System properties below could be used to control broadcast loop behavior. + * Property below have to be set explicitly in command line. It's not possible to + * set it in management.config file. Careless changes of these properties could + * lead to security or network issues. + *

    + *
  • com.sun.management.jdp.ttl - set ttl for broadcast packet
  • + *
  • com.sun.management.jdp.pause - set broadcast interval in seconds
  • + *
  • com.sun.management.jdp.source_addr - an address of interface to use for broadcast
  • + *
+

+ *

null parameters values are filtered out on {@link JdpPacketWriter} level and + * corresponding keys are not placed to packet.

+ */ +public final class JdpController { + + private static class JDPControllerRunner implements Runnable { + + private final JdpJmxPacket packet; + private final JdpBroadcaster bcast; + private final int pause; + private volatile boolean shutdown = false; + + private JDPControllerRunner(JdpBroadcaster bcast, JdpJmxPacket packet, int pause) { + this.bcast = bcast; + this.packet = packet; + this.pause = pause; + } + + @Override + public void run() { + try { + while (!shutdown) { + bcast.sendPacket(packet); + try { + Thread.sleep(this.pause); + } catch (InterruptedException e) { + // pass + } + } + + } catch (IOException e) { + // pass; + } + + // It's not possible to re-use controller, + // nevertheless reset shutdown variable + try { + stop(); + bcast.shutdown(); + } catch (IOException ex) { + // pass - ignore IOException during shutdown + } + } + + public void stop() { + shutdown = true; + } + } + private static JDPControllerRunner controller = null; + + private JdpController(){ + // Don't allow to instantiate this class. + } + + // Utility to handle optional system properties + // Parse an integer from string or return default if provided string is null + private static int getInteger(String val, int dflt, String msg) throws JdpException { + try { + return (val == null) ? dflt : Integer.parseInt(val); + } catch (NumberFormatException ex) { + throw new JdpException(msg); + } + } + + // Parse an inet address from string or return default if provided string is null + private static InetAddress getInetAddress(String val, InetAddress dflt, String msg) throws JdpException { + try { + return (val == null) ? dflt : InetAddress.getByName(val); + } catch (UnknownHostException ex) { + throw new JdpException(msg); + } + } + + /** + * Starts discovery service + * + * @param address - multicast group address + * @param port - udp port to use + * @param instanceName - name of running JVM instance + * @param url - JMX service url + * @throws IOException + */ + public static synchronized void startDiscoveryService(InetAddress address, int port, String instanceName, String url) + throws IOException, JdpException { + + // Limit packet to local subnet by default + int ttl = getInteger( + System.getProperty("com.sun.management.jdp.ttl"), 1, + "Invalid jdp packet ttl"); + + // Broadcast once a 5 seconds by default + int pause = getInteger( + System.getProperty("com.sun.management.jdp.pause"), 5, + "Invalid jdp pause"); + + // Converting seconds to milliseconds + pause = pause * 1000; + + // Allow OS to choose broadcast source + InetAddress sourceAddress = getInetAddress( + System.getProperty("com.sun.management.jdp.source_addr"), null, + "Invalid source address provided"); + + // Generate session id + UUID id = UUID.randomUUID(); + + JdpJmxPacket packet = new JdpJmxPacket(id, url); + + // Don't broadcast whole command line for security reason. + // Strip everything after first space + String javaCommand = System.getProperty("sun.java.command"); + if (javaCommand != null) { + String[] arr = javaCommand.split(" ", 2); + packet.setMainClass(arr[0]); + } + + // Put optional explicit java instance name to packet, if user doesn't specify + // it the key is skipped. PacketWriter is responsible to skip keys having null value. + packet.setInstanceName(instanceName); + + JdpBroadcaster bcast = new JdpBroadcaster(address, sourceAddress, port, ttl); + + // Stop discovery service if it's already running + stopDiscoveryService(); + + controller = new JDPControllerRunner(bcast, packet, pause); + + Thread t = new Thread(controller, "JDP broadcaster"); + t.setDaemon(true); + t.start(); + } + + /** + * Stop running discovery service, + * it's safe to attempt to stop not started service + */ + public static synchronized void stopDiscoveryService() { + if ( controller != null ){ + controller.stop(); + controller = null; + } + } +} diff --git a/jdk/src/share/classes/sun/management/jdp/JdpException.java b/jdk/src/share/classes/sun/management/jdp/JdpException.java new file mode 100644 index 00000000000..03404223e94 --- /dev/null +++ b/jdk/src/share/classes/sun/management/jdp/JdpException.java @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2012, 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. + * + * 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. + */ +package sun.management.jdp; + +/** + * An Exception thrown if a JDP implementation encounters a problem. + */ +public final class JdpException extends Exception { + + private static final long serialVersionUID = 1L; + + /** + * Construct a new JDP exception with a meaningful message + * + * @param msg - message + */ + public JdpException(String msg) { + super(msg); + } +} diff --git a/jdk/src/share/classes/sun/management/jdp/JdpGenericPacket.java b/jdk/src/share/classes/sun/management/jdp/JdpGenericPacket.java new file mode 100644 index 00000000000..8e88b148265 --- /dev/null +++ b/jdk/src/share/classes/sun/management/jdp/JdpGenericPacket.java @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2012, 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. + * + * 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. + */ +package sun.management.jdp; + +/** + * JdpGenericPacket responsible to provide fields + * common for all Jdp packets + */ +public abstract class JdpGenericPacket implements JdpPacket { + + /** + * JDP protocol magic. Magic allows a reader to quickly select + * JDP packets from a bunch of broadcast packets addressed to the same port + * and broadcast group. Any packet intended to be parsed by JDP client + * has to start from this magic. + */ + private static final int MAGIC = 0xC0FFEE42; + + /** + * Current version of protocol. Any implementation of this protocol has to + * conform with the packet structure and the flow described in JEP-168 + */ + private static final short PROTOCOL_VERSION = 1; + + /** + * Default do-nothing constructor + */ + protected JdpGenericPacket(){ + // do nothing + } + + + /** + * Validate protocol header magic field + * + * @param magic - value to validate + * @throws JdpException + */ + public static void checkMagic(int magic) + throws JdpException { + if (magic != MAGIC) { + throw new JdpException("Invalid JDP magic header: " + magic); + } + } + + /** + * Validate protocol header version field + * + * @param version - value to validate + * @throws JdpException + */ + public static void checkVersion(short version) + throws JdpException { + + if (version > PROTOCOL_VERSION) { + throw new JdpException("Unsupported protocol version: " + version); + } + } + + /** + * + * @return protocol magic + */ + public static int getMagic() { + return MAGIC; + } + + /** + * + * @return current protocol version + */ + public static short getVersion() { + return PROTOCOL_VERSION; + } +} diff --git a/jdk/src/share/classes/sun/management/jdp/JdpJmxPacket.java b/jdk/src/share/classes/sun/management/jdp/JdpJmxPacket.java new file mode 100644 index 00000000000..7d5ccc2f892 --- /dev/null +++ b/jdk/src/share/classes/sun/management/jdp/JdpJmxPacket.java @@ -0,0 +1,196 @@ +/* + * Copyright (c) 2012, 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. + * + * 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. + */ +package sun.management.jdp; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; +import java.util.UUID; + +/** + * A packet to broadcasts JMX URL + * + * Fields: + * + *
    + *
  • UUID - broadcast session ID, changed every time when we start/stop + * discovery service
  • + *
  • JMX_URL - URL to connect to JMX service
  • + *
  • MAIN_CLASS - optional name of main class, filled from sun.java.command stripped for + * security reason to first space
  • + *
  • INSTANCE_NAME - optional custom name of particular instance as provided by customer
  • + *
+ */ +public final class JdpJmxPacket + extends JdpGenericPacket + implements JdpPacket { + + /** + * Session ID + */ + public final static String UUID_KEY = "DISCOVERABLE_SESSION_UUID"; + /** + * Name of main class + */ + public final static String MAIN_CLASS_KEY = "MAIN_CLASS"; + /** + * JMX service URL + */ + public final static String JMX_SERVICE_URL_KEY = "JMX_SERVICE_URL"; + /** + * Name of Java instance + */ + public final static String INSTANCE_NAME_KEY = "INSTANCE_NAME"; + + private UUID id; + private String mainClass; + private String jmxServiceUrl; + private String instanceName; + + /** + * Create new instance from user provided data. Set mandatory fields + * + * @param id - java instance id + * @param jmxServiceUrl - JMX service url + */ + public JdpJmxPacket(UUID id, String jmxServiceUrl) { + this.id = id; + this.jmxServiceUrl = jmxServiceUrl; + } + + /** + * Create new instance from network data Parse packet and set fields. + * + * @param data - raw packet data as it came from a Net + * @throws JdpException + */ + public JdpJmxPacket(byte[] data) + throws JdpException { + JdpPacketReader reader; + + reader = new JdpPacketReader(data); + Map p = reader.getDiscoveryDataAsMap(); + + String sId = p.get(UUID_KEY); + this.id = (sId == null) ? null : UUID.fromString(sId); + this.jmxServiceUrl = p.get(JMX_SERVICE_URL_KEY); + this.mainClass = p.get(MAIN_CLASS_KEY); + this.instanceName = p.get(INSTANCE_NAME_KEY); + } + + /** + * Set main class field + * + * @param mainClass - main class of running app + */ + public void setMainClass(String mainClass) { + this.mainClass = mainClass; + } + + /** + * Set instance name field + * + * @param instanceName - name of instance as provided by customer + */ + public void setInstanceName(String instanceName) { + this.instanceName = instanceName; + } + + /** + * @return id of discovery session + */ + public UUID getId() { + return id; + } + + /** + * + * @return main class field + */ + public String getMainClass() { + return mainClass; + } + + /** + * + * @return JMX service URL + */ + public String getJmxServiceUrl() { + return jmxServiceUrl; + } + + /** + * + * @return instance name + */ + public String getInstanceName() { + return instanceName; + } + + /** + * + * @return assembled packet ready to be sent across a Net + * @throws IOException + */ + @Override + public byte[] getPacketData() throws IOException { + // Assemble packet from fields to byte array + JdpPacketWriter writer; + writer = new JdpPacketWriter(); + writer.addEntry(UUID_KEY, (id == null) ? null : id.toString()); + writer.addEntry(MAIN_CLASS_KEY, mainClass); + writer.addEntry(JMX_SERVICE_URL_KEY, jmxServiceUrl); + writer.addEntry(INSTANCE_NAME_KEY, instanceName); + return writer.getPacketBytes(); + } + + /** + * + * @return packet hash code + */ + @Override + public int hashCode() { + int hash = 1; + hash = hash * 31 + id.hashCode(); + hash = hash * 31 + jmxServiceUrl.hashCode(); + return hash; + } + + /** + * Compare two packets + * + * @param o - packet to compare + * @return either packet equals or not + */ + @Override + public boolean equals(Object o) { + + if (o == null || ! (o instanceof JdpJmxPacket) ){ + return false; + } + + JdpJmxPacket p = (JdpJmxPacket) o; + return Objects.equals(id, p.getId()) && Objects.equals(jmxServiceUrl, p.getJmxServiceUrl()); + } +} diff --git a/jdk/src/share/classes/sun/management/jdp/JdpPacket.java b/jdk/src/share/classes/sun/management/jdp/JdpPacket.java new file mode 100644 index 00000000000..ba0ec4f97ac --- /dev/null +++ b/jdk/src/share/classes/sun/management/jdp/JdpPacket.java @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2012, 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. + * + * 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. + */ + +package sun.management.jdp; + +import java.io.IOException; + +/** + * Packet to broadcast + * + *

Each packet have to contain MAGIC and PROTOCOL_VERSION in order to be + * recognized as a valid JDP packet.

+ * + *

Default implementation build packet as a set of UTF-8 encoded Key/Value pairs + * are stored as an ordered list of values, and are sent to the server + * in that order.

+ * + *

+ * Packet structure: + * + * 4 bytes JDP magic (0xC0FFE42) + * 2 bytes JDP protocol version (01) + * + * 2 bytes size of key + * x bytes key (UTF-8 encoded) + * 2 bytes size of value + * x bytes value (UTF-8 encoded) + * + * repeat as many times as necessary ... + *

+ */ +public interface JdpPacket { + + /** + * This method responsible to assemble packet and return a byte array + * ready to be sent across a Net. + * + * @return assembled packet as an array of bytes + * @throws IOException + */ + public byte[] getPacketData() throws IOException; + +} diff --git a/jdk/src/share/classes/sun/management/jdp/JdpPacketReader.java b/jdk/src/share/classes/sun/management/jdp/JdpPacketReader.java new file mode 100644 index 00000000000..9f3957ab5ce --- /dev/null +++ b/jdk/src/share/classes/sun/management/jdp/JdpPacketReader.java @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2012, 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. + * + * 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. + */ +package sun.management.jdp; + +import java.io.ByteArrayInputStream; +import java.io.DataInputStream; +import java.io.EOFException; +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +/** + * JdpPacketReader responsible for reading a packet

This class gets a byte + * array as it came from a Net, validates it and breaks a part

+ */ +public final class JdpPacketReader { + + private final DataInputStream pkt; + private Map pmap = null; + + /** + * Create packet reader, extract and check magic and version + * + * @param packet - packet received from a Net + * @throws JdpException + */ + public JdpPacketReader(byte[] packet) + throws JdpException { + ByteArrayInputStream bais = new ByteArrayInputStream(packet); + pkt = new DataInputStream(bais); + + try { + int magic = pkt.readInt(); + JdpGenericPacket.checkMagic(magic); + } catch (IOException e) { + throw new JdpException("Invalid JDP packet received, bad magic"); + } + + try { + short version = pkt.readShort(); + JdpGenericPacket.checkVersion(version); + } catch (IOException e) { + throw new JdpException("Invalid JDP packet received, bad protocol version"); + } + } + + /** + * Get next entry from packet + * + * @return the entry + * @throws EOFException + * @throws JdpException + */ + public String getEntry() + throws EOFException, JdpException { + + try { + short len = pkt.readShort(); + // Artificial setting the "len" field to Short.MAX_VALUE may cause a reader to allocate + // to much memory. Prevent this possible DOS attack. + if (len < 1 && len > pkt.available()) { + throw new JdpException("Broken JDP packet. Invalid entry length field."); + } + + byte[] b = new byte[len]; + if (pkt.read(b) != len) { + throw new JdpException("Broken JDP packet. Unable to read entry."); + } + return new String(b, "UTF-8"); + + } catch (EOFException e) { + throw e; + } catch (UnsupportedEncodingException ex) { + throw new JdpException("Broken JDP packet. Unable to decode entry."); + } catch (IOException e) { + throw new JdpException("Broken JDP packet. Unable to read entry."); + } + + + } + + /** + * return packet content as a key/value map + * + * @return map containing packet entries pair of entries treated as + * key,value + * @throws IOException + * @throws JdpException + */ + public Map getDiscoveryDataAsMap() + throws JdpException { + // return cached map if possible + if (pmap != null) { + return pmap; + } + + String key = null, value = null; + + final Map tmpMap = new HashMap<>(); + try { + while (true) { + key = getEntry(); + value = getEntry(); + tmpMap.put(key, value); + } + } catch (EOFException e) { + // EOF reached on reading value, report broken packet + // otherwise ignore it. + if (value == null) { + throw new JdpException("Broken JDP packet. Key without value." + key); + } + } + + pmap = Collections.unmodifiableMap(tmpMap); + return pmap; + } +} diff --git a/jdk/src/share/classes/sun/management/jdp/JdpPacketWriter.java b/jdk/src/share/classes/sun/management/jdp/JdpPacketWriter.java new file mode 100644 index 00000000000..7ebd002608c --- /dev/null +++ b/jdk/src/share/classes/sun/management/jdp/JdpPacketWriter.java @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2012, 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. + * + * 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. + */ +package sun.management.jdp; + +import java.io.ByteArrayOutputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +/** + * JdpPacketWriter responsible for writing a packet + *

This class assembles a set of key/value pairs to valid JDP packet, + * ready to be sent across a Net

+ */ +public final class JdpPacketWriter { + + private final ByteArrayOutputStream baos; + private final DataOutputStream pkt; + + /** + * Create a JDP packet, add mandatory magic and version headers + * + * @throws IOException + */ + public JdpPacketWriter() + throws IOException { + baos = new ByteArrayOutputStream(); + pkt = new DataOutputStream(baos); + + pkt.writeInt(JdpGenericPacket.getMagic()); + pkt.writeShort(JdpGenericPacket.getVersion()); + } + + /** + * Put string entry to packet + * + * @param entry - string to put (utf-8 encoded) + * @throws IOException + */ + public void addEntry(String entry) + throws IOException { + pkt.writeShort(entry.length()); + byte[] b = entry.getBytes("UTF-8"); + pkt.write(b); + } + + /** + * Put key/value pair to packet + * + * @param key - key to put (utf-8 encoded) + * @param val - value to put (utf-8 encoded) + * @throws IOException + */ + public void addEntry(String key, String val) + throws IOException { + /* Silently skip key if value is null. + * We don't need to distinguish between key missing + * and key has no value cases + */ + if (val != null) { + addEntry(key); + addEntry(val); + } + } + + /** + * Return assembled packet as a byte array + * + * @return packet bytes + */ + public byte[] getPacketBytes() { + return baos.toByteArray(); + } +} diff --git a/jdk/src/share/classes/sun/management/jdp/package-info.java b/jdk/src/share/classes/sun/management/jdp/package-info.java new file mode 100644 index 00000000000..e21e461214f --- /dev/null +++ b/jdk/src/share/classes/sun/management/jdp/package-info.java @@ -0,0 +1,55 @@ +/** + * Summary + * ------- + * + * Define a lightweight network protocol for discovering running and + * manageable Java processes within a network subnet. + * + * + * Description + * ----------- + * + * The protocol is lightweight multicast based, and works like a beacon, + * broadcasting the JMXService URL needed to connect to the external JMX + * agent if an application is started with appropriate parameters. + * + * The payload is structured like this: + * + * 4 bytes JDP magic (0xC0FFEE42) + * 2 bytes JDP protocol version (1) + * 2 bytes size of the next entry + * x bytes next entry (UTF-8 encoded) + * 2 bytes size of next entry + * ... Rinse and repeat... + * + * The payload will be parsed as even entries being keys, odd entries being + * values. + * + * The standard JDP packet contains four entries: + * + * - `DISCOVERABLE_SESSION_UUID` -- Unique id of the instance; this id changes every time + * the discovery protocol starts and stops + * + * - `MAIN_CLASS` -- The value of the `sun.java.command` property + * + * - `JMX_SERVICE_URL` -- The URL to connect to the JMX agent + * + * - `INSTANCE_NAME` -- The user-provided name of the running instance + * + * The protocol sends packets to 239.255.255.225:7095 by default. + * + * The protocol uses system properties to control it's behaviour: + * - `com.sun.management.jdp.port` -- override default port + * + * - `com.sun.management.jdp.address` -- override default address + * + * - `com.sun.management.jmxremote.autodiscovery` -- whether we should start autodiscovery or + * not. Autodiscovery starts if and only if following conditions are met: (autodiscovery is + * true OR (autodiscovery is not set AND jdp.port is set)) + * + * - `com.sun.management.jdp.ttl` -- set ttl for broadcast packet, default is 1 + * - `com.sun.management.jdp.pause` -- set broadcast interval in seconds default is 5 + * - `com.sun.management.jdp.source_addr` -- an address of interface to use for broadcast + */ + +package sun.management.jdp; diff --git a/jdk/test/sun/management/jdp/JdpClient.java b/jdk/test/sun/management/jdp/JdpClient.java new file mode 100644 index 00000000000..4a2348468b2 --- /dev/null +++ b/jdk/test/sun/management/jdp/JdpClient.java @@ -0,0 +1,160 @@ +/* + * Copyright (c) 2012, 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. + * + * 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. + */ + +import java.io.IOException; +import java.net.Inet6Address; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.NetworkInterface; +import java.net.ProtocolFamily; +import java.net.StandardProtocolFamily; +import java.net.StandardSocketOptions; +import java.nio.ByteBuffer; +import java.nio.channels.DatagramChannel; +import java.nio.channels.SelectionKey; +import java.nio.channels.Selector; +import java.util.Collections; +import java.util.Enumeration; +import sun.management.jdp.JdpException; +import sun.management.jdp.JdpJmxPacket; + +public class JdpClient { + + private static class PacketListener implements Runnable { + + private static final int BUFFER_LENGTH = 4096; + private final DatagramChannel channel; + private static int maxPacketCount = 1; + private static int maxEmptyPacketCount = 10; + + + PacketListener(DatagramChannel channel) { + this.channel = channel; + } + + @java.lang.Override + public void run() { + try { + Selector sel; + sel = Selector.open(); + channel.configureBlocking(false); + channel.register(sel, SelectionKey.OP_READ); + ByteBuffer buf = ByteBuffer.allocate(1024); + + int count = 1; + int emptyPacketsCount = 1; + + try { + while (true) { + + sel.selectedKeys().clear(); + buf.rewind(); + + sel.select(10 * 1000); + channel.receive(buf); + + if (buf.position() == 0 ){ + if (JdpDoSomething.getVerbose()){ + System.err.println("Empty packet received"); + } + if (++emptyPacketsCount > maxEmptyPacketCount){ + throw new RuntimeException("Test failed, maxEmptyPacketCount reached"); + } + + continue; + } + + buf.flip(); + byte[] dgramData = new byte[buf.remaining()]; + buf.get(dgramData); + + try { + JdpJmxPacket packet = new JdpJmxPacket(dgramData); + JdpDoSomething.printJdpPacket(packet); + if(++count > maxPacketCount){ + break; + } + } catch (JdpException e) { + e.printStackTrace(); + throw new RuntimeException("Test failed"); + } + + } + + System.out.println("OK: Test passed"); + + } finally { + sel.close(); + channel.close(); + } + } catch (IOException e) { + e.printStackTrace(); + throw new RuntimeException("Test failed"); + } + } + } + + public static void main(String[] args) { + try { + String discoveryPort = System.getProperty("com.sun.management.jdp.port"); + String discoveryAddress = System.getProperty("com.sun.management.jdp.address"); + if (discoveryAddress == null || discoveryPort == null) { + System.out.println("Test failed. address and port must be specified"); + return; + } + + int port = Integer.parseInt(discoveryPort); + InetAddress address = InetAddress.getByName(discoveryAddress); + + + ProtocolFamily family = (address instanceof Inet6Address) + ? StandardProtocolFamily.INET6 : StandardProtocolFamily.INET; + + DatagramChannel channel; + + channel = DatagramChannel.open(family); + channel.setOption(StandardSocketOptions.SO_REUSEADDR, true); + channel.bind(new InetSocketAddress(port)); + + Enumeration nets = NetworkInterface.getNetworkInterfaces(); + for (NetworkInterface interf : Collections.list(nets)) { + if (interf.supportsMulticast()) { + try { + channel.join(address, interf); + } catch (IOException e) { + // Skip not configured interfaces + } + } + } + + PacketListener listener = new PacketListener(channel); + new Thread(listener, "Jdp Client").start(); + + } catch (RuntimeException e){ + System.out.println("Test failed."); + } catch (Exception e) { + e.printStackTrace(); + System.out.println("Test failed. unexpected error " + e); + } + } +} diff --git a/jdk/test/sun/management/jdp/JdpDoSomething.java b/jdk/test/sun/management/jdp/JdpDoSomething.java new file mode 100644 index 00000000000..ad9366cbaa4 --- /dev/null +++ b/jdk/test/sun/management/jdp/JdpDoSomething.java @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2012, 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. + * + * 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. + */ + +import java.io.File; +import java.io.IOException; +import java.io.RandomAccessFile; +import java.util.Objects; + +import sun.management.jdp.JdpJmxPacket; +import sun.management.jdp.JdpException; + +public class JdpDoSomething { + + private static final String lockFileName = "JdpDoSomething.lck"; + private static final boolean verbose=false; + + public static boolean getVerbose(){ + return verbose; + } + + public static void printJdpPacket(JdpJmxPacket p) { + if (getVerbose()) { + try { + RandomAccessFile f = new RandomAccessFile("out.dmp", "rw"); + f.write(p.getPacketData()); + f.close(); + } catch (IOException e) { + System.out.println("Can't write a dump file: " + e); + } + + System.out.println("Id: " + p.getId()); + System.out.println("Jmx: " + p.getJmxServiceUrl()); + System.out.println("Main: " + p.getMainClass()); + System.out.println("InstanceName: " + p.getInstanceName()); + + System.out.flush(); + } + } + + public static void compaireJdpPacketEx(JdpJmxPacket p1, JdpJmxPacket p2) + throws JdpException { + + if (!Objects.equals(p1, p1)) { + throw new JdpException("Packet mismatch error"); + } + + if (!Objects.equals(p1.getMainClass(), p2.getMainClass())) { + throw new JdpException("Packet mismatch error (main class)"); + } + + if (!Objects.equals(p1.getInstanceName(), p2.getInstanceName())) { + throw new JdpException("Packet mismatch error (instance name)"); + } + } + + public static void doSomething() { + try { + File lockFile = new File(lockFileName); + lockFile.createNewFile(); + + while (lockFile.exists()) { + long datetime = lockFile.lastModified(); + long epoch = System.currentTimeMillis() / 1000; + + // Don't allow test app to run more than an hour + if (epoch - datetime > 3600) { + System.err.println("Lock is too old. Aborting"); + return; + } + Thread.sleep(1); + } + + } catch (Throwable e) { + System.err.println("Something bad happens:" + e); + } + } + + public static void main(String args[]) throws Exception { + System.err.println("main enter"); + doSomething(); + System.err.println("main exit"); + } +} diff --git a/jdk/test/sun/management/jdp/JdpTest.sh b/jdk/test/sun/management/jdp/JdpTest.sh new file mode 100644 index 00000000000..2aded729953 --- /dev/null +++ b/jdk/test/sun/management/jdp/JdpTest.sh @@ -0,0 +1,323 @@ +#!/bin/sh + +# Copyright (c) 2011, 2012 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. +# +# 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. + +# @test +# @bug 7169888 +# @build JdpUnitTest JdpClient JdpDoSomething +# @run shell JdpTest.sh --jtreg --no-compile +# @summary No word Failed expected in the test output + +_verbose=no +_jtreg=no +_compile=yes + +# temporary disable jcmd related tests +# _testsuite="01,02,03,04,05" +_testsuite="01,02,04" + +_pwd=`pwd` + +_testclasses=".classes" +_testsrc="${_pwd}" +_lockFileName="JdpDoSomething.lck" + +_logname=".classes/output.txt" +_last_pid="" + + +_compile(){ + + if [ ! -e ${_testclasses} ] + then + mkdir -p ${_testclasses} + fi + + rm -f ${_testclasses}/*.class + + # Compile testcase + ${TESTJAVA}/bin/javac -d ${_testclasses} JdpUnitTest.java \ + JdpDoSomething.java \ + JdpClient.java + + + if [ ! -e ${_testclasses}/JdpDoSomething.class -o ! -e ${_testclasses}/JdpClient.class -o ! -e ${_testclasses}/JdpUnitTest.class ] + then + echo "ERROR: Can't compile" + exit -1 + fi +} + + +_app_start(){ + + testappname=$1 + shift + + ${TESTJAVA}/bin/java -server $* -cp ${_testclasses} ${testappname} >> ${_logname} 2>&1 & + _last_pid=$! + + npid=`_get_pid` + if [ "${npid}" = "" ] + then + echo "ERROR: Test app not started" + if [ "${_jtreg}" = "yes" ] + then + exit -1 + fi + fi +} + +_get_pid(){ + ${TESTJAVA}/bin/jps | sed -n "/Jdp/s/ .*//p" +} + +_app_stop(){ + rm ${_lockFileName} + +# wait until VM is actually shuts down + while true + do + npid=`_get_pid` + if [ "${npid}" = "" ] + then + break + fi + sleep 1 + done +} + +_testme(){ + ${TESTJAVA}/bin/java \ + -cp ${_testclasses} \ + $* \ + -Dcom.sun.management.jdp.port=7095 \ + -Dcom.sun.management.jdp.address=239.255.255.225 \ + JdpClient + +} + + +_jcmd(){ + ${TESTJAVA}/bin/jcmd JdpDoSomething $* > /dev/null 2>/dev/null +} + + +_echo(){ + echo "$*" + echo "$*" >> ${_logname} +} + +# ============= TESTS ====================================== + +test_01(){ + + _echo "**** Test one ****" + + _app_start JdpUnitTest \ + -Dcom.sun.management.jdp.port=7095 \ + -Dcom.sun.management.jdp.address=239.255.255.225 \ + -Dcom.sun.management.jdp.pause=5 + + res=`_testme` + + case "${res}" in + OK*) + _echo "Passed" + ;; + *) + _echo "Failed!" + ;; + esac + + _app_stop +} + +test_02(){ + + _echo "**** Test two ****" + + _app_start JdpDoSomething \ + -Dcom.sun.management.jdp.port=7095 \ + -Dcom.sun.management.jdp.address=239.255.255.225 \ + -Dcom.sun.management.jdp.pause=5 \ + -Dcom.sun.management.jmxremote.port=4545 \ + -Dcom.sun.management.jmxremote.authenticate=false \ + -Dcom.sun.management.jmxremote.ssl=false + + res=`_testme` + + case "${res}" in + OK*) + _echo "Passed" + ;; + *) + _echo "Failed!" + ;; + esac + + _app_stop +} + +test_03(){ + + _echo "**** Test three ****" + + _app_start JdpDoSomething + + _jcmd ManagementAgent.start\ + jdp.port=7095 \ + jdp.address=239.255.255.225 \ + jdp.pause=5 \ + jmxremote.port=4545 \ + jmxremote.authenticate=false \ + jmxremote.ssl=false + + res=`_testme` + + case "${res}" in + OK*) + _echo "Passed" + ;; + *) + _echo "Failed!" + ;; + esac + + _app_stop +} + +test_04(){ + + _echo "**** Test four ****" + + _app_start JdpDoSomething \ + -Dcom.sun.management.jmxremote.autodiscovery=true \ + -Dcom.sun.management.jmxremote.port=4545 \ + -Dcom.sun.management.jmxremote.authenticate=false \ + -Dcom.sun.management.jmxremote.ssl=false + + res=`_testme` + + case "${res}" in + OK*) + _echo "Passed" + ;; + *) + _echo "Failed!" + ;; + esac + + _app_stop +} + +test_05(){ + + _echo "**** Test five ****" + + _app_start JdpDoSomething + + _jcmd ManagementAgent.start\ + jmxremote.autodiscovery=true \ + jmxremote.port=4545 \ + jmxremote.authenticate=false \ + jmxremote.ssl=false + + + res=`_testme` + + case "${res}" in + OK*) + _echo "Passed" + ;; + *) + _echo "Failed!" + ;; + esac + + _app_stop +} + + +# ============= MAIN ======================================= + +if [ "x${TESTJAVA}" = "x" ] +then + echo "TESTJAVA env have to be set" + exit +fi + +#------------------------------------------------------------------------------ +# reading parameters + +for parm in "$@" +do + case $parm in + --verbose) _verbose=yes ;; + --jtreg) _jtreg=yes ;; + --no-compile) _compile=no ;; + --testsuite=*) _testsuite=`_echo $parm | sed "s,^--.*=\(.*\),\1,"` ;; + *) + echo "Undefined parameter $parm. Try --help for help" + exit + ;; + esac +done + +if [ ${_compile} = "yes" ] +then + _compile +fi + +if [ ${_jtreg} = "yes" ] +then + _testclasses=${TESTCLASSES} + _testsrc=${TESTSRC} + _logname="output.txt" +fi + +# Make sure _tesclasses is absolute path +tt=`echo ${_testclasses} | sed -e 's,/,,'` +if [ ${tt} = ${_testclasses} ] +then + _testclasses="${_pwd}/${_testclasses}" +fi + +_policyname="${_testclasses}/policy" + +rm -f ${_logname} +rm -f ${_policyname} + +if [ -e ${_testsrc}/policy.tpl ] +then + +cat ${_testsrc}/policy.tpl | \ + sed -e "s,@_TESTCLASSES@,${_testclasses},g" -e "s,@TESTJAVA@,${TESTJAVA},g" \ + > ${_policyname} + +fi + +# Local mode tests +for i in `echo ${_testsuite} | sed -e "s/,/ /g"` +do + test_${i} +done diff --git a/jdk/test/sun/management/jdp/JdpUnitTest.java b/jdk/test/sun/management/jdp/JdpUnitTest.java new file mode 100644 index 00000000000..fed4ae216c2 --- /dev/null +++ b/jdk/test/sun/management/jdp/JdpUnitTest.java @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2012, 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. + * + * 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. + */ + +import java.io.IOException; +import java.net.InetAddress; +import java.util.UUID; + +import sun.management.jdp.JdpController; +import sun.management.jdp.JdpPacket; +import sun.management.jdp.JdpJmxPacket; +import sun.management.jdp.JdpException; + +public class JdpUnitTest { + + /** + * This test tests that complete packet is build correctly + */ + public static void PacketBuilderTest() + throws IOException, JdpException { + + /* Complete packet test */ + { + JdpJmxPacket p1 = new JdpJmxPacket(UUID.randomUUID(), "fake://unit-test"); + p1.setMainClass("FakeUnitTest"); + p1.setInstanceName("Fake"); + byte[] b = p1.getPacketData(); + + JdpJmxPacket p2 = new JdpJmxPacket(b); + JdpDoSomething.printJdpPacket(p1); + JdpDoSomething.compaireJdpPacketEx(p1, p2); + } + + /*Missed field packet test*/ + { + JdpJmxPacket p1 = new JdpJmxPacket(UUID.randomUUID(), "fake://unit-test"); + p1.setMainClass("FakeUnitTest"); + p1.setInstanceName(null); + byte[] b = p1.getPacketData(); + + JdpJmxPacket p2 = new JdpJmxPacket(b); + JdpDoSomething.printJdpPacket(p1); + JdpDoSomething.compaireJdpPacketEx(p1, p2); + } + + System.out.println("OK: Test passed"); + + } + + public static void startFakeDiscoveryService() + throws IOException, JdpException { + + String discoveryPort = System.getProperty("com.sun.management.jdp.port"); + String discoveryAddress = System.getProperty("com.sun.management.jdp.address"); + InetAddress address = InetAddress.getByName(discoveryAddress); + int port = Integer.parseInt(discoveryPort); + JdpController.startDiscoveryService(address, port, "FakeDiscovery", "fake://unit-test"); + } + + public static void main(String[] args) { + try { + PacketBuilderTest(); + startFakeDiscoveryService(); + JdpDoSomething.doSomething(); + + } catch (Throwable e) { + e.printStackTrace(); + System.out.println("Test failed. unexpected error " + e); + } + } +} From 302a583c08b64a9ea34b61290f529769698061f7 Mon Sep 17 00:00:00 2001 From: Dmitry Samersoff Date: Sun, 3 Feb 2013 22:28:08 +0400 Subject: [PATCH 171/210] 8002048: Protocol to discovery of manageable Java processes on a network Introduce a protocol to discover manageble Java instances across a network subnet, JDP Reviewed-by: sla, dfuchs --- .../share/vm/services/diagnosticCommand.cpp | 44 +++++++++++++++++-- .../share/vm/services/diagnosticCommand.hpp | 10 +++++ 2 files changed, 51 insertions(+), 3 deletions(-) diff --git a/hotspot/src/share/vm/services/diagnosticCommand.cpp b/hotspot/src/share/vm/services/diagnosticCommand.cpp index 6bdc059f35b..df01ec83b19 100644 --- a/hotspot/src/share/vm/services/diagnosticCommand.cpp +++ b/hotspot/src/share/vm/services/diagnosticCommand.cpp @@ -464,7 +464,32 @@ JMXStartRemoteDCmd::JMXStartRemoteDCmd(outputStream *output, bool heap_allocated _jmxremote_ssl_config_file ("jmxremote.ssl.config.file", - "set com.sun.management.jmxremote.ssl_config_file", "STRING", false) + "set com.sun.management.jmxremote.ssl_config_file", "STRING", false), + +// JDP Protocol support + _jmxremote_autodiscovery + ("jmxremote.autodiscovery", + "set com.sun.management.jmxremote.autodiscovery", "STRING", false), + + _jdp_port + ("jdp.port", + "set com.sun.management.jdp.port", "INT", false), + + _jdp_address + ("jdp.address", + "set com.sun.management.jdp.address", "STRING", false), + + _jdp_source_addr + ("jdp.source_addr", + "set com.sun.management.jdp.source_addr", "STRING", false), + + _jdp_ttl + ("jdp.ttl", + "set com.sun.management.jdp.ttl", "INT", false), + + _jdp_pause + ("jdp.pause", + "set com.sun.management.jdp.pause", "INT", false) { _dcmdparser.add_dcmd_option(&_config_file); @@ -480,6 +505,12 @@ JMXStartRemoteDCmd::JMXStartRemoteDCmd(outputStream *output, bool heap_allocated _dcmdparser.add_dcmd_option(&_jmxremote_ssl_enabled_protocols); _dcmdparser.add_dcmd_option(&_jmxremote_ssl_need_client_auth); _dcmdparser.add_dcmd_option(&_jmxremote_ssl_config_file); + _dcmdparser.add_dcmd_option(&_jmxremote_autodiscovery); + _dcmdparser.add_dcmd_option(&_jdp_port); + _dcmdparser.add_dcmd_option(&_jdp_address); + _dcmdparser.add_dcmd_option(&_jdp_source_addr); + _dcmdparser.add_dcmd_option(&_jdp_ttl); + _dcmdparser.add_dcmd_option(&_jdp_pause); } @@ -494,7 +525,6 @@ int JMXStartRemoteDCmd::num_arguments() { } } - void JMXStartRemoteDCmd::execute(TRAPS) { ResourceMark rm(THREAD); HandleMark hm(THREAD); @@ -524,7 +554,9 @@ void JMXStartRemoteDCmd::execute(TRAPS) { // file. #define PUT_OPTION(a) \ if ( (a).is_set() ){ \ - options.print("%scom.sun.management.%s=%s", comma, (a).name(), (a).value()); \ + options.print(\ + ( *((a).type()) == 'I' ) ? "%scom.sun.management.%s=%d" : "%scom.sun.management.%s=%s",\ + comma, (a).name(), (a).value()); \ comma[0] = ','; \ } @@ -541,6 +573,12 @@ void JMXStartRemoteDCmd::execute(TRAPS) { PUT_OPTION(_jmxremote_ssl_enabled_protocols); PUT_OPTION(_jmxremote_ssl_need_client_auth); PUT_OPTION(_jmxremote_ssl_config_file); + PUT_OPTION(_jmxremote_autodiscovery); + PUT_OPTION(_jdp_port); + PUT_OPTION(_jdp_address); + PUT_OPTION(_jdp_source_addr); + PUT_OPTION(_jdp_ttl); + PUT_OPTION(_jdp_pause); #undef PUT_OPTION diff --git a/hotspot/src/share/vm/services/diagnosticCommand.hpp b/hotspot/src/share/vm/services/diagnosticCommand.hpp index 10b7214f17a..b9dec46e096 100644 --- a/hotspot/src/share/vm/services/diagnosticCommand.hpp +++ b/hotspot/src/share/vm/services/diagnosticCommand.hpp @@ -257,6 +257,16 @@ class JMXStartRemoteDCmd : public DCmdWithParser { DCmdArgument _jmxremote_ssl_need_client_auth; DCmdArgument _jmxremote_ssl_config_file; + // JDP support + // Keep autodiscovery char* not bool to pass true/false + // as property value to java level. + DCmdArgument _jmxremote_autodiscovery; + DCmdArgument _jdp_port; + DCmdArgument _jdp_address; + DCmdArgument _jdp_source_addr; + DCmdArgument _jdp_ttl; + DCmdArgument _jdp_pause; + public: JMXStartRemoteDCmd(outputStream *output, bool heap_allocated); From 812262d16bf42a690ddbca9e965bb5ebf5788e34 Mon Sep 17 00:00:00 2001 From: Harold Seigel Date: Sun, 3 Feb 2013 16:49:16 -0500 Subject: [PATCH 172/210] 7197672: There are issues with shared data on windows On Windows, set rw protection on the CDS file just before removing it. Reviewed-by: dcubed, iklam --- hotspot/src/share/vm/memory/filemap.cpp | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/hotspot/src/share/vm/memory/filemap.cpp b/hotspot/src/share/vm/memory/filemap.cpp index fe0958073e3..fec0957f145 100644 --- a/hotspot/src/share/vm/memory/filemap.cpp +++ b/hotspot/src/share/vm/memory/filemap.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2013, 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 @@ -210,13 +210,14 @@ void FileMapInfo::open_for_write() { tty->print_cr(" %s", _full_path); } - // Remove the existing file in case another process has it open. - remove(_full_path); -#ifdef _WINDOWS // if 0444 is used on Windows, then remove() will fail. - int fd = open(_full_path, O_RDWR | O_CREAT | O_TRUNC | O_BINARY, 0744); -#else - int fd = open(_full_path, O_RDWR | O_CREAT | O_TRUNC | O_BINARY, 0444); +#ifdef _WINDOWS // On Windows, need WRITE permission to remove the file. + chmod(_full_path, _S_IREAD | _S_IWRITE); #endif + + // Use remove() to delete the existing file because, on Unix, this will + // allow processes that have it open continued access to the file. + remove(_full_path); + int fd = open(_full_path, O_RDWR | O_CREAT | O_TRUNC | O_BINARY, 0444); if (fd < 0) { fail_stop("Unable to create shared archive file %s.", _full_path); } From f13dbb00cfa1bbcd5f2ae21949c2259b14fcfbf5 Mon Sep 17 00:00:00 2001 From: Roland Westrelin Date: Mon, 4 Feb 2013 09:11:21 +0100 Subject: [PATCH 173/210] 8005114: VM is crashing in ciKlass*ciObjArrayKlass::element_klass() if metaspaces are full Missing test for loaded klass in c1 Reviewed-by: kvn --- hotspot/src/share/vm/c1/c1_Instruction.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hotspot/src/share/vm/c1/c1_Instruction.cpp b/hotspot/src/share/vm/c1/c1_Instruction.cpp index 628091ce315..985cb098e6f 100644 --- a/hotspot/src/share/vm/c1/c1_Instruction.cpp +++ b/hotspot/src/share/vm/c1/c1_Instruction.cpp @@ -188,7 +188,7 @@ ciType* LoadIndexed::exact_type() const { ciType* LoadIndexed::declared_type() const { ciType* array_type = array()->declared_type(); - if (array_type == NULL) { + if (array_type == NULL || !array_type->is_loaded()) { return NULL; } assert(array_type->is_array_klass(), "what else?"); From 2708349f7ce97aedb63113748e31b749ac16ae5a Mon Sep 17 00:00:00 2001 From: Erik Joelsson Date: Mon, 4 Feb 2013 10:53:38 +0100 Subject: [PATCH 174/210] 8007093: build-infra: Make should fail if spec is older than configure files Reviewed-by: tbell --- common/makefiles/Main.gmk | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/common/makefiles/Main.gmk b/common/makefiles/Main.gmk index c96747f090c..ded49ff55e4 100644 --- a/common/makefiles/Main.gmk +++ b/common/makefiles/Main.gmk @@ -75,7 +75,14 @@ ifeq ($(OPENJDK_TARGET_OS)-$(OPENJDK_TARGET_CPU_BITS),solaris-64) all: overlay-images endif -start-make: +# Setup a rule for SPEC file that fails if executed. This check makes sure the configuration +# is up to date after changes to configure +$(SPEC): $(wildcard $(SRC_ROOT)/common/autoconf/*) + @$(ECHO) ERROR: $(SPEC) is not up to date + @$(ECHO) Please rerun configure! + @if test "x$(IGNORE_OLD_CONFIG)" != "xtrue"; then exit 1; fi + +start-make: $(SPEC) @$(call AtMakeStart) langtools: langtools-only From fe5aed65c281040a2a304423d929ee249e04084c Mon Sep 17 00:00:00 2001 From: Erik Joelsson Date: Mon, 4 Feb 2013 10:58:26 +0100 Subject: [PATCH 175/210] 8007268: build-infra: configure reports Solaris needs gcc for deploy, but logs don't indicate it's used Reviewed-by: tbell, katleman --- jdk/make/common/shared/Sanity.gmk | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/jdk/make/common/shared/Sanity.gmk b/jdk/make/common/shared/Sanity.gmk index c73a3b755d6..c4a96d73c5f 100644 --- a/jdk/make/common/shared/Sanity.gmk +++ b/jdk/make/common/shared/Sanity.gmk @@ -1486,26 +1486,6 @@ endif ###################################################### sane-gcc-compiler: ifndef OPENJDK - ifeq ($(PLATFORM), solaris) - @if [ -r $(GCC_COMPILER_PATH) ]; then \ - if [ ! "$(GCC_VER)" = $(REQUIRED_GCC_VER) ]; then \ - $(ECHO) "ERROR: The Solaris GCC compiler version must be $(REQUIRED_GCC_VER). \n" \ - " You are using the following compiler version: $(GCC_VER) \n" \ - " The compiler was obtained from the following location: \n" \ - " $(GCC_COMPILER_PATH) \n" \ - " Please change your compiler. \n" \ - "" >> $(ERROR_FILE) ; \ - fi \ - else \ - $(ECHO) "ERROR: You do not have a valid GCC_COMPILER_PATH setting. \n" \ - " Please check your access to \n" \ - " $(GCC_COMPILER_PATH) \n" \ - " and/or check your value of ALT_GCC_COMPILER_PATH. \n" \ - " This will affect you if you build the plugin target. \n" \ - "" >> $(ERROR_FILE) ; \ - fi - endif - ifeq ($(PLATFORM), linux) ifeq ($(ARCH_DATA_MODEL), 32) ifdef ALT_GCC29_COMPILER_PATH From 2b800f01d965c164badc9b4ea2286d30717ce032 Mon Sep 17 00:00:00 2001 From: Erik Joelsson Date: Mon, 4 Feb 2013 11:02:03 +0100 Subject: [PATCH 176/210] 8007275: build-infra: Create final-images target Reviewed-by: tbell --- common/autoconf/generated-configure.sh | 11 +++++-- common/makefiles/Jprt.gmk | 45 ++++++++++++++++++++------ 2 files changed, 44 insertions(+), 12 deletions(-) diff --git a/common/autoconf/generated-configure.sh b/common/autoconf/generated-configure.sh index 2415b520802..d53e56ec100 100644 --- a/common/autoconf/generated-configure.sh +++ b/common/autoconf/generated-configure.sh @@ -3723,7 +3723,7 @@ fi #CUSTOM_AUTOCONF_INCLUDE # Do not change or remove the following line, it is needed for consistency checks: -DATE_WHEN_GENERATED=1359376859 +DATE_WHEN_GENERATED=1359971740 ############################################################################### # @@ -10778,7 +10778,8 @@ if test "x$with_milestone" = xyes; then as_fn_error $? "Milestone must have a value" "$LINENO" 5 elif test "x$with_milestone" != x; then MILESTONE="$with_milestone" -else +fi +if test "x$MILESTONE" = x; then MILESTONE=internal fi @@ -29247,6 +29248,12 @@ fi fi +# AC_PATH_XTRA creates X_LIBS and sometimes adds -R flags. When cross compiling +# this doesn't make sense so we remove it. +if test "x$COMPILE_TYPE" = xcross; then + X_LIBS=`$ECHO $X_LIBS | $SED 's/-R \{0,1\}[^ ]*//g'` +fi + if test "x$no_x" = xyes && test "x$X11_NOT_NEEDED" != xyes; then # Print a helpful message on how to acquire the necessary build dependency. diff --git a/common/makefiles/Jprt.gmk b/common/makefiles/Jprt.gmk index b8bc418fbae..c70cf8872b4 100644 --- a/common/makefiles/Jprt.gmk +++ b/common/makefiles/Jprt.gmk @@ -179,27 +179,52 @@ jprt_bundle: $(JPRT_ARCHIVE_BUNDLE) $(JPRT_ARCHIVE_BUNDLE): bundles $(MKDIR) -p $(@D) $(RM) $@ - $(CP) $(BUILD_OUTPUT)/bundles/j2sdk-image.zip $@ + $(CP) $(BUILD_OUTPUT)/bundles/$(JDK_IMAGE_SUBDIR).zip $@ -# This target must be called in the context of a SPEC file -bundles: all +ifeq ($(OPENJDK_TARGET_OS)-$(OPENJDK_TARGET_CPU_BITS),solaris-64) + SRC_JDK_IMAGE_DIR := $(JDK_OVERLAY_IMAGE_DIR) + SRC_JRE_IMAGE_DIR := $(JRE_OVERLAY_IMAGE_DIR) +else + SRC_JDK_IMAGE_DIR := $(JDK_IMAGE_DIR) + SRC_JRE_IMAGE_DIR := $(JRE_IMAGE_DIR) +endif +SRC_JDK_BUNDLE_DIR := $(JDK_BUNDLE_DIR) +SRC_JRE_BUNDLE_DIR := $(JRE_BUNDLE_DIR) + +# Bundle up the images +bundles: all bundles-only +bundles-only: start-make @$(call TargetEnter) $(MKDIR) -p $(BUILD_OUTPUT)/bundles -ifeq ($(OPENJDK_TARGET_OS)-$(OPENJDK_TARGET_CPU_BITS),solaris-64) - $(CD) $(JDK_OVERLAY_IMAGE_DIR) && $(ZIP) -q -r $(BUILD_OUTPUT)/bundles/j2sdk-image.zip . - $(CD) $(JRE_OVERLAY_IMAGE_DIR) && $(ZIP) -q -r $(BUILD_OUTPUT)/bundles/j2re-image.zip . -else - $(CD) $(JDK_IMAGE_DIR) && $(ZIP) -q -r $(BUILD_OUTPUT)/bundles/j2sdk-image.zip . - $(CD) $(JRE_IMAGE_DIR) && $(ZIP) -q -r $(BUILD_OUTPUT)/bundles/j2re-image.zip . + $(CD) $(SRC_JDK_IMAGE_DIR) && $(ZIP) -q -r $(BUILD_OUTPUT)/bundles/$(JDK_IMAGE_SUBDIR).zip . + $(CD) $(SRC_JRE_IMAGE_DIR) && $(ZIP) -q -r $(BUILD_OUTPUT)/bundles/$(JRE_IMAGE_SUBDIR).zip . if [ -d $(BUILD_OUTPUT)/install/bundles ] ; then \ $(CD) $(BUILD_OUTPUT)/install/bundles && $(ZIP) -q -r $(JPRT_ARCHIVE_INSTALL_BUNDLE) . ; \ fi + @$(call TargetExit) + +# Copy images to one unified location regardless of platform etc. +final-images: all final-images-only +final-images-only: start-make + @$(call TargetEnter) + $(RM) -r $(BUILD_OUTPUT)/final-images + $(MKDIR) -p $(BUILD_OUTPUT)/final-images/$(JDK_IMAGE_SUBDIR) + $(MKDIR) -p $(BUILD_OUTPUT)/final-images/$(JRE_IMAGE_SUBDIR) + $(CP) -R -P $(SRC_JDK_IMAGE_DIR)/* $(BUILD_OUTPUT)/final-images/$(JDK_IMAGE_SUBDIR)/ + $(CP) -R -P $(SRC_JRE_IMAGE_DIR)/* $(BUILD_OUTPUT)/final-images/$(JRE_IMAGE_SUBDIR)/ +ifeq ($(OPENJDK_TARGET_OS),macosx) + $(MKDIR) -p $(BUILD_OUTPUT)/final-images/$(JDK_BUNDLE_SUBDIR) + $(MKDIR) -p $(BUILD_OUTPUT)/final-images/$(JRE_BUNDLE_SUBDIR) + $(CP) -R -P $(SRC_JDK_BUNDLE_DIR)/* $(BUILD_OUTPUT)/final-images/$(JDK_BUNDLE_SUBDIR)/ + $(CP) -R -P $(SRC_JRE_BUNDLE_DIR)/* $(BUILD_OUTPUT)/final-images/$(JRE_BUNDLE_SUBDIR)/ endif @$(call TargetExit) + # Keep track of phony targets PHONY_LIST += jprt_build_product jprt_build_fastdebug jprt_build_debug \ - jprt_build_generic bundles jprt_bundle + jprt_build_generic bundles jprt_bundle \ + final-images final-images-only ########################################################################### # Phony targets From eaa663b2412290c3006d64124f3cf88e917a3a08 Mon Sep 17 00:00:00 2001 From: Mikael Vidstedt Date: Mon, 4 Feb 2013 10:28:39 -0800 Subject: [PATCH 177/210] 8007403: Incorrect format arguments in adlparse.cpp Reviewed-by: kvn, twisti --- hotspot/src/share/vm/adlc/adlparse.cpp | 54 +++++++++++++------------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/hotspot/src/share/vm/adlc/adlparse.cpp b/hotspot/src/share/vm/adlc/adlparse.cpp index 6d08eab8010..04fb735c38c 100644 --- a/hotspot/src/share/vm/adlc/adlparse.cpp +++ b/hotspot/src/share/vm/adlc/adlparse.cpp @@ -168,7 +168,7 @@ void ADLParser::instr_parse(void) { // Check for block delimiter if ( (_curchar != '%') || ( next_char(), (_curchar != '{')) ) { - parse_err(SYNERR, "missing '%{' in instruction definition\n"); + parse_err(SYNERR, "missing '%%{' in instruction definition\n"); return; } next_char(); // Maintain the invariant @@ -253,7 +253,7 @@ void ADLParser::instr_parse(void) { } while(_curchar != '%'); next_char(); if (_curchar != '}') { - parse_err(SYNERR, "missing '%}' in instruction definition\n"); + parse_err(SYNERR, "missing '%%}' in instruction definition\n"); return; } // Check for "Set" form of chain rule @@ -423,7 +423,7 @@ void ADLParser::oper_parse(void) { skipws(); // Check for block delimiter if ((_curchar != '%') || (*(_ptr+1) != '{')) { // If not open block - parse_err(SYNERR, "missing '%c{' in operand definition\n","%"); + parse_err(SYNERR, "missing '%%{' in operand definition\n"); return; } next_char(); next_char(); // Skip over "%{" symbol @@ -483,7 +483,7 @@ void ADLParser::oper_parse(void) { } while(_curchar != '%'); next_char(); if (_curchar != '}') { - parse_err(SYNERR, "missing '%}' in operand definition\n"); + parse_err(SYNERR, "missing '%%}' in operand definition\n"); return; } // Add operand to tail of operand list @@ -1324,7 +1324,7 @@ void ADLParser::pipe_parse(void) { // Check for block delimiter if ( (_curchar != '%') || ( next_char(), (_curchar != '{')) ) { - parse_err(SYNERR, "missing '%{' in pipeline definition\n"); + parse_err(SYNERR, "missing '%%{' in pipeline definition\n"); return; } next_char(); // Maintain the invariant @@ -1341,7 +1341,7 @@ void ADLParser::pipe_parse(void) { skipws(); if ( (_curchar != '%') || ( next_char(), (_curchar != '{')) ) { - parse_err(SYNERR, "expected '%{'\n"); + parse_err(SYNERR, "expected '%%{'\n"); return; } next_char(); skipws(); @@ -1397,7 +1397,7 @@ void ADLParser::pipe_parse(void) { skipws(); if ( (_curchar != '%') || ( next_char(), (_curchar != '{')) ) { - parse_err(SYNERR, "expected '%{'\n"); + parse_err(SYNERR, "expected '%%{'\n"); return; } next_char(); skipws(); @@ -1586,7 +1586,7 @@ void ADLParser::pipe_parse(void) { if ( (_curchar != '%') || ( next_char(), (_curchar != '}')) ) { - parse_err(SYNERR, "expected '%}', found \"%c\"\n", _curchar); + parse_err(SYNERR, "expected '%%}', found \"%c\"\n", _curchar); } next_char(); skipws(); @@ -1612,7 +1612,7 @@ void ADLParser::pipe_parse(void) { next_char(); if (_curchar != '}') { - parse_err(SYNERR, "missing \"%}\" in pipeline definition\n"); + parse_err(SYNERR, "missing \"%%}\" in pipeline definition\n"); return; } @@ -1775,7 +1775,7 @@ void ADLParser::pipe_class_parse(PipelineForm &pipeline) { // Check for block delimiter if ( (_curchar != '%') || ( next_char(), (_curchar != '{')) ) { - parse_err(SYNERR, "missing \"%{\" in pipe_class definition\n"); + parse_err(SYNERR, "missing \"%%{\" in pipe_class definition\n"); return; } next_char(); @@ -2062,7 +2062,7 @@ void ADLParser::pipe_class_parse(PipelineForm &pipeline) { next_char(); if (_curchar != '}') { - parse_err(SYNERR, "missing \"%}\" in pipe_class definition\n"); + parse_err(SYNERR, "missing \"%%}\" in pipe_class definition\n"); return; } @@ -3341,12 +3341,12 @@ Interface *ADLParser::mem_interface_parse(void) { char *disp = NULL; if (_curchar != '%') { - parse_err(SYNERR, "Missing '%{' for 'interface' block.\n"); + parse_err(SYNERR, "Missing '%%{' for 'interface' block.\n"); return NULL; } next_char(); // Skip '%' if (_curchar != '{') { - parse_err(SYNERR, "Missing '%{' for 'interface' block.\n"); + parse_err(SYNERR, "Missing '%%{' for 'interface' block.\n"); return NULL; } next_char(); // Skip '{' @@ -3354,7 +3354,7 @@ Interface *ADLParser::mem_interface_parse(void) { do { char *field = get_ident(); if (field == NULL) { - parse_err(SYNERR, "Expected keyword, base|index|scale|disp, or '%}' ending interface.\n"); + parse_err(SYNERR, "Expected keyword, base|index|scale|disp, or '%%}' ending interface.\n"); return NULL; } if ( strcmp(field,"base") == 0 ) { @@ -3370,13 +3370,13 @@ Interface *ADLParser::mem_interface_parse(void) { disp = interface_field_parse(); } else { - parse_err(SYNERR, "Expected keyword, base|index|scale|disp, or '%}' ending interface.\n"); + parse_err(SYNERR, "Expected keyword, base|index|scale|disp, or '%%}' ending interface.\n"); return NULL; } } while( _curchar != '%' ); next_char(); // Skip '%' if ( _curchar != '}' ) { - parse_err(SYNERR, "Missing '%}' for 'interface' block.\n"); + parse_err(SYNERR, "Missing '%%}' for 'interface' block.\n"); return NULL; } next_char(); // Skip '}' @@ -3403,12 +3403,12 @@ Interface *ADLParser::cond_interface_parse(void) { const char *greater_format = "gt"; if (_curchar != '%') { - parse_err(SYNERR, "Missing '%{' for 'cond_interface' block.\n"); + parse_err(SYNERR, "Missing '%%{' for 'cond_interface' block.\n"); return NULL; } next_char(); // Skip '%' if (_curchar != '{') { - parse_err(SYNERR, "Missing '%{' for 'cond_interface' block.\n"); + parse_err(SYNERR, "Missing '%%{' for 'cond_interface' block.\n"); return NULL; } next_char(); // Skip '{' @@ -3416,7 +3416,7 @@ Interface *ADLParser::cond_interface_parse(void) { do { char *field = get_ident(); if (field == NULL) { - parse_err(SYNERR, "Expected keyword, base|index|scale|disp, or '%}' ending interface.\n"); + parse_err(SYNERR, "Expected keyword, base|index|scale|disp, or '%%}' ending interface.\n"); return NULL; } if ( strcmp(field,"equal") == 0 ) { @@ -3438,13 +3438,13 @@ Interface *ADLParser::cond_interface_parse(void) { greater = interface_field_parse(&greater_format); } else { - parse_err(SYNERR, "Expected keyword, base|index|scale|disp, or '%}' ending interface.\n"); + parse_err(SYNERR, "Expected keyword, base|index|scale|disp, or '%%}' ending interface.\n"); return NULL; } } while( _curchar != '%' ); next_char(); // Skip '%' if ( _curchar != '}' ) { - parse_err(SYNERR, "Missing '%}' for 'interface' block.\n"); + parse_err(SYNERR, "Missing '%%}' for 'interface' block.\n"); return NULL; } next_char(); // Skip '}' @@ -3543,7 +3543,7 @@ MatchRule *ADLParser::match_parse(FormDict &operands) { } else if ((cnstr = find_cpp_block("match constructor")) == NULL ) { parse_err(SYNERR, "invalid construction of match rule\n" - "Missing ';' or invalid '%{' and '%}' constructor\n"); + "Missing ';' or invalid '%%{' and '%%}' constructor\n"); return NULL; // No MatchRule to return } if (_AD._adl_debug > 1) @@ -3646,7 +3646,7 @@ FormatRule* ADLParser::format_parse(void) { // Check for closing '"' and '%}' in format description skipws(); // Move to closing '%}' if ( _curchar != '%' ) { - parse_err(SYNERR, "non-blank characters between closing '\"' and '%' in format"); + parse_err(SYNERR, "non-blank characters between closing '\"' and '%%' in format"); return NULL; } } // Done with format description inside @@ -3654,7 +3654,7 @@ FormatRule* ADLParser::format_parse(void) { skipws(); // Past format description, at '%' if ( _curchar != '%' || *(_ptr+1) != '}' ) { - parse_err(SYNERR, "missing '%}' at end of format block"); + parse_err(SYNERR, "missing '%%}' at end of format block"); return NULL; } next_char(); // Move past the '%' @@ -3785,7 +3785,7 @@ FormatRule* ADLParser::template_parse(void) { skipws(); // Past format description, at '%' if ( _curchar != '%' || *(_ptr+1) != '}' ) { - parse_err(SYNERR, "missing '%}' at end of format block"); + parse_err(SYNERR, "missing '%%}' at end of format block"); return NULL; } next_char(); // Move past the '%' @@ -3834,7 +3834,7 @@ ExpandRule* ADLParser::expand_parse(InstructForm *instr) { skipws(); // Skip leading whitespace if ((_curchar != '%') || (next_char(), (_curchar != '{')) ) { // If not open block - parse_err(SYNERR, "missing '%{' in expand definition\n"); + parse_err(SYNERR, "missing '%%{' in expand definition\n"); return(NULL); } next_char(); // Maintain the invariant @@ -3933,7 +3933,7 @@ ExpandRule* ADLParser::expand_parse(InstructForm *instr) { } while(_curchar != '%'); next_char(); if (_curchar != '}') { - parse_err(SYNERR, "missing '%}' in expand rule definition\n"); + parse_err(SYNERR, "missing '%%}' in expand rule definition\n"); return(NULL); } next_char(); From da5499f4ed5ea185e7ed2ec58973c87d1463458e Mon Sep 17 00:00:00 2001 From: Roland Westrelin Date: Mon, 4 Feb 2013 11:30:37 +0100 Subject: [PATCH 178/210] 8007144: Incremental inlining mistakes some call sites for dead ones and doesn't inline them Wrong detection for dead call sites. Reviewed-by: kvn --- hotspot/src/share/vm/opto/callGenerator.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/hotspot/src/share/vm/opto/callGenerator.cpp b/hotspot/src/share/vm/opto/callGenerator.cpp index 89a7c46f6ed..8cac8ee769b 100644 --- a/hotspot/src/share/vm/opto/callGenerator.cpp +++ b/hotspot/src/share/vm/opto/callGenerator.cpp @@ -305,11 +305,13 @@ class LateInlineCallGenerator : public DirectCallGenerator { void LateInlineCallGenerator::do_late_inline() { // Can't inline it if (call_node() == NULL || call_node()->outcnt() == 0 || - call_node()->in(0) == NULL || call_node()->in(0)->is_top()) + call_node()->in(0) == NULL || call_node()->in(0)->is_top()) { return; + } + const TypeTuple *r = call_node()->tf()->domain(); for (int i1 = 0; i1 < method()->arg_size(); i1++) { - if (call_node()->in(TypeFunc::Parms + i1)->is_top()) { + if (call_node()->in(TypeFunc::Parms + i1)->is_top() && r->field_at(TypeFunc::Parms + i1) != Type::HALF) { assert(Compile::current()->inlining_incrementally(), "shouldn't happen during parsing"); return; } From 1831def9cc6a97c3a6dde21e69d9e25b2db5468c Mon Sep 17 00:00:00 2001 From: Harold Seigel Date: Mon, 4 Feb 2013 08:26:02 -0500 Subject: [PATCH 179/210] 8000968: NPG: UseCompressedKlassPointers asserts with ObjectAlignmentInBytes for > 32G CompressedOops Pick a base that works for both CompressedOpps alignment and CompressedKlassPtrs alignment. Reviewed-by: kvn, roland --- hotspot/src/share/vm/memory/universe.cpp | 38 ++++++-- hotspot/src/share/vm/memory/universe.hpp | 12 ++- hotspot/src/share/vm/oops/oop.inline.hpp | 6 +- hotspot/src/share/vm/runtime/arguments.cpp | 19 ++-- hotspot/test/runtime/8000968/Test8000968.sh | 99 +++++++++++++++++++++ 5 files changed, 154 insertions(+), 20 deletions(-) create mode 100644 hotspot/test/runtime/8000968/Test8000968.sh diff --git a/hotspot/src/share/vm/memory/universe.cpp b/hotspot/src/share/vm/memory/universe.cpp index c9199228cb9..b0d43d3895e 100644 --- a/hotspot/src/share/vm/memory/universe.cpp +++ b/hotspot/src/share/vm/memory/universe.cpp @@ -144,6 +144,7 @@ NarrowPtrStruct Universe::_narrow_oop = { NULL, 0, true }; NarrowPtrStruct Universe::_narrow_klass = { NULL, 0, true }; address Universe::_narrow_ptrs_base; +size_t Universe::_class_metaspace_size; void Universe::basic_type_classes_do(void f(Klass*)) { f(boolArrayKlassObj()); @@ -689,8 +690,15 @@ char* Universe::preferred_heap_base(size_t heap_size, NARROW_OOP_MODE mode) { // Return specified base for the first request. if (!FLAG_IS_DEFAULT(HeapBaseMinAddress) && (mode == UnscaledNarrowOop)) { base = HeapBaseMinAddress; - } else if (total_size <= OopEncodingHeapMax && (mode != HeapBasedNarrowOop)) { - if (total_size <= NarrowOopHeapMax && (mode == UnscaledNarrowOop) && + + // If the total size and the metaspace size are small enough to allow + // UnscaledNarrowOop then just use UnscaledNarrowOop. + } else if ((total_size <= OopEncodingHeapMax) && (mode != HeapBasedNarrowOop) && + (!UseCompressedKlassPointers || + (((OopEncodingHeapMax - heap_size) + Universe::class_metaspace_size()) <= KlassEncodingMetaspaceMax))) { + // We don't need to check the metaspace size here because it is always smaller + // than total_size. + if ((total_size <= NarrowOopHeapMax) && (mode == UnscaledNarrowOop) && (Universe::narrow_oop_shift() == 0)) { // Use 32-bits oops without encoding and // place heap's top on the 4Gb boundary @@ -706,14 +714,24 @@ char* Universe::preferred_heap_base(size_t heap_size, NARROW_OOP_MODE mode) { base = (OopEncodingHeapMax - heap_size); } } + + // See if ZeroBaseNarrowOop encoding will work for a heap based at + // (KlassEncodingMetaspaceMax - class_metaspace_size()). + } else if (UseCompressedKlassPointers && (mode != HeapBasedNarrowOop) && + (Universe::class_metaspace_size() + HeapBaseMinAddress <= KlassEncodingMetaspaceMax) && + (KlassEncodingMetaspaceMax + heap_size - Universe::class_metaspace_size() <= OopEncodingHeapMax)) { + base = (KlassEncodingMetaspaceMax - Universe::class_metaspace_size()); } else { - // Can't reserve below 32Gb. + // UnscaledNarrowOop encoding didn't work, and no base was found for ZeroBasedOops or + // HeapBasedNarrowOop encoding was requested. So, can't reserve below 32Gb. Universe::set_narrow_oop_shift(LogMinObjAlignmentInBytes); } + // Set narrow_oop_base and narrow_oop_use_implicit_null_checks // used in ReservedHeapSpace() constructors. // The final values will be set in initialize_heap() below. - if (base != 0 && (base + heap_size) <= OopEncodingHeapMax) { + if ((base != 0) && ((base + heap_size) <= OopEncodingHeapMax) && + (!UseCompressedKlassPointers || (base + Universe::class_metaspace_size()) <= KlassEncodingMetaspaceMax)) { // Use zero based compressed oops Universe::set_narrow_oop_base(NULL); // Don't need guard page for implicit checks in indexed @@ -796,7 +814,9 @@ jint Universe::initialize_heap() { tty->print("heap address: " PTR_FORMAT ", size: " SIZE_FORMAT " MB", Universe::heap()->base(), Universe::heap()->reserved_region().byte_size()/M); } - if ((uint64_t)Universe::heap()->reserved_region().end() > OopEncodingHeapMax) { + if (((uint64_t)Universe::heap()->reserved_region().end() > OopEncodingHeapMax) || + (UseCompressedKlassPointers && + ((uint64_t)Universe::heap()->base() + Universe::class_metaspace_size() > KlassEncodingMetaspaceMax))) { // Can't reserve heap below 32Gb. // keep the Universe::narrow_oop_base() set in Universe::reserve_heap() Universe::set_narrow_oop_shift(LogMinObjAlignmentInBytes); @@ -862,8 +882,8 @@ ReservedSpace Universe::reserve_heap(size_t heap_size, size_t alignment) { // be compressed the same as instances. // Need to round class space size up because it's below the heap and // the actual alignment depends on its size. - size_t metaspace_size = align_size_up(ClassMetaspaceSize, alignment); - size_t total_reserved = align_size_up(heap_size + metaspace_size, alignment); + Universe::set_class_metaspace_size(align_size_up(ClassMetaspaceSize, alignment)); + size_t total_reserved = align_size_up(heap_size + Universe::class_metaspace_size(), alignment); char* addr = Universe::preferred_heap_base(total_reserved, Universe::UnscaledNarrowOop); ReservedHeapSpace total_rs(total_reserved, alignment, UseLargePages, addr); @@ -904,8 +924,8 @@ ReservedSpace Universe::reserve_heap(size_t heap_size, size_t alignment) { // compressed oops is greater than the one used for compressed klass // ptrs, a metadata space on top of the heap could become // unreachable. - ReservedSpace class_rs = total_rs.first_part(metaspace_size); - ReservedSpace heap_rs = total_rs.last_part(metaspace_size, alignment); + ReservedSpace class_rs = total_rs.first_part(Universe::class_metaspace_size()); + ReservedSpace heap_rs = total_rs.last_part(Universe::class_metaspace_size(), alignment); Metaspace::initialize_class_space(class_rs); if (UseCompressedOops) { diff --git a/hotspot/src/share/vm/memory/universe.hpp b/hotspot/src/share/vm/memory/universe.hpp index ca7b09c7b19..2bf0b653f58 100644 --- a/hotspot/src/share/vm/memory/universe.hpp +++ b/hotspot/src/share/vm/memory/universe.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, 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 @@ -211,6 +211,9 @@ class Universe: AllStatic { static struct NarrowPtrStruct _narrow_klass; static address _narrow_ptrs_base; + // Aligned size of the metaspace. + static size_t _class_metaspace_size; + // array of dummy objects used with +FullGCAlot debug_only(static objArrayOop _fullgc_alot_dummy_array;) // index of next entry to clear @@ -278,6 +281,13 @@ class Universe: AllStatic { static bool reserve_metaspace_helper(bool with_base = false); static ReservedHeapSpace reserve_heap_metaspace(size_t heap_size, size_t alignment, bool& contiguous); + static size_t class_metaspace_size() { + return _class_metaspace_size; + } + static void set_class_metaspace_size(size_t metaspace_size) { + _class_metaspace_size = metaspace_size; + } + // Debugging static int _verify_count; // number of verifies done // True during call to verify(). Should only be set/cleared in verify(). diff --git a/hotspot/src/share/vm/oops/oop.inline.hpp b/hotspot/src/share/vm/oops/oop.inline.hpp index c097617478d..a4b535f08ab 100644 --- a/hotspot/src/share/vm/oops/oop.inline.hpp +++ b/hotspot/src/share/vm/oops/oop.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, 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 @@ -227,12 +227,12 @@ inline oop oopDesc::decode_heap_oop(oop v) { return v; } // might not be the same as oop. inline narrowOop oopDesc::encode_klass_not_null(Klass* v) { - assert(!is_null(v), "oop value can never be zero"); + assert(!is_null(v), "klass value can never be zero"); assert(check_klass_alignment(v), "Address not aligned"); address base = Universe::narrow_klass_base(); int shift = Universe::narrow_klass_shift(); uint64_t pd = (uint64_t)(pointer_delta((void*)v, (void*)base, 1)); - assert(OopEncodingHeapMax > pd, "change encoding max if new encoding"); + assert(KlassEncodingMetaspaceMax > pd, "change encoding max if new encoding"); uint64_t result = pd >> shift; assert((result & CONST64(0xffffffff00000000)) == 0, "narrow klass pointer overflow"); assert(decode_klass(result) == v, "reversibility"); diff --git a/hotspot/src/share/vm/runtime/arguments.cpp b/hotspot/src/share/vm/runtime/arguments.cpp index 47851058cd9..b0d87df7080 100644 --- a/hotspot/src/share/vm/runtime/arguments.cpp +++ b/hotspot/src/share/vm/runtime/arguments.cpp @@ -1446,13 +1446,18 @@ void Arguments::set_ergonomics_flags() { } // Set the ClassMetaspaceSize to something that will not need to be // expanded, since it cannot be expanded. - if (UseCompressedKlassPointers && FLAG_IS_DEFAULT(ClassMetaspaceSize)) { - // 100,000 classes seems like a good size, so 100M assumes around 1K - // per klass. The vtable and oopMap is embedded so we don't have a fixed - // size per klass. Eventually, this will be parameterized because it - // would also be useful to determine the optimal size of the - // systemDictionary. - FLAG_SET_ERGO(uintx, ClassMetaspaceSize, 100*M); + if (UseCompressedKlassPointers) { + if (ClassMetaspaceSize > KlassEncodingMetaspaceMax) { + warning("Class metaspace size is too large for UseCompressedKlassPointers"); + FLAG_SET_DEFAULT(UseCompressedKlassPointers, false); + } else if (FLAG_IS_DEFAULT(ClassMetaspaceSize)) { + // 100,000 classes seems like a good size, so 100M assumes around 1K + // per klass. The vtable and oopMap is embedded so we don't have a fixed + // size per klass. Eventually, this will be parameterized because it + // would also be useful to determine the optimal size of the + // systemDictionary. + FLAG_SET_ERGO(uintx, ClassMetaspaceSize, 100*M); + } } } // Also checks that certain machines are slower with compressed oops diff --git a/hotspot/test/runtime/8000968/Test8000968.sh b/hotspot/test/runtime/8000968/Test8000968.sh new file mode 100644 index 00000000000..cd7183476cf --- /dev/null +++ b/hotspot/test/runtime/8000968/Test8000968.sh @@ -0,0 +1,99 @@ +# +# Copyright (c) 2013, 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. +# +# 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. +# + + +# @test Test8000968.sh +# @bug 8000968 +# @summary NPG: UseCompressedKlassPointers asserts with ObjectAlignmentInBytes=32 +# @run shell Test8000968.sh +# + +if [ "${TESTJAVA}" = "" ] +then + PARENT=`dirname \`which java\`` + TESTJAVA=`dirname ${PARENT}` + printf "TESTJAVA not set, selecting " ${TESTJAVA} + printf " If this is incorrect, try setting the variable manually.\n" +fi + + +# set platform-dependent variables +OS=`uname -s` +case "$OS" in + Windows_* ) + FS="\\" + NULL=NUL + ;; + * ) + FS="/" + NULL=/dev/null + ;; +esac + +JAVA=${TESTJAVA}${FS}bin${FS}java + +# +# See if platform has 64 bit java. +# +${JAVA} ${TESTVMOPTS} -d64 -version 2>&1 | grep -i "does not support" > ${NULL} +if [ "$?" != "1" ] +then + printf "Platform is 32 bit, does not support -XX:ObjectAlignmentInBytes= option.\n" + printf "Passed.\n" + exit 0 +fi + +# +# Test -XX:ObjectAlignmentInBytes with -XX:+UseCompressedKlassPointers -XX:+UseCompressedOops. +# +${JAVA} ${TESTVMOPTS} -d64 -XX:+UseCompressedKlassPointers -XX:+UseCompressedOops -XX:ObjectAlignmentInBytes=16 -version 2>&1 > ${NULL} +if [ "$?" != "0" ] +then + printf "FAILED: -XX:ObjectAlignmentInBytes=16 option did not work.\n" + exit 1 +fi + +${JAVA} ${TESTVMOPTS} -d64 -XX:+UseCompressedKlassPointers -XX:+UseCompressedOops -XX:ObjectAlignmentInBytes=32 -version 2>&1 > ${NULL} +if [ "$?" != "0" ] +then + printf "FAILED: -XX:ObjectAlignmentInBytes=32 option did not work.\n" + exit 1 +fi + +${JAVA} ${TESTVMOPTS} -d64 -XX:+UseCompressedKlassPointers -XX:+UseCompressedOops -XX:ObjectAlignmentInBytes=64 -version 2>&1 > ${NULL} +if [ "$?" != "0" ] +then + printf "FAILED: -XX:ObjectAlignmentInBytes=64 option did not work.\n" + exit 1 +fi + +${JAVA} ${TESTVMOPTS} -d64 -XX:+UseCompressedKlassPointers -XX:+UseCompressedOops -XX:ObjectAlignmentInBytes=128 -version 2>&1 > ${NULL} +if [ "$?" != "0" ] +then + printf "FAILED: -XX:ObjectAlignmentInBytes=128 option did not work.\n" + exit 1 +fi + + +printf "Passed.\n" +exit 0 From 7add1f152df5a65b00418c481f1959f60c3feffb Mon Sep 17 00:00:00 2001 From: Sergey Bylokhov Date: Mon, 4 Feb 2013 19:50:06 +0400 Subject: [PATCH 180/210] 8004821: Graphics2D.drawPolygon() fails with IllegalPathStateException Reviewed-by: prr, flar --- .../java2d/pipe/PixelToShapeConverter.java | 14 ++--- jdk/test/sun/java2d/pipe/Test8004821.java | 60 +++++++++++++++++++ 2 files changed, 67 insertions(+), 7 deletions(-) create mode 100644 jdk/test/sun/java2d/pipe/Test8004821.java diff --git a/jdk/src/share/classes/sun/java2d/pipe/PixelToShapeConverter.java b/jdk/src/share/classes/sun/java2d/pipe/PixelToShapeConverter.java index c130068612e..5a01e000790 100644 --- a/jdk/src/share/classes/sun/java2d/pipe/PixelToShapeConverter.java +++ b/jdk/src/share/classes/sun/java2d/pipe/PixelToShapeConverter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 1998, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, 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 @@ -103,12 +103,12 @@ public class PixelToShapeConverter GeneralPath gp = new GeneralPath(GeneralPath.WIND_EVEN_ODD); if (nPoints > 0) { gp.moveTo(xPoints[0], yPoints[0]); - } - for (int i = 1; i < nPoints; i++) { - gp.lineTo(xPoints[i], yPoints[i]); - } - if (close) { - gp.closePath(); + for (int i = 1; i < nPoints; i++) { + gp.lineTo(xPoints[i], yPoints[i]); + } + if (close) { + gp.closePath(); + } } return gp; } diff --git a/jdk/test/sun/java2d/pipe/Test8004821.java b/jdk/test/sun/java2d/pipe/Test8004821.java new file mode 100644 index 00000000000..c2143dda308 --- /dev/null +++ b/jdk/test/sun/java2d/pipe/Test8004821.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2013, 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. + * + * 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. + */ + +import java.awt.Graphics2D; +import java.awt.Polygon; +import java.awt.image.BufferedImage; + +/** + * @test + * @bug 8004821 + * @summary Verifies that drawPolygon() works with empty arrays. + * @author Sergey Bylokhov + */ +public final class Test8004821 { + + public static void main(final String[] args) { + final int[] arrEmpty = {}; + final int[] arr1elem = {150}; + final BufferedImage bi = new BufferedImage(300, 300, + BufferedImage.TYPE_INT_RGB); + final Graphics2D g = (Graphics2D) bi.getGraphics(); + test(g, arrEmpty); + test(g, arr1elem); + g.translate(2.0, 2.0); + test(g, arrEmpty); + test(g, arr1elem); + g.scale(2.0, 2.0); + test(g, arrEmpty); + test(g, arr1elem); + g.dispose(); + } + + private static void test(final Graphics2D g, final int[] arr) { + g.drawPolygon(arr, arr, arr.length); + g.drawPolygon(new Polygon(arr, arr, arr.length)); + g.fillPolygon(arr, arr, arr.length); + g.fillPolygon(new Polygon(arr, arr, arr.length)); + g.drawPolyline(arr, arr, arr.length); + } +} From ddbfa5fe533275175c38fc7acedc124f1684df68 Mon Sep 17 00:00:00 2001 From: Vinnie Ryan Date: Mon, 4 Feb 2013 17:20:26 +0000 Subject: [PATCH 181/210] 8006994: Cleanup PKCS12 tests to ensure streams get closed Reviewed-by: mullan --- jdk/test/java/security/KeyStore/PBETest.java | 63 ++++++++------- .../security/pkcs12/StorePasswordTest.java | 50 ++++++------ .../security/pkcs12/StoreSecretKeyTest.java | 41 +++++----- .../security/pkcs12/StoreTrustedCertTest.java | 80 +++++++++---------- 4 files changed, 116 insertions(+), 118 deletions(-) diff --git a/jdk/test/java/security/KeyStore/PBETest.java b/jdk/test/java/security/KeyStore/PBETest.java index be437d03bbd..2186165ea68 100644 --- a/jdk/test/java/security/KeyStore/PBETest.java +++ b/jdk/test/java/security/KeyStore/PBETest.java @@ -58,45 +58,46 @@ public class PBETest { new File(NEW_KEYSTORE).delete(); - try { - KeyStore keystore = load(KEYSTORE_TYPE, KEYSTORE, PASSWORD); - KeyStore.Entry entry = - keystore.getEntry(ALIAS, - new KeyStore.PasswordProtection(PASSWORD)); - System.out.println("Retrieved entry named '" + ALIAS + "'"); - - // Set entry - KeyStore keystore2 = load(NEW_KEYSTORE_TYPE, null, null); - keystore2.setEntry(ALIAS, entry, - new KeyStore.PasswordProtection(PASSWORD, PBE_ALGO, - new PBEParameterSpec(SALT, ITERATION_COUNT, - new IvParameterSpec(IV)))); - System.out.println("Encrypted entry using: " + PBE_ALGO); - - System.out.println("Storing keystore to: " + NEW_KEYSTORE); - keystore2.store(new FileOutputStream(NEW_KEYSTORE), PASSWORD); - - keystore2 = load(NEW_KEYSTORE_TYPE, NEW_KEYSTORE, PASSWORD); - entry = keystore2.getEntry(ALIAS, + KeyStore keystore = load(KEYSTORE_TYPE, KEYSTORE, PASSWORD); + KeyStore.Entry entry = + keystore.getEntry(ALIAS, new KeyStore.PasswordProtection(PASSWORD)); - System.out.println("Retrieved entry named '" + ALIAS + "'"); + System.out.println("Retrieved entry named '" + ALIAS + "'"); - } finally { - new File(NEW_KEYSTORE).delete(); - System.out.println("Deleted keystore: " + NEW_KEYSTORE); + // Set entry + KeyStore keystore2 = load(NEW_KEYSTORE_TYPE, null, null); + keystore2.setEntry(ALIAS, entry, + new KeyStore.PasswordProtection(PASSWORD, PBE_ALGO, + new PBEParameterSpec(SALT, ITERATION_COUNT, + new IvParameterSpec(IV)))); + System.out.println("Encrypted entry using: " + PBE_ALGO); + + try (FileOutputStream outStream = new FileOutputStream(NEW_KEYSTORE)) { + System.out.println("Storing keystore to: " + NEW_KEYSTORE); + keystore2.store(outStream, PASSWORD); } + + keystore2 = load(NEW_KEYSTORE_TYPE, NEW_KEYSTORE, PASSWORD); + entry = keystore2.getEntry(ALIAS, + new KeyStore.PasswordProtection(PASSWORD)); + System.out.println("Retrieved entry named '" + ALIAS + "'"); } private static KeyStore load(String type, String path, char[] password) throws Exception { - - FileInputStream stream = null; - if (path != null) { - stream = new FileInputStream(path); - } KeyStore keystore = KeyStore.getInstance(type); - System.out.println("Loading keystore from: " + path); - keystore.load(stream, password); + + if (path != null) { + + try (FileInputStream inStream = new FileInputStream(path)) { + System.out.println("Loading keystore from: " + path); + keystore.load(inStream, password); + System.out.println("Loaded keystore with " + keystore.size() + + " entries"); + } + } else { + keystore.load(null, null); + } return keystore; } diff --git a/jdk/test/sun/security/pkcs12/StorePasswordTest.java b/jdk/test/sun/security/pkcs12/StorePasswordTest.java index fc2f77c51c1..d258aaa10a7 100644 --- a/jdk/test/sun/security/pkcs12/StorePasswordTest.java +++ b/jdk/test/sun/security/pkcs12/StorePasswordTest.java @@ -47,40 +47,40 @@ public class StorePasswordTest { new File(KEYSTORE).delete(); - try { + KeyStore keystore = KeyStore.getInstance("PKCS12"); + keystore.load(null, null); - KeyStore keystore = KeyStore.getInstance("PKCS12"); - keystore.load(null, null); - - // Set entry - keystore.setEntry(ALIAS, - new KeyStore.SecretKeyEntry(convertPassword(USER_PASSWORD)), - new KeyStore.PasswordProtection(PASSWORD)); + // Set entry + keystore.setEntry(ALIAS, + new KeyStore.SecretKeyEntry(convertPassword(USER_PASSWORD)), + new KeyStore.PasswordProtection(PASSWORD)); + try (FileOutputStream outStream = new FileOutputStream(KEYSTORE)) { System.out.println("Storing keystore to: " + KEYSTORE); - keystore.store(new FileOutputStream(KEYSTORE), PASSWORD); + keystore.store(outStream, PASSWORD); + } + try (FileInputStream inStream = new FileInputStream(KEYSTORE)) { System.out.println("Loading keystore from: " + KEYSTORE); - keystore.load(new FileInputStream(KEYSTORE), PASSWORD); + keystore.load(inStream, PASSWORD); System.out.println("Loaded keystore with " + keystore.size() + " entries"); - KeyStore.Entry entry = keystore.getEntry(ALIAS, - new KeyStore.PasswordProtection(PASSWORD)); - System.out.println("Retrieved entry: " + entry); + } - SecretKey key = (SecretKey) keystore.getKey(ALIAS, PASSWORD); - SecretKeyFactory factory = - SecretKeyFactory.getInstance(key.getAlgorithm()); - PBEKeySpec keySpec = - (PBEKeySpec) factory.getKeySpec(key, PBEKeySpec.class); - char[] pwd = keySpec.getPassword(); - System.out.println("Recovered credential: " + new String(pwd)); + KeyStore.Entry entry = keystore.getEntry(ALIAS, + new KeyStore.PasswordProtection(PASSWORD)); + System.out.println("Retrieved entry: " + entry); - if (!Arrays.equals(USER_PASSWORD.toCharArray(), pwd)) { - throw new Exception("Failed to recover the stored password"); - } - } finally { - new File(KEYSTORE).delete(); + SecretKey key = (SecretKey) keystore.getKey(ALIAS, PASSWORD); + SecretKeyFactory factory = + SecretKeyFactory.getInstance(key.getAlgorithm()); + PBEKeySpec keySpec = + (PBEKeySpec) factory.getKeySpec(key, PBEKeySpec.class); + char[] pwd = keySpec.getPassword(); + System.out.println("Recovered credential: " + new String(pwd)); + + if (!Arrays.equals(USER_PASSWORD.toCharArray(), pwd)) { + throw new Exception("Failed to recover the stored password"); } } diff --git a/jdk/test/sun/security/pkcs12/StoreSecretKeyTest.java b/jdk/test/sun/security/pkcs12/StoreSecretKeyTest.java index f002ef7506a..84c28899126 100644 --- a/jdk/test/sun/security/pkcs12/StoreSecretKeyTest.java +++ b/jdk/test/sun/security/pkcs12/StoreSecretKeyTest.java @@ -53,35 +53,34 @@ public class StoreSecretKeyTest { new File(KEYSTORE).delete(); - try { + KeyStore keystore = KeyStore.getInstance("PKCS12"); + keystore.load(null, null); - KeyStore keystore = KeyStore.getInstance("PKCS12"); - keystore.load(null, null); - - // Set entry - keystore.setEntry(ALIAS, - new KeyStore.SecretKeyEntry(generateSecretKey("AES", 128)), - new KeyStore.PasswordProtection(PASSWORD)); + // Set entry + keystore.setEntry(ALIAS, + new KeyStore.SecretKeyEntry(generateSecretKey("AES", 128)), + new KeyStore.PasswordProtection(PASSWORD)); + try (FileOutputStream outStream = new FileOutputStream(KEYSTORE)) { System.out.println("Storing keystore to: " + KEYSTORE); - keystore.store(new FileOutputStream(KEYSTORE), PASSWORD); + keystore.store(outStream, PASSWORD); + } + try (FileInputStream inStream = new FileInputStream(KEYSTORE)) { System.out.println("Loading keystore from: " + KEYSTORE); - keystore.load(new FileInputStream(KEYSTORE), PASSWORD); + keystore.load(inStream, PASSWORD); System.out.println("Loaded keystore with " + keystore.size() + " entries"); - KeyStore.Entry entry = keystore.getEntry(ALIAS, - new KeyStore.PasswordProtection(PASSWORD)); - System.out.println("Retrieved entry: " + entry); + } - if (entry instanceof KeyStore.SecretKeyEntry) { - System.out.println("Retrieved secret key entry: " + - entry); - } else { - throw new Exception("Not a secret key entry"); - } - } finally { - new File(KEYSTORE).delete(); + KeyStore.Entry entry = keystore.getEntry(ALIAS, + new KeyStore.PasswordProtection(PASSWORD)); + System.out.println("Retrieved entry: " + entry); + + if (entry instanceof KeyStore.SecretKeyEntry) { + System.out.println("Retrieved secret key entry: " + entry); + } else { + throw new Exception("Not a secret key entry"); } } diff --git a/jdk/test/sun/security/pkcs12/StoreTrustedCertTest.java b/jdk/test/sun/security/pkcs12/StoreTrustedCertTest.java index a1481749d7e..0cbca31e2d1 100644 --- a/jdk/test/sun/security/pkcs12/StoreTrustedCertTest.java +++ b/jdk/test/sun/security/pkcs12/StoreTrustedCertTest.java @@ -49,59 +49,57 @@ public class StoreTrustedCertTest { new File(KEYSTORE).delete(); - try { - KeyStore keystore = KeyStore.getInstance("PKCS12"); - keystore.load(null, null); + KeyStore keystore = KeyStore.getInstance("PKCS12"); + keystore.load(null, null); - Certificate cert = loadCertificate(CERT); - Set attributes = new HashSet<>(); - attributes.add(new PKCS12Attribute("1.3.5.7.9", "that's odd")); - attributes.add(new PKCS12Attribute("2.4.6.8.10", "that's even")); + Certificate cert = loadCertificate(CERT); + Set attributes = new HashSet<>(); + attributes.add(new PKCS12Attribute("1.3.5.7.9", "that's odd")); + attributes.add(new PKCS12Attribute("2.4.6.8.10", "that's even")); - // Set trusted certificate entry - keystore.setEntry(ALIAS, - new KeyStore.TrustedCertificateEntry(cert), null); + // Set trusted certificate entry + keystore.setEntry(ALIAS, + new KeyStore.TrustedCertificateEntry(cert), null); - // Set trusted certificate entry with attributes - keystore.setEntry(ALIAS2, - new KeyStore.TrustedCertificateEntry(cert, attributes), null); + // Set trusted certificate entry with attributes + keystore.setEntry(ALIAS2, + new KeyStore.TrustedCertificateEntry(cert, attributes), null); + try (FileOutputStream outStream = new FileOutputStream(KEYSTORE)) { System.out.println("Storing keystore to: " + KEYSTORE); - keystore.store(new FileOutputStream(KEYSTORE), PASSWORD); + keystore.store(outStream, PASSWORD); + } + try (FileInputStream inStream = new FileInputStream(KEYSTORE)) { System.out.println("Loading keystore from: " + KEYSTORE); - keystore.load(new FileInputStream(KEYSTORE), PASSWORD); + keystore.load(inStream, PASSWORD); System.out.println("Loaded keystore with " + keystore.size() + " entries"); + } - KeyStore.Entry entry = keystore.getEntry(ALIAS, null); - if (entry instanceof KeyStore.TrustedCertificateEntry) { - System.out.println("Retrieved trusted certificate entry: " + - entry); + KeyStore.Entry entry = keystore.getEntry(ALIAS, null); + if (entry instanceof KeyStore.TrustedCertificateEntry) { + System.out.println("Retrieved trusted certificate entry: " + entry); + } else { + throw new Exception("Not a trusted certificate entry"); + } + System.out.println(); + + entry = keystore.getEntry(ALIAS2, null); + if (entry instanceof KeyStore.TrustedCertificateEntry) { + KeyStore.TrustedCertificateEntry trustedEntry = + (KeyStore.TrustedCertificateEntry) entry; + Set entryAttributes = + trustedEntry.getAttributes(); + + if (entryAttributes.containsAll(attributes)) { + System.out.println("Retrieved trusted certificate entry " + + "with attributes: " + entry); } else { - throw new Exception("Not a trusted certificate entry"); + throw new Exception("Failed to retrieve entry attributes"); } - System.out.println(); - - entry = keystore.getEntry(ALIAS2, null); - if (entry instanceof KeyStore.TrustedCertificateEntry) { - KeyStore.TrustedCertificateEntry trustedEntry = - (KeyStore.TrustedCertificateEntry) entry; - Set entryAttributes = - trustedEntry.getAttributes(); - - if (entryAttributes.containsAll(attributes)) { - System.out.println("Retrieved trusted certificate entry " + - "with attributes: " + entry); - } else { - throw new Exception("Failed to retrieve entry attributes"); - } - } else { - throw new Exception("Not a trusted certificate entry"); - } - - } finally { - new File(KEYSTORE).delete(); + } else { + throw new Exception("Not a trusted certificate entry"); } } From 16990e896a57b12c15a611241d4464a5410950fd Mon Sep 17 00:00:00 2001 From: Eric McCorkle Date: Mon, 4 Feb 2013 13:05:32 -0500 Subject: [PATCH 182/210] 8006949: Update hotspot for MethodParameters format change 8006907: Hotspot should reject classfiles with multiple MethodParameters attributes Update to Hotspot's processing of MethodParameters attributes in classfiles Reviewed-by: coleenp, jrose --- .../share/vm/classfile/classFileParser.cpp | 47 ++++++++++++------- hotspot/src/share/vm/oops/constMethod.hpp | 7 +-- hotspot/src/share/vm/prims/jvm.cpp | 2 +- 3 files changed, 32 insertions(+), 24 deletions(-) diff --git a/hotspot/src/share/vm/classfile/classFileParser.cpp b/hotspot/src/share/vm/classfile/classFileParser.cpp index 557707ba432..d46a1eab840 100644 --- a/hotspot/src/share/vm/classfile/classFileParser.cpp +++ b/hotspot/src/share/vm/classfile/classFileParser.cpp @@ -1947,6 +1947,8 @@ methodHandle ClassFileParser::parse_method(ClassLoaderData* loader_data, u2** localvariable_type_table_start; u2 method_parameters_length = 0; u1* method_parameters_data = NULL; + bool method_parameters_seen = false; + bool method_parameters_four_byte_flags; bool parsed_code_attribute = false; bool parsed_checked_exceptions_attribute = false; bool parsed_stackmap_attribute = false; @@ -2157,22 +2159,32 @@ methodHandle ClassFileParser::parse_method(ClassLoaderData* loader_data, method_attribute_length, cp, CHECK_(nullHandle)); } else if (method_attribute_name == vmSymbols::tag_method_parameters()) { + // reject multiple method parameters + if (method_parameters_seen) { + classfile_parse_error("Multiple MethodParameters attributes in class file %s", CHECK_(nullHandle)); + } + method_parameters_seen = true; method_parameters_length = cfs->get_u1_fast(); // Track the actual size (note: this is written for clarity; a // decent compiler will CSE and constant-fold this into a single // expression) - u2 actual_size = 1; - method_parameters_data = cfs->get_u1_buffer(); - actual_size += 2 * method_parameters_length; - cfs->skip_u2_fast(method_parameters_length); - actual_size += 4 * method_parameters_length; - cfs->skip_u4_fast(method_parameters_length); - // Enforce attribute length - if (method_attribute_length != actual_size) { + // Use the attribute length to figure out the size of flags + if (method_attribute_length == (method_parameters_length * 6u) + 1u) { + method_parameters_four_byte_flags = true; + } else if (method_attribute_length == (method_parameters_length * 4u) + 1u) { + method_parameters_four_byte_flags = false; + } else { classfile_parse_error( - "Invalid MethodParameters method attribute length %u in class file %s", + "Invalid MethodParameters method attribute length %u in class file", method_attribute_length, CHECK_(nullHandle)); } + method_parameters_data = cfs->get_u1_buffer(); + cfs->skip_u2_fast(method_parameters_length); + if (method_parameters_four_byte_flags) { + cfs->skip_u4_fast(method_parameters_length); + } else { + cfs->skip_u2_fast(method_parameters_length); + } // ignore this attribute if it cannot be reflected if (!SystemDictionary::Parameter_klass_loaded()) method_parameters_length = 0; @@ -2316,15 +2328,16 @@ methodHandle ClassFileParser::parse_method(ClassLoaderData* loader_data, // Copy method parameters if (method_parameters_length > 0) { MethodParametersElement* elem = m->constMethod()->method_parameters_start(); - for(int i = 0; i < method_parameters_length; i++) { - elem[i].name_cp_index = - Bytes::get_Java_u2(method_parameters_data); + for (int i = 0; i < method_parameters_length; i++) { + elem[i].name_cp_index = Bytes::get_Java_u2(method_parameters_data); method_parameters_data += 2; - u4 flags = Bytes::get_Java_u4(method_parameters_data); - // This caused an alignment fault on Sparc, if flags was a u4 - elem[i].flags_lo = extract_low_short_from_int(flags); - elem[i].flags_hi = extract_high_short_from_int(flags); - method_parameters_data += 4; + if (method_parameters_four_byte_flags) { + elem[i].flags = Bytes::get_Java_u4(method_parameters_data); + method_parameters_data += 4; + } else { + elem[i].flags = Bytes::get_Java_u2(method_parameters_data); + method_parameters_data += 2; + } } } diff --git a/hotspot/src/share/vm/oops/constMethod.hpp b/hotspot/src/share/vm/oops/constMethod.hpp index bd3acd23188..12a36c24470 100644 --- a/hotspot/src/share/vm/oops/constMethod.hpp +++ b/hotspot/src/share/vm/oops/constMethod.hpp @@ -122,12 +122,7 @@ class ExceptionTableElement VALUE_OBJ_CLASS_SPEC { class MethodParametersElement VALUE_OBJ_CLASS_SPEC { public: u2 name_cp_index; - // This has to happen, otherwise it will cause SIGBUS from a - // misaligned u4 on some architectures (ie SPARC) - // because MethodParametersElements are only aligned mod 2 - // within the ConstMethod container u2 flags_hi; - u2 flags_hi; - u2 flags_lo; + u2 flags; }; class KlassSizeStats; diff --git a/hotspot/src/share/vm/prims/jvm.cpp b/hotspot/src/share/vm/prims/jvm.cpp index 7fffe0020c2..84ab5f04828 100644 --- a/hotspot/src/share/vm/prims/jvm.cpp +++ b/hotspot/src/share/vm/prims/jvm.cpp @@ -1620,7 +1620,7 @@ JVM_ENTRY(jobjectArray, JVM_GetMethodParameters(JNIEnv *env, jobject method)) // For a 0 index, give a NULL symbol Symbol* const sym = 0 != params[i].name_cp_index ? mh->constants()->symbol_at(params[i].name_cp_index) : NULL; - int flags = build_int_from_shorts(params[i].flags_lo, params[i].flags_hi); + int flags = params[i].flags; oop param = Reflection::new_parameter(reflected_method, i, sym, flags, CHECK_NULL); result->obj_at_put(i, param); From 37d83019d0e05267dd343fa114a60b0b5725ffd8 Mon Sep 17 00:00:00 2001 From: Volker Simonis Date: Mon, 4 Feb 2013 13:14:12 -0500 Subject: [PATCH 183/210] 8007475: Memory stomp with UseMallocOnly Fix off-by-one error Reviewed-by: coleenp, hseigel --- .../src/share/vm/classfile/stackMapFrame.hpp | 2 +- .../runtime/8007475/StackMapFrameTest.java | 41 +++++++++++++++++++ 2 files changed, 42 insertions(+), 1 deletion(-) create mode 100644 hotspot/test/runtime/8007475/StackMapFrameTest.java diff --git a/hotspot/src/share/vm/classfile/stackMapFrame.hpp b/hotspot/src/share/vm/classfile/stackMapFrame.hpp index 3329f7a9e8b..bdeb956ba68 100644 --- a/hotspot/src/share/vm/classfile/stackMapFrame.hpp +++ b/hotspot/src/share/vm/classfile/stackMapFrame.hpp @@ -178,7 +178,7 @@ class StackMapFrame : public ResourceObj { #ifdef DEBUG // Put bogus type to indicate it's no longer valid. if (_stack_mark != -1) { - for (int i = _stack_mark; i >= _stack_size; --i) { + for (int i = _stack_mark - 1; i >= _stack_size; --i) { _stack[i] = VerificationType::bogus_type(); } } diff --git a/hotspot/test/runtime/8007475/StackMapFrameTest.java b/hotspot/test/runtime/8007475/StackMapFrameTest.java new file mode 100644 index 00000000000..b927ae76db6 --- /dev/null +++ b/hotspot/test/runtime/8007475/StackMapFrameTest.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2013, 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. + * + * 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. + */ + +/* + * @test + * @bug 8007475 + * @summary Test memory stomp in stack map test + * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+UseMallocOnly StackMapFrameTest + */ +public class StackMapFrameTest { + + public static void foo() { + Object o = new Object(); + } + + public static void main(String args[]) { + for (int i = 0; i < 25000; i++) { + foo(); + } + } +} From db8ced219f196ccdbae9f1121dd5411412dbdf90 Mon Sep 17 00:00:00 2001 From: Xueming Shen Date: Mon, 4 Feb 2013 11:58:43 -0800 Subject: [PATCH 184/210] 8006295: Base64.Decoder.wrap(java.io.InputStream) returns InputStream which throws unspecified IOException on attempt to decode invalid Base64 byte stream 8006315: Base64.Decoder decoding methods are not consistent in treating non-padded data 8006530: Base64.getMimeDecoder().decode() throws exception for non-base64 character after adding = Updated the spec to describe the expected behave explicitly and the implementation to follow Reviewed-by: alanb, chegar, lancea --- jdk/src/share/classes/java/util/Base64.java | 121 +++++++++++++------- jdk/test/java/util/Base64/TestBase64.java | 83 +++++++++++++- 2 files changed, 161 insertions(+), 43 deletions(-) diff --git a/jdk/src/share/classes/java/util/Base64.java b/jdk/src/share/classes/java/util/Base64.java index 471b4e28620..88b17406799 100644 --- a/jdk/src/share/classes/java/util/Base64.java +++ b/jdk/src/share/classes/java/util/Base64.java @@ -64,7 +64,8 @@ import java.nio.charset.StandardCharsets; * RFC 2045 for encoding and decoding operation. The encoded output * must be represented in lines of no more than 76 characters each * and uses a carriage return {@code '\r'} followed immediately by - * a linefeed {@code '\n'} as the line separator. All line separators + * a linefeed {@code '\n'} as the line separator. No line separator + * is added to the end of the encoded output. All line separators * or other characters not found in the base64 alphabet table are * ignored in decoding operation.

* @@ -614,6 +615,13 @@ public class Base64 { * This class implements a decoder for decoding byte data using the * Base64 encoding scheme as specified in RFC 4648 and RFC 2045. * + *

The Base64 padding character {@code '='} is accepted and + * interpreted as the end of the encoded byte data, but is not + * required. So if the final unit of the encoded byte data only has + * two or three Base64 characters (without the corresponding padding + * character(s) padded), they are decoded as if followed by padding + * character(s). + * *

Instances of {@link Decoder} class are safe for use by * multiple concurrent threads. * @@ -857,6 +865,9 @@ public class Base64 { /** * Returns an input stream for decoding {@link Base64} encoded byte stream. * + *

The {@code read} methods of the returned {@code InputStream} will + * throw {@code IOException} when reading bytes that cannot be decoded. + * *

Closing the returned input stream will close the underlying * input stream. * @@ -883,13 +894,16 @@ public class Base64 { int dl = dst.arrayOffset() + dst.limit(); int dp0 = dp; int mark = sp; - boolean padding = false; try { while (sp < sl) { int b = sa[sp++] & 0xff; if ((b = base64[b]) < 0) { if (b == -2) { // padding byte - padding = true; + if (shiftto == 6 && (sp == sl || sa[sp++] != '=') || + shiftto == 18) { + throw new IllegalArgumentException( + "Input byte array has wrong 4-byte ending unit"); + } break; } if (isMIME) // skip if for rfc2045 @@ -915,24 +929,23 @@ public class Base64 { if (shiftto == 6) { if (dl - dp < 1) return dp - dp0; - if (padding && (sp + 1 != sl || sa[sp++] != '=')) - throw new IllegalArgumentException( - "Input buffer has wrong 4-byte ending unit"); da[dp++] = (byte)(bits >> 16); - mark = sp; } else if (shiftto == 0) { if (dl - dp < 2) return dp - dp0; - if (padding && sp != sl) - throw new IllegalArgumentException( - "Input buffer has wrong 4-byte ending unit"); da[dp++] = (byte)(bits >> 16); da[dp++] = (byte)(bits >> 8); - mark = sp; - } else if (padding || shiftto != 18) { + } else if (shiftto == 12) { throw new IllegalArgumentException( "Last unit does not have enough valid bits"); } + while (sp < sl) { + if (isMIME && base64[sa[sp++]] < 0) + continue; + throw new IllegalArgumentException( + "Input byte array has incorrect ending byte at " + sp); + } + mark = sp; return dp - dp0; } finally { src.position(mark); @@ -950,14 +963,16 @@ public class Base64 { int dl = dst.limit(); int dp0 = dp; int mark = sp; - boolean padding = false; - try { while (sp < sl) { int b = src.get(sp++) & 0xff; if ((b = base64[b]) < 0) { if (b == -2) { // padding byte - padding = true; + if (shiftto == 6 && (sp == sl || src.get(sp++) != '=') || + shiftto == 18) { + throw new IllegalArgumentException( + "Input byte array has wrong 4-byte ending unit"); + } break; } if (isMIME) // skip if for rfc2045 @@ -983,24 +998,23 @@ public class Base64 { if (shiftto == 6) { if (dl - dp < 1) return dp - dp0; - if (padding && (sp + 1 != sl || src.get(sp++) != '=')) - throw new IllegalArgumentException( - "Input buffer has wrong 4-byte ending unit"); dst.put(dp++, (byte)(bits >> 16)); - mark = sp; } else if (shiftto == 0) { if (dl - dp < 2) return dp - dp0; - if (padding && sp != sl) - throw new IllegalArgumentException( - "Input buffer has wrong 4-byte ending unit"); dst.put(dp++, (byte)(bits >> 16)); dst.put(dp++, (byte)(bits >> 8)); - mark = sp; - } else if (padding || shiftto != 18) { + } else if (shiftto == 12) { throw new IllegalArgumentException( "Last unit does not have enough valid bits"); } + while (sp < sl) { + if (isMIME && base64[src.get(sp++)] < 0) + continue; + throw new IllegalArgumentException( + "Input byte array has incorrect ending byte at " + sp); + } + mark = sp; return dp - dp0; } finally { src.position(mark); @@ -1048,12 +1062,20 @@ public class Base64 { int dp = 0; int bits = 0; int shiftto = 18; // pos of first byte of 4-byte atom - boolean padding = false; while (sp < sl) { int b = src[sp++] & 0xff; if ((b = base64[b]) < 0) { - if (b == -2) { // padding byte - padding = true; + if (b == -2) { // padding byte '=' + // xx= shiftto==6&&sp==sl missing last = + // xx=y shiftto==6 last is not = + // = shiftto==18 unnecessary padding + // x= shiftto==12 be taken care later + // together with single x, invalid anyway + if (shiftto == 6 && (sp == sl || src[sp++] != '=') || + shiftto == 18) { + throw new IllegalArgumentException( + "Input byte array has wrong 4-byte ending unit"); + } break; } if (isMIME) // skip if for rfc2045 @@ -1073,22 +1095,23 @@ public class Base64 { bits = 0; } } - // reach end of byte arry or hit padding '=' characters. - // if '=' presents, they must be the last one or two. - if (shiftto == 6) { // xx== - if (padding && (sp + 1 != sl || src[sp] != '=')) - throw new IllegalArgumentException( - "Input byte array has wrong 4-byte ending unit"); + // reached end of byte array or hit padding '=' characters. + if (shiftto == 6) { dst[dp++] = (byte)(bits >> 16); - } else if (shiftto == 0) { // xxx= - if (padding && sp != sl) - throw new IllegalArgumentException( - "Input byte array has wrong 4-byte ending unit"); + } else if (shiftto == 0) { dst[dp++] = (byte)(bits >> 16); dst[dp++] = (byte)(bits >> 8); - } else if (padding || shiftto != 18) { - throw new IllegalArgumentException( - "last unit does not have enough bytes"); + } else if (shiftto == 12) { + throw new IllegalArgumentException( + "Last unit does not have enough valid bits"); + } + // anything left is invalid, if is not MIME. + // if MIME, ignore all non-base64 character + while (sp < sl) { + if (isMIME && base64[src[sp++]] < 0) + continue; + throw new IllegalArgumentException( + "Input byte array has incorrect ending byte at " + sp); } return dp; } @@ -1252,8 +1275,22 @@ public class Base64 { int v = is.read(); if (v == -1) { eof = true; - if (nextin != 18) - throw new IOException("Base64 stream has un-decoded dangling byte(s)."); + if (nextin != 18) { + if (nextin == 12) + throw new IOException("Base64 stream has one un-decoded dangling byte."); + // treat ending xx/xxx without padding character legal. + // same logic as v == 'v' below + b[off++] = (byte)(bits >> (16)); + len--; + if (nextin == 0) { // only one padding byte + if (len == 0) { // no enough output space + bits >>= 8; // shift to lowest byte + nextout = 0; + } else { + b[off++] = (byte) (bits >> 8); + } + } + } if (off == oldOff) return -1; else diff --git a/jdk/test/java/util/Base64/TestBase64.java b/jdk/test/java/util/Base64/TestBase64.java index 0a8eea6e4aa..e0af4de23b7 100644 --- a/jdk/test/java/util/Base64/TestBase64.java +++ b/jdk/test/java/util/Base64/TestBase64.java @@ -22,7 +22,7 @@ */ /** - * @test 4235519 8004212 8005394 8007298 + * @test 4235519 8004212 8005394 8007298 8006295 8006315 8006530 * @summary tests java.util.Base64 */ @@ -112,6 +112,12 @@ public class TestBase64 { // test single-non-base64 character for mime decoding testSingleNonBase64MimeDec(); + + // test decoding of unpadded data + testDecodeUnpadded(); + + // test mime decoding with ignored character after padding + testDecodeIgnoredAfterPadding(); } private static sun.misc.BASE64Encoder sunmisc = new sun.misc.BASE64Encoder(); @@ -359,6 +365,81 @@ public class TestBase64 { } catch (IllegalArgumentException iae) {} } + private static void testDecodeIgnoredAfterPadding() throws Throwable { + for (byte nonBase64 : new byte[] {'#', '(', '!', '\\', '-', '_', '\n', '\r'}) { + byte[][] src = new byte[][] { + "A".getBytes("ascii"), + "AB".getBytes("ascii"), + "ABC".getBytes("ascii"), + "ABCD".getBytes("ascii"), + "ABCDE".getBytes("ascii") + }; + Base64.Encoder encM = Base64.getMimeEncoder(); + Base64.Decoder decM = Base64.getMimeDecoder(); + Base64.Encoder enc = Base64.getEncoder(); + Base64.Decoder dec = Base64.getDecoder(); + for (int i = 0; i < src.length; i++) { + // decode(byte[]) + byte[] encoded = encM.encode(src[i]); + encoded = Arrays.copyOf(encoded, encoded.length + 1); + encoded[encoded.length - 1] = nonBase64; + checkEqual(decM.decode(encoded), src[i], "Non-base64 char is not ignored"); + try { + dec.decode(encoded); + throw new RuntimeException("No IAE for non-base64 char"); + } catch (IllegalArgumentException iae) {} + + // decode(ByteBuffer[], ByteBuffer[]) + ByteBuffer encodedBB = ByteBuffer.wrap(encoded); + ByteBuffer decodedBB = ByteBuffer.allocate(100); + int ret = decM.decode(encodedBB, decodedBB); + byte[] buf = new byte[ret]; + decodedBB.flip(); + decodedBB.get(buf); + checkEqual(buf, src[i], "Non-base64 char is not ignored"); + try { + encodedBB.rewind(); + decodedBB.clear(); + dec.decode(encodedBB, decodedBB); + throw new RuntimeException("No IAE for non-base64 char"); + } catch (IllegalArgumentException iae) {} + // direct + encodedBB.rewind(); + decodedBB = ByteBuffer.allocateDirect(100); + ret = decM.decode(encodedBB, decodedBB); + buf = new byte[ret]; + decodedBB.flip(); + decodedBB.get(buf); + checkEqual(buf, src[i], "Non-base64 char is not ignored"); + try { + encodedBB.rewind(); + decodedBB.clear(); + dec.decode(encodedBB, decodedBB); + throw new RuntimeException("No IAE for non-base64 char"); + } catch (IllegalArgumentException iae) {} + } + } + } + + private static void testDecodeUnpadded() throws Throwable { + byte[] srcA = new byte[] { 'Q', 'Q' }; + byte[] srcAA = new byte[] { 'Q', 'Q', 'E'}; + Base64.Decoder dec = Base64.getDecoder(); + byte[] ret = dec.decode(srcA); + if (ret[0] != 'A') + throw new RuntimeException("Decoding unpadding input A failed"); + ret = dec.decode(srcAA); + if (ret[0] != 'A' && ret[1] != 'A') + throw new RuntimeException("Decoding unpadding input AA failed"); + ret = new byte[10]; + if (dec.wrap(new ByteArrayInputStream(srcA)).read(ret) != 1 && + ret[0] != 'A') + throw new RuntimeException("Decoding unpadding input A from stream failed"); + if (dec.wrap(new ByteArrayInputStream(srcA)).read(ret) != 2 && + ret[0] != 'A' && ret[1] != 'A') + throw new RuntimeException("Decoding unpadding input AA from stream failed"); + } + // single-non-base64-char should be ignored for mime decoding, but // iae for basic decoding private static void testSingleNonBase64MimeDec() throws Throwable { From 78b547afa764065c3a7a5e7240fb1998359410dc Mon Sep 17 00:00:00 2001 From: Jia-Hong Chen Date: Mon, 4 Feb 2013 12:04:38 -0800 Subject: [PATCH 185/210] 8005052: [parfait] #416 X11SurfaceData.c UNINITIALISED OR MISSING RETURN VALUE 8005054: [parfait] #417 X11SurfaceData.c UNINITIALISED OR MISSING RETURN VALUE Reviewed-by: prr, vadim --- jdk/src/solaris/native/sun/java2d/x11/X11SurfaceData.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/jdk/src/solaris/native/sun/java2d/x11/X11SurfaceData.c b/jdk/src/solaris/native/sun/java2d/x11/X11SurfaceData.c index 5b8aeb4be20..cee9bb75bfd 100644 --- a/jdk/src/solaris/native/sun/java2d/x11/X11SurfaceData.c +++ b/jdk/src/solaris/native/sun/java2d/x11/X11SurfaceData.c @@ -135,11 +135,11 @@ jboolean XShared_initIDs(JNIEnv *env, jboolean allowShmPixmaps) useMitShmPixmaps = JNI_FALSE; } } - - return JNI_TRUE; #endif /* MITSHM */ #endif /* !HEADLESS */ + + return JNI_TRUE; } @@ -468,8 +468,8 @@ jboolean XShared_initSurface(JNIEnv *env, X11SDOps *xsdo, jint depth, jint width return JNI_FALSE; } - return JNI_TRUE; #endif /* !HEADLESS */ + return JNI_TRUE; } From 13339482664abfc3ab5f7c3c6fe5a3710628e2c9 Mon Sep 17 00:00:00 2001 From: John Cuthbertson Date: Mon, 4 Feb 2013 13:24:57 -0800 Subject: [PATCH 186/210] 8001384: G1: assert(!is_null(v)) failed: narrow oop value can never be zero Flush any deferred card mark before a Java thread exits. Reviewed-by: brutisso, jmasa --- hotspot/src/share/vm/runtime/thread.cpp | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/hotspot/src/share/vm/runtime/thread.cpp b/hotspot/src/share/vm/runtime/thread.cpp index ff6adde6eee..b2357878954 100644 --- a/hotspot/src/share/vm/runtime/thread.cpp +++ b/hotspot/src/share/vm/runtime/thread.cpp @@ -1500,7 +1500,7 @@ JavaThread::JavaThread(bool is_attaching_via_jni) : } else { _jni_attach_state = _not_attaching_via_jni; } - assert(_deferred_card_mark.is_empty(), "Default MemRegion ctor"); + assert(deferred_card_mark().is_empty(), "Default MemRegion ctor"); _safepoint_visible = false; } @@ -1896,9 +1896,16 @@ void JavaThread::exit(bool destroy_vm, ExitType exit_type) { JvmtiExport::cleanup_thread(this); } -#ifndef SERIALGC - // We must flush G1-related buffers before removing a thread from + // We must flush any deferred card marks before removing a thread from // the list of active threads. + Universe::heap()->flush_deferred_store_barrier(this); + assert(deferred_card_mark().is_empty(), "Should have been flushed"); + +#ifndef SERIALGC + // We must flush the G1-related buffers before removing a thread + // from the list of active threads. We must do this after any deferred + // card marks have been flushed (above) so that any entries that are + // added to the thread's dirty card queue as a result are not lost. if (UseG1GC) { flush_barrier_queues(); } From 4d8014cefadf0e9aead5b3c3cad80301e6c3a410 Mon Sep 17 00:00:00 2001 From: Jonathan Gibbons Date: Mon, 4 Feb 2013 15:30:10 -0800 Subject: [PATCH 187/210] 8007490: NPE from DocumentationTool.run Reviewed-by: darcy --- .../sun/tools/javadoc/api/JavadocTool.java | 6 +-- .../test/tools/javadoc/api/basic/RunTest.java | 52 +++++++++++++++++-- 2 files changed, 51 insertions(+), 7 deletions(-) diff --git a/langtools/src/share/classes/com/sun/tools/javadoc/api/JavadocTool.java b/langtools/src/share/classes/com/sun/tools/javadoc/api/JavadocTool.java index a8aa2786577..e36dfd0913f 100644 --- a/langtools/src/share/classes/com/sun/tools/javadoc/api/JavadocTool.java +++ b/langtools/src/share/classes/com/sun/tools/javadoc/api/JavadocTool.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2013, 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 @@ -139,8 +139,8 @@ public class JavadocTool implements DocumentationTool { @Override public int run(InputStream in, OutputStream out, OutputStream err, String... arguments) { - PrintWriter err_pw = new PrintWriter(err, true); - PrintWriter out_pw = new PrintWriter(out); + PrintWriter err_pw = new PrintWriter(err == null ? System.err : err, true); + PrintWriter out_pw = new PrintWriter(out == null ? System.out : out); try { String standardDocletName = "com.sun.tools.doclets.standard.Standard"; return com.sun.tools.javadoc.Main.execute( diff --git a/langtools/test/tools/javadoc/api/basic/RunTest.java b/langtools/test/tools/javadoc/api/basic/RunTest.java index 2e6c65252df..380f5b69a9d 100644 --- a/langtools/test/tools/javadoc/api/basic/RunTest.java +++ b/langtools/test/tools/javadoc/api/basic/RunTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2013, 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 @@ -23,7 +23,7 @@ /* * @test - * @bug 6493690 + * @bug 6493690 8007490 * @summary javadoc should have a javax.tools.Tool service provider * @build APITest * @run main RunTest @@ -31,6 +31,7 @@ import java.io.ByteArrayOutputStream; import java.io.File; +import java.io.PrintStream; import javax.tools.DocumentationTool; import javax.tools.ToolProvider; @@ -46,7 +47,7 @@ public class RunTest extends APITest { * Verify that run method can be invoked. */ @Test - public void testRun() throws Exception { + public void testRunOK() throws Exception { File testSrc = new File(System.getProperty("test.src")); File srcFile = new File(testSrc, "pkg/C.java"); File outDir = getOutDir(); @@ -77,7 +78,7 @@ public class RunTest extends APITest { * Verify that run method can be invoked. */ @Test - public void testRun2() throws Exception { + public void testRunFail() throws Exception { File outDir = getOutDir(); String badfile = "badfile.java"; String[] args = { "-d", outDir.getPath(), badfile }; @@ -100,5 +101,48 @@ public class RunTest extends APITest { } } + /** + * Verify that null args are accepted. + */ + @Test + public void testNullArgs() throws Exception { + File testSrc = new File(System.getProperty("test.src")); + File srcFile = new File(testSrc, "pkg/C.java"); + File outDir = getOutDir(); + String[] args = { "-d", outDir.getPath(), srcFile.getPath() }; + + ByteArrayOutputStream stdout = new ByteArrayOutputStream(); + PrintStream prevStdout = System.out; + System.setOut(new PrintStream(stdout)); + + ByteArrayOutputStream stderr = new ByteArrayOutputStream(); + PrintStream prevStderr = System.err; + System.setErr(new PrintStream(stderr)); + + int rc ; + try { + DocumentationTool tool = ToolProvider.getSystemDocumentationTool(); + rc = tool.run(null, null, null, args); + } finally { + System.setOut(prevStdout); + System.setErr(prevStderr); + } + + System.err.println("stdout >>" + stdout.toString() + "<<"); + System.err.println("stderr >>" + stderr.toString() + "<<"); + + if (rc == 0) { + System.err.println("call succeeded"); + checkFiles(outDir, standardExpectFiles); + String out = stdout.toString(); + for (String f: standardExpectFiles) { + String f1 = f.replace('/', File.separatorChar); + if (f1.endsWith(".html") && !out.contains(f1)) + error("expected string not found: " + f1); + } + } else { + error("call failed"); + } + } } From 920d11993cab6fa85589e06887af42d1192b3a36 Mon Sep 17 00:00:00 2001 From: Joe Darcy Date: Mon, 4 Feb 2013 17:56:29 -0800 Subject: [PATCH 188/210] 8007113: Upgrade AnnotatedElement.isAnnotionPresent to be a default method Reviewed-by: chegar, jfranck --- jdk/src/share/classes/java/lang/Class.java | 10 ---------- jdk/src/share/classes/java/lang/Package.java | 11 +---------- .../classes/java/lang/reflect/AccessibleObject.java | 8 -------- .../classes/java/lang/reflect/AnnotatedElement.java | 7 ++++++- .../share/classes/java/lang/reflect/Parameter.java | 8 -------- .../sun/reflect/annotation/AnnotatedTypeFactory.java | 5 ----- .../generics/reflectiveObjects/TypeVariableImpl.java | 5 ----- 7 files changed, 7 insertions(+), 47 deletions(-) diff --git a/jdk/src/share/classes/java/lang/Class.java b/jdk/src/share/classes/java/lang/Class.java index 31e2294ebf6..dab6c98e47a 100644 --- a/jdk/src/share/classes/java/lang/Class.java +++ b/jdk/src/share/classes/java/lang/Class.java @@ -3083,16 +3083,6 @@ public final return (A) annotations.get(annotationClass); } - /** - * @throws NullPointerException {@inheritDoc} - * @since 1.5 - */ - public boolean isAnnotationPresent(Class annotationClass) { - Objects.requireNonNull(annotationClass); - - return getAnnotation(annotationClass) != null; - } - /** * @throws NullPointerException {@inheritDoc} * @since 1.8 diff --git a/jdk/src/share/classes/java/lang/Package.java b/jdk/src/share/classes/java/lang/Package.java index 744a292d6ee..234f807181a 100644 --- a/jdk/src/share/classes/java/lang/Package.java +++ b/jdk/src/share/classes/java/lang/Package.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, 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 @@ -385,15 +385,6 @@ public class Package implements java.lang.reflect.AnnotatedElement { return getPackageInfo().getAnnotation(annotationClass); } - /** - * @throws NullPointerException {@inheritDoc} - * @since 1.5 - */ - public boolean isAnnotationPresent( - Class annotationClass) { - return getPackageInfo().isAnnotationPresent(annotationClass); - } - /** * @throws NullPointerException {@inheritDoc} * @since 1.8 diff --git a/jdk/src/share/classes/java/lang/reflect/AccessibleObject.java b/jdk/src/share/classes/java/lang/reflect/AccessibleObject.java index baaec298a85..9986aef6cf7 100644 --- a/jdk/src/share/classes/java/lang/reflect/AccessibleObject.java +++ b/jdk/src/share/classes/java/lang/reflect/AccessibleObject.java @@ -180,14 +180,6 @@ public class AccessibleObject implements AnnotatedElement { throw new AssertionError("All subclasses should override this method"); } - /** - * @throws NullPointerException {@inheritDoc} - * @since 1.5 - */ - public boolean isAnnotationPresent(Class annotationClass) { - return getAnnotation(annotationClass) != null; - } - /** * @throws NullPointerException {@inheritDoc} * @since 1.8 diff --git a/jdk/src/share/classes/java/lang/reflect/AnnotatedElement.java b/jdk/src/share/classes/java/lang/reflect/AnnotatedElement.java index e7de9429b0c..85472ff5b00 100644 --- a/jdk/src/share/classes/java/lang/reflect/AnnotatedElement.java +++ b/jdk/src/share/classes/java/lang/reflect/AnnotatedElement.java @@ -91,6 +91,9 @@ public interface AnnotatedElement { *

The truth value returned by this method is equivalent to: * {@code getAnnotation(annotationClass) != null} * + *

The body of the default method is specified to be the code + * above. + * * @param annotationClass the Class object corresponding to the * annotation type * @return true if an annotation for the specified annotation @@ -98,7 +101,9 @@ public interface AnnotatedElement { * @throws NullPointerException if the given annotation class is null * @since 1.5 */ - boolean isAnnotationPresent(Class annotationClass); + default boolean isAnnotationPresent(Class annotationClass) { + return getAnnotation(annotationClass) != null; + } /** * Returns this element's annotation for the specified type if diff --git a/jdk/src/share/classes/java/lang/reflect/Parameter.java b/jdk/src/share/classes/java/lang/reflect/Parameter.java index 4fda579c5fc..04bc274ca9f 100644 --- a/jdk/src/share/classes/java/lang/reflect/Parameter.java +++ b/jdk/src/share/classes/java/lang/reflect/Parameter.java @@ -280,14 +280,6 @@ public final class Parameter implements AnnotatedElement { return getDeclaredAnnotations(); } - /** - * @throws NullPointerException {@inheritDoc} - */ - public boolean isAnnotationPresent( - Class annotationClass) { - return getAnnotation(annotationClass) != null; - } - private transient Map, Annotation> declaredAnnotations; private synchronized Map, Annotation> declaredAnnotations() { diff --git a/jdk/src/share/classes/sun/reflect/annotation/AnnotatedTypeFactory.java b/jdk/src/share/classes/sun/reflect/annotation/AnnotatedTypeFactory.java index afb4c4865e7..e0524e849dc 100644 --- a/jdk/src/share/classes/sun/reflect/annotation/AnnotatedTypeFactory.java +++ b/jdk/src/share/classes/sun/reflect/annotation/AnnotatedTypeFactory.java @@ -137,11 +137,6 @@ public class AnnotatedTypeFactory { } // AnnotatedElement - @Override - public final boolean isAnnotationPresent(Class annotation) { - return annotations.get(annotation) != null; - } - @Override public final Annotation[] getAnnotations() { return getDeclaredAnnotations(); diff --git a/jdk/src/share/classes/sun/reflect/generics/reflectiveObjects/TypeVariableImpl.java b/jdk/src/share/classes/sun/reflect/generics/reflectiveObjects/TypeVariableImpl.java index 4bc3356278b..528658d0d16 100644 --- a/jdk/src/share/classes/sun/reflect/generics/reflectiveObjects/TypeVariableImpl.java +++ b/jdk/src/share/classes/sun/reflect/generics/reflectiveObjects/TypeVariableImpl.java @@ -188,11 +188,6 @@ public class TypeVariableImpl } // Implementations of AnnotatedElement methods. - public boolean isAnnotationPresent(Class annotationClass) { - Objects.requireNonNull(annotationClass); - return false; - } - @SuppressWarnings("unchecked") public T getAnnotation(Class annotationClass) { Objects.requireNonNull(annotationClass); From 05a047b442e8bdb345cb7dfdeca0b405a2216a46 Mon Sep 17 00:00:00 2001 From: Jonathan Gibbons Date: Mon, 4 Feb 2013 18:14:24 -0800 Subject: [PATCH 189/210] 8007492: DocumentationTool cannot locate standard doclet when invoked from JRE Reviewed-by: darcy --- .../share/classes/com/sun/tools/javadoc/api/JavadocTool.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/langtools/src/share/classes/com/sun/tools/javadoc/api/JavadocTool.java b/langtools/src/share/classes/com/sun/tools/javadoc/api/JavadocTool.java index e36dfd0913f..5df92804aa1 100644 --- a/langtools/src/share/classes/com/sun/tools/javadoc/api/JavadocTool.java +++ b/langtools/src/share/classes/com/sun/tools/javadoc/api/JavadocTool.java @@ -143,8 +143,9 @@ public class JavadocTool implements DocumentationTool { PrintWriter out_pw = new PrintWriter(out == null ? System.out : out); try { String standardDocletName = "com.sun.tools.doclets.standard.Standard"; + ClassLoader cl = getClass().getClassLoader(); return com.sun.tools.javadoc.Main.execute( - "javadoc", err_pw, err_pw, out_pw, standardDocletName, arguments); + "javadoc", err_pw, err_pw, out_pw, standardDocletName, cl, arguments); } finally { err_pw.flush(); out_pw.flush(); From 329bc97900d65183fb4abf9f59e29fbc42244e8a Mon Sep 17 00:00:00 2001 From: Jeremy Manson Date: Mon, 4 Feb 2013 23:53:10 -0500 Subject: [PATCH 190/210] 8006508: Wrong frame constructor is called in os_linux_x86.cpp Reviewed-by: dholmes, coleenp --- hotspot/src/os_cpu/bsd_x86/vm/os_bsd_x86.cpp | 2 +- hotspot/src/os_cpu/linux_x86/vm/os_linux_x86.cpp | 2 +- hotspot/src/os_cpu/windows_x86/vm/os_windows_x86.cpp | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/hotspot/src/os_cpu/bsd_x86/vm/os_bsd_x86.cpp b/hotspot/src/os_cpu/bsd_x86/vm/os_bsd_x86.cpp index fc55e4ec71e..9eabc200bb8 100644 --- a/hotspot/src/os_cpu/bsd_x86/vm/os_bsd_x86.cpp +++ b/hotspot/src/os_cpu/bsd_x86/vm/os_bsd_x86.cpp @@ -372,7 +372,7 @@ frame os::current_frame() { CAST_FROM_FN_PTR(address, os::current_frame)); if (os::is_first_C_frame(&myframe)) { // stack is not walkable - return frame(NULL, NULL, NULL); + return frame(); } else { return os::get_sender_for_C_frame(&myframe); } diff --git a/hotspot/src/os_cpu/linux_x86/vm/os_linux_x86.cpp b/hotspot/src/os_cpu/linux_x86/vm/os_linux_x86.cpp index 907395bb22a..bfb0e960a0c 100644 --- a/hotspot/src/os_cpu/linux_x86/vm/os_linux_x86.cpp +++ b/hotspot/src/os_cpu/linux_x86/vm/os_linux_x86.cpp @@ -189,7 +189,7 @@ frame os::current_frame() { CAST_FROM_FN_PTR(address, os::current_frame)); if (os::is_first_C_frame(&myframe)) { // stack is not walkable - return frame(NULL, NULL, NULL); + return frame(); } else { return os::get_sender_for_C_frame(&myframe); } diff --git a/hotspot/src/os_cpu/windows_x86/vm/os_windows_x86.cpp b/hotspot/src/os_cpu/windows_x86/vm/os_windows_x86.cpp index e8bd38dc13e..1ef29f99a55 100644 --- a/hotspot/src/os_cpu/windows_x86/vm/os_windows_x86.cpp +++ b/hotspot/src/os_cpu/windows_x86/vm/os_windows_x86.cpp @@ -399,7 +399,7 @@ frame os::current_frame() { typedef intptr_t* get_fp_func (); get_fp_func* func = CAST_TO_FN_PTR(get_fp_func*, StubRoutines::x86::get_previous_fp_entry()); - if (func == NULL) return frame(NULL, NULL, NULL); + if (func == NULL) return frame(); intptr_t* fp = (*func)(); #else intptr_t* fp = _get_previous_fp(); @@ -410,7 +410,7 @@ frame os::current_frame() { CAST_FROM_FN_PTR(address, os::current_frame)); if (os::is_first_C_frame(&myframe)) { // stack is not walkable - return frame(NULL, NULL, NULL); + return frame(); } else { return os::get_sender_for_C_frame(&myframe); } From d1a58e452a8ae757003428dd077ca9bbfb85a0f7 Mon Sep 17 00:00:00 2001 From: Jaroslav Bachorik Date: Tue, 5 Feb 2013 12:28:47 +0100 Subject: [PATCH 191/210] 7170447: Intermittent DeadListenerTest.java failure Due to asynchronous nature of processing server notifications it may happen that an "unregister" notification ha$ Reviewed-by: sjiang --- .../mandatory/notif/DeadListenerTest.java | 58 +++++++++++-------- 1 file changed, 35 insertions(+), 23 deletions(-) diff --git a/jdk/test/javax/management/remote/mandatory/notif/DeadListenerTest.java b/jdk/test/javax/management/remote/mandatory/notif/DeadListenerTest.java index d5fd91e527f..db313040c25 100644 --- a/jdk/test/javax/management/remote/mandatory/notif/DeadListenerTest.java +++ b/jdk/test/javax/management/remote/mandatory/notif/DeadListenerTest.java @@ -31,6 +31,7 @@ import com.sun.jmx.remote.internal.ServerNotifForwarder; import java.io.IOException; import java.lang.management.ManagementFactory; +import java.lang.ref.WeakReference; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.ArrayList; @@ -86,20 +87,26 @@ public class DeadListenerTest { Map> listenerMap = (Map>) listenerMapF.get(serverNotifForwarder); assertTrue("Server listenerMap initially empty", mapWithoutKey(listenerMap, delegateName).isEmpty()); - CountListener count1 = new CountListener(); + final AtomicInteger count1Val = new AtomicInteger(); + CountListener count1 = new CountListener(count1Val); mbsc.addNotificationListener(name, count1, null, null); + WeakReference count1Ref = new WeakReference<>(count1); + count1 = null; - CountListener count2 = new CountListener(); + final AtomicInteger count2Val = new AtomicInteger(); + CountListener count2 = new CountListener(count2Val); NotificationFilterSupport dummyFilter = new NotificationFilterSupport(); dummyFilter.enableType(""); mbsc.addNotificationListener(name, count2, dummyFilter, "noddy"); + WeakReference count2Ref = new WeakReference<>(count2); + count2 = null; assertTrue("One entry in listenerMap for two listeners on same MBean", mapWithoutKey(listenerMap, delegateName).size() == 1); Set set = listenerMap.get(name); assertTrue("Set in listenerMap for MBean has two elements", set != null && set.size() == 2); - assertTrue("Initial value of count1 == 0", count1.count() == 0); - assertTrue("Initial value of count2 == 0", count2.count() == 0); + assertTrue("Initial value of count1 == 0", count1Val.get() == 0); + assertTrue("Initial value of count2 == 0", count2Val.get() == 0); Notification notif = new Notification("type", name, 0); @@ -107,11 +114,11 @@ public class DeadListenerTest { // Make sure notifs are working normally. long deadline = System.currentTimeMillis() + 2000; - while ((count1.count() != 1 || count2.count() != 1) && System.currentTimeMillis() < deadline) { + while ((count1Val.get() != 1 || count2Val.get() != 1) && System.currentTimeMillis() < deadline) { Thread.sleep(10); } - assertTrue("New value of count1 == 1", count1.count() == 1); - assertTrue("Initial value of count2 == 1", count2.count() == 1); + assertTrue("New value of count1 == 1", count1Val.get() == 1); + assertTrue("Initial value of count2 == 1", count2Val.get() == 1); // Make sure that removing a nonexistent listener from an existent MBean produces ListenerNotFoundException CountListener count3 = new CountListener(); @@ -136,28 +143,29 @@ public class DeadListenerTest { mbs.unregisterMBean(name); mbean.sendNotification(notif); Thread.sleep(200); - assertTrue("New value of count1 == 1", count1.count() == 1); - assertTrue("Initial value of count2 == 1", count2.count() == 1); + + assertTrue("New value of count1 == 1", count1Val.get() == 1); + assertTrue("Initial value of count2 == 1", count2Val.get() == 1); + + // wait for the listener cleanup to take place upon processing notifications + int countdown = 50; // waiting max. 5 secs + while (countdown-- > 0 && + (count1Ref.get() != null || + count2Ref.get() != null)) { + System.gc(); + Thread.sleep(100); + System.gc(); + } + // listener has been removed or the wait has timed out + + assertTrue("count1 notification listener has not been cleaned up", count1Ref.get() == null); + assertTrue("count2 notification listener has not been cleaned up", count2Ref.get() == null); // Check that there is no trace of the listeners any more in ServerNotifForwarder.listenerMap. // THIS DEPENDS ON JMX IMPLEMENTATION DETAILS. // If the JMX implementation changes, the code here may have to change too. Set setForUnreg = listenerMap.get(name); assertTrue("No trace of unregistered MBean: " + setForUnreg, setForUnreg == null); - - // Remove attempts should fail. - try { - mbsc.removeNotificationListener(name, count1); - assertTrue("Remove of count1 listener should have failed", false); - } catch (ListenerNotFoundException e) { - // OK: expected - } - try { - mbsc.removeNotificationListener(name, count2, dummyFilter, "noddy"); - assertTrue("Remove of count2 listener should have failed", false); - } catch (ListenerNotFoundException e) { - // OK: expected - } } private static Map mapWithoutKey(Map map, K key) { @@ -173,6 +181,10 @@ public class DeadListenerTest { public static class CountListener implements NotificationListener { final AtomicInteger count; + public CountListener(AtomicInteger i) { + count = i; + } + public CountListener() { this.count = new AtomicInteger(); } From 631c9a9bada048a16e31f07f30cbaa60b52250e3 Mon Sep 17 00:00:00 2001 From: Jaroslav Bachorik Date: Tue, 5 Feb 2013 12:36:32 +0100 Subject: [PATCH 192/210] 8005791: Remove java.beans.* imports from com.sun.jmx.mbeanserver.Introspector Reviewed-by: rbackman --- jdk/src/share/classes/com/sun/jmx/mbeanserver/Introspector.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/jdk/src/share/classes/com/sun/jmx/mbeanserver/Introspector.java b/jdk/src/share/classes/com/sun/jmx/mbeanserver/Introspector.java index 2e259a818c8..5680cc66631 100644 --- a/jdk/src/share/classes/com/sun/jmx/mbeanserver/Introspector.java +++ b/jdk/src/share/classes/com/sun/jmx/mbeanserver/Introspector.java @@ -50,8 +50,6 @@ import javax.management.MBeanInfo; import javax.management.NotCompliantMBeanException; import com.sun.jmx.remote.util.EnvHelp; -import java.beans.BeanInfo; -import java.beans.PropertyDescriptor; import java.lang.reflect.Array; import java.lang.reflect.InvocationTargetException; import javax.management.AttributeNotFoundException; From 85c0519ca648a5da2a3ada8b7a0b3683b09574ec Mon Sep 17 00:00:00 2001 From: Vinnie Ryan Date: Tue, 5 Feb 2013 14:25:47 +0000 Subject: [PATCH 193/210] 8007483: attributes are ignored when loading keys from a PKCS12 keystore Reviewed-by: mullan --- .../classes/sun/security/pkcs12/PKCS12KeyStore.java | 7 ++++++- jdk/test/sun/security/pkcs12/StorePasswordTest.java | 13 +++++++++++-- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/jdk/src/share/classes/sun/security/pkcs12/PKCS12KeyStore.java b/jdk/src/share/classes/sun/security/pkcs12/PKCS12KeyStore.java index eefdbff811f..d40e033d9f0 100644 --- a/jdk/src/share/classes/sun/security/pkcs12/PKCS12KeyStore.java +++ b/jdk/src/share/classes/sun/security/pkcs12/PKCS12KeyStore.java @@ -1116,7 +1116,7 @@ public final class PKCS12KeyStore extends KeyStoreSpi { if (privateKeyCount > 0 || secretKeyCount > 0) { if (debug != null) { - debug.println("Storing " + privateKeyCount + + debug.println("Storing " + (privateKeyCount + secretKeyCount) + " protected key(s) in a PKCS#7 data content-type"); } @@ -2122,6 +2122,7 @@ public final class PKCS12KeyStore extends KeyStoreSpi { SecretKeyEntry kEntry = new SecretKeyEntry(); kEntry.protectedSecretKey = secretValue.getOctetString(); bagItem = kEntry; + secretKeyCount++; } else { if (debug != null) { @@ -2220,6 +2221,10 @@ public final class PKCS12KeyStore extends KeyStoreSpi { if (bagItem instanceof PrivateKeyEntry) { keyList.add((PrivateKeyEntry) entry); } + if (entry.attributes == null) { + entry.attributes = new HashSet<>(); + } + entry.attributes.addAll(attributes); if (alias == null) { alias = getUnfriendlyName(); } diff --git a/jdk/test/sun/security/pkcs12/StorePasswordTest.java b/jdk/test/sun/security/pkcs12/StorePasswordTest.java index d258aaa10a7..821b1759a2c 100644 --- a/jdk/test/sun/security/pkcs12/StorePasswordTest.java +++ b/jdk/test/sun/security/pkcs12/StorePasswordTest.java @@ -51,8 +51,12 @@ public class StorePasswordTest { keystore.load(null, null); // Set entry + Set attrs = new HashSet<>(); + attrs.add(new PKCS12Attribute("1.3.5.7.9", "printable1")); + attrs.add(new PKCS12Attribute("2.4.6.8.10", "1F:2F:3F:4F:5F")); + int originalAttrCount = attrs.size() + 2; keystore.setEntry(ALIAS, - new KeyStore.SecretKeyEntry(convertPassword(USER_PASSWORD)), + new KeyStore.SecretKeyEntry(convertPassword(USER_PASSWORD), attrs), new KeyStore.PasswordProtection(PASSWORD)); try (FileOutputStream outStream = new FileOutputStream(KEYSTORE)) { @@ -69,7 +73,12 @@ public class StorePasswordTest { KeyStore.Entry entry = keystore.getEntry(ALIAS, new KeyStore.PasswordProtection(PASSWORD)); - System.out.println("Retrieved entry: " + entry); + int attrCount = entry.getAttributes().size(); + System.out.println("Retrieved entry with " + attrCount + " attrs: " + + entry); + if (attrCount != originalAttrCount) { + throw new Exception("Failed to recover all the entry attributes"); + } SecretKey key = (SecretKey) keystore.getKey(ALIAS, PASSWORD); SecretKeyFactory factory = From 3d09f6b621ca7de743e4058ae0e2cee682d5ba62 Mon Sep 17 00:00:00 2001 From: Eric McCorkle Date: Tue, 5 Feb 2013 14:56:34 +0000 Subject: [PATCH 194/210] 8007389: Remove uses of _ as identifier in jaxp Reviewed-by: lancea, joehw --- jaxp/src/javax/xml/validation/SchemaFactoryFinder.java | 4 ++-- jaxp/src/javax/xml/xpath/XPathFactoryFinder.java | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/jaxp/src/javax/xml/validation/SchemaFactoryFinder.java b/jaxp/src/javax/xml/validation/SchemaFactoryFinder.java index 39c76ed428f..abd0a7ca0af 100644 --- a/jaxp/src/javax/xml/validation/SchemaFactoryFinder.java +++ b/jaxp/src/javax/xml/validation/SchemaFactoryFinder.java @@ -68,7 +68,7 @@ class SchemaFactoryFinder { // Use try/catch block to support applets try { debug = ss.getSystemProperty("jaxp.debug") != null; - } catch (Exception _) { + } catch (Exception unused) { debug = false; } } @@ -113,7 +113,7 @@ class SchemaFactoryFinder { debugPrintln("using thread context class loader ("+classLoader+") for search"); return; } - } catch( Throwable _ ) { + } catch( Throwable unused ) { ; // getContextClassLoader() undefined in JDK1.1 } diff --git a/jaxp/src/javax/xml/xpath/XPathFactoryFinder.java b/jaxp/src/javax/xml/xpath/XPathFactoryFinder.java index 6db1dae1794..b22120da26a 100644 --- a/jaxp/src/javax/xml/xpath/XPathFactoryFinder.java +++ b/jaxp/src/javax/xml/xpath/XPathFactoryFinder.java @@ -56,7 +56,7 @@ class XPathFactoryFinder { // Use try/catch block to support applets try { debug = ss.getSystemProperty("jaxp.debug") != null; - } catch (Exception _) { + } catch (Exception unused) { debug = false; } } @@ -111,7 +111,7 @@ class XPathFactoryFinder { debugPrintln("using thread context class loader ("+classLoader+") for search"); return; } - } catch( Throwable _ ) { + } catch( Throwable unused ) { ; // getContextClassLoader() undefined in JDK1.1 } From 99468dc6c0de703f0232b5bd307c9baffc8062d8 Mon Sep 17 00:00:00 2001 From: Erik Joelsson Date: Tue, 5 Feb 2013 16:50:05 +0100 Subject: [PATCH 195/210] 8007524: build-infra: Incremental build of tools.jar broken Reviewed-by: tbell --- common/makefiles/JavaCompilation.gmk | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/common/makefiles/JavaCompilation.gmk b/common/makefiles/JavaCompilation.gmk index 22c199ad5b5..27257183ac6 100644 --- a/common/makefiles/JavaCompilation.gmk +++ b/common/makefiles/JavaCompilation.gmk @@ -143,8 +143,8 @@ define SetupArchive ifneq (,$2) $1_DEPS:=$2 else - $1_DEPS:=$$(filter $$(addprefix %,$$($1_FIND_PATTERNS)),\ - $$(call CacheFind $$($1_SRCS))) + $1_DEPS:=$$(filter $$(addprefix %,$$($1_SUFFIXES)),\ + $$(call CacheFind,$$($1_SRCS))) ifneq (,$$($1_GREP_INCLUDE_PATTERNS)) $1_DEPS:=$$(filter $$(addsuffix %,$$($1_GREP_INCLUDE_PATTERNS)),$$($1_DEPS)) endif From 014d9489bbe33c841a1a4928d67ef30cac1fc773 Mon Sep 17 00:00:00 2001 From: Igor Ignatyev Date: Tue, 5 Feb 2013 08:25:51 -0800 Subject: [PATCH 196/210] 8006613: adding reason to made_not_compilable Reviewed-by: kvn, vlivanov --- hotspot/src/share/vm/ci/ciMethod.cpp | 4 ++-- hotspot/src/share/vm/ci/ciMethod.hpp | 2 +- .../src/share/vm/compiler/compileBroker.cpp | 2 +- hotspot/src/share/vm/oops/method.cpp | 19 +++++++++++++------ hotspot/src/share/vm/oops/method.hpp | 6 +++--- hotspot/src/share/vm/oops/methodData.hpp | 2 +- .../src/share/vm/runtime/deoptimization.cpp | 2 +- 7 files changed, 22 insertions(+), 15 deletions(-) diff --git a/hotspot/src/share/vm/ci/ciMethod.cpp b/hotspot/src/share/vm/ci/ciMethod.cpp index e5c5e72de9b..0fa11470c94 100644 --- a/hotspot/src/share/vm/ci/ciMethod.cpp +++ b/hotspot/src/share/vm/ci/ciMethod.cpp @@ -977,7 +977,7 @@ bool ciMethod::can_be_compiled() { // ciMethod::set_not_compilable // // Tell the VM that this method cannot be compiled at all. -void ciMethod::set_not_compilable() { +void ciMethod::set_not_compilable(const char* reason) { check_is_loaded(); VM_ENTRY_MARK; ciEnv* env = CURRENT_ENV; @@ -986,7 +986,7 @@ void ciMethod::set_not_compilable() { } else { _is_c2_compilable = false; } - get_Method()->set_not_compilable(env->comp_level()); + get_Method()->set_not_compilable(env->comp_level(), true, reason); } // ------------------------------------------------------------------ diff --git a/hotspot/src/share/vm/ci/ciMethod.hpp b/hotspot/src/share/vm/ci/ciMethod.hpp index 193eb68de05..c98f2c0dccf 100644 --- a/hotspot/src/share/vm/ci/ciMethod.hpp +++ b/hotspot/src/share/vm/ci/ciMethod.hpp @@ -252,7 +252,7 @@ class ciMethod : public ciMetadata { bool has_option(const char *option); bool can_be_compiled(); bool can_be_osr_compiled(int entry_bci); - void set_not_compilable(); + void set_not_compilable(const char* reason = NULL); bool has_compiled_code(); void log_nmethod_identity(xmlStream* log); bool is_not_reached(int bci); diff --git a/hotspot/src/share/vm/compiler/compileBroker.cpp b/hotspot/src/share/vm/compiler/compileBroker.cpp index 41883d1b44d..6f4e671c165 100644 --- a/hotspot/src/share/vm/compiler/compileBroker.cpp +++ b/hotspot/src/share/vm/compiler/compileBroker.cpp @@ -1398,7 +1398,7 @@ bool CompileBroker::compilation_is_prohibited(methodHandle method, int osr_bci, method->print_short_name(tty); tty->cr(); } - method->set_not_compilable_quietly(); + method->set_not_compilable(CompLevel_all, !quietly, "excluded by CompilerOracle"); } return false; diff --git a/hotspot/src/share/vm/oops/method.cpp b/hotspot/src/share/vm/oops/method.cpp index 936090f50c0..7ab6042475b 100644 --- a/hotspot/src/share/vm/oops/method.cpp +++ b/hotspot/src/share/vm/oops/method.cpp @@ -699,7 +699,7 @@ void Method::set_signature_handler(address handler) { } -void Method::print_made_not_compilable(int comp_level, bool is_osr, bool report) { +void Method::print_made_not_compilable(int comp_level, bool is_osr, bool report, const char* reason) { if (PrintCompilation && report) { ttyLocker ttyl; tty->print("made not %scompilable on ", is_osr ? "OSR " : ""); @@ -713,14 +713,21 @@ void Method::print_made_not_compilable(int comp_level, bool is_osr, bool report) } this->print_short_name(tty); int size = this->code_size(); - if (size > 0) + if (size > 0) { tty->print(" (%d bytes)", size); + } + if (reason != NULL) { + tty->print(" %s", reason); + } tty->cr(); } if ((TraceDeoptimization || LogCompilation) && (xtty != NULL)) { ttyLocker ttyl; xtty->begin_elem("make_not_%scompilable thread='" UINTX_FORMAT "'", is_osr ? "osr_" : "", os::current_thread_id()); + if (reason != NULL) { + xtty->print(" reason=\'%s\'", reason); + } xtty->method(this); xtty->stamp(); xtty->end_elem(); @@ -742,8 +749,8 @@ bool Method::is_not_compilable(int comp_level) const { } // call this when compiler finds that this method is not compilable -void Method::set_not_compilable(int comp_level, bool report) { - print_made_not_compilable(comp_level, /*is_osr*/ false, report); +void Method::set_not_compilable(int comp_level, bool report, const char* reason) { + print_made_not_compilable(comp_level, /*is_osr*/ false, report, reason); if (comp_level == CompLevel_all) { set_not_c1_compilable(); set_not_c2_compilable(); @@ -768,8 +775,8 @@ bool Method::is_not_osr_compilable(int comp_level) const { return false; } -void Method::set_not_osr_compilable(int comp_level, bool report) { - print_made_not_compilable(comp_level, /*is_osr*/ true, report); +void Method::set_not_osr_compilable(int comp_level, bool report, const char* reason) { + print_made_not_compilable(comp_level, /*is_osr*/ true, report, reason); if (comp_level == CompLevel_all) { set_not_c1_osr_compilable(); set_not_c2_osr_compilable(); diff --git a/hotspot/src/share/vm/oops/method.hpp b/hotspot/src/share/vm/oops/method.hpp index 72a4faf11d7..fad601e2aaf 100644 --- a/hotspot/src/share/vm/oops/method.hpp +++ b/hotspot/src/share/vm/oops/method.hpp @@ -760,18 +760,18 @@ class Method : public Metadata { // whether it is not compilable for another reason like having a // breakpoint set in it. bool is_not_compilable(int comp_level = CompLevel_any) const; - void set_not_compilable(int comp_level = CompLevel_all, bool report = true); + void set_not_compilable(int comp_level = CompLevel_all, bool report = true, const char* reason = NULL); void set_not_compilable_quietly(int comp_level = CompLevel_all) { set_not_compilable(comp_level, false); } bool is_not_osr_compilable(int comp_level = CompLevel_any) const; - void set_not_osr_compilable(int comp_level = CompLevel_all, bool report = true); + void set_not_osr_compilable(int comp_level = CompLevel_all, bool report = true, const char* reason = NULL); void set_not_osr_compilable_quietly(int comp_level = CompLevel_all) { set_not_osr_compilable(comp_level, false); } private: - void print_made_not_compilable(int comp_level, bool is_osr, bool report); + void print_made_not_compilable(int comp_level, bool is_osr, bool report, const char* reason); public: bool is_not_c1_compilable() const { return access_flags().is_not_c1_compilable(); } diff --git a/hotspot/src/share/vm/oops/methodData.hpp b/hotspot/src/share/vm/oops/methodData.hpp index 133278878ef..728305c1120 100644 --- a/hotspot/src/share/vm/oops/methodData.hpp +++ b/hotspot/src/share/vm/oops/methodData.hpp @@ -1465,7 +1465,7 @@ public: void inc_decompile_count() { _nof_decompiles += 1; if (decompile_count() > (uint)PerMethodRecompilationCutoff) { - method()->set_not_compilable(CompLevel_full_optimization); + method()->set_not_compilable(CompLevel_full_optimization, true, "decompile_count > PerMethodRecompilationCutoff"); } } diff --git a/hotspot/src/share/vm/runtime/deoptimization.cpp b/hotspot/src/share/vm/runtime/deoptimization.cpp index 63df5aa5f88..8f735b7d6fb 100644 --- a/hotspot/src/share/vm/runtime/deoptimization.cpp +++ b/hotspot/src/share/vm/runtime/deoptimization.cpp @@ -1559,7 +1559,7 @@ JRT_ENTRY(void, Deoptimization::uncommon_trap_inner(JavaThread* thread, jint tra if (trap_method() == nm->method()) { make_not_compilable = true; } else { - trap_method->set_not_compilable(CompLevel_full_optimization); + trap_method->set_not_compilable(CompLevel_full_optimization, true, "overflow_recompile_count > PerBytecodeRecompilationCutoff"); // But give grace to the enclosing nm->method(). } } From c2bb152e6c6f09fa30986b1d6f6b25a1284ae0e4 Mon Sep 17 00:00:00 2001 From: John Cuthbertson Date: Tue, 5 Feb 2013 09:13:05 -0800 Subject: [PATCH 197/210] 8005032: G1: Cleanup serial reference processing closures in concurrent marking Reuse the parallel reference processing oop closures during serial reference processing. Reviewed-by: brutisso --- .../gc_implementation/g1/concurrentMark.cpp | 244 +++++++++--------- .../gc_implementation/g1/concurrentMark.hpp | 4 +- 2 files changed, 117 insertions(+), 131 deletions(-) diff --git a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp index b77cd155e74..28c733c150f 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp @@ -2167,7 +2167,8 @@ void ConcurrentMark::completeCleanup() { assert(tmp_free_list.is_empty(), "post-condition"); } -// Support closures for reference procssing in G1 +// Supporting Object and Oop closures for reference discovery +// and processing in during marking bool G1CMIsAliveClosure::do_object_b(oop obj) { HeapWord* addr = (HeapWord*)obj; @@ -2175,73 +2176,26 @@ bool G1CMIsAliveClosure::do_object_b(oop obj) { (!_g1->is_in_g1_reserved(addr) || !_g1->is_obj_ill(obj)); } -class G1CMKeepAliveClosure: public ExtendedOopClosure { - G1CollectedHeap* _g1; - ConcurrentMark* _cm; - public: - G1CMKeepAliveClosure(G1CollectedHeap* g1, ConcurrentMark* cm) : - _g1(g1), _cm(cm) { - assert(Thread::current()->is_VM_thread(), "otherwise fix worker id"); - } +// 'Keep Alive' oop closure used by both serial parallel reference processing. +// Uses the CMTask associated with a worker thread (for serial reference +// processing the CMTask for worker 0 is used) to preserve (mark) and +// trace referent objects. +// +// Using the CMTask and embedded local queues avoids having the worker +// threads operating on the global mark stack. This reduces the risk +// of overflowing the stack - which we would rather avoid at this late +// state. Also using the tasks' local queues removes the potential +// of the workers interfering with each other that could occur if +// operating on the global stack. - virtual void do_oop(narrowOop* p) { do_oop_work(p); } - virtual void do_oop( oop* p) { do_oop_work(p); } - - template void do_oop_work(T* p) { - oop obj = oopDesc::load_decode_heap_oop(p); - HeapWord* addr = (HeapWord*)obj; - - if (_cm->verbose_high()) { - gclog_or_tty->print_cr("\t[0] we're looking at location " - "*"PTR_FORMAT" = "PTR_FORMAT, - p, (void*) obj); - } - - if (_g1->is_in_g1_reserved(addr) && _g1->is_obj_ill(obj)) { - _cm->mark_and_count(obj); - _cm->mark_stack_push(obj); - } - } -}; - -class G1CMDrainMarkingStackClosure: public VoidClosure { - ConcurrentMark* _cm; - CMMarkStack* _markStack; - G1CMKeepAliveClosure* _oopClosure; - public: - G1CMDrainMarkingStackClosure(ConcurrentMark* cm, CMMarkStack* markStack, - G1CMKeepAliveClosure* oopClosure) : - _cm(cm), - _markStack(markStack), - _oopClosure(oopClosure) { } - - void do_void() { - _markStack->drain(_oopClosure, _cm->nextMarkBitMap(), false); - } -}; - -// 'Keep Alive' closure used by parallel reference processing. -// An instance of this closure is used in the parallel reference processing -// code rather than an instance of G1CMKeepAliveClosure. We could have used -// the G1CMKeepAliveClosure as it is MT-safe. Also reference objects are -// placed on to discovered ref lists once so we can mark and push with no -// need to check whether the object has already been marked. Using the -// G1CMKeepAliveClosure would mean, however, having all the worker threads -// operating on the global mark stack. This means that an individual -// worker would be doing lock-free pushes while it processes its own -// discovered ref list followed by drain call. If the discovered ref lists -// are unbalanced then this could cause interference with the other -// workers. Using a CMTask (and its embedded local data structures) -// avoids that potential interference. -class G1CMParKeepAliveAndDrainClosure: public OopClosure { +class G1CMKeepAliveAndDrainClosure: public OopClosure { ConcurrentMark* _cm; CMTask* _task; int _ref_counter_limit; int _ref_counter; public: - G1CMParKeepAliveAndDrainClosure(ConcurrentMark* cm, CMTask* task) : - _cm(cm), _task(task), - _ref_counter_limit(G1RefProcDrainInterval) { + G1CMKeepAliveAndDrainClosure(ConcurrentMark* cm, CMTask* task) : + _cm(cm), _task(task), _ref_counter_limit(G1RefProcDrainInterval) { assert(_ref_counter_limit > 0, "sanity"); _ref_counter = _ref_counter_limit; } @@ -2262,18 +2216,22 @@ class G1CMParKeepAliveAndDrainClosure: public OopClosure { _ref_counter--; if (_ref_counter == 0) { - // We have dealt with _ref_counter_limit references, pushing them and objects - // reachable from them on to the local stack (and possibly the global stack). - // Call do_marking_step() to process these entries. We call the routine in a - // loop, which we'll exit if there's nothing more to do (i.e. we're done - // with the entries that we've pushed as a result of the deal_with_reference - // calls above) or we overflow. - // Note: CMTask::do_marking_step() can set the CMTask::has_aborted() flag - // while there may still be some work to do. (See the comment at the - // beginning of CMTask::do_marking_step() for those conditions - one of which - // is reaching the specified time target.) It is only when - // CMTask::do_marking_step() returns without setting the has_aborted() flag - // that the marking has completed. + // We have dealt with _ref_counter_limit references, pushing them + // and objects reachable from them on to the local stack (and + // possibly the global stack). Call CMTask::do_marking_step() to + // process these entries. + // + // We call CMTask::do_marking_step() in a loop, which we'll exit if + // there's nothing more to do (i.e. we're done with the entries that + // were pushed as a result of the CMTask::deal_with_reference() calls + // above) or we overflow. + // + // Note: CMTask::do_marking_step() can set the CMTask::has_aborted() + // flag while there may still be some work to do. (See the comment at + // the beginning of CMTask::do_marking_step() for those conditions - + // one of which is reaching the specified time target.) It is only + // when CMTask::do_marking_step() returns without setting the + // has_aborted() flag that the marking step has completed. do { double mark_step_duration_ms = G1ConcMarkStepDurationMillis; _task->do_marking_step(mark_step_duration_ms, @@ -2290,36 +2248,59 @@ class G1CMParKeepAliveAndDrainClosure: public OopClosure { } }; -class G1CMParDrainMarkingStackClosure: public VoidClosure { +// 'Drain' oop closure used by both serial and parallel reference processing. +// Uses the CMTask associated with a given worker thread (for serial +// reference processing the CMtask for worker 0 is used). Calls the +// do_marking_step routine, with an unbelievably large timeout value, +// to drain the marking data structures of the remaining entries +// added by the 'keep alive' oop closure above. + +class G1CMDrainMarkingStackClosure: public VoidClosure { ConcurrentMark* _cm; - CMTask* _task; + CMTask* _task; + bool _do_stealing; + bool _do_termination; public: - G1CMParDrainMarkingStackClosure(ConcurrentMark* cm, CMTask* task) : - _cm(cm), _task(task) { } + G1CMDrainMarkingStackClosure(ConcurrentMark* cm, CMTask* task, bool is_par) : + _cm(cm), _task(task) { + assert(is_par || _task->worker_id() == 0, + "Only task for worker 0 should be used if ref processing is single threaded"); + // We only allow stealing and only enter the termination protocol + // in CMTask::do_marking_step() if this closure is being instantiated + // for parallel reference processing. + _do_stealing = _do_termination = is_par; + } void do_void() { do { if (_cm->verbose_high()) { - gclog_or_tty->print_cr("\t[%u] Drain: Calling do marking_step", - _task->worker_id()); + gclog_or_tty->print_cr("\t[%u] Drain: Calling do_marking_step - " + "stealing: %s, termination: %s", + _task->worker_id(), + BOOL_TO_STR(_do_stealing), + BOOL_TO_STR(_do_termination)); } - // We call CMTask::do_marking_step() to completely drain the local and - // global marking stacks. The routine is called in a loop, which we'll - // exit if there's nothing more to do (i.e. we'completely drained the - // entries that were pushed as a result of applying the - // G1CMParKeepAliveAndDrainClosure to the entries on the discovered ref - // lists above) or we overflow the global marking stack. - // Note: CMTask::do_marking_step() can set the CMTask::has_aborted() flag - // while there may still be some work to do. (See the comment at the - // beginning of CMTask::do_marking_step() for those conditions - one of which - // is reaching the specified time target.) It is only when - // CMTask::do_marking_step() returns without setting the has_aborted() flag - // that the marking has completed. + // We call CMTask::do_marking_step() to completely drain the local + // and global marking stacks of entries pushed by the 'keep alive' + // oop closure (an instance of G1CMKeepAliveAndDrainClosure above). + // + // CMTask::do_marking_step() is called in a loop, which we'll exit + // if there's nothing more to do (i.e. we'completely drained the + // entries that were pushed as a a result of applying the 'keep alive' + // closure to the entries on the discovered ref lists) or we overflow + // the global marking stack. + // + // Note: CMTask::do_marking_step() can set the CMTask::has_aborted() + // flag while there may still be some work to do. (See the comment at + // the beginning of CMTask::do_marking_step() for those conditions - + // one of which is reaching the specified time target.) It is only + // when CMTask::do_marking_step() returns without setting the + // has_aborted() flag that the marking step has completed. _task->do_marking_step(1000000000.0 /* something very large */, - true /* do_stealing */, - true /* do_termination */); + _do_stealing, + _do_termination); } while (_task->has_aborted() && !_cm->has_overflown()); } }; @@ -2352,19 +2333,23 @@ class G1CMRefProcTaskProxy: public AbstractGangTask { ProcessTask& _proc_task; G1CollectedHeap* _g1h; ConcurrentMark* _cm; + bool _processing_is_mt; public: G1CMRefProcTaskProxy(ProcessTask& proc_task, G1CollectedHeap* g1h, ConcurrentMark* cm) : AbstractGangTask("Process reference objects in parallel"), - _proc_task(proc_task), _g1h(g1h), _cm(cm) { } + _proc_task(proc_task), _g1h(g1h), _cm(cm) { + ReferenceProcessor* rp = _g1h->ref_processor_cm(); + _processing_is_mt = rp->processing_is_mt(); + } virtual void work(uint worker_id) { CMTask* marking_task = _cm->task(worker_id); G1CMIsAliveClosure g1_is_alive(_g1h); - G1CMParKeepAliveAndDrainClosure g1_par_keep_alive(_cm, marking_task); - G1CMParDrainMarkingStackClosure g1_par_drain(_cm, marking_task); + G1CMKeepAliveAndDrainClosure g1_par_keep_alive(_cm, marking_task); + G1CMDrainMarkingStackClosure g1_par_drain(_cm, marking_task, _processing_is_mt); _proc_task.work(worker_id, g1_is_alive, g1_par_keep_alive, g1_par_drain); } @@ -2372,6 +2357,7 @@ public: void G1CMRefProcTaskExecutor::execute(ProcessTask& proc_task) { assert(_workers != NULL, "Need parallel worker threads."); + assert(_g1h->ref_processor_cm()->processing_is_mt(), "processing is not MT"); G1CMRefProcTaskProxy proc_task_proxy(proc_task, _g1h, _cm); @@ -2399,6 +2385,7 @@ public: void G1CMRefProcTaskExecutor::execute(EnqueueTask& enq_task) { assert(_workers != NULL, "Need parallel worker threads."); + assert(_g1h->ref_processor_cm()->processing_is_mt(), "processing is not MT"); G1CMRefEnqueueTaskProxy enq_task_proxy(enq_task); @@ -2429,59 +2416,58 @@ void ConcurrentMark::weakRefsWork(bool clear_all_soft_refs) { // See the comment in G1CollectedHeap::ref_processing_init() // about how reference processing currently works in G1. - // Process weak references. + // Set the soft reference policy rp->setup_policy(clear_all_soft_refs); assert(_markStack.isEmpty(), "mark stack should be empty"); - G1CMKeepAliveClosure g1_keep_alive(g1h, this); - G1CMDrainMarkingStackClosure - g1_drain_mark_stack(this, &_markStack, &g1_keep_alive); + // Non-MT instances 'Keep Alive' and 'Complete GC' oop closures. + G1CMKeepAliveAndDrainClosure g1_keep_alive(this, task(0)); + G1CMDrainMarkingStackClosure g1_drain_mark_stack(this, task(0), false); + + // We need at least one active thread. If reference processing is + // not multi-threaded we use the current (ConcurrentMarkThread) thread, + // otherwise we use the work gang from the G1CollectedHeap and we + // utilize all the worker threads we can. + uint active_workers = (rp->processing_is_mt() && g1h->workers() != NULL + ? g1h->workers()->active_workers() + : 1U); - // We use the work gang from the G1CollectedHeap and we utilize all - // the worker threads. - uint active_workers = g1h->workers() ? g1h->workers()->active_workers() : 1U; active_workers = MAX2(MIN2(active_workers, _max_worker_id), 1U); G1CMRefProcTaskExecutor par_task_executor(g1h, this, g1h->workers(), active_workers); - if (rp->processing_is_mt()) { - // Set the degree of MT here. If the discovery is done MT, there - // may have been a different number of threads doing the discovery - // and a different number of discovered lists may have Ref objects. - // That is OK as long as the Reference lists are balanced (see - // balance_all_queues() and balance_queues()). - rp->set_active_mt_degree(active_workers); + AbstractRefProcTaskExecutor* executor = (rp->processing_is_mt() + ? &par_task_executor + : NULL); - rp->process_discovered_references(&g1_is_alive, + // Set the degree of MT processing here. If the discovery was done MT, + // the number of threads involved during discovery could differ from + // the number of active workers. This is OK as long as the discovered + // Reference lists are balanced (see balance_all_queues() and balance_queues()). + rp->set_active_mt_degree(active_workers); + + // Process the weak references. + rp->process_discovered_references(&g1_is_alive, &g1_keep_alive, &g1_drain_mark_stack, - &par_task_executor); + executor); - // The work routines of the parallel keep_alive and drain_marking_stack - // will set the has_overflown flag if we overflow the global marking - // stack. - } else { - rp->process_discovered_references(&g1_is_alive, - &g1_keep_alive, - &g1_drain_mark_stack, - NULL); - } + // The do_oop work routines of the keep_alive and drain_marking_stack + // oop closures will set the has_overflown flag if we overflow the + // global marking stack. assert(_markStack.overflow() || _markStack.isEmpty(), "mark stack should be empty (unless it overflowed)"); if (_markStack.overflow()) { - // Should have been done already when we tried to push an + // This should have been done already when we tried to push an // entry on to the global mark stack. But let's do it again. set_has_overflown(); } - if (rp->processing_is_mt()) { - assert(rp->num_q() == active_workers, "why not"); - rp->enqueue_discovered_references(&par_task_executor); - } else { - rp->enqueue_discovered_references(); - } + assert(rp->num_q() == active_workers, "why not"); + + rp->enqueue_discovered_references(executor); rp->verify_no_references_recorded(); assert(!rp->discovery_enabled(), "Post condition"); diff --git a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.hpp b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.hpp index 6701e9f4171..6ec27c7d9fa 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.hpp @@ -371,8 +371,8 @@ class ConcurrentMark: public CHeapObj { friend class CalcLiveObjectsClosure; friend class G1CMRefProcTaskProxy; friend class G1CMRefProcTaskExecutor; - friend class G1CMParKeepAliveAndDrainClosure; - friend class G1CMParDrainMarkingStackClosure; + friend class G1CMKeepAliveAndDrainClosure; + friend class G1CMDrainMarkingStackClosure; protected: ConcurrentMarkThread* _cmThread; // the thread doing the work From 8985a7c2aca7355bcdca70c0627d3c50712a523a Mon Sep 17 00:00:00 2001 From: Jim Holmlund Date: Tue, 5 Feb 2013 18:55:13 +0000 Subject: [PATCH 198/210] 8007504: Remove @ignore from tests that no longer need it Reviewed-by: mcimadamore --- langtools/test/tools/javac/api/T6306137.java | 3 --- .../tools/javac/defaultMethods/TestNoBridgeOnDefaults.java | 1 - langtools/test/tools/javac/lambda/LambdaCapture06.java | 1 - langtools/test/tools/javac/lambda/LambdaExpr15.java | 1 - 4 files changed, 6 deletions(-) diff --git a/langtools/test/tools/javac/api/T6306137.java b/langtools/test/tools/javac/api/T6306137.java index b961d800e4b..8ccf577b088 100644 --- a/langtools/test/tools/javac/api/T6306137.java +++ b/langtools/test/tools/javac/api/T6306137.java @@ -26,9 +26,6 @@ * @bug 6306137 * @summary JSR 199: encoding option doesn't affect standard file manager * @author Peter von der Ahé - * @ignore - * Need to make the contentCache in JavacFileManager be aware of changes to the encoding. - * Need to propogate -source (and -encoding?) down to the JavacFileManager */ import java.io.File; diff --git a/langtools/test/tools/javac/defaultMethods/TestNoBridgeOnDefaults.java b/langtools/test/tools/javac/defaultMethods/TestNoBridgeOnDefaults.java index a52cfb7240e..328629c51e7 100644 --- a/langtools/test/tools/javac/defaultMethods/TestNoBridgeOnDefaults.java +++ b/langtools/test/tools/javac/defaultMethods/TestNoBridgeOnDefaults.java @@ -23,7 +23,6 @@ /* * @test - * @ignore awaits for VM support * @summary check that javac does not generate bridge methods for defaults */ diff --git a/langtools/test/tools/javac/lambda/LambdaCapture06.java b/langtools/test/tools/javac/lambda/LambdaCapture06.java index 85a6feb0e23..99a72d26af6 100644 --- a/langtools/test/tools/javac/lambda/LambdaCapture06.java +++ b/langtools/test/tools/javac/lambda/LambdaCapture06.java @@ -23,7 +23,6 @@ /* * @test - * @ignore investigate as to whether code generation fails * @bug 8003280 * @summary Add lambda tests * Compiler crash when local inner class nested inside lambda captures local variables from enclosing scope diff --git a/langtools/test/tools/javac/lambda/LambdaExpr15.java b/langtools/test/tools/javac/lambda/LambdaExpr15.java index 3b38e8039b6..fd5f4e14bf0 100644 --- a/langtools/test/tools/javac/lambda/LambdaExpr15.java +++ b/langtools/test/tools/javac/lambda/LambdaExpr15.java @@ -23,7 +23,6 @@ /* * @test - * @ignore investigate as to whether code generation fails * @bug 8003280 * @summary Add lambda tests * check that nested inner class in statement lambdas don't get corrupted return statements From 285249963c8f0bb5c9dc17d9475208897db9e8a8 Mon Sep 17 00:00:00 2001 From: Volker Simonis Date: Wed, 6 Feb 2013 11:33:49 -0800 Subject: [PATCH 199/210] 8006807: C2 crash due to out of bounds array access in Parse::do_multianewarray Check ndimensions before accessing length[i] element Reviewed-by: kvn --- hotspot/src/share/vm/opto/parse3.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/hotspot/src/share/vm/opto/parse3.cpp b/hotspot/src/share/vm/opto/parse3.cpp index ac6f4ec8f76..9de92a2ae54 100644 --- a/hotspot/src/share/vm/opto/parse3.cpp +++ b/hotspot/src/share/vm/opto/parse3.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2013, 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 @@ -487,7 +487,8 @@ void Parse::do_multianewarray() { fun, NULL, TypeRawPtr::BOTTOM, makecon(TypeKlassPtr::make(array_klass)), length[0], length[1], length[2], - length[3], length[4]); + (ndimensions > 2) ? length[3] : NULL, + (ndimensions > 3) ? length[4] : NULL); } else { // Create a java array for dimension sizes Node* dims = NULL; From 081316260859560e4a829612bdf745ba842ed787 Mon Sep 17 00:00:00 2001 From: David Katleman Date: Thu, 7 Feb 2013 12:32:32 -0800 Subject: [PATCH 200/210] Added tag jdk8-b76 for changeset 6bb57fea1027 --- .hgtags-top-repo | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags-top-repo b/.hgtags-top-repo index 4b6644480b7..b6c4116ea62 100644 --- a/.hgtags-top-repo +++ b/.hgtags-top-repo @@ -197,3 +197,4 @@ c1be681d80a1f1c848dc671d664fccb19e046a12 jdk8-b72 93b9664f97eeb6f89397a8842318ebacaac9feb9 jdk8-b73 b43aa5bd8ca5c8121336495382d35ecfa7a71536 jdk8-b74 2a713921952cbd77a1e699626976cb6cdfe3e57e jdk8-b75 +278af9fc67e7eba2884936b49ec07345f423aabb jdk8-b76 From a68198e6bc4952542efe09343943b5b8e04f41dc Mon Sep 17 00:00:00 2001 From: David Katleman Date: Thu, 7 Feb 2013 12:32:39 -0800 Subject: [PATCH 201/210] Added tag jdk8-b76 for changeset 2fea158ee664 --- corba/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/corba/.hgtags b/corba/.hgtags index 294902d0bc8..c292f1b787d 100644 --- a/corba/.hgtags +++ b/corba/.hgtags @@ -197,3 +197,4 @@ cb40427f47145b01b7e53c3e02b38ff7625efbda jdk8-b72 191afde59e7be0e1a1d76d06f2a32ff17444f0ec jdk8-b73 2132845cf5f717ff5c240a2431c0c0e03e66e3a5 jdk8-b74 d4e68ce17795601017ac2f952baad7272942c36e jdk8-b75 +58be6ca3c0603882a1ec478724e337aac85e0da0 jdk8-b76 From 2ac871a5a19e90cfbda90be9d6b57db03ca85a10 Mon Sep 17 00:00:00 2001 From: David Katleman Date: Thu, 7 Feb 2013 12:32:50 -0800 Subject: [PATCH 202/210] Added tag jdk8-b76 for changeset faf3f7a9a86f --- hotspot/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/hotspot/.hgtags b/hotspot/.hgtags index 494b1c8a523..c1c175fb80d 100644 --- a/hotspot/.hgtags +++ b/hotspot/.hgtags @@ -312,3 +312,4 @@ d5cb5830f570d1304ea4b196dde672a291b55f29 jdk8-b72 1a3e54283c54aaa8b3437813e8507fbdc966e5b6 jdk8-b74 b4391649e91ea8d37f66317a03d6d2573a93d10d hs25-b17 6778d0b1659323a506ca47600ca29a9d9f8b383d jdk8-b75 +20b605466ccb1b3725eb25314d9e8782199630c5 jdk8-b76 From b0b7e821de5ac83200d6a8068f6b666090ebd801 Mon Sep 17 00:00:00 2001 From: David Katleman Date: Thu, 7 Feb 2013 12:32:59 -0800 Subject: [PATCH 203/210] Added tag jdk8-b76 for changeset 503de5a7b5ef --- jaxp/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/jaxp/.hgtags b/jaxp/.hgtags index 172530e8a1a..ce25c2db0cb 100644 --- a/jaxp/.hgtags +++ b/jaxp/.hgtags @@ -197,3 +197,4 @@ bdf2af722a6b54fca47d8c51d17a1b8f41dd7a3e jdk8-b72 84946404d1e1de003ed2bf218ef8d48906a90e37 jdk8-b73 2087e24a4357eceb6432e94918e75fdc706a27d6 jdk8-b74 ff0b73a6b3f6cea644d37d56d746a37743419fa7 jdk8-b75 +0c08593944d0cd30645f6e1e4946c51ff2b10c8c jdk8-b76 From 2683bbdf2f194389e49b06aa1fecb036880519e5 Mon Sep 17 00:00:00 2001 From: David Katleman Date: Thu, 7 Feb 2013 12:33:01 -0800 Subject: [PATCH 204/210] Added tag jdk8-b76 for changeset 95266e83c5e7 --- jaxws/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/jaxws/.hgtags b/jaxws/.hgtags index 5811938d611..54f020a17c1 100644 --- a/jaxws/.hgtags +++ b/jaxws/.hgtags @@ -197,3 +197,4 @@ d9707230294d54e695e745a90de6112909100f12 jdk8-b72 c606f644a5d9118c14b5822738bf23c300f14f24 jdk8-b73 12db3c5a3393b03eeb09ff26f418c4420c21aaab jdk8-b74 966bf9f3c41a59ff5d86ff4275291c52f329f984 jdk8-b75 +c4853f3f0e89ac60aa5b517f5f224f0f60e08577 jdk8-b76 From 45f09caa8de2244f5c695ceb174155ad6aa3d780 Mon Sep 17 00:00:00 2001 From: David Katleman Date: Thu, 7 Feb 2013 12:33:10 -0800 Subject: [PATCH 205/210] Added tag jdk8-b76 for changeset 0da59c40187c --- jdk/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/jdk/.hgtags b/jdk/.hgtags index ac37d19a025..ea4808559e0 100644 --- a/jdk/.hgtags +++ b/jdk/.hgtags @@ -197,3 +197,4 @@ a996b57e554198f4592a5f3c30f2f9f4075e545d jdk8-b70 733885f57e14cc27f5a5ff0dffe641d2fa3c704a jdk8-b73 57d5d954462831ac353a1f40d3bb05ddb4620952 jdk8-b74 4a67fdb752b7d6329d9be9c28d3f9d6cf7eb9a3c jdk8-b75 +3a263052866137b645ab86498a43693ff5c19e69 jdk8-b76 From 4f0f5861edb130c7277f65f0bf253626e5c9804e Mon Sep 17 00:00:00 2001 From: David Katleman Date: Thu, 7 Feb 2013 12:33:21 -0800 Subject: [PATCH 206/210] Added tag jdk8-b76 for changeset aa274a6f970a --- langtools/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/langtools/.hgtags b/langtools/.hgtags index b29a3af53a1..788268b7d8a 100644 --- a/langtools/.hgtags +++ b/langtools/.hgtags @@ -197,3 +197,4 @@ d7360bf35ee1f40ff78c2e83a22b5446ee464346 jdk8-b69 8d0baee36c7184d55c80354b45704c37d6b7ac79 jdk8-b73 56c97aff46bb577b8668874154c24115a7e8a3e8 jdk8-b74 c2e11e2ec4a3682513e566849e5562f31ded8c65 jdk8-b75 +e81839b3233792415daaab051698edc6067f1a16 jdk8-b76 From 59bf14707f22b1cdc2fa7effa59783e6ac2d852a Mon Sep 17 00:00:00 2001 From: Alejandro Murillo Date: Fri, 8 Feb 2013 08:07:07 -0800 Subject: [PATCH 207/210] Added tag hs25-b18 for changeset f3f52401a78c --- hotspot/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/hotspot/.hgtags b/hotspot/.hgtags index c1c175fb80d..da10e708478 100644 --- a/hotspot/.hgtags +++ b/hotspot/.hgtags @@ -313,3 +313,4 @@ d5cb5830f570d1304ea4b196dde672a291b55f29 jdk8-b72 b4391649e91ea8d37f66317a03d6d2573a93d10d hs25-b17 6778d0b1659323a506ca47600ca29a9d9f8b383d jdk8-b75 20b605466ccb1b3725eb25314d9e8782199630c5 jdk8-b76 +412d722168bc23f8e6d98995202728678561417f hs25-b18 From 8a530c580d0ca71a36cdadae666b19ca1e4ac998 Mon Sep 17 00:00:00 2001 From: "J. Duke" Date: Wed, 5 Jul 2017 18:37:14 +0200 Subject: [PATCH 208/210] Added tag jdk8-b74 for changeset f627eff81962 --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index af2c1e3c0a5..261cb1ea200 100644 --- a/.hgtags +++ b/.hgtags @@ -195,3 +195,4 @@ adb5171c554e14cd86f618b5584f6e3d693d5889 jdk8-b69 a41ada2ed4ef735449531c6ebe6cec593d890a1c jdk8-b71 6725b3961f987cf40f446d1c11cd324a3bec545f jdk8-b72 fe94b40ffd9390f6cffcdf51c0389b0e6dde0c13 jdk8-b73 +f627eff819628822a0777af8062244352f2a29cf jdk8-b74 From 828d2063d29152bedaf9f4f53aa1c851b979e6ba Mon Sep 17 00:00:00 2001 From: "J. Duke" Date: Wed, 5 Jul 2017 18:38:33 +0200 Subject: [PATCH 209/210] Added tag jdk8-b75 for changeset f1478a6d25fd --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index 261cb1ea200..54784e72850 100644 --- a/.hgtags +++ b/.hgtags @@ -196,3 +196,4 @@ a41ada2ed4ef735449531c6ebe6cec593d890a1c jdk8-b71 6725b3961f987cf40f446d1c11cd324a3bec545f jdk8-b72 fe94b40ffd9390f6cffcdf51c0389b0e6dde0c13 jdk8-b73 f627eff819628822a0777af8062244352f2a29cf jdk8-b74 +f1478a6d25fddd311a84dcbfac50824cc1858bdd jdk8-b75 From 918f015f183b159968b360ca0308c78d9cc2c454 Mon Sep 17 00:00:00 2001 From: "J. Duke" Date: Wed, 5 Jul 2017 18:39:14 +0200 Subject: [PATCH 210/210] Added tag jdk8-b76 for changeset f407160c280d --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index 54784e72850..602ce40b2cb 100644 --- a/.hgtags +++ b/.hgtags @@ -197,3 +197,4 @@ a41ada2ed4ef735449531c6ebe6cec593d890a1c jdk8-b71 fe94b40ffd9390f6cffcdf51c0389b0e6dde0c13 jdk8-b73 f627eff819628822a0777af8062244352f2a29cf jdk8-b74 f1478a6d25fddd311a84dcbfac50824cc1858bdd jdk8-b75 +f407160c280d1c5b00d314c535441ac26f195fee jdk8-b76