Merge jdk8-b12
authorduke
Wed, 05 Jul 2017 17:54:24 +0200
changeset 10823 86db042b3385
parent 10822 0294e016d9b1 (diff)
parent 10763 3fac017b40e9 (current diff)
child 10824 b6f58481f3c4
child 10825 c3b8ec8ea08d
child 10826 85bc5eb55e94
child 10827 e8c62dff4701
child 10834 e1524ac19646
child 10840 046ca5cf0539
child 10841 32925b032690
child 10845 e0e566b9d2b2
child 10847 5002669612fc
child 10849 d4e4b5f54af7
child 10851 7e7229cae97b
child 11331 245d2d6da902
child 11875 9e774ef874a3
child 11922 3e0f54141c6d
child 11927 3b9977463e78
child 11932 e49a2dc96c23
Merge
--- a/.hgtags-top-repo	Wed Jul 05 17:53:51 2017 +0200
+++ b/.hgtags-top-repo	Wed Jul 05 17:54:24 2017 +0200
@@ -132,3 +132,4 @@
 fb1bc13260d76447e269e843859eb593fe2a8ab2 jdk8-b08
 8adb70647b5af5273dfe6a540f07be667cd50216 jdk8-b09
 a6c4c248e8fa350c35014fa94bab5ac1a1ac3299 jdk8-b10
+1defbc57940a56f0aa41e9dee87b71e8c8b71103 jdk8-b11
--- a/corba/.hgtags	Wed Jul 05 17:53:51 2017 +0200
+++ b/corba/.hgtags	Wed Jul 05 17:54:24 2017 +0200
@@ -132,3 +132,4 @@
 0d52b1c87aa8fdea7fdc9c4126ea58f95ca6b351 jdk8-b08
 a891732c1a83082177ff7a4cf1506068d9cc0a47 jdk8-b09
 cda87f7fefcee3b89742a57ce5ad9b03a54c210d jdk8-b10
+0199e4fef5cc2bd234c65b93220459ef7a3bb3b1 jdk8-b11
--- a/hotspot/.hgtags	Wed Jul 05 17:53:51 2017 +0200
+++ b/hotspot/.hgtags	Wed Jul 05 17:54:24 2017 +0200
@@ -193,3 +193,5 @@
 e4f412d2b75d2c797acff965aa2c420e3d358f09 hs23-b02
 d815de2e85e511b7deab2a83cf80c0224d011da9 jdk8-b10
 4d3850d9d326ac3a9bee2d867727e954322d014e hs23-b03
+4538caeef7b6cbd4302bebced805d65e68ccf301 jdk8-b11
+6534482ff68ad79066dfe15dfb6d8905f09681bd hs23-b04
--- a/hotspot/make/hotspot_version	Wed Jul 05 17:53:51 2017 +0200
+++ b/hotspot/make/hotspot_version	Wed Jul 05 17:54:24 2017 +0200
@@ -35,7 +35,7 @@
 
 HS_MAJOR_VER=23
 HS_MINOR_VER=0
-HS_BUILD_NUMBER=03
+HS_BUILD_NUMBER=04
 
 JDK_MAJOR_VER=1
 JDK_MINOR_VER=8
--- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp	Wed Jul 05 17:53:51 2017 +0200
+++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp	Wed Jul 05 17:54:24 2017 +0200
@@ -62,7 +62,7 @@
   MinChunkSize = numQuanta(sizeof(FreeChunk), MinObjAlignmentInBytes) * MinObjAlignment;
 
   assert(IndexSetStart == 0 && IndexSetStride == 0, "already set");
-  IndexSetStart  = MinObjAlignment;
+  IndexSetStart  = (int) MinChunkSize;
   IndexSetStride = MinObjAlignment;
 }
 
@@ -138,7 +138,7 @@
   } else {
     _fitStrategy = FreeBlockStrategyNone;
   }
-  checkFreeListConsistency();
+  check_free_list_consistency();
 
   // Initialize locks for parallel case.
 
@@ -1358,17 +1358,29 @@
   ShouldNotReachHere();
 }
 
-bool CompactibleFreeListSpace::verifyChunkInIndexedFreeLists(FreeChunk* fc)
-  const {
+bool CompactibleFreeListSpace::verifyChunkInIndexedFreeLists(FreeChunk* fc) const {
   assert(fc->size() < IndexSetSize, "Size of chunk is too large");
   return _indexedFreeList[fc->size()].verifyChunkInFreeLists(fc);
 }
 
+bool CompactibleFreeListSpace::verify_chunk_is_linear_alloc_block(FreeChunk* fc) const {
+  assert((_smallLinearAllocBlock._ptr != (HeapWord*)fc) ||
+         (_smallLinearAllocBlock._word_size == fc->size()),
+         "Linear allocation block shows incorrect size");
+  return ((_smallLinearAllocBlock._ptr == (HeapWord*)fc) &&
+          (_smallLinearAllocBlock._word_size == fc->size()));
+}
+
+// Check if the purported free chunk is present either as a linear
+// allocation block, the size-indexed table of (smaller) free blocks,
+// or the larger free blocks kept in the binary tree dictionary.
 bool CompactibleFreeListSpace::verifyChunkInFreeLists(FreeChunk* fc) const {
-  if (fc->size() >= IndexSetSize) {
+  if (verify_chunk_is_linear_alloc_block(fc)) {
+    return true;
+  } else if (fc->size() < IndexSetSize) {
+    return verifyChunkInIndexedFreeLists(fc);
+  } else {
     return dictionary()->verifyChunkInFreeLists(fc);
-  } else {
-    return verifyChunkInIndexedFreeLists(fc);
   }
 }
 
@@ -2495,7 +2507,8 @@
   FreeChunk* tail =  _indexedFreeList[size].tail();
   size_t    num = _indexedFreeList[size].count();
   size_t      n = 0;
-  guarantee((size % 2 == 0) || fc == NULL, "Odd slots should be empty");
+  guarantee(((size >= MinChunkSize) && (size % IndexSetStride == 0)) || fc == NULL,
+            "Slot should have been empty");
   for (; fc != NULL; fc = fc->next(), n++) {
     guarantee(fc->size() == size, "Size inconsistency");
     guarantee(fc->isFree(), "!free?");
@@ -2506,14 +2519,14 @@
 }
 
 #ifndef PRODUCT
-void CompactibleFreeListSpace::checkFreeListConsistency() const {
+void CompactibleFreeListSpace::check_free_list_consistency() const {
   assert(_dictionary->minSize() <= IndexSetSize,
     "Some sizes can't be allocated without recourse to"
     " linear allocation buffers");
   assert(MIN_TREE_CHUNK_SIZE*HeapWordSize == sizeof(TreeChunk),
     "else MIN_TREE_CHUNK_SIZE is wrong");
-  assert((IndexSetStride == 2 && IndexSetStart == 2) ||
-         (IndexSetStride == 1 && IndexSetStart == 1), "just checking");
+  assert((IndexSetStride == 2 && IndexSetStart == 4) ||                   // 32-bit
+         (IndexSetStride == 1 && IndexSetStart == 3), "just checking");   // 64-bit
   assert((IndexSetStride != 2) || (MinChunkSize % 2 == 0),
       "Some for-loops may be incorrectly initialized");
   assert((IndexSetStride != 2) || (IndexSetSize % 2 == 1),
@@ -2688,33 +2701,27 @@
   }
 }
 
+// If this is changed in the future to allow parallel
+// access, one would need to take the FL locks and,
+// depending on how it is used, stagger access from
+// parallel threads to reduce contention.
 void CFLS_LAB::retire(int tid) {
   // We run this single threaded with the world stopped;
   // so no need for locks and such.
-#define CFLS_LAB_PARALLEL_ACCESS 0
   NOT_PRODUCT(Thread* t = Thread::current();)
   assert(Thread::current()->is_VM_thread(), "Error");
-  assert(CompactibleFreeListSpace::IndexSetStart == CompactibleFreeListSpace::IndexSetStride,
-         "Will access to uninitialized slot below");
-#if CFLS_LAB_PARALLEL_ACCESS
-  for (size_t i = CompactibleFreeListSpace::IndexSetSize - 1;
-       i > 0;
-       i -= CompactibleFreeListSpace::IndexSetStride) {
-#else // CFLS_LAB_PARALLEL_ACCESS
   for (size_t i =  CompactibleFreeListSpace::IndexSetStart;
        i < CompactibleFreeListSpace::IndexSetSize;
        i += CompactibleFreeListSpace::IndexSetStride) {
-#endif // !CFLS_LAB_PARALLEL_ACCESS
     assert(_num_blocks[i] >= (size_t)_indexedFreeList[i].count(),
            "Can't retire more than what we obtained");
     if (_num_blocks[i] > 0) {
       size_t num_retire =  _indexedFreeList[i].count();
       assert(_num_blocks[i] > num_retire, "Should have used at least one");
       {
-#if CFLS_LAB_PARALLEL_ACCESS
-        MutexLockerEx x(_cfls->_indexedFreeListParLocks[i],
-                        Mutex::_no_safepoint_check_flag);
-#endif // CFLS_LAB_PARALLEL_ACCESS
+        // MutexLockerEx x(_cfls->_indexedFreeListParLocks[i],
+        //                Mutex::_no_safepoint_check_flag);
+
         // Update globals stats for num_blocks used
         _global_num_blocks[i] += (_num_blocks[i] - num_retire);
         _global_num_workers[i]++;
--- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.hpp	Wed Jul 05 17:53:51 2017 +0200
+++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.hpp	Wed Jul 05 17:54:24 2017 +0200
@@ -502,10 +502,14 @@
   void verifyFreeLists()                  const PRODUCT_RETURN;
   void verifyIndexedFreeLists()           const;
   void verifyIndexedFreeList(size_t size) const;
-  // verify that the given chunk is in the free lists.
+  // Verify that the given chunk is in the free lists:
+  // i.e. either the binary tree dictionary, the indexed free lists
+  // or the linear allocation block.
   bool verifyChunkInFreeLists(FreeChunk* fc) const;
+  // Verify that the given chunk is the linear allocation block
+  bool verify_chunk_is_linear_alloc_block(FreeChunk* fc) const;
   // Do some basic checks on the the free lists.
-  void checkFreeListConsistency()         const PRODUCT_RETURN;
+  void check_free_list_consistency()      const PRODUCT_RETURN;
 
   // Printing support
   void dump_at_safepoint_with_locks(CMSCollector* c, outputStream* st);
--- a/hotspot/src/share/vm/gc_implementation/g1/concurrentMarkThread.cpp	Wed Jul 05 17:53:51 2017 +0200
+++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMarkThread.cpp	Wed Jul 05 17:54:24 2017 +0200
@@ -147,12 +147,8 @@
           }
         }
       } while (cm()->restart_for_overflow());
+
       double counting_start_time = os::elapsedVTime();
-
-      // YSR: These look dubious (i.e. redundant) !!! FIX ME
-      slt()->manipulatePLL(SurrogateLockerThread::acquirePLL);
-      slt()->manipulatePLL(SurrogateLockerThread::releaseAndNotifyPLL);
-
       if (!cm()->has_aborted()) {
         double count_start_sec = os::elapsedTime();
         if (PrintGC) {
@@ -175,6 +171,7 @@
           }
         }
       }
+
       double end_time = os::elapsedVTime();
       _vtime_count_accum += (end_time - counting_start_time);
       // Update the total virtual time before doing this, since it will try
@@ -335,13 +332,15 @@
   clear_started();
 }
 
-// Note: this method, although exported by the ConcurrentMarkSweepThread,
-// which is a non-JavaThread, can only be called by a JavaThread.
-// Currently this is done at vm creation time (post-vm-init) by the
-// main/Primordial (Java)Thread.
-// XXX Consider changing this in the future to allow the CMS thread
+// Note: As is the case with CMS - this method, although exported
+// by the ConcurrentMarkThread, which is a non-JavaThread, can only
+// be called by a JavaThread. Currently this is done at vm creation
+// time (post-vm-init) by the main/Primordial (Java)Thread.
+// XXX Consider changing this in the future to allow the CM thread
 // itself to create this thread?
 void ConcurrentMarkThread::makeSurrogateLockerThread(TRAPS) {
+  assert(UseG1GC, "SLT thread needed only for concurrent GC");
+  assert(THREAD->is_Java_thread(), "must be a Java thread");
   assert(_slt == NULL, "SLT already created");
   _slt = SurrogateLockerThread::make(THREAD);
 }
--- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp	Wed Jul 05 17:53:51 2017 +0200
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp	Wed Jul 05 17:54:24 2017 +0200
@@ -5502,34 +5502,36 @@
   CardTableModRefBS* ct_bs = (CardTableModRefBS*) (barrier_set());
   double start = os::elapsedTime();
 
-  // Iterate over the dirty cards region list.
-  G1ParCleanupCTTask cleanup_task(ct_bs, this);
-
-  if (ParallelGCThreads > 0) {
-    set_par_threads(workers()->total_workers());
-    workers()->run_task(&cleanup_task);
-    set_par_threads(0);
-  } else {
-    while (_dirty_cards_region_list) {
-      HeapRegion* r = _dirty_cards_region_list;
-      cleanup_task.clear_cards(r);
-      _dirty_cards_region_list = r->get_next_dirty_cards_region();
-      if (_dirty_cards_region_list == r) {
-        // The last region.
-        _dirty_cards_region_list = NULL;
+  {
+    // Iterate over the dirty cards region list.
+    G1ParCleanupCTTask cleanup_task(ct_bs, this);
+
+    if (ParallelGCThreads > 0) {
+      set_par_threads(workers()->total_workers());
+      workers()->run_task(&cleanup_task);
+      set_par_threads(0);
+    } else {
+      while (_dirty_cards_region_list) {
+        HeapRegion* r = _dirty_cards_region_list;
+        cleanup_task.clear_cards(r);
+        _dirty_cards_region_list = r->get_next_dirty_cards_region();
+        if (_dirty_cards_region_list == r) {
+          // The last region.
+          _dirty_cards_region_list = NULL;
+        }
+        r->set_next_dirty_cards_region(NULL);
       }
-      r->set_next_dirty_cards_region(NULL);
     }
+#ifndef PRODUCT
+    if (G1VerifyCTCleanup || VerifyAfterGC) {
+      G1VerifyCardTableCleanup cleanup_verifier(this, ct_bs);
+      heap_region_iterate(&cleanup_verifier);
+    }
+#endif
   }
 
   double elapsed = os::elapsedTime() - start;
   g1_policy()->record_clear_ct_time(elapsed * 1000.0);
-#ifndef PRODUCT
-  if (G1VerifyCTCleanup || VerifyAfterGC) {
-    G1VerifyCardTableCleanup cleanup_verifier(this, ct_bs);
-    heap_region_iterate(&cleanup_verifier);
-  }
-#endif
 }
 
 void G1CollectedHeap::free_collection_set(HeapRegion* cs_head) {
--- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp	Wed Jul 05 17:53:51 2017 +0200
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp	Wed Jul 05 17:54:24 2017 +0200
@@ -320,6 +320,7 @@
   _par_last_termination_attempts = new double[_parallel_gc_threads];
   _par_last_gc_worker_end_times_ms = new double[_parallel_gc_threads];
   _par_last_gc_worker_times_ms = new double[_parallel_gc_threads];
+  _par_last_gc_worker_other_times_ms = new double[_parallel_gc_threads];
 
   // start conservatively
   _expensive_region_limit_ms = 0.5 * (double) MaxGCPauseMillis;
@@ -497,7 +498,6 @@
   initialize_gc_policy_counters();
 
   G1YoungGenSizer sizer;
-  size_t initial_region_num = sizer.initial_young_region_num();
   _min_desired_young_length = sizer.min_young_region_num();
   _max_desired_young_length = sizer.max_young_region_num();
 
@@ -511,17 +511,14 @@
     }
   }
 
-  // GenCollectorPolicy guarantees that min <= initial <= max.
-  // Asserting here just to state that we rely on this property.
   assert(_min_desired_young_length <= _max_desired_young_length, "Invalid min/max young gen size values");
-  assert(initial_region_num <= _max_desired_young_length, "Initial young gen size too large");
-  assert(_min_desired_young_length <= initial_region_num, "Initial young gen size too small");
 
   set_adaptive_young_list_length(_min_desired_young_length < _max_desired_young_length);
   if (adaptive_young_list_length()) {
     _young_list_fixed_length = 0;
   } else {
-    _young_list_fixed_length = initial_region_num;
+    assert(_min_desired_young_length == _max_desired_young_length, "Min and max young size differ");
+    _young_list_fixed_length = _min_desired_young_length;
   }
   _free_regions_at_end_of_collection = _g1->free_regions();
   update_young_list_target_length();
@@ -976,6 +973,7 @@
     _par_last_termination_attempts[i] = -1234.0;
     _par_last_gc_worker_end_times_ms[i] = -1234.0;
     _par_last_gc_worker_times_ms[i] = -1234.0;
+    _par_last_gc_worker_other_times_ms[i] = -1234.0;
   }
 #endif
 
@@ -984,8 +982,10 @@
     _cur_aux_times_set[i] = false;
   }
 
-  _satb_drain_time_set = false;
-  _last_satb_drain_processed_buffers = -1;
+  // These are initialized to zero here and they are set during
+  // the evacuation pause if marking is in progress.
+  _cur_satb_drain_time_ms = 0.0;
+  _last_satb_drain_processed_buffers = 0;
 
   _last_young_gc_full = false;
 
@@ -1097,61 +1097,65 @@
     (int)total, (int)avg, (int)min, (int)max, (int)max - (int)min);
 }
 
-void G1CollectorPolicy::print_stats (int level,
-                                     const char* str,
-                                     double value) {
+void G1CollectorPolicy::print_stats(int level,
+                                    const char* str,
+                                    double value) {
   LineBuffer(level).append_and_print_cr("[%s: %5.1lf ms]", str, value);
 }
 
-void G1CollectorPolicy::print_stats (int level,
-                                     const char* str,
-                                     int value) {
+void G1CollectorPolicy::print_stats(int level,
+                                    const char* str,
+                                    int value) {
   LineBuffer(level).append_and_print_cr("[%s: %d]", str, value);
 }
 
-double G1CollectorPolicy::avg_value (double* data) {
+double G1CollectorPolicy::avg_value(double* data) {
   if (G1CollectedHeap::use_parallel_gc_threads()) {
     double ret = 0.0;
-    for (uint i = 0; i < ParallelGCThreads; ++i)
+    for (uint i = 0; i < ParallelGCThreads; ++i) {
       ret += data[i];
+    }
     return ret / (double) ParallelGCThreads;
   } else {
     return data[0];
   }
 }
 
-double G1CollectorPolicy::max_value (double* data) {
+double G1CollectorPolicy::max_value(double* data) {
   if (G1CollectedHeap::use_parallel_gc_threads()) {
     double ret = data[0];
-    for (uint i = 1; i < ParallelGCThreads; ++i)
-      if (data[i] > ret)
+    for (uint i = 1; i < ParallelGCThreads; ++i) {
+      if (data[i] > ret) {
         ret = data[i];
+      }
+    }
     return ret;
   } else {
     return data[0];
   }
 }
 
-double G1CollectorPolicy::sum_of_values (double* data) {
+double G1CollectorPolicy::sum_of_values(double* data) {
   if (G1CollectedHeap::use_parallel_gc_threads()) {
     double sum = 0.0;
-    for (uint i = 0; i < ParallelGCThreads; i++)
+    for (uint i = 0; i < ParallelGCThreads; i++) {
       sum += data[i];
+    }
     return sum;
   } else {
     return data[0];
   }
 }
 
-double G1CollectorPolicy::max_sum (double* data1,
-                                   double* data2) {
+double G1CollectorPolicy::max_sum(double* data1, double* data2) {
   double ret = data1[0] + data2[0];
 
   if (G1CollectedHeap::use_parallel_gc_threads()) {
     for (uint i = 1; i < ParallelGCThreads; ++i) {
       double data = data1[i] + data2[i];
-      if (data > ret)
+      if (data > ret) {
         ret = data;
+      }
     }
   }
   return ret;
@@ -1251,6 +1255,10 @@
 
   _n_pauses++;
 
+  // These values are used to update the summary information that is
+  // displayed when TraceGen0Time is enabled, and are output as part
+  // of the PrintGCDetails output, in the non-parallel case.
+
   double ext_root_scan_time = avg_value(_par_last_ext_root_scan_times_ms);
   double mark_stack_scan_time = avg_value(_par_last_mark_stack_scan_times_ms);
   double update_rs_time = avg_value(_par_last_update_rs_times_ms);
@@ -1260,42 +1268,68 @@
   double obj_copy_time = avg_value(_par_last_obj_copy_times_ms);
   double termination_time = avg_value(_par_last_termination_times_ms);
 
-  double parallel_known_time = update_rs_time +
-                               ext_root_scan_time +
-                               mark_stack_scan_time +
-                               scan_rs_time +
-                               obj_copy_time +
-                               termination_time;
-
-  double parallel_other_time = _cur_collection_par_time_ms - parallel_known_time;
-
-  PauseSummary* summary = _summary;
+  double known_time = ext_root_scan_time +
+                      mark_stack_scan_time +
+                      update_rs_time +
+                      scan_rs_time +
+                      obj_copy_time;
+
+  double other_time_ms = elapsed_ms;
+
+  // Subtract the SATB drain time. It's initialized to zero at the
+  // start of the pause and is updated during the pause if marking
+  // is in progress.
+  other_time_ms -= _cur_satb_drain_time_ms;
+
+  if (parallel) {
+    other_time_ms -= _cur_collection_par_time_ms;
+  } else {
+    other_time_ms -= known_time;
+  }
+
+  // Subtract the time taken to clean the card table from the
+  // current value of "other time"
+  other_time_ms -= _cur_clear_ct_time_ms;
+
+  // TraceGen0Time and TraceGen1Time summary info updating.
+  _all_pause_times_ms->add(elapsed_ms);
 
   if (update_stats) {
     _recent_rs_scan_times_ms->add(scan_rs_time);
     _recent_pause_times_ms->add(elapsed_ms);
     _recent_rs_sizes->add(rs_size);
 
-    MainBodySummary* body_summary = summary->main_body_summary();
-    guarantee(body_summary != NULL, "should not be null!");
-
-    if (_satb_drain_time_set)
-      body_summary->record_satb_drain_time_ms(_cur_satb_drain_time_ms);
-    else
-      body_summary->record_satb_drain_time_ms(0.0);
+    _summary->record_total_time_ms(elapsed_ms);
+    _summary->record_other_time_ms(other_time_ms);
+
+    MainBodySummary* body_summary = _summary->main_body_summary();
+    assert(body_summary != NULL, "should not be null!");
+
+    // This will be non-zero iff marking is currently in progress (i.e.
+    // _g1->mark_in_progress() == true) and the currrent pause was not
+    // an initial mark pause. Since the body_summary items are NumberSeqs,
+    // however, they have to be consistent and updated in lock-step with
+    // each other. Therefore we unconditionally record the SATB drain
+    // time - even if it's zero.
+    body_summary->record_satb_drain_time_ms(_cur_satb_drain_time_ms);
 
     body_summary->record_ext_root_scan_time_ms(ext_root_scan_time);
     body_summary->record_mark_stack_scan_time_ms(mark_stack_scan_time);
     body_summary->record_update_rs_time_ms(update_rs_time);
     body_summary->record_scan_rs_time_ms(scan_rs_time);
     body_summary->record_obj_copy_time_ms(obj_copy_time);
+
     if (parallel) {
       body_summary->record_parallel_time_ms(_cur_collection_par_time_ms);
-      body_summary->record_clear_ct_time_ms(_cur_clear_ct_time_ms);
       body_summary->record_termination_time_ms(termination_time);
+
+      double parallel_known_time = known_time + termination_time;
+      double parallel_other_time = _cur_collection_par_time_ms - parallel_known_time;
       body_summary->record_parallel_other_time_ms(parallel_other_time);
     }
+
     body_summary->record_mark_closure_time_ms(_mark_closure_time_ms);
+    body_summary->record_clear_ct_time_ms(_cur_clear_ct_time_ms);
 
     // We exempt parallel collection from this check because Alloc Buffer
     // fragmentation can produce negative collections.  Same with evac
@@ -1307,6 +1341,7 @@
            || _g1->evacuation_failed()
            || surviving_bytes <= _collection_set_bytes_used_before,
            "Or else negative collection!");
+
     _recent_CS_bytes_used_before->add(_collection_set_bytes_used_before);
     _recent_CS_bytes_surviving->add(surviving_bytes);
 
@@ -1357,6 +1392,13 @@
     }
   }
 
+  for (int i = 0; i < _aux_num; ++i) {
+    if (_cur_aux_times_set[i]) {
+      _all_aux_times_ms[i].add(_cur_aux_times_ms[i]);
+    }
+  }
+
+
   if (G1PolicyVerbose > 1) {
     gclog_or_tty->print_cr("   Recording collection pause(%d)", _n_pauses);
   }
@@ -1383,61 +1425,60 @@
                            recent_avg_pause_time_ratio() * 100.0);
   }
 
-  double other_time_ms = elapsed_ms;
-
-  if (_satb_drain_time_set) {
-    other_time_ms -= _cur_satb_drain_time_ms;
-  }
-
-  if (parallel) {
-    other_time_ms -= _cur_collection_par_time_ms + _cur_clear_ct_time_ms;
-  } else {
-    other_time_ms -=
-      update_rs_time +
-      ext_root_scan_time + mark_stack_scan_time +
-      scan_rs_time + obj_copy_time;
-  }
-
+  // PrintGCDetails output
   if (PrintGCDetails) {
+    bool print_marking_info =
+      _g1->mark_in_progress() && !last_pause_included_initial_mark;
+
     gclog_or_tty->print_cr("%s, %1.8lf secs]",
                            (last_pause_included_initial_mark) ? " (initial-mark)" : "",
                            elapsed_ms / 1000.0);
 
-    if (_satb_drain_time_set) {
+    if (print_marking_info) {
       print_stats(1, "SATB Drain Time", _cur_satb_drain_time_ms);
-    }
-    if (_last_satb_drain_processed_buffers >= 0) {
       print_stats(2, "Processed Buffers", _last_satb_drain_processed_buffers);
     }
+
     if (parallel) {
       print_stats(1, "Parallel Time", _cur_collection_par_time_ms);
-      print_par_stats(2, "GC Worker Start Time", _par_last_gc_worker_start_times_ms);
+      print_par_stats(2, "GC Worker Start", _par_last_gc_worker_start_times_ms);
+      print_par_stats(2, "Ext Root Scanning", _par_last_ext_root_scan_times_ms);
+      if (print_marking_info) {
+        print_par_stats(2, "Mark Stack Scanning", _par_last_mark_stack_scan_times_ms);
+      }
       print_par_stats(2, "Update RS", _par_last_update_rs_times_ms);
       print_par_sizes(3, "Processed Buffers", _par_last_update_rs_processed_buffers);
-      print_par_stats(2, "Ext Root Scanning", _par_last_ext_root_scan_times_ms);
-      print_par_stats(2, "Mark Stack Scanning", _par_last_mark_stack_scan_times_ms);
       print_par_stats(2, "Scan RS", _par_last_scan_rs_times_ms);
       print_par_stats(2, "Object Copy", _par_last_obj_copy_times_ms);
       print_par_stats(2, "Termination", _par_last_termination_times_ms);
       print_par_sizes(3, "Termination Attempts", _par_last_termination_attempts);
-      print_par_stats(2, "GC Worker End Time", _par_last_gc_worker_end_times_ms);
+      print_par_stats(2, "GC Worker End", _par_last_gc_worker_end_times_ms);
 
       for (int i = 0; i < _parallel_gc_threads; i++) {
         _par_last_gc_worker_times_ms[i] = _par_last_gc_worker_end_times_ms[i] - _par_last_gc_worker_start_times_ms[i];
+
+        double worker_known_time = _par_last_ext_root_scan_times_ms[i] +
+                                   _par_last_mark_stack_scan_times_ms[i] +
+                                   _par_last_update_rs_times_ms[i] +
+                                   _par_last_scan_rs_times_ms[i] +
+                                   _par_last_obj_copy_times_ms[i] +
+                                   _par_last_termination_times_ms[i];
+
+        _par_last_gc_worker_other_times_ms[i] = _cur_collection_par_time_ms - worker_known_time;
       }
-      print_par_stats(2, "GC Worker Times", _par_last_gc_worker_times_ms);
-
-      print_stats(2, "Parallel Other", parallel_other_time);
-      print_stats(1, "Clear CT", _cur_clear_ct_time_ms);
+      print_par_stats(2, "GC Worker", _par_last_gc_worker_times_ms);
+      print_par_stats(2, "GC Worker Other", _par_last_gc_worker_other_times_ms);
     } else {
+      print_stats(1, "Ext Root Scanning", ext_root_scan_time);
+      if (print_marking_info) {
+        print_stats(1, "Mark Stack Scanning", mark_stack_scan_time);
+      }
       print_stats(1, "Update RS", update_rs_time);
-      print_stats(2, "Processed Buffers",
-                  (int)update_rs_processed_buffers);
-      print_stats(1, "Ext Root Scanning", ext_root_scan_time);
-      print_stats(1, "Mark Stack Scanning", mark_stack_scan_time);
+      print_stats(2, "Processed Buffers", (int)update_rs_processed_buffers);
       print_stats(1, "Scan RS", scan_rs_time);
       print_stats(1, "Object Copying", obj_copy_time);
     }
+    print_stats(1, "Clear CT", _cur_clear_ct_time_ms);
 #ifndef PRODUCT
     print_stats(1, "Cur Clear CC", _cur_clear_cc_time_ms);
     print_stats(1, "Cum Clear CC", _cum_clear_cc_time_ms);
@@ -1461,16 +1502,6 @@
     }
   }
 
-  _all_pause_times_ms->add(elapsed_ms);
-  if (update_stats) {
-    summary->record_total_time_ms(elapsed_ms);
-    summary->record_other_time_ms(other_time_ms);
-  }
-  for (int i = 0; i < _aux_num; ++i)
-    if (_cur_aux_times_set[i]) {
-      _all_aux_times_ms[i].add(_cur_aux_times_ms[i]);
-    }
-
   // Update the efficiency-since-mark vars.
   double proc_ms = elapsed_ms * (double) _parallel_gc_threads;
   if (elapsed_ms < MIN_TIMER_GRANULARITY) {
@@ -2138,17 +2169,17 @@
   _g1->collection_set_iterate(&cs_closure);
 }
 
-void G1CollectorPolicy::print_summary (int level,
-                                       const char* str,
-                                       NumberSeq* seq) const {
+void G1CollectorPolicy::print_summary(int level,
+                                      const char* str,
+                                      NumberSeq* seq) const {
   double sum = seq->sum();
   LineBuffer(level + 1).append_and_print_cr("%-24s = %8.2lf s (avg = %8.2lf ms)",
                 str, sum / 1000.0, seq->avg());
 }
 
-void G1CollectorPolicy::print_summary_sd (int level,
-                                          const char* str,
-                                          NumberSeq* seq) const {
+void G1CollectorPolicy::print_summary_sd(int level,
+                                         const char* str,
+                                         NumberSeq* seq) const {
   print_summary(level, str, seq);
   LineBuffer(level + 6).append_and_print_cr("(num = %5d, std dev = %8.2lf ms, max = %8.2lf ms)",
                 seq->num(), seq->sd(), seq->maximum());
@@ -2211,20 +2242,18 @@
       print_summary(1, "SATB Drain", body_summary->get_satb_drain_seq());
       if (parallel) {
         print_summary(1, "Parallel Time", body_summary->get_parallel_seq());
+        print_summary(2, "Ext Root Scanning", body_summary->get_ext_root_scan_seq());
+        print_summary(2, "Mark Stack Scanning", body_summary->get_mark_stack_scan_seq());
         print_summary(2, "Update RS", body_summary->get_update_rs_seq());
-        print_summary(2, "Ext Root Scanning",
-                      body_summary->get_ext_root_scan_seq());
-        print_summary(2, "Mark Stack Scanning",
-                      body_summary->get_mark_stack_scan_seq());
         print_summary(2, "Scan RS", body_summary->get_scan_rs_seq());
         print_summary(2, "Object Copy", body_summary->get_obj_copy_seq());
         print_summary(2, "Termination", body_summary->get_termination_seq());
-        print_summary(2, "Other", body_summary->get_parallel_other_seq());
+        print_summary(2, "Parallel Other", body_summary->get_parallel_other_seq());
         {
           NumberSeq* other_parts[] = {
-            body_summary->get_update_rs_seq(),
             body_summary->get_ext_root_scan_seq(),
             body_summary->get_mark_stack_scan_seq(),
+            body_summary->get_update_rs_seq(),
             body_summary->get_scan_rs_seq(),
             body_summary->get_obj_copy_seq(),
             body_summary->get_termination_seq()
@@ -2234,18 +2263,16 @@
           check_other_times(2, body_summary->get_parallel_other_seq(),
                             &calc_other_times_ms);
         }
-        print_summary(1, "Mark Closure", body_summary->get_mark_closure_seq());
-        print_summary(1, "Clear CT", body_summary->get_clear_ct_seq());
       } else {
+        print_summary(1, "Ext Root Scanning", body_summary->get_ext_root_scan_seq());
+        print_summary(1, "Mark Stack Scanning", body_summary->get_mark_stack_scan_seq());
         print_summary(1, "Update RS", body_summary->get_update_rs_seq());
-        print_summary(1, "Ext Root Scanning",
-                      body_summary->get_ext_root_scan_seq());
-        print_summary(1, "Mark Stack Scanning",
-                      body_summary->get_mark_stack_scan_seq());
         print_summary(1, "Scan RS", body_summary->get_scan_rs_seq());
         print_summary(1, "Object Copy", body_summary->get_obj_copy_seq());
       }
     }
+    print_summary(1, "Mark Closure", body_summary->get_mark_closure_seq());
+    print_summary(1, "Clear CT", body_summary->get_clear_ct_seq());
     print_summary(1, "Other", summary->get_other_seq());
     {
       if (body_summary != NULL) {
--- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp	Wed Jul 05 17:53:51 2017 +0200
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp	Wed Jul 05 17:54:24 2017 +0200
@@ -74,7 +74,7 @@
     define_num_seq(termination) // parallel only
     define_num_seq(parallel_other) // parallel only
   define_num_seq(mark_closure)
-  define_num_seq(clear_ct)  // parallel only
+  define_num_seq(clear_ct)
 };
 
 class Summary: public PauseSummary,
@@ -115,7 +115,6 @@
   double _cur_collection_par_time_ms;
   double _cur_satb_drain_time_ms;
   double _cur_clear_ct_time_ms;
-  bool   _satb_drain_time_set;
   double _cur_ref_proc_time_ms;
   double _cur_ref_enq_time_ms;
 
@@ -176,6 +175,11 @@
   double* _par_last_gc_worker_end_times_ms;
   double* _par_last_gc_worker_times_ms;
 
+  // Each workers 'other' time i.e. the elapsed time of the parallel
+  // phase of the pause minus the sum of the individual sub-phase
+  // times for a given worker thread.
+  double* _par_last_gc_worker_other_times_ms;
+
   // indicates whether we are in full young or partially young GC mode
   bool _full_young_gcs;
 
@@ -892,11 +896,12 @@
   }
 
   void record_satb_drain_time(double ms) {
+    assert(_g1->mark_in_progress(), "shouldn't be here otherwise");
     _cur_satb_drain_time_ms = ms;
-    _satb_drain_time_set    = true;
   }
 
-  void record_satb_drain_processed_buffers (int processed_buffers) {
+  void record_satb_drain_processed_buffers(int processed_buffers) {
+    assert(_g1->mark_in_progress(), "shouldn't be here otherwise");
     _last_satb_drain_processed_buffers = processed_buffers;
   }
 
--- a/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.cpp	Wed Jul 05 17:53:51 2017 +0200
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.cpp	Wed Jul 05 17:54:24 2017 +0200
@@ -122,10 +122,10 @@
   void set_try_claimed() { _try_claimed = true; }
 
   void scanCard(size_t index, HeapRegion *r) {
-    DirtyCardToOopClosure* cl =
-      r->new_dcto_closure(_oc,
-                         CardTableModRefBS::Precise,
-                         HeapRegionDCTOC::IntoCSFilterKind);
+    // Stack allocate the DirtyCardToOopClosure instance
+    HeapRegionDCTOC cl(_g1h, r, _oc,
+                       CardTableModRefBS::Precise,
+                       HeapRegionDCTOC::IntoCSFilterKind);
 
     // Set the "from" region in the closure.
     _oc->set_region(r);
@@ -140,7 +140,7 @@
       // scans (the rsets of the regions in the cset can intersect).
       _ct_bs->set_card_claimed(index);
       _cards_done++;
-      cl->do_MemRegion(mr);
+      cl.do_MemRegion(mr);
     }
   }
 
--- a/hotspot/src/share/vm/gc_implementation/g1/heapRegion.cpp	Wed Jul 05 17:53:51 2017 +0200
+++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegion.cpp	Wed Jul 05 17:54:24 2017 +0200
@@ -340,14 +340,6 @@
   init_top_at_mark_start();
 }
 
-DirtyCardToOopClosure*
-HeapRegion::new_dcto_closure(OopClosure* cl,
-                             CardTableModRefBS::PrecisionStyle precision,
-                             HeapRegionDCTOC::FilterKind fk) {
-  return new HeapRegionDCTOC(G1CollectedHeap::heap(),
-                             this, cl, precision, fk);
-}
-
 void HeapRegion::hr_clear(bool par, bool clear_space) {
   assert(_humongous_type == NotHumongous,
          "we should have already filtered out humongous regions");
--- a/hotspot/src/share/vm/gc_implementation/g1/heapRegion.hpp	Wed Jul 05 17:53:51 2017 +0200
+++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegion.hpp	Wed Jul 05 17:54:24 2017 +0200
@@ -431,6 +431,14 @@
     return _humongous_start_region;
   }
 
+  // Same as Space::is_in_reserved, but will use the original size of the region.
+  // The original size is different only for start humongous regions. They get
+  // their _end set up to be the end of the last continues region of the
+  // corresponding humongous object.
+  bool is_in_reserved_raw(const void* p) const {
+    return _bottom <= p && p < _orig_end;
+  }
+
   // Makes the current region be a "starts humongous" region, i.e.,
   // the first region in a series of one or more contiguous regions
   // that will contain a single "humongous" object. The two parameters
@@ -569,11 +577,6 @@
   // allocated in the current region before the last call to "save_mark".
   void oop_before_save_marks_iterate(OopClosure* cl);
 
-  DirtyCardToOopClosure*
-  new_dcto_closure(OopClosure* cl,
-                   CardTableModRefBS::PrecisionStyle precision,
-                   HeapRegionDCTOC::FilterKind fk);
-
   // Note the start or end of marking. This tells the heap region
   // that the collector is about to start or has finished (concurrently)
   // marking the heap.
--- a/hotspot/src/share/vm/gc_implementation/g1/heapRegionRemSet.cpp	Wed Jul 05 17:53:51 2017 +0200
+++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegionRemSet.cpp	Wed Jul 05 17:54:24 2017 +0200
@@ -143,7 +143,11 @@
     // If the test below fails, then this table was reused concurrently
     // with this operation.  This is OK, since the old table was coarsened,
     // and adding a bit to the new table is never incorrect.
-    if (loc_hr->is_in_reserved(from)) {
+    // If the table used to belong to a continues humongous region and is
+    // now reused for the corresponding start humongous region, we need to
+    // make sure that we detect this. Thus, we call is_in_reserved_raw()
+    // instead of just is_in_reserved() here.
+    if (loc_hr->is_in_reserved_raw(from)) {
       size_t hw_offset = pointer_delta((HeapWord*)from, loc_hr->bottom());
       CardIdx_t from_card = (CardIdx_t)
           hw_offset >> (CardTableModRefBS::card_shift - LogHeapWordSize);
--- a/hotspot/src/share/vm/gc_implementation/g1/vm_operations_g1.cpp	Wed Jul 05 17:53:51 2017 +0200
+++ b/hotspot/src/share/vm/gc_implementation/g1/vm_operations_g1.cpp	Wed Jul 05 17:54:24 2017 +0200
@@ -23,6 +23,7 @@
  */
 
 #include "precompiled.hpp"
+#include "gc_implementation/g1/concurrentMarkThread.inline.hpp"
 #include "gc_implementation/g1/g1CollectedHeap.inline.hpp"
 #include "gc_implementation/g1/g1CollectorPolicy.hpp"
 #include "gc_implementation/g1/vm_operations_g1.hpp"
@@ -165,6 +166,20 @@
   }
 }
 
+void VM_CGC_Operation::acquire_pending_list_lock() {
+  // The caller may block while communicating
+  // with the SLT thread in order to acquire/release the PLL.
+  ConcurrentMarkThread::slt()->
+    manipulatePLL(SurrogateLockerThread::acquirePLL);
+}
+
+void VM_CGC_Operation::release_and_notify_pending_list_lock() {
+  // The caller may block while communicating
+  // with the SLT thread in order to acquire/release the PLL.
+  ConcurrentMarkThread::slt()->
+    manipulatePLL(SurrogateLockerThread::releaseAndNotifyPLL);
+}
+
 void VM_CGC_Operation::doit() {
   gclog_or_tty->date_stamp(PrintGC && PrintGCDateStamps);
   TraceCPUTime tcpu(PrintGCDetails, true, gclog_or_tty);
@@ -180,12 +195,19 @@
 }
 
 bool VM_CGC_Operation::doit_prologue() {
+  // Note the relative order of the locks must match that in
+  // VM_GC_Operation::doit_prologue() or deadlocks can occur
+  acquire_pending_list_lock();
+
   Heap_lock->lock();
   SharedHeap::heap()->_thread_holds_heap_lock_for_gc = true;
   return true;
 }
 
 void VM_CGC_Operation::doit_epilogue() {
+  // Note the relative order of the unlocks must match that in
+  // VM_GC_Operation::doit_epilogue()
   SharedHeap::heap()->_thread_holds_heap_lock_for_gc = false;
   Heap_lock->unlock();
+  release_and_notify_pending_list_lock();
 }
--- a/hotspot/src/share/vm/gc_implementation/g1/vm_operations_g1.hpp	Wed Jul 05 17:53:51 2017 +0200
+++ b/hotspot/src/share/vm/gc_implementation/g1/vm_operations_g1.hpp	Wed Jul 05 17:54:24 2017 +0200
@@ -93,11 +93,17 @@
   }
 };
 
-// Concurrent GC stop-the-world operations such as initial and final mark;
+// Concurrent GC stop-the-world operations such as remark and cleanup;
 // consider sharing these with CMS's counterparts.
 class VM_CGC_Operation: public VM_Operation {
   VoidClosure* _cl;
   const char* _printGCMessage;
+
+protected:
+  // java.lang.ref.Reference support
+  void acquire_pending_list_lock();
+  void release_and_notify_pending_list_lock();
+
 public:
   VM_CGC_Operation(VoidClosure* cl, const char *printGCMsg)
     : _cl(cl), _printGCMessage(printGCMsg) { }
--- a/hotspot/src/share/vm/gc_implementation/shared/concurrentGCThread.cpp	Wed Jul 05 17:53:51 2017 +0200
+++ b/hotspot/src/share/vm/gc_implementation/shared/concurrentGCThread.cpp	Wed Jul 05 17:54:24 2017 +0200
@@ -224,6 +224,8 @@
   MutexLockerEx x(&_monitor, Mutex::_no_safepoint_check_flag);
   assert(_buffer == empty, "Should be empty");
   assert(msg != empty, "empty message");
+  assert(!Heap_lock->owned_by_self(), "Heap_lock owned by requesting thread");
+
   _buffer = msg;
   while (_buffer != empty) {
     _monitor.notify();
--- a/jaxp/.hgtags	Wed Jul 05 17:53:51 2017 +0200
+++ b/jaxp/.hgtags	Wed Jul 05 17:54:24 2017 +0200
@@ -132,3 +132,4 @@
 de4794dd69c48b08029d158a972993ff9d5627df jdk8-b08
 93554324c014282571aeeb48552ad00d3fedb089 jdk8-b09
 d21a4d5141c04bc9e88f2c0253121d449b66d667 jdk8-b10
+d1b7a4f6dd2065fdeafbcdfd9dcc0072da8c6881 jdk8-b11
--- a/jaxws/.hgtags	Wed Jul 05 17:53:51 2017 +0200
+++ b/jaxws/.hgtags	Wed Jul 05 17:54:24 2017 +0200
@@ -132,3 +132,4 @@
 1c9d4f59acf8f71477473c170239b43b2c9dee24 jdk8-b08
 70172e57cf29efe271b068987eefb601c2a77780 jdk8-b09
 8e7fdc8e3c758644ca6d0fd70bb255e9d2e64cda jdk8-b10
+a12ab897a249feb7859a6e6cd84b49411f4c06ac jdk8-b11
--- a/jdk/.hgtags	Wed Jul 05 17:53:51 2017 +0200
+++ b/jdk/.hgtags	Wed Jul 05 17:54:24 2017 +0200
@@ -132,3 +132,4 @@
 1c023bcd0c5a01ac07bc7eea728aafbb0d8991e9 jdk8-b08
 f1ec21b8142168ff40f3278d2f6b5fe4bd5f3b26 jdk8-b09
 4788745572ef2bde34924ef34e7e4d55ba07e979 jdk8-b10
+7ab0d613cd1a271a9763ffb894dc1f0a5b95a7e4 jdk8-b11
--- a/jdk/make/com/sun/security/auth/module/Makefile	Wed Jul 05 17:53:51 2017 +0200
+++ b/jdk/make/com/sun/security/auth/module/Makefile	Wed Jul 05 17:54:24 2017 +0200
@@ -78,7 +78,3 @@
 #
 include $(BUILDDIR)/common/Library.gmk
 
-#
-# JVMDI implementation lives in the VM.
-#
-OTHER_LDLIBS = $(JVMLIB)
--- a/jdk/make/common/Defs.gmk	Wed Jul 05 17:53:51 2017 +0200
+++ b/jdk/make/common/Defs.gmk	Wed Jul 05 17:54:24 2017 +0200
@@ -220,14 +220,30 @@
 JRE_NONEXIST_LOCALES = en en_US de_DE es_ES fr_FR it_IT ja_JP ko_KR sv_SE zh
 
 #
-# All libraries except libjava and libjvm itself link against libjvm and
-# libjava, the latter for its exported common utilities.  libjava only links
-# against libjvm.  Programs' makefiles take their own responsibility for
+# For now, most libraries except libjava and libjvm itself link against libjvm
+# and libjava, the latter for its exported common utilities. libjava only
+# links against libjvm. Programs' makefiles take their own responsibility for
 # adding other libs.
 #
+# The makefiles for these packages do not link against libjvm and libjava.
+# This list will eventually go away and each Programs' makefiles
+# will have to explicitly declare that they want to link to libjava/libjvm
+#
+NO_JAVALIB_PKGS = \
+		sun.security.mscapi \
+		sun.security.krb5 \
+		sun.security.pkcs11 \
+		sun.security.jgss \
+		sun.security.jgss.wrapper \
+		sun.security.ec \
+		sun.security.smartcardio \
+		com.sun.security.auth.module
+
 ifdef PACKAGE
 # put JAVALIB first, but do not lose any platform specific values....
-  LDLIBS_COMMON = $(JAVALIB)
+  ifeq (,$(findstring $(PACKAGE),$(NO_JAVALIB_PKGS)))
+    LDLIBS_COMMON = $(JAVALIB)
+  endif
 endif # PACKAGE
 
 #
--- a/jdk/make/common/Library.gmk	Wed Jul 05 17:53:51 2017 +0200
+++ b/jdk/make/common/Library.gmk	Wed Jul 05 17:54:24 2017 +0200
@@ -165,7 +165,7 @@
 	$(LINK) -dll -out:$(OBJDIR)/$(@F) \
 	  -map:$(OBJDIR)/$(LIBRARY).map \
 	  $(LFLAGS) @$(OBJDIR)/$(LIBRARY).lcf \
-	  $(OTHER_LCF) $(JAVALIB) $(LDLIBS)
+	  $(OTHER_LCF) $(LDLIBS)
 	$(CP) $(OBJDIR)/$(@F) $@
 	@$(call binary_file_verification,$@)
 	$(CP) $(OBJDIR)/$(LIBRARY).map $(@D)
--- a/jdk/make/java/java/mapfile-vers	Wed Jul 05 17:53:51 2017 +0200
+++ b/jdk/make/java/java/mapfile-vers	Wed Jul 05 17:54:24 2017 +0200
@@ -90,7 +90,6 @@
 		Java_java_io_FileSystem_getFileSystem;
 		Java_java_io_ObjectInputStream_bytesToDoubles;
 		Java_java_io_ObjectInputStream_bytesToFloats;
-		Java_java_io_ObjectInputStream_latestUserDefinedLoader;
 		Java_java_io_ObjectOutputStream_doublesToBytes;
 		Java_java_io_ObjectOutputStream_floatsToBytes;
 		Java_java_io_ObjectStreamClass_hasStaticInitializer;
@@ -275,6 +274,7 @@
                 Java_sun_misc_Version_getJvmVersionInfo;
                 Java_sun_misc_Version_getJvmSpecialVersion;
                 Java_sun_misc_VM_getThreadStateValues;
+		Java_sun_misc_VM_latestUserDefinedLoader;
                 Java_sun_misc_VM_initialize;
 		Java_sun_misc_VMSupport_initAgentProperties;
 
--- a/jdk/make/sun/javazic/tzdata/VERSION	Wed Jul 05 17:53:51 2017 +0200
+++ b/jdk/make/sun/javazic/tzdata/VERSION	Wed Jul 05 17:54:24 2017 +0200
@@ -21,4 +21,4 @@
 # or visit www.oracle.com if you need additional information or have any
 # questions.
 #
-tzdata2011j
+tzdata2011l
--- a/jdk/make/sun/javazic/tzdata/asia	Wed Jul 05 17:53:51 2017 +0200
+++ b/jdk/make/sun/javazic/tzdata/asia	Wed Jul 05 17:54:24 2017 +0200
@@ -2216,7 +2216,47 @@
 # http://www.timeanddate.com/news/time/westbank-gaza-end-dst-2010.html
 # </a>
 
+# From Steffen Thorsen (2011-08-26):
+# Gaza and the West Bank did go back to standard time in the beginning of
+# August, and will now enter daylight saving time again on 2011-08-30
+# 00:00 (so two periods of DST in 2011). The pause was because of
+# Ramadan.
+#
+# <a href="http://www.maannews.net/eng/ViewDetails.aspx?ID=416217">
+# http://www.maannews.net/eng/ViewDetails.aspx?ID=416217
+# </a>
+# Additional info:
+# <a href="http://www.timeanddate.com/news/time/palestine-dst-2011.html">
+# http://www.timeanddate.com/news/time/palestine-dst-2011.html
+# </a>
+
+# From Alexander Krivenyshev (2011-08-27):
+# According to the article in The Jerusalem Post:
+# "...Earlier this month, the Palestinian government in the West Bank decided to
+# move to standard time for 30 days, during Ramadan. The Palestinians in the
+# Gaza Strip accepted the change and also moved their clocks one hour back.
+# The Hamas government said on Saturday that it won't observe summertime after
+# the Muslim feast of Id al-Fitr, which begins on Tuesday..."
+# ...
+# <a href="http://www.jpost.com/MiddleEast/Article.aspx?id=235650">
+# http://www.jpost.com/MiddleEast/Article.aspx?id=235650
+# </a>
+# or
+# <a href="http://www.worldtimezone.com/dst_news/dst_news_gazastrip05.html">
+# http://www.worldtimezone.com/dst_news/dst_news_gazastrip05.html
+# </a>
 # The rules for Egypt are stolen from the `africa' file.
+
+# From Steffen Thorsen (2011-09-30):
+# West Bank did end Daylight Saving Time this morning/midnight (2011-09-30 
+# 00:00).
+# So West Bank and Gaza now have the same time again.
+#
+# Many sources, including:
+# <a href="http://www.maannews.net/eng/ViewDetails.aspx?ID=424808">
+# http://www.maannews.net/eng/ViewDetails.aspx?ID=424808
+# </a>
+
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
 Rule EgyptAsia	1957	only	-	May	10	0:00	1:00	S
 Rule EgyptAsia	1957	1958	-	Oct	 1	0:00	0	-
@@ -2232,19 +2272,37 @@
 Rule Palestine	2006	2008	-	Apr	 1	0:00	1:00	S
 Rule Palestine	2006	only	-	Sep	22	0:00	0	-
 Rule Palestine	2007	only	-	Sep	Thu>=8	2:00	0	-
-Rule Palestine	2008	only	-	Aug	lastFri	2:00	0	-
+Rule Palestine	2008	only	-	Aug	lastFri	0:00	0	-
 Rule Palestine	2009	only	-	Mar	lastFri	0:00	1:00	S
-Rule Palestine	2010	max	-	Mar	lastSat	0:01	1:00	S
-Rule Palestine	2009	max	-	Sep	Fri>=1	2:00	0	-
+Rule Palestine	2009	only	-	Sep	Fri>=1	2:00	0	-
+Rule Palestine	2010	only	-	Mar	lastSat	0:01	1:00	S
 Rule Palestine	2010	only	-	Aug	11	0:00	0	-
 
+# From Arthur David Olson (2011-09-20):
+# 2011 transitions per http://www.timeanddate.com as of 2011-09-20.
+
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Asia/Gaza	2:17:52	-	LMT	1900 Oct
 			2:00	Zion	EET	1948 May 15
 			2:00 EgyptAsia	EE%sT	1967 Jun  5
 			2:00	Zion	I%sT	1996
 			2:00	Jordan	EE%sT	1999
-			2:00 Palestine	EE%sT
+			2:00 Palestine	EE%sT	2011 Apr  2 12:01
+			2:00	1:00	EEST	2011 Aug  1
+			2:00	-	EET
+
+Zone	Asia/Hebron	2:20:23	-	LMT	1900 Oct
+			2:00	Zion	EET	1948 May 15
+			2:00 EgyptAsia	EE%sT	1967 Jun  5
+			2:00	Zion	I%sT	1996
+			2:00	Jordan	EE%sT	1999
+			2:00 Palestine	EE%sT	2008 Aug
+			2:00 	1:00	EEST	2008 Sep
+			2:00 Palestine	EE%sT	2011 Apr  1 12:01
+			2:00	1:00	EEST	2011 Aug  1
+			2:00	-	EET	2011 Aug 30
+			2:00	1:00	EEST	2011 Sep 30 3:00
+			2:00	-	EET
 
 # Paracel Is
 # no information
--- a/jdk/make/sun/javazic/tzdata/australasia	Wed Jul 05 17:53:51 2017 +0200
+++ b/jdk/make/sun/javazic/tzdata/australasia	Wed Jul 05 17:54:24 2017 +0200
@@ -318,6 +318,18 @@
 # http://www.worldtimezone.com/dst_news/dst_news_fiji04.html
 # </a>
 
+# From Steffen Thorsen (2011-10-03):
+# Now the dates have been confirmed, and at least our start date 
+# assumption was correct (end date was one week wrong).
+#
+# <a href="http://www.fiji.gov.fj/index.php?option=com_content&view=article&id=4966:daylight-saving-starts-in-fiji&catid=71:press-releases&Itemid=155">
+# www.fiji.gov.fj/index.php?option=com_content&view=article&id=4966:daylight-saving-starts-in-fiji&catid=71:press-releases&Itemid=155
+# </a>
+# which says
+# Members of the public are reminded to change their time to one hour in 
+# advance at 2am to 3am on October 23, 2011 and one hour back at 3am to 
+# 2am on February 26 next year.
+
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
 Rule	Fiji	1998	1999	-	Nov	Sun>=1	2:00	1:00	S
 Rule	Fiji	1999	2000	-	Feb	lastSun	3:00	0	-
@@ -325,6 +337,8 @@
 Rule	Fiji	2010	only	-	Mar	lastSun	3:00	0	-
 Rule	Fiji	2010	only	-	Oct	24	2:00	1:00	S
 Rule	Fiji	2011	only	-	Mar	Sun>=1	3:00	0	-
+Rule	Fiji	2011	only	-	Oct	23	2:00	1:00	S
+Rule	Fiji	2012	only	-	Feb	26	3:00	0	-
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Pacific/Fiji	11:53:40 -	LMT	1915 Oct 26	# Suva
 			12:00	Fiji	FJ%sT	# Fiji Time
--- a/jdk/make/sun/javazic/tzdata/europe	Wed Jul 05 17:53:51 2017 +0200
+++ b/jdk/make/sun/javazic/tzdata/europe	Wed Jul 05 17:54:24 2017 +0200
@@ -583,9 +583,9 @@
 #
 Rule	Russia	1992	only	-	Mar	lastSat	 23:00	1:00	S
 Rule	Russia	1992	only	-	Sep	lastSat	 23:00	0	-
-Rule	Russia	1993	max	-	Mar	lastSun	 2:00s	1:00	S
+Rule	Russia	1993	2010	-	Mar	lastSun	 2:00s	1:00	S
 Rule	Russia	1993	1995	-	Sep	lastSun	 2:00s	0	-
-Rule	Russia	1996	max	-	Oct	lastSun	 2:00s	0	-
+Rule	Russia	1996	2010	-	Oct	lastSun	 2:00s	0	-
 
 # From Alexander Krivenyshev (2011-06-14):
 # According to Kremlin press service, Russian President Dmitry Medvedev
@@ -605,7 +605,6 @@
 # From Arthur David Olson (2011-06-15):
 # Take "abolishing daylight saving time" to mean that time is now considered
 # to be standard.
-# At least for now, keep the "old" Russia rules for the benefit of Belarus.
 
 # These are for backward compatibility with older versions.
 
@@ -711,6 +710,23 @@
 			1:00	EU	CE%sT
 
 # Belarus
+# From Yauhen Kharuzhy (2011-09-16):
+# By latest Belarus government act Europe/Minsk timezone was changed to
+# GMT+3 without DST (was GMT+2 with DST).
+#
+# Sources (Russian language):
+# 1.
+# <a href="http://www.belta.by/ru/all_news/society/V-Belarusi-otmenjaetsja-perexod-na-sezonnoe-vremja_i_572952.html">
+# http://www.belta.by/ru/all_news/society/V-Belarusi-otmenjaetsja-perexod-na-sezonnoe-vremja_i_572952.html
+# </a>
+# 2.
+# <a href="http://naviny.by/rubrics/society/2011/09/16/ic_articles_116_175144/">
+# http://naviny.by/rubrics/society/2011/09/16/ic_articles_116_175144/
+# </a>
+# 3.
+# <a href="http://news.tut.by/society/250578.html">
+# http://news.tut.by/society/250578.html
+# </a>
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Europe/Minsk	1:50:16 -	LMT	1880
 			1:50	-	MMT	1924 May 2 # Minsk Mean Time
@@ -722,7 +738,8 @@
 			2:00	1:00	EEST	1991 Sep 29 2:00s
 			2:00	-	EET	1992 Mar 29 0:00s
 			2:00	1:00	EEST	1992 Sep 27 0:00s
-			2:00	Russia	EE%sT
+			2:00	Russia	EE%sT	2011 Mar 27 2:00s
+			3:00	-	FET # Further-eastern European Time
 
 # Belgium
 #
@@ -2056,7 +2073,7 @@
 			 2:00	Poland	CE%sT	1946
 			 3:00	Russia	MSK/MSD	1991 Mar 31 2:00s
 			 2:00	Russia	EE%sT	2011 Mar 27 2:00s
-			 3:00	-	KALT
+			 3:00	-	FET # Further-eastern European Time
 #
 # From Oscar van Vlijmen (2001-08-25): [This region consists of]
 # Respublika Adygeya, Arkhangel'skaya oblast',
@@ -2211,7 +2228,7 @@
 # [parts of] Respublika Sakha (Yakutiya), Chitinskaya oblast'.
 
 # From Oscar van Vlijmen (2009-11-29):
-# ...some regions of RUssia were merged with others since 2005...
+# ...some regions of [Russia] were merged with others since 2005...
 # Some names were changed, no big deal, except for one instance: a new name.
 # YAK/YAKST: UTC+9 Zabajkal'skij kraj.
 
@@ -2635,6 +2652,28 @@
 # of March at 3am the time is changing to 4am and each last Sunday of
 # October the time at 4am is changing to 3am"
 
+# From Alexander Krivenyshev (2011-09-20):
+# On September 20, 2011 the deputies of the Verkhovna Rada agreed to
+# abolish the transfer clock to winter time.
+#
+# Bill number 8330 of MP from the Party of Regions Oleg Nadoshi got
+# approval from 266 deputies.
+#
+# Ukraine abolishes transter back to the winter time (in Russian)
+# <a href="http://news.mail.ru/politics/6861560/">
+# http://news.mail.ru/politics/6861560/
+# </a>
+#
+# The Ukrainians will no longer change the clock (in Russian)
+# <a href="http://www.segodnya.ua/news/14290482.html">
+# http://www.segodnya.ua/news/14290482.html
+# </a>
+#
+# Deputies cancelled the winter time (in Russian)
+# <a href="http://www.pravda.com.ua/rus/news/2011/09/20/6600616/">
+# http://www.pravda.com.ua/rus/news/2011/09/20/6600616/
+# </a>
+
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 # Most of Ukraine since 1970 has been like Kiev.
 # "Kyiv" is the transliteration of the Ukrainian name, but
@@ -2648,7 +2687,8 @@
 			3:00	-	MSK	1990 Jul  1 2:00
 			2:00	-	EET	1992
 			2:00	E-Eur	EE%sT	1995
-			2:00	EU	EE%sT
+			2:00	EU	EE%sT	2011 Mar lastSun 1:00u
+			3:00	-	FET # Further-eastern European Time
 # Ruthenia used CET 1990/1991.
 # "Uzhhorod" is the transliteration of the Ukrainian name, but
 # "Uzhgorod" is more common in English.
@@ -2662,7 +2702,8 @@
 			1:00	-	CET	1991 Mar 31 3:00
 			2:00	-	EET	1992
 			2:00	E-Eur	EE%sT	1995
-			2:00	EU	EE%sT
+			2:00	EU	EE%sT	2011 Mar lastSun 1:00u
+			3:00	-	FET # Further-eastern European Time
 # Zaporozh'ye and eastern Lugansk oblasts observed DST 1990/1991.
 # "Zaporizhia" is the transliteration of the Ukrainian name, but
 # "Zaporozh'ye" is more common in English.  Use the common English
@@ -2675,7 +2716,8 @@
 			1:00	C-Eur	CE%sT	1943 Oct 25
 			3:00	Russia	MSK/MSD	1991 Mar 31 2:00
 			2:00	E-Eur	EE%sT	1995
-			2:00	EU	EE%sT
+			2:00	EU	EE%sT	2011 Mar lastSun 1:00u
+			3:00	-	FET # Further-eastern European Time
 # Central Crimea used Moscow time 1994/1997.
 Zone Europe/Simferopol	2:16:24 -	LMT	1880
 			2:16	-	SMT	1924 May  2 # Simferopol Mean T
@@ -2700,7 +2742,8 @@
 # Assume it happened in March by not changing the clocks.
 			3:00	Russia	MSK/MSD	1997
 			3:00	-	MSK	1997 Mar lastSun 1:00u
-			2:00	EU	EE%sT
+			2:00	EU	EE%sT	2011 Mar lastSun 1:00u
+			3:00	-	FET # Further-eastern European Time
 
 ###############################################################################
 
--- a/jdk/make/sun/javazic/tzdata/northamerica	Wed Jul 05 17:53:51 2017 +0200
+++ b/jdk/make/sun/javazic/tzdata/northamerica	Wed Jul 05 17:54:24 2017 +0200
@@ -505,7 +505,7 @@
 			 -8:00	US	P%sT	1983 Oct 30 2:00
 			 -9:00	US	Y%sT	1983 Nov 30
 			 -9:00	US	AK%sT
-Zone America/Sitka	 -14:58:47 -	LMT	1867 Oct 18
+Zone America/Sitka	 14:58:47 -	LMT	1867 Oct 18
 			 -9:01:13 -	LMT	1900 Aug 20 12:00
 			 -8:00	-	PST	1942
 			 -8:00	US	P%sT	1946
@@ -1190,31 +1190,21 @@
 # INMS (2000-09-12) says that, since 1988 at least, Newfoundland switches
 # at 00:01 local time.  For now, assume it started in 1987.
 
-# From Michael Pelley (2011-08-05):
-# The Government of Newfoundland and Labrador has pending changes to
-# modify the hour for daylight savings time to come into effect in
-# November 2011. This modification would change the time from 12:01AM to
-# 2:00AM on the dates of the switches of Daylight Savings Time to/from
-# Standard Time.
-#
-# As a matter of reference, in Canada provinces have the authority of
-# setting time zone information. The legislation has passed our
-# legislative body (The House of Assembly) and is awaiting the
-# proclamation to come into effect. You may find this information at:
-# <a href="http://www.assembly.nl.ca/legislation/sr/lists/Proclamation.htm">
-# http://www.assembly.nl.ca/legislation/sr/lists/Proclamation.htm
-# </a>
-# and
-# search within that web page for Standard Time (Amendment) Act. The Act
-# may be found at:
-# <a href="http://www.assembly.nl.ca/business/bills/Bill1106.htm">
-# http://www.assembly.nl.ca/business/bills/Bill1106.htm
+# From Michael Pelley (2011-09-12):
+# We received today, Monday, September 12, 2011, notification that the
+# changes to the Newfoundland Standard Time Act have been proclaimed.
+# The change in the Act stipulates that the change from Daylight Savings
+# Time to Standard Time and from Standard Time to Daylight Savings Time
+# now occurs at 2:00AM.
+# ...
+# <a href="http://www.assembly.nl.ca/legislation/sr/annualstatutes/2011/1106.chp.htm">
+# http://www.assembly.nl.ca/legislation/sr/annualstatutes/2011/1106.chp.htm
 # </a>
 # ...
-# MICHAEL PELLEY | Manager of Enterprise Architecture - Solution Delivery
-# Office of the Chief Information Officer Executive Council Government of
-# Newfoundland & Labrador P.O. Box 8700, 40 Higgins Line, St. John's NL
-# A1B 4J6
+# MICHAEL PELLEY  |  Manager of Enterprise Architecture - Solution Delivery
+# Office of the Chief Information Officer
+# Executive Council
+# Government of Newfoundland & Labrador
 
 Rule	StJohns	1987	only	-	Apr	Sun>=1	0:01	1:00	D
 Rule	StJohns	1987	2006	-	Oct	lastSun	0:01	0	S
--- a/jdk/make/sun/javazic/tzdata/southamerica	Wed Jul 05 17:53:51 2017 +0200
+++ b/jdk/make/sun/javazic/tzdata/southamerica	Wed Jul 05 17:54:24 2017 +0200
@@ -819,6 +819,26 @@
 # <a href="http://www.timeanddate.com/news/time/brazil-dst-2008-2009.html">
 # http://www.timeanddate.com/news/time/brazil-dst-2008-2009.html
 # </a>
+#
+# From Alexander Krivenyshev (2011-10-04):
+# State Bahia will return to Daylight savings time this year after 8 years off.
+# The announcement was made by Governor Jaques Wagner in an interview to a 
+# television station in Salvador. 
+
+# In Portuguese:
+# <a href="http://g1.globo.com/bahia/noticia/2011/10/governador-jaques-wagner-confirma-horario-de-verao-na-bahia.html">
+# http://g1.globo.com/bahia/noticia/2011/10/governador-jaques-wagner-confirma-horario-de-verao-na-bahia.html
+# </a> and
+# <a href="http://noticias.terra.com.br/brasil/noticias/0,,OI5390887-EI8139,00-Bahia+volta+a+ter+horario+de+verao+apos+oito+anos.html">
+# http://noticias.terra.com.br/brasil/noticias/0,,OI5390887-EI8139,00-Bahia+volta+a+ter+horario+de+verao+apos+oito+anos.html
+# </a>
+
+# From Guilherme Bernardes Rodrigues (2011-10-07):
+# There is news in the media, however there is still no decree about it.
+# I just send a e-mail to Zulmira Brandão at
+# <a href="http://pcdsh01.on.br/">http://pcdsh01.on.br/</a> the
+# oficial agency about time in Brazil, and she confirmed that the old rule is
+# still in force.
 
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
 # Decree <a href="http://pcdsh01.on.br/HV20466.htm">20,466</a> (1931-10-01)
@@ -1057,6 +1077,9 @@
 Zone America/Bahia	-2:34:04 -	LMT	1914
 			-3:00	Brazil	BR%sT	2003 Sep 24
 			-3:00	-	BRT
+# as noted above, not yet in operation.
+#			-3:00	-	BRT	2011 Oct 16
+#			-3:00	Brazil	BR%sT
 #
 # Goias (GO), Distrito Federal (DF), Minas Gerais (MG),
 # Espirito Santo (ES), Rio de Janeiro (RJ), Sao Paulo (SP), Parana (PR),
--- a/jdk/make/sun/javazic/tzdata/zone.tab	Wed Jul 05 17:53:51 2017 +0200
+++ b/jdk/make/sun/javazic/tzdata/zone.tab	Wed Jul 05 17:54:24 2017 +0200
@@ -341,7 +341,8 @@
 PM	+4703-05620	America/Miquelon
 PN	-2504-13005	Pacific/Pitcairn
 PR	+182806-0660622	America/Puerto_Rico
-PS	+3130+03428	Asia/Gaza
+PS	+3130+03428	Asia/Gaza	Gaza Strip
+PS	+313200+0350542	Asia/Hebron	West Bank
 PT	+3843-00908	Europe/Lisbon	mainland
 PT	+3238-01654	Atlantic/Madeira	Madeira Islands
 PT	+3744-02540	Atlantic/Azores	Azores
--- a/jdk/make/sun/rmi/rmi/Makefile	Wed Jul 05 17:53:51 2017 +0200
+++ b/jdk/make/sun/rmi/rmi/Makefile	Wed Jul 05 17:54:24 2017 +0200
@@ -30,16 +30,9 @@
 BUILDDIR = ../../..
 PACKAGE = sun.rmi
 PRODUCT = sun
-LIBRARY = rmi
 include $(BUILDDIR)/common/Defs.gmk
 
 #
-# Add use of a mapfile
-#
-FILES_m = mapfile-vers
-include $(BUILDDIR)/common/Mapfile-vers.gmk
-
-#
 # Java files to compile.
 #
 AUTO_FILES_JAVA_DIRS = \
@@ -52,31 +45,9 @@
 	com/sun/rmi
 
 #
-# Native files to compile.
-#
-FILES_c = \
-	sun/rmi/server/MarshalInputStream.c
-
-#
-# Add ambient vpath to pick up files not part of sun.rmi package
-#
-vpath %.c $(SHARE_SRC)/native/sun/rmi/server
-
-#
-# Exported files that require generated .h 
-#
-FILES_export = \
-    sun/rmi/server/MarshalInputStream.java
-
-#
-# Link to JVM for JVM_LatestUserDefinedLoader
-#
-OTHER_LDLIBS = $(JVMLIB)
-
-#
 # Rules
 #
-include $(BUILDDIR)/common/Library.gmk
+include $(BUILDDIR)/common/Rules.gmk
 
 #
 # Full package names of implementations requiring stubs
--- a/jdk/make/sun/rmi/rmi/mapfile-vers	Wed Jul 05 17:53:51 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,33 +0,0 @@
-#
-# Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
-# 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.
-#
-
-# Define library interface.
-
-SUNWprivate_1.1 {
-	global:
-	    Java_sun_rmi_server_MarshalInputStream_latestUserDefinedLoader;
-	local:
-	    *;
-};
--- a/jdk/make/sun/security/ec/Makefile	Wed Jul 05 17:53:51 2017 +0200
+++ b/jdk/make/sun/security/ec/Makefile	Wed Jul 05 17:54:24 2017 +0200
@@ -192,10 +192,8 @@
   #
   # Libraries to link
   #
-  ifeq ($(PLATFORM), windows)
-    OTHER_LDLIBS += $(JVMLIB)
-  else
-    OTHER_LDLIBS = -ldl $(JVMLIB) $(LIBCXX)
+  ifneq ($(PLATFORM), windows)
+    OTHER_LDLIBS = $(LIBCXX)
   endif
 
   include $(BUILDDIR)/common/Mapfile-vers.gmk
--- a/jdk/make/sun/security/jgss/wrapper/Makefile	Wed Jul 05 17:53:51 2017 +0200
+++ b/jdk/make/sun/security/jgss/wrapper/Makefile	Wed Jul 05 17:54:24 2017 +0200
@@ -72,5 +72,6 @@
 # Libraries to link
 #
 ifneq ($(PLATFORM), windows)
-  OTHER_LDLIBS = -ldl $(JVMLIB)
+  OTHER_LDLIBS = -ldl
 endif
+
--- a/jdk/make/sun/security/krb5/Makefile	Wed Jul 05 17:53:51 2017 +0200
+++ b/jdk/make/sun/security/krb5/Makefile	Wed Jul 05 17:54:24 2017 +0200
@@ -69,15 +69,6 @@
 include $(BUILDDIR)/common/Classes.gmk
 endif # PLATFORM
 
-#
-# Libraries to link
-#
-ifeq ($(PLATFORM), windows)
-  OTHER_LDLIBS = $(JVMLIB)
-else
-  OTHER_LDLIBS = -ldl $(JVMLIB)
-endif
-
 build:
 ifeq ($(PLATFORM),windows)
 	$(call make-launcher, kinit, sun.security.krb5.internal.tools.Kinit, , )
--- a/jdk/make/sun/security/mscapi/Makefile	Wed Jul 05 17:53:51 2017 +0200
+++ b/jdk/make/sun/security/mscapi/Makefile	Wed Jul 05 17:54:24 2017 +0200
@@ -159,7 +159,7 @@
 # Libraries to link
 #
 ifeq ($(PLATFORM), windows)
-  OTHER_LDLIBS += $(JVMLIB) Crypt32.Lib
+  OTHER_LDLIBS += Crypt32.Lib
 endif
 
 #
--- a/jdk/make/sun/security/other/Makefile	Wed Jul 05 17:53:51 2017 +0200
+++ b/jdk/make/sun/security/other/Makefile	Wed Jul 05 17:54:24 2017 +0200
@@ -38,6 +38,7 @@
     sun/security/acl \
     sun/security/jca \
     sun/security/pkcs \
+    sun/security/pkcs10 \
     sun/security/pkcs12 \
     sun/security/provider \
     sun/security/rsa \
--- a/jdk/make/sun/security/pkcs11/Makefile	Wed Jul 05 17:53:51 2017 +0200
+++ b/jdk/make/sun/security/pkcs11/Makefile	Wed Jul 05 17:54:24 2017 +0200
@@ -159,10 +159,8 @@
 #
 # Libraries to link
 #
-ifeq ($(PLATFORM), windows)
-  OTHER_LDLIBS = $(JVMLIB)
-else
-  OTHER_LDLIBS = -ldl $(JVMLIB)
+ifneq ($(PLATFORM), windows)
+  OTHER_LDLIBS = -ldl
 endif
 
 # Other config files
--- a/jdk/make/sun/security/smartcardio/Makefile	Wed Jul 05 17:53:51 2017 +0200
+++ b/jdk/make/sun/security/smartcardio/Makefile	Wed Jul 05 17:54:24 2017 +0200
@@ -73,8 +73,8 @@
 # Libraries to link
 #
 ifeq ($(PLATFORM), windows)
-  OTHER_LDLIBS = $(JVMLIB) winscard.lib
+  OTHER_LDLIBS = winscard.lib
 else
-  OTHER_LDLIBS = -ldl $(JVMLIB)
+  OTHER_LDLIBS = -ldl
   OTHER_CFLAGS = -D__sun_jdk
 endif
--- a/jdk/src/share/classes/java/io/ObjectInputStream.java	Wed Jul 05 17:53:51 2017 +0200
+++ b/jdk/src/share/classes/java/io/ObjectInputStream.java	Wed Jul 05 17:54:24 2017 +0200
@@ -2025,8 +2025,9 @@
      * This method should not be removed or its signature changed without
      * corresponding modifications to the above class.
      */
-    // REMIND: change name to something more accurate?
-    private static native ClassLoader latestUserDefinedLoader();
+    private static ClassLoader latestUserDefinedLoader() {
+        return sun.misc.VM.latestUserDefinedLoader();
+    }
 
     /**
      * Default GetField implementation.
--- a/jdk/src/share/classes/java/util/Collections.java	Wed Jul 05 17:53:51 2017 +0200
+++ b/jdk/src/share/classes/java/util/Collections.java	Wed Jul 05 17:54:24 2017 +0200
@@ -2352,6 +2352,64 @@
     }
 
     /**
+     * Returns a dynamically typesafe view of the specified queue.
+     * Any attempt to insert an element of the wrong type will result in
+     * an immediate {@link ClassCastException}.  Assuming a queue contains
+     * no incorrectly typed elements prior to the time a dynamically typesafe
+     * view is generated, and that all subsequent access to the queue
+     * takes place through the view, it is <i>guaranteed</i> that the
+     * queue cannot contain an incorrectly typed element.
+     *
+     * <p>A discussion of the use of dynamically typesafe views may be
+     * found in the documentation for the {@link #checkedCollection
+     * checkedCollection} method.
+     *
+     * <p>The returned queue will be serializable if the specified queue
+     * is serializable.
+     *
+     * <p>Since {@code null} is considered to be a value of any reference
+     * type, the returned queue permits insertion of {@code null} elements
+     * whenever the backing queue does.
+     *
+     * @param queue the queue for which a dynamically typesafe view is to be
+     *             returned
+     * @param type the type of element that {@code queue} is permitted to hold
+     * @return a dynamically typesafe view of the specified queue
+     * @since 1.8
+     */
+    public static <E> Queue<E> checkedQueue(Queue<E> queue, Class<E> type) {
+        return new CheckedQueue<>(queue, type);
+    }
+
+    /**
+     * @serial include
+     */
+    static class CheckedQueue<E>
+        extends CheckedCollection<E>
+        implements Queue<E>, Serializable
+    {
+        private static final long serialVersionUID = 1433151992604707767L;
+        final Queue<E> queue;
+
+        CheckedQueue(Queue<E> queue, Class<E> elementType) {
+            super(queue, elementType);
+            this.queue = queue;
+        }
+
+        public E element()              {return queue.element();}
+        public boolean equals(Object o) {return o == this || c.equals(o);}
+        public int hashCode()           {return c.hashCode();}
+        public E peek()                 {return queue.peek();}
+        public E poll()                 {return queue.poll();}
+        public E remove()               {return queue.remove();}
+
+        public boolean offer(E e) {
+            typeCheck(e);
+            return add(e);
+        }
+    }
+
+    /**
      * Returns a dynamically typesafe view of the specified set.
      * Any attempt to insert an element of the wrong type will result in
      * an immediate {@link ClassCastException}.  Assuming a set contains
--- a/jdk/src/share/classes/sun/misc/VM.java	Wed Jul 05 17:53:51 2017 +0200
+++ b/jdk/src/share/classes/sun/misc/VM.java	Wed Jul 05 17:54:24 2017 +0200
@@ -371,6 +371,12 @@
     private final static int JVMTI_THREAD_STATE_WAITING_INDEFINITELY = 0x0010;
     private final static int JVMTI_THREAD_STATE_WAITING_WITH_TIMEOUT = 0x0020;
 
+    /*
+     * Returns the first non-null class loader up the execution stack,
+     * or null if only code from the null class loader is on the stack.
+     */
+    public static native ClassLoader latestUserDefinedLoader();
+
     static {
         initialize();
     }
--- a/jdk/src/share/classes/sun/rmi/server/MarshalInputStream.java	Wed Jul 05 17:53:51 2017 +0200
+++ b/jdk/src/share/classes/sun/rmi/server/MarshalInputStream.java	Wed Jul 05 17:54:24 2017 +0200
@@ -110,14 +110,6 @@
     }
 
     /**
-     * Load the "rmi" native library.
-     */
-    static {
-        java.security.AccessController.doPrivileged(
-            new sun.security.action.LoadLibraryAction("rmi"));
-    }
-
-    /**
      * Create a new MarshalInputStream object.
      */
     public MarshalInputStream(InputStream in)
@@ -262,7 +254,9 @@
      * Returns the first non-null class loader up the execution stack, or null
      * if only code from the null class loader is on the stack.
      */
-    private static native ClassLoader latestUserDefinedLoader();
+    private static ClassLoader latestUserDefinedLoader() {
+        return sun.misc.VM.latestUserDefinedLoader();
+    }
 
     /**
      * Fix for 4179055: Need to assist resolving sun stubs; resolve
--- a/jdk/src/share/classes/sun/security/pkcs/EncodingException.java	Wed Jul 05 17:53:51 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,45 +0,0 @@
-/*
- * Copyright (c) 1996, 2003, Oracle and/or its affiliates. All rights reserved.
- * 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.
- */
-
-/**
- * Generic PKCS Encoding exception.
- *
- * @author Benjamin Renaud
- */
-
-package sun.security.pkcs;
-
-public class EncodingException extends Exception {
-
-    private static final long serialVersionUID = 4060198374240668325L;
-
-    public EncodingException() {
-        super();
-    }
-
-    public EncodingException(String s) {
-        super(s);
-    }
-}
--- a/jdk/src/share/classes/sun/security/pkcs/PKCS10.java	Wed Jul 05 17:53:51 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,353 +0,0 @@
-/*
- * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved.
- * 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.security.pkcs;
-
-import java.io.PrintStream;
-import java.io.IOException;
-import java.math.BigInteger;
-
-import java.security.cert.CertificateException;
-import java.security.NoSuchAlgorithmException;
-import java.security.InvalidKeyException;
-import java.security.Signature;
-import java.security.SignatureException;
-import java.security.PublicKey;
-
-import sun.misc.BASE64Encoder;
-
-import sun.security.util.*;
-import sun.security.x509.AlgorithmId;
-import sun.security.x509.X509Key;
-import sun.security.x509.X500Name;
-
-/**
- * A PKCS #10 certificate request is created and sent to a Certificate
- * Authority, which then creates an X.509 certificate and returns it to
- * the entity that requested it. A certificate request basically consists
- * of the subject's X.500 name, public key, and optionally some attributes,
- * signed using the corresponding private key.
- *
- * The ASN.1 syntax for a Certification Request is:
- * <pre>
- * CertificationRequest ::= SEQUENCE {
- *    certificationRequestInfo CertificationRequestInfo,
- *    signatureAlgorithm       SignatureAlgorithmIdentifier,
- *    signature                Signature
- *  }
- *
- * SignatureAlgorithmIdentifier ::= AlgorithmIdentifier
- * Signature ::= BIT STRING
- *
- * CertificationRequestInfo ::= SEQUENCE {
- *    version                 Version,
- *    subject                 Name,
- *    subjectPublicKeyInfo    SubjectPublicKeyInfo,
- *    attributes [0] IMPLICIT Attributes
- * }
- * Attributes ::= SET OF Attribute
- * </pre>
- *
- * @author David Brownell
- * @author Amit Kapoor
- * @author Hemma Prafullchandra
- */
-public class PKCS10 {
-    /**
-     * Constructs an unsigned PKCS #10 certificate request.  Before this
-     * request may be used, it must be encoded and signed.  Then it
-     * must be retrieved in some conventional format (e.g. string).
-     *
-     * @param publicKey the public key that should be placed
-     *          into the certificate generated by the CA.
-     */
-    public PKCS10(PublicKey publicKey) {
-        subjectPublicKeyInfo = publicKey;
-        attributeSet = new PKCS10Attributes();
-    }
-
-    /**
-     * Constructs an unsigned PKCS #10 certificate request.  Before this
-     * request may be used, it must be encoded and signed.  Then it
-     * must be retrieved in some conventional format (e.g. string).
-     *
-     * @param publicKey the public key that should be placed
-     *          into the certificate generated by the CA.
-     * @param attributes additonal set of PKCS10 attributes requested
-     *          for in the certificate.
-     */
-    public PKCS10(PublicKey publicKey, PKCS10Attributes attributes) {
-        subjectPublicKeyInfo = publicKey;
-        attributeSet = attributes;
-    }
-
-    /**
-     * Parses an encoded, signed PKCS #10 certificate request, verifying
-     * the request's signature as it does so.  This constructor would
-     * typically be used by a Certificate Authority, from which a new
-     * certificate would then be constructed.
-     *
-     * @param data the DER-encoded PKCS #10 request.
-     * @exception IOException for low level errors reading the data
-     * @exception SignatureException when the signature is invalid
-     * @exception NoSuchAlgorithmException when the signature
-     *  algorithm is not supported in this environment
-     */
-    public PKCS10(byte[] data)
-    throws IOException, SignatureException, NoSuchAlgorithmException {
-        DerInputStream  in;
-        DerValue[]      seq;
-        AlgorithmId     id;
-        byte[]          sigData;
-        Signature       sig;
-
-        encoded = data;
-
-        //
-        // Outer sequence:  request, signature algorithm, signature.
-        // Parse, and prepare to verify later.
-        //
-        in = new DerInputStream(data);
-        seq = in.getSequence(3);
-
-        if (seq.length != 3)
-            throw new IllegalArgumentException("not a PKCS #10 request");
-
-        data = seq[0].toByteArray();            // reusing this variable
-        id = AlgorithmId.parse(seq[1]);
-        sigData = seq[2].getBitString();
-
-        //
-        // Inner sequence:  version, name, key, attributes
-        //
-        BigInteger      serial;
-        DerValue        val;
-
-        serial = seq[0].data.getBigInteger();
-        if (!serial.equals(BigInteger.ZERO))
-            throw new IllegalArgumentException("not PKCS #10 v1");
-
-        subject = new X500Name(seq[0].data);
-        subjectPublicKeyInfo = X509Key.parse(seq[0].data.getDerValue());
-
-        // Cope with a somewhat common illegal PKCS #10 format
-        if (seq[0].data.available() != 0)
-            attributeSet = new PKCS10Attributes(seq[0].data);
-        else
-            attributeSet = new PKCS10Attributes();
-
-        if (seq[0].data.available() != 0)
-            throw new IllegalArgumentException("illegal PKCS #10 data");
-
-        //
-        // OK, we parsed it all ... validate the signature using the
-        // key and signature algorithm we found.
-        //
-        try {
-            sig = Signature.getInstance(id.getName());
-            sig.initVerify(subjectPublicKeyInfo);
-            sig.update(data);
-            if (!sig.verify(sigData))
-                throw new SignatureException("Invalid PKCS #10 signature");
-        } catch (InvalidKeyException e) {
-            throw new SignatureException("invalid key");
-        }
-    }
-
-    /**
-     * Create the signed certificate request.  This will later be
-     * retrieved in either string or binary format.
-     *
-     * @param subject identifies the signer (by X.500 name).
-     * @param signature private key and signing algorithm to use.
-     * @exception IOException on errors.
-     * @exception CertificateException on certificate handling errors.
-     * @exception SignatureException on signature handling errors.
-     */
-    public void encodeAndSign(X500Name subject, Signature signature)
-    throws CertificateException, IOException, SignatureException {
-        DerOutputStream out, scratch;
-        byte[]          certificateRequestInfo;
-        byte[]          sig;
-
-        if (encoded != null)
-            throw new SignatureException("request is already signed");
-
-        this.subject = subject;
-
-        /*
-         * Encode cert request info, wrap in a sequence for signing
-         */
-        scratch = new DerOutputStream();
-        scratch.putInteger(BigInteger.ZERO);            // PKCS #10 v1.0
-        subject.encode(scratch);                        // X.500 name
-        scratch.write(subjectPublicKeyInfo.getEncoded()); // public key
-        attributeSet.encode(scratch);
-
-        out = new DerOutputStream();
-        out.write(DerValue.tag_Sequence, scratch);      // wrap it!
-        certificateRequestInfo = out.toByteArray();
-        scratch = out;
-
-        /*
-         * Sign it ...
-         */
-        signature.update(certificateRequestInfo, 0,
-                certificateRequestInfo.length);
-        sig = signature.sign();
-
-        /*
-         * Build guts of SIGNED macro
-         */
-        AlgorithmId algId = null;
-        try {
-            algId = AlgorithmId.get(signature.getAlgorithm());
-        } catch (NoSuchAlgorithmException nsae) {
-            throw new SignatureException(nsae);
-        }
-        algId.encode(scratch);     // sig algorithm
-        scratch.putBitString(sig);                      // sig
-
-        /*
-         * Wrap those guts in a sequence
-         */
-        out = new DerOutputStream();
-        out.write(DerValue.tag_Sequence, scratch);
-        encoded = out.toByteArray();
-    }
-
-    /**
-     * Returns the subject's name.
-     */
-    public X500Name getSubjectName() { return subject; }
-
-    /**
-     * Returns the subject's public key.
-     */
-    public PublicKey getSubjectPublicKeyInfo()
-        { return subjectPublicKeyInfo; }
-
-    /**
-     * Returns the additional attributes requested.
-     */
-    public PKCS10Attributes getAttributes()
-        { return attributeSet; }
-
-    /**
-     * Returns the encoded and signed certificate request as a
-     * DER-encoded byte array.
-     *
-     * @return the certificate request, or null if encodeAndSign()
-     *          has not yet been called.
-     */
-    public byte[] getEncoded() {
-        if (encoded != null)
-            return encoded.clone();
-        else
-            return null;
-    }
-
-    /**
-     * Prints an E-Mailable version of the certificate request on the print
-     * stream passed.  The format is a common base64 encoded one, supported
-     * by most Certificate Authorities because Netscape web servers have
-     * used this for some time.  Some certificate authorities expect some
-     * more information, in particular contact information for the web
-     * server administrator.
-     *
-     * @param out the print stream where the certificate request
-     *  will be printed.
-     * @exception IOException when an output operation failed
-     * @exception SignatureException when the certificate request was
-     *  not yet signed.
-     */
-    public void print(PrintStream out)
-    throws IOException, SignatureException {
-        if (encoded == null)
-            throw new SignatureException("Cert request was not signed");
-
-        BASE64Encoder   encoder = new BASE64Encoder();
-
-        out.println("-----BEGIN NEW CERTIFICATE REQUEST-----");
-        encoder.encodeBuffer(encoded, out);
-        out.println("-----END NEW CERTIFICATE REQUEST-----");
-    }
-
-    /**
-     * Provides a short description of this request.
-     */
-    public String toString() {
-        return "[PKCS #10 certificate request:\n"
-            + subjectPublicKeyInfo.toString()
-            + " subject: <" + subject + ">" + "\n"
-            + " attributes: " + attributeSet.toString()
-            + "\n]";
-    }
-
-    /**
-     * Compares this object for equality with the specified
-     * object. If the <code>other</code> object is an
-     * <code>instanceof</code> <code>PKCS10</code>, then
-     * its encoded form is retrieved and compared with the
-     * encoded form of this certificate request.
-     *
-     * @param other the object to test for equality with this object.
-     * @return true iff the encoded forms of the two certificate
-     * requests match, false otherwise.
-     */
-    public boolean equals(Object other) {
-        if (this == other)
-            return true;
-        if (!(other instanceof PKCS10))
-            return false;
-        if (encoded == null) // not signed yet
-            return false;
-        byte[] otherEncoded = ((PKCS10)other).getEncoded();
-        if (otherEncoded == null)
-            return false;
-
-        return java.util.Arrays.equals(encoded, otherEncoded);
-    }
-
-    /**
-     * Returns a hashcode value for this certificate request from its
-     * encoded form.
-     *
-     * @return the hashcode value.
-     */
-    public int hashCode() {
-        int     retval = 0;
-        if (encoded != null)
-            for (int i = 1; i < encoded.length; i++)
-             retval += encoded[i] * i;
-        return(retval);
-    }
-
-    private X500Name            subject;
-    private PublicKey           subjectPublicKeyInfo;
-    private PKCS10Attributes    attributeSet;
-    private byte[]              encoded;        // signed
-}
--- a/jdk/src/share/classes/sun/security/pkcs/PKCS10Attribute.java	Wed Jul 05 17:53:51 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,135 +0,0 @@
-/*
- * Copyright (c) 1997, 1998, Oracle and/or its affiliates. All rights reserved.
- * 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.security.pkcs;
-
-import java.io.OutputStream;
-import java.io.IOException;
-
-import sun.security.util.*;
-
-/**
- * Represent a PKCS#10 Attribute.
- *
- * <p>Attributes are additonal information which can be inserted in a PKCS#10
- * certificate request. For example a "Driving License Certificate" could have
- * the driving license number as an attribute.
- *
- * <p>Attributes are represented as a sequence of the attribute identifier
- * (Object Identifier) and a set of DER encoded attribute values.
- *
- * ASN.1 definition of Attribute:
- * <pre>
- * Attribute :: SEQUENCE {
- *    type    AttributeType,
- *    values  SET OF AttributeValue
- * }
- * AttributeType  ::= OBJECT IDENTIFIER
- * AttributeValue ::= ANY defined by type
- * </pre>
- *
- * @author Amit Kapoor
- * @author Hemma Prafullchandra
- */
-public class PKCS10Attribute implements DerEncoder {
-
-    protected ObjectIdentifier  attributeId = null;
-    protected Object            attributeValue = null;
-
-    /**
-     * Constructs an attribute from a DER encoding.
-     * This constructor expects the value to be encoded as defined above,
-     * i.e. a SEQUENCE of OID and SET OF value(s), not a literal
-     * X.509 v3 extension. Only PKCS9 defined attributes are supported
-     * currently.
-     *
-     * @param derVal the der encoded attribute.
-     * @exception IOException on parsing errors.
-     */
-    public PKCS10Attribute(DerValue derVal) throws IOException {
-        PKCS9Attribute attr = new PKCS9Attribute(derVal);
-        this.attributeId = attr.getOID();
-        this.attributeValue = attr.getValue();
-    }
-
-    /**
-     * Constructs an attribute from individual components of
-     * ObjectIdentifier and the value (any java object).
-     *
-     * @param attributeId the ObjectIdentifier of the attribute.
-     * @param attributeValue an instance of a class that implements
-     * the attribute identified by the ObjectIdentifier.
-     */
-    public PKCS10Attribute(ObjectIdentifier attributeId,
-                           Object attributeValue) {
-        this.attributeId = attributeId;
-        this.attributeValue = attributeValue;
-    }
-
-    /**
-     * Constructs an attribute from PKCS9 attribute.
-     *
-     * @param attr the PKCS9Attribute to create from.
-     */
-    public PKCS10Attribute(PKCS9Attribute attr) {
-        this.attributeId = attr.getOID();
-        this.attributeValue = attr.getValue();
-    }
-
-    /**
-     * DER encode this object onto an output stream.
-     * Implements the <code>DerEncoder</code> interface.
-     *
-     * @param out
-     * the OutputStream on which to write the DER encoding.
-     *
-     * @exception IOException on encoding errors.
-     */
-    public void derEncode(OutputStream out) throws IOException {
-        PKCS9Attribute attr = new PKCS9Attribute(attributeId, attributeValue);
-        attr.derEncode(out);
-    }
-
-    /**
-     * Returns the ObjectIdentifier of the attribute.
-     */
-    public ObjectIdentifier getAttributeId() {
-        return (attributeId);
-    }
-
-    /**
-     * Returns the attribute value.
-     */
-    public Object getAttributeValue() {
-        return (attributeValue);
-    }
-
-    /**
-     * Returns the attribute in user readable form.
-     */
-    public String toString() {
-        return (attributeValue.toString());
-    }
-}
--- a/jdk/src/share/classes/sun/security/pkcs/PKCS10Attributes.java	Wed Jul 05 17:53:51 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,219 +0,0 @@
-/*
- * Copyright (c) 1997, 2006, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.security.pkcs;
-
-import java.io.IOException;
-import java.io.OutputStream;
-import java.security.cert.CertificateException;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Enumeration;
-import java.util.Hashtable;
-
-import sun.security.util.*;
-
-/**
- * This class defines the PKCS10 attributes for the request.
- * The ASN.1 syntax for this is:
- * <pre>
- * Attributes ::= SET OF Attribute
- * </pre>
- *
- * @author Amit Kapoor
- * @author Hemma Prafullchandra
- * @see PKCS10
- * @see PKCS10Attribute
- */
-public class PKCS10Attributes implements DerEncoder {
-
-    private Hashtable<String, PKCS10Attribute> map =
-                        new Hashtable<String, PKCS10Attribute>(3);
-
-    /**
-     * Default constructor for the PKCS10 attribute.
-     */
-    public PKCS10Attributes() { }
-
-    /**
-     * Create the object from the array of PKCS10Attribute objects.
-     *
-     * @param attrs the array of PKCS10Attribute objects.
-     */
-    public PKCS10Attributes(PKCS10Attribute[] attrs) {
-        for (int i = 0; i < attrs.length; i++) {
-            map.put(attrs[i].getAttributeId().toString(), attrs[i]);
-        }
-    }
-
-    /**
-     * Create the object, decoding the values from the passed DER stream.
-     * The DER stream contains the SET OF Attribute.
-     *
-     * @param in the DerInputStream to read the attributes from.
-     * @exception IOException on decoding errors.
-     */
-    public PKCS10Attributes(DerInputStream in) throws IOException {
-        DerValue[] attrs = in.getSet(3, true);
-
-        if (attrs == null)
-            throw new IOException("Illegal encoding of attributes");
-        for (int i = 0; i < attrs.length; i++) {
-            PKCS10Attribute attr = new PKCS10Attribute(attrs[i]);
-            map.put(attr.getAttributeId().toString(), attr);
-        }
-    }
-
-    /**
-     * Encode the attributes in DER form to the stream.
-     *
-     * @param out the OutputStream to marshal the contents to.
-     * @exception IOException on encoding errors.
-     */
-    public void encode(OutputStream out) throws IOException {
-        derEncode(out);
-    }
-
-    /**
-     * Encode the attributes in DER form to the stream.
-     * Implements the <code>DerEncoder</code> interface.
-     *
-     * @param out the OutputStream to marshal the contents to.
-     * @exception IOException on encoding errors.
-     */
-    public void derEncode(OutputStream out) throws IOException {
-        // first copy the elements into an array
-        Collection<PKCS10Attribute> allAttrs = map.values();
-        PKCS10Attribute[] attribs =
-                allAttrs.toArray(new PKCS10Attribute[map.size()]);
-
-        DerOutputStream attrOut = new DerOutputStream();
-        attrOut.putOrderedSetOf(DerValue.createTag(DerValue.TAG_CONTEXT,
-                                                   true, (byte)0),
-                                attribs);
-        out.write(attrOut.toByteArray());
-    }
-
-    /**
-     * Set the attribute value.
-     */
-    public void setAttribute(String name, Object obj) {
-        if (obj instanceof PKCS10Attribute) {
-            map.put(name, (PKCS10Attribute)obj);
-        }
-    }
-
-    /**
-     * Get the attribute value.
-     */
-    public Object getAttribute(String name) {
-        return map.get(name);
-    }
-
-    /**
-     * Delete the attribute value.
-     */
-    public void deleteAttribute(String name) {
-        map.remove(name);
-    }
-
-    /**
-     * Return an enumeration of names of attributes existing within this
-     * attribute.
-     */
-    public Enumeration<PKCS10Attribute> getElements() {
-        return (map.elements());
-    }
-
-    /**
-     * Return a Collection of attributes existing within this
-     * PKCS10Attributes object.
-     */
-    public Collection<PKCS10Attribute> getAttributes() {
-        return (Collections.unmodifiableCollection(map.values()));
-    }
-
-    /**
-     * Compares this PKCS10Attributes for equality with the specified
-     * object. If the <code>other</code> object is an
-     * <code>instanceof</code> <code>PKCS10Attributes</code>, then
-     * all the entries are compared with the entries from this.
-     *
-     * @param other the object to test for equality with this PKCS10Attributes.
-     * @return true if all the entries match that of the Other,
-     * false otherwise.
-     */
-    public boolean equals(Object other) {
-        if (this == other)
-            return true;
-        if (!(other instanceof PKCS10Attributes))
-            return false;
-
-        Collection<PKCS10Attribute> othersAttribs =
-                ((PKCS10Attributes)other).getAttributes();
-        PKCS10Attribute[] attrs =
-            othersAttribs.toArray(new PKCS10Attribute[othersAttribs.size()]);
-        int len = attrs.length;
-        if (len != map.size())
-            return false;
-        PKCS10Attribute thisAttr, otherAttr;
-        String key = null;
-        for (int i=0; i < len; i++) {
-            otherAttr = attrs[i];
-            key = otherAttr.getAttributeId().toString();
-
-            if (key == null)
-                return false;
-            thisAttr = map.get(key);
-            if (thisAttr == null)
-                return false;
-            if (! thisAttr.equals(otherAttr))
-                return false;
-        }
-        return true;
-    }
-
-    /**
-     * Returns a hashcode value for this PKCS10Attributes.
-     *
-     * @return the hashcode value.
-     */
-    public int hashCode() {
-        return map.hashCode();
-    }
-
-    /**
-     * Returns a string representation of this <tt>PKCS10Attributes</tt> object
-     * in the form of a set of entries, enclosed in braces and separated
-     * by the ASCII characters "<tt>,&nbsp;</tt>" (comma and space).
-     * <p>Overrides the <tt>toString</tt> method of <tt>Object</tt>.
-     *
-     * @return  a string representation of this PKCS10Attributes.
-     */
-    public String toString() {
-        String s = map.size() + "\n" + map.toString();
-        return s;
-    }
-}
--- a/jdk/src/share/classes/sun/security/pkcs/PKCS7.java	Wed Jul 05 17:53:51 2017 +0200
+++ b/jdk/src/share/classes/sun/security/pkcs/PKCS7.java	Wed Jul 05 17:54:24 2017 +0200
@@ -27,6 +27,7 @@
 
 import java.io.*;
 import java.math.BigInteger;
+import java.net.URI;
 import java.util.*;
 import java.security.cert.X509Certificate;
 import java.security.cert.CertificateException;
@@ -35,6 +36,7 @@
 import java.security.cert.CertificateFactory;
 import java.security.*;
 
+import sun.security.timestamp.*;
 import sun.security.util.*;
 import sun.security.x509.AlgorithmId;
 import sun.security.x509.CertificateIssuerName;
@@ -68,6 +70,30 @@
 
     private Principal[] certIssuerNames;
 
+    /*
+     * Random number generator for creating nonce values
+     */
+    private static final SecureRandom RANDOM;
+    static {
+        SecureRandom tmp = null;
+        try {
+            tmp = SecureRandom.getInstance("SHA1PRNG");
+        } catch (NoSuchAlgorithmException e) {
+            // should not happen
+        }
+        RANDOM = tmp;
+    }
+
+    /*
+     * Object identifier for the timestamping key purpose.
+     */
+    private static final String KP_TIMESTAMPING_OID = "1.3.6.1.5.5.7.3.8";
+
+    /*
+     * Object identifier for extendedKeyUsage extension
+     */
+    private static final String EXTENDED_KEY_USAGE_OID = "2.5.29.37";
+
     /**
      * Unmarshals a PKCS7 block from its encoded form, parsing the
      * encoded bytes from the InputStream.
@@ -733,4 +759,164 @@
     public boolean isOldStyle() {
         return this.oldStyle;
     }
+
+    /**
+     * Assembles a PKCS #7 signed data message that optionally includes a
+     * signature timestamp.
+     *
+     * @param signature the signature bytes
+     * @param signerChain the signer's X.509 certificate chain
+     * @param content the content that is signed; specify null to not include
+     *        it in the PKCS7 data
+     * @param signatureAlgorithm the name of the signature algorithm
+     * @param tsaURI the URI of the Timestamping Authority; or null if no
+     *         timestamp is requested
+     * @return the bytes of the encoded PKCS #7 signed data message
+     * @throws NoSuchAlgorithmException The exception is thrown if the signature
+     *         algorithm is unrecognised.
+     * @throws CertificateException The exception is thrown if an error occurs
+     *         while processing the signer's certificate or the TSA's
+     *         certificate.
+     * @throws IOException The exception is thrown if an error occurs while
+     *         generating the signature timestamp or while generating the signed
+     *         data message.
+     */
+    public static byte[] generateSignedData(byte[] signature,
+                                            X509Certificate[] signerChain,
+                                            byte[] content,
+                                            String signatureAlgorithm,
+                                            URI tsaURI)
+        throws CertificateException, IOException, NoSuchAlgorithmException
+    {
+
+        // Generate the timestamp token
+        PKCS9Attributes unauthAttrs = null;
+        if (tsaURI != null) {
+            // Timestamp the signature
+            HttpTimestamper tsa = new HttpTimestamper(tsaURI);
+            byte[] tsToken = generateTimestampToken(tsa, signature);
+
+            // Insert the timestamp token into the PKCS #7 signer info element
+            // (as an unsigned attribute)
+            unauthAttrs =
+                new PKCS9Attributes(new PKCS9Attribute[]{
+                    new PKCS9Attribute(
+                        PKCS9Attribute.SIGNATURE_TIMESTAMP_TOKEN_STR,
+                        tsToken)});
+        }
+
+        // Create the SignerInfo
+        X500Name issuerName =
+            X500Name.asX500Name(signerChain[0].getIssuerX500Principal());
+        BigInteger serialNumber = signerChain[0].getSerialNumber();
+        String encAlg = AlgorithmId.getEncAlgFromSigAlg(signatureAlgorithm);
+        String digAlg = AlgorithmId.getDigAlgFromSigAlg(signatureAlgorithm);
+        SignerInfo signerInfo = new SignerInfo(issuerName, serialNumber,
+                                               AlgorithmId.get(digAlg), null,
+                                               AlgorithmId.get(encAlg),
+                                               signature, unauthAttrs);
+
+        // Create the PKCS #7 signed data message
+        SignerInfo[] signerInfos = {signerInfo};
+        AlgorithmId[] algorithms = {signerInfo.getDigestAlgorithmId()};
+        // Include or exclude content
+        ContentInfo contentInfo = (content == null)
+            ? new ContentInfo(ContentInfo.DATA_OID, null)
+            : new ContentInfo(content);
+        PKCS7 pkcs7 = new PKCS7(algorithms, contentInfo,
+                                signerChain, signerInfos);
+        ByteArrayOutputStream p7out = new ByteArrayOutputStream();
+        pkcs7.encodeSignedData(p7out);
+
+        return p7out.toByteArray();
+    }
+
+    /**
+     * Requests, processes and validates a timestamp token from a TSA using
+     * common defaults. Uses the following defaults in the timestamp request:
+     * SHA-1 for the hash algorithm, a 64-bit nonce, and request certificate
+     * set to true.
+     *
+     * @param tsa the timestamping authority to use
+     * @param toBeTimestamped the token that is to be timestamped
+     * @return the encoded timestamp token
+     * @throws IOException The exception is thrown if an error occurs while
+     *                     communicating with the TSA.
+     * @throws CertificateException The exception is thrown if the TSA's
+     *                     certificate is not permitted for timestamping.
+     */
+    private static byte[] generateTimestampToken(Timestamper tsa,
+                                                 byte[] toBeTimestamped)
+        throws IOException, CertificateException
+    {
+        // Generate a timestamp
+        MessageDigest messageDigest = null;
+        TSRequest tsQuery = null;
+        try {
+            // SHA-1 is always used.
+            messageDigest = MessageDigest.getInstance("SHA-1");
+            tsQuery = new TSRequest(toBeTimestamped, messageDigest);
+        } catch (NoSuchAlgorithmException e) {
+            // ignore
+        }
+
+        // Generate a nonce
+        BigInteger nonce = null;
+        if (RANDOM != null) {
+            nonce = new BigInteger(64, RANDOM);
+            tsQuery.setNonce(nonce);
+        }
+        tsQuery.requestCertificate(true);
+
+        TSResponse tsReply = tsa.generateTimestamp(tsQuery);
+        int status = tsReply.getStatusCode();
+        // Handle TSP error
+        if (status != 0 && status != 1) {
+            throw new IOException("Error generating timestamp: " +
+                tsReply.getStatusCodeAsText() + " " +
+                tsReply.getFailureCodeAsText());
+        }
+        PKCS7 tsToken = tsReply.getToken();
+
+        TimestampToken tst = tsReply.getTimestampToken();
+        if (!tst.getHashAlgorithm().getName().equals("SHA")) {
+            throw new IOException("Digest algorithm not SHA-1 in "
+                                  + "timestamp token");
+        }
+        if (!MessageDigest.isEqual(tst.getHashedMessage(),
+                                   tsQuery.getHashedMessage())) {
+            throw new IOException("Digest octets changed in timestamp token");
+        }
+
+        BigInteger replyNonce = tst.getNonce();
+        if (replyNonce == null && nonce != null) {
+            throw new IOException("Nonce missing in timestamp token");
+        }
+        if (replyNonce != null && !replyNonce.equals(nonce)) {
+            throw new IOException("Nonce changed in timestamp token");
+        }
+
+        // Examine the TSA's certificate (if present)
+        for (SignerInfo si: tsToken.getSignerInfos()) {
+            X509Certificate cert = si.getCertificate(tsToken);
+            if (cert == null) {
+                // Error, we've already set tsRequestCertificate = true
+                throw new CertificateException(
+                "Certificate not included in timestamp token");
+            } else {
+                if (!cert.getCriticalExtensionOIDs().contains(
+                        EXTENDED_KEY_USAGE_OID)) {
+                    throw new CertificateException(
+                    "Certificate is not valid for timestamping");
+                }
+                List<String> keyPurposes = cert.getExtendedKeyUsage();
+                if (keyPurposes == null ||
+                        !keyPurposes.contains(KP_TIMESTAMPING_OID)) {
+                    throw new CertificateException(
+                    "Certificate is not valid for timestamping");
+                }
+            }
+        }
+        return tsReply.getEncodedToken();
+    }
 }
--- a/jdk/src/share/classes/sun/security/pkcs/SignerInfo.java	Wed Jul 05 17:53:51 2017 +0200
+++ b/jdk/src/share/classes/sun/security/pkcs/SignerInfo.java	Wed Jul 05 17:54:24 2017 +0200
@@ -28,10 +28,14 @@
 import java.io.OutputStream;
 import java.io.IOException;
 import java.math.BigInteger;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateFactory;
+import java.security.cert.CertPath;
 import java.security.cert.X509Certificate;
 import java.security.*;
 import java.util.ArrayList;
 
+import sun.security.timestamp.TimestampToken;
 import sun.security.util.*;
 import sun.security.x509.AlgorithmId;
 import sun.security.x509.X500Name;
@@ -51,6 +55,8 @@
     AlgorithmId digestAlgorithmId;
     AlgorithmId digestEncryptionAlgorithmId;
     byte[] encryptedDigest;
+    Timestamp timestamp;
+    private boolean hasTimestamp = true;
 
     PKCS9Attributes authenticatedAttributes;
     PKCS9Attributes unauthenticatedAttributes;
@@ -442,6 +448,62 @@
         return unauthenticatedAttributes;
     }
 
+    /*
+     * Extracts a timestamp from a PKCS7 SignerInfo.
+     *
+     * Examines the signer's unsigned attributes for a
+     * <tt>signatureTimestampToken</tt> attribute. If present,
+     * then it is parsed to extract the date and time at which the
+     * timestamp was generated.
+     *
+     * @param info A signer information element of a PKCS 7 block.
+     *
+     * @return A timestamp token or null if none is present.
+     * @throws IOException if an error is encountered while parsing the
+     *         PKCS7 data.
+     * @throws NoSuchAlgorithmException if an error is encountered while
+     *         verifying the PKCS7 object.
+     * @throws SignatureException if an error is encountered while
+     *         verifying the PKCS7 object.
+     * @throws CertificateException if an error is encountered while generating
+     *         the TSA's certpath.
+     */
+    public Timestamp getTimestamp()
+        throws IOException, NoSuchAlgorithmException, SignatureException,
+               CertificateException
+    {
+        if (timestamp != null || !hasTimestamp)
+            return timestamp;
+
+        if (unauthenticatedAttributes == null) {
+            hasTimestamp = false;
+            return null;
+        }
+        PKCS9Attribute tsTokenAttr =
+            unauthenticatedAttributes.getAttribute(
+                PKCS9Attribute.SIGNATURE_TIMESTAMP_TOKEN_OID);
+        if (tsTokenAttr == null) {
+            hasTimestamp = false;
+            return null;
+        }
+
+        PKCS7 tsToken = new PKCS7((byte[])tsTokenAttr.getValue());
+        // Extract the content (an encoded timestamp token info)
+        byte[] encTsTokenInfo = tsToken.getContentInfo().getData();
+        // Extract the signer (the Timestamping Authority)
+        // while verifying the content
+        SignerInfo[] tsa = tsToken.verify(encTsTokenInfo);
+        // Expect only one signer
+        ArrayList<X509Certificate> chain = tsa[0].getCertificateChain(tsToken);
+        CertificateFactory cf = CertificateFactory.getInstance("X.509");
+        CertPath tsaChain = cf.generateCertPath(chain);
+        // Create a timestamp token info object
+        TimestampToken tsTokenInfo = new TimestampToken(encTsTokenInfo);
+        // Create a timestamp object
+        timestamp = new Timestamp(tsTokenInfo.getDate(), tsaChain);
+        return timestamp;
+    }
+
     public String toString() {
         HexDumpEncoder hexDump = new HexDumpEncoder();
 
@@ -467,5 +529,4 @@
         }
         return out;
     }
-
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/sun/security/pkcs10/PKCS10.java	Wed Jul 05 17:54:24 2017 +0200
@@ -0,0 +1,353 @@
+/*
+ * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved.
+ * 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.security.pkcs10;
+
+import java.io.PrintStream;
+import java.io.IOException;
+import java.math.BigInteger;
+
+import java.security.cert.CertificateException;
+import java.security.NoSuchAlgorithmException;
+import java.security.InvalidKeyException;
+import java.security.Signature;
+import java.security.SignatureException;
+import java.security.PublicKey;
+
+import sun.misc.BASE64Encoder;
+
+import sun.security.util.*;
+import sun.security.x509.AlgorithmId;
+import sun.security.x509.X509Key;
+import sun.security.x509.X500Name;
+
+/**
+ * A PKCS #10 certificate request is created and sent to a Certificate
+ * Authority, which then creates an X.509 certificate and returns it to
+ * the entity that requested it. A certificate request basically consists
+ * of the subject's X.500 name, public key, and optionally some attributes,
+ * signed using the corresponding private key.
+ *
+ * The ASN.1 syntax for a Certification Request is:
+ * <pre>
+ * CertificationRequest ::= SEQUENCE {
+ *    certificationRequestInfo CertificationRequestInfo,
+ *    signatureAlgorithm       SignatureAlgorithmIdentifier,
+ *    signature                Signature
+ *  }
+ *
+ * SignatureAlgorithmIdentifier ::= AlgorithmIdentifier
+ * Signature ::= BIT STRING
+ *
+ * CertificationRequestInfo ::= SEQUENCE {
+ *    version                 Version,
+ *    subject                 Name,
+ *    subjectPublicKeyInfo    SubjectPublicKeyInfo,
+ *    attributes [0] IMPLICIT Attributes
+ * }
+ * Attributes ::= SET OF Attribute
+ * </pre>
+ *
+ * @author David Brownell
+ * @author Amit Kapoor
+ * @author Hemma Prafullchandra
+ */
+public class PKCS10 {
+    /**
+     * Constructs an unsigned PKCS #10 certificate request.  Before this
+     * request may be used, it must be encoded and signed.  Then it
+     * must be retrieved in some conventional format (e.g. string).
+     *
+     * @param publicKey the public key that should be placed
+     *          into the certificate generated by the CA.
+     */
+    public PKCS10(PublicKey publicKey) {
+        subjectPublicKeyInfo = publicKey;
+        attributeSet = new PKCS10Attributes();
+    }
+
+    /**
+     * Constructs an unsigned PKCS #10 certificate request.  Before this
+     * request may be used, it must be encoded and signed.  Then it
+     * must be retrieved in some conventional format (e.g. string).
+     *
+     * @param publicKey the public key that should be placed
+     *          into the certificate generated by the CA.
+     * @param attributes additonal set of PKCS10 attributes requested
+     *          for in the certificate.
+     */
+    public PKCS10(PublicKey publicKey, PKCS10Attributes attributes) {
+        subjectPublicKeyInfo = publicKey;
+        attributeSet = attributes;
+    }
+
+    /**
+     * Parses an encoded, signed PKCS #10 certificate request, verifying
+     * the request's signature as it does so.  This constructor would
+     * typically be used by a Certificate Authority, from which a new
+     * certificate would then be constructed.
+     *
+     * @param data the DER-encoded PKCS #10 request.
+     * @exception IOException for low level errors reading the data
+     * @exception SignatureException when the signature is invalid
+     * @exception NoSuchAlgorithmException when the signature
+     *  algorithm is not supported in this environment
+     */
+    public PKCS10(byte[] data)
+    throws IOException, SignatureException, NoSuchAlgorithmException {
+        DerInputStream  in;
+        DerValue[]      seq;
+        AlgorithmId     id;
+        byte[]          sigData;
+        Signature       sig;
+
+        encoded = data;
+
+        //
+        // Outer sequence:  request, signature algorithm, signature.
+        // Parse, and prepare to verify later.
+        //
+        in = new DerInputStream(data);
+        seq = in.getSequence(3);
+
+        if (seq.length != 3)
+            throw new IllegalArgumentException("not a PKCS #10 request");
+
+        data = seq[0].toByteArray();            // reusing this variable
+        id = AlgorithmId.parse(seq[1]);
+        sigData = seq[2].getBitString();
+
+        //
+        // Inner sequence:  version, name, key, attributes
+        //
+        BigInteger      serial;
+        DerValue        val;
+
+        serial = seq[0].data.getBigInteger();
+        if (!serial.equals(BigInteger.ZERO))
+            throw new IllegalArgumentException("not PKCS #10 v1");
+
+        subject = new X500Name(seq[0].data);
+        subjectPublicKeyInfo = X509Key.parse(seq[0].data.getDerValue());
+
+        // Cope with a somewhat common illegal PKCS #10 format
+        if (seq[0].data.available() != 0)
+            attributeSet = new PKCS10Attributes(seq[0].data);
+        else
+            attributeSet = new PKCS10Attributes();
+
+        if (seq[0].data.available() != 0)
+            throw new IllegalArgumentException("illegal PKCS #10 data");
+
+        //
+        // OK, we parsed it all ... validate the signature using the
+        // key and signature algorithm we found.
+        //
+        try {
+            sig = Signature.getInstance(id.getName());
+            sig.initVerify(subjectPublicKeyInfo);
+            sig.update(data);
+            if (!sig.verify(sigData))
+                throw new SignatureException("Invalid PKCS #10 signature");
+        } catch (InvalidKeyException e) {
+            throw new SignatureException("invalid key");
+        }
+    }
+
+    /**
+     * Create the signed certificate request.  This will later be
+     * retrieved in either string or binary format.
+     *
+     * @param subject identifies the signer (by X.500 name).
+     * @param signature private key and signing algorithm to use.
+     * @exception IOException on errors.
+     * @exception CertificateException on certificate handling errors.
+     * @exception SignatureException on signature handling errors.
+     */
+    public void encodeAndSign(X500Name subject, Signature signature)
+    throws CertificateException, IOException, SignatureException {
+        DerOutputStream out, scratch;
+        byte[]          certificateRequestInfo;
+        byte[]          sig;
+
+        if (encoded != null)
+            throw new SignatureException("request is already signed");
+
+        this.subject = subject;
+
+        /*
+         * Encode cert request info, wrap in a sequence for signing
+         */
+        scratch = new DerOutputStream();
+        scratch.putInteger(BigInteger.ZERO);            // PKCS #10 v1.0
+        subject.encode(scratch);                        // X.500 name
+        scratch.write(subjectPublicKeyInfo.getEncoded()); // public key
+        attributeSet.encode(scratch);
+
+        out = new DerOutputStream();
+        out.write(DerValue.tag_Sequence, scratch);      // wrap it!
+        certificateRequestInfo = out.toByteArray();
+        scratch = out;
+
+        /*
+         * Sign it ...
+         */
+        signature.update(certificateRequestInfo, 0,
+                certificateRequestInfo.length);
+        sig = signature.sign();
+
+        /*
+         * Build guts of SIGNED macro
+         */
+        AlgorithmId algId = null;
+        try {
+            algId = AlgorithmId.get(signature.getAlgorithm());
+        } catch (NoSuchAlgorithmException nsae) {
+            throw new SignatureException(nsae);
+        }
+        algId.encode(scratch);     // sig algorithm
+        scratch.putBitString(sig);                      // sig
+
+        /*
+         * Wrap those guts in a sequence
+         */
+        out = new DerOutputStream();
+        out.write(DerValue.tag_Sequence, scratch);
+        encoded = out.toByteArray();
+    }
+
+    /**
+     * Returns the subject's name.
+     */
+    public X500Name getSubjectName() { return subject; }
+
+    /**
+     * Returns the subject's public key.
+     */
+    public PublicKey getSubjectPublicKeyInfo()
+        { return subjectPublicKeyInfo; }
+
+    /**
+     * Returns the additional attributes requested.
+     */
+    public PKCS10Attributes getAttributes()
+        { return attributeSet; }
+
+    /**
+     * Returns the encoded and signed certificate request as a
+     * DER-encoded byte array.
+     *
+     * @return the certificate request, or null if encodeAndSign()
+     *          has not yet been called.
+     */
+    public byte[] getEncoded() {
+        if (encoded != null)
+            return encoded.clone();
+        else
+            return null;
+    }
+
+    /**
+     * Prints an E-Mailable version of the certificate request on the print
+     * stream passed.  The format is a common base64 encoded one, supported
+     * by most Certificate Authorities because Netscape web servers have
+     * used this for some time.  Some certificate authorities expect some
+     * more information, in particular contact information for the web
+     * server administrator.
+     *
+     * @param out the print stream where the certificate request
+     *  will be printed.
+     * @exception IOException when an output operation failed
+     * @exception SignatureException when the certificate request was
+     *  not yet signed.
+     */
+    public void print(PrintStream out)
+    throws IOException, SignatureException {
+        if (encoded == null)
+            throw new SignatureException("Cert request was not signed");
+
+        BASE64Encoder   encoder = new BASE64Encoder();
+
+        out.println("-----BEGIN NEW CERTIFICATE REQUEST-----");
+        encoder.encodeBuffer(encoded, out);
+        out.println("-----END NEW CERTIFICATE REQUEST-----");
+    }
+
+    /**
+     * Provides a short description of this request.
+     */
+    public String toString() {
+        return "[PKCS #10 certificate request:\n"
+            + subjectPublicKeyInfo.toString()
+            + " subject: <" + subject + ">" + "\n"
+            + " attributes: " + attributeSet.toString()
+            + "\n]";
+    }
+
+    /**
+     * Compares this object for equality with the specified
+     * object. If the <code>other</code> object is an
+     * <code>instanceof</code> <code>PKCS10</code>, then
+     * its encoded form is retrieved and compared with the
+     * encoded form of this certificate request.
+     *
+     * @param other the object to test for equality with this object.
+     * @return true iff the encoded forms of the two certificate
+     * requests match, false otherwise.
+     */
+    public boolean equals(Object other) {
+        if (this == other)
+            return true;
+        if (!(other instanceof PKCS10))
+            return false;
+        if (encoded == null) // not signed yet
+            return false;
+        byte[] otherEncoded = ((PKCS10)other).getEncoded();
+        if (otherEncoded == null)
+            return false;
+
+        return java.util.Arrays.equals(encoded, otherEncoded);
+    }
+
+    /**
+     * Returns a hashcode value for this certificate request from its
+     * encoded form.
+     *
+     * @return the hashcode value.
+     */
+    public int hashCode() {
+        int     retval = 0;
+        if (encoded != null)
+            for (int i = 1; i < encoded.length; i++)
+             retval += encoded[i] * i;
+        return(retval);
+    }
+
+    private X500Name            subject;
+    private PublicKey           subjectPublicKeyInfo;
+    private PKCS10Attributes    attributeSet;
+    private byte[]              encoded;        // signed
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/sun/security/pkcs10/PKCS10Attribute.java	Wed Jul 05 17:54:24 2017 +0200
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
+ * 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.security.pkcs10;
+
+import java.io.OutputStream;
+import java.io.IOException;
+
+import sun.security.pkcs.PKCS9Attribute;
+import sun.security.util.*;
+
+/**
+ * Represent a PKCS#10 Attribute.
+ *
+ * <p>Attributes are additonal information which can be inserted in a PKCS#10
+ * certificate request. For example a "Driving License Certificate" could have
+ * the driving license number as an attribute.
+ *
+ * <p>Attributes are represented as a sequence of the attribute identifier
+ * (Object Identifier) and a set of DER encoded attribute values.
+ *
+ * ASN.1 definition of Attribute:
+ * <pre>
+ * Attribute :: SEQUENCE {
+ *    type    AttributeType,
+ *    values  SET OF AttributeValue
+ * }
+ * AttributeType  ::= OBJECT IDENTIFIER
+ * AttributeValue ::= ANY defined by type
+ * </pre>
+ *
+ * @author Amit Kapoor
+ * @author Hemma Prafullchandra
+ */
+public class PKCS10Attribute implements DerEncoder {
+
+    protected ObjectIdentifier  attributeId = null;
+    protected Object            attributeValue = null;
+
+    /**
+     * Constructs an attribute from a DER encoding.
+     * This constructor expects the value to be encoded as defined above,
+     * i.e. a SEQUENCE of OID and SET OF value(s), not a literal
+     * X.509 v3 extension. Only PKCS9 defined attributes are supported
+     * currently.
+     *
+     * @param derVal the der encoded attribute.
+     * @exception IOException on parsing errors.
+     */
+    public PKCS10Attribute(DerValue derVal) throws IOException {
+        PKCS9Attribute attr = new PKCS9Attribute(derVal);
+        this.attributeId = attr.getOID();
+        this.attributeValue = attr.getValue();
+    }
+
+    /**
+     * Constructs an attribute from individual components of
+     * ObjectIdentifier and the value (any java object).
+     *
+     * @param attributeId the ObjectIdentifier of the attribute.
+     * @param attributeValue an instance of a class that implements
+     * the attribute identified by the ObjectIdentifier.
+     */
+    public PKCS10Attribute(ObjectIdentifier attributeId,
+                           Object attributeValue) {
+        this.attributeId = attributeId;
+        this.attributeValue = attributeValue;
+    }
+
+    /**
+     * Constructs an attribute from PKCS9 attribute.
+     *
+     * @param attr the PKCS9Attribute to create from.
+     */
+    public PKCS10Attribute(PKCS9Attribute attr) {
+        this.attributeId = attr.getOID();
+        this.attributeValue = attr.getValue();
+    }
+
+    /**
+     * DER encode this object onto an output stream.
+     * Implements the <code>DerEncoder</code> interface.
+     *
+     * @param out
+     * the OutputStream on which to write the DER encoding.
+     *
+     * @exception IOException on encoding errors.
+     */
+    public void derEncode(OutputStream out) throws IOException {
+        PKCS9Attribute attr = new PKCS9Attribute(attributeId, attributeValue);
+        attr.derEncode(out);
+    }
+
+    /**
+     * Returns the ObjectIdentifier of the attribute.
+     */
+    public ObjectIdentifier getAttributeId() {
+        return (attributeId);
+    }
+
+    /**
+     * Returns the attribute value.
+     */
+    public Object getAttributeValue() {
+        return (attributeValue);
+    }
+
+    /**
+     * Returns the attribute in user readable form.
+     */
+    public String toString() {
+        return (attributeValue.toString());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/sun/security/pkcs10/PKCS10Attributes.java	Wed Jul 05 17:54:24 2017 +0200
@@ -0,0 +1,219 @@
+/*
+ * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
+ * 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.security.pkcs10;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.security.cert.CertificateException;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.Hashtable;
+
+import sun.security.util.*;
+
+/**
+ * This class defines the PKCS10 attributes for the request.
+ * The ASN.1 syntax for this is:
+ * <pre>
+ * Attributes ::= SET OF Attribute
+ * </pre>
+ *
+ * @author Amit Kapoor
+ * @author Hemma Prafullchandra
+ * @see PKCS10
+ * @see PKCS10Attribute
+ */
+public class PKCS10Attributes implements DerEncoder {
+
+    private Hashtable<String, PKCS10Attribute> map =
+                        new Hashtable<String, PKCS10Attribute>(3);
+
+    /**
+     * Default constructor for the PKCS10 attribute.
+     */
+    public PKCS10Attributes() { }
+
+    /**
+     * Create the object from the array of PKCS10Attribute objects.
+     *
+     * @param attrs the array of PKCS10Attribute objects.
+     */
+    public PKCS10Attributes(PKCS10Attribute[] attrs) {
+        for (int i = 0; i < attrs.length; i++) {
+            map.put(attrs[i].getAttributeId().toString(), attrs[i]);
+        }
+    }
+
+    /**
+     * Create the object, decoding the values from the passed DER stream.
+     * The DER stream contains the SET OF Attribute.
+     *
+     * @param in the DerInputStream to read the attributes from.
+     * @exception IOException on decoding errors.
+     */
+    public PKCS10Attributes(DerInputStream in) throws IOException {
+        DerValue[] attrs = in.getSet(3, true);
+
+        if (attrs == null)
+            throw new IOException("Illegal encoding of attributes");
+        for (int i = 0; i < attrs.length; i++) {
+            PKCS10Attribute attr = new PKCS10Attribute(attrs[i]);
+            map.put(attr.getAttributeId().toString(), attr);
+        }
+    }
+
+    /**
+     * Encode the attributes in DER form to the stream.
+     *
+     * @param out the OutputStream to marshal the contents to.
+     * @exception IOException on encoding errors.
+     */
+    public void encode(OutputStream out) throws IOException {
+        derEncode(out);
+    }
+
+    /**
+     * Encode the attributes in DER form to the stream.
+     * Implements the <code>DerEncoder</code> interface.
+     *
+     * @param out the OutputStream to marshal the contents to.
+     * @exception IOException on encoding errors.
+     */
+    public void derEncode(OutputStream out) throws IOException {
+        // first copy the elements into an array
+        Collection<PKCS10Attribute> allAttrs = map.values();
+        PKCS10Attribute[] attribs =
+                allAttrs.toArray(new PKCS10Attribute[map.size()]);
+
+        DerOutputStream attrOut = new DerOutputStream();
+        attrOut.putOrderedSetOf(DerValue.createTag(DerValue.TAG_CONTEXT,
+                                                   true, (byte)0),
+                                attribs);
+        out.write(attrOut.toByteArray());
+    }
+
+    /**
+     * Set the attribute value.
+     */
+    public void setAttribute(String name, Object obj) {
+        if (obj instanceof PKCS10Attribute) {
+            map.put(name, (PKCS10Attribute)obj);
+        }
+    }
+
+    /**
+     * Get the attribute value.
+     */
+    public Object getAttribute(String name) {
+        return map.get(name);
+    }
+
+    /**
+     * Delete the attribute value.
+     */
+    public void deleteAttribute(String name) {
+        map.remove(name);
+    }
+
+    /**
+     * Return an enumeration of names of attributes existing within this
+     * attribute.
+     */
+    public Enumeration<PKCS10Attribute> getElements() {
+        return (map.elements());
+    }
+
+    /**
+     * Return a Collection of attributes existing within this
+     * PKCS10Attributes object.
+     */
+    public Collection<PKCS10Attribute> getAttributes() {
+        return (Collections.unmodifiableCollection(map.values()));
+    }
+
+    /**
+     * Compares this PKCS10Attributes for equality with the specified
+     * object. If the <code>other</code> object is an
+     * <code>instanceof</code> <code>PKCS10Attributes</code>, then
+     * all the entries are compared with the entries from this.
+     *
+     * @param other the object to test for equality with this PKCS10Attributes.
+     * @return true if all the entries match that of the Other,
+     * false otherwise.
+     */
+    public boolean equals(Object other) {
+        if (this == other)
+            return true;
+        if (!(other instanceof PKCS10Attributes))
+            return false;
+
+        Collection<PKCS10Attribute> othersAttribs =
+                ((PKCS10Attributes)other).getAttributes();
+        PKCS10Attribute[] attrs =
+            othersAttribs.toArray(new PKCS10Attribute[othersAttribs.size()]);
+        int len = attrs.length;
+        if (len != map.size())
+            return false;
+        PKCS10Attribute thisAttr, otherAttr;
+        String key = null;
+        for (int i=0; i < len; i++) {
+            otherAttr = attrs[i];
+            key = otherAttr.getAttributeId().toString();
+
+            if (key == null)
+                return false;
+            thisAttr = map.get(key);
+            if (thisAttr == null)
+                return false;
+            if (! thisAttr.equals(otherAttr))
+                return false;
+        }
+        return true;
+    }
+
+    /**
+     * Returns a hashcode value for this PKCS10Attributes.
+     *
+     * @return the hashcode value.
+     */
+    public int hashCode() {
+        return map.hashCode();
+    }
+
+    /**
+     * Returns a string representation of this <tt>PKCS10Attributes</tt> object
+     * in the form of a set of entries, enclosed in braces and separated
+     * by the ASCII characters "<tt>,&nbsp;</tt>" (comma and space).
+     * <p>Overrides the <tt>toString</tt> method of <tt>Object</tt>.
+     *
+     * @return  a string representation of this PKCS10Attributes.
+     */
+    public String toString() {
+        String s = map.size() + "\n" + map.toString();
+        return s;
+    }
+}
--- a/jdk/src/share/classes/sun/security/pkcs11/Config.java	Wed Jul 05 17:53:51 2017 +0200
+++ b/jdk/src/share/classes/sun/security/pkcs11/Config.java	Wed Jul 05 17:54:24 2017 +0200
@@ -192,6 +192,11 @@
     // works only for NSS providers created via the Secmod API
     private boolean nssUseSecmodTrust = false;
 
+    // Flag to indicate whether the X9.63 encoding for EC points shall be used
+    // (true) or whether that encoding shall be wrapped in an ASN.1 OctetString
+    // (false).
+    private boolean useEcX963Encoding = false;
+
     private Config(String filename, InputStream in) throws IOException {
         if (in == null) {
             if (filename.startsWith("--")) {
@@ -320,6 +325,10 @@
         return nssUseSecmodTrust;
     }
 
+    boolean getUseEcX963Encoding() {
+        return useEcX963Encoding;
+    }
+
     private static String expand(final String s) throws IOException {
         try {
             return PropertyExpander.expand(s);
@@ -440,6 +449,8 @@
                 parseNSSArgs(word);
             } else if (word.equals("nssUseSecmodTrust")) {
                 nssUseSecmodTrust = parseBooleanEntry(word);
+            } else if (word.equals("useEcX963Encoding")) {
+                useEcX963Encoding = parseBooleanEntry(word);
             } else {
                 throw new ConfigurationException
                         ("Unknown keyword '" + word + "', line " + st.lineno());
--- a/jdk/src/share/classes/sun/security/pkcs11/KeyCache.java	Wed Jul 05 17:53:51 2017 +0200
+++ b/jdk/src/share/classes/sun/security/pkcs11/KeyCache.java	Wed Jul 05 17:54:24 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -48,7 +48,7 @@
  */
 final class KeyCache {
 
-    private final Cache strongCache;
+    private final Cache<IdentityWrapper, P11Key> strongCache;
 
     private WeakReference<Map<Key,P11Key>> cacheReference;
 
@@ -77,7 +77,7 @@
     }
 
     synchronized P11Key get(Key key) {
-        P11Key p11Key = (P11Key)strongCache.get(new IdentityWrapper(key));
+        P11Key p11Key = strongCache.get(new IdentityWrapper(key));
         if (p11Key != null) {
             return p11Key;
         }
@@ -94,8 +94,8 @@
         Map<Key,P11Key> map =
                 (cacheReference == null) ? null : cacheReference.get();
         if (map == null) {
-            map = new IdentityHashMap<Key,P11Key>();
-            cacheReference = new WeakReference<Map<Key,P11Key>>(map);
+            map = new IdentityHashMap<>();
+            cacheReference = new WeakReference<>(map);
         }
         map.put(key, p11Key);
     }
--- a/jdk/src/share/classes/sun/security/pkcs11/P11ECKeyFactory.java	Wed Jul 05 17:53:51 2017 +0200
+++ b/jdk/src/share/classes/sun/security/pkcs11/P11ECKeyFactory.java	Wed Jul 05 17:54:24 2017 +0200
@@ -203,14 +203,20 @@
 
     private PublicKey generatePublic(ECPoint point, ECParameterSpec params) throws PKCS11Exception {
         byte[] encodedParams = ECParameters.encodeParameters(params);
-        byte[] encodedPoint = null;
-        DerValue pkECPoint = new DerValue(DerValue.tag_OctetString,
-            ECParameters.encodePoint(point, params.getCurve()));
+        byte[] encodedPoint =
+            ECParameters.encodePoint(point, params.getCurve());
 
-        try {
-            encodedPoint = pkECPoint.toByteArray();
-        } catch (IOException e) {
-            throw new IllegalArgumentException("Could not DER encode point", e);
+        // Check whether the X9.63 encoding of an EC point shall be wrapped
+        // in an ASN.1 OCTET STRING
+        if (!token.config.getUseEcX963Encoding()) {
+            try {
+                encodedPoint =
+                    new DerValue(DerValue.tag_OctetString, encodedPoint)
+                        .toByteArray();
+            } catch (IOException e) {
+                throw new
+                    IllegalArgumentException("Could not DER encode point", e);
+            }
         }
 
         CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
--- a/jdk/src/share/classes/sun/security/pkcs11/P11Key.java	Wed Jul 05 17:53:51 2017 +0200
+++ b/jdk/src/share/classes/sun/security/pkcs11/P11Key.java	Wed Jul 05 17:54:24 2017 +0200
@@ -1028,28 +1028,21 @@
             try {
                 params = P11ECKeyFactory.decodeParameters
                             (attributes[1].getByteArray());
-
-                /*
-                 * An uncompressed EC point may be in either of two formats.
-                 * First try the OCTET STRING encoding:
-                 *   04 <length> 04 <X-coordinate> <Y-coordinate>
-                 *
-                 * Otherwise try the raw encoding:
-                 *   04 <X-coordinate> <Y-coordinate>
-                 */
                 byte[] ecKey = attributes[0].getByteArray();
 
-                try {
+                // Check whether the X9.63 encoding of an EC point is wrapped
+                // in an ASN.1 OCTET STRING
+                if (!token.config.getUseEcX963Encoding()) {
                     DerValue wECPoint = new DerValue(ecKey);
-                    if (wECPoint.getTag() != DerValue.tag_OctetString)
-                        throw new IOException("Unexpected tag: " +
-                            wECPoint.getTag());
 
+                    if (wECPoint.getTag() != DerValue.tag_OctetString) {
+                        throw new IOException("Could not DER decode EC point." +
+                            " Unexpected tag: " + wECPoint.getTag());
+                    }
                     w = P11ECKeyFactory.decodePoint
                         (wECPoint.getDataBytes(), params.getCurve());
 
-                } catch (IOException e) {
-                    // Failover
+                } else {
                     w = P11ECKeyFactory.decodePoint(ecKey, params.getCurve());
                 }
 
--- a/jdk/src/share/classes/sun/security/provider/X509Factory.java	Wed Jul 05 17:53:51 2017 +0200
+++ b/jdk/src/share/classes/sun/security/provider/X509Factory.java	Wed Jul 05 17:54:24 2017 +0200
@@ -64,8 +64,10 @@
 
     private static final int ENC_MAX_LENGTH = 4096 * 1024; // 4 MB MAX
 
-    private static final Cache certCache = Cache.newSoftMemoryCache(750);
-    private static final Cache crlCache = Cache.newSoftMemoryCache(750);
+    private static final Cache<Object, X509CertImpl> certCache
+        = Cache.newSoftMemoryCache(750);
+    private static final Cache<Object, X509CRLImpl> crlCache
+        = Cache.newSoftMemoryCache(750);
 
     /**
      * Generates an X.509 certificate object and initializes it with
@@ -90,7 +92,7 @@
         try {
             byte[] encoding = readOneBlock(is);
             if (encoding != null) {
-                X509CertImpl cert = (X509CertImpl)getFromCache(certCache, encoding);
+                X509CertImpl cert = getFromCache(certCache, encoding);
                 if (cert != null) {
                     return cert;
                 }
@@ -151,7 +153,7 @@
         } else {
             encoding = c.getEncoded();
         }
-        X509CertImpl newC = (X509CertImpl)getFromCache(certCache, encoding);
+        X509CertImpl newC = getFromCache(certCache, encoding);
         if (newC != null) {
             return newC;
         }
@@ -181,7 +183,7 @@
         } else {
             encoding = c.getEncoded();
         }
-        X509CRLImpl newC = (X509CRLImpl)getFromCache(crlCache, encoding);
+        X509CRLImpl newC = getFromCache(crlCache, encoding);
         if (newC != null) {
             return newC;
         }
@@ -198,18 +200,17 @@
     /**
      * Get the X509CertImpl or X509CRLImpl from the cache.
      */
-    private static synchronized Object getFromCache(Cache cache,
+    private static synchronized <K,V> V getFromCache(Cache<K,V> cache,
             byte[] encoding) {
         Object key = new Cache.EqualByteArray(encoding);
-        Object value = cache.get(key);
-        return value;
+        return cache.get(key);
     }
 
     /**
      * Add the X509CertImpl or X509CRLImpl to the cache.
      */
-    private static synchronized void addToCache(Cache cache, byte[] encoding,
-            Object value) {
+    private static synchronized <V> void addToCache(Cache<Object, V> cache,
+            byte[] encoding, V value) {
         if (encoding.length > ENC_MAX_LENGTH) {
             return;
         }
@@ -361,7 +362,7 @@
         try {
             byte[] encoding = readOneBlock(is);
             if (encoding != null) {
-                X509CRLImpl crl = (X509CRLImpl)getFromCache(crlCache, encoding);
+                X509CRLImpl crl = getFromCache(crlCache, encoding);
                 if (crl != null) {
                     return crl;
                 }
@@ -669,6 +670,23 @@
                 bout.write(midByte);
                 bout.write(lowByte);
                 length = (highByte << 16) | (midByte << 8) | lowByte;
+            } else if (n == 0x84) {
+                int highByte = is.read();
+                int nextByte = is.read();
+                int midByte = is.read();
+                int lowByte = is.read();
+                if (lowByte == -1) {
+                    throw new IOException("Incomplete BER/DER length info");
+                }
+                if (highByte > 127) {
+                    throw new IOException("Invalid BER/DER data (a little huge?)");
+                }
+                bout.write(highByte);
+                bout.write(nextByte);
+                bout.write(midByte);
+                bout.write(lowByte);
+                length = (highByte << 24 ) | (nextByte << 16) |
+                        (midByte << 8) | lowByte;
             } else { // ignore longer length forms
                 throw new IOException("Invalid BER/DER data (too huge?)");
             }
--- a/jdk/src/share/classes/sun/security/provider/certpath/CertStoreHelper.java	Wed Jul 05 17:53:51 2017 +0200
+++ b/jdk/src/share/classes/sun/security/provider/certpath/CertStoreHelper.java	Wed Jul 05 17:54:24 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
  * 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,32 +27,87 @@
 
 import java.net.URI;
 import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+import java.security.AccessController;
 import java.security.NoSuchAlgorithmException;
 import java.security.InvalidAlgorithmParameterException;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
 import java.security.cert.CertStore;
 import java.security.cert.X509CertSelector;
 import java.security.cert.X509CRLSelector;
 import javax.security.auth.x500.X500Principal;
 import java.io.IOException;
 
+import sun.security.util.Cache;
+
 /**
- * Helper used by URICertStore when delegating to another CertStore to
- * fetch certs and CRLs.
+ * Helper used by URICertStore and others when delegating to another CertStore
+ * to fetch certs and CRLs.
  */
 
-public interface CertStoreHelper {
+public abstract class CertStoreHelper {
+
+    private static final int NUM_TYPES = 2;
+    private final static Map<String,String> classMap = new HashMap<>(NUM_TYPES);
+    static {
+        classMap.put(
+            "LDAP",
+            "sun.security.provider.certpath.ldap.LDAPCertStoreHelper");
+        classMap.put(
+            "SSLServer",
+            "sun.security.provider.certpath.ssl.SSLServerCertStoreHelper");
+    };
+    private static Cache<String, CertStoreHelper> cache
+        = Cache.newSoftMemoryCache(NUM_TYPES);
+
+    public static CertStoreHelper getInstance(final String type)
+        throws NoSuchAlgorithmException
+    {
+        CertStoreHelper helper = cache.get(type);
+        if (helper != null) {
+            return helper;
+        }
+        final String cl = classMap.get(type);
+        if (cl == null) {
+            throw new NoSuchAlgorithmException(type + " not available");
+        }
+        try {
+            helper = AccessController.doPrivileged(
+                new PrivilegedExceptionAction<CertStoreHelper>() {
+                    public CertStoreHelper run() throws ClassNotFoundException {
+                        try {
+                            Class<?> c = Class.forName(cl, true, null);
+                            CertStoreHelper csh
+                                = (CertStoreHelper)c.newInstance();
+                            cache.put(type, csh);
+                            return csh;
+                        } catch (InstantiationException e) {
+                            throw new AssertionError(e);
+                        } catch (IllegalAccessException e) {
+                            throw new AssertionError(e);
+                        }
+                    }
+            });
+            return helper;
+        } catch (PrivilegedActionException e) {
+            throw new NoSuchAlgorithmException(type + " not available",
+                                               e.getException());
+        }
+    }
 
     /**
      * Returns a CertStore using the given URI as parameters.
      */
-    CertStore getCertStore(URI uri)
+    public abstract CertStore getCertStore(URI uri)
         throws NoSuchAlgorithmException, InvalidAlgorithmParameterException;
 
     /**
      * Wraps an existing X509CertSelector when needing to avoid DN matching
      * issues.
      */
-    X509CertSelector wrap(X509CertSelector selector,
+    public abstract X509CertSelector wrap(X509CertSelector selector,
                           X500Principal certSubject,
                           String dn)
         throws IOException;
@@ -61,7 +116,7 @@
      * Wraps an existing X509CRLSelector when needing to avoid DN matching
      * issues.
      */
-    X509CRLSelector wrap(X509CRLSelector selector,
+    public abstract X509CRLSelector wrap(X509CRLSelector selector,
                          Collection<X500Principal> certIssuers,
                          String dn)
         throws IOException;
--- a/jdk/src/share/classes/sun/security/provider/certpath/URICertStore.java	Wed Jul 05 17:53:51 2017 +0200
+++ b/jdk/src/share/classes/sun/security/provider/certpath/URICertStore.java	Wed Jul 05 17:54:24 2017 +0200
@@ -30,8 +30,6 @@
 import java.net.HttpURLConnection;
 import java.net.URI;
 import java.net.URLConnection;
-import java.security.AccessController;
-import java.security.PrivilegedAction;
 import java.security.InvalidAlgorithmParameterException;
 import java.security.NoSuchAlgorithmException;
 import java.security.Provider;
@@ -102,8 +100,7 @@
     private final CertificateFactory factory;
 
     // cached Collection of X509Certificates (may be empty, never null)
-    private Collection<X509Certificate> certs =
-        Collections.<X509Certificate>emptySet();
+    private Collection<X509Certificate> certs = Collections.emptySet();
 
     // cached X509CRL (may be null)
     private X509CRL crl;
@@ -120,36 +117,11 @@
 
     // true if URI is ldap
     private boolean ldap = false;
+    private CertStoreHelper ldapHelper;
     private CertStore ldapCertStore;
     private String ldapPath;
 
     /**
-     * Holder class to lazily load LDAPCertStoreHelper if present.
-     */
-    private static class LDAP {
-        private static final String CERT_STORE_HELPER =
-            "sun.security.provider.certpath.ldap.LDAPCertStoreHelper";
-        private static final CertStoreHelper helper =
-            AccessController.doPrivileged(
-                new PrivilegedAction<CertStoreHelper>() {
-                    public CertStoreHelper run() {
-                        try {
-                            Class<?> c = Class.forName(CERT_STORE_HELPER, true, null);
-                            return (CertStoreHelper)c.newInstance();
-                        } catch (ClassNotFoundException cnf) {
-                            return null;
-                        } catch (InstantiationException e) {
-                            throw new AssertionError(e);
-                        } catch (IllegalAccessException e) {
-                            throw new AssertionError(e);
-                        }
-                    }});
-        static CertStoreHelper helper() {
-            return helper;
-        }
-    }
-
-    /**
      * Creates a URICertStore.
      *
      * @param parameters specifying the URI
@@ -164,10 +136,9 @@
         this.uri = ((URICertStoreParameters) params).uri;
         // if ldap URI, use an LDAPCertStore to fetch certs and CRLs
         if (uri.getScheme().toLowerCase(Locale.ENGLISH).equals("ldap")) {
-            if (LDAP.helper() == null)
-                throw new NoSuchAlgorithmException("LDAP not present");
             ldap = true;
-            ldapCertStore = LDAP.helper().getCertStore(uri);
+            ldapHelper = CertStoreHelper.getInstance("LDAP");
+            ldapCertStore = ldapHelper.getCertStore(uri);
             ldapPath = uri.getPath();
             // strip off leading '/'
             if (ldapPath.charAt(0) == '/') {
@@ -185,14 +156,14 @@
      * Returns a URI CertStore. This method consults a cache of
      * CertStores (shared per JVM) using the URI as a key.
      */
-    private static final Cache certStoreCache =
-        Cache.newSoftMemoryCache(CACHE_SIZE);
+    private static final Cache<URICertStoreParameters, CertStore>
+        certStoreCache = Cache.newSoftMemoryCache(CACHE_SIZE);
     static synchronized CertStore getInstance(URICertStoreParameters params)
         throws NoSuchAlgorithmException, InvalidAlgorithmParameterException {
         if (debug != null) {
             debug.println("CertStore URI:" + params.uri);
         }
-        CertStore ucs = (CertStore) certStoreCache.get(params);
+        CertStore ucs = certStoreCache.get(params);
         if (ucs == null) {
             ucs = new UCS(new URICertStore(params), null, "URI", params);
             certStoreCache.put(params, ucs);
@@ -251,7 +222,7 @@
         if (ldap) {
             X509CertSelector xsel = (X509CertSelector) selector;
             try {
-                xsel = LDAP.helper().wrap(xsel, xsel.getSubject(), ldapPath);
+                xsel = ldapHelper.wrap(xsel, xsel.getSubject(), ldapPath);
             } catch (IOException ioe) {
                 throw new CertStoreException(ioe);
             }
@@ -273,62 +244,49 @@
             return getMatchingCerts(certs, selector);
         }
         lastChecked = time;
-        InputStream in = null;
         try {
             URLConnection connection = uri.toURL().openConnection();
             if (lastModified != 0) {
                 connection.setIfModifiedSince(lastModified);
             }
-            in = connection.getInputStream();
             long oldLastModified = lastModified;
-            lastModified = connection.getLastModified();
-            if (oldLastModified != 0) {
-                if (oldLastModified == lastModified) {
-                    if (debug != null) {
-                        debug.println("Not modified, using cached copy");
-                    }
-                    return getMatchingCerts(certs, selector);
-                } else if (connection instanceof HttpURLConnection) {
-                    // some proxy servers omit last modified
-                    HttpURLConnection hconn = (HttpURLConnection) connection;
-                    if (hconn.getResponseCode()
-                                == HttpURLConnection.HTTP_NOT_MODIFIED) {
+            try (InputStream in = connection.getInputStream()) {
+                lastModified = connection.getLastModified();
+                if (oldLastModified != 0) {
+                    if (oldLastModified == lastModified) {
                         if (debug != null) {
                             debug.println("Not modified, using cached copy");
                         }
                         return getMatchingCerts(certs, selector);
+                    } else if (connection instanceof HttpURLConnection) {
+                        // some proxy servers omit last modified
+                        HttpURLConnection hconn = (HttpURLConnection)connection;
+                        if (hconn.getResponseCode()
+                                    == HttpURLConnection.HTTP_NOT_MODIFIED) {
+                            if (debug != null) {
+                                debug.println("Not modified, using cached copy");
+                            }
+                            return getMatchingCerts(certs, selector);
+                        }
                     }
                 }
-            }
-            if (debug != null) {
-                debug.println("Downloading new certificates...");
+                if (debug != null) {
+                    debug.println("Downloading new certificates...");
+                }
+                // Safe cast since factory is an X.509 certificate factory
+                certs = (Collection<X509Certificate>)
+                    factory.generateCertificates(in);
             }
-            // Safe cast since factory is an X.509 certificate factory
-            certs = (Collection<X509Certificate>)
-                factory.generateCertificates(in);
             return getMatchingCerts(certs, selector);
-        } catch (IOException e) {
+        } catch (IOException | CertificateException e) {
             if (debug != null) {
                 debug.println("Exception fetching certificates:");
                 e.printStackTrace();
             }
-        } catch (CertificateException e) {
-            if (debug != null) {
-                debug.println("Exception fetching certificates:");
-                e.printStackTrace();
-            }
-        } finally {
-            if (in != null) {
-                try {
-                    in.close();
-                } catch (IOException e) {
-                    // ignore
-                }
-            }
         }
         // exception, forget previous values
         lastModified = 0;
-        certs = Collections.<X509Certificate>emptySet();
+        certs = Collections.emptySet();
         return certs;
     }
 
@@ -343,8 +301,7 @@
         if (selector == null) {
             return certs;
         }
-        List<X509Certificate> matchedCerts =
-            new ArrayList<X509Certificate>(certs.size());
+        List<X509Certificate> matchedCerts = new ArrayList<>(certs.size());
         for (X509Certificate cert : certs) {
             if (selector.match(cert)) {
                 matchedCerts.add(cert);
@@ -374,7 +331,7 @@
         if (ldap) {
             X509CRLSelector xsel = (X509CRLSelector) selector;
             try {
-                xsel = LDAP.helper().wrap(xsel, null, ldapPath);
+                xsel = ldapHelper.wrap(xsel, null, ldapPath);
             } catch (IOException ioe) {
                 throw new CertStoreException(ioe);
             }
@@ -395,61 +352,48 @@
             return getMatchingCRLs(crl, selector);
         }
         lastChecked = time;
-        InputStream in = null;
         try {
             URLConnection connection = uri.toURL().openConnection();
             if (lastModified != 0) {
                 connection.setIfModifiedSince(lastModified);
             }
-            in = connection.getInputStream();
             long oldLastModified = lastModified;
-            lastModified = connection.getLastModified();
-            if (oldLastModified != 0) {
-                if (oldLastModified == lastModified) {
-                    if (debug != null) {
-                        debug.println("Not modified, using cached copy");
-                    }
-                    return getMatchingCRLs(crl, selector);
-                } else if (connection instanceof HttpURLConnection) {
-                    // some proxy servers omit last modified
-                    HttpURLConnection hconn = (HttpURLConnection) connection;
-                    if (hconn.getResponseCode()
-                                == HttpURLConnection.HTTP_NOT_MODIFIED) {
+            try (InputStream in = connection.getInputStream()) {
+                lastModified = connection.getLastModified();
+                if (oldLastModified != 0) {
+                    if (oldLastModified == lastModified) {
                         if (debug != null) {
                             debug.println("Not modified, using cached copy");
                         }
                         return getMatchingCRLs(crl, selector);
+                    } else if (connection instanceof HttpURLConnection) {
+                        // some proxy servers omit last modified
+                        HttpURLConnection hconn = (HttpURLConnection)connection;
+                        if (hconn.getResponseCode()
+                                    == HttpURLConnection.HTTP_NOT_MODIFIED) {
+                            if (debug != null) {
+                                debug.println("Not modified, using cached copy");
+                            }
+                            return getMatchingCRLs(crl, selector);
+                        }
                     }
                 }
-            }
-            if (debug != null) {
-                debug.println("Downloading new CRL...");
+                if (debug != null) {
+                    debug.println("Downloading new CRL...");
+                }
+                crl = (X509CRL) factory.generateCRL(in);
             }
-            crl = (X509CRL) factory.generateCRL(in);
             return getMatchingCRLs(crl, selector);
-        } catch (IOException e) {
+        } catch (IOException | CRLException e) {
             if (debug != null) {
                 debug.println("Exception fetching CRL:");
                 e.printStackTrace();
             }
-        } catch (CRLException e) {
-            if (debug != null) {
-                debug.println("Exception fetching CRL:");
-                e.printStackTrace();
-            }
-        } finally {
-            if (in != null) {
-                try {
-                    in.close();
-                } catch (IOException e) {
-                    // ignore
-                }
-            }
         }
         // exception, forget previous values
         lastModified = 0;
         crl = null;
-        return Collections.<X509CRL>emptyList();
+        return Collections.emptyList();
     }
 
     /**
@@ -459,9 +403,9 @@
     private static Collection<X509CRL> getMatchingCRLs
         (X509CRL crl, CRLSelector selector) {
         if (selector == null || (crl != null && selector.match(crl))) {
-            return Collections.<X509CRL>singletonList(crl);
+            return Collections.singletonList(crl);
         } else {
-            return Collections.<X509CRL>emptyList();
+            return Collections.emptyList();
         }
     }
 
--- a/jdk/src/share/classes/sun/security/provider/certpath/X509CertificatePair.java	Wed Jul 05 17:53:51 2017 +0200
+++ b/jdk/src/share/classes/sun/security/provider/certpath/X509CertificatePair.java	Wed Jul 05 17:54:24 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2002, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -79,7 +79,8 @@
     private X509Certificate reverse;
     private byte[] encoded;
 
-    private static final Cache cache = Cache.newSoftMemoryCache(750);
+    private static final Cache<Object, X509CertificatePair> cache
+        = Cache.newSoftMemoryCache(750);
 
     /**
      * Creates an empty instance of X509CertificatePair.
@@ -114,7 +115,7 @@
      *
      * For internal use only, external code should use generateCertificatePair.
      */
-    private X509CertificatePair(byte[] encoded)throws CertificateException {
+    private X509CertificatePair(byte[] encoded) throws CertificateException {
         try {
             parse(new DerValue(encoded));
             this.encoded = encoded;
@@ -138,7 +139,7 @@
     public static synchronized X509CertificatePair generateCertificatePair
             (byte[] encoded) throws CertificateException {
         Object key = new Cache.EqualByteArray(encoded);
-        X509CertificatePair pair = (X509CertificatePair)cache.get(key);
+        X509CertificatePair pair = cache.get(key);
         if (pair != null) {
             return pair;
         }
--- a/jdk/src/share/classes/sun/security/provider/certpath/ldap/LDAPCertStore.java	Wed Jul 05 17:53:51 2017 +0200
+++ b/jdk/src/share/classes/sun/security/provider/certpath/ldap/LDAPCertStore.java	Wed Jul 05 17:54:24 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
  * 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,7 +103,7 @@
  * @author      Steve Hanna
  * @author      Andreas Sterbenz
  */
-public class LDAPCertStore extends CertStoreSpi {
+public final class LDAPCertStore extends CertStoreSpi {
 
     private static final Debug debug = Debug.getInstance("certpath");
 
@@ -160,7 +160,7 @@
      */
     private boolean prefetchCRLs = false;
 
-    private final Cache valueCache;
+    private final Cache<String, byte[][]> valueCache;
 
     private int cacheHits = 0;
     private int cacheMisses = 0;
@@ -207,10 +207,11 @@
      * Returns an LDAP CertStore. This method consults a cache of
      * CertStores (shared per JVM) using the LDAP server/port as a key.
      */
-    private static final Cache certStoreCache = Cache.newSoftMemoryCache(185);
+    private static final Cache<LDAPCertStoreParameters, CertStore>
+        certStoreCache = Cache.newSoftMemoryCache(185);
     static synchronized CertStore getInstance(LDAPCertStoreParameters params)
         throws NoSuchAlgorithmException, InvalidAlgorithmParameterException {
-        CertStore lcs = (CertStore) certStoreCache.get(params);
+        CertStore lcs = certStoreCache.get(params);
         if (lcs == null) {
             lcs = CertStore.getInstance("LDAP", params);
             certStoreCache.put(params, lcs);
@@ -232,7 +233,7 @@
     private void createInitialDirContext(String server, int port)
             throws InvalidAlgorithmParameterException {
         String url = "ldap://" + server + ":" + port;
-        Hashtable<String,Object> env = new Hashtable<String,Object>();
+        Hashtable<String,Object> env = new Hashtable<>();
         env.put(Context.INITIAL_CONTEXT_FACTORY,
                 "com.sun.jndi.ldap.LdapCtxFactory");
         env.put(Context.PROVIDER_URL, url);
@@ -283,7 +284,7 @@
 
         LDAPRequest(String name) {
             this.name = name;
-            requestedAttributes = new ArrayList<String>(5);
+            requestedAttributes = new ArrayList<>(5);
         }
 
         String getName() {
@@ -311,7 +312,7 @@
                         + cacheMisses);
             }
             String cacheKey = name + "|" + attrId;
-            byte[][] values = (byte[][])valueCache.get(cacheKey);
+            byte[][] values = valueCache.get(cacheKey);
             if (values != null) {
                 cacheHits++;
                 return values;
@@ -347,7 +348,7 @@
                     System.out.println("LDAP requests: " + requests);
                 }
             }
-            valueMap = new HashMap<String, byte[][]>(8);
+            valueMap = new HashMap<>(8);
             String[] attrIds = requestedAttributes.toArray(STRING0);
             Attributes attrs;
             try {
@@ -429,10 +430,10 @@
 
         int n = encodedCert.length;
         if (n == 0) {
-            return Collections.<X509Certificate>emptySet();
+            return Collections.emptySet();
         }
 
-        List<X509Certificate> certs = new ArrayList<X509Certificate>(n);
+        List<X509Certificate> certs = new ArrayList<>(n);
         /* decode certs and check if they satisfy selector */
         for (int i = 0; i < n; i++) {
             ByteArrayInputStream bais = new ByteArrayInputStream(encodedCert[i]);
@@ -477,11 +478,10 @@
 
         int n = encodedCertPair.length;
         if (n == 0) {
-            return Collections.<X509CertificatePair>emptySet();
+            return Collections.emptySet();
         }
 
-        List<X509CertificatePair> certPairs =
-                                new ArrayList<X509CertificatePair>(n);
+        List<X509CertificatePair> certPairs = new ArrayList<>(n);
         /* decode each cert pair and add it to the Collection */
         for (int i = 0; i < n; i++) {
             try {
@@ -528,8 +528,7 @@
                                 getCertPairs(request, CROSS_CERT);
 
         // Find Certificates that match and put them in a list
-        ArrayList<X509Certificate> matchingCerts =
-                                        new ArrayList<X509Certificate>();
+        ArrayList<X509Certificate> matchingCerts = new ArrayList<>();
         for (X509CertificatePair certPair : certPairs) {
             X509Certificate cert;
             if (forward != null) {
@@ -587,7 +586,7 @@
         int basicConstraints = xsel.getBasicConstraints();
         String subject = xsel.getSubjectAsString();
         String issuer = xsel.getIssuerAsString();
-        HashSet<X509Certificate> certs = new HashSet<X509Certificate>();
+        HashSet<X509Certificate> certs = new HashSet<>();
         if (debug != null) {
             debug.println("LDAPCertStore.engineGetCertificates() basicConstraints: "
                 + basicConstraints);
@@ -706,10 +705,10 @@
 
         int n = encodedCRL.length;
         if (n == 0) {
-            return Collections.<X509CRL>emptySet();
+            return Collections.emptySet();
         }
 
-        List<X509CRL> crls = new ArrayList<X509CRL>(n);
+        List<X509CRL> crls = new ArrayList<>(n);
         /* decode each crl and check if it matches selector */
         for (int i = 0; i < n; i++) {
             try {
@@ -765,13 +764,13 @@
             throw new CertStoreException("need X509CRLSelector to find CRLs");
         }
         X509CRLSelector xsel = (X509CRLSelector) selector;
-        HashSet<X509CRL> crls = new HashSet<X509CRL>();
+        HashSet<X509CRL> crls = new HashSet<>();
 
         // Look in directory entry for issuer of cert we're checking.
         Collection<Object> issuerNames;
         X509Certificate certChecking = xsel.getCertificateChecking();
         if (certChecking != null) {
-            issuerNames = new HashSet<Object>();
+            issuerNames = new HashSet<>();
             X500Principal issuer = certChecking.getIssuerX500Principal();
             issuerNames.add(issuer.getName(X500Principal.RFC2253));
         } else {
@@ -796,7 +795,7 @@
                 issuerName = (String)nameObject;
             }
             // If all we want is CA certs, try to get the (probably shorter) ARL
-            Collection<X509CRL> entryCRLs = Collections.<X509CRL>emptySet();
+            Collection<X509CRL> entryCRLs = Collections.emptySet();
             if (certChecking == null || certChecking.getBasicConstraints() != -1) {
                 LDAPRequest request = new LDAPRequest(issuerName);
                 request.addRequestedAttribute(CROSS_CERT);
@@ -1028,9 +1027,9 @@
             throws IOException {
             this.selector = selector == null ? new X509CRLSelector() : selector;
             this.certIssuers = certIssuers;
-            issuerNames = new HashSet<Object>();
+            issuerNames = new HashSet<>();
             issuerNames.add(ldapDN);
-            issuers = new HashSet<X500Principal>();
+            issuers = new HashSet<>();
             issuers.add(new X500Name(ldapDN).asX500Principal());
         }
         // we only override the get (accessor methods) since the set methods
--- a/jdk/src/share/classes/sun/security/provider/certpath/ldap/LDAPCertStoreHelper.java	Wed Jul 05 17:53:51 2017 +0200
+++ b/jdk/src/share/classes/sun/security/provider/certpath/ldap/LDAPCertStoreHelper.java	Wed Jul 05 17:54:24 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
  * 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,11 +41,9 @@
  * LDAP implementation of CertStoreHelper.
  */
 
-public class LDAPCertStoreHelper
-    implements CertStoreHelper
+public final class LDAPCertStoreHelper
+    extends CertStoreHelper
 {
-    public LDAPCertStoreHelper() { }
-
     @Override
     public CertStore getCertStore(URI uri)
         throws NoSuchAlgorithmException, InvalidAlgorithmParameterException
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/sun/security/provider/certpath/ssl/SSLServerCertStore.java	Wed Jul 05 17:54:24 2017 +0200
@@ -0,0 +1,153 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * 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.security.provider.certpath.ssl;
+
+import java.io.IOException;
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.security.GeneralSecurityException;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.Provider;
+import java.security.cert.CertificateException;
+import java.security.cert.CertSelector;
+import java.security.cert.CertStore;
+import java.security.cert.CertStoreException;
+import java.security.cert.CertStoreParameters;
+import java.security.cert.CertStoreSpi;
+import java.security.cert.CRLSelector;
+import java.security.cert.X509Certificate;
+import java.security.cert.X509CRL;
+import javax.net.ssl.HostnameVerifier;
+import javax.net.ssl.HttpsURLConnection;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLSession;
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.X509TrustManager;
+
+/**
+ * A CertStore that retrieves an SSL server's certificate chain.
+ */
+public final class SSLServerCertStore extends CertStoreSpi {
+
+    private final URI uri;
+
+    SSLServerCertStore(URI uri) throws InvalidAlgorithmParameterException {
+        super(null);
+        this.uri = uri;
+    }
+
+    public synchronized Collection<X509Certificate> engineGetCertificates
+        (CertSelector selector) throws CertStoreException
+    {
+        try {
+            SSLContext sc = SSLContext.getInstance("SSL");
+            GetChainTrustManager xtm = new GetChainTrustManager();
+            sc.init(null, new TrustManager[] { xtm }, null);
+            HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
+            HttpsURLConnection.setDefaultHostnameVerifier(
+                new HostnameVerifier() {
+                    public boolean verify(String hostname, SSLSession session) {
+                        return true;
+                    }
+            });
+            uri.toURL().openConnection().connect();
+            return getMatchingCerts(xtm.serverChain, selector);
+        } catch (GeneralSecurityException | IOException e) {
+            throw new CertStoreException(e);
+        }
+    }
+
+    private static List<X509Certificate> getMatchingCerts
+        (List<X509Certificate> certs, CertSelector selector)
+    {
+        // if selector not specified, all certs match
+        if (selector == null) {
+            return certs;
+        }
+        List<X509Certificate> matchedCerts = new ArrayList<>(certs.size());
+        for (X509Certificate cert : certs) {
+            if (selector.match(cert)) {
+                matchedCerts.add(cert);
+            }
+        }
+        return matchedCerts;
+    }
+
+    public Collection<X509CRL> engineGetCRLs(CRLSelector selector)
+        throws CertStoreException
+    {
+        throw new UnsupportedOperationException();
+    }
+
+    static synchronized CertStore getInstance(URI uri)
+        throws InvalidAlgorithmParameterException
+    {
+        return new CS(new SSLServerCertStore(uri), null, "SSLServer", null);
+    }
+
+    /*
+     * An X509TrustManager that simply stores a reference to the server's
+     * certificate chain.
+     */
+    private static class GetChainTrustManager implements X509TrustManager {
+        private List<X509Certificate> serverChain;
+
+        public X509Certificate[] getAcceptedIssuers() {
+            throw new UnsupportedOperationException();
+        }
+
+        public void checkClientTrusted(X509Certificate[] chain,
+                                       String authType)
+            throws CertificateException
+        {
+            throw new UnsupportedOperationException();
+        }
+
+        public void checkServerTrusted(X509Certificate[] chain,
+                                       String authType)
+            throws CertificateException
+        {
+            this.serverChain = (chain == null)
+                               ? Collections.<X509Certificate>emptyList()
+                               : Arrays.asList(chain);
+        }
+    }
+
+    /**
+     * This class allows the SSLServerCertStore to be accessed as a CertStore.
+     */
+    private static class CS extends CertStore {
+        protected CS(CertStoreSpi spi, Provider p, String type,
+                     CertStoreParameters params)
+        {
+            super(spi, p, type, params);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/sun/security/provider/certpath/ssl/SSLServerCertStoreHelper.java	Wed Jul 05 17:54:24 2017 +0200
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * 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.security.provider.certpath.ssl;
+
+import java.net.URI;
+import java.util.Collection;
+import java.security.NoSuchAlgorithmException;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.cert.CertStore;
+import java.security.cert.X509CertSelector;
+import java.security.cert.X509CRLSelector;
+import javax.security.auth.x500.X500Principal;
+import java.io.IOException;
+
+import sun.security.provider.certpath.CertStoreHelper;
+
+/**
+ * SSL implementation of CertStoreHelper.
+ */
+public final class SSLServerCertStoreHelper extends CertStoreHelper {
+
+    @Override
+    public CertStore getCertStore(URI uri)
+        throws NoSuchAlgorithmException, InvalidAlgorithmParameterException
+    {
+        return SSLServerCertStore.getInstance(uri);
+    }
+
+    @Override
+    public X509CertSelector wrap(X509CertSelector selector,
+                                 X500Principal certSubject,
+                                 String ldapDN)
+        throws IOException
+    {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public X509CRLSelector wrap(X509CRLSelector selector,
+                                Collection<X500Principal> certIssuers,
+                                String ldapDN)
+        throws IOException
+    {
+        throw new UnsupportedOperationException();
+    }
+}
--- a/jdk/src/share/classes/sun/security/ssl/CipherBox.java	Wed Jul 05 17:53:51 2017 +0200
+++ b/jdk/src/share/classes/sun/security/ssl/CipherBox.java	Wed Jul 05 17:54:24 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -305,9 +305,11 @@
                     byte[] buf = null;
                     int limit = bb.limit();
                     if (bb.hasArray()) {
+                        int arrayOffset = bb.arrayOffset();
                         buf = bb.array();
-                        System.arraycopy(buf, pos,
-                                buf, pos + prefix.length, limit - pos);
+                        System.arraycopy(buf, arrayOffset + pos,
+                            buf, arrayOffset + pos + prefix.length,
+                            limit - pos);
                         bb.limit(limit + prefix.length);
                     } else {
                         buf = new byte[limit - pos];
@@ -491,9 +493,10 @@
                     byte[] buf = null;
                     int limit = bb.limit();
                     if (bb.hasArray()) {
+                        int arrayOffset = bb.arrayOffset();
                         buf = bb.array();
-                        System.arraycopy(buf, pos + blockSize,
-                                         buf, pos, limit - pos - blockSize);
+                        System.arraycopy(buf, arrayOffset + pos + blockSize,
+                            buf, arrayOffset + pos, limit - pos - blockSize);
                         bb.limit(limit - blockSize);
                     } else {
                         buf = new byte[limit - pos - blockSize];
--- a/jdk/src/share/classes/sun/security/ssl/SSLSessionContextImpl.java	Wed Jul 05 17:53:51 2017 +0200
+++ b/jdk/src/share/classes/sun/security/ssl/SSLSessionContextImpl.java	Wed Jul 05 17:54:24 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
  * 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,14 @@
 import javax.net.ssl.SSLSession;
 
 import sun.security.util.Cache;
+import sun.security.util.Cache.CacheVisitor;
 
 
 final class SSLSessionContextImpl implements SSLSessionContext {
-    private Cache sessionCache;         // session cache, session id as key
-    private Cache sessionHostPortCache; // session cache, "host:port" as key
+    private Cache<SessionId, SSLSessionImpl> sessionCache;
+                                        // session cache, session id as key
+    private Cache<String, SSLSessionImpl> sessionHostPortCache;
+                                        // session cache, "host:port" as key
     private int cacheLimit;             // the max cache size
     private int timeout;                // timeout in seconds
 
@@ -71,8 +74,7 @@
             throw new NullPointerException("session id cannot be null");
         }
 
-        SSLSessionImpl sess =
-                (SSLSessionImpl)sessionCache.get(new SessionId(sessionId));
+        SSLSessionImpl sess = sessionCache.get(new SessionId(sessionId));
         if (!isTimedout(sess)) {
             return sess;
         }
@@ -157,8 +159,7 @@
             return null;
         }
 
-        SSLSessionImpl sess =
-            (SSLSessionImpl)sessionHostPortCache.get(getKey(hostname, port));
+        SSLSessionImpl sess = sessionHostPortCache.get(getKey(hostname, port));
         if (!isTimedout(sess)) {
             return sess;
         }
@@ -193,7 +194,7 @@
 
     // package-private method, remove a cached SSLSession
     void remove(SessionId key) {
-        SSLSessionImpl s = (SSLSessionImpl)sessionCache.get(key);
+        SSLSessionImpl s = sessionCache.get(key);
         if (s != null) {
             sessionCache.remove(key);
             sessionHostPortCache.remove(
@@ -233,17 +234,17 @@
     }
 
     final class SessionCacheVisitor
-            implements sun.security.util.Cache.CacheVisitor {
+            implements Cache.CacheVisitor<SessionId, SSLSessionImpl> {
         Vector<byte[]> ids = null;
 
-        // public void visit(java.util.Map<Object, Object> map) {}
-        public void visit(java.util.Map<Object, Object> map) {
-            ids = new Vector<byte[]>(map.size());
+        // public void visit(java.util.Map<K,V> map) {}
+        public void visit(java.util.Map<SessionId, SSLSessionImpl> map) {
+            ids = new Vector<>(map.size());
 
-            for (Object key : map.keySet()) {
-                SSLSessionImpl value = (SSLSessionImpl)map.get(key);
+            for (SessionId key : map.keySet()) {
+                SSLSessionImpl value = map.get(key);
                 if (!isTimedout(value)) {
-                    ids.addElement(((SessionId)key).getId());
+                    ids.addElement(key.getId());
                 }
             }
         }
--- a/jdk/src/share/classes/sun/security/timestamp/HttpTimestamper.java	Wed Jul 05 17:53:51 2017 +0200
+++ b/jdk/src/share/classes/sun/security/timestamp/HttpTimestamper.java	Wed Jul 05 17:54:24 2017 +0200
@@ -28,13 +28,13 @@
 import java.io.BufferedInputStream;
 import java.io.DataOutputStream;
 import java.io.IOException;
+import java.net.URI;
 import java.net.URL;
 import java.net.HttpURLConnection;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
+import java.util.*;
 
 import sun.misc.IOUtils;
+import sun.security.util.Debug;
 
 /**
  * A timestamper that communicates with a Timestamping Authority (TSA)
@@ -58,20 +58,23 @@
     private static final String TS_REPLY_MIME_TYPE =
         "application/timestamp-reply";
 
-    private static final boolean DEBUG = false;
+    private static final Debug debug = Debug.getInstance("ts");
 
     /*
-     * HTTP URL identifying the location of the TSA
+     * HTTP URI identifying the location of the TSA
      */
-    private String tsaUrl = null;
+    private URI tsaURI = null;
 
     /**
      * Creates a timestamper that connects to the specified TSA.
      *
-     * @param tsa The location of the TSA. It must be an HTTP URL.
+     * @param tsa The location of the TSA. It must be an HTTP URI.
+     * @throws IllegalArgumentException if tsaURI is not an HTTP URI
      */
-    public HttpTimestamper(String tsaUrl) {
-        this.tsaUrl = tsaUrl;
+    public HttpTimestamper(URI tsaURI) {
+        if (!tsaURI.getScheme().equalsIgnoreCase("http"))
+            throw new IllegalArgumentException("TSA must be an HTTP URI");
+        this.tsaURI = tsaURI;
     }
 
     /**
@@ -85,7 +88,7 @@
     public TSResponse generateTimestamp(TSRequest tsQuery) throws IOException {
 
         HttpURLConnection connection =
-            (HttpURLConnection) new URL(tsaUrl).openConnection();
+            (HttpURLConnection) tsaURI.toURL().openConnection();
         connection.setDoOutput(true);
         connection.setUseCaches(false); // ignore cache
         connection.setRequestProperty("Content-Type", TS_QUERY_MIME_TYPE);
@@ -93,15 +96,15 @@
         // Avoids the "hang" when a proxy is required but none has been set.
         connection.setConnectTimeout(CONNECT_TIMEOUT);
 
-        if (DEBUG) {
+        if (debug != null) {
             Set<Map.Entry<String, List<String>>> headers =
-                    connection.getRequestProperties().entrySet();
-            System.out.println(connection.getRequestMethod() + " " + tsaUrl +
+                connection.getRequestProperties().entrySet();
+            debug.println(connection.getRequestMethod() + " " + tsaURI +
                 " HTTP/1.1");
-            for (Map.Entry<String, List<String>> entry : headers) {
-                System.out.println("  " + entry);
+            for (Map.Entry<String, List<String>> e : headers) {
+                debug.println("  " + e);
             }
-            System.out.println();
+            debug.println();
         }
         connection.connect(); // No HTTP authentication is performed
 
@@ -112,8 +115,8 @@
             byte[] request = tsQuery.encode();
             output.write(request, 0, request.length);
             output.flush();
-            if (DEBUG) {
-                System.out.println("sent timestamp query (length=" +
+            if (debug != null) {
+                debug.println("sent timestamp query (length=" +
                         request.length + ")");
             }
         } finally {
@@ -127,17 +130,17 @@
         byte[] replyBuffer = null;
         try {
             input = new BufferedInputStream(connection.getInputStream());
-            if (DEBUG) {
+            if (debug != null) {
                 String header = connection.getHeaderField(0);
-                System.out.println(header);
+                debug.println(header);
                 int i = 1;
                 while ((header = connection.getHeaderField(i)) != null) {
                     String key = connection.getHeaderFieldKey(i);
-                    System.out.println("  " + ((key==null) ? "" : key + ": ") +
+                    debug.println("  " + ((key==null) ? "" : key + ": ") +
                         header);
                     i++;
                 }
-                System.out.println();
+                debug.println();
             }
             verifyMimeType(connection.getContentType());
 
@@ -145,8 +148,8 @@
             int contentLength = connection.getContentLength();
             replyBuffer = IOUtils.readFully(input, contentLength, false);
 
-            if (DEBUG) {
-                System.out.println("received timestamp response (length=" +
+            if (debug != null) {
+                debug.println("received timestamp response (length=" +
                         total + ")");
             }
         } finally {
--- a/jdk/src/share/classes/sun/security/timestamp/TSRequest.java	Wed Jul 05 17:53:51 2017 +0200
+++ b/jdk/src/share/classes/sun/security/timestamp/TSRequest.java	Wed Jul 05 17:54:24 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
  * 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,13 @@
 
 import java.io.IOException;
 import java.math.BigInteger;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
 import java.security.cert.X509Extension;
 import sun.security.util.DerValue;
 import sun.security.util.DerOutputStream;
 import sun.security.util.ObjectIdentifier;
+import sun.security.x509.AlgorithmId;
 
 /**
  * This class provides a timestamp request, as defined in
@@ -64,24 +67,9 @@
 
 public class TSRequest {
 
-    private static final ObjectIdentifier SHA1_OID;
-    private static final ObjectIdentifier MD5_OID;
-    static {
-        ObjectIdentifier sha1 = null;
-        ObjectIdentifier md5 = null;
-        try {
-            sha1 = new ObjectIdentifier("1.3.14.3.2.26");
-            md5 = new ObjectIdentifier("1.2.840.113549.2.5");
-        } catch (IOException ioe) {
-            // should not happen
-        }
-        SHA1_OID = sha1;
-        MD5_OID = md5;
-    }
-
     private int version = 1;
 
-    private ObjectIdentifier hashAlgorithmId = null;
+    private AlgorithmId hashAlgorithmId = null;
 
     private byte[] hashValue;
 
@@ -94,30 +82,21 @@
     private X509Extension[] extensions = null;
 
     /**
-     * Constructs a timestamp request for the supplied hash value..
+     * Constructs a timestamp request for the supplied data.
      *
-     * @param hashValue     The hash value. This is the data to be timestamped.
-     * @param hashAlgorithm The name of the hash algorithm.
+     * @param toBeTimeStamped  The data to be timestamped.
+     * @param messageDigest The MessageDigest of the hash algorithm to use.
+     * @throws NoSuchAlgorithmException if the hash algorithm is not supported
      */
-    public TSRequest(byte[] hashValue, String hashAlgorithm) {
+    public TSRequest(byte[] toBeTimeStamped, MessageDigest messageDigest)
+        throws NoSuchAlgorithmException {
 
-        // Check the common hash algorithms
-        if ("MD5".equalsIgnoreCase(hashAlgorithm)) {
-            hashAlgorithmId = MD5_OID;
-            // Check that the hash value matches the hash algorithm
-            assert hashValue.length == 16;
+        this.hashAlgorithmId = AlgorithmId.get(messageDigest.getAlgorithm());
+        this.hashValue = messageDigest.digest(toBeTimeStamped);
+    }
 
-        } else if ("SHA-1".equalsIgnoreCase(hashAlgorithm) ||
-            "SHA".equalsIgnoreCase(hashAlgorithm) ||
-            "SHA1".equalsIgnoreCase(hashAlgorithm)) {
-            hashAlgorithmId = SHA1_OID;
-            // Check that the hash value matches the hash algorithm
-            assert hashValue.length == 20;
-
-        }
-        // Clone the hash value
-        this.hashValue = new byte[hashValue.length];
-        System.arraycopy(hashValue, 0, this.hashValue, 0, hashValue.length);
+    public byte[] getHashedMessage() {
+        return hashValue.clone();
     }
 
     /**
@@ -176,9 +155,7 @@
 
         // encode messageImprint
         DerOutputStream messageImprint = new DerOutputStream();
-        DerOutputStream hashAlgorithm = new DerOutputStream();
-        hashAlgorithm.putOID(hashAlgorithmId);
-        messageImprint.write(DerValue.tag_Sequence, hashAlgorithm);
+        hashAlgorithmId.encode(messageImprint);
         messageImprint.putOctetString(hashValue);
         request.write(DerValue.tag_Sequence, messageImprint);
 
--- a/jdk/src/share/classes/sun/security/timestamp/TSResponse.java	Wed Jul 05 17:53:51 2017 +0200
+++ b/jdk/src/share/classes/sun/security/timestamp/TSResponse.java	Wed Jul 05 17:54:24 2017 +0200
@@ -27,6 +27,7 @@
 
 import java.io.IOException;
 import sun.security.pkcs.PKCS7;
+import sun.security.util.Debug;
 import sun.security.util.DerValue;
 
 /**
@@ -175,18 +176,20 @@
      */
     public static final int SYSTEM_FAILURE = 25;
 
-    private static final boolean DEBUG = false;
+    private static final Debug debug = Debug.getInstance("ts");
 
     private int status;
 
     private String[] statusString = null;
 
-    private int failureInfo = -1;
+    private boolean[] failureInfo = null;
 
     private byte[] encodedTsToken = null;
 
     private PKCS7 tsToken = null;
 
+    private TimestampToken tstInfo;
+
     /**
      * Constructs an object to store the response to a timestamp request.
      *
@@ -215,11 +218,11 @@
     }
 
     /**
-     * Retrieve the failure code returned by the TSA.
+     * Retrieve the failure info returned by the TSA.
      *
-     * @return If -1 then no failure code was received.
+     * @return the failure info, or null if no failure code was received.
      */
-    public int getFailureCode() {
+    public boolean[] getFailureInfo() {
         return failureInfo;
     }
 
@@ -250,42 +253,38 @@
         }
     }
 
+    private boolean isSet(int position) {
+        return failureInfo[position];
+    }
+
     public String getFailureCodeAsText() {
 
-        if (failureInfo == -1) {
-            return null;
+        if (failureInfo == null) {
+            return "";
         }
 
-        switch (failureInfo)  {
-
-        case BAD_ALG:
-            return "Unrecognized or unsupported alrorithm identifier.";
-
-        case BAD_REQUEST:
-            return "The requested transaction is not permitted or supported.";
-
-        case BAD_DATA_FORMAT:
-            return "The data submitted has the wrong format.";
-
-        case TIME_NOT_AVAILABLE:
-            return "The TSA's time source is not available.";
+        try {
+            if (isSet(BAD_ALG))
+                return "Unrecognized or unsupported algorithm identifier.";
+            if (isSet(BAD_REQUEST))
+                return "The requested transaction is not permitted or " +
+                       "supported.";
+            if (isSet(BAD_DATA_FORMAT))
+                return "The data submitted has the wrong format.";
+            if (isSet(TIME_NOT_AVAILABLE))
+                return "The TSA's time source is not available.";
+            if (isSet(UNACCEPTED_POLICY))
+                return "The requested TSA policy is not supported by the TSA.";
+            if (isSet(UNACCEPTED_EXTENSION))
+                return "The requested extension is not supported by the TSA.";
+            if (isSet(ADD_INFO_NOT_AVAILABLE))
+                return "The additional information requested could not be " +
+                       "understood or is not available.";
+            if (isSet(SYSTEM_FAILURE))
+                return "The request cannot be handled due to system failure.";
+        } catch (ArrayIndexOutOfBoundsException ex) {}
 
-        case UNACCEPTED_POLICY:
-            return "The requested TSA policy is not supported by the TSA.";
-
-        case UNACCEPTED_EXTENSION:
-            return "The requested extension is not supported by the TSA.";
-
-        case ADD_INFO_NOT_AVAILABLE:
-            return "The additional information requested could not be " +
-                "understood or is not available.";
-
-        case SYSTEM_FAILURE:
-            return "The request cannot be handled due to system failure.";
-
-        default:
-            return ("unknown status code " + status);
-        }
+        return ("unknown failure code");
     }
 
     /**
@@ -297,6 +296,10 @@
         return tsToken;
     }
 
+    public TimestampToken getTimestampToken() {
+        return tstInfo;
+    }
+
     /**
      * Retrieve the ASN.1 BER encoded timestamp token returned by the TSA.
      *
@@ -323,29 +326,30 @@
 
         // Parse status
 
-        DerValue status = derValue.data.getDerValue();
-        // Parse status
-        this.status = status.data.getInteger();
-        if (DEBUG) {
-            System.out.println("timestamp response: status=" + this.status);
+        DerValue statusInfo = derValue.data.getDerValue();
+        this.status = statusInfo.data.getInteger();
+        if (debug != null) {
+            debug.println("timestamp response: status=" + this.status);
         }
         // Parse statusString, if present
-        if (status.data.available() > 0) {
-            DerValue[] strings = status.data.getSequence(1);
-            statusString = new String[strings.length];
-            for (int i = 0; i < strings.length; i++) {
-                statusString[i] = strings[i].data.getUTF8String();
+        if (statusInfo.data.available() > 0) {
+            byte tag = (byte)statusInfo.data.peekByte();
+            if (tag == DerValue.tag_SequenceOf) {
+                DerValue[] strings = statusInfo.data.getSequence(1);
+                statusString = new String[strings.length];
+                for (int i = 0; i < strings.length; i++) {
+                    statusString[i] = strings[i].getUTF8String();
+                    if (debug != null) {
+                        debug.println("timestamp response: statusString=" +
+                                      statusString[i]);
+                    }
+                }
             }
         }
         // Parse failInfo, if present
-        if (status.data.available() > 0) {
-            byte[] failInfo = status.data.getBitString();
-            int failureInfo = (new Byte(failInfo[0])).intValue();
-            if (failureInfo < 0 || failureInfo > 25 || failInfo.length != 1) {
-                throw new IOException("Bad encoding for timestamp response: " +
-                    "unrecognized value for the failInfo element");
-            }
-            this.failureInfo = failureInfo;
+        if (statusInfo.data.available() > 0) {
+            this.failureInfo
+                = statusInfo.data.getUnalignedBitString().toBooleanArray();
         }
 
         // Parse timeStampToken, if present
@@ -353,6 +357,7 @@
             DerValue timestampToken = derValue.data.getDerValue();
             encodedTsToken = timestampToken.toByteArray();
             tsToken = new PKCS7(encodedTsToken);
+            tstInfo = new TimestampToken(tsToken.getContentInfo().getData());
         }
 
         // Check the format of the timestamp response
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/sun/security/tools/CertAndKeyGen.java	Wed Jul 05 17:54:24 2017 +0200
@@ -0,0 +1,313 @@
+/*
+ * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved.
+ * 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.security.tools;
+
+import java.io.IOException;
+import java.security.cert.X509Certificate;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateEncodingException;
+import java.security.*;
+import java.util.Date;
+
+import sun.security.pkcs10.PKCS10;
+import sun.security.x509.AlgorithmId;
+import sun.security.x509.CertificateAlgorithmId;
+import sun.security.x509.CertificateIssuerName;
+import sun.security.x509.CertificateSerialNumber;
+import sun.security.x509.CertificateSubjectName;
+import sun.security.x509.CertificateValidity;
+import sun.security.x509.CertificateVersion;
+import sun.security.x509.CertificateX509Key;
+import sun.security.x509.X500Name;
+import sun.security.x509.X509CertImpl;
+import sun.security.x509.X509CertInfo;
+import sun.security.x509.X509Key;
+
+
+/**
+ * Generate a pair of keys, and provide access to them.  This class is
+ * provided primarily for ease of use.
+ *
+ * <P>This provides some simple certificate management functionality.
+ * Specifically, it allows you to create self-signed X.509 certificates
+ * as well as PKCS 10 based certificate signing requests.
+ *
+ * <P>Keys for some public key signature algorithms have algorithm
+ * parameters, such as DSS/DSA.  Some sites' Certificate Authorities
+ * adopt fixed algorithm parameters, which speeds up some operations
+ * including key generation and signing.  <em>At this time, this interface
+ * does not provide a way to provide such algorithm parameters, e.g.
+ * by providing the CA certificate which includes those parameters.</em>
+ *
+ * <P>Also, note that at this time only signature-capable keys may be
+ * acquired through this interface.  Diffie-Hellman keys, used for secure
+ * key exchange, may be supported later.
+ *
+ * @author David Brownell
+ * @author Hemma Prafullchandra
+ * @see PKCS10
+ * @see X509CertImpl
+ */
+public final class CertAndKeyGen {
+    /**
+     * Creates a CertAndKeyGen object for a particular key type
+     * and signature algorithm.
+     *
+     * @param keyType type of key, e.g. "RSA", "DSA"
+     * @param sigAlg name of the signature algorithm, e.g. "MD5WithRSA",
+     *          "MD2WithRSA", "SHAwithDSA".
+     * @exception NoSuchAlgorithmException on unrecognized algorithms.
+     */
+    public CertAndKeyGen (String keyType, String sigAlg)
+    throws NoSuchAlgorithmException
+    {
+        keyGen = KeyPairGenerator.getInstance(keyType);
+        this.sigAlg = sigAlg;
+    }
+
+    /**
+     * Creates a CertAndKeyGen object for a particular key type,
+     * signature algorithm, and provider.
+     *
+     * @param keyType type of key, e.g. "RSA", "DSA"
+     * @param sigAlg name of the signature algorithm, e.g. "MD5WithRSA",
+     *          "MD2WithRSA", "SHAwithDSA".
+     * @param providerName name of the provider
+     * @exception NoSuchAlgorithmException on unrecognized algorithms.
+     * @exception NoSuchProviderException on unrecognized providers.
+     */
+    public CertAndKeyGen (String keyType, String sigAlg, String providerName)
+    throws NoSuchAlgorithmException, NoSuchProviderException
+    {
+        if (providerName == null) {
+            keyGen = KeyPairGenerator.getInstance(keyType);
+        } else {
+            try {
+                keyGen = KeyPairGenerator.getInstance(keyType, providerName);
+            } catch (Exception e) {
+                // try first available provider instead
+                keyGen = KeyPairGenerator.getInstance(keyType);
+            }
+        }
+        this.sigAlg = sigAlg;
+    }
+
+    /**
+     * Sets the source of random numbers used when generating keys.
+     * If you do not provide one, a system default facility is used.
+     * You may wish to provide your own source of random numbers
+     * to get a reproducible sequence of keys and signatures, or
+     * because you may be able to take advantage of strong sources
+     * of randomness/entropy in your environment.
+     */
+    public void         setRandom (SecureRandom generator)
+    {
+        prng = generator;
+    }
+
+    // want "public void generate (X509Certificate)" ... inherit DSA/D-H param
+
+    /**
+     * Generates a random public/private key pair, with a given key
+     * size.  Different algorithms provide different degrees of security
+     * for the same key size, because of the "work factor" involved in
+     * brute force attacks.  As computers become faster, it becomes
+     * easier to perform such attacks.  Small keys are to be avoided.
+     *
+     * <P>Note that not all values of "keyBits" are valid for all
+     * algorithms, and not all public key algorithms are currently
+     * supported for use in X.509 certificates.  If the algorithm
+     * you specified does not produce X.509 compatible keys, an
+     * invalid key exception is thrown.
+     *
+     * @param keyBits the number of bits in the keys.
+     * @exception InvalidKeyException if the environment does not
+     *  provide X.509 public keys for this signature algorithm.
+     */
+    public void generate (int keyBits)
+    throws InvalidKeyException
+    {
+        KeyPair pair;
+
+        try {
+            if (prng == null) {
+                prng = new SecureRandom();
+            }
+            keyGen.initialize(keyBits, prng);
+            pair = keyGen.generateKeyPair();
+
+        } catch (Exception e) {
+            throw new IllegalArgumentException(e.getMessage());
+        }
+
+        publicKey = pair.getPublic();
+        privateKey = pair.getPrivate();
+    }
+
+
+    /**
+     * Returns the public key of the generated key pair if it is of type
+     * <code>X509Key</code>, or null if the public key is of a different type.
+     *
+     * XXX Note: This behaviour is needed for backwards compatibility.
+     * What this method really should return is the public key of the
+     * generated key pair, regardless of whether or not it is an instance of
+     * <code>X509Key</code>. Accordingly, the return type of this method
+     * should be <code>PublicKey</code>.
+     */
+    public X509Key getPublicKey()
+    {
+        if (!(publicKey instanceof X509Key)) {
+            return null;
+        }
+        return (X509Key)publicKey;
+    }
+
+
+    /**
+     * Returns the private key of the generated key pair.
+     *
+     * <P><STRONG><em>Be extremely careful when handling private keys.
+     * When private keys are not kept secret, they lose their ability
+     * to securely authenticate specific entities ... that is a huge
+     * security risk!</em></STRONG>
+     */
+    public PrivateKey getPrivateKey ()
+    {
+        return privateKey;
+    }
+
+
+    /**
+     * Returns a self-signed X.509v3 certificate for the public key.
+     * The certificate is immediately valid. No extensions.
+     *
+     * <P>Such certificates normally are used to identify a "Certificate
+     * Authority" (CA).  Accordingly, they will not always be accepted by
+     * other parties.  However, such certificates are also useful when
+     * you are bootstrapping your security infrastructure, or deploying
+     * system prototypes.
+     *
+     * @param myname X.500 name of the subject (who is also the issuer)
+     * @param firstDate the issue time of the certificate
+     * @param validity how long the certificate should be valid, in seconds
+     * @exception CertificateException on certificate handling errors.
+     * @exception InvalidKeyException on key handling errors.
+     * @exception SignatureException on signature handling errors.
+     * @exception NoSuchAlgorithmException on unrecognized algorithms.
+     * @exception NoSuchProviderException on unrecognized providers.
+     */
+    public X509Certificate getSelfCertificate (
+            X500Name myname, Date firstDate, long validity)
+    throws CertificateException, InvalidKeyException, SignatureException,
+        NoSuchAlgorithmException, NoSuchProviderException
+    {
+        X509CertImpl    cert;
+        Date            lastDate;
+
+        try {
+            lastDate = new Date ();
+            lastDate.setTime (firstDate.getTime () + validity * 1000);
+
+            CertificateValidity interval =
+                                   new CertificateValidity(firstDate,lastDate);
+
+            X509CertInfo info = new X509CertInfo();
+            // Add all mandatory attributes
+            info.set(X509CertInfo.VERSION,
+                     new CertificateVersion(CertificateVersion.V3));
+            info.set(X509CertInfo.SERIAL_NUMBER, new CertificateSerialNumber(
+                    new java.util.Random().nextInt() & 0x7fffffff));
+            AlgorithmId algID = AlgorithmId.get(sigAlg);
+            info.set(X509CertInfo.ALGORITHM_ID,
+                     new CertificateAlgorithmId(algID));
+            info.set(X509CertInfo.SUBJECT, new CertificateSubjectName(myname));
+            info.set(X509CertInfo.KEY, new CertificateX509Key(publicKey));
+            info.set(X509CertInfo.VALIDITY, interval);
+            info.set(X509CertInfo.ISSUER, new CertificateIssuerName(myname));
+
+            cert = new X509CertImpl(info);
+            cert.sign(privateKey, this.sigAlg);
+
+            return (X509Certificate)cert;
+
+        } catch (IOException e) {
+             throw new CertificateEncodingException("getSelfCert: " +
+                                                    e.getMessage());
+        }
+    }
+
+    // Keep the old method
+    public X509Certificate getSelfCertificate (X500Name myname, long validity)
+    throws CertificateException, InvalidKeyException, SignatureException,
+        NoSuchAlgorithmException, NoSuchProviderException
+    {
+        return getSelfCertificate(myname, new Date(), validity);
+    }
+
+    /**
+     * Returns a PKCS #10 certificate request.  The caller uses either
+     * <code>PKCS10.print</code> or <code>PKCS10.toByteArray</code>
+     * operations on the result, to get the request in an appropriate
+     * transmission format.
+     *
+     * <P>PKCS #10 certificate requests are sent, along with some proof
+     * of identity, to Certificate Authorities (CAs) which then issue
+     * X.509 public key certificates.
+     *
+     * @param myname X.500 name of the subject
+     * @exception InvalidKeyException on key handling errors.
+     * @exception SignatureException on signature handling errors.
+     */
+    public PKCS10 getCertRequest (X500Name myname)
+    throws InvalidKeyException, SignatureException
+    {
+        PKCS10  req = new PKCS10 (publicKey);
+
+        try {
+            Signature signature = Signature.getInstance(sigAlg);
+            signature.initSign (privateKey);
+            req.encodeAndSign(myname, signature);
+
+        } catch (CertificateException e) {
+            throw new SignatureException (sigAlg + " CertificateException");
+
+        } catch (IOException e) {
+            throw new SignatureException (sigAlg + " IOException");
+
+        } catch (NoSuchAlgorithmException e) {
+            // "can't happen"
+            throw new SignatureException (sigAlg + " unavailable?");
+        }
+        return req;
+    }
+
+    private SecureRandom        prng;
+    private String              sigAlg;
+    private KeyPairGenerator    keyGen;
+    private PublicKey           publicKey;
+    private PrivateKey          privateKey;
+}
--- a/jdk/src/share/classes/sun/security/tools/JarSigner.java	Wed Jul 05 17:53:51 2017 +0200
+++ b/jdk/src/share/classes/sun/security/tools/JarSigner.java	Wed Jul 05 17:54:24 2017 +0200
@@ -1277,11 +1277,10 @@
                     System.out.println(rb.getString("TSA.location.") + tsaUrl);
                 }
                 if (tsaCert != null) {
-                    String certUrl =
-                        TimestampedSigner.getTimestampingUrl(tsaCert);
-                    if (certUrl != null) {
+                    URI tsaURI = TimestampedSigner.getTimestampingURI(tsaCert);
+                    if (tsaURI != null) {
                         System.out.println(rb.getString("TSA.location.") +
-                            certUrl);
+                            tsaURI);
                     }
                     System.out.println(rb.getString("TSA.certificate.") +
                         printCert("", tsaCert, false, 0, false));
--- a/jdk/src/share/classes/sun/security/tools/KeyTool.java	Wed Jul 05 17:53:51 2017 +0200
+++ b/jdk/src/share/classes/sun/security/tools/KeyTool.java	Wed Jul 05 17:54:24 2017 +0200
@@ -38,10 +38,12 @@
 import java.security.Timestamp;
 import java.security.UnrecoverableEntryException;
 import java.security.UnrecoverableKeyException;
+import java.security.NoSuchAlgorithmException;
 import java.security.Principal;
 import java.security.Provider;
 import java.security.cert.Certificate;
 import java.security.cert.CertificateFactory;
+import java.security.cert.CertStoreException;
 import java.security.cert.CRL;
 import java.security.cert.X509Certificate;
 import java.security.cert.CertificateException;
@@ -63,23 +65,16 @@
 import javax.security.auth.x500.X500Principal;
 import sun.misc.BASE64Encoder;
 import sun.security.util.ObjectIdentifier;
-import sun.security.pkcs.PKCS10;
+import sun.security.pkcs10.PKCS10;
+import sun.security.pkcs10.PKCS10Attribute;
 import sun.security.provider.X509Factory;
+import sun.security.provider.certpath.CertStoreHelper;
 import sun.security.util.Password;
-import sun.security.util.PathList;
 import javax.crypto.KeyGenerator;
 import javax.crypto.SecretKey;
 
-import javax.net.ssl.HostnameVerifier;
-import javax.net.ssl.HttpsURLConnection;
-import javax.net.ssl.SSLContext;
-import javax.net.ssl.SSLSession;
-import javax.net.ssl.TrustManager;
-import javax.net.ssl.X509TrustManager;
 import sun.misc.BASE64Decoder;
-import sun.security.pkcs.PKCS10Attribute;
 import sun.security.pkcs.PKCS9Attribute;
-import sun.security.provider.certpath.ldap.LDAPCertStoreHelper;
 import sun.security.util.DerValue;
 import sun.security.x509.*;
 
@@ -917,18 +912,13 @@
 
         // Perform the specified command
         if (command == CERTREQ) {
-            PrintStream ps = null;
             if (filename != null) {
-                ps = new PrintStream(new FileOutputStream
-                                                 (filename));
-                out = ps;
-            }
-            try {
+                try (PrintStream ps = new PrintStream(new FileOutputStream
+                                                      (filename))) {
+                    doCertReq(alias, sigAlgName, ps);
+                }
+            } else {
                 doCertReq(alias, sigAlgName, out);
-            } finally {
-                if (ps != null) {
-                    ps.close();
-                }
             }
             if (verbose && filename != null) {
                 MessageFormat form = new MessageFormat(rb.getString
@@ -941,18 +931,13 @@
             doDeleteEntry(alias);
             kssave = true;
         } else if (command == EXPORTCERT) {
-            PrintStream ps = null;
             if (filename != null) {
-                ps = new PrintStream(new FileOutputStream
-                                                 (filename));
-                out = ps;
-            }
-            try {
+                try (PrintStream ps = new PrintStream(new FileOutputStream
+                                                   (filename))) {
+                    doExportCert(alias, ps);
+                }
+            } else {
                 doExportCert(alias, out);
-            } finally {
-                if (ps != null) {
-                    ps.close();
-                }
             }
             if (filename != null) {
                 MessageFormat form = new MessageFormat(rb.getString
@@ -973,16 +958,12 @@
             doGenSecretKey(alias, keyAlgName, keysize);
             kssave = true;
         } else if (command == IDENTITYDB) {
-            InputStream inStream = System.in;
             if (filename != null) {
-                inStream = new FileInputStream(filename);
-            }
-            try {
-                doImportIdentityDatabase(inStream);
-            } finally {
-                if (inStream != System.in) {
-                    inStream.close();
+                try (InputStream inStream = new FileInputStream(filename)) {
+                    doImportIdentityDatabase(inStream);
                 }
+            } else {
+                doImportIdentityDatabase(System.in);
             }
         } else if (command == IMPORTCERT) {
             InputStream inStream = System.in;
@@ -1101,29 +1082,21 @@
             if (alias == null) {
                 alias = keyAlias;
             }
-            PrintStream ps = null;
             if (filename != null) {
-                ps = new PrintStream(new FileOutputStream(filename));
-                out = ps;
-            }
-            try {
+                try (PrintStream ps =
+                         new PrintStream(new FileOutputStream(filename))) {
+                    doGenCRL(ps);
+                }
+            } else {
                 doGenCRL(out);
-            } finally {
-                if (ps != null) {
-                    ps.close();
-                }
             }
         } else if (command == PRINTCERTREQ) {
-            InputStream inStream = System.in;
             if (filename != null) {
-                inStream = new FileInputStream(filename);
-            }
-            try {
-                doPrintCertReq(inStream, out);
-            } finally {
-                if (inStream != System.in) {
-                    inStream.close();
+                try (InputStream inStream = new FileInputStream(filename)) {
+                    doPrintCertReq(inStream, out);
                 }
+            } else {
+                doPrintCertReq(System.in, out);
             }
         } else if (command == PRINTCRL) {
             doPrintCRL(filename, out);
@@ -2070,12 +2043,13 @@
                 }
             }
         } else {    // must be LDAP, and uri is not null
+            // Lazily load LDAPCertStoreHelper if present
+            CertStoreHelper helper = CertStoreHelper.getInstance("LDAP");
             String path = uri.getPath();
             if (path.charAt(0) == '/') path = path.substring(1);
-            LDAPCertStoreHelper h = new LDAPCertStoreHelper();
-            CertStore s = h.getCertStore(uri);
+            CertStore s = helper.getCertStore(uri);
             X509CRLSelector sel =
-                    h.wrap(new X509CRLSelector(), null, path);
+                    helper.wrap(new X509CRLSelector(), null, path);
             return s.getCRLs(sel);
         }
     }
@@ -2259,18 +2233,12 @@
             int pos = 0;
             while (entries.hasMoreElements()) {
                 JarEntry je = entries.nextElement();
-                InputStream is = null;
-                try {
-                    is = jf.getInputStream(je);
+                try (InputStream is = jf.getInputStream(je)) {
                     while (is.read(buffer) != -1) {
                         // we just read. this will throw a SecurityException
                         // if a signature/digest check fails. This also
                         // populate the signers
                     }
-                } finally {
-                    if (is != null) {
-                        is.close();
-                    }
                 }
                 CodeSigner[] signers = je.getCodeSigners();
                 if (signers != null) {
@@ -2316,85 +2284,52 @@
                 out.println(rb.getString("Not.a.signed.jar.file"));
             }
         } else if (sslserver != null) {
-            SSLContext sc = SSLContext.getInstance("SSL");
-            final boolean[] certPrinted = new boolean[1];
-            sc.init(null, new TrustManager[] {
-                new X509TrustManager() {
-
-                    public java.security.cert.X509Certificate[] getAcceptedIssuers() {
-                        return null;
-                    }
-
-                    public void checkClientTrusted(
-                        java.security.cert.X509Certificate[] certs, String authType) {
+            // Lazily load SSLCertStoreHelper if present
+            CertStoreHelper helper = CertStoreHelper.getInstance("SSLServer");
+            CertStore cs = helper.getCertStore(new URI("https://" + sslserver));
+            Collection<? extends Certificate> chain;
+            try {
+                chain = cs.getCertificates(null);
+                if (chain.isEmpty()) {
+                    // If the certs are not retrieved, we consider it an error
+                    // even if the URL connection is successful.
+                    throw new Exception(rb.getString(
+                                        "No.certificate.from.the.SSL.server"));
+                }
+            } catch (CertStoreException cse) {
+                if (cse.getCause() instanceof IOException) {
+                    throw new Exception(rb.getString(
+                                        "No.certificate.from.the.SSL.server"),
+                                        cse.getCause());
+                } else {
+                    throw cse;
+                }
+            }
+
+            int i = 0;
+            for (Certificate cert : chain) {
+                try {
+                    if (rfc) {
+                        dumpCert(cert, out);
+                    } else {
+                        out.println("Certificate #" + i++);
+                        out.println("====================================");
+                        printX509Cert((X509Certificate)cert, out);
+                        out.println();
                     }
-
-                    public void checkServerTrusted(
-                            java.security.cert.X509Certificate[] certs, String authType) {
-                        for (int i=0; i<certs.length; i++) {
-                            X509Certificate cert = certs[i];
-                            try {
-                                if (rfc) {
-                                    dumpCert(cert, out);
-                                } else {
-                                    out.println("Certificate #" + i);
-                                    out.println("====================================");
-                                    printX509Cert(cert, out);
-                                    out.println();
-                                }
-                            } catch (Exception e) {
-                                if (debug) {
-                                    e.printStackTrace();
-                                }
-                            }
-                        }
-
-                        // Set to true where there's something to print
-                        if (certs.length > 0) {
-                            certPrinted[0] = true;
-                        }
+                } catch (Exception e) {
+                    if (debug) {
+                        e.printStackTrace();
                     }
                 }
-            }, null);
-            HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
-            HttpsURLConnection.setDefaultHostnameVerifier(
-                    new HostnameVerifier() {
-                        public boolean verify(String hostname, SSLSession session) {
-                            return true;
-                        }
-                    });
-            // HTTPS instead of raw SSL, so that -Dhttps.proxyHost and
-            // -Dhttps.proxyPort can be used. Since we only go through
-            // the handshake process, an HTTPS server is not needed.
-            // This program should be able to deal with any SSL-based
-            // network service.
-            Exception ex = null;
-            try {
-                new URL("https://" + sslserver).openConnection().connect();
-            } catch (Exception e) {
-                ex = e;
-            }
-            // If the certs are not printed out, we consider it an error even
-            // if the URL connection is successful.
-            if (!certPrinted[0]) {
-                Exception e = new Exception(
-                        rb.getString("No.certificate.from.the.SSL.server"));
-                if (ex != null) {
-                    e.initCause(ex);
-                }
-                throw e;
             }
         } else {
-            InputStream inStream = System.in;
             if (filename != null) {
-                inStream = new FileInputStream(filename);
-            }
-            try {
-                printCertFromStream(inStream, out);
-            } finally {
-                if (inStream != System.in) {
-                    inStream.close();
+                try (FileInputStream inStream = new FileInputStream(filename)) {
+                    printCertFromStream(inStream, out);
                 }
+            } else {
+                printCertFromStream(System.in, out);
             }
         }
     }
@@ -2590,9 +2525,7 @@
         X509Certificate cert = null;
         try {
             cert = (X509Certificate)cf.generateCertificate(in);
-        } catch (ClassCastException cce) {
-            throw new Exception(rb.getString("Input.not.an.X.509.certificate"));
-        } catch (CertificateException ce) {
+        } catch (ClassCastException | CertificateException ce) {
             throw new Exception(rb.getString("Input.not.an.X.509.certificate"));
         }
 
@@ -3441,16 +3374,10 @@
         if (!file.exists()) {
             return null;
         }
-        FileInputStream fis = null;
         KeyStore caks = null;
-        try {
-            fis = new FileInputStream(file);
+        try (FileInputStream fis = new FileInputStream(file)) {
             caks = KeyStore.getInstance(JKS);
             caks.load(fis, null);
-        } finally {
-            if (fis != null) {
-                fis.close();
-            }
         }
         return caks;
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/sun/security/tools/PathList.java	Wed Jul 05 17:54:24 2017 +0200
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved.
+ * 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.security.tools;
+
+import java.io.File;
+import java.io.IOException;
+import java.lang.String;
+import java.util.StringTokenizer;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.net.MalformedURLException;
+
+/**
+ * A utility class for handle path list
+ *
+ */
+public class PathList {
+    /**
+     * Utility method for appending path from pathFrom to pathTo.
+     *
+     * @param pathTo the target path
+     * @param pathSource the path to be appended to pathTo
+     * @return the resulting path
+     */
+    public static String appendPath(String pathTo, String pathFrom) {
+        if (pathTo == null || pathTo.length() == 0) {
+            return pathFrom;
+        } else if (pathFrom == null || pathFrom.length() == 0) {
+            return pathTo;
+        } else {
+            return pathTo  + File.pathSeparator + pathFrom;
+        }
+    }
+
+    /**
+     * Utility method for converting a search path string to an array
+     * of directory and JAR file URLs.
+     *
+     * @param path the search path string
+     * @return the resulting array of directory and JAR file URLs
+     */
+    public static URL[] pathToURLs(String path) {
+        StringTokenizer st = new StringTokenizer(path, File.pathSeparator);
+        URL[] urls = new URL[st.countTokens()];
+        int count = 0;
+        while (st.hasMoreTokens()) {
+            URL url = fileToURL(new File(st.nextToken()));
+            if (url != null) {
+                urls[count++] = url;
+            }
+        }
+        if (urls.length != count) {
+            URL[] tmp = new URL[count];
+            System.arraycopy(urls, 0, tmp, 0, count);
+            urls = tmp;
+        }
+        return urls;
+    }
+
+    /**
+     * Returns the directory or JAR file URL corresponding to the specified
+     * local file name.
+     *
+     * @param file the File object
+     * @return the resulting directory or JAR file URL, or null if unknown
+     */
+    private static URL fileToURL(File file) {
+        String name;
+        try {
+            name = file.getCanonicalPath();
+        } catch (IOException e) {
+            name = file.getAbsolutePath();
+        }
+        name = name.replace(File.separatorChar, '/');
+        if (!name.startsWith("/")) {
+            name = "/" + name;
+        }
+        // If the file does not exist, then assume that it's a directory
+        if (!file.isFile()) {
+            name = name + "/";
+        }
+        try {
+            return new URL("file", "", name);
+        } catch (MalformedURLException e) {
+            throw new IllegalArgumentException("file");
+        }
+    }
+}
--- a/jdk/src/share/classes/sun/security/tools/TimestampedSigner.java	Wed Jul 05 17:53:51 2017 +0200
+++ b/jdk/src/share/classes/sun/security/tools/TimestampedSigner.java	Wed Jul 05 17:54:24 2017 +0200
@@ -25,22 +25,14 @@
 
 package sun.security.tools;
 
-import java.io.ByteArrayOutputStream;
 import java.io.IOException;
-import java.math.BigInteger;
 import java.net.URI;
-import java.security.MessageDigest;
 import java.security.NoSuchAlgorithmException;
-import java.security.Principal;
-import java.security.SecureRandom;
 import java.security.cert.CertificateException;
 import java.security.cert.X509Certificate;
-import java.util.List;
 
 import com.sun.jarsigner.*;
-import java.util.Arrays;
-import sun.security.pkcs.*;
-import sun.security.timestamp.*;
+import sun.security.pkcs.PKCS7;
 import sun.security.util.*;
 import sun.security.x509.*;
 
@@ -57,36 +49,12 @@
 public final class TimestampedSigner extends ContentSigner {
 
     /*
-     * Random number generator for creating nonce values
-     */
-    private static final SecureRandom RANDOM;
-    static {
-        SecureRandom tmp = null;
-        try {
-            tmp = SecureRandom.getInstance("SHA1PRNG");
-        } catch (NoSuchAlgorithmException e) {
-            // should not happen
-        }
-        RANDOM = tmp;
-    }
-
-    /*
      * Object identifier for the subject information access X.509 certificate
      * extension.
      */
     private static final String SUBJECT_INFO_ACCESS_OID = "1.3.6.1.5.5.7.1.11";
 
     /*
-     * Object identifier for the timestamping key purpose.
-     */
-    private static final String KP_TIMESTAMPING_OID = "1.3.6.1.5.5.7.3.8";
-
-    /*
-     * Object identifier for extendedKeyUsage extension
-     */
-    private static final String EXTENDED_KEY_USAGE_OID = "2.5.29.37";
-
-    /*
      * Object identifier for the timestamping access descriptors.
      */
     private static final ObjectIdentifier AD_TIMESTAMPING_Id;
@@ -100,26 +68,6 @@
         AD_TIMESTAMPING_Id = tmp;
     }
 
-    /*
-     * Location of the TSA.
-     */
-    private String tsaUrl = null;
-
-    /*
-     * TSA's X.509 certificate.
-     */
-    private X509Certificate tsaCertificate = null;
-
-    /*
-     * Generates an SHA-1 hash value for the data to be timestamped.
-     */
-    private MessageDigest messageDigest = null;
-
-    /*
-     * Parameters for the timestamping protocol.
-     */
-    private boolean tsRequestCertificate = true;
-
     /**
      * Instantiates a content signer that supports timestamped signatures.
      */
@@ -134,7 +82,7 @@
      * and optionally the content that was signed, are packaged into a PKCS #7
      * signed data message.
      *
-     * @param parameters The non-null input parameters.
+     * @param params The non-null input parameters.
      * @param omitContent true if the content should be omitted from the
      *        signed data message. Otherwise the content is included.
      * @param applyTimestamp true if the signature should be timestamped.
@@ -151,98 +99,41 @@
      * @throws NullPointerException The exception is thrown if parameters is
      *         null.
      */
-    public byte[] generateSignedData(ContentSignerParameters parameters,
+    public byte[] generateSignedData(ContentSignerParameters params,
         boolean omitContent, boolean applyTimestamp)
             throws NoSuchAlgorithmException, CertificateException, IOException {
 
-        if (parameters == null) {
+        if (params == null) {
             throw new NullPointerException();
         }
 
-        // Parse the signature algorithm to extract the digest and key
-        // algorithms. The expected format is:
+        // Parse the signature algorithm to extract the digest
+        // algorithm. The expected format is:
         //     "<digest>with<encryption>"
         // or  "<digest>with<encryption>and<mgf>"
-        String signatureAlgorithm = parameters.getSignatureAlgorithm();
-        String keyAlgorithm =
-                AlgorithmId.getEncAlgFromSigAlg(signatureAlgorithm);
-        String digestAlgorithm =
-                AlgorithmId.getDigAlgFromSigAlg(signatureAlgorithm);
-        AlgorithmId digestAlgorithmId = AlgorithmId.get(digestAlgorithm);
+        String signatureAlgorithm = params.getSignatureAlgorithm();
 
-        // Examine signer's certificate
-        X509Certificate[] signerCertificateChain =
-            parameters.getSignerCertificateChain();
-        Principal issuerName = signerCertificateChain[0].getIssuerDN();
-        if (!(issuerName instanceof X500Name)) {
-            // must extract the original encoded form of DN for subsequent
-            // name comparison checks (converting to a String and back to
-            // an encoded DN could cause the types of String attribute
-            // values to be changed)
-            X509CertInfo tbsCert = new
-                X509CertInfo(signerCertificateChain[0].getTBSCertificate());
-            issuerName = (Principal)
-                tbsCert.get(CertificateIssuerName.NAME + "." +
-                CertificateIssuerName.DN_NAME);
-        }
-        BigInteger serialNumber = signerCertificateChain[0].getSerialNumber();
+        X509Certificate[] signerChain = params.getSignerCertificateChain();
+        byte[] signature = params.getSignature();
 
         // Include or exclude content
-        byte[] content = parameters.getContent();
-        ContentInfo contentInfo;
-        if (omitContent) {
-            contentInfo = new ContentInfo(ContentInfo.DATA_OID, null);
-        } else {
-            contentInfo = new ContentInfo(content);
-        }
+        byte[] content = (omitContent == true) ? null : params.getContent();
 
-        // Generate the timestamp token
-        byte[] signature = parameters.getSignature();
-        SignerInfo signerInfo = null;
+        URI tsaURI = null;
         if (applyTimestamp) {
-
-            tsaCertificate = parameters.getTimestampingAuthorityCertificate();
-            URI tsaUri = parameters.getTimestampingAuthority();
-            if (tsaUri != null) {
-                tsaUrl = tsaUri.toString();
-            } else {
+            tsaURI = params.getTimestampingAuthority();
+            if (tsaURI == null) {
                 // Examine TSA cert
-                String certUrl = getTimestampingUrl(tsaCertificate);
-                if (certUrl == null) {
+                tsaURI = getTimestampingURI(
+                    params.getTimestampingAuthorityCertificate());
+                if (tsaURI == null) {
                     throw new CertificateException(
                         "Subject Information Access extension not found");
                 }
-                tsaUrl = certUrl;
             }
-
-            // Timestamp the signature
-            byte[] tsToken = generateTimestampToken(signature);
-
-            // Insert the timestamp token into the PKCS #7 signer info element
-            // (as an unsigned attribute)
-            PKCS9Attributes unsignedAttrs =
-                new PKCS9Attributes(new PKCS9Attribute[]{
-                    new PKCS9Attribute(
-                        PKCS9Attribute.SIGNATURE_TIMESTAMP_TOKEN_STR,
-                        tsToken)});
-            signerInfo = new SignerInfo((X500Name)issuerName, serialNumber,
-                digestAlgorithmId, null, AlgorithmId.get(keyAlgorithm),
-                    signature, unsignedAttrs);
-        } else {
-            signerInfo = new SignerInfo((X500Name)issuerName, serialNumber,
-                digestAlgorithmId, AlgorithmId.get(keyAlgorithm), signature);
         }
-
-        SignerInfo[] signerInfos = {signerInfo};
-        AlgorithmId[] algorithms = {digestAlgorithmId};
-
-        // Create the PKCS #7 signed data message
-        PKCS7 p7 = new PKCS7(algorithms, contentInfo, signerCertificateChain,
-                null, signerInfos);
-        ByteArrayOutputStream p7out = new ByteArrayOutputStream();
-        p7.encodeSignedData(p7out);
-
-        return p7out.toByteArray();
+        return PKCS7.generateSignedData(signature, signerChain, content,
+                                        params.getSignatureAlgorithm(), tsaURI);
     }
 
     /**
@@ -253,9 +144,9 @@
      * <tt>accessLocation</tt> field should contain an HTTP or HTTPS URL.
      *
      * @param tsaCertificate An X.509 certificate for the TSA.
-     * @return An HTTP or HTTPS URL or null if none was found.
+     * @return An HTTP or HTTPS URI or null if none was found.
      */
-    public static String getTimestampingUrl(X509Certificate tsaCertificate) {
+    public static URI getTimestampingURI(X509Certificate tsaCertificate) {
 
         if (tsaCertificate == null) {
             return null;
@@ -282,7 +173,7 @@
                         uri = (URIName) location.getName();
                         if (uri.getScheme().equalsIgnoreCase("http") ||
                                 uri.getScheme().equalsIgnoreCase("https")) {
-                            return uri.getName();
+                            return uri.getURI();
                         }
                     }
                 }
@@ -292,97 +183,4 @@
         }
         return null;
     }
-
-    /*
-     * Returns a timestamp token from a TSA for the given content.
-     * Performs a basic check on the token to confirm that it has been signed
-     * by a certificate that is permitted to sign timestamps.
-     *
-     * @param  toBeTimestamped The data to be timestamped.
-     * @throws IOException The exception is throw if an error occurs while
-     *                     communicating with the TSA.
-     * @throws CertificateException The exception is throw if the TSA's
-     *                     certificate is not permitted for timestamping.
-     */
-    private byte[] generateTimestampToken(byte[] toBeTimestamped)
-            throws CertificateException, IOException {
-
-        // Generate hash value for the data to be timestamped
-        // SHA-1 is always used.
-        if (messageDigest == null) {
-            try {
-                messageDigest = MessageDigest.getInstance("SHA-1");
-            } catch (NoSuchAlgorithmException e) {
-                // ignore
-            }
-        }
-        byte[] digest = messageDigest.digest(toBeTimestamped);
-
-        // Generate a timestamp
-        TSRequest tsQuery = new TSRequest(digest, "SHA-1");
-        // Generate a nonce
-        BigInteger nonce = null;
-        if (RANDOM != null) {
-            nonce = new BigInteger(64, RANDOM);
-            tsQuery.setNonce(nonce);
-        }
-        tsQuery.requestCertificate(tsRequestCertificate);
-
-        Timestamper tsa = new HttpTimestamper(tsaUrl); // use supplied TSA
-        TSResponse tsReply = tsa.generateTimestamp(tsQuery);
-        int status = tsReply.getStatusCode();
-        // Handle TSP error
-        if (status != 0 && status != 1) {
-            int failureCode = tsReply.getFailureCode();
-            if (failureCode == -1) {
-                throw new IOException("Error generating timestamp: " +
-                    tsReply.getStatusCodeAsText());
-            } else {
-                throw new IOException("Error generating timestamp: " +
-                    tsReply.getStatusCodeAsText() + " " +
-                    tsReply.getFailureCodeAsText());
-            }
-        }
-        PKCS7 tsToken = tsReply.getToken();
-
-        TimestampToken tst = new TimestampToken(tsToken.getContentInfo().getData());
-        if (!tst.getHashAlgorithm().equals(
-                new AlgorithmId(new ObjectIdentifier("1.3.14.3.2.26")))) {
-            throw new IOException("Digest algorithm not SHA-1 in timestamp token");
-        }
-        if (!Arrays.equals(tst.getHashedMessage(), digest)) {
-            throw new IOException("Digest octets changed in timestamp token");
-        }
-
-        BigInteger replyNonce = tst.getNonce();
-        if (replyNonce == null && nonce != null) {
-            throw new IOException("Nonce missing in timestamp token");
-        }
-        if (replyNonce != null && !replyNonce.equals(nonce)) {
-            throw new IOException("Nonce changed in timestamp token");
-        }
-
-        // Examine the TSA's certificate (if present)
-        for (SignerInfo si: tsToken.getSignerInfos()) {
-            X509Certificate cert = si.getCertificate(tsToken);
-            if (cert == null) {
-                // Error, we've already set tsRequestCertificate = true
-                throw new CertificateException(
-                "Certificate not included in timestamp token");
-            } else {
-                if (!cert.getCriticalExtensionOIDs().contains(
-                        EXTENDED_KEY_USAGE_OID)) {
-                    throw new CertificateException(
-                    "Certificate is not valid for timestamping");
-                }
-                List<String> keyPurposes = cert.getExtendedKeyUsage();
-                if (keyPurposes == null ||
-                        ! keyPurposes.contains(KP_TIMESTAMPING_OID)) {
-                    throw new CertificateException(
-                    "Certificate is not valid for timestamping");
-                }
-            }
-        }
-        return tsReply.getEncodedToken();
-    }
 }
--- a/jdk/src/share/classes/sun/security/util/BigInt.java	Wed Jul 05 17:53:51 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,198 +0,0 @@
-/*
- * Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.security.util;
-
-import java.math.BigInteger;
-
-
-/**
- * A low-overhead arbitrary-precision <em>unsigned</em> integer.
- * This is intended for use with ASN.1 parsing, and printing of
- * such parsed values.  Convert to "BigInteger" if you need to do
- * arbitrary precision arithmetic, rather than just represent
- * the number as a wrapped array of bytes.
- *
- * <P><em><b>NOTE:</b>  This class may eventually disappear, to
- * be supplanted by big-endian byte arrays which hold both signed
- * and unsigned arbitrary-precision integers.</em>
- *
- * @author David Brownell
- */
-public final class BigInt {
-
-    // Big endian -- MSB first.
-    private byte[]      places;
-
-    /**
-     * Constructs a "Big" integer from a set of (big-endian) bytes.
-     * Leading zeroes should be stripped off.
-     *
-     * @param data a sequence of bytes, most significant bytes/digits
-     *          first.  CONSUMED.
-     */
-    public BigInt(byte[] data) { places = data.clone(); }
-
-    /**
-     * Constructs a "Big" integer from a "BigInteger", which must be
-     * positive (or zero) in value.
-     */
-    public BigInt(BigInteger i) {
-        byte[]  temp = i.toByteArray();
-
-        if ((temp[0] & 0x80) != 0)
-            throw new IllegalArgumentException("negative BigInteger");
-
-        // XXX we assume exactly _one_ sign byte is used...
-
-        if (temp[0] != 0)
-            places = temp;
-        else {
-            places = new byte[temp.length - 1];
-            for (int j = 1; j < temp.length; j++)
-                places[j - 1] = temp[j];
-        }
-    }
-
-    /**
-     * Constructs a "Big" integer from a normal Java integer.
-     *
-     * @param i the java primitive integer
-     */
-    public BigInt(int i) {
-        if (i < (1 << 8)) {
-            places = new byte[1];
-            places[0] = (byte) i;
-        } else if (i < (1 << 16)) {
-            places = new byte[2];
-            places[0] = (byte) (i >> 8);
-            places[1] = (byte) i;
-        } else if (i < (1 << 24)) {
-            places = new byte[3];
-            places[0] = (byte) (i >> 16);
-            places[1] = (byte) (i >> 8);
-            places[2] = (byte) i;
-        } else {
-            places = new byte[4];
-            places[0] = (byte) (i >> 24);
-            places[1] = (byte) (i >> 16);
-            places[2] = (byte) (i >> 8);
-            places[3] = (byte) i;
-        }
-    }
-
-    /**
-     * Converts the "big" integer to a java primitive integer.
-     *
-     * @excpet NumberFormatException if 32 bits is insufficient.
-     */
-    public int toInt() {
-        if (places.length > 4)
-            throw new NumberFormatException("BigInt.toLong, too big");
-        int retval = 0, i = 0;
-        for (; i < places.length; i++)
-            retval = (retval << 8) + ((int)places[i] & 0xff);
-        return retval;
-    }
-
-    /**
-     * Returns a hexadecimal printed representation.  The value is
-     * formatted to fit on lines of at least 75 characters, with
-     * embedded newlines.  Words are separated for readability,
-     * with eight words (32 bytes) per line.
-     */
-    public String toString() { return hexify(); }
-
-    /**
-     * Returns a BigInteger value which supports many arithmetic
-     * operations. Assumes negative values will never occur.
-     */
-    public BigInteger toBigInteger()
-        { return new BigInteger(1, places); }
-
-    /**
-     * Returns the data as a byte array.  The most significant bit
-     * of the array is bit zero (as in <code>java.math.BigInteger</code>).
-     */
-    public byte[] toByteArray() { return places.clone(); }
-
-    private static final String digits = "0123456789abcdef";
-    private String hexify() {
-        if (places.length == 0)
-            return "  0  ";
-
-        StringBuffer buf = new StringBuffer(places.length * 2);
-        buf.append("    ");     // four spaces
-        for (int i = 0; i < places.length; i++) {
-            buf.append(digits.charAt((places[i] >> 4) & 0x0f));
-            buf.append(digits.charAt(places[i] & 0x0f));
-            if (((i + 1) % 32) == 0) {
-                if ((i +  1) != places.length)
-                    buf.append("\n    ");       // line after four words
-            } else if (((i + 1) % 4) == 0)
-                buf.append(' ');                // space between words
-        }
-        return buf.toString();
-    }
-
-    /**
-     * Returns true iff the parameter is a numerically equivalent
-     * BigInt.
-     *
-     * @param other the object being compared with this one.
-     */
-    public boolean equals(Object other) {
-        if (other instanceof BigInt)
-            return equals((BigInt) other);
-        return false;
-    }
-
-    /**
-     * Returns true iff the parameter is numerically equivalent.
-     *
-     * @param other the BigInt being compared with this one.
-     */
-    public boolean equals(BigInt other) {
-        if (this == other)
-            return true;
-
-        byte[] otherPlaces = other.toByteArray();
-        if (places.length != otherPlaces.length)
-            return false;
-        for (int i = 0; i < places.length; i++)
-            if (places[i] != otherPlaces[i])
-                return false;
-        return true;
-    }
-
-    /**
-     * Returns a hashcode for this BigInt.
-     *
-     * @return a hashcode for this BigInt.
-     */
-    public int hashCode() {
-        return hexify().hashCode();
-    }
-}
--- a/jdk/src/share/classes/sun/security/util/Cache.java	Wed Jul 05 17:53:51 2017 +0200
+++ b/jdk/src/share/classes/sun/security/util/Cache.java	Wed Jul 05 17:54:24 2017 +0200
@@ -43,7 +43,7 @@
  *
  *  . optional lifetime, specified in seconds.
  *
- *  . save for concurrent use by multiple threads
+ *  . safe for concurrent use by multiple threads
  *
  *  . values are held by either standard references or via SoftReferences.
  *    SoftReferences have the advantage that they are automatically cleared
@@ -69,7 +69,7 @@
  *
  * @author Andreas Sterbenz
  */
-public abstract class Cache {
+public abstract class Cache<K,V> {
 
     protected Cache() {
         // empty
@@ -88,12 +88,12 @@
     /**
      * Add an entry to the cache.
      */
-    public abstract void put(Object key, Object value);
+    public abstract void put(K key, V value);
 
     /**
      * Get a value from the cache.
      */
-    public abstract Object get(Object key);
+    public abstract V get(Object key);
 
     /**
      * Remove an entry from the cache.
@@ -113,14 +113,14 @@
     /**
      * accept a visitor
      */
-    public abstract void accept(CacheVisitor visitor);
+    public abstract void accept(CacheVisitor<K,V> visitor);
 
     /**
      * Return a new memory cache with the specified maximum size, unlimited
      * lifetime for entries, with the values held by SoftReferences.
      */
-    public static Cache newSoftMemoryCache(int size) {
-        return new MemoryCache(true, size);
+    public static <K,V> Cache<K,V> newSoftMemoryCache(int size) {
+        return new MemoryCache<>(true, size);
     }
 
     /**
@@ -128,23 +128,24 @@
      * specified maximum lifetime (in seconds), with the values held
      * by SoftReferences.
      */
-    public static Cache newSoftMemoryCache(int size, int timeout) {
-        return new MemoryCache(true, size, timeout);
+    public static <K,V> Cache<K,V> newSoftMemoryCache(int size, int timeout) {
+        return new MemoryCache<>(true, size, timeout);
     }
 
     /**
      * Return a new memory cache with the specified maximum size, unlimited
      * lifetime for entries, with the values held by standard references.
      */
-    public static Cache newHardMemoryCache(int size) {
-        return new MemoryCache(false, size);
+    public static <K,V> Cache<K,V> newHardMemoryCache(int size) {
+        return new MemoryCache<>(false, size);
     }
 
     /**
      * Return a dummy cache that does nothing.
      */
-    public static Cache newNullCache() {
-        return NullCache.INSTANCE;
+    @SuppressWarnings("unchecked")
+    public static <K,V> Cache<K,V> newNullCache() {
+        return (Cache<K,V>) NullCache.INSTANCE;
     }
 
     /**
@@ -152,8 +153,8 @@
      * specified maximum lifetime (in seconds), with the values held
      * by standard references.
      */
-    public static Cache newHardMemoryCache(int size, int timeout) {
-        return new MemoryCache(false, size, timeout);
+    public static <K,V> Cache<K,V> newHardMemoryCache(int size, int timeout) {
+        return new MemoryCache<>(false, size, timeout);
     }
 
     /**
@@ -193,15 +194,15 @@
         }
     }
 
-    public interface CacheVisitor {
-        public void visit(Map<Object, Object> map);
+    public interface CacheVisitor<K,V> {
+        public void visit(Map<K,V> map);
     }
 
 }
 
-class NullCache extends Cache {
+class NullCache<K,V> extends Cache<K,V> {
 
-    final static Cache INSTANCE = new NullCache();
+    final static Cache<Object,Object> INSTANCE = new NullCache<>();
 
     private NullCache() {
         // empty
@@ -215,11 +216,11 @@
         // empty
     }
 
-    public void put(Object key, Object value) {
+    public void put(K key, V value) {
         // empty
     }
 
-    public Object get(Object key) {
+    public V get(Object key) {
         return null;
     }
 
@@ -235,23 +236,26 @@
         // empty
     }
 
-    public void accept(CacheVisitor visitor) {
+    public void accept(CacheVisitor<K,V> visitor) {
         // empty
     }
 
 }
 
-class MemoryCache extends Cache {
+class MemoryCache<K,V> extends Cache<K,V> {
 
     private final static float LOAD_FACTOR = 0.75f;
 
     // XXXX
     private final static boolean DEBUG = false;
 
-    private final Map<Object, CacheEntry> cacheMap;
+    private final Map<K, CacheEntry<K,V>> cacheMap;
     private int maxSize;
     private long lifetime;
-    private final ReferenceQueue<Object> queue;
+
+    // ReferenceQueue is of type V instead of Cache<K,V>
+    // to allow SoftCacheEntry to extend SoftReference<V>
+    private final ReferenceQueue<V> queue;
 
     public MemoryCache(boolean soft, int maxSize) {
         this(soft, maxSize, 0);
@@ -260,10 +264,13 @@
     public MemoryCache(boolean soft, int maxSize, int lifetime) {
         this.maxSize = maxSize;
         this.lifetime = lifetime * 1000;
-        this.queue = soft ? new ReferenceQueue<Object>() : null;
+        if (soft)
+            this.queue = new ReferenceQueue<>();
+        else
+            this.queue = null;
+
         int buckets = (int)(maxSize / LOAD_FACTOR) + 1;
-        cacheMap = new LinkedHashMap<Object, CacheEntry>(buckets,
-                                                        LOAD_FACTOR, true);
+        cacheMap = new LinkedHashMap<>(buckets, LOAD_FACTOR, true);
     }
 
     /**
@@ -279,16 +286,17 @@
         }
         int startSize = cacheMap.size();
         while (true) {
-            CacheEntry entry = (CacheEntry)queue.poll();
+            @SuppressWarnings("unchecked")
+            CacheEntry<K,V> entry = (CacheEntry<K,V>)queue.poll();
             if (entry == null) {
                 break;
             }
-            Object key = entry.getKey();
+            K key = entry.getKey();
             if (key == null) {
                 // key is null, entry has already been removed
                 continue;
             }
-            CacheEntry currentEntry = cacheMap.remove(key);
+            CacheEntry<K,V> currentEntry = cacheMap.remove(key);
             // check if the entry in the map corresponds to the expired
             // entry. If not, readd the entry
             if ((currentEntry != null) && (entry != currentEntry)) {
@@ -314,9 +322,9 @@
         }
         int cnt = 0;
         long time = System.currentTimeMillis();
-        for (Iterator<CacheEntry> t = cacheMap.values().iterator();
+        for (Iterator<CacheEntry<K,V>> t = cacheMap.values().iterator();
                 t.hasNext(); ) {
-            CacheEntry entry = t.next();
+            CacheEntry<K,V> entry = t.next();
             if (entry.isValid(time) == false) {
                 t.remove();
                 cnt++;
@@ -339,7 +347,7 @@
         if (queue != null) {
             // if this is a SoftReference cache, first invalidate() all
             // entries so that GC does not have to enqueue them
-            for (CacheEntry entry : cacheMap.values()) {
+            for (CacheEntry<K,V> entry : cacheMap.values()) {
                 entry.invalidate();
             }
             while (queue.poll() != null) {
@@ -349,12 +357,12 @@
         cacheMap.clear();
     }
 
-    public synchronized void put(Object key, Object value) {
+    public synchronized void put(K key, V value) {
         emptyQueue();
         long expirationTime = (lifetime == 0) ? 0 :
                                         System.currentTimeMillis() + lifetime;
-        CacheEntry newEntry = newEntry(key, value, expirationTime, queue);
-        CacheEntry oldEntry = cacheMap.put(key, newEntry);
+        CacheEntry<K,V> newEntry = newEntry(key, value, expirationTime, queue);
+        CacheEntry<K,V> oldEntry = cacheMap.put(key, newEntry);
         if (oldEntry != null) {
             oldEntry.invalidate();
             return;
@@ -362,8 +370,8 @@
         if (maxSize > 0 && cacheMap.size() > maxSize) {
             expungeExpiredEntries();
             if (cacheMap.size() > maxSize) { // still too large?
-                Iterator<CacheEntry> t = cacheMap.values().iterator();
-                CacheEntry lruEntry = t.next();
+                Iterator<CacheEntry<K,V>> t = cacheMap.values().iterator();
+                CacheEntry<K,V> lruEntry = t.next();
                 if (DEBUG) {
                     System.out.println("** Overflow removal "
                         + lruEntry.getKey() + " | " + lruEntry.getValue());
@@ -374,9 +382,9 @@
         }
     }
 
-    public synchronized Object get(Object key) {
+    public synchronized V get(Object key) {
         emptyQueue();
-        CacheEntry entry = cacheMap.get(key);
+        CacheEntry<K,V> entry = cacheMap.get(key);
         if (entry == null) {
             return null;
         }
@@ -393,7 +401,7 @@
 
     public synchronized void remove(Object key) {
         emptyQueue();
-        CacheEntry entry = cacheMap.remove(key);
+        CacheEntry<K,V> entry = cacheMap.remove(key);
         if (entry != null) {
             entry.invalidate();
         }
@@ -402,9 +410,9 @@
     public synchronized void setCapacity(int size) {
         expungeExpiredEntries();
         if (size > 0 && cacheMap.size() > size) {
-            Iterator<CacheEntry> t = cacheMap.values().iterator();
+            Iterator<CacheEntry<K,V>> t = cacheMap.values().iterator();
             for (int i = cacheMap.size() - size; i > 0; i--) {
-                CacheEntry lruEntry = t.next();
+                CacheEntry<K,V> lruEntry = t.next();
                 if (DEBUG) {
                     System.out.println("** capacity reset removal "
                         + lruEntry.getKey() + " | " + lruEntry.getValue());
@@ -431,60 +439,61 @@
     }
 
     // it is a heavyweight method.
-    public synchronized void accept(CacheVisitor visitor) {
+    public synchronized void accept(CacheVisitor<K,V> visitor) {
         expungeExpiredEntries();
-        Map<Object, Object> cached = getCachedEntries();
+        Map<K,V> cached = getCachedEntries();
 
         visitor.visit(cached);
     }
 
-    private Map<Object, Object> getCachedEntries() {
-        Map<Object,Object> kvmap = new HashMap<Object,Object>(cacheMap.size());
+    private Map<K,V> getCachedEntries() {
+        Map<K,V> kvmap = new HashMap<>(cacheMap.size());
 
-        for (CacheEntry entry : cacheMap.values()) {
+        for (CacheEntry<K,V> entry : cacheMap.values()) {
             kvmap.put(entry.getKey(), entry.getValue());
         }
 
         return kvmap;
     }
 
-    protected CacheEntry newEntry(Object key, Object value,
-            long expirationTime, ReferenceQueue<Object> queue) {
+    protected CacheEntry<K,V> newEntry(K key, V value,
+            long expirationTime, ReferenceQueue<V> queue) {
         if (queue != null) {
-            return new SoftCacheEntry(key, value, expirationTime, queue);
+            return new SoftCacheEntry<>(key, value, expirationTime, queue);
         } else {
-            return new HardCacheEntry(key, value, expirationTime);
+            return new HardCacheEntry<>(key, value, expirationTime);
         }
     }
 
-    private static interface CacheEntry {
+    private static interface CacheEntry<K,V> {
 
         boolean isValid(long currentTime);
 
         void invalidate();
 
-        Object getKey();
+        K getKey();
 
-        Object getValue();
+        V getValue();
 
     }
 
-    private static class HardCacheEntry implements CacheEntry {
+    private static class HardCacheEntry<K,V> implements CacheEntry<K,V> {
 
-        private Object key, value;
+        private K key;
+        private V value;
         private long expirationTime;
 
-        HardCacheEntry(Object key, Object value, long expirationTime) {
+        HardCacheEntry(K key, V value, long expirationTime) {
             this.key = key;
             this.value = value;
             this.expirationTime = expirationTime;
         }
 
-        public Object getKey() {
+        public K getKey() {
             return key;
         }
 
-        public Object getValue() {
+        public V getValue() {
             return value;
         }
 
@@ -503,24 +512,25 @@
         }
     }
 
-    private static class SoftCacheEntry
-            extends SoftReference<Object> implements CacheEntry {
+    private static class SoftCacheEntry<K,V>
+            extends SoftReference<V>
+            implements CacheEntry<K,V> {
 
-        private Object key;
+        private K key;
         private long expirationTime;
 
-        SoftCacheEntry(Object key, Object value, long expirationTime,
-                ReferenceQueue<Object> queue) {
+        SoftCacheEntry(K key, V value, long expirationTime,
+                ReferenceQueue<V> queue) {
             super(value, queue);
             this.key = key;
             this.expirationTime = expirationTime;
         }
 
-        public Object getKey() {
+        public K getKey() {
             return key;
         }
 
-        public Object getValue() {
+        public V getValue() {
             return get();
         }
 
--- a/jdk/src/share/classes/sun/security/util/Debug.java	Wed Jul 05 17:53:51 2017 +0200
+++ b/jdk/src/share/classes/sun/security/util/Debug.java	Wed Jul 05 17:54:24 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -80,6 +80,7 @@
         System.err.println("policy        loading and granting");
         System.err.println("provider      security provider debugging");
         System.err.println("scl           permissions SecureClassLoader assigns");
+        System.err.println("ts            timestamping");
         System.err.println();
         System.err.println("The following can be used with access:");
         System.err.println();
--- a/jdk/src/share/classes/sun/security/util/PathList.java	Wed Jul 05 17:53:51 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,111 +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.  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.security.util;
-
-import java.io.File;
-import java.io.IOException;
-import java.lang.String;
-import java.util.StringTokenizer;
-import java.net.URL;
-import java.net.URLClassLoader;
-import java.net.MalformedURLException;
-
-/**
- * A utility class for handle path list
- *
- */
-public class PathList {
-    /**
-     * Utility method for appending path from pathFrom to pathTo.
-     *
-     * @param pathTo the target path
-     * @param pathSource the path to be appended to pathTo
-     * @return the resulting path
-     */
-    public static String appendPath(String pathTo, String pathFrom) {
-        if (pathTo == null || pathTo.length() == 0) {
-            return pathFrom;
-        } else if (pathFrom == null || pathFrom.length() == 0) {
-            return pathTo;
-        } else {
-            return pathTo  + File.pathSeparator + pathFrom;
-        }
-    }
-
-    /**
-     * Utility method for converting a search path string to an array
-     * of directory and JAR file URLs.
-     *
-     * @param path the search path string
-     * @return the resulting array of directory and JAR file URLs
-     */
-    public static URL[] pathToURLs(String path) {
-        StringTokenizer st = new StringTokenizer(path, File.pathSeparator);
-        URL[] urls = new URL[st.countTokens()];
-        int count = 0;
-        while (st.hasMoreTokens()) {
-            URL url = fileToURL(new File(st.nextToken()));
-            if (url != null) {
-                urls[count++] = url;
-            }
-        }
-        if (urls.length != count) {
-            URL[] tmp = new URL[count];
-            System.arraycopy(urls, 0, tmp, 0, count);
-            urls = tmp;
-        }
-        return urls;
-    }
-
-    /**
-     * Returns the directory or JAR file URL corresponding to the specified
-     * local file name.
-     *
-     * @param file the File object
-     * @return the resulting directory or JAR file URL, or null if unknown
-     */
-    private static URL fileToURL(File file) {
-        String name;
-        try {
-            name = file.getCanonicalPath();
-        } catch (IOException e) {
-            name = file.getAbsolutePath();
-        }
-        name = name.replace(File.separatorChar, '/');
-        if (!name.startsWith("/")) {
-            name = "/" + name;
-        }
-        // If the file does not exist, then assume that it's a directory
-        if (!file.isFile()) {
-            name = name + "/";
-        }
-        try {
-            return new URL("file", "", name);
-        } catch (MalformedURLException e) {
-            throw new IllegalArgumentException("file");
-        }
-    }
-}
--- a/jdk/src/share/classes/sun/security/util/SignatureFileVerifier.java	Wed Jul 05 17:53:51 2017 +0200
+++ b/jdk/src/share/classes/sun/security/util/SignatureFileVerifier.java	Wed Jul 05 17:54:24 2017 +0200
@@ -35,7 +35,6 @@
 import java.util.jar.*;
 
 import sun.security.pkcs.*;
-import sun.security.timestamp.TimestampToken;
 import sun.misc.BASE64Decoder;
 
 import sun.security.jca.Providers;
@@ -485,7 +484,7 @@
                 signers = new ArrayList<CodeSigner>();
             }
             // Append the new code signer
-            signers.add(new CodeSigner(certChain, getTimestamp(info)));
+            signers.add(new CodeSigner(certChain, info.getTimestamp()));
 
             if (debug != null) {
                 debug.println("Signature Block Certificate: " +
@@ -500,62 +499,6 @@
         }
     }
 
-    /*
-     * Examines a signature timestamp token to generate a timestamp object.
-     *
-     * Examines the signer's unsigned attributes for a
-     * <tt>signatureTimestampToken</tt> attribute. If present,
-     * then it is parsed to extract the date and time at which the
-     * timestamp was generated.
-     *
-     * @param info A signer information element of a PKCS 7 block.
-     *
-     * @return A timestamp token or null if none is present.
-     * @throws IOException if an error is encountered while parsing the
-     *         PKCS7 data.
-     * @throws NoSuchAlgorithmException if an error is encountered while
-     *         verifying the PKCS7 object.
-     * @throws SignatureException if an error is encountered while
-     *         verifying the PKCS7 object.
-     * @throws CertificateException if an error is encountered while generating
-     *         the TSA's certpath.
-     */
-    private Timestamp getTimestamp(SignerInfo info)
-        throws IOException, NoSuchAlgorithmException, SignatureException,
-            CertificateException {
-
-        Timestamp timestamp = null;
-
-        // Extract the signer's unsigned attributes
-        PKCS9Attributes unsignedAttrs = info.getUnauthenticatedAttributes();
-        if (unsignedAttrs != null) {
-            PKCS9Attribute timestampTokenAttr =
-                unsignedAttrs.getAttribute("signatureTimestampToken");
-            if (timestampTokenAttr != null) {
-                PKCS7 timestampToken =
-                    new PKCS7((byte[])timestampTokenAttr.getValue());
-                // Extract the content (an encoded timestamp token info)
-                byte[] encodedTimestampTokenInfo =
-                    timestampToken.getContentInfo().getData();
-                // Extract the signer (the Timestamping Authority)
-                // while verifying the content
-                SignerInfo[] tsa =
-                    timestampToken.verify(encodedTimestampTokenInfo);
-                // Expect only one signer
-                ArrayList<X509Certificate> chain =
-                                tsa[0].getCertificateChain(timestampToken);
-                CertPath tsaChain = certificateFactory.generateCertPath(chain);
-                // Create a timestamp token info object
-                TimestampToken timestampTokenInfo =
-                    new TimestampToken(encodedTimestampTokenInfo);
-                // Create a timestamp object
-                timestamp =
-                    new Timestamp(timestampTokenInfo.getDate(), tsaChain);
-            }
-        }
-        return timestamp;
-    }
-
     // for the toHex function
     private static final char[] hexc =
             {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
--- a/jdk/src/share/classes/sun/security/x509/CertAndKeyGen.java	Wed Jul 05 17:53:51 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,301 +0,0 @@
-/*
- * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved.
- * 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.security.x509;
-
-import java.io.IOException;
-import java.security.cert.X509Certificate;
-import java.security.cert.CertificateException;
-import java.security.cert.CertificateEncodingException;
-import java.security.*;
-import java.util.Date;
-
-import sun.security.pkcs.PKCS10;
-
-
-/**
- * Generate a pair of keys, and provide access to them.  This class is
- * provided primarily for ease of use.
- *
- * <P>This provides some simple certificate management functionality.
- * Specifically, it allows you to create self-signed X.509 certificates
- * as well as PKCS 10 based certificate signing requests.
- *
- * <P>Keys for some public key signature algorithms have algorithm
- * parameters, such as DSS/DSA.  Some sites' Certificate Authorities
- * adopt fixed algorithm parameters, which speeds up some operations
- * including key generation and signing.  <em>At this time, this interface
- * does not provide a way to provide such algorithm parameters, e.g.
- * by providing the CA certificate which includes those parameters.</em>
- *
- * <P>Also, note that at this time only signature-capable keys may be
- * acquired through this interface.  Diffie-Hellman keys, used for secure
- * key exchange, may be supported later.
- *
- * @author David Brownell
- * @author Hemma Prafullchandra
- * @see PKCS10
- * @see X509CertImpl
- */
-public final class CertAndKeyGen {
-    /**
-     * Creates a CertAndKeyGen object for a particular key type
-     * and signature algorithm.
-     *
-     * @param keyType type of key, e.g. "RSA", "DSA"
-     * @param sigAlg name of the signature algorithm, e.g. "MD5WithRSA",
-     *          "MD2WithRSA", "SHAwithDSA".
-     * @exception NoSuchAlgorithmException on unrecognized algorithms.
-     */
-    public CertAndKeyGen (String keyType, String sigAlg)
-    throws NoSuchAlgorithmException
-    {
-        keyGen = KeyPairGenerator.getInstance(keyType);
-        this.sigAlg = sigAlg;
-    }
-
-    /**
-     * Creates a CertAndKeyGen object for a particular key type,
-     * signature algorithm, and provider.
-     *
-     * @param keyType type of key, e.g. "RSA", "DSA"
-     * @param sigAlg name of the signature algorithm, e.g. "MD5WithRSA",
-     *          "MD2WithRSA", "SHAwithDSA".
-     * @param providerName name of the provider
-     * @exception NoSuchAlgorithmException on unrecognized algorithms.
-     * @exception NoSuchProviderException on unrecognized providers.
-     */
-    public CertAndKeyGen (String keyType, String sigAlg, String providerName)
-    throws NoSuchAlgorithmException, NoSuchProviderException
-    {
-        if (providerName == null) {
-            keyGen = KeyPairGenerator.getInstance(keyType);
-        } else {
-            try {
-                keyGen = KeyPairGenerator.getInstance(keyType, providerName);
-            } catch (Exception e) {
-                // try first available provider instead
-                keyGen = KeyPairGenerator.getInstance(keyType);
-            }
-        }
-        this.sigAlg = sigAlg;
-    }
-
-    /**
-     * Sets the source of random numbers used when generating keys.
-     * If you do not provide one, a system default facility is used.
-     * You may wish to provide your own source of random numbers
-     * to get a reproducible sequence of keys and signatures, or
-     * because you may be able to take advantage of strong sources
-     * of randomness/entropy in your environment.
-     */
-    public void         setRandom (SecureRandom generator)
-    {
-        prng = generator;
-    }
-
-    // want "public void generate (X509Certificate)" ... inherit DSA/D-H param
-
-    /**
-     * Generates a random public/private key pair, with a given key
-     * size.  Different algorithms provide different degrees of security
-     * for the same key size, because of the "work factor" involved in
-     * brute force attacks.  As computers become faster, it becomes
-     * easier to perform such attacks.  Small keys are to be avoided.
-     *
-     * <P>Note that not all values of "keyBits" are valid for all
-     * algorithms, and not all public key algorithms are currently
-     * supported for use in X.509 certificates.  If the algorithm
-     * you specified does not produce X.509 compatible keys, an
-     * invalid key exception is thrown.
-     *
-     * @param keyBits the number of bits in the keys.
-     * @exception InvalidKeyException if the environment does not
-     *  provide X.509 public keys for this signature algorithm.
-     */
-    public void generate (int keyBits)
-    throws InvalidKeyException
-    {
-        KeyPair pair;
-
-        try {
-            if (prng == null) {
-                prng = new SecureRandom();
-            }
-            keyGen.initialize(keyBits, prng);
-            pair = keyGen.generateKeyPair();
-
-        } catch (Exception e) {
-            throw new IllegalArgumentException(e.getMessage());
-        }
-
-        publicKey = pair.getPublic();
-        privateKey = pair.getPrivate();
-    }
-
-
-    /**
-     * Returns the public key of the generated key pair if it is of type
-     * <code>X509Key</code>, or null if the public key is of a different type.
-     *
-     * XXX Note: This behaviour is needed for backwards compatibility.
-     * What this method really should return is the public key of the
-     * generated key pair, regardless of whether or not it is an instance of
-     * <code>X509Key</code>. Accordingly, the return type of this method
-     * should be <code>PublicKey</code>.
-     */
-    public X509Key getPublicKey()
-    {
-        if (!(publicKey instanceof X509Key)) {
-            return null;
-        }
-        return (X509Key)publicKey;
-    }
-
-
-    /**
-     * Returns the private key of the generated key pair.
-     *
-     * <P><STRONG><em>Be extremely careful when handling private keys.
-     * When private keys are not kept secret, they lose their ability
-     * to securely authenticate specific entities ... that is a huge
-     * security risk!</em></STRONG>
-     */
-    public PrivateKey getPrivateKey ()
-    {
-        return privateKey;
-    }
-
-
-    /**
-     * Returns a self-signed X.509v3 certificate for the public key.
-     * The certificate is immediately valid. No extensions.
-     *
-     * <P>Such certificates normally are used to identify a "Certificate
-     * Authority" (CA).  Accordingly, they will not always be accepted by
-     * other parties.  However, such certificates are also useful when
-     * you are bootstrapping your security infrastructure, or deploying
-     * system prototypes.
-     *
-     * @param myname X.500 name of the subject (who is also the issuer)
-     * @param firstDate the issue time of the certificate
-     * @param validity how long the certificate should be valid, in seconds
-     * @exception CertificateException on certificate handling errors.
-     * @exception InvalidKeyException on key handling errors.
-     * @exception SignatureException on signature handling errors.
-     * @exception NoSuchAlgorithmException on unrecognized algorithms.
-     * @exception NoSuchProviderException on unrecognized providers.
-     */
-    public X509Certificate getSelfCertificate (
-            X500Name myname, Date firstDate, long validity)
-    throws CertificateException, InvalidKeyException, SignatureException,
-        NoSuchAlgorithmException, NoSuchProviderException
-    {
-        X509CertImpl    cert;
-        Date            lastDate;
-
-        try {
-            lastDate = new Date ();
-            lastDate.setTime (firstDate.getTime () + validity * 1000);
-
-            CertificateValidity interval =
-                                   new CertificateValidity(firstDate,lastDate);
-
-            X509CertInfo info = new X509CertInfo();
-            // Add all mandatory attributes
-            info.set(X509CertInfo.VERSION,
-                     new CertificateVersion(CertificateVersion.V3));
-            info.set(X509CertInfo.SERIAL_NUMBER, new CertificateSerialNumber(
-                    new java.util.Random().nextInt() & 0x7fffffff));
-            AlgorithmId algID = AlgorithmId.get(sigAlg);
-            info.set(X509CertInfo.ALGORITHM_ID,
-                     new CertificateAlgorithmId(algID));
-            info.set(X509CertInfo.SUBJECT, new CertificateSubjectName(myname));
-            info.set(X509CertInfo.KEY, new CertificateX509Key(publicKey));
-            info.set(X509CertInfo.VALIDITY, interval);
-            info.set(X509CertInfo.ISSUER, new CertificateIssuerName(myname));
-
-            cert = new X509CertImpl(info);
-            cert.sign(privateKey, this.sigAlg);
-
-            return (X509Certificate)cert;
-
-        } catch (IOException e) {
-             throw new CertificateEncodingException("getSelfCert: " +
-                                                    e.getMessage());
-        }
-    }
-
-    // Keep the old method
-    public X509Certificate getSelfCertificate (X500Name myname, long validity)
-    throws CertificateException, InvalidKeyException, SignatureException,
-        NoSuchAlgorithmException, NoSuchProviderException
-    {
-        return getSelfCertificate(myname, new Date(), validity);
-    }
-
-    /**
-     * Returns a PKCS #10 certificate request.  The caller uses either
-     * <code>PKCS10.print</code> or <code>PKCS10.toByteArray</code>
-     * operations on the result, to get the request in an appropriate
-     * transmission format.
-     *
-     * <P>PKCS #10 certificate requests are sent, along with some proof
-     * of identity, to Certificate Authorities (CAs) which then issue
-     * X.509 public key certificates.
-     *
-     * @param myname X.500 name of the subject
-     * @exception InvalidKeyException on key handling errors.
-     * @exception SignatureException on signature handling errors.
-     */
-    public PKCS10 getCertRequest (X500Name myname)
-    throws InvalidKeyException, SignatureException
-    {
-        PKCS10  req = new PKCS10 (publicKey);
-
-        try {
-            Signature signature = Signature.getInstance(sigAlg);
-            signature.initSign (privateKey);
-            req.encodeAndSign(myname, signature);
-
-        } catch (CertificateException e) {
-            throw new SignatureException (sigAlg + " CertificateException");
-
-        } catch (IOException e) {
-            throw new SignatureException (sigAlg + " IOException");
-
-        } catch (NoSuchAlgorithmException e) {
-            // "can't happen"
-            throw new SignatureException (sigAlg + " unavailable?");
-        }
-        return req;
-    }
-
-    private SecureRandom        prng;
-    private String              sigAlg;
-    private KeyPairGenerator    keyGen;
-    private PublicKey           publicKey;
-    private PrivateKey          privateKey;
-}
--- a/jdk/src/share/classes/sun/util/resources/TimeZoneNames.java	Wed Jul 05 17:53:51 2017 +0200
+++ b/jdk/src/share/classes/sun/util/resources/TimeZoneNames.java	Wed Jul 05 17:54:24 2017 +0200
@@ -103,6 +103,8 @@
                                      "Eastern Daylight Time", "EDT"};
         String EST_NSW[] = new String[] {"Eastern Standard Time (New South Wales)", "EST",
                                          "Eastern Summer Time (New South Wales)", "EST"};
+        String FET[] = new String[] {"Further-eastern European Time", "FET",
+                                     "Further-eastern European Summer Time", "FEST"};
         String GHMT[] = new String[] {"Ghana Mean Time", "GMT",
                                      "Ghana Summer Time", "GHST"};
         String GAMBIER[] =  new String[] {"Gambier Time", "GAMT",
@@ -186,7 +188,7 @@
         String SAMOA[] = new String[] {"Samoa Standard Time", "SST",
                                        "Samoa Daylight Time", "SDT"};
         String WST_SAMOA[] = new String[] {"West Samoa Time", "WST",
-                                           "West Samoa Summer Time", "WSST"};
+                                           "West Samoa Daylight Time", "WSDT"};
         String ChST[] = new String[] {"Chamorro Standard Time", "ChST",
                                       "Chamorro Daylight Time", "ChDT"};
         String VICTORIA[] = new String[] {"Eastern Standard Time (Victoria)", "EST",
@@ -511,6 +513,7 @@
                                             "Tajikistan Summer Time", "TJST"}},
             {"Asia/Gaza", EET},
             {"Asia/Harbin", CTT},
+            {"Asia/Hebron", EET},
             {"Asia/Ho_Chi_Minh", ICT},
             {"Asia/Hong_Kong", HKT},
             {"Asia/Hovd", new String[] {"Hovd Time", "HOVT",
@@ -674,9 +677,8 @@
             {"Europe/Isle_of_Man", GMTBST},
             {"Europe/Istanbul", EET},
             {"Europe/Jersey", GMTBST},
-            {"Europe/Kaliningrad", new String[] {"Kaliningrad Time", "KALT",
-                                                 "Kaliningrad Summer Time", "KALST"}},
-            {"Europe/Kiev", EET},
+            {"Europe/Kaliningrad", FET},
+            {"Europe/Kiev", FET},
             {"Europe/Lisbon", WET},
             {"Europe/Ljubljana", CET},
             {"Europe/London", GMTBST},
@@ -684,7 +686,7 @@
             {"Europe/Madrid", CET},
             {"Europe/Malta", CET},
             {"Europe/Mariehamn", EET},
-            {"Europe/Minsk", EET},
+            {"Europe/Minsk", FET},
             {"Europe/Monaco", CET},
             {"Europe/Moscow", MSK},
             {"Europe/Nicosia", EET},
@@ -697,14 +699,14 @@
                                             "Samara Summer Time", "SAMST"}},
             {"Europe/San_Marino", CET},
             {"Europe/Sarajevo", CET},
-            {"Europe/Simferopol", EET},
+            {"Europe/Simferopol", FET},
             {"Europe/Skopje", CET},
             {"Europe/Sofia", EET},
             {"Europe/Stockholm", CET},
             {"Europe/Tallinn", EET},
             {"Europe/Tirane", CET},
             {"Europe/Tiraspol", EET},
-            {"Europe/Uzhgorod", EET},
+            {"Europe/Uzhgorod", FET},
             {"Europe/Vaduz", CET},
             {"Europe/Vatican", CET},
             {"Europe/Vienna", CET},
@@ -713,7 +715,7 @@
                                                "Volgograd Summer Time", "VOLST"}},
             {"Europe/Warsaw", CET},
             {"Europe/Zagreb", CET},
-            {"Europe/Zaporozhye", EET},
+            {"Europe/Zaporozhye", FET},
             {"Europe/Zurich", CET},
             {"GB", GMTBST},
             {"GB-Eire", GMTBST},
--- a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_de.java	Wed Jul 05 17:53:51 2017 +0200
+++ b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_de.java	Wed Jul 05 17:54:24 2017 +0200
@@ -103,6 +103,8 @@
                                      "\u00d6stliche Sommerzeit", "EDT"};
         String EST_NSW[] = new String[] {"\u00d6stliche Normalzeit (New South Wales)", "EST",
                                          "\u00d6stliche Sommerzeit (New South Wales)", "EST"};
+        String FET[] = new String[] {"Further-eastern European Time", "FET",
+                                     "Further-eastern European Summer Time", "FEST"};
         String GHMT[] = new String[] {"Ghanaische Normalzeit", "GMT",
                                       "Ghanaische Sommerzeit", "GHST"};
         String GAMBIER[] =  new String[] {"Gambier Zeit", "GAMT",
@@ -186,7 +188,7 @@
         String SAMOA[] = new String[] {"Samoa Normalzeit", "SST",
                                        "Samoa Sommerzeit", "SDT"};
         String WST_SAMOA[] = new String[] {"West Samoa Zeit", "WST",
-                                           "West Samoa Sommerzeit", "WSST"};
+                                           "West Samoa Sommerzeit", "WSDT"};
         String ChST[] = new String[] {"Chamorro Normalzeit", "ChST",
                       "Chamorro Sommerzeit", "ChDT"};
         String VICTORIA[] = new String[] {"\u00d6stliche Normalzeit (Victoria)", "EST",
@@ -511,6 +513,7 @@
                                             "Tadschikische Sommerzeit", "TJST"}},
             {"Asia/Gaza", EET},
             {"Asia/Harbin", CTT},
+            {"Asia/Hebron", EET},
             {"Asia/Ho_Chi_Minh", ICT},
             {"Asia/Hong_Kong", HKT},
             {"Asia/Hovd", new String[] {"Hovd Zeit", "HOVT",
@@ -674,9 +677,8 @@
             {"Europe/Isle_of_Man", GMTBST},
             {"Europe/Istanbul", EET},
             {"Europe/Jersey", GMTBST},
-            {"Europe/Kaliningrad", new String[] {"Kaliningrad Time", "KALT",
-                                                 "Kaliningrad Summer Time", "KALST"}},
-            {"Europe/Kiev", EET},
+            {"Europe/Kaliningrad", FET},
+            {"Europe/Kiev", FET},
             {"Europe/Lisbon", WET},
             {"Europe/Ljubljana", CET},
             {"Europe/London", GMTBST},
@@ -684,7 +686,7 @@
             {"Europe/Madrid", CET},
             {"Europe/Malta", CET},
             {"Europe/Mariehamn", EET},
-            {"Europe/Minsk", EET},
+            {"Europe/Minsk", FET},
             {"Europe/Monaco", CET},
             {"Europe/Moscow", MSK},
             {"Europe/Nicosia", EET},
@@ -697,14 +699,14 @@
                                             "Samarische Sommerzeit", "SAMST"}},
             {"Europe/San_Marino", CET},
             {"Europe/Sarajevo", CET},
-            {"Europe/Simferopol", EET},
+            {"Europe/Simferopol", FET},
             {"Europe/Skopje", CET},
             {"Europe/Sofia", EET},
             {"Europe/Stockholm", CET},
             {"Europe/Tallinn", EET},
             {"Europe/Tirane", CET},
             {"Europe/Tiraspol", EET},
-            {"Europe/Uzhgorod", EET},
+            {"Europe/Uzhgorod", FET},
             {"Europe/Vaduz", CET},
             {"Europe/Vatican", CET},
             {"Europe/Vienna", CET},
@@ -713,7 +715,7 @@
                                                "Wolgograder Sommerzeit", "VOLST"}},
             {"Europe/Warsaw", CET},
             {"Europe/Zagreb", CET},
-            {"Europe/Zaporozhye", EET},
+            {"Europe/Zaporozhye", FET},
             {"Europe/Zurich", CET},
             {"GB", GMTBST},
             {"GB-Eire", GMTBST},
--- a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_es.java	Wed Jul 05 17:53:51 2017 +0200
+++ b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_es.java	Wed Jul 05 17:54:24 2017 +0200
@@ -103,6 +103,8 @@
                                      "Hora de verano Oriental", "EDT"};
         String EST_NSW[] = new String[] {"Hora est\u00e1ndar Oriental (Nueva Gales del Sur)", "EST",
                                          "Hora de verano Oriental (Nueva Gales del Sur)", "EST"};
+        String FET[] = new String[] {"Further-eastern European Time", "FET",
+                                     "Further-eastern European Summer Time", "FEST"};
         String GHMT[] = new String[] {"Hora central de Ghana", "GMT",
                                       "Hora de verano de Ghana", "GHST"};
         String GAMBIER[] =  new String[] {"Hora de Gambier", "GAMT",
@@ -186,7 +188,7 @@
         String SAMOA[] = new String[] {"Hora est\u00e1ndar de Samoa", "SST",
                                        "Hora de verano de Samoa", "SDT"};
         String WST_SAMOA[] = new String[] {"Hora de Samoa Occidental", "WST",
-                                           "Hora de verano de Samoa Occidental", "WSST"};
+                                           "Hora de verano de Samoa Occidental", "WSDT"};
         String ChST[] = new String[] {"Hora est\u00e1ndar de Chamorro", "ChST",
                                       "Hora de verano de Chamorro", "ChDT"};
         String VICTORIA[] = new String[] {"Hora est\u00e1ndar del Este (Victoria)", "EST",
@@ -511,6 +513,7 @@
                                             "Hora de verano de Tajikist\u00e1n", "TJST"}},
             {"Asia/Gaza", EET},
             {"Asia/Harbin", CTT},
+            {"Asia/Hebron", EET},
             {"Asia/Ho_Chi_Minh", ICT},
             {"Asia/Hong_Kong", HKT},
             {"Asia/Hovd", new String[] {"Hora de Hovd", "HOVT",
@@ -674,9 +677,8 @@
             {"Europe/Isle_of_Man", GMTBST},
             {"Europe/Istanbul", EET},
             {"Europe/Jersey", GMTBST},
-            {"Europe/Kaliningrad", new String[] {"Kaliningrad Time", "KALT",
-                                                 "Kaliningrad Summer Time", "KALST"}},
-            {"Europe/Kiev", EET},
+            {"Europe/Kaliningrad", FET},
+            {"Europe/Kiev", FET},
             {"Europe/Lisbon", WET},
             {"Europe/Ljubljana", CET},
             {"Europe/London", GMTBST},
@@ -684,7 +686,7 @@
             {"Europe/Madrid", CET},
             {"Europe/Malta", CET},
             {"Europe/Mariehamn", EET},
-            {"Europe/Minsk", EET},
+            {"Europe/Minsk", FET},
             {"Europe/Monaco", CET},
             {"Europe/Moscow", MSK},
             {"Europe/Nicosia", EET},
@@ -697,14 +699,14 @@
                                             "Hora de verano de Samara", "SAMST"}},
             {"Europe/San_Marino", CET},
             {"Europe/Sarajevo", CET},
-            {"Europe/Simferopol", EET},
+            {"Europe/Simferopol", FET},
             {"Europe/Skopje", CET},
             {"Europe/Sofia", EET},
             {"Europe/Stockholm", CET},
             {"Europe/Tallinn", EET},
             {"Europe/Tirane", CET},
             {"Europe/Tiraspol", EET},
-            {"Europe/Uzhgorod", EET},
+            {"Europe/Uzhgorod", FET},
             {"Europe/Vaduz", CET},
             {"Europe/Vatican", CET},
             {"Europe/Vienna", CET},
@@ -713,7 +715,7 @@
                                                "Hora de verano de Volgogrado", "VOLST"}},
             {"Europe/Warsaw", CET},
             {"Europe/Zagreb", CET},
-            {"Europe/Zaporozhye", EET},
+            {"Europe/Zaporozhye", FET},
             {"Europe/Zurich", CET},
             {"GB", GMTBST},
             {"GB-Eire", GMTBST},
--- a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_fr.java	Wed Jul 05 17:53:51 2017 +0200
+++ b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_fr.java	Wed Jul 05 17:54:24 2017 +0200
@@ -103,6 +103,8 @@
                                      "Heure avanc\u00e9e de l'Est", "EDT"} ;
         String EST_NSW[] = new String[] {"Heure normale de l'Est (Nouvelle-Galles du Sud)", "EST",
                                          "Heure d'\u00e9t\u00e9 de l'Est (Nouvelle-Galles du Sud)", "EST"} ;
+        String FET[] = new String[] {"Further-eastern European Time", "FET",
+                                     "Further-eastern European Summer Time", "FEST"};
         String GHMT[] = new String[] {"Heure du Ghana", "GMT",
                                       "Heure d'\u00e9t\u00e9 du Ghana", "GHST"};
         String GAMBIER[] =  new String[] {"Heure de Gambi", "GAMT",
@@ -186,7 +188,7 @@
         String SAMOA[] = new String[] {"Heure standard de Samoa", "SST",
                                        "Heure avanc\u00e9e de Samoa", "SDT"};
         String WST_SAMOA[] = new String[] {"Heure des Samoas occidentales", "WST",
-                                           "Heure d'\u00e9t\u00e9 des Samoas occidentales", "WSST"} ;
+                                           "Heure d'\u00e9t\u00e9 des Samoas occidentales", "WSDT"} ;
         String ChST[] = new String[] {"Heure normale des \u00eeles Mariannes", "ChST",
                       "Heure d'\u00e9t\u00e9 des \u00eeles Mariannes", "ChDT"};
         String VICTORIA[] = new String[] {"Heure standard d'Australie orientale (Victoria)", "EST",
@@ -511,6 +513,7 @@
                                             "Heure d'\u00e9t\u00e9 du Tadjikistan", "TJST"}},
             {"Asia/Gaza", EET},
             {"Asia/Harbin", CTT},
+            {"Asia/Hebron", EET},
             {"Asia/Ho_Chi_Minh", ICT},
             {"Asia/Hong_Kong", HKT},
             {"Asia/Hovd", new String[] {"Heure de Hovd", "HOVT",
@@ -674,9 +677,8 @@
             {"Europe/Isle_of_Man", GMTBST},
             {"Europe/Istanbul", EET},
             {"Europe/Jersey", GMTBST},
-            {"Europe/Kaliningrad", new String[] {"Kaliningrad Time", "KALT",
-                                                 "Kaliningrad Summer Time", "KALST"}},
-            {"Europe/Kiev", EET},
+            {"Europe/Kaliningrad", FET},
+            {"Europe/Kiev", FET},
             {"Europe/Lisbon", WET},
             {"Europe/Ljubljana", CET},
             {"Europe/London", GMTBST},
@@ -684,7 +686,7 @@
             {"Europe/Madrid", CET},
             {"Europe/Malta", CET},
             {"Europe/Mariehamn", EET},
-            {"Europe/Minsk", EET},
+            {"Europe/Minsk", FET},
             {"Europe/Monaco", CET},
             {"Europe/Moscow", MSK},
             {"Europe/Nicosia", EET},
@@ -697,14 +699,14 @@
                                             "Heure d'\u00e9t\u00e9 de Samara", "SAMST"}},
             {"Europe/San_Marino", CET},
             {"Europe/Sarajevo", CET},
-            {"Europe/Simferopol", EET},
+            {"Europe/Simferopol", FET},
             {"Europe/Skopje", CET},
             {"Europe/Sofia", EET},
             {"Europe/Stockholm", CET},
             {"Europe/Tallinn", EET},
             {"Europe/Tirane", CET},
             {"Europe/Tiraspol", EET},
-            {"Europe/Uzhgorod", EET},
+            {"Europe/Uzhgorod", FET},
             {"Europe/Vaduz", CET},
             {"Europe/Vatican", CET},
             {"Europe/Vienna", CET},
@@ -713,7 +715,7 @@
                                                "Heure d'\u00e9t\u00e9 de Volgograd", "VOLST"}},
             {"Europe/Warsaw", CET},
             {"Europe/Zagreb", CET},
-            {"Europe/Zaporozhye", EET},
+            {"Europe/Zaporozhye", FET},
             {"Europe/Zurich", CET},
             {"GB", GMTBST},
             {"GB-Eire", GMTBST},
--- a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_it.java	Wed Jul 05 17:53:51 2017 +0200
+++ b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_it.java	Wed Jul 05 17:54:24 2017 +0200
@@ -103,6 +103,8 @@
                                      "Ora legale USA orientale", "EDT"};
         String EST_NSW[] = new String[] {"Ora solare dell'Australia orientale (Nuovo Galles del Sud)", "EST",
                                          "Ora estiva dell'Australia orientale (Nuovo Galles del Sud)", "EST"};
+        String FET[] = new String[] {"Further-eastern European Time", "FET",
+                                     "Further-eastern European Summer Time", "FEST"};
         String GHMT[] = new String[] {"Ora media del Ghana", "GMT",
                                       "Ora legale del Ghana", "GHST"};
         String GAMBIER[] =  new String[] {"Ora di Gambier", "GAMT",
@@ -186,7 +188,7 @@
         String SAMOA[] = new String[] {"Ora standard di Samoa", "SST",
                                        "Ora legale di Samoa", "SDT"};
         String WST_SAMOA[] = new String[] {"Ora di Samoa", "WST",
-                                           "Ora estiva di Samoa", "WSST"};
+                                           "Ora estiva di Samoa", "WSDT"};
         String ChST[] = new String[] {"Ora standard di Chamorro", "ChST",
                               "Ora legale di Chamorro", "ChDT"};
         String VICTORIA[] = new String[] {"Ora orientale standard (Victoria)", "EST",
@@ -511,6 +513,7 @@
                                             "Ora estiva del Tagikistan", "TJST"}},
             {"Asia/Gaza", EET},
             {"Asia/Harbin", CTT},
+            {"Asia/Hebron", EET},
             {"Asia/Ho_Chi_Minh", ICT},
             {"Asia/Hong_Kong", HKT},
             {"Asia/Hovd", new String[] {"Ora di Hovd", "HOVT",
@@ -674,9 +677,8 @@
             {"Europe/Isle_of_Man", GMTBST},
             {"Europe/Istanbul", EET},
             {"Europe/Jersey", GMTBST},
-            {"Europe/Kaliningrad", new String[] {"Kaliningrad Time", "KALT",
-                                                 "Kaliningrad Summer Time", "KALST"}},
-            {"Europe/Kiev", EET},
+            {"Europe/Kaliningrad", FET},
+            {"Europe/Kiev", FET},
             {"Europe/Lisbon", WET},
             {"Europe/Ljubljana", CET},
             {"Europe/London", GMTBST},
@@ -684,7 +686,7 @@
             {"Europe/Madrid", CET},
             {"Europe/Malta", CET},
             {"Europe/Mariehamn", EET},
-            {"Europe/Minsk", EET},
+            {"Europe/Minsk", FET},
             {"Europe/Monaco", CET},
             {"Europe/Moscow", MSK},
             {"Europe/Nicosia", EET},
@@ -697,14 +699,14 @@
                                             "Ora estiva di Samara", "SAMST"}},
             {"Europe/San_Marino", CET},
             {"Europe/Sarajevo", CET},
-            {"Europe/Simferopol", EET},
+            {"Europe/Simferopol", FET},
             {"Europe/Skopje", CET},
             {"Europe/Sofia", EET},
             {"Europe/Stockholm", CET},
             {"Europe/Tallinn", EET},
             {"Europe/Tirane", CET},
             {"Europe/Tiraspol", EET},
-            {"Europe/Uzhgorod", EET},
+            {"Europe/Uzhgorod", FET},
             {"Europe/Vaduz", CET},
             {"Europe/Vatican", CET},
             {"Europe/Vienna", CET},
@@ -713,7 +715,7 @@
                                                "Ora estiva di Volgograd", "VOLST"}},
             {"Europe/Warsaw", CET},
             {"Europe/Zagreb", CET},
-            {"Europe/Zaporozhye", EET},
+            {"Europe/Zaporozhye", FET},
             {"Europe/Zurich", CET},
             {"GB", GMTBST},
             {"GB-Eire", GMTBST},
--- a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_ja.java	Wed Jul 05 17:53:51 2017 +0200
+++ b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_ja.java	Wed Jul 05 17:54:24 2017 +0200
@@ -103,6 +103,8 @@
                                      "\u6771\u90e8\u590f\u6642\u9593", "EDT"};
         String EST_NSW[] = new String[] {"\u6771\u90e8\u6a19\u6e96\u6642 (\u30cb\u30e5\u30fc\u30b5\u30a6\u30b9\u30a6\u30a7\u30fc\u30eb\u30ba)", "EST",
                                          "\u6771\u90e8\u590f\u6642\u9593 (\u30cb\u30e5\u30fc\u30b5\u30a6\u30b9\u30a6\u30a7\u30fc\u30eb\u30ba)", "EST"};
+        String FET[] = new String[] {"Further-eastern European Time", "FET",
+                                     "Further-eastern European Summer Time", "FEST"};
         String GHMT[] = new String[] {"\u30ac\u30fc\u30ca\u6a19\u6e96\u6642", "GMT",
                                      "\u30ac\u30fc\u30ca\u590f\u6642\u9593", "GHST"};
         String GAMBIER[] =  new String[] {"\u30ac\u30f3\u30d3\u30a2\u6642\u9593", "GAMT",
@@ -186,7 +188,7 @@
         String SAMOA[] = new String[] {"\u30b5\u30e2\u30a2\u6a19\u6e96\u6642", "SST",
                                        "\u30b5\u30e2\u30a2\u590f\u6642\u9593", "SDT"};
         String WST_SAMOA[] = new String[] {"\u897f\u30b5\u30e2\u30a2\u6642\u9593", "WST",
-                                           "\u897f\u30b5\u30e2\u30a2\u590f\u6642\u9593", "WSST"};
+                                           "\u897f\u30b5\u30e2\u30a2\u590f\u6642\u9593", "WSDT"};
         String ChST[] = new String[] {"\u30b0\u30a2\u30e0\u6a19\u6e96\u6642", "ChST",
                                       "\u30b0\u30a2\u30e0\u590f\u6642\u9593", "ChDT"};
         String VICTORIA[] = new String[] {"\u6771\u90e8\u6a19\u6e96\u6642 (\u30d3\u30af\u30c8\u30ea\u30a2)", "EST",
@@ -511,6 +513,7 @@
                                             "\u30bf\u30b8\u30ad\u30b9\u30bf\u30f3\u590f\u6642\u9593", "TJST"}},
             {"Asia/Gaza", EET},
             {"Asia/Harbin", CTT},
+            {"Asia/Hebron", EET},
             {"Asia/Ho_Chi_Minh", ICT},
             {"Asia/Hong_Kong", HKT},
             {"Asia/Hovd", new String[] {"\u30db\u30d6\u30c9\u6642\u9593", "HOVT",
@@ -674,9 +677,8 @@
             {"Europe/Isle_of_Man", GMTBST},
             {"Europe/Istanbul", EET},
             {"Europe/Jersey", GMTBST},
-            {"Europe/Kaliningrad", new String[] {"Kaliningrad Time", "KALT",
-                                                 "Kaliningrad Summer Time", "KALST"}},
-            {"Europe/Kiev", EET},
+            {"Europe/Kaliningrad", FET},
+            {"Europe/Kiev", FET},
             {"Europe/Lisbon", WET},
             {"Europe/Ljubljana", CET},
             {"Europe/London", GMTBST},
@@ -684,7 +686,7 @@
             {"Europe/Madrid", CET},
             {"Europe/Malta", CET},
             {"Europe/Mariehamn", EET},
-            {"Europe/Minsk", EET},
+            {"Europe/Minsk", FET},
             {"Europe/Monaco", CET},
             {"Europe/Moscow", MSK},
             {"Europe/Nicosia", EET},
@@ -697,14 +699,14 @@
                                             "\u30b5\u30de\u30e9\u590f\u6642\u9593", "SAMST"}},
             {"Europe/San_Marino", CET},
             {"Europe/Sarajevo", CET},
-            {"Europe/Simferopol", EET},
+            {"Europe/Simferopol", FET},
             {"Europe/Skopje", CET},
             {"Europe/Sofia", EET},
             {"Europe/Stockholm", CET},
             {"Europe/Tallinn", EET},
             {"Europe/Tirane", CET},
             {"Europe/Tiraspol", EET},
-            {"Europe/Uzhgorod", EET},
+            {"Europe/Uzhgorod", FET},
             {"Europe/Vaduz", CET},
             {"Europe/Vatican", CET},
             {"Europe/Vienna", CET},
@@ -713,7 +715,7 @@
                                                "\u30dc\u30eb\u30b4\u30b0\u30e9\u30fc\u30c9\u590f\u6642\u9593", "VOLST"}},
             {"Europe/Warsaw", CET},
             {"Europe/Zagreb", CET},
-            {"Europe/Zaporozhye", EET},
+            {"Europe/Zaporozhye", FET},
             {"Europe/Zurich", CET},
             {"GB", GMTBST},
             {"GB-Eire", GMTBST},
--- a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_ko.java	Wed Jul 05 17:53:51 2017 +0200
+++ b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_ko.java	Wed Jul 05 17:54:24 2017 +0200
@@ -103,6 +103,8 @@
                                      "\ub3d9\ubd80 \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "EDT"};
         String EST_NSW[] = new String[] {"\ub3d9\ubd80 \ud45c\uc900\uc2dc(\ub274 \uc0ac\uc6b0\uc2a4 \uc6e8\uc77c\uc988)", "EST",
                                          "\ub3d9\ubd80 \uc77c\uad11\uc808\uc57d\uc2dc\uac04(\ub274 \uc0ac\uc6b0\uc2a4 \uc6e8\uc77c\uc988)", "EST"};
+        String FET[] = new String[] {"Further-eastern European Time", "FET",
+                                     "Further-eastern European Summer Time", "FEST"};
         String GHMT[] = new String[] {"\uac00\ub098 \ud45c\uc900\uc2dc", "GMT",
                                      "\uac00\ub098 \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "GHST"};
         String GAMBIER[] =  new String[] {"\uac10\ube44\uc544 \uc2dc\uac04", "GAMT",
@@ -186,7 +188,7 @@
         String SAMOA[] = new String[] {"\uc0ac\ubaa8\uc544 \ud45c\uc900\uc2dc", "SST",
                                        "\uc0ac\ubaa8\uc544 \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "SDT"};
         String WST_SAMOA[] = new String[] {"\uc11c\uc0ac\ubaa8\uc544 \uc2dc\uac04", "WST",
-                                           "\uc11c\uc0ac\ubaa8\uc544 \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "WSST"};
+                                           "\uc11c\uc0ac\ubaa8\uc544 \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "WSDT"};
         String ChST[] = new String[] {"\ucc28\ubaa8\ub85c \ud45c\uc900\uc2dc", "ChST",
                                       "\ucc28\ubaa8\ub85c \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "ChDT"};
         String VICTORIA[] = new String[] {"\ub3d9\ubd80 \ud45c\uc900\uc2dc(\ube45\ud1a0\ub9ac\uc544)", "EST",
@@ -511,6 +513,7 @@
                                             "\ud0c0\uc9c0\ud0a4\uc2a4\ud0c4 \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "TJST"}},
             {"Asia/Gaza", EET},
             {"Asia/Harbin", CTT},
+            {"Asia/Hebron", EET},
             {"Asia/Ho_Chi_Minh", ICT},
             {"Asia/Hong_Kong", HKT},
             {"Asia/Hovd", new String[] {"Hovd \uc2dc\uac04", "HOVT",
@@ -674,9 +677,8 @@
             {"Europe/Isle_of_Man", GMTBST},
             {"Europe/Istanbul", EET},
             {"Europe/Jersey", GMTBST},
-            {"Europe/Kaliningrad", new String[] {"Kaliningrad Time", "KALT",
-                                                 "Kaliningrad Summer Time", "KALST"}},
-            {"Europe/Kiev", EET},
+            {"Europe/Kaliningrad", FET},
+            {"Europe/Kiev", FET},
             {"Europe/Lisbon", WET},
             {"Europe/Ljubljana", CET},
             {"Europe/London", GMTBST},
@@ -684,7 +686,7 @@
             {"Europe/Madrid", CET},
             {"Europe/Malta", CET},
             {"Europe/Mariehamn", EET},
-            {"Europe/Minsk", EET},
+            {"Europe/Minsk", FET},
             {"Europe/Monaco", CET},
             {"Europe/Moscow", MSK},
             {"Europe/Nicosia", EET},
@@ -697,14 +699,14 @@
                                             "\uc0ac\ub9c8\ub77c \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "SAMST"}},
             {"Europe/San_Marino", CET},
             {"Europe/Sarajevo", CET},
-            {"Europe/Simferopol", EET},
+            {"Europe/Simferopol", FET},
             {"Europe/Skopje", CET},
             {"Europe/Sofia", EET},
             {"Europe/Stockholm", CET},
             {"Europe/Tallinn", EET},
             {"Europe/Tirane", CET},
             {"Europe/Tiraspol", EET},
-            {"Europe/Uzhgorod", EET},
+            {"Europe/Uzhgorod", FET},
             {"Europe/Vaduz", CET},
             {"Europe/Vatican", CET},
             {"Europe/Vienna", CET},
@@ -713,7 +715,7 @@
                                                "\ubcfc\uace0\uadf8\ub77c\ub4dc \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "VOLST"}},
             {"Europe/Warsaw", CET},
             {"Europe/Zagreb", CET},
-            {"Europe/Zaporozhye", EET},
+            {"Europe/Zaporozhye", FET},
             {"Europe/Zurich", CET},
             {"GB", GMTBST},
             {"GB-Eire", GMTBST},
--- a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_pt_BR.java	Wed Jul 05 17:53:51 2017 +0200
+++ b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_pt_BR.java	Wed Jul 05 17:54:24 2017 +0200
@@ -101,6 +101,8 @@
                                      "Hor\u00e1rio de luz natural oriental", "EDT"};
         String EST_NSW[] = new String[] {"Fuso hor\u00e1rio padr\u00e3o oriental (Nova Gales do Sul)", "EST",
                                          "Fuso hor\u00e1rio de ver\u00e3o oriental (Nova Gales do Sul)", "EST"};
+        String FET[] = new String[] {"Further-eastern European Time", "FET",
+                                     "Further-eastern European Summer Time", "FEST"};
         String GHMT[] = new String[] {"Fuso hor\u00e1rio do meridiano de Gana", "GMT",
                                       "Fuso hor\u00e1rio de ver\u00e3o de Gana", "GHST"};
         String GAMBIER[] =  new String[] {"Fuso hor\u00e1rio de Gambier", "GAMT",
@@ -184,7 +186,7 @@
         String SAMOA[] = new String[] {"Fuso hor\u00e1rio padr\u00e3o de Samoa", "SST",
                                        "Hor\u00e1rio de luz natural de Samoa", "SDT"};
         String WST_SAMOA[] = new String[] {"Fuso hor\u00e1rio de Samoa Ocidental", "WST",
-                                           "Fuso hor\u00e1rio de ver\u00e3o de Samoa Ocidental", "WSST"};
+                                           "Fuso hor\u00e1rio de ver\u00e3o de Samoa Ocidental", "WSDT"};
         String ChST[] = new String[] {"Fuso hor\u00e1rio padr\u00e3o de Chamorro", "ChST",
                                       "Hor\u00e1rio de luz natural de Chamorro", "ChDT"};
         String VICTORIA[] = new String[] {"Fuso hor\u00e1rio padr\u00e3o oriental (Victoria)", "EST",
@@ -511,6 +513,7 @@
                                             "Fuso hor\u00e1rio de ver\u00e3o do Tadjiquist\u00e3o", "TJST"}},
             {"Asia/Gaza", EET},
             {"Asia/Harbin", CTT},
+            {"Asia/Hebron", EET},
             {"Asia/Ho_Chi_Minh", ICT},
             {"Asia/Hong_Kong", HKT},
             {"Asia/Hovd", new String[] {"Fuso hor\u00e1rio de Hovd", "HOVT",
@@ -674,9 +677,8 @@
             {"Europe/Isle_of_Man", GMTBST},
             {"Europe/Istanbul", EET},
             {"Europe/Jersey", GMTBST},
-            {"Europe/Kaliningrad", new String[] {"Kaliningrad Time", "KALT",
-                                                 "Kaliningrad Summer Time", "KALST"}},
-            {"Europe/Kiev", EET},
+            {"Europe/Kaliningrad", FET},
+            {"Europe/Kiev", FET},
             {"Europe/Lisbon", WET},
             {"Europe/Ljubljana", CET},
             {"Europe/London", GMTBST},
@@ -684,7 +686,7 @@
             {"Europe/Madrid", CET},
             {"Europe/Malta", CET},
             {"Europe/Mariehamn", EET},
-            {"Europe/Minsk", EET},
+            {"Europe/Minsk", FET},
             {"Europe/Monaco", CET},
             {"Europe/Moscow", MSK},
             {"Europe/Nicosia", EET},
@@ -697,14 +699,14 @@
                                             "Fuso hor\u00e1rio de ver\u00e3o de Samara", "SAMST"}},
             {"Europe/San_Marino", CET},
             {"Europe/Sarajevo", CET},
-            {"Europe/Simferopol", EET},
+            {"Europe/Simferopol", FET},
             {"Europe/Skopje", CET},
             {"Europe/Sofia", EET},
             {"Europe/Stockholm", CET},
             {"Europe/Tallinn", EET},
             {"Europe/Tirane", CET},
             {"Europe/Tiraspol", EET},
-            {"Europe/Uzhgorod", EET},
+            {"Europe/Uzhgorod", FET},
             {"Europe/Vaduz", CET},
             {"Europe/Vatican", CET},
             {"Europe/Vienna", CET},
@@ -713,7 +715,7 @@
                                                "Fuso hor\u00e1rio de ver\u00e3o de Volgogrado", "VOLST"}},
             {"Europe/Warsaw", CET},
             {"Europe/Zagreb", CET},
-            {"Europe/Zaporozhye", EET},
+            {"Europe/Zaporozhye", FET},
             {"Europe/Zurich", CET},
             {"GB", GMTBST},
             {"GB-Eire", GMTBST},
--- a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_sv.java	Wed Jul 05 17:53:51 2017 +0200
+++ b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_sv.java	Wed Jul 05 17:54:24 2017 +0200
@@ -103,6 +103,8 @@
                                      "Eastern, sommartid", "EDT"};
         String EST_NSW[] = new String[] {"Eastern, normaltid (Nya Sydwales)", "EST",
                                          "Eastern, sommartid (Nya Sydwales)", "EST"};
+        String FET[] = new String[] {"Further-eastern European Time", "FET",
+                                     "Further-eastern European Summer Time", "FEST"};
         String GHMT[] = new String[] {"Ghana, normaltid", "GMT",
                                       "Ghana, sommartid", "GHST"};
         String GAMBIER[] =  new String[] {"Gambier, normaltid", "GAMT",
@@ -186,7 +188,7 @@
         String SAMOA[] = new String[] {"Samoa, normaltid", "SST",
                                        "Samoa, sommartid", "SDT"};
         String WST_SAMOA[] = new String[] {"V\u00e4stsamoansk tid", "WST",
-                                           "V\u00e4stsamoansk sommartid", "WSST"};
+                                           "V\u00e4stsamoansk sommartid", "WSDT"};
         String ChST[] = new String[] {"Chamorro, normaltid", "ChST",
                                       "Chamorro, sommartid", "ChDT"};
         String VICTORIA[] = new String[] {"\u00d6stlig normaltid (Victoria)", "EST",
@@ -511,6 +513,7 @@
                                             "Tadzjikistan, sommartid", "TJST"}},
             {"Asia/Gaza", EET},
             {"Asia/Harbin", CTT},
+            {"Asia/Hebron", EET},
             {"Asia/Ho_Chi_Minh", ICT},
             {"Asia/Hong_Kong", HKT},
             {"Asia/Hovd", new String[] {"Hovd, normaltid", "HOVT",
@@ -674,9 +677,8 @@
             {"Europe/Isle_of_Man", GMTBST},
             {"Europe/Istanbul", EET},
             {"Europe/Jersey", GMTBST},
-            {"Europe/Kaliningrad", new String[] {"Kaliningrad Time", "KALT",
-                                                 "Kaliningrad Summer Time", "KALST"}},
-            {"Europe/Kiev", EET},
+            {"Europe/Kaliningrad", FET},
+            {"Europe/Kiev", FET},
             {"Europe/Lisbon", WET},
             {"Europe/Ljubljana", CET},
             {"Europe/London", GMTBST},
@@ -684,7 +686,7 @@
             {"Europe/Madrid", CET},
             {"Europe/Malta", CET},
             {"Europe/Mariehamn", EET},
-            {"Europe/Minsk", EET},
+            {"Europe/Minsk", FET},
             {"Europe/Monaco", CET},
             {"Europe/Moscow", MSK},
             {"Europe/Nicosia", EET},
@@ -697,14 +699,14 @@
                                             "Samara, sommartid", "SAMST"}},
             {"Europe/San_Marino", CET},
             {"Europe/Sarajevo", CET},
-            {"Europe/Simferopol", EET},
+            {"Europe/Simferopol", FET},
             {"Europe/Skopje", CET},
             {"Europe/Sofia", EET},
             {"Europe/Stockholm", CET},
             {"Europe/Tallinn", EET},
             {"Europe/Tirane", CET},
             {"Europe/Tiraspol", EET},
-            {"Europe/Uzhgorod", EET},
+            {"Europe/Uzhgorod", FET},
             {"Europe/Vaduz", CET},
             {"Europe/Vatican", CET},
             {"Europe/Vienna", CET},
@@ -713,7 +715,7 @@
                                                "Volgograd, sommartid", "VOLST"}},
             {"Europe/Warsaw", CET},
             {"Europe/Zagreb", CET},
-            {"Europe/Zaporozhye", EET},
+            {"Europe/Zaporozhye", FET},
             {"Europe/Zurich", CET},
             {"GB", GMTBST},
             {"GB-Eire", GMTBST},
--- a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_zh_CN.java	Wed Jul 05 17:53:51 2017 +0200
+++ b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_zh_CN.java	Wed Jul 05 17:54:24 2017 +0200
@@ -103,6 +103,8 @@
                                      "\u4e1c\u90e8\u590f\u4ee4\u65f6", "EDT"};
         String EST_NSW[] = new String[] {"\u4e1c\u90e8\u6807\u51c6\u65f6\u95f4\uff08\u65b0\u5357\u5a01\u5c14\u65af\uff09", "EST",
                                          "\u4e1c\u90e8\u590f\u4ee4\u65f6\uff08\u65b0\u5357\u5a01\u5c14\u65af\uff09", "EST"};
+        String FET[] = new String[] {"Further-eastern European Time", "FET",
+                                     "Further-eastern European Summer Time", "FEST"};
         String GHMT[] = new String[] {"\u52a0\u7eb3\u65f6\u95f4", "GMT",
                                      "\u52a0\u7eb3\u590f\u4ee4\u65f6", "GHST"};
         String GAMBIER[] =  new String[] {"\u5188\u6bd4\u4e9a\u65f6\u95f4", "GAMT",
@@ -186,7 +188,7 @@
         String SAMOA[] = new String[] {"\u8428\u6469\u4e9a\u7fa4\u5c9b\u6807\u51c6\u65f6\u95f4", "SST",
                                        "\u8428\u6469\u4e9a\u7fa4\u5c9b\u590f\u4ee4\u65f6", "SDT"};
         String WST_SAMOA[] = new String[] {"\u897f\u8428\u6469\u4e9a\u65f6\u95f4", "WST",
-                                           "\u897f\u8428\u6469\u4e9a\u590f\u4ee4\u65f6", "WSST"};
+                                           "\u897f\u8428\u6469\u4e9a\u590f\u4ee4\u65f6", "WSDT"};
         String ChST[] = new String[] {"Chamorro \u6807\u51c6\u65f6\u95f4", "ChST",
                                       "Chamorro \u590f\u4ee4\u65f6", "ChDT"};
         String VICTORIA[] = new String[] {"\u4e1c\u90e8\u6807\u51c6\u65f6\u95f4\uff08\u7ef4\u591a\u5229\u4e9a\uff09", "EST",
@@ -511,6 +513,7 @@
                                             "\u5854\u5409\u514b\u65af\u5766\u590f\u4ee4\u65f6", "TJST"}},
             {"Asia/Gaza", EET},
             {"Asia/Harbin", CTT},
+            {"Asia/Hebron", EET},
             {"Asia/Ho_Chi_Minh", ICT},
             {"Asia/Hong_Kong", HKT},
             {"Asia/Hovd", new String[] {"\u79d1\u5e03\u591a\u65f6\u95f4", "HOVT",
@@ -674,9 +677,8 @@
             {"Europe/Isle_of_Man", GMTBST},
             {"Europe/Istanbul", EET},
             {"Europe/Jersey", GMTBST},
-            {"Europe/Kaliningrad", new String[] {"Kaliningrad Time", "KALT",
-                                                 "Kaliningrad Summer Time", "KALST"}},
-            {"Europe/Kiev", EET},
+            {"Europe/Kaliningrad", FET},
+            {"Europe/Kiev", FET},
             {"Europe/Lisbon", WET},
             {"Europe/Ljubljana", CET},
             {"Europe/London", GMTBST},
@@ -684,7 +686,7 @@
             {"Europe/Madrid", CET},
             {"Europe/Malta", CET},
             {"Europe/Mariehamn", EET},
-            {"Europe/Minsk", EET},
+            {"Europe/Minsk", FET},
             {"Europe/Monaco", CET},
             {"Europe/Moscow", MSK},
             {"Europe/Nicosia", EET},
@@ -697,14 +699,14 @@
                                             "\u6c99\u9a6c\u62c9\u590f\u4ee4\u65f6", "SAMST"}},
             {"Europe/San_Marino", CET},
             {"Europe/Sarajevo", CET},
-            {"Europe/Simferopol", EET},
+            {"Europe/Simferopol", FET},
             {"Europe/Skopje", CET},
             {"Europe/Sofia", EET},
             {"Europe/Stockholm", CET},
             {"Europe/Tallinn", EET},
             {"Europe/Tirane", CET},
             {"Europe/Tiraspol", EET},
-            {"Europe/Uzhgorod", EET},
+            {"Europe/Uzhgorod", FET},
             {"Europe/Vaduz", CET},
             {"Europe/Vatican", CET},
             {"Europe/Vienna", CET},
@@ -713,7 +715,7 @@
                                                "\u4f0f\u5c14\u52a0\u683c\u52d2\u590f\u4ee4\u65f6", "VOLST"}},
             {"Europe/Warsaw", CET},
             {"Europe/Zagreb", CET},
-            {"Europe/Zaporozhye", EET},
+            {"Europe/Zaporozhye", FET},
             {"Europe/Zurich", CET},
             {"GB", GMTBST},
             {"GB-Eire", GMTBST},
--- a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_zh_TW.java	Wed Jul 05 17:53:51 2017 +0200
+++ b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_zh_TW.java	Wed Jul 05 17:54:24 2017 +0200
@@ -103,6 +103,8 @@
                                      "\u6771\u65b9\u65e5\u5149\u7bc0\u7d04\u6642\u9593", "EDT"};
         String EST_NSW[] = new String[] {"\u6771\u65b9\u6a19\u6e96\u6642\u9593 (\u65b0\u5357\u5a01\u723e\u65af)", "EST",
                                          "\u6771\u65b9\u590f\u4ee4\u6642\u9593 (\u65b0\u5357\u5a01\u723e\u65af)", "EST"};
+        String FET[] = new String[] {"Further-eastern European Time", "FET",
+                                     "Further-eastern European Summer Time", "FEST"};
         String GHMT[] = new String[] {"\u8fe6\u7d0d\u5e73\u5747\u6642\u9593", "GMT",
                                       "\u8fe6\u7d0d\u590f\u4ee4\u6642\u9593", "GHST"};
         String GAMBIER[] =  new String[] {"\u7518\u6bd4\u723e\u6642\u9593", "GAMT",
@@ -186,7 +188,7 @@
         String SAMOA[] = new String[] {"\u85a9\u6469\u4e9e\u6a19\u6e96\u6642\u9593", "SST",
                                        "\u85a9\u6469\u4e9e\u65e5\u5149\u7bc0\u7d04\u6642\u9593", "SDT"};
         String WST_SAMOA[] = new String[] {"\u897f\u85a9\u6469\u4e9e\u6642\u9593", "WST",
-                                           "\u897f\u85a9\u6469\u4e9e\u590f\u4ee4\u6642\u9593", "WSST"};
+                                           "\u897f\u85a9\u6469\u4e9e\u590f\u4ee4\u6642\u9593", "WSDT"};
         String ChST[] = new String[] {"\u67e5\u83ab\u6d1b\u6a19\u6e96\u6642\u9593", "ChST",
                                      "\u67e5\u83ab\u6d1b\u65e5\u5149\u7bc0\u7d04\u6642\u9593", "ChDT"};
         String VICTORIA[] = new String[] {"\u6771\u90e8\u6a19\u6e96\u6642\u9593 (\u7dad\u591a\u5229\u4e9e\u90a6)", "EST",
@@ -511,6 +513,7 @@
                                             "\u5854\u5409\u514b\u590f\u4ee4\u6642\u9593", "TJST"}},
             {"Asia/Gaza", EET},
             {"Asia/Harbin", CTT},
+            {"Asia/Hebron", EET},
             {"Asia/Ho_Chi_Minh", ICT},
             {"Asia/Hong_Kong", HKT},
             {"Asia/Hovd", new String[] {"\u4faf\u5fb7 (Hovd) \u6642\u9593", "HOVT",
@@ -675,9 +678,8 @@
             {"Europe/Isle_of_Man", GMTBST},
             {"Europe/Istanbul", EET},
             {"Europe/Jersey", GMTBST},
-            {"Europe/Kaliningrad", new String[] {"Kaliningrad Time", "KALT",
-                                                 "Kaliningrad Summer Time", "KALST"}},
-            {"Europe/Kiev", EET},
+            {"Europe/Kaliningrad", FET},
+            {"Europe/Kiev", FET},
             {"Europe/Lisbon", WET},
             {"Europe/Ljubljana", CET},
             {"Europe/London", GMTBST},
@@ -685,7 +687,7 @@
             {"Europe/Madrid", CET},
             {"Europe/Malta", CET},
             {"Europe/Mariehamn", EET},
-            {"Europe/Minsk", EET},
+            {"Europe/Minsk", FET},
             {"Europe/Monaco", CET},
             {"Europe/Moscow", MSK},
             {"Europe/Nicosia", EET},
@@ -698,14 +700,14 @@
                                             "\u6c99\u99ac\u62c9\u590f\u4ee4\u6642\u9593", "SAMST"}},
             {"Europe/San_Marino", CET},
             {"Europe/Sarajevo", CET},
-            {"Europe/Simferopol", EET},
+            {"Europe/Simferopol", FET},
             {"Europe/Skopje", CET},
             {"Europe/Sofia", EET},
             {"Europe/Stockholm", CET},
             {"Europe/Tallinn", EET},
             {"Europe/Tirane", CET},
             {"Europe/Tiraspol", EET},
-            {"Europe/Uzhgorod", EET},
+            {"Europe/Uzhgorod", FET},
             {"Europe/Vaduz", CET},
             {"Europe/Vatican", CET},
             {"Europe/Vienna", CET},
@@ -714,7 +716,7 @@
                                                "\u4f0f\u723e\u52a0\u683c\u52d2\u590f\u4ee4\u6642\u9593", "VOLST"}},
             {"Europe/Warsaw", CET},
             {"Europe/Zagreb", CET},
-            {"Europe/Zaporozhye", EET},
+            {"Europe/Zaporozhye", FET},
             {"Europe/Zurich", CET},
             {"GB", GMTBST},
             {"GB-Eire", GMTBST},
--- a/jdk/src/share/lib/security/sunpkcs11-solaris.cfg	Wed Jul 05 17:53:51 2017 +0200
+++ b/jdk/src/share/lib/security/sunpkcs11-solaris.cfg	Wed Jul 05 17:54:24 2017 +0200
@@ -11,6 +11,9 @@
 
 handleStartupErrors = ignoreAll
 
+# Use the X9.63 encoding for EC points (do not wrap in an ASN.1 OctetString).
+useEcX963Encoding = true
+
 attributes = compatibility
 
 disabledMechanisms = {
--- a/jdk/src/share/native/java/io/ObjectInputStream.c	Wed Jul 05 17:53:51 2017 +0200
+++ b/jdk/src/share/native/java/io/ObjectInputStream.c	Wed Jul 05 17:54:24 2017 +0200
@@ -173,16 +173,3 @@
     (*env)->ReleasePrimitiveArrayCritical(env, dst, doubles, 0);
 }
 
-/*
- * Class:     java_io_ObjectInputStream
- * Method:    latestUserDefinedLoader
- * Signature: ()Ljava/lang/ClassLoader;
- *
- * Returns the first non-null class loader up the execution stack, or null
- * if only code from the null class loader is on the stack.
- */
-JNIEXPORT jobject JNICALL
-Java_java_io_ObjectInputStream_latestUserDefinedLoader(JNIEnv *env, jclass cls)
-{
-    return JVM_LatestUserDefinedLoader(env);
-}
--- a/jdk/src/share/native/sun/misc/VM.c	Wed Jul 05 17:53:51 2017 +0200
+++ b/jdk/src/share/native/sun/misc/VM.c	Wed Jul 05 17:54:24 2017 +0200
@@ -111,6 +111,11 @@
     get_thread_state_info(env, JAVA_THREAD_STATE_TERMINATED, values, names);
 }
 
+JNIEXPORT jobject JNICALL
+Java_sun_misc_VM_latestUserDefinedLoader(JNIEnv *env, jclass cls) {
+    return JVM_LatestUserDefinedLoader(env);
+}
+
 typedef void (JNICALL *GetJvmVersionInfo_fp)(JNIEnv*, jvm_version_info*, size_t);
 
 JNIEXPORT void JNICALL
--- a/jdk/src/share/native/sun/rmi/server/MarshalInputStream.c	Wed Jul 05 17:53:51 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,44 +0,0 @@
-/*
- * Copyright (c) 2000, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-#include "jni.h"
-#include "jvm.h"
-#include "jni_util.h"
-
-#include "sun_rmi_server_MarshalInputStream.h"
-
-/*
- * Class:     sun_rmi_server_MarshalInputStream
- * Method:    latestUserDefinedLoader
- * Signature: ()Ljava/lang/ClassLoader;
- *
- * Returns the first non-null class loader up the execution stack, or null
- * if only code from the null class loader is on the stack.
- */
-JNIEXPORT jobject JNICALL
-Java_sun_rmi_server_MarshalInputStream_latestUserDefinedLoader(JNIEnv *env, jclass cls)
-{
-    return JVM_LatestUserDefinedLoader(env);
-}
--- a/jdk/src/share/native/sun/security/pkcs11/wrapper/p11_convert.c	Wed Jul 05 17:53:51 2017 +0200
+++ b/jdk/src/share/native/sun/security/pkcs11/wrapper/p11_convert.c	Wed Jul 05 17:54:24 2017 +0200
@@ -273,7 +273,7 @@
     /* allocate memory for CK_VERSION pointer */
     ckpVersion = (CK_VERSION_PTR) malloc(sizeof(CK_VERSION));
     if (ckpVersion == NULL) {
-        JNU_ThrowOutOfMemoryError(env, 0);
+        throwOutOfMemoryError(env, 0);
         return NULL;
     }
     ckpVersion->major = jByteToCKByte(jMajor);
@@ -326,7 +326,7 @@
     /* allocate memory for CK_DATE pointer */
     ckpDate = (CK_DATE *) malloc(sizeof(CK_DATE));
     if (ckpDate == NULL) {
-        JNU_ThrowOutOfMemoryError(env, 0);
+        throwOutOfMemoryError(env, 0);
         return NULL;
     }
 
@@ -340,7 +340,7 @@
         jTempChars = (jchar*) malloc((ckLength) * sizeof(jchar));
         if (jTempChars == NULL) {
             free(ckpDate);
-            JNU_ThrowOutOfMemoryError(env, 0);
+            throwOutOfMemoryError(env, 0);
             return NULL;
         }
         (*env)->GetCharArrayRegion(env, jYear, 0, ckLength, jTempChars);
@@ -364,7 +364,7 @@
         jTempChars = (jchar*) malloc((ckLength) * sizeof(jchar));
         if (jTempChars == NULL) {
             free(ckpDate);
-            JNU_ThrowOutOfMemoryError(env, 0);
+            throwOutOfMemoryError(env, 0);
             return NULL;
         }
         (*env)->GetCharArrayRegion(env, jMonth, 0, ckLength, jTempChars);
@@ -388,7 +388,7 @@
         jTempChars = (jchar*) malloc((ckLength) * sizeof(jchar));
         if (jTempChars == NULL) {
             free(ckpDate);
-            JNU_ThrowOutOfMemoryError(env, 0);
+            throwOutOfMemoryError(env, 0);
             return NULL;
         }
         (*env)->GetCharArrayRegion(env, jDay, 0, ckLength, jTempChars);
@@ -558,7 +558,7 @@
     if (ckParam.pulOutputLen == NULL) {
         free(ckParam.pSeed);
         free(ckParam.pLabel);
-        JNU_ThrowOutOfMemoryError(env, 0);
+        throwOutOfMemoryError(env, 0);
         return ckParam;
     }
     jByteArrayToCKByteArray(env, jOutput, &(ckParam.pOutput), ckParam.pulOutputLen);
@@ -665,7 +665,7 @@
     if (ckParam.pReturnedKeyMaterial == NULL) {
         free(ckParam.RandomInfo.pClientRandom);
         free(ckParam.RandomInfo.pServerRandom);
-        JNU_ThrowOutOfMemoryError(env, 0);
+        throwOutOfMemoryError(env, 0);
         return ckParam;
     }
 
@@ -1013,7 +1013,7 @@
 
         ckpParam = (CK_SSL3_MASTER_KEY_DERIVE_PARAMS_PTR) malloc(sizeof(CK_SSL3_MASTER_KEY_DERIVE_PARAMS));
         if (ckpParam == NULL) {
-            JNU_ThrowOutOfMemoryError(env, 0);
+            throwOutOfMemoryError(env, 0);
             return;
         }
 
@@ -1040,7 +1040,7 @@
 
         ckpParam = (CK_SSL3_KEY_MAT_PARAMS_PTR) malloc(sizeof(CK_SSL3_KEY_MAT_PARAMS));
         if (ckpParam == NULL) {
-            JNU_ThrowOutOfMemoryError(env, 0);
+            throwOutOfMemoryError(env, 0);
             return;
         }
 
@@ -1067,7 +1067,7 @@
 
         ckpParam = (CK_TLS_PRF_PARAMS_PTR) malloc(sizeof(CK_TLS_PRF_PARAMS));
         if (ckpParam == NULL) {
-            JNU_ThrowOutOfMemoryError(env, 0);
+            throwOutOfMemoryError(env, 0);
             return;
         }
 
@@ -1094,7 +1094,7 @@
 
         ckpParam = (CK_AES_CTR_PARAMS_PTR) malloc(sizeof(CK_AES_CTR_PARAMS));
         if (ckpParam == NULL) {
-            JNU_ThrowOutOfMemoryError(env, 0);
+            throwOutOfMemoryError(env, 0);
             return;
         }
 
@@ -1121,7 +1121,7 @@
 
         ckpParam = (CK_RSA_PKCS_OAEP_PARAMS_PTR) malloc(sizeof(CK_RSA_PKCS_OAEP_PARAMS));
         if (ckpParam == NULL) {
-            JNU_ThrowOutOfMemoryError(env, 0);
+            throwOutOfMemoryError(env, 0);
             return;
         }
 
@@ -1148,7 +1148,7 @@
 
         ckpParam = (CK_PBE_PARAMS_PTR) malloc(sizeof(CK_PBE_PARAMS));
         if (ckpParam == NULL) {
-            JNU_ThrowOutOfMemoryError(env, 0);
+            throwOutOfMemoryError(env, 0);
             return;
         }
 
@@ -1175,7 +1175,7 @@
 
         ckpParam = (CK_PKCS5_PBKD2_PARAMS_PTR) malloc(sizeof(CK_PKCS5_PBKD2_PARAMS));
         if (ckpParam == NULL) {
-            JNU_ThrowOutOfMemoryError(env, 0);
+            throwOutOfMemoryError(env, 0);
             return;
         }
 
@@ -1202,7 +1202,7 @@
 
         ckpParam = (CK_RSA_PKCS_PSS_PARAMS_PTR) malloc(sizeof(CK_RSA_PKCS_PSS_PARAMS));
         if (ckpParam == NULL) {
-            JNU_ThrowOutOfMemoryError(env, 0);
+            throwOutOfMemoryError(env, 0);
             return;
         }
 
@@ -1229,7 +1229,7 @@
 
         ckpParam = (CK_ECDH1_DERIVE_PARAMS_PTR) malloc(sizeof(CK_ECDH1_DERIVE_PARAMS));
         if (ckpParam == NULL) {
-            JNU_ThrowOutOfMemoryError(env, 0);
+            throwOutOfMemoryError(env, 0);
             return;
         }
 
@@ -1256,7 +1256,7 @@
 
         ckpParam = (CK_ECDH2_DERIVE_PARAMS_PTR) malloc(sizeof(CK_ECDH2_DERIVE_PARAMS));
         if (ckpParam == NULL) {
-            JNU_ThrowOutOfMemoryError(env, 0);
+            throwOutOfMemoryError(env, 0);
             return;
         }
 
@@ -1283,7 +1283,7 @@
 
         ckpParam = (CK_X9_42_DH1_DERIVE_PARAMS_PTR) malloc(sizeof(CK_X9_42_DH1_DERIVE_PARAMS));
         if (ckpParam == NULL) {
-            JNU_ThrowOutOfMemoryError(env, 0);
+            throwOutOfMemoryError(env, 0);
             return;
         }
 
@@ -1310,7 +1310,7 @@
 
         ckpParam = (CK_X9_42_DH2_DERIVE_PARAMS_PTR) malloc(sizeof(CK_X9_42_DH2_DERIVE_PARAMS));
         if (ckpParam == NULL) {
-            JNU_ThrowOutOfMemoryError(env, 0);
+            throwOutOfMemoryError(env, 0);
             return;
         }
 
--- a/jdk/src/share/native/sun/security/pkcs11/wrapper/p11_digest.c	Wed Jul 05 17:53:51 2017 +0200
+++ b/jdk/src/share/native/sun/security/pkcs11/wrapper/p11_digest.c	Wed Jul 05 17:54:24 2017 +0200
@@ -131,7 +131,7 @@
         /* always use single part op, even for large data */
         bufP = (CK_BYTE_PTR) malloc((size_t)jInLen);
         if (bufP == NULL) {
-            JNU_ThrowOutOfMemoryError(env, 0);
+            throwOutOfMemoryError(env, 0);
             return 0;
         }
     }
@@ -190,7 +190,7 @@
         bufLen = min(MAX_HEAP_BUFFER_LEN, jInLen);
         bufP = (CK_BYTE_PTR) malloc((size_t)bufLen);
         if (bufP == NULL) {
-            JNU_ThrowOutOfMemoryError(env, 0);
+            throwOutOfMemoryError(env, 0);
             return;
         }
     }
--- a/jdk/src/share/native/sun/security/pkcs11/wrapper/p11_dual.c	Wed Jul 05 17:53:51 2017 +0200
+++ b/jdk/src/share/native/sun/security/pkcs11/wrapper/p11_dual.c	Wed Jul 05 17:54:24 2017 +0200
@@ -92,7 +92,7 @@
     ckpEncryptedPart = (CK_BYTE_PTR) malloc(ckEncryptedPartLength * sizeof(CK_BYTE));
     if (ckpEncryptedPart == NULL) {
         free(ckpPart);
-        JNU_ThrowOutOfMemoryError(env, 0);
+        throwOutOfMemoryError(env, 0);
         return NULL;
     }
 
@@ -144,7 +144,7 @@
     ckpPart = (CK_BYTE_PTR) malloc(ckPartLength * sizeof(CK_BYTE));
     if (ckpPart == NULL) {
         free(ckpEncryptedPart);
-        JNU_ThrowOutOfMemoryError(env, 0);
+        throwOutOfMemoryError(env, 0);
         return NULL;
     }
 
@@ -196,7 +196,7 @@
     ckpEncryptedPart = (CK_BYTE_PTR) malloc(ckEncryptedPartLength * sizeof(CK_BYTE));
     if (ckpEncryptedPart == NULL) {
         free(ckpPart);
-        JNU_ThrowOutOfMemoryError(env, 0);
+        throwOutOfMemoryError(env, 0);
         return NULL;
     }
 
@@ -248,7 +248,7 @@
     ckpPart = (CK_BYTE_PTR) malloc(ckPartLength * sizeof(CK_BYTE));
     if (ckpPart == NULL) {
         free(ckpEncryptedPart);
-        JNU_ThrowOutOfMemoryError(env, 0);
+        throwOutOfMemoryError(env, 0);
         return NULL;
     }
 
--- a/jdk/src/share/native/sun/security/pkcs11/wrapper/p11_general.c	Wed Jul 05 17:53:51 2017 +0200
+++ b/jdk/src/share/native/sun/security/pkcs11/wrapper/p11_general.c	Wed Jul 05 17:54:24 2017 +0200
@@ -71,7 +71,10 @@
 jclass jByteArrayClass;
 jclass jLongClass;
 
+JavaVM* jvm = NULL;
+
 JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) {
+    jvm = vm;
     return JNI_VERSION_1_4;
 }
 
@@ -351,7 +354,7 @@
 
     ckpSlotList = (CK_SLOT_ID_PTR) malloc(ckTokenNumber * sizeof(CK_SLOT_ID));
     if (ckpSlotList == NULL) {
-        JNU_ThrowOutOfMemoryError(env, 0);
+        throwOutOfMemoryError(env, 0);
         return NULL;
     }
 
@@ -652,7 +655,7 @@
     ckpMechanismList = (CK_MECHANISM_TYPE_PTR)
       malloc(ckMechanismNumber * sizeof(CK_MECHANISM_TYPE));
     if (ckpMechanismList == NULL) {
-        JNU_ThrowOutOfMemoryError(env, 0);
+        throwOutOfMemoryError(env, 0);
         return NULL;
     }
 
--- a/jdk/src/share/native/sun/security/pkcs11/wrapper/p11_keymgmt.c	Wed Jul 05 17:53:51 2017 +0200
+++ b/jdk/src/share/native/sun/security/pkcs11/wrapper/p11_keymgmt.c	Wed Jul 05 17:54:24 2017 +0200
@@ -165,7 +165,7 @@
         if (ckMechanism.pParameter != NULL_PTR) {
             free(ckMechanism.pParameter);
         }
-        JNU_ThrowOutOfMemoryError(env, 0);
+        throwOutOfMemoryError(env, 0);
         return NULL;
     }
     ckpPublicKeyHandle = ckpKeyHandles;   /* first element of array is Public Key */
@@ -253,7 +253,7 @@
             if (ckMechanism.pParameter != NULL_PTR) {
                 free(ckMechanism.pParameter);
             }
-            JNU_ThrowOutOfMemoryError(env, 0);
+            throwOutOfMemoryError(env, 0);
             return NULL;
         }
 
--- a/jdk/src/share/native/sun/security/pkcs11/wrapper/p11_mutex.c	Wed Jul 05 17:53:51 2017 +0200
+++ b/jdk/src/share/native/sun/security/pkcs11/wrapper/p11_mutex.c	Wed Jul 05 17:54:24 2017 +0200
@@ -92,7 +92,7 @@
     /* convert the Java InitArgs object to a pointer to a CK_C_INITIALIZE_ARGS structure */
     ckpInitArgs = (CK_C_INITIALIZE_ARGS_PTR) malloc(sizeof(CK_C_INITIALIZE_ARGS));
     if (ckpInitArgs == NULL) {
-        JNU_ThrowOutOfMemoryError(env, 0);
+        throwOutOfMemoryError(env, 0);
         return NULL_PTR;
     }
 
@@ -141,7 +141,7 @@
         ckpGlobalInitArgs = (CK_C_INITIALIZE_ARGS_PTR) malloc(sizeof(CK_C_INITIALIZE_ARGS));
         if (ckpGlobalInitArgs == NULL) {
             free(ckpInitArgs);
-            JNU_ThrowOutOfMemoryError(env, 0);
+            throwOutOfMemoryError(env, 0);
             return NULL_PTR;
         }
 
@@ -178,9 +178,8 @@
  */
 CK_RV callJCreateMutex(CK_VOID_PTR_PTR ppMutex)
 {
-    JavaVM *jvm;
+    extern JavaVM *jvm;
     JNIEnv *env;
-    jsize actualNumberVMs;
     jint returnValue;
     jthrowable pkcs11Exception;
     jclass pkcs11ExceptionClass;
@@ -196,8 +195,7 @@
 
 
     /* Get the currently running Java VM */
-    returnValue = JNI_GetCreatedJavaVMs(&jvm, (jsize) 1, &actualNumberVMs);
-    if ((returnValue != 0) || (actualNumberVMs <= 0)) { return rv ;} /* there is no VM running */
+    if (jvm == NULL) { return rv ;} /* there is no VM running */
 
     /* Determine, if current thread is already attached */
     returnValue = (*jvm)->GetEnv(jvm, (void **) &env, JNI_VERSION_1_2);
@@ -273,9 +271,8 @@
  */
 CK_RV callJDestroyMutex(CK_VOID_PTR pMutex)
 {
-    JavaVM *jvm;
+    extern JavaVM *jvm;
     JNIEnv *env;
-    jsize actualNumberVMs;
     jint returnValue;
     jthrowable pkcs11Exception;
     jclass pkcs11ExceptionClass;
@@ -291,8 +288,7 @@
 
 
     /* Get the currently running Java VM */
-    returnValue = JNI_GetCreatedJavaVMs(&jvm, (jsize) 1, &actualNumberVMs);
-    if ((returnValue != 0) || (actualNumberVMs <= 0)) { return rv ; } /* there is no VM running */
+    if (jvm == NULL) { return rv ; } /* there is no VM running */
 
     /* Determine, if current thread is already attached */
     returnValue = (*jvm)->GetEnv(jvm, (void **) &env, JNI_VERSION_1_2);
@@ -367,9 +363,8 @@
  */
 CK_RV callJLockMutex(CK_VOID_PTR pMutex)
 {
-    JavaVM *jvm;
+    extern JavaVM *jvm;
     JNIEnv *env;
-    jsize actualNumberVMs;
     jint returnValue;
     jthrowable pkcs11Exception;
     jclass pkcs11ExceptionClass;
@@ -385,8 +380,7 @@
 
 
     /* Get the currently running Java VM */
-    returnValue = JNI_GetCreatedJavaVMs(&jvm, (jsize) 1, &actualNumberVMs);
-    if ((returnValue != 0) || (actualNumberVMs <= 0)) { return rv ; } /* there is no VM running */
+    if (jvm == NULL) { return rv ; } /* there is no VM running */
 
     /* Determine, if current thread is already attached */
     returnValue = (*jvm)->GetEnv(jvm, (void **) &env, JNI_VERSION_1_2);
@@ -457,9 +451,8 @@
  */
 CK_RV callJUnlockMutex(CK_VOID_PTR pMutex)
 {
-    JavaVM *jvm;
+    extern JavaVM *jvm;
     JNIEnv *env;
-    jsize actualNumberVMs;
     jint returnValue;
     jthrowable pkcs11Exception;
     jclass pkcs11ExceptionClass;
@@ -475,8 +468,7 @@
 
 
     /* Get the currently running Java VM */
-    returnValue = JNI_GetCreatedJavaVMs(&jvm, (jsize) 1, &actualNumberVMs);
-    if ((returnValue != 0) || (actualNumberVMs <= 0)) { return rv ; } /* there is no VM running */
+    if (jvm == NULL) { return rv ; } /* there is no VM running */
 
     /* Determine, if current thread is already attached */
     returnValue = (*jvm)->GetEnv(jvm, (void **) &env, JNI_VERSION_1_2);
--- a/jdk/src/share/native/sun/security/pkcs11/wrapper/p11_objmgmt.c	Wed Jul 05 17:53:51 2017 +0200
+++ b/jdk/src/share/native/sun/security/pkcs11/wrapper/p11_objmgmt.c	Wed Jul 05 17:54:24 2017 +0200
@@ -258,7 +258,7 @@
         ckpAttributes[i].pValue = (void *) malloc(ckBufferLength);
         if (ckpAttributes[i].pValue == NULL) {
             freeCKAttributeArray(ckpAttributes, i);
-            JNU_ThrowOutOfMemoryError(env, 0);
+            throwOutOfMemoryError(env, 0);
             return;
         }
         ckpAttributes[i].ulValueLen = ckBufferLength;
@@ -390,7 +390,7 @@
     ckMaxObjectLength = jLongToCKULong(jMaxObjectCount);
     ckpObjectHandleArray = (CK_OBJECT_HANDLE_PTR) malloc(sizeof(CK_OBJECT_HANDLE) * ckMaxObjectLength);
     if (ckpObjectHandleArray == NULL) {
-        JNU_ThrowOutOfMemoryError(env, 0);
+        throwOutOfMemoryError(env, 0);
         return NULL;
     }
 
--- a/jdk/src/share/native/sun/security/pkcs11/wrapper/p11_sessmgmt.c	Wed Jul 05 17:53:51 2017 +0200
+++ b/jdk/src/share/native/sun/security/pkcs11/wrapper/p11_sessmgmt.c	Wed Jul 05 17:54:24 2017 +0200
@@ -98,7 +98,7 @@
     if (jNotify != NULL) {
         notifyEncapsulation = (NotifyEncapsulation *) malloc(sizeof(NotifyEncapsulation));
         if (notifyEncapsulation == NULL) {
-            JNU_ThrowOutOfMemoryError(env, 0);
+            throwOutOfMemoryError(env, 0);
             return 0L;
         }
         notifyEncapsulation->jApplicationData = (jApplication != NULL)
@@ -301,7 +301,7 @@
 
     ckpState = (CK_BYTE_PTR) malloc(ckStateLength);
     if (ckpState == NULL) {
-        JNU_ThrowOutOfMemoryError(env, 0);
+        throwOutOfMemoryError(env, 0);
         return NULL;
     }
 
@@ -435,7 +435,7 @@
 
     newNode = (NotifyListNode *) malloc(sizeof(NotifyListNode));
     if (newNode == NULL) {
-        JNU_ThrowOutOfMemoryError(env, 0);
+        throwOutOfMemoryError(env, 0);
         return;
     }
     newNode->hSession = hSession;
@@ -558,9 +558,8 @@
 )
 {
     NotifyEncapsulation *notifyEncapsulation;
-    JavaVM *jvm;
+    extern JavaVM *jvm;
     JNIEnv *env;
-    jsize actualNumberVMs;
     jint returnValue;
     jlong jSessionHandle;
     jlong jEvent;
@@ -577,8 +576,7 @@
     notifyEncapsulation = (NotifyEncapsulation *) pApplication;
 
     /* Get the currently running Java VM */
-    returnValue = JNI_GetCreatedJavaVMs(&jvm, (jsize) 1, &actualNumberVMs);
-    if ((returnValue != 0) || (actualNumberVMs <= 0)) { return rv ; } /* there is no VM running */
+    if (jvm == NULL) { return rv ; } /* there is no VM running */
 
     /* Determine, if current thread is already attached */
     returnValue = (*jvm)->GetEnv(jvm, (void **) &env, JNI_VERSION_1_2);
--- a/jdk/src/share/native/sun/security/pkcs11/wrapper/p11_sign.c	Wed Jul 05 17:53:51 2017 +0200
+++ b/jdk/src/share/native/sun/security/pkcs11/wrapper/p11_sign.c	Wed Jul 05 17:54:24 2017 +0200
@@ -132,7 +132,7 @@
     ckpSignature = (CK_BYTE_PTR) malloc(ckSignatureLength * sizeof(CK_BYTE));
     if (ckpSignature == NULL) {
         free(ckpData);
-        JNU_ThrowOutOfMemoryError(env, 0);
+        throwOutOfMemoryError(env, 0);
         return NULL;
     }
 
@@ -146,7 +146,7 @@
     ckpSignature = (CK_BYTE_PTR) malloc(256 * sizeof(CK_BYTE));
     if (ckpSignature == NULL) {
         free(ckpData);
-        JNU_ThrowOutOfMemoryError(env, 0);
+        throwOutOfMemoryError(env, 0);
         return NULL;
     }
     rv = (*ckpFunctions->C_Sign)(ckSessionHandle, ckpData, ckDataLength, ckpSignature, &ckSignatureLength);
@@ -156,7 +156,7 @@
         ckpSignature = (CK_BYTE_PTR) malloc(ckSignatureLength * sizeof(CK_BYTE));
         if (ckpSignature == NULL) {
             free(ckpData);
-            JNU_ThrowOutOfMemoryError(env, 0);
+            throwOutOfMemoryError(env, 0);
             return NULL;
         }
         rv = (*ckpFunctions->C_Sign)(ckSessionHandle, ckpData, ckDataLength, ckpSignature, &ckSignatureLength);
@@ -210,7 +210,7 @@
         bufLen = min(MAX_HEAP_BUFFER_LEN, jInLen);
         bufP = (CK_BYTE_PTR) malloc((size_t)bufLen);
         if (bufP == NULL) {
-            JNU_ThrowOutOfMemoryError(env, 0);
+            throwOutOfMemoryError(env, 0);
             return;
         }
     }
@@ -270,7 +270,7 @@
     if (rv == CKR_BUFFER_TOO_SMALL) {
         bufP = (CK_BYTE_PTR) malloc(ckSignatureLength);
         if (bufP == NULL) {
-            JNU_ThrowOutOfMemoryError(env, 0);
+            throwOutOfMemoryError(env, 0);
             return NULL;
         }
         rv = (*ckpFunctions->C_SignFinal)(ckSessionHandle, bufP, &ckSignatureLength);
@@ -355,7 +355,7 @@
     } else {
         inBufP = (CK_BYTE_PTR) malloc((size_t)jInLen);
         if (inBufP == NULL) {
-            JNU_ThrowOutOfMemoryError(env, 0);
+            throwOutOfMemoryError(env, 0);
             return 0;
         }
     }
@@ -373,7 +373,7 @@
             if (inBufP != INBUF) {
                 free(inBufP);
             }
-            JNU_ThrowOutOfMemoryError(env, 0);
+            throwOutOfMemoryError(env, 0);
             return 0;
         }
         rv = (*ckpFunctions->C_SignRecover)(ckSessionHandle, inBufP, jInLen, outBufP, &ckSignatureLength);
@@ -508,7 +508,7 @@
         bufLen = min(MAX_HEAP_BUFFER_LEN, jInLen);
         bufP = (CK_BYTE_PTR) malloc((size_t)bufLen);
         if (bufP == NULL) {
-            JNU_ThrowOutOfMemoryError(env, 0);
+            throwOutOfMemoryError(env, 0);
             return;
         }
     }
@@ -638,7 +638,7 @@
     } else {
         inBufP = (CK_BYTE_PTR) malloc((size_t)jInLen);
         if (inBufP == NULL) {
-            JNU_ThrowOutOfMemoryError(env, 0);
+            throwOutOfMemoryError(env, 0);
             return 0;
         }
     }
@@ -656,7 +656,7 @@
         outBufP = (CK_BYTE_PTR) malloc(ckDataLength);
         if (outBufP == NULL) {
             if (inBufP != INBUF) { free(inBufP); }
-            JNU_ThrowOutOfMemoryError(env, 0);
+            throwOutOfMemoryError(env, 0);
             return 0;
         }
         rv = (*ckpFunctions->C_VerifyRecover)(ckSessionHandle, inBufP, jInLen, outBufP, &ckDataLength);
--- a/jdk/src/share/native/sun/security/pkcs11/wrapper/p11_util.c	Wed Jul 05 17:53:51 2017 +0200
+++ b/jdk/src/share/native/sun/security/pkcs11/wrapper/p11_util.c	Wed Jul 05 17:54:24 2017 +0200
@@ -213,28 +213,52 @@
     return jErrorCode ;
 }
 
+
 /*
- * This function simply throws an IOException
- *
- * @param env Used to call JNI funktions and to get the Exception class.
- * @param message The message string of the Exception object.
+ * Throws a Java Exception by name
+ */
+void throwByName(JNIEnv *env, const char *name, const char *msg)
+{
+    jclass cls = (*env)->FindClass(env, name);
+
+    if (cls != 0) /* Otherwise an exception has already been thrown */
+        (*env)->ThrowNew(env, cls, msg);
+}
+
+/*
+ * Throws java.lang.OutOfMemoryError
  */
-void throwIOException(JNIEnv *env, const char *message)
+void throwOutOfMemoryError(JNIEnv *env, const char *msg)
+{
+    throwByName(env, "java/lang/OutOfMemoryError", msg);
+}
+
+/*
+ * Throws java.lang.NullPointerException
+ */
+void throwNullPointerException(JNIEnv *env, const char *msg)
 {
-    JNU_ThrowByName(env, CLASS_IO_EXCEPTION, message);
+    throwByName(env, "java/lang/NullPointerException", msg);
+}
+
+/*
+ * Throws java.io.IOException
+ */
+void throwIOException(JNIEnv *env, const char *msg)
+{
+    throwByName(env, "java/io/IOException", msg);
 }
 
 /*
  * This function simply throws a PKCS#11RuntimeException with the given
- * string as its message. If the message is NULL, the exception is created
- * using the default constructor.
+ * string as its message.
  *
  * @param env Used to call JNI funktions and to get the Exception class.
  * @param jmessage The message string of the Exception object.
  */
 void throwPKCS11RuntimeException(JNIEnv *env, const char *message)
 {
-    JNU_ThrowByName(env, CLASS_PKCS11RUNTIMEEXCEPTION, message);
+    throwByName(env, CLASS_PKCS11RUNTIMEEXCEPTION, message);
 }
 
 /*
@@ -318,7 +342,7 @@
     *ckpLength = (*env)->GetArrayLength(env, jArray);
     jpTemp = (jboolean*) malloc((*ckpLength) * sizeof(jboolean));
     if (jpTemp == NULL) {
-        JNU_ThrowOutOfMemoryError(env, 0);
+        throwOutOfMemoryError(env, 0);
         return;
     }
     (*env)->GetBooleanArrayRegion(env, jArray, 0, *ckpLength, jpTemp);
@@ -330,7 +354,7 @@
     *ckpArray = (CK_BBOOL*) malloc ((*ckpLength) * sizeof(CK_BBOOL));
     if (*ckpArray == NULL) {
         free(jpTemp);
-        JNU_ThrowOutOfMemoryError(env, 0);
+        throwOutOfMemoryError(env, 0);
         return;
     }
     for (i=0; i<(*ckpLength); i++) {
@@ -360,7 +384,7 @@
     *ckpLength = (*env)->GetArrayLength(env, jArray);
     jpTemp = (jbyte*) malloc((*ckpLength) * sizeof(jbyte));
     if (jpTemp == NULL) {
-        JNU_ThrowOutOfMemoryError(env, 0);
+        throwOutOfMemoryError(env, 0);
         return;
     }
     (*env)->GetByteArrayRegion(env, jArray, 0, *ckpLength, jpTemp);
@@ -376,7 +400,7 @@
         *ckpArray = (CK_BYTE_PTR) malloc ((*ckpLength) * sizeof(CK_BYTE));
         if (*ckpArray == NULL) {
             free(jpTemp);
-            JNU_ThrowOutOfMemoryError(env, 0);
+            throwOutOfMemoryError(env, 0);
             return;
         }
         for (i=0; i<(*ckpLength); i++) {
@@ -407,7 +431,7 @@
     *ckpLength = (*env)->GetArrayLength(env, jArray);
     jTemp = (jlong*) malloc((*ckpLength) * sizeof(jlong));
     if (jTemp == NULL) {
-        JNU_ThrowOutOfMemoryError(env, 0);
+        throwOutOfMemoryError(env, 0);
         return;
     }
     (*env)->GetLongArrayRegion(env, jArray, 0, *ckpLength, jTemp);
@@ -419,7 +443,7 @@
     *ckpArray = (CK_ULONG_PTR) malloc (*ckpLength * sizeof(CK_ULONG));
     if (*ckpArray == NULL) {
         free(jTemp);
-        JNU_ThrowOutOfMemoryError(env, 0);
+        throwOutOfMemoryError(env, 0);
         return;
     }
     for (i=0; i<(*ckpLength); i++) {
@@ -449,7 +473,7 @@
     *ckpLength = (*env)->GetArrayLength(env, jArray);
     jpTemp = (jchar*) malloc((*ckpLength) * sizeof(jchar));
     if (jpTemp == NULL) {
-        JNU_ThrowOutOfMemoryError(env, 0);
+        throwOutOfMemoryError(env, 0);
         return;
     }
     (*env)->GetCharArrayRegion(env, jArray, 0, *ckpLength, jpTemp);
@@ -461,7 +485,7 @@
     *ckpArray = (CK_CHAR_PTR) malloc (*ckpLength * sizeof(CK_CHAR));
     if (*ckpArray == NULL) {
         free(jpTemp);
-        JNU_ThrowOutOfMemoryError(env, 0);
+        throwOutOfMemoryError(env, 0);
         return;
     }
     for (i=0; i<(*ckpLength); i++) {
@@ -491,7 +515,7 @@
     *ckpLength = (*env)->GetArrayLength(env, jArray);
     jTemp = (jchar*) malloc((*ckpLength) * sizeof(jchar));
     if (jTemp == NULL) {
-        JNU_ThrowOutOfMemoryError(env, 0);
+        throwOutOfMemoryError(env, 0);
         return;
     }
     (*env)->GetCharArrayRegion(env, jArray, 0, *ckpLength, jTemp);
@@ -503,7 +527,7 @@
     *ckpArray = (CK_UTF8CHAR_PTR) malloc (*ckpLength * sizeof(CK_UTF8CHAR));
     if (*ckpArray == NULL) {
         free(jTemp);
-        JNU_ThrowOutOfMemoryError(env, 0);
+        throwOutOfMemoryError(env, 0);
         return;
     }
     for (i=0; i<(*ckpLength); i++) {
@@ -538,7 +562,7 @@
     *ckpArray = (CK_UTF8CHAR_PTR) malloc((*ckpLength + 1) * sizeof(CK_UTF8CHAR));
     if (*ckpArray == NULL) {
         (*env)->ReleaseStringUTFChars(env, (jstring) jArray, pCharArray);
-        JNU_ThrowOutOfMemoryError(env, 0);
+        throwOutOfMemoryError(env, 0);
         return;
     }
     strcpy((char*)*ckpArray, pCharArray);
@@ -571,7 +595,7 @@
     *ckpLength = jLongToCKULong(jLength);
     *ckpArray = (CK_ATTRIBUTE_PTR) malloc(*ckpLength * sizeof(CK_ATTRIBUTE));
     if (*ckpArray == NULL) {
-        JNU_ThrowOutOfMemoryError(env, 0);
+        throwOutOfMemoryError(env, 0);
         return;
     }
     TRACE1(", converting %d attibutes", jLength);
@@ -613,7 +637,7 @@
     } else {
         jpTemp = (jbyte*) malloc((ckLength) * sizeof(jbyte));
         if (jpTemp == NULL) {
-            JNU_ThrowOutOfMemoryError(env, 0);
+            throwOutOfMemoryError(env, 0);
             return NULL;
         }
         for (i=0; i<ckLength; i++) {
@@ -647,7 +671,7 @@
 
     jpTemp = (jlong*) malloc((ckLength) * sizeof(jlong));
     if (jpTemp == NULL) {
-        JNU_ThrowOutOfMemoryError(env, 0);
+        throwOutOfMemoryError(env, 0);
         return NULL;
     }
     for (i=0; i<ckLength; i++) {
@@ -678,7 +702,7 @@
 
     jpTemp = (jchar*) malloc(ckLength * sizeof(jchar));
     if (jpTemp == NULL) {
-        JNU_ThrowOutOfMemoryError(env, 0);
+        throwOutOfMemoryError(env, 0);
         return NULL;
     }
     for (i=0; i<ckLength; i++) {
@@ -709,7 +733,7 @@
 
     jpTemp = (jchar*) malloc(ckLength * sizeof(jchar));
     if (jpTemp == NULL) {
-        JNU_ThrowOutOfMemoryError(env, 0);
+        throwOutOfMemoryError(env, 0);
         return NULL;
     }
     for (i=0; i<ckLength; i++) {
@@ -812,7 +836,7 @@
     jValue = (*env)->CallBooleanMethod(env, jObject, jValueMethod);
     ckpValue = (CK_BBOOL *) malloc(sizeof(CK_BBOOL));
     if (ckpValue == NULL) {
-        JNU_ThrowOutOfMemoryError(env, 0);
+        throwOutOfMemoryError(env, 0);
         return NULL;
     }
     *ckpValue = jBooleanToCKBBool(jValue);
@@ -842,7 +866,7 @@
     jValue = (*env)->CallByteMethod(env, jObject, jValueMethod);
     ckpValue = (CK_BYTE_PTR) malloc(sizeof(CK_BYTE));
     if (ckpValue == NULL) {
-        JNU_ThrowOutOfMemoryError(env, 0);
+        throwOutOfMemoryError(env, 0);
         return NULL;
     }
     *ckpValue = jByteToCKByte(jValue);
@@ -871,7 +895,7 @@
     jValue = (*env)->CallIntMethod(env, jObject, jValueMethod);
     ckpValue = (CK_ULONG *) malloc(sizeof(CK_ULONG));
     if (ckpValue == NULL) {
-        JNU_ThrowOutOfMemoryError(env, 0);
+        throwOutOfMemoryError(env, 0);
         return NULL;
     }
     *ckpValue = jLongToCKLong(jValue);
@@ -900,7 +924,7 @@
     jValue = (*env)->CallLongMethod(env, jObject, jValueMethod);
     ckpValue = (CK_ULONG *) malloc(sizeof(CK_ULONG));
     if (ckpValue == NULL) {
-        JNU_ThrowOutOfMemoryError(env, 0);
+        throwOutOfMemoryError(env, 0);
         return NULL;
     }
     *ckpValue = jLongToCKULong(jValue);
@@ -930,7 +954,7 @@
     jValue = (*env)->CallCharMethod(env, jObject, jValueMethod);
     ckpValue = (CK_CHAR_PTR) malloc(sizeof(CK_CHAR));
     if (ckpValue == NULL) {
-        JNU_ThrowOutOfMemoryError(env, 0);
+        throwOutOfMemoryError(env, 0);
         return NULL;
     }
     *ckpValue = jCharToCKChar(jValue);
@@ -1087,7 +1111,7 @@
         malloc((strlen(exceptionMsgPrefix) + strlen(classNameString) + 1));
     if (exceptionMsg == NULL) {
         (*env)->ReleaseStringUTFChars(env, jClassNameString, classNameString);
-        JNU_ThrowOutOfMemoryError(env, 0);
+        throwOutOfMemoryError(env, 0);
         return;
     }
     strcpy(exceptionMsg, exceptionMsgPrefix);
--- a/jdk/src/share/native/sun/security/pkcs11/wrapper/pkcs11wrapper.h	Wed Jul 05 17:53:51 2017 +0200
+++ b/jdk/src/share/native/sun/security/pkcs11/wrapper/pkcs11wrapper.h	Wed Jul 05 17:54:24 2017 +0200
@@ -228,7 +228,6 @@
 #define CLASS_PKCS11EXCEPTION "sun/security/pkcs11/wrapper/PKCS11Exception"
 #define CLASS_PKCS11RUNTIMEEXCEPTION "sun/security/pkcs11/wrapper/PKCS11RuntimeException"
 #define CLASS_FILE_NOT_FOUND_EXCEPTION "java/io/FileNotFoundException"
-#define CLASS_IO_EXCEPTION "java/io/IOException"
 #define CLASS_C_INITIALIZE_ARGS "sun/security/pkcs11/wrapper/CK_C_INITIALIZE_ARGS"
 #define CLASS_CREATEMUTEX "sun/security/pkcs11/wrapper/CK_CREATEMUTEX"
 #define CLASS_DESTROYMUTEX "sun/security/pkcs11/wrapper/CK_DESTROYMUTEX"
@@ -280,6 +279,8 @@
  */
 
 jlong ckAssertReturnValueOK(JNIEnv *env, CK_RV returnValue);
+void throwOutOfMemoryError(JNIEnv *env, const char *message);
+void throwNullPointerException(JNIEnv *env, const char *message);
 void throwIOException(JNIEnv *env, const char *message);
 void throwPKCS11RuntimeException(JNIEnv *env, const char *message);
 void throwDisconnectedRuntimeException(JNIEnv *env);
--- a/jdk/src/solaris/classes/sun/print/UnixPrintServiceLookup.java	Wed Jul 05 17:53:51 2017 +0200
+++ b/jdk/src/solaris/classes/sun/print/UnixPrintServiceLookup.java	Wed Jul 05 17:54:24 2017 +0200
@@ -189,7 +189,7 @@
         if (printServices == null) {
             return new PrintService[0];
         } else {
-            return printServices;
+            return (PrintService[])printServices.clone();
         }
     }
 
--- a/jdk/src/solaris/native/sun/nio/fs/genSolarisConstants.c	Wed Jul 05 17:53:51 2017 +0200
+++ b/jdk/src/solaris/native/sun/nio/fs/genSolarisConstants.c	Wed Jul 05 17:54:24 2017 +0200
@@ -27,7 +27,7 @@
 #include <errno.h>
 #include <unistd.h>
 #include <sys/acl.h>
-#include <sys/fcntl.h>
+#include <fcntl.h>
 #include <sys/stat.h>
 
 /**
--- a/jdk/src/solaris/native/sun/nio/fs/genUnixConstants.c	Wed Jul 05 17:53:51 2017 +0200
+++ b/jdk/src/solaris/native/sun/nio/fs/genUnixConstants.c	Wed Jul 05 17:54:24 2017 +0200
@@ -26,7 +26,7 @@
 #include <stdio.h>
 #include <errno.h>
 #include <unistd.h>
-#include <sys/fcntl.h>
+#include <fcntl.h>
 #include <sys/stat.h>
 
 /**
--- a/jdk/src/solaris/native/sun/security/pkcs11/j2secmod_md.c	Wed Jul 05 17:53:51 2017 +0200
+++ b/jdk/src/solaris/native/sun/security/pkcs11/j2secmod_md.c	Wed Jul 05 17:54:24 2017 +0200
@@ -40,7 +40,7 @@
     if (fAddress == NULL) {
         char errorMessage[256];
         snprintf(errorMessage, sizeof(errorMessage), "Symbol not found: %s", functionName);
-        JNU_ThrowNullPointerException(env, errorMessage);
+        throwNullPointerException(env, errorMessage);
         return NULL;
     }
     return fAddress;
@@ -69,7 +69,7 @@
     dprintf2("-handle: %u (0X%X)\n", hModule, hModule);
 
     if (hModule == NULL) {
-        JNU_ThrowIOException(env, dlerror());
+        throwIOException(env, dlerror());
         return 0;
     }
 
--- a/jdk/src/solaris/native/sun/security/smartcardio/pcsc_md.c	Wed Jul 05 17:53:51 2017 +0200
+++ b/jdk/src/solaris/native/sun/security/smartcardio/pcsc_md.c	Wed Jul 05 17:54:24 2017 +0200
@@ -51,12 +51,40 @@
 FPTR_SCardEndTransaction scardEndTransaction;
 FPTR_SCardControl scardControl;
 
+/*
+ * Throws a Java Exception by name
+ */
+void throwByName(JNIEnv *env, const char *name, const char *msg)
+{
+    jclass cls = (*env)->FindClass(env, name);
+
+    if (cls != 0) /* Otherwise an exception has already been thrown */
+        (*env)->ThrowNew(env, cls, msg);
+}
+
+/*
+ * Throws java.lang.NullPointerException
+ */
+void throwNullPointerException(JNIEnv *env, const char *msg)
+{
+    throwByName(env, "java/lang/NullPointerException", msg);
+}
+
+/*
+ * Throws java.io.IOException
+ */
+void throwIOException(JNIEnv *env, const char *msg)
+{
+    throwByName(env, "java/io/IOException", msg);
+}
+
+
 void *findFunction(JNIEnv *env, void *hModule, char *functionName) {
     void *fAddress = dlsym(hModule, functionName);
     if (fAddress == NULL) {
         char errorMessage[256];
         snprintf(errorMessage, sizeof(errorMessage), "Symbol not found: %s", functionName);
-        JNU_ThrowNullPointerException(env, errorMessage);
+        throwNullPointerException(env, errorMessage);
         return NULL;
     }
     return fAddress;
@@ -69,7 +97,7 @@
     (*env)->ReleaseStringUTFChars(env, jLibName, libName);
 
     if (hModule == NULL) {
-        JNU_ThrowIOException(env, dlerror());
+        throwIOException(env, dlerror());
         return;
     }
     scardEstablishContext = (FPTR_SCardEstablishContext)findFunction(env, hModule, "SCardEstablishContext");
--- a/jdk/src/windows/classes/sun/java2d/d3d/D3DSurfaceData.java	Wed Jul 05 17:53:51 2017 +0200
+++ b/jdk/src/windows/classes/sun/java2d/d3d/D3DSurfaceData.java	Wed Jul 05 17:54:24 2017 +0200
@@ -486,7 +486,7 @@
             int dataType = 0;
             int scanStride = width;
 
-            if (dcm.getPixelSize() == 24 || dcm.getPixelSize() == 32) {
+            if (dcm.getPixelSize() > 16) {
                 dataType = DataBuffer.TYPE_INT;
             } else {
                 // 15, 16
--- a/jdk/src/windows/native/sun/security/pkcs11/j2secmod_md.c	Wed Jul 05 17:53:51 2017 +0200
+++ b/jdk/src/windows/native/sun/security/pkcs11/j2secmod_md.c	Wed Jul 05 17:54:24 2017 +0200
@@ -37,7 +37,7 @@
     if (fAddress == NULL) {
         char errorMessage[256];
         _snprintf(errorMessage, sizeof(errorMessage), "Symbol not found: %s", functionName);
-        JNU_ThrowNullPointerException(env, errorMessage);
+        throwNullPointerException(env, errorMessage);
         return NULL;
     }
     return fAddress;
@@ -78,7 +78,7 @@
             NULL
         );
         dprintf1("-error: %s\n", lpMsgBuf);
-        JNU_ThrowIOException(env, (char*)lpMsgBuf);
+        throwIOException(env, (char*)lpMsgBuf);
         LocalFree(lpMsgBuf);
         return 0;
     }
--- a/jdk/test/ProblemList.txt	Wed Jul 05 17:53:51 2017 +0200
+++ b/jdk/test/ProblemList.txt	Wed Jul 05 17:54:24 2017 +0200
@@ -377,6 +377,12 @@
 # 7081476
 java/net/InetSocketAddress/B6469803.java                        generic-all
 
+# 7102670
+java/net/InetAddress/CheckJNI.java                              linux-all
+
+# failing on vista 32/64 on nightly
+# 7102702
+java/net/PortUnreachableException/OneExceptionOnly.java         windows-all
 ############################################################################
 
 # jdk_io
@@ -517,9 +523,6 @@
 # 7079203 sun/security/tools/keytool/printssl.sh fails on solaris with timeout
 sun/security/tools/keytool/printssl.sh                          solaris-all
 
-# 7054637
-sun/security/tools/jarsigner/ec.sh                             solaris-all
-
 # 7081817
 sun/security/provider/certpath/X509CertPath/IllegalCertiticates.java    generic-all
 
--- a/jdk/test/java/net/DatagramSocket/ChangingAddress.java	Wed Jul 05 17:53:51 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,56 +0,0 @@
-/*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
- * 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 7084030
- * @summary Tests that DatagramSocket.getLocalAddress returns the right local
- *          address after connect/disconnect.
- */
-import java.net.*;
-
-public class ChangingAddress {
-
-    static void check(DatagramSocket ds, InetAddress expected) {
-        InetAddress actual = ds.getLocalAddress();
-        if (!expected.equals(actual)) {
-            throw new RuntimeException("Expected:"+expected+" Actual"+
-                                       actual);
-        }
-    }
-
-    public static void main(String[] args) throws Exception {
-        InetAddress lh = InetAddress.getLocalHost();
-        SocketAddress remote = new InetSocketAddress(lh, 1234);
-        InetAddress wildcard = InetAddress.getByAddress
-                               ("localhost", new byte[]{0,0,0,0});
-        try (DatagramSocket ds = new DatagramSocket()) {
-            check(ds, wildcard);
-
-            ds.connect(remote);
-            check(ds, lh);
-
-            ds.disconnect();
-            check(ds, wildcard);
-       }
-    }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/Collections/CheckedQueue.java	Wed Jul 05 17:54:24 2017 +0200
@@ -0,0 +1,190 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * 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 5020931
+ * @summary Unit test for Collections.checkedQueue
+ */
+
+import java.lang.reflect.Method;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.Queue;
+import java.util.concurrent.ArrayBlockingQueue;
+
+public class CheckedQueue {
+    static int status = 0;
+
+    public static void main(String[] args) throws Exception {
+        new CheckedQueue();
+    }
+
+    public CheckedQueue() throws Exception {
+        run();
+    }
+
+    private void run() throws Exception {
+        Method[] methods = this.getClass().getDeclaredMethods();
+
+        for (int i = 0; i < methods.length; i++) {
+            Method method = methods[i];
+            String methodName = method.getName();
+
+            if (methodName.startsWith("test")) {
+                try {
+                    Object obj = method.invoke(this, new Object[0]);
+                } catch(Exception e) {
+                    throw new Exception(this.getClass().getName() + "." +
+                            methodName + " test failed, test exception "
+                            + "follows\n" + e.getCause());
+                }
+            }
+        }
+    }
+
+    /**
+     * This test adds items to a queue.
+     */
+    private void test00() {
+        int arrayLength = 10;
+        ArrayBlockingQueue<String> abq = new ArrayBlockingQueue(arrayLength);
+
+        for (int i = 0; i < arrayLength; i++) {
+            abq.add(new String(Integer.toString(i)));
+        }
+    }
+
+    /**
+     * This test tests the CheckedQueue.add method.  It creates a queue of
+     * {@code String}s gets the checked queue, and attempt to add an Integer to
+     * the checked queue.
+     */
+    private void test01() throws Exception {
+        int arrayLength = 10;
+        ArrayBlockingQueue<String> abq = new ArrayBlockingQueue(arrayLength + 1);
+
+        for (int i = 0; i < arrayLength; i++) {
+            abq.add(new String(Integer.toString(i)));
+        }
+
+        Queue q = Collections.checkedQueue(abq, String.class);
+
+        try {
+            q.add(new Integer(0));
+            throw new Exception(this.getClass().getName() + "." + "test01 test"
+                    + " failed, should throw ClassCastException.");
+        } catch(ClassCastException cce) {
+            // Do nothing.
+        }
+    }
+
+    /**
+     * This test tests the CheckedQueue.add method.  It creates a queue of one
+     * {@code String}, gets the checked queue, and attempt to add an Integer to
+     * the checked queue.
+     */
+    private void test02() throws Exception {
+        ArrayBlockingQueue<String> abq = new ArrayBlockingQueue(1);
+        Queue q = Collections.checkedQueue(abq, String.class);
+
+        try {
+            q.add(new Integer(0));
+            throw new Exception(this.getClass().getName() + "." + "test02 test"
+                    + " failed, should throw ClassCastException.");
+        } catch(ClassCastException e) {
+            // Do nothing.
+        }
+    }
+
+    /**
+     * This test tests the Collections.checkedQueue method call for nulls in
+     * each and both of the parameters.
+     */
+    private void test03() throws Exception {
+        ArrayBlockingQueue<String> abq = new ArrayBlockingQueue(1);
+        Queue q;
+
+        try {
+            q = Collections.checkedQueue(null, String.class);
+            throw new Exception(this.getClass().getName() + "." + "test03 test"
+                    + " failed, should throw NullPointerException.");
+        } catch(NullPointerException npe) {
+            // Do nothing
+        }
+
+        try {
+            q = Collections.checkedQueue(abq, null);
+            throw new Exception(this.getClass().getName() + "." + "test03 test"
+                    + " failed, should throw NullPointerException.");
+        } catch(Exception e) {
+            // Do nothing
+        }
+
+        try {
+            q = Collections.checkedQueue(null, null);
+            throw new Exception(this.getClass().getName() + "." + "test03 test"
+                    + " failed, should throw NullPointerException.");
+        } catch(Exception e) {
+            // Do nothing
+        }
+    }
+
+    /**
+     * This test tests the CheckedQueue.offer method.
+     */
+    private void test04() throws Exception {
+        ArrayBlockingQueue<String> abq = new ArrayBlockingQueue(1);
+        Queue q = Collections.checkedQueue(abq, String.class);
+
+        try {
+            q.offer(null);
+            throw new Exception(this.getClass().getName() + "." + "test04 test"
+                    + " failed, should throw NullPointerException.");
+        } catch (NullPointerException npe) {
+            // Do nothing
+        }
+
+        try {
+            q.offer(new Integer(0));
+            throw new Exception(this.getClass().getName() + "." + "test04 test"
+                    + " failed, should throw ClassCastException.");
+        } catch (ClassCastException cce) {
+            // Do nothing
+        }
+
+        q.offer(new String("0"));
+
+        try {
+            q.offer(new String("1"));
+            throw new Exception(this.getClass().getName() + "." + "test04 test"
+                    + " failed, should throw IllegalStateException.");
+        } catch(IllegalStateException ise) {
+            // Do nothing
+        }
+    }
+
+    private void test05() {
+
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/java2d/DirectX/DrawBitmaskToSurfaceTest.java	Wed Jul 05 17:54:24 2017 +0200
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * 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     6997116
+ * @summary Test verifies that rendering of images with bitmap transparency
+ *          to a D3D surface does not cause an ClassCastException.
+ *
+ * @run main/othervm -Dsun.java2d.d3d=True DrawBitmaskToSurfaceTest
+ */
+
+import java.awt.Graphics;
+import java.awt.Image;
+import java.awt.image.BufferedImage;
+import java.awt.image.IndexColorModel;
+import java.util.concurrent.CountDownLatch;
+import javax.swing.JFrame;
+
+public class DrawBitmaskToSurfaceTest extends JFrame {
+
+    private final Image src;
+    private static java.util.concurrent.CountDownLatch latch = null;
+    private static Throwable theError = null;
+
+    public DrawBitmaskToSurfaceTest() {
+        src = createTestImage();
+    }
+
+    private static Image createTestImage() {
+        byte[] r = new byte[]{(byte)0x00, (byte)0x80, (byte)0xff, (byte)0xff};
+        byte[] g = new byte[]{(byte)0x00, (byte)0x80, (byte)0xff, (byte)0x00};
+        byte[] b = new byte[]{(byte)0x00, (byte)0x80, (byte)0xff, (byte)0x00};
+
+        IndexColorModel icm = new IndexColorModel(2, 4, r, g, b, 3);
+
+        BufferedImage img = new BufferedImage(100, 100,
+                                              BufferedImage.TYPE_BYTE_INDEXED,
+                                              icm);
+        return img;
+    }
+
+    @Override
+    public void paint(final Graphics g) {
+        try {
+            System.err.println("paint frame....");
+            g.drawImage(src, 30, 30, this);
+        } catch (Throwable e) {
+            theError = e;
+        } finally {
+            if (latch != null) {
+                latch.countDown();
+            }
+        }
+    }
+
+    public static void main(final String[] args) throws Exception {
+        final JFrame frame = new DrawBitmaskToSurfaceTest();
+        frame.setBounds(10, 350, 200, 200);
+        frame.setVisible(true);
+
+        Thread.sleep(2000);
+
+        System.err.println("Change frame bounds...");
+        latch = new CountDownLatch(1);
+        frame.setBounds(10, 350, 90, 90);
+        frame.repaint();
+
+        try {
+            if (latch.getCount() > 0) {
+                latch.await();
+            }
+        } catch (InterruptedException e) {
+        }
+
+        frame.dispose();
+
+        if (theError != null) {
+            throw new RuntimeException("Test failed.", theError);
+        }
+
+        System.err.println("Test passed");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/provider/X509Factory/BigCRL.java	Wed Jul 05 17:54:24 2017 +0200
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * 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 7099399
+ * @summary cannot deal with CRL file larger than 16MB
+ * @run main/othervm -Xmx1024m BigCRL
+ */
+
+import java.io.FileInputStream;
+import java.math.BigInteger;
+import java.security.KeyStore;
+import java.security.cert.Certificate;
+import java.security.PrivateKey;
+import java.security.cert.X509CRLEntry;
+import java.util.Arrays;
+import java.util.Date;
+import sun.security.x509.*;
+import java.security.cert.CertificateFactory;
+import java.io.ByteArrayInputStream;
+
+public class BigCRL {
+
+    public static void main(String[] args) throws Exception {
+        int n = 500000;
+        String ks = System.getProperty("test.src", ".")
+                + "/../../ssl/etc/keystore";
+        String pass = "passphrase";
+        String alias = "dummy";
+
+        KeyStore keyStore = KeyStore.getInstance("JKS");
+        keyStore.load(new FileInputStream(ks), pass.toCharArray());
+        Certificate signerCert = keyStore.getCertificate(alias);
+        byte[] encoded = signerCert.getEncoded();
+        X509CertImpl signerCertImpl = new X509CertImpl(encoded);
+        X509CertInfo signerCertInfo = (X509CertInfo)signerCertImpl.get(
+                X509CertImpl.NAME + "." + X509CertImpl.INFO);
+        X500Name owner = (X500Name)signerCertInfo.get(X509CertInfo.SUBJECT + "."
+                + CertificateSubjectName.DN_NAME);
+
+        Date date = new Date();
+        PrivateKey privateKey = (PrivateKey)
+                keyStore.getKey(alias, pass.toCharArray());
+        String sigAlgName = signerCertImpl.getSigAlgOID();
+
+        X509CRLEntry[] badCerts = new X509CRLEntry[n];
+        CRLExtensions ext = new CRLExtensions();
+        ext.set("Reason", new CRLReasonCodeExtension(1));
+        for (int i = 0; i < n; i++) {
+            badCerts[i] = new X509CRLEntryImpl(
+                    BigInteger.valueOf(i), date, ext);
+        }
+        X509CRLImpl crl = new X509CRLImpl(owner, date, date, badCerts);
+        crl.sign(privateKey, sigAlgName);
+        byte[] data = crl.getEncodedInternal();
+
+        // Make sure the CRL is big enough
+        if ((data[1]&0xff) != 0x84) {
+            throw new Exception("The file should be big enough?");
+        }
+
+        CertificateFactory cf = CertificateFactory.getInstance("X.509");
+        cf.generateCRL(new ByteArrayInputStream(data));
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLEngineImpl/SSLEngineBadBufferArrayAccess.java	Wed Jul 05 17:54:24 2017 +0200
@@ -0,0 +1,479 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * 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 7031830
+ * @summary bad_record_mac failure on TLSv1.2 enabled connection with SSLEngine
+ * @run main/othervm SSLEngineBadBufferArrayAccess
+ *
+ *     SunJSSE does not support dynamic system properties, no way to re-use
+ *     system properties in samevm/agentvm mode.
+ */
+
+/**
+ * A SSLSocket/SSLEngine interop test case.  This is not the way to
+ * code SSLEngine-based servers, but works for what we need to do here,
+ * which is to make sure that SSLEngine/SSLSockets can talk to each other.
+ * SSLEngines can use direct or indirect buffers, and different code
+ * is used to get at the buffer contents internally, so we test that here.
+ *
+ * The test creates one SSLSocket (client) and one SSLEngine (server).
+ * The SSLSocket talks to a raw ServerSocket, and the server code
+ * does the translation between byte [] and ByteBuffers that the SSLEngine
+ * can use.  The "transport" layer consists of a Socket Input/OutputStream
+ * and two byte buffers for the SSLEngines:  think of them
+ * as directly connected pipes.
+ *
+ * Again, this is a *very* simple example: real code will be much more
+ * involved.  For example, different threading and I/O models could be
+ * used, transport mechanisms could close unexpectedly, and so on.
+ *
+ * When this application runs, notice that several messages
+ * (wrap/unwrap) pass before any application data is consumed or
+ * produced.  (For more information, please see the SSL/TLS
+ * specifications.)  There may several steps for a successful handshake,
+ * so it's typical to see the following series of operations:
+ *
+ *      client          server          message
+ *      ======          ======          =======
+ *      write()         ...             ClientHello
+ *      ...             unwrap()        ClientHello
+ *      ...             wrap()          ServerHello/Certificate
+ *      read()         ...             ServerHello/Certificate
+ *      write()         ...             ClientKeyExchange
+ *      write()         ...             ChangeCipherSpec
+ *      write()         ...             Finished
+ *      ...             unwrap()        ClientKeyExchange
+ *      ...             unwrap()        ChangeCipherSpec
+ *      ...             unwrap()        Finished
+ *      ...             wrap()          ChangeCipherSpec
+ *      ...             wrap()          Finished
+ *      read()          ...             ChangeCipherSpec
+ *      read()          ...             Finished
+ *
+ * This particular bug had a problem where byte buffers backed by an
+ * array didn't offset correctly, and we got bad MAC errors.
+ */
+import javax.net.ssl.*;
+import javax.net.ssl.SSLEngineResult.*;
+import java.io.*;
+import java.net.*;
+import java.security.*;
+import java.nio.*;
+
+public class SSLEngineBadBufferArrayAccess {
+
+    /*
+     * Enables logging of the SSL/TLS operations.
+     */
+    private static boolean logging = true;
+
+    /*
+     * Enables the JSSE system debugging system property:
+     *
+     *     -Djavax.net.debug=all
+     *
+     * This gives a lot of low-level information about operations underway,
+     * including specific handshake messages, and might be best examined
+     * after gaining some familiarity with this application.
+     */
+    private static boolean debug = false;
+    private SSLContext sslc;
+    private SSLEngine serverEngine;     // server-side SSLEngine
+    private SSLSocket sslSocket;        // client-side socket
+    private ServerSocket serverSocket;  // server-side Socket, generates the...
+    private Socket socket;              // server-side socket that will read
+
+    private final byte[] serverMsg = "Hi there Client, I'm a Server".getBytes();
+    private final byte[] clientMsg = "Hello Server, I'm a Client".getBytes();
+
+    private ByteBuffer serverOut;       // write side of serverEngine
+    private ByteBuffer serverIn;        // read side of serverEngine
+
+    private volatile Exception clientException;
+    private volatile Exception serverException;
+
+    /*
+     * For data transport, this example uses local ByteBuffers.
+     */
+    private ByteBuffer cTOs;            // "reliable" transport client->server
+    private ByteBuffer sTOc;            // "reliable" transport server->client
+
+    /*
+     * The following is to set up the keystores/trust material.
+     */
+    private static final String pathToStores = "../../../../../../../etc/";
+    private static final String keyStoreFile = "keystore";
+    private static final String trustStoreFile = "truststore";
+    private static final String passwd = "passphrase";
+    private static String keyFilename =
+            System.getProperty("test.src", ".") + "/" + pathToStores
+            + "/" + keyStoreFile;
+    private static String trustFilename =
+            System.getProperty("test.src", ".") + "/" + pathToStores
+            + "/" + trustStoreFile;
+
+    /*
+     * Main entry point for this test.
+     */
+    public static void main(String args[]) throws Exception {
+        if (debug) {
+            System.setProperty("javax.net.debug", "all");
+        }
+
+        String [] protocols = new String [] {
+            "SSLv3", "TLSv1", "TLSv1.1", "TLSv1.2" };
+
+        for (String protocol : protocols) {
+            log("Testing " + protocol);
+            /*
+             * Run the tests with direct and indirect buffers.
+             */
+            SSLEngineBadBufferArrayAccess test =
+                new SSLEngineBadBufferArrayAccess(protocol);
+            test.runTest(true);
+            test.runTest(false);
+        }
+
+        System.out.println("Test Passed.");
+    }
+
+    /*
+     * Create an initialized SSLContext to use for these tests.
+     */
+    public SSLEngineBadBufferArrayAccess(String protocol) throws Exception {
+
+        KeyStore ks = KeyStore.getInstance("JKS");
+        KeyStore ts = KeyStore.getInstance("JKS");
+
+        char[] passphrase = "passphrase".toCharArray();
+
+        ks.load(new FileInputStream(keyFilename), passphrase);
+        ts.load(new FileInputStream(trustFilename), passphrase);
+
+        KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
+        kmf.init(ks, passphrase);
+
+        TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
+        tmf.init(ts);
+
+        SSLContext sslCtx = SSLContext.getInstance(protocol);
+
+        sslCtx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
+
+        sslc = sslCtx;
+    }
+
+    /*
+     * Run the test.
+     *
+     * Sit in a tight loop, with the server engine calling wrap/unwrap
+     * regardless of whether data is available or not.  We do this until
+     * we get the application data.  Then we shutdown and go to the next one.
+     *
+     * The main loop handles all of the I/O phases of the SSLEngine's
+     * lifetime:
+     *
+     *     initial handshaking
+     *     application data transfer
+     *     engine closing
+     *
+     * One could easily separate these phases into separate
+     * sections of code.
+     */
+    private void runTest(boolean direct) throws Exception {
+        boolean serverClose = direct;
+
+        serverSocket = new ServerSocket(0);
+        int port = serverSocket.getLocalPort();
+        Thread thread = createClientThread(port, serverClose);
+
+        socket = serverSocket.accept();
+        socket.setSoTimeout(500);
+        serverSocket.close();
+
+        createSSLEngine();
+        createBuffers(direct);
+
+        try {
+            boolean closed = false;
+
+            InputStream is = socket.getInputStream();
+            OutputStream os = socket.getOutputStream();
+
+            SSLEngineResult serverResult;   // results from last operation
+
+            /*
+             * Examining the SSLEngineResults could be much more involved,
+             * and may alter the overall flow of the application.
+             *
+             * For example, if we received a BUFFER_OVERFLOW when trying
+             * to write to the output pipe, we could reallocate a larger
+             * pipe, but instead we wait for the peer to drain it.
+             */
+            byte[] inbound = new byte[8192];
+            byte[] outbound = new byte[8192];
+
+            while (!isEngineClosed(serverEngine)) {
+                int len = 0;
+
+                // Inbound data
+                log("================");
+
+                // Read from the Client side.
+                try {
+                    len = is.read(inbound);
+                    if (len == -1) {
+                        throw new Exception("Unexpected EOF");
+                    }
+                    cTOs.put(inbound, 0, len);
+                } catch (SocketTimeoutException ste) {
+                    // swallow.  Nothing yet, probably waiting on us.
+                }
+
+                cTOs.flip();
+
+                serverResult = serverEngine.unwrap(cTOs, serverIn);
+                log("server unwrap: ", serverResult);
+                runDelegatedTasks(serverResult, serverEngine);
+                cTOs.compact();
+
+                // Outbound data
+                log("----");
+
+                serverResult = serverEngine.wrap(serverOut, sTOc);
+                log("server wrap: ", serverResult);
+                runDelegatedTasks(serverResult, serverEngine);
+
+                sTOc.flip();
+
+                if ((len = sTOc.remaining()) != 0) {
+                    sTOc.get(outbound, 0, len);
+                    os.write(outbound, 0, len);
+                    // Give the other side a chance to process
+                }
+
+                sTOc.compact();
+
+                if (!closed && (serverOut.remaining() == 0)) {
+                    closed = true;
+
+                    /*
+                     * We'll alternate initiatating the shutdown.
+                     * When the server initiates, it will take one more
+                     * loop, but tests the orderly shutdown.
+                     */
+                    if (serverClose) {
+                        serverEngine.closeOutbound();
+                    }
+                    serverIn.flip();
+
+                    /*
+                     * A sanity check to ensure we got what was sent.
+                     */
+                    if (serverIn.remaining() != clientMsg.length) {
+                        throw new Exception("Client:  Data length error");
+                    }
+
+                    for (int i = 0; i < clientMsg.length; i++) {
+                        if (clientMsg[i] != serverIn.get()) {
+                            throw new Exception("Client:  Data content error");
+                        }
+                    }
+                    serverIn.compact();
+                }
+            }
+            return;
+        } catch (Exception e) {
+            serverException = e;
+        } finally {
+            socket.close();
+
+            // Wait for the client to join up with us.
+            thread.join();
+            if (serverException != null) {
+                throw serverException;
+            }
+            if (clientException != null) {
+                throw clientException;
+            }
+        }
+    }
+
+    /*
+     * Create a client thread which does simple SSLSocket operations.
+     * We'll write and read one data packet.
+     */
+    private Thread createClientThread(final int port,
+            final boolean serverClose) throws Exception {
+
+        Thread t = new Thread("ClientThread") {
+
+            @Override
+            public void run() {
+                try {
+                    Thread.sleep(1000);  // Give server time to finish setup.
+
+                    sslSocket = (SSLSocket) sslc.getSocketFactory().
+                            createSocket("localhost", port);
+                    OutputStream os = sslSocket.getOutputStream();
+                    InputStream is = sslSocket.getInputStream();
+
+                    // write(byte[]) goes in one shot.
+                    os.write(clientMsg);
+
+                    byte[] inbound = new byte[2048];
+                    int pos = 0;
+
+                    int len;
+done:
+                    while ((len = is.read(inbound, pos, 2048 - pos)) != -1) {
+                        pos += len;
+                        // Let the client do the closing.
+                        if ((pos == serverMsg.length) && !serverClose) {
+                            sslSocket.close();
+                            break done;
+                        }
+                    }
+
+                    if (pos != serverMsg.length) {
+                        throw new Exception("Client:  Data length error");
+                    }
+
+                    for (int i = 0; i < serverMsg.length; i++) {
+                        if (inbound[i] != serverMsg[i]) {
+                            throw new Exception("Client:  Data content error");
+                        }
+                    }
+                } catch (Exception e) {
+                    clientException = e;
+                }
+            }
+        };
+        t.start();
+        return t;
+    }
+
+    /*
+     * Using the SSLContext created during object creation,
+     * create/configure the SSLEngines we'll use for this test.
+     */
+    private void createSSLEngine() throws Exception {
+        /*
+         * Configure the serverEngine to act as a server in the SSL/TLS
+         * handshake.
+         */
+        serverEngine = sslc.createSSLEngine();
+        serverEngine.setUseClientMode(false);
+        serverEngine.getNeedClientAuth();
+    }
+
+    /*
+     * Create and size the buffers appropriately.
+     */
+    private void createBuffers(boolean direct) {
+
+        SSLSession session = serverEngine.getSession();
+        int appBufferMax = session.getApplicationBufferSize();
+        int netBufferMax = session.getPacketBufferSize();
+
+        /*
+         * We'll make the input buffers a bit bigger than the max needed
+         * size, so that unwrap()s following a successful data transfer
+         * won't generate BUFFER_OVERFLOWS.
+         *
+         * We'll use a mix of direct and indirect ByteBuffers for
+         * tutorial purposes only.  In reality, only use direct
+         * ByteBuffers when they give a clear performance enhancement.
+         */
+        if (direct) {
+            serverIn = ByteBuffer.allocateDirect(appBufferMax + 50);
+            cTOs = ByteBuffer.allocateDirect(netBufferMax);
+            sTOc = ByteBuffer.allocateDirect(netBufferMax);
+        } else {
+            serverIn = ByteBuffer.allocate(appBufferMax + 50);
+            cTOs = ByteBuffer.allocate(netBufferMax);
+            sTOc = ByteBuffer.allocate(netBufferMax);
+        }
+
+        serverOut = ByteBuffer.wrap(serverMsg);
+    }
+
+    /*
+     * If the result indicates that we have outstanding tasks to do,
+     * go ahead and run them in this thread.
+     */
+    private static void runDelegatedTasks(SSLEngineResult result,
+            SSLEngine engine) throws Exception {
+
+        if (result.getHandshakeStatus() == HandshakeStatus.NEED_TASK) {
+            Runnable runnable;
+            while ((runnable = engine.getDelegatedTask()) != null) {
+                log("\trunning delegated task...");
+                runnable.run();
+            }
+            HandshakeStatus hsStatus = engine.getHandshakeStatus();
+            if (hsStatus == HandshakeStatus.NEED_TASK) {
+                throw new Exception(
+                        "handshake shouldn't need additional tasks");
+            }
+            log("\tnew HandshakeStatus: " + hsStatus);
+        }
+    }
+
+    private static boolean isEngineClosed(SSLEngine engine) {
+        return (engine.isOutboundDone() && engine.isInboundDone());
+    }
+
+    /*
+     * Logging code
+     */
+    private static boolean resultOnce = true;
+
+    private static void log(String str, SSLEngineResult result) {
+        if (!logging) {
+            return;
+        }
+        if (resultOnce) {
+            resultOnce = false;
+            System.out.println("The format of the SSLEngineResult is: \n"
+                    + "\t\"getStatus() / getHandshakeStatus()\" +\n"
+                    + "\t\"bytesConsumed() / bytesProduced()\"\n");
+        }
+        HandshakeStatus hsStatus = result.getHandshakeStatus();
+        log(str
+                + result.getStatus() + "/" + hsStatus + ", "
+                + result.bytesConsumed() + "/" + result.bytesProduced()
+                + " bytes");
+        if (hsStatus == HandshakeStatus.FINISHED) {
+            log("\t...ready for application data");
+        }
+    }
+
+    private static void log(String str) {
+        if (logging) {
+            System.out.println(str);
+        }
+    }
+}
--- a/jdk/test/sun/security/util/BigInt/BigIntEqualsHashCode.java	Wed Jul 05 17:53:51 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,46 +0,0 @@
-/*
- * Copyright (c) 1999, Oracle and/or its affiliates. All rights reserved.
- * 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
- * @author Gary Ellison
- * @bug 4170635
- * @summary Verify equals()/hashCode() contract honored
- */
-
-import java.io.*;
-import sun.security.util.*;
-
-
-public class BigIntEqualsHashCode {
-    public static void main(String[] args) throws Exception {
-        BigInt bi1 = new BigInt(12345678);
-        BigInt bi2 = new BigInt(12345678);
-
-        if ( (bi1.equals(bi2)) == (bi1.hashCode()==bi2.hashCode()) )
-            System.out.println("PASSED");
-        else
-            throw new Exception ("FAILED equals()/hashCode() contract");
-
-    }
-}
--- a/langtools/.hgtags	Wed Jul 05 17:53:51 2017 +0200
+++ b/langtools/.hgtags	Wed Jul 05 17:54:24 2017 +0200
@@ -132,3 +132,4 @@
 e8acc2d6c32f0c8321e642e1a86672a2e196a056 jdk8-b08
 b7a7e47c8d3daf7822abf7c37e5179ccbbf53008 jdk8-b09
 f6c783e18bdf4d46a0ab273868afebbf32600ff7 jdk8-b10
+4bf01f1c4e3464f378959d10f3983a0469181d94 jdk8-b11
--- a/langtools/src/share/classes/com/sun/tools/apt/main/AptJavaCompiler.java	Wed Jul 05 17:53:51 2017 +0200
+++ b/langtools/src/share/classes/com/sun/tools/apt/main/AptJavaCompiler.java	Wed Jul 05 17:54:24 2017 +0200
@@ -42,7 +42,6 @@
 import com.sun.tools.apt.comp.*;
 import com.sun.tools.apt.util.Bark;
 import com.sun.mirror.apt.AnnotationProcessorFactory;
-import com.sun.tools.javac.parser.DocCommentScanner;
 
 /**
  *  <p><b>This is NOT part of any supported API.
--- a/langtools/src/share/classes/com/sun/tools/apt/main/Main.java	Wed Jul 05 17:53:51 2017 +0200
+++ b/langtools/src/share/classes/com/sun/tools/apt/main/Main.java	Wed Jul 05 17:54:24 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -56,7 +56,7 @@
 import com.sun.tools.apt.util.Bark;
 import com.sun.mirror.apt.AnnotationProcessorFactory;
 
-import static com.sun.tools.javac.file.Paths.pathToURLs;
+import static com.sun.tools.javac.file.Locations.pathToURLs;
 
 /** This class provides a commandline interface to the apt build-time
  *  tool.
--- a/langtools/src/share/classes/com/sun/tools/javac/code/Printer.java	Wed Jul 05 17:53:51 2017 +0200
+++ b/langtools/src/share/classes/com/sun/tools/javac/code/Printer.java	Wed Jul 05 17:54:24 2017 +0200
@@ -258,7 +258,7 @@
             ClassType norm = (ClassType) t.tsym.type;
             if (norm == null) {
                 s = localize(locale, "compiler.misc.anonymous.class", (Object) null);
-            } else if (norm.interfaces_field.nonEmpty()) {
+            } else if (norm.interfaces_field != null && norm.interfaces_field.nonEmpty()) {
                 s = localize(locale, "compiler.misc.anonymous.class",
                         visit(norm.interfaces_field.head, locale));
             } else {
--- a/langtools/src/share/classes/com/sun/tools/javac/code/Types.java	Wed Jul 05 17:53:51 2017 +0200
+++ b/langtools/src/share/classes/com/sun/tools/javac/code/Types.java	Wed Jul 05 17:54:24 2017 +0200
@@ -278,7 +278,6 @@
         boolean tPrimitive = t.isPrimitive();
         boolean sPrimitive = s.isPrimitive();
         if (tPrimitive == sPrimitive) {
-            checkUnsafeVarargsConversion(t, s, warn);
             return isSubtypeUnchecked(t, s, warn);
         }
         if (!allowBoxing) return false;
@@ -286,27 +285,6 @@
             ? isSubtype(boxedClass(t).type, s)
             : isSubtype(unboxedType(t), s);
     }
-    //where
-    private void checkUnsafeVarargsConversion(Type t, Type s, Warner warn) {
-        if (t.tag != ARRAY || isReifiable(t)) return;
-        ArrayType from = (ArrayType)t;
-        boolean shouldWarn = false;
-        switch (s.tag) {
-            case ARRAY:
-                ArrayType to = (ArrayType)s;
-                shouldWarn = from.isVarargs() &&
-                        !to.isVarargs() &&
-                        !isReifiable(from);
-                break;
-            case CLASS:
-                shouldWarn = from.isVarargs() &&
-                        isSubtype(from, s);
-                break;
-        }
-        if (shouldWarn) {
-            warn.warn(LintCategory.VARARGS);
-        }
-    }
 
     /**
      * Is t a subtype of or convertiable via boxing/unboxing
@@ -328,42 +306,63 @@
      * Is t an unchecked subtype of s?
      */
     public boolean isSubtypeUnchecked(Type t, Type s, Warner warn) {
-        if (t.tag == ARRAY && s.tag == ARRAY) {
-            if (((ArrayType)t).elemtype.tag <= lastBaseTag) {
-                return isSameType(elemtype(t), elemtype(s));
-            } else {
-                ArrayType from = (ArrayType)t;
-                ArrayType to = (ArrayType)s;
-                if (from.isVarargs() &&
-                        !to.isVarargs() &&
-                        !isReifiable(from)) {
-                    warn.warn(LintCategory.VARARGS);
-                }
-                return isSubtypeUnchecked(elemtype(t), elemtype(s), warn);
-            }
-        } else if (isSubtype(t, s)) {
-            return true;
+        boolean result = isSubtypeUncheckedInternal(t, s, warn);
+        if (result) {
+            checkUnsafeVarargsConversion(t, s, warn);
         }
-        else if (t.tag == TYPEVAR) {
-            return isSubtypeUnchecked(t.getUpperBound(), s, warn);
-        }
-        else if (s.tag == UNDETVAR) {
-            UndetVar uv = (UndetVar)s;
-            if (uv.inst != null)
-                return isSubtypeUnchecked(t, uv.inst, warn);
-        }
-        else if (!s.isRaw()) {
-            Type t2 = asSuper(t, s.tsym);
-            if (t2 != null && t2.isRaw()) {
-                if (isReifiable(s))
-                    warn.silentWarn(LintCategory.UNCHECKED);
-                else
-                    warn.warn(LintCategory.UNCHECKED);
+        return result;
+    }
+    //where
+        private boolean isSubtypeUncheckedInternal(Type t, Type s, Warner warn) {
+            if (t.tag == ARRAY && s.tag == ARRAY) {
+                if (((ArrayType)t).elemtype.tag <= lastBaseTag) {
+                    return isSameType(elemtype(t), elemtype(s));
+                } else {
+                    return isSubtypeUnchecked(elemtype(t), elemtype(s), warn);
+                }
+            } else if (isSubtype(t, s)) {
                 return true;
             }
+            else if (t.tag == TYPEVAR) {
+                return isSubtypeUnchecked(t.getUpperBound(), s, warn);
+            }
+            else if (s.tag == UNDETVAR) {
+                UndetVar uv = (UndetVar)s;
+                if (uv.inst != null)
+                    return isSubtypeUnchecked(t, uv.inst, warn);
+            }
+            else if (!s.isRaw()) {
+                Type t2 = asSuper(t, s.tsym);
+                if (t2 != null && t2.isRaw()) {
+                    if (isReifiable(s))
+                        warn.silentWarn(LintCategory.UNCHECKED);
+                    else
+                        warn.warn(LintCategory.UNCHECKED);
+                    return true;
+                }
+            }
+            return false;
         }
-        return false;
-    }
+
+        private void checkUnsafeVarargsConversion(Type t, Type s, Warner warn) {
+            if (t.tag != ARRAY || isReifiable(t)) return;
+            ArrayType from = (ArrayType)t;
+            boolean shouldWarn = false;
+            switch (s.tag) {
+                case ARRAY:
+                    ArrayType to = (ArrayType)s;
+                    shouldWarn = from.isVarargs() &&
+                            !to.isVarargs() &&
+                            !isReifiable(from);
+                    break;
+                case CLASS:
+                    shouldWarn = from.isVarargs();
+                    break;
+            }
+            if (shouldWarn) {
+                warn.warn(LintCategory.VARARGS);
+            }
+        }
 
     /**
      * Is t a subtype of s?<br>
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/Infer.java	Wed Jul 05 17:53:51 2017 +0200
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Infer.java	Wed Jul 05 17:54:24 2017 +0200
@@ -34,7 +34,8 @@
 import com.sun.tools.javac.code.Type.*;
 import com.sun.tools.javac.code.Type.ForAll.ConstraintKind;
 import com.sun.tools.javac.code.Symbol.*;
-import com.sun.tools.javac.util.JCDiagnostic;
+import com.sun.tools.javac.comp.Resolve.VerboseResolutionMode;
+import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
 
 import static com.sun.tools.javac.code.TypeTags.*;
 
@@ -56,6 +57,7 @@
     Types types;
     Check chk;
     Resolve rs;
+    Log log;
     JCDiagnostic.Factory diags;
 
     public static Infer instance(Context context) {
@@ -70,6 +72,7 @@
         syms = Symtab.instance(context);
         types = Types.instance(context);
         rs = Resolve.instance(context);
+        log = Log.instance(context);
         chk = Check.instance(context);
         diags = JCDiagnostic.Factory.instance(context);
         ambiguousNoInstanceException =
@@ -460,7 +463,7 @@
             // quantify result type with them
             final List<Type> inferredTypes = insttypes.toList();
             final List<Type> all_tvars = tvars; //this is the wrong tvars
-            return new UninferredMethodType(mt, restvars.toList()) {
+            return new UninferredMethodType(env.tree.pos(), msym, mt, restvars.toList()) {
                 @Override
                 List<Type> getConstraints(TypeVar tv, ConstraintKind ck) {
                     for (Type t : restundet.toList()) {
@@ -502,13 +505,17 @@
          * type - when the return type is instantiated (see Infer.instantiateExpr)
          * the underlying method type is also updated.
          */
-        static abstract class UninferredMethodType extends DelegatedType {
+        abstract class UninferredMethodType extends DelegatedType {
 
             final List<Type> tvars;
+            final Symbol msym;
+            final DiagnosticPosition pos;
 
-            public UninferredMethodType(MethodType mtype, List<Type> tvars) {
+            public UninferredMethodType(DiagnosticPosition pos, Symbol msym, MethodType mtype, List<Type> tvars) {
                 super(METHOD, new MethodType(mtype.argtypes, null, mtype.thrown, mtype.tsym));
                 this.tvars = tvars;
+                this.msym = msym;
+                this.pos = pos;
                 asMethodType().restype = new UninferredReturnType(tvars, mtype.restype);
             }
 
@@ -543,6 +550,9 @@
                 public Type inst(List<Type> actuals, Types types) {
                     Type newRestype = super.inst(actuals, types);
                     instantiateReturnType(newRestype, actuals, types);
+                    if (rs.verboseResolutionMode.contains(VerboseResolutionMode.DEFERRED_INST)) {
+                        log.note(pos, "deferred.method.inst", msym, UninferredMethodType.this.qtype, newRestype);
+                    }
                     return newRestype;
                 }
                 @Override
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/Resolve.java	Wed Jul 05 17:53:51 2017 +0200
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Resolve.java	Wed Jul 05 17:54:24 2017 +0200
@@ -25,29 +25,33 @@
 
 package com.sun.tools.javac.comp;
 
-import com.sun.tools.javac.util.*;
-import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
+import com.sun.tools.javac.api.Formattable.LocalizedString;
 import com.sun.tools.javac.code.*;
+import com.sun.tools.javac.code.Type.*;
+import com.sun.tools.javac.code.Symbol.*;
 import com.sun.tools.javac.jvm.*;
 import com.sun.tools.javac.tree.*;
-import com.sun.tools.javac.api.Formattable.LocalizedString;
-import static com.sun.tools.javac.comp.Resolve.MethodResolutionPhase.*;
+import com.sun.tools.javac.tree.JCTree.*;
+import com.sun.tools.javac.util.*;
+import com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag;
+import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
+import com.sun.tools.javac.util.JCDiagnostic.DiagnosticType;
 
-import com.sun.tools.javac.code.Type.*;
-import com.sun.tools.javac.code.Symbol.*;
-import com.sun.tools.javac.tree.JCTree.*;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.EnumSet;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Set;
+
+import javax.lang.model.element.ElementVisitor;
 
 import static com.sun.tools.javac.code.Flags.*;
 import static com.sun.tools.javac.code.Kinds.*;
 import static com.sun.tools.javac.code.TypeTags.*;
-import com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag;
-import com.sun.tools.javac.util.JCDiagnostic.DiagnosticType;
-import javax.lang.model.element.ElementVisitor;
-
-import java.util.Map;
-import java.util.Set;
-import java.util.HashMap;
-import java.util.HashSet;
+import static com.sun.tools.javac.comp.Resolve.MethodResolutionPhase.*;
 
 /** Helper class for name resolution, used mostly by the attribution phase.
  *
@@ -73,9 +77,45 @@
     public final boolean varargsEnabled; // = source.allowVarargs();
     public final boolean allowMethodHandles;
     private final boolean debugResolve;
+    final EnumSet<VerboseResolutionMode> verboseResolutionMode;
 
     Scope polymorphicSignatureScope;
 
+    enum VerboseResolutionMode {
+        SUCCESS("success"),
+        FAILURE("failure"),
+        APPLICABLE("applicable"),
+        INAPPLICABLE("inapplicable"),
+        DEFERRED_INST("deferred-inference"),
+        PREDEF("predef"),
+        OBJECT_INIT("object-init"),
+        INTERNAL("internal");
+
+        String opt;
+
+        private VerboseResolutionMode(String opt) {
+            this.opt = opt;
+        }
+
+        static EnumSet<VerboseResolutionMode> getVerboseResolutionMode(Options opts) {
+            String s = opts.get("verboseResolution");
+            EnumSet<VerboseResolutionMode> res = EnumSet.noneOf(VerboseResolutionMode.class);
+            if (s == null) return res;
+            if (s.contains("all")) {
+                res = EnumSet.allOf(VerboseResolutionMode.class);
+            }
+            Collection<String> args = Arrays.asList(s.split(","));
+            for (VerboseResolutionMode mode : values()) {
+                if (args.contains(mode.opt)) {
+                    res.add(mode);
+                } else if (args.contains("-" + mode.opt)) {
+                    res.remove(mode);
+                }
+            }
+            return res;
+        }
+    }
+
     public static Resolve instance(Context context) {
         Resolve instance = context.get(resolveKey);
         if (instance == null)
@@ -111,6 +151,7 @@
         varargsEnabled = source.allowVarargs();
         Options options = Options.instance(context);
         debugResolve = options.isSet("debugresolve");
+        verboseResolutionMode = VerboseResolutionMode.getVerboseResolutionMode(options);
         Target target = Target.instance(context);
         allowMethodHandles = target.hasMethodHandles();
         polymorphicSignatureScope = new Scope(syms.noSymbol);
@@ -684,13 +725,16 @@
         if (!sym.isInheritedIn(site.tsym, types)) return bestSoFar;
         Assert.check(sym.kind < AMBIGUOUS);
         try {
-            rawInstantiate(env, site, sym, argtypes, typeargtypes,
+            Type mt = rawInstantiate(env, site, sym, argtypes, typeargtypes,
                                allowBoxing, useVarargs, Warner.noWarnings);
+            if (!operator) addVerboseApplicableCandidateDiag(sym ,mt);
         } catch (InapplicableMethodException ex) {
+            if (!operator) addVerboseInapplicableCandidateDiag(sym, ex.getDiagnostic());
             switch (bestSoFar.kind) {
             case ABSENT_MTH:
                 return wrongMethod.setWrongSym(sym, ex.getDiagnostic());
             case WRONG_MTH:
+                if (operator) return bestSoFar;
                 wrongMethods.addCandidate(currentStep, wrongMethod.sym, wrongMethod.explanation);
             case WRONG_MTHS:
                 return wrongMethods.addCandidate(currentStep, sym, ex.getDiagnostic());
@@ -708,6 +752,34 @@
             : mostSpecific(sym, bestSoFar, env, site,
                            allowBoxing && operator, useVarargs);
     }
+    //where
+        void addVerboseApplicableCandidateDiag(Symbol sym, Type inst) {
+            if (!verboseResolutionMode.contains(VerboseResolutionMode.APPLICABLE))
+                return;
+
+            JCDiagnostic subDiag = null;
+            if (inst.getReturnType().tag == FORALL) {
+                Type diagType = types.createMethodTypeWithReturn(inst.asMethodType(),
+                                                                ((ForAll)inst.getReturnType()).qtype);
+                subDiag = diags.fragment("partial.inst.sig", diagType);
+            } else if (sym.type.tag == FORALL) {
+                subDiag = diags.fragment("full.inst.sig", inst.asMethodType());
+            }
+
+            String key = subDiag == null ?
+                    "applicable.method.found" :
+                    "applicable.method.found.1";
+
+            verboseResolutionCandidateDiags.put(sym,
+                    diags.fragment(key, verboseResolutionCandidateDiags.size(), sym, subDiag));
+        }
+
+        void addVerboseInapplicableCandidateDiag(Symbol sym, JCDiagnostic subDiag) {
+            if (!verboseResolutionMode.contains(VerboseResolutionMode.INAPPLICABLE))
+                return;
+            verboseResolutionCandidateDiags.put(sym,
+                    diags.fragment("not.applicable.method.found", verboseResolutionCandidateDiags.size(), sym, subDiag));
+        }
 
     /* Return the most specific of the two methods for a call,
      *  given that both are accessible and applicable.
@@ -905,8 +977,9 @@
                       boolean allowBoxing,
                       boolean useVarargs,
                       boolean operator) {
+        verboseResolutionCandidateDiags.clear();
         Symbol bestSoFar = methodNotFound;
-        return findMethod(env,
+        bestSoFar = findMethod(env,
                           site,
                           name,
                           argtypes,
@@ -918,6 +991,8 @@
                           useVarargs,
                           operator,
                           new HashSet<TypeSymbol>());
+        reportVerboseResolutionDiagnostic(env.tree.pos(), name, site, argtypes, typeargtypes, bestSoFar);
+        return bestSoFar;
     }
     // where
     private Symbol findMethod(Env<AttrContext> env,
@@ -975,6 +1050,37 @@
         }
         return bestSoFar;
     }
+    //where
+        void reportVerboseResolutionDiagnostic(DiagnosticPosition dpos, Name name, Type site, List<Type> argtypes, List<Type> typeargtypes, Symbol bestSoFar) {
+            boolean success = bestSoFar.kind < ERRONEOUS;
+
+            if (success && !verboseResolutionMode.contains(VerboseResolutionMode.SUCCESS)) {
+                return;
+            } else if (!success && !verboseResolutionMode.contains(VerboseResolutionMode.FAILURE)) {
+                return;
+            }
+
+            if (bestSoFar.name == names.init &&
+                    bestSoFar.owner == syms.objectType.tsym &&
+                    !verboseResolutionMode.contains(VerboseResolutionMode.OBJECT_INIT)) {
+                return; //skip diags for Object constructor resolution
+            } else if (site == syms.predefClass.type && !verboseResolutionMode.contains(VerboseResolutionMode.PREDEF)) {
+                return; //skip spurious diags for predef symbols (i.e. operators)
+            } else if (internalResolution && !verboseResolutionMode.contains(VerboseResolutionMode.INTERNAL)) {
+                return;
+            }
+
+            int pos = 0;
+            for (Symbol s : verboseResolutionCandidateDiags.keySet()) {
+                if (s == bestSoFar) break;
+                pos++;
+            }
+            String key = success ? "verbose.resolve.multi" : "verbose.resolve.multi.1";
+            JCDiagnostic main = diags.note(log.currentSource(), dpos, key, name, site.tsym, pos, currentStep,
+                    methodArguments(argtypes), methodArguments(typeargtypes));
+            JCDiagnostic d = new JCDiagnostic.MultilineDiagnostic(main, List.from(verboseResolutionCandidateDiags.values().toArray(new JCDiagnostic[verboseResolutionCandidateDiags.size()])));
+            log.report(d);
+        }
 
     /** Find unqualified method matching given name, type and value arguments.
      *  @param env       The current environment.
@@ -1543,12 +1649,19 @@
                                         Type site, Name name,
                                         List<Type> argtypes,
                                         List<Type> typeargtypes) {
-        Symbol sym = resolveQualifiedMethod(
-            pos, env, site.tsym, site, name, argtypes, typeargtypes);
-        if (sym.kind == MTH) return (MethodSymbol)sym;
-        else throw new FatalError(
-                 diags.fragment("fatal.err.cant.locate.meth",
-                                name));
+        boolean prevInternal = internalResolution;
+        try {
+            internalResolution = true;
+            Symbol sym = resolveQualifiedMethod(
+                pos, env, site.tsym, site, name, argtypes, typeargtypes);
+            if (sym.kind == MTH) return (MethodSymbol)sym;
+            else throw new FatalError(
+                     diags.fragment("fatal.err.cant.locate.meth",
+                                    name));
+        }
+        finally {
+            internalResolution = prevInternal;
+        }
     }
 
     /** Resolve constructor.
@@ -1685,6 +1798,7 @@
      */
     Symbol resolveOperator(DiagnosticPosition pos, int optag,
                            Env<AttrContext> env, List<Type> argtypes) {
+        startResolution();
         Name name = treeinfo.operatorName(optag);
         Symbol sym = findMethod(env, syms.predefClass.type, name, argtypes,
                                 null, false, false, true);
@@ -1828,7 +1942,7 @@
     private final LocalizedString noArgs = new LocalizedString("compiler.misc.no.args");
 
     public Object methodArguments(List<Type> argtypes) {
-        return argtypes.isEmpty() ? noArgs : argtypes;
+        return argtypes == null || argtypes.isEmpty() ? noArgs : argtypes;
     }
 
     /**
@@ -2375,10 +2489,15 @@
     private Map<MethodResolutionPhase, Symbol> methodResolutionCache =
         new HashMap<MethodResolutionPhase, Symbol>(MethodResolutionPhase.values().length);
 
+    private Map<Symbol, JCDiagnostic> verboseResolutionCandidateDiags =
+        new LinkedHashMap<Symbol, JCDiagnostic>();
+
     final List<MethodResolutionPhase> methodResolutionSteps = List.of(BASIC, BOX, VARARITY);
 
     private MethodResolutionPhase currentStep = null;
 
+    private boolean internalResolution = false;
+
     private MethodResolutionPhase firstErroneousResolutionPhase() {
         MethodResolutionPhase bestSoFar = BASIC;
         Symbol sym = methodNotFound;
--- a/langtools/src/share/classes/com/sun/tools/javac/file/JavacFileManager.java	Wed Jul 05 17:53:51 2017 +0200
+++ b/langtools/src/share/classes/com/sun/tools/javac/file/JavacFileManager.java	Wed Jul 05 17:54:24 2017 +0200
@@ -25,7 +25,6 @@
 
 package com.sun.tools.javac.file;
 
-import java.util.Comparator;
 import java.io.ByteArrayOutputStream;
 import java.io.File;
 import java.io.FileNotFoundException;
@@ -41,6 +40,7 @@
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
+import java.util.Comparator;
 import java.util.EnumSet;
 import java.util.HashMap;
 import java.util.Iterator;
@@ -56,14 +56,12 @@
 
 import com.sun.tools.javac.file.RelativePath.RelativeFile;
 import com.sun.tools.javac.file.RelativePath.RelativeDirectory;
-import com.sun.tools.javac.main.OptionName;
 import com.sun.tools.javac.util.BaseFileManager;
 import com.sun.tools.javac.util.Context;
 import com.sun.tools.javac.util.List;
 import com.sun.tools.javac.util.ListBuffer;
 
 import static javax.tools.StandardLocation.*;
-import static com.sun.tools.javac.main.OptionName.*;
 
 /**
  * This class provides access to the source, class and other files
@@ -83,32 +81,14 @@
             return buffer.toString().toCharArray();
     }
 
-    /** Encapsulates knowledge of paths
-     */
-    private Paths paths;
-
     private FSInfo fsInfo;
 
     private boolean contextUseOptimizedZip;
     private ZipFileIndexCache zipFileIndexCache;
 
-    private final File uninited = new File("U N I N I T E D");
-
     private final Set<JavaFileObject.Kind> sourceOrClass =
         EnumSet.of(JavaFileObject.Kind.SOURCE, JavaFileObject.Kind.CLASS);
 
-    /** The standard output directory, primarily used for classes.
-     *  Initialized by the "-d" option.
-     *  If classOutDir = null, files are written into same directory as the sources
-     *  they were generated from.
-     */
-    private File classOutDir = uninited;
-
-    /** The output directory, used when generating sources while processing annotations.
-     *  Initialized by the "-s" option.
-     */
-    private File sourceOutDir = uninited;
-
     protected boolean mmappedIO;
     protected boolean ignoreSymbolFile;
 
@@ -154,13 +134,6 @@
     @Override
     public void setContext(Context context) {
         super.setContext(context);
-        if (paths == null) {
-            paths = Paths.instance(context);
-        } else {
-            // Reuse the Paths object as it stores the locations that
-            // have been set with setLocation, etc.
-            paths.setContext(context);
-        }
 
         fsInfo = FSInfo.instance(context);
 
@@ -179,7 +152,7 @@
 
     @Override
     public boolean isDefaultBootClassPath() {
-        return paths.isDefaultBootClassPath();
+        return locations.isDefaultBootClassPath();
     }
 
     public JavaFileObject getFileForInput(String name) {
@@ -493,7 +466,7 @@
      */
     private Archive openArchive(File zipFileName, boolean useOptimizedZip) throws IOException {
         File origZipFileName = zipFileName;
-        if (!ignoreSymbolFile && paths.isDefaultBootClassPathRtJar(zipFileName)) {
+        if (!ignoreSymbolFile && locations.isDefaultBootClassPathRtJar(zipFileName)) {
             File file = zipFileName.getParentFile().getParentFile(); // ${java.home}
             if (new File(file.getName()).equals(new File("jre")))
                 file = file.getParentFile();
@@ -780,7 +753,7 @@
         } else if (location == SOURCE_OUTPUT) {
             dir = (getSourceOutDir() != null ? getSourceOutDir() : getClassOutDir());
         } else {
-            Iterable<? extends File> path = paths.getPathForLocation(location);
+            Iterable<? extends File> path = locations.getLocation(location);
             dir = null;
             for (File f: path) {
                 dir = f;
@@ -815,64 +788,20 @@
         throws IOException
     {
         nullCheck(location);
-        paths.lazy();
-
-        final File dir = location.isOutputLocation() ? getOutputDirectory(path) : null;
-
-        if (location == CLASS_OUTPUT)
-            classOutDir = getOutputLocation(dir, D);
-        else if (location == SOURCE_OUTPUT)
-            sourceOutDir = getOutputLocation(dir, S);
-        else
-            paths.setPathForLocation(location, path);
-    }
-    // where
-        private File getOutputDirectory(Iterable<? extends File> path) throws IOException {
-            if (path == null)
-                return null;
-            Iterator<? extends File> pathIter = path.iterator();
-            if (!pathIter.hasNext())
-                throw new IllegalArgumentException("empty path for directory");
-            File dir = pathIter.next();
-            if (pathIter.hasNext())
-                throw new IllegalArgumentException("path too long for directory");
-            if (!dir.exists())
-                throw new FileNotFoundException(dir + ": does not exist");
-            else if (!dir.isDirectory())
-                throw new IOException(dir + ": not a directory");
-            return dir;
-        }
-
-    private File getOutputLocation(File dir, OptionName defaultOptionName) {
-        if (dir != null)
-            return dir;
-        String arg = options.get(defaultOptionName);
-        if (arg == null)
-            return null;
-        return new File(arg);
+        locations.setLocation(location, path);
     }
 
     public Iterable<? extends File> getLocation(Location location) {
         nullCheck(location);
-        paths.lazy();
-        if (location == CLASS_OUTPUT) {
-            return (getClassOutDir() == null ? null : List.of(getClassOutDir()));
-        } else if (location == SOURCE_OUTPUT) {
-            return (getSourceOutDir() == null ? null : List.of(getSourceOutDir()));
-        } else
-            return paths.getPathForLocation(location);
+        return locations.getLocation(location);
     }
 
     private File getClassOutDir() {
-        if (classOutDir == uninited)
-            classOutDir = getOutputLocation(null, D);
-        return classOutDir;
+        return locations.getOutputLocation(CLASS_OUTPUT);
     }
 
     private File getSourceOutDir() {
-        if (sourceOutDir == uninited)
-            sourceOutDir = getOutputLocation(null, S);
-        return sourceOutDir;
+        return locations.getOutputLocation(SOURCE_OUTPUT);
     }
 
     /**
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/share/classes/com/sun/tools/javac/file/Locations.java	Wed Jul 05 17:54:24 2017 +0200
@@ -0,0 +1,771 @@
+/*
+ * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * 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.file;
+
+import java.io.FileNotFoundException;
+import java.util.Iterator;
+import java.io.File;
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.EnumMap;
+import java.util.EnumSet;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedHashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.StringTokenizer;
+import java.util.zip.ZipFile;
+import javax.tools.JavaFileManager.Location;
+import javax.tools.StandardLocation;
+
+import com.sun.tools.javac.code.Lint;
+import com.sun.tools.javac.main.OptionName;
+import com.sun.tools.javac.util.ListBuffer;
+import com.sun.tools.javac.util.Log;
+import com.sun.tools.javac.util.Options;
+
+import javax.tools.JavaFileManager;
+import static javax.tools.StandardLocation.*;
+import static com.sun.tools.javac.main.OptionName.*;
+
+/** This class converts command line arguments, environment variables
+ *  and system properties (in File.pathSeparator-separated String form)
+ *  into a boot class path, user class path, and source path (in
+ *  Collection<String> form).
+ *
+ *  <p><b>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.</b>
+ */
+public class Locations {
+
+    /** The log to use for warning output */
+    private Log log;
+
+    /** Collection of command-line options */
+    private Options options;
+
+    /** Handler for -Xlint options */
+    private Lint lint;
+
+    /** Access to (possibly cached) file info */
+    private FSInfo fsInfo;
+
+    /** Whether to warn about non-existent path elements */
+    private boolean warn;
+
+    // TODO: remove need for this
+    private boolean inited = false; // TODO? caching bad?
+
+    public Locations() {
+        initHandlers();
+    }
+
+    public void update(Log log, Options options, Lint lint, FSInfo fsInfo) {
+        this.log = log;
+        this.options = options;
+        this.lint = lint;
+        this.fsInfo = fsInfo;
+    }
+
+    public Collection<File> bootClassPath() {
+        return getLocation(PLATFORM_CLASS_PATH);
+    }
+
+    public boolean isDefaultBootClassPath() {
+        BootClassPathLocationHandler h =
+                (BootClassPathLocationHandler) getHandler(PLATFORM_CLASS_PATH);
+        return h.isDefault();
+    }
+
+    boolean isDefaultBootClassPathRtJar(File file) {
+        BootClassPathLocationHandler h =
+                (BootClassPathLocationHandler) getHandler(PLATFORM_CLASS_PATH);
+        return h.isDefaultRtJar(file);
+    }
+
+    public Collection<File> userClassPath() {
+        return getLocation(CLASS_PATH);
+    }
+
+    public Collection<File> sourcePath() {
+        Collection<File> p = getLocation(SOURCE_PATH);
+        // TODO: this should be handled by the LocationHandler
+        return p == null || p.isEmpty() ? null : p;
+    }
+
+    /**
+     * Split a path into its elements. Empty path elements will be ignored.
+     * @param path The path to be split
+     * @return The elements of the path
+     */
+    private static Iterable<File> getPathEntries(String path) {
+        return getPathEntries(path, null);
+    }
+
+    /**
+     * Split a path into its elements. If emptyPathDefault is not null, all
+     * empty elements in the path, including empty elements at either end of
+     * the path, will be replaced with the value of emptyPathDefault.
+     * @param path The path to be split
+     * @param emptyPathDefault The value to substitute for empty path elements,
+     *  or null, to ignore empty path elements
+     * @return The elements of the path
+     */
+    private static Iterable<File> getPathEntries(String path, File emptyPathDefault) {
+        ListBuffer<File> entries = new ListBuffer<File>();
+        int start = 0;
+        while (start <= path.length()) {
+            int sep = path.indexOf(File.pathSeparatorChar, start);
+            if (sep == -1)
+                sep = path.length();
+            if (start < sep)
+                entries.add(new File(path.substring(start, sep)));
+            else if (emptyPathDefault != null)
+                entries.add(emptyPathDefault);
+            start = sep + 1;
+        }
+        return entries;
+    }
+
+    /**
+     * Utility class to help evaluate a path option.
+     * Duplicate entries are ignored, jar class paths can be expanded.
+     */
+    private class Path extends LinkedHashSet<File> {
+        private static final long serialVersionUID = 0;
+
+        private boolean expandJarClassPaths = false;
+        private Set<File> canonicalValues = new HashSet<File>();
+
+        public Path expandJarClassPaths(boolean x) {
+            expandJarClassPaths = x;
+            return this;
+        }
+
+        /** What to use when path element is the empty string */
+        private File emptyPathDefault = null;
+
+        public Path emptyPathDefault(File x) {
+            emptyPathDefault = x;
+            return this;
+        }
+
+        public Path() { super(); }
+
+        public Path addDirectories(String dirs, boolean warn) {
+            boolean prev = expandJarClassPaths;
+            expandJarClassPaths = true;
+            try {
+                if (dirs != null)
+                    for (File dir : getPathEntries(dirs))
+                        addDirectory(dir, warn);
+                return this;
+            } finally {
+                expandJarClassPaths = prev;
+            }
+        }
+
+        public Path addDirectories(String dirs) {
+            return addDirectories(dirs, warn);
+        }
+
+        private void addDirectory(File dir, boolean warn) {
+            if (!dir.isDirectory()) {
+                if (warn)
+                    log.warning(Lint.LintCategory.PATH,
+                            "dir.path.element.not.found", dir);
+                return;
+            }
+
+            File[] files = dir.listFiles();
+            if (files == null)
+                return;
+
+            for (File direntry : files) {
+                if (isArchive(direntry))
+                    addFile(direntry, warn);
+            }
+        }
+
+        public Path addFiles(String files, boolean warn) {
+            if (files != null) {
+                addFiles(getPathEntries(files, emptyPathDefault), warn);
+            }
+            return this;
+        }
+
+        public Path addFiles(String files) {
+            return addFiles(files, warn);
+        }
+
+        public Path addFiles(Iterable<? extends File> files, boolean warn) {
+            if (files != null) {
+                for (File file: files)
+                    addFile(file, warn);
+            }
+            return this;
+        }
+
+        public Path addFiles(Iterable<? extends File> files) {
+            return addFiles(files, warn);
+        }
+
+        public void addFile(File file, boolean warn) {
+            if (contains(file)) {
+                // discard duplicates
+                return;
+            }
+
+            if (! fsInfo.exists(file)) {
+                /* No such file or directory exists */
+                if (warn) {
+                    log.warning(Lint.LintCategory.PATH,
+                            "path.element.not.found", file);
+                }
+                super.add(file);
+                return;
+            }
+
+            File canonFile = fsInfo.getCanonicalFile(file);
+            if (canonicalValues.contains(canonFile)) {
+                /* Discard duplicates and avoid infinite recursion */
+                return;
+            }
+
+            if (fsInfo.isFile(file)) {
+                /* File is an ordinary file. */
+                if (!isArchive(file)) {
+                    /* Not a recognized extension; open it to see if
+                     it looks like a valid zip file. */
+                    try {
+                        ZipFile z = new ZipFile(file);
+                        z.close();
+                        if (warn) {
+                            log.warning(Lint.LintCategory.PATH,
+                                    "unexpected.archive.file", file);
+                        }
+                    } catch (IOException e) {
+                        // FIXME: include e.getLocalizedMessage in warning
+                        if (warn) {
+                            log.warning(Lint.LintCategory.PATH,
+                                    "invalid.archive.file", file);
+                        }
+                        return;
+                    }
+                }
+            }
+
+            /* Now what we have left is either a directory or a file name
+               conforming to archive naming convention */
+            super.add(file);
+            canonicalValues.add(canonFile);
+
+            if (expandJarClassPaths && fsInfo.isFile(file))
+                addJarClassPath(file, warn);
+        }
+
+        // Adds referenced classpath elements from a jar's Class-Path
+        // Manifest entry.  In some future release, we may want to
+        // update this code to recognize URLs rather than simple
+        // filenames, but if we do, we should redo all path-related code.
+        private void addJarClassPath(File jarFile, boolean warn) {
+            try {
+                for (File f: fsInfo.getJarClassPath(jarFile)) {
+                    addFile(f, warn);
+                }
+            } catch (IOException e) {
+                log.error("error.reading.file", jarFile, JavacFileManager.getMessage(e));
+            }
+        }
+    }
+
+    /**
+     * Base class for handling support for the representation of Locations.
+     * Implementations are responsible for handling the interactions between
+     * the command line options for a location, and API access via setLocation.
+     * @see #initHandlers
+     * @see #getHandler
+     */
+    protected abstract class LocationHandler {
+        final Location location;
+        final Set<OptionName> options;
+
+        /**
+         * Create a handler. The location and options provide a way to map
+         * from a location or an option to the corresponding handler.
+         * @see #initHandlers
+         */
+        protected LocationHandler(Location location, OptionName... options) {
+            this.location = location;
+            this.options = options.length == 0 ?
+                EnumSet.noneOf(OptionName.class):
+                EnumSet.copyOf(Arrays.asList(options));
+        }
+
+        // TODO: TEMPORARY, while Options still used for command line options
+        void update(Options optionTable) {
+            for (OptionName o: options) {
+                String v = optionTable.get(o);
+                if (v != null) {
+                    handleOption(o, v);
+                }
+            }
+        }
+
+        /** @see JavaFileManager#handleOption. */
+        abstract boolean handleOption(OptionName option, String value);
+        /** @see JavaFileManager#getLocation. */
+        abstract Collection<File> getLocation();
+        /** @see JavaFileManager#setLocation. */
+        abstract void setLocation(Iterable<? extends File> files) throws IOException;
+    }
+
+    /**
+     * General purpose implementation for output locations,
+     * such as -d/CLASS_OUTPUT and -s/SOURCE_OUTPUT.
+     * All options are treated as equivalent (i.e. aliases.)
+     * The value is a single file, possibly null.
+     */
+    private class OutputLocationHandler extends LocationHandler {
+        private File outputDir;
+
+        OutputLocationHandler(Location location, OptionName... options) {
+            super(location, options);
+        }
+
+        @Override
+        boolean handleOption(OptionName option, String value) {
+            if (!options.contains(option))
+                return false;
+
+            // TODO: could/should validate outputDir exists and is a directory
+            // need to decide how best to report issue for benefit of
+            // direct API call on JavaFileManager.handleOption(specifies IAE)
+            // vs. command line decoding.
+            outputDir = new File(value);
+            return true;
+        }
+
+        @Override
+        Collection<File> getLocation() {
+            return (outputDir == null) ? null : Collections.singleton(outputDir);
+        }
+
+        @Override
+        void setLocation(Iterable<? extends File> files) throws IOException {
+            if (files == null) {
+                outputDir = null;
+            } else {
+                Iterator<? extends File> pathIter = files.iterator();
+                if (!pathIter.hasNext())
+                    throw new IllegalArgumentException("empty path for directory");
+                File dir = pathIter.next();
+                if (pathIter.hasNext())
+                    throw new IllegalArgumentException("path too long for directory");
+                if (!dir.exists())
+                    throw new FileNotFoundException(dir + ": does not exist");
+                else if (!dir.isDirectory())
+                    throw new IOException(dir + ": not a directory");
+                outputDir = dir;
+            }
+        }
+    }
+
+    /**
+     * General purpose implementation for search path locations,
+     * such as -sourcepath/SOURCE_PATH and -processorPath/ANNOTATION_PROCESS_PATH.
+     * All options are treated as equivalent (i.e. aliases.)
+     * The value is an ordered set of files and/or directories.
+     */
+    private class SimpleLocationHandler extends LocationHandler {
+        protected Collection<File> searchPath;
+
+        SimpleLocationHandler(Location location, OptionName... options) {
+            super(location, options);
+        }
+
+        @Override
+        boolean handleOption(OptionName option, String value) {
+            if (!options.contains(option))
+                return false;
+            searchPath = value == null ? null :
+                    Collections.unmodifiableCollection(computePath(value));
+            return true;
+        }
+
+        protected Path computePath(String value) {
+            return new Path().addFiles(value);
+        }
+
+        @Override
+        Collection<File> getLocation() {
+            return searchPath;
+        }
+
+        @Override
+        void setLocation(Iterable<? extends File> files) {
+            Path p;
+            if (files == null) {
+                p = computePath(null);
+            } else {
+                p = new Path().addFiles(files);
+            }
+            searchPath = Collections.unmodifiableCollection(p);
+        }
+    }
+
+    /**
+     * Subtype of SimpleLocationHandler for -classpath/CLASS_PATH.
+     * If no value is given, a default is provided, based on system properties
+     * and other values.
+     */
+    private class ClassPathLocationHandler extends SimpleLocationHandler {
+        ClassPathLocationHandler() {
+            super(StandardLocation.CLASS_PATH,
+                    OptionName.CLASSPATH, OptionName.CP);
+        }
+
+        @Override
+        Collection<File> getLocation() {
+            lazy();
+            return searchPath;
+        }
+
+        @Override
+        protected Path computePath(String value) {
+            String cp = value;
+
+            // CLASSPATH environment variable when run from `javac'.
+            if (cp == null) cp = System.getProperty("env.class.path");
+
+            // If invoked via a java VM (not the javac launcher), use the
+            // platform class path
+            if (cp == null && System.getProperty("application.home") == null)
+                cp = System.getProperty("java.class.path");
+
+            // Default to current working directory.
+            if (cp == null) cp = ".";
+
+            return new Path()
+                .expandJarClassPaths(true)        // Only search user jars for Class-Paths
+                .emptyPathDefault(new File("."))  // Empty path elt ==> current directory
+                .addFiles(cp);
+            }
+
+        private void lazy() {
+            if (searchPath == null)
+                setLocation(null);
+        }
+    }
+
+    /**
+     * Custom subtype of LocationHandler for PLATFORM_CLASS_PATH.
+     * Various options are supported for different components of the
+     * platform class path.
+     * Setting a value with setLocation overrides all existing option values.
+     * Setting any option overrides any value set with setLocation, and reverts
+     * to using default values for options that have not been set.
+     * Setting -bootclasspath or -Xbootclasspath overrides any existing
+     * value for -Xbootclasspath/p: and -Xbootclasspath/a:.
+     */
+    private class BootClassPathLocationHandler extends LocationHandler {
+        private Collection<File> searchPath;
+        final Map<OptionName, String> optionValues = new EnumMap<OptionName,String>(OptionName.class);
+
+        /**
+         * rt.jar as found on the default bootclasspath.
+         * If the user specified a bootclasspath, null is used.
+         */
+        private File defaultBootClassPathRtJar = null;
+
+        /**
+         *  Is bootclasspath the default?
+         */
+        private boolean isDefaultBootClassPath;
+
+        BootClassPathLocationHandler() {
+            super(StandardLocation.PLATFORM_CLASS_PATH,
+                    OptionName.BOOTCLASSPATH, OptionName.XBOOTCLASSPATH,
+                    OptionName.XBOOTCLASSPATH_PREPEND,
+                    OptionName.XBOOTCLASSPATH_APPEND,
+                    OptionName.ENDORSEDDIRS, OptionName.DJAVA_ENDORSED_DIRS,
+                    OptionName.EXTDIRS, OptionName.DJAVA_EXT_DIRS);
+        }
+
+        boolean isDefault() {
+            lazy();
+            return isDefaultBootClassPath;
+        }
+
+        boolean isDefaultRtJar(File file) {
+            lazy();
+            return file.equals(defaultBootClassPathRtJar);
+        }
+
+        @Override
+        boolean handleOption(OptionName option, String value) {
+            if (!options.contains(option))
+                return false;
+
+            option = canonicalize(option);
+            optionValues.put(option, value);
+            if (option == BOOTCLASSPATH) {
+                optionValues.remove(XBOOTCLASSPATH_PREPEND);
+                optionValues.remove(XBOOTCLASSPATH_APPEND);
+            }
+            searchPath = null;  // reset to "uninitialized"
+            return true;
+        }
+        // where
+            // TODO: would be better if option aliasing was handled at a higher
+            // level
+            private OptionName canonicalize(OptionName option) {
+                switch (option) {
+                    case XBOOTCLASSPATH:
+                        return OptionName.BOOTCLASSPATH;
+                    case DJAVA_ENDORSED_DIRS:
+                        return OptionName.ENDORSEDDIRS;
+                    case DJAVA_EXT_DIRS:
+                        return OptionName.EXTDIRS;
+                    default:
+                        return option;
+                }
+            }
+
+        @Override
+        Collection<File> getLocation() {
+            lazy();
+            return searchPath;
+        }
+
+        @Override
+        void setLocation(Iterable<? extends File> files) {
+            if (files == null) {
+                searchPath = null;  // reset to "uninitialized"
+            } else {
+                defaultBootClassPathRtJar = null;
+                isDefaultBootClassPath = false;
+                Path p = new Path().addFiles(files, false);
+                searchPath = Collections.unmodifiableCollection(p);
+                optionValues.clear();
+            }
+        }
+
+        Path computePath() {
+            defaultBootClassPathRtJar = null;
+            Path path = new Path();
+
+            String bootclasspathOpt = optionValues.get(BOOTCLASSPATH);
+            String endorseddirsOpt = optionValues.get(ENDORSEDDIRS);
+            String extdirsOpt = optionValues.get(EXTDIRS);
+            String xbootclasspathPrependOpt = optionValues.get(XBOOTCLASSPATH_PREPEND);
+            String xbootclasspathAppendOpt = optionValues.get(XBOOTCLASSPATH_APPEND);
+
+            path.addFiles(xbootclasspathPrependOpt);
+
+            if (endorseddirsOpt != null)
+                path.addDirectories(endorseddirsOpt);
+            else
+                path.addDirectories(System.getProperty("java.endorsed.dirs"), false);
+
+            if (bootclasspathOpt != null) {
+                path.addFiles(bootclasspathOpt);
+            } else {
+                // Standard system classes for this compiler's release.
+                String files = System.getProperty("sun.boot.class.path");
+                path.addFiles(files, false);
+                File rt_jar = new File("rt.jar");
+                for (File file : getPathEntries(files)) {
+                    if (new File(file.getName()).equals(rt_jar))
+                        defaultBootClassPathRtJar = file;
+                }
+            }
+
+            path.addFiles(xbootclasspathAppendOpt);
+
+            // Strictly speaking, standard extensions are not bootstrap
+            // classes, but we treat them identically, so we'll pretend
+            // that they are.
+            if (extdirsOpt != null)
+                path.addDirectories(extdirsOpt);
+            else
+                path.addDirectories(System.getProperty("java.ext.dirs"), false);
+
+            isDefaultBootClassPath =
+                    (xbootclasspathPrependOpt == null) &&
+                    (bootclasspathOpt == null) &&
+                    (xbootclasspathAppendOpt == null);
+
+            return path;
+        }
+
+        private void lazy() {
+            if (searchPath == null)
+                searchPath = Collections.unmodifiableCollection(computePath());
+        }
+    }
+
+    Map<Location, LocationHandler> handlersForLocation;
+    Map<OptionName, LocationHandler> handlersForOption;
+
+    void initHandlers() {
+        handlersForLocation = new HashMap<Location, LocationHandler>();
+        handlersForOption = new EnumMap<OptionName, LocationHandler>(OptionName.class);
+
+        LocationHandler[] handlers = {
+            new BootClassPathLocationHandler(),
+            new ClassPathLocationHandler(),
+            new SimpleLocationHandler(StandardLocation.SOURCE_PATH, OptionName.SOURCEPATH),
+            new SimpleLocationHandler(StandardLocation.ANNOTATION_PROCESSOR_PATH, OptionName.PROCESSORPATH),
+            new OutputLocationHandler((StandardLocation.CLASS_OUTPUT), OptionName.D),
+            new OutputLocationHandler((StandardLocation.SOURCE_OUTPUT), OptionName.S)
+        };
+
+        for (LocationHandler h: handlers) {
+            handlersForLocation.put(h.location, h);
+            for (OptionName o: h.options)
+                handlersForOption.put(o, h);
+        }
+    }
+
+    boolean handleOption(OptionName option, String value) {
+        LocationHandler h = handlersForOption.get(option);
+        return (h == null ? false : h.handleOption(option, value));
+    }
+
+    Collection<File> getLocation(Location location) {
+        LocationHandler h = getHandler(location);
+        return (h == null ? null : h.getLocation());
+    }
+
+    File getOutputLocation(Location location) {
+        if (!location.isOutputLocation())
+            throw new IllegalArgumentException();
+        LocationHandler h = getHandler(location);
+        return ((OutputLocationHandler) h).outputDir;
+    }
+
+    void setLocation(Location location, Iterable<? extends File> files) throws IOException {
+        LocationHandler h = getHandler(location);
+        if (h == null) {
+            if (location.isOutputLocation())
+                h = new OutputLocationHandler(location);
+            else
+                h = new SimpleLocationHandler(location);
+            handlersForLocation.put(location, h);
+        }
+        h.setLocation(files);
+    }
+
+    protected LocationHandler getHandler(Location location) {
+        location.getClass(); // null check
+        lazy();
+        return handlersForLocation.get(location);
+    }
+
+// TOGO
+    protected void lazy() {
+        if (!inited) {
+            warn = lint.isEnabled(Lint.LintCategory.PATH);
+
+            for (LocationHandler h: handlersForLocation.values()) {
+                h.update(options);
+            }
+
+            inited = true;
+        }
+    }
+
+    /** Is this the name of an archive file? */
+    private boolean isArchive(File file) {
+        String n = file.getName().toLowerCase();
+        return fsInfo.isFile(file)
+            && (n.endsWith(".jar") || n.endsWith(".zip"));
+    }
+
+    /**
+     * Utility method for converting a search path string to an array
+     * of directory and JAR file URLs.
+     *
+     * Note that this method is called by apt and the DocletInvoker.
+     *
+     * @param path the search path string
+     * @return the resulting array of directory and JAR file URLs
+     */
+    public static URL[] pathToURLs(String path) {
+        StringTokenizer st = new StringTokenizer(path, File.pathSeparator);
+        URL[] urls = new URL[st.countTokens()];
+        int count = 0;
+        while (st.hasMoreTokens()) {
+            URL url = fileToURL(new File(st.nextToken()));
+            if (url != null) {
+                urls[count++] = url;
+            }
+        }
+        if (urls.length != count) {
+            URL[] tmp = new URL[count];
+            System.arraycopy(urls, 0, tmp, 0, count);
+            urls = tmp;
+        }
+        return urls;
+    }
+
+    /**
+     * Returns the directory or JAR file URL corresponding to the specified
+     * local file name.
+     *
+     * @param file the File object
+     * @return the resulting directory or JAR file URL, or null if unknown
+     */
+    private static URL fileToURL(File file) {
+        String name;
+        try {
+            name = file.getCanonicalPath();
+        } catch (IOException e) {
+            name = file.getAbsolutePath();
+        }
+        name = name.replace(File.separatorChar, '/');
+        if (!name.startsWith("/")) {
+            name = "/" + name;
+        }
+        // If the file does not exist, then assume that it's a directory
+        if (!file.isFile()) {
+            name = name + "/";
+        }
+        try {
+            return new URL("file", "", name);
+        } catch (MalformedURLException e) {
+            throw new IllegalArgumentException(file.toString());
+        }
+    }
+}
--- a/langtools/src/share/classes/com/sun/tools/javac/file/Paths.java	Wed Jul 05 17:53:51 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,558 +0,0 @@
-/*
- * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
- * 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.file;
-
-import java.io.File;
-import java.io.IOException;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.LinkedHashSet;
-import java.util.StringTokenizer;
-import java.util.zip.ZipFile;
-import javax.tools.JavaFileManager.Location;
-
-import com.sun.tools.javac.code.Lint;
-import com.sun.tools.javac.util.Context;
-import com.sun.tools.javac.util.ListBuffer;
-import com.sun.tools.javac.util.Log;
-import com.sun.tools.javac.util.Options;
-
-import static javax.tools.StandardLocation.*;
-import static com.sun.tools.javac.main.OptionName.*;
-
-/** This class converts command line arguments, environment variables
- *  and system properties (in File.pathSeparator-separated String form)
- *  into a boot class path, user class path, and source path (in
- *  Collection<String> form).
- *
- *  <p><b>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.</b>
- */
-public class Paths {
-
-    /** The context key for the todo list */
-    protected static final Context.Key<Paths> pathsKey =
-        new Context.Key<Paths>();
-
-    /** Get the Paths instance for this context.
-     *  @param context the context
-     *  @return the Paths instance for this context
-     */
-    public static Paths instance(Context context) {
-        Paths instance = context.get(pathsKey);
-        if (instance == null)
-            instance = new Paths(context);
-        return instance;
-    }
-
-    /** The log to use for warning output */
-    private Log log;
-
-    /** Collection of command-line options */
-    private Options options;
-
-    /** Handler for -Xlint options */
-    private Lint lint;
-
-    /** Access to (possibly cached) file info */
-    private FSInfo fsInfo;
-
-    protected Paths(Context context) {
-        context.put(pathsKey, this);
-        pathsForLocation = new HashMap<Location,Path>(16);
-        setContext(context);
-    }
-
-    void setContext(Context context) {
-        log = Log.instance(context);
-        options = Options.instance(context);
-        lint = Lint.instance(context);
-        fsInfo = FSInfo.instance(context);
-    }
-
-    /** Whether to warn about non-existent path elements */
-    private boolean warn;
-
-    private Map<Location, Path> pathsForLocation;
-
-    private boolean inited = false; // TODO? caching bad?
-
-    /**
-     * rt.jar as found on the default bootclass path.  If the user specified a
-     * bootclasspath, null is used.
-     */
-    private File defaultBootClassPathRtJar = null;
-
-    /**
-     *  Is bootclasspath the default?
-     */
-    private boolean isDefaultBootClassPath;
-
-    Path getPathForLocation(Location location) {
-        Path path = pathsForLocation.get(location);
-        if (path == null)
-            setPathForLocation(location, null);
-        return pathsForLocation.get(location);
-    }
-
-    void setPathForLocation(Location location, Iterable<? extends File> path) {
-        // TODO? if (inited) throw new IllegalStateException
-        // TODO: otherwise reset sourceSearchPath, classSearchPath as needed
-        Path p;
-        if (path == null) {
-            if (location == CLASS_PATH)
-                p = computeUserClassPath();
-            else if (location == PLATFORM_CLASS_PATH)
-                p = computeBootClassPath(); // sets isDefaultBootClassPath
-            else if (location == ANNOTATION_PROCESSOR_PATH)
-                p = computeAnnotationProcessorPath();
-            else if (location == SOURCE_PATH)
-                p = computeSourcePath();
-            else
-                // no defaults for other paths
-                p = null;
-        } else {
-            if (location == PLATFORM_CLASS_PATH) {
-                defaultBootClassPathRtJar = null;
-                isDefaultBootClassPath = false;
-            }
-            p = new Path();
-            for (File f: path)
-                p.addFile(f, warn); // TODO: is use of warn appropriate?
-        }
-        pathsForLocation.put(location, p);
-    }
-
-    public boolean isDefaultBootClassPath() {
-        lazy();
-        return isDefaultBootClassPath;
-    }
-
-    protected void lazy() {
-        if (!inited) {
-            warn = lint.isEnabled(Lint.LintCategory.PATH);
-
-            pathsForLocation.put(PLATFORM_CLASS_PATH, computeBootClassPath());
-            pathsForLocation.put(CLASS_PATH, computeUserClassPath());
-            pathsForLocation.put(SOURCE_PATH, computeSourcePath());
-
-            inited = true;
-        }
-    }
-
-    public Collection<File> bootClassPath() {
-        lazy();
-        return Collections.unmodifiableCollection(getPathForLocation(PLATFORM_CLASS_PATH));
-    }
-    public Collection<File> userClassPath() {
-        lazy();
-        return Collections.unmodifiableCollection(getPathForLocation(CLASS_PATH));
-    }
-    public Collection<File> sourcePath() {
-        lazy();
-        Path p = getPathForLocation(SOURCE_PATH);
-        return p == null || p.size() == 0
-            ? null
-            : Collections.unmodifiableCollection(p);
-    }
-
-    boolean isDefaultBootClassPathRtJar(File file) {
-        return file.equals(defaultBootClassPathRtJar);
-    }
-
-    /**
-     * Split a path into its elements. Empty path elements will be ignored.
-     * @param path The path to be split
-     * @return The elements of the path
-     */
-    private static Iterable<File> getPathEntries(String path) {
-        return getPathEntries(path, null);
-    }
-
-    /**
-     * Split a path into its elements. If emptyPathDefault is not null, all
-     * empty elements in the path, including empty elements at either end of
-     * the path, will be replaced with the value of emptyPathDefault.
-     * @param path The path to be split
-     * @param emptyPathDefault The value to substitute for empty path elements,
-     *  or null, to ignore empty path elements
-     * @return The elements of the path
-     */
-    private static Iterable<File> getPathEntries(String path, File emptyPathDefault) {
-        ListBuffer<File> entries = new ListBuffer<File>();
-        int start = 0;
-        while (start <= path.length()) {
-            int sep = path.indexOf(File.pathSeparatorChar, start);
-            if (sep == -1)
-                sep = path.length();
-            if (start < sep)
-                entries.add(new File(path.substring(start, sep)));
-            else if (emptyPathDefault != null)
-                entries.add(emptyPathDefault);
-            start = sep + 1;
-        }
-        return entries;
-    }
-
-    private class Path extends LinkedHashSet<File> {
-        private static final long serialVersionUID = 0;
-
-        private boolean expandJarClassPaths = false;
-        private Set<File> canonicalValues = new HashSet<File>();
-
-        public Path expandJarClassPaths(boolean x) {
-            expandJarClassPaths = x;
-            return this;
-        }
-
-        /** What to use when path element is the empty string */
-        private File emptyPathDefault = null;
-
-        public Path emptyPathDefault(File x) {
-            emptyPathDefault = x;
-            return this;
-        }
-
-        public Path() { super(); }
-
-        public Path addDirectories(String dirs, boolean warn) {
-            boolean prev = expandJarClassPaths;
-            expandJarClassPaths = true;
-            try {
-                if (dirs != null)
-                    for (File dir : getPathEntries(dirs))
-                        addDirectory(dir, warn);
-                return this;
-            } finally {
-                expandJarClassPaths = prev;
-            }
-        }
-
-        public Path addDirectories(String dirs) {
-            return addDirectories(dirs, warn);
-        }
-
-        private void addDirectory(File dir, boolean warn) {
-            if (!dir.isDirectory()) {
-                if (warn)
-                    log.warning(Lint.LintCategory.PATH,
-                            "dir.path.element.not.found", dir);
-                return;
-            }
-
-            File[] files = dir.listFiles();
-            if (files == null)
-                return;
-
-            for (File direntry : files) {
-                if (isArchive(direntry))
-                    addFile(direntry, warn);
-            }
-        }
-
-        public Path addFiles(String files, boolean warn) {
-            if (files != null) {
-                for (File file : getPathEntries(files, emptyPathDefault))
-                    addFile(file, warn);
-            }
-            return this;
-        }
-
-        public Path addFiles(String files) {
-            return addFiles(files, warn);
-        }
-
-        public void addFile(File file, boolean warn) {
-            if (contains(file)) {
-                // discard duplicates
-                return;
-            }
-
-            if (! fsInfo.exists(file)) {
-                /* No such file or directory exists */
-                if (warn) {
-                    log.warning(Lint.LintCategory.PATH,
-                            "path.element.not.found", file);
-                }
-                super.add(file);
-                return;
-            }
-
-            File canonFile = fsInfo.getCanonicalFile(file);
-            if (canonicalValues.contains(canonFile)) {
-                /* Discard duplicates and avoid infinite recursion */
-                return;
-            }
-
-            if (fsInfo.isFile(file)) {
-                /* File is an ordinary file. */
-                if (!isArchive(file)) {
-                    /* Not a recognized extension; open it to see if
-                     it looks like a valid zip file. */
-                    try {
-                        ZipFile z = new ZipFile(file);
-                        z.close();
-                        if (warn) {
-                            log.warning(Lint.LintCategory.PATH,
-                                    "unexpected.archive.file", file);
-                        }
-                    } catch (IOException e) {
-                        // FIXME: include e.getLocalizedMessage in warning
-                        if (warn) {
-                            log.warning(Lint.LintCategory.PATH,
-                                    "invalid.archive.file", file);
-                        }
-                        return;
-                    }
-                }
-            }
-
-            /* Now what we have left is either a directory or a file name
-               conforming to archive naming convention */
-            super.add(file);
-            canonicalValues.add(canonFile);
-
-            if (expandJarClassPaths && fsInfo.isFile(file))
-                addJarClassPath(file, warn);
-        }
-
-        // Adds referenced classpath elements from a jar's Class-Path
-        // Manifest entry.  In some future release, we may want to
-        // update this code to recognize URLs rather than simple
-        // filenames, but if we do, we should redo all path-related code.
-        private void addJarClassPath(File jarFile, boolean warn) {
-            try {
-                for (File f: fsInfo.getJarClassPath(jarFile)) {
-                    addFile(f, warn);
-                }
-            } catch (IOException e) {
-                log.error("error.reading.file", jarFile, JavacFileManager.getMessage(e));
-            }
-        }
-    }
-
-    private Path computeBootClassPath() {
-        defaultBootClassPathRtJar = null;
-        Path path = new Path();
-
-        String bootclasspathOpt = options.get(BOOTCLASSPATH);
-        String endorseddirsOpt = options.get(ENDORSEDDIRS);
-        String extdirsOpt = options.get(EXTDIRS);
-        String xbootclasspathPrependOpt = options.get(XBOOTCLASSPATH_PREPEND);
-        String xbootclasspathAppendOpt = options.get(XBOOTCLASSPATH_APPEND);
-
-        path.addFiles(xbootclasspathPrependOpt);
-
-        if (endorseddirsOpt != null)
-            path.addDirectories(endorseddirsOpt);
-        else
-            path.addDirectories(System.getProperty("java.endorsed.dirs"), false);
-
-        if (bootclasspathOpt != null) {
-            path.addFiles(bootclasspathOpt);
-        } else {
-            // Standard system classes for this compiler's release.
-            String files = System.getProperty("sun.boot.class.path");
-            path.addFiles(files, false);
-            File rt_jar = new File("rt.jar");
-            for (File file : getPathEntries(files)) {
-                if (new File(file.getName()).equals(rt_jar))
-                    defaultBootClassPathRtJar = file;
-            }
-        }
-
-        path.addFiles(xbootclasspathAppendOpt);
-
-        // Strictly speaking, standard extensions are not bootstrap
-        // classes, but we treat them identically, so we'll pretend
-        // that they are.
-        if (extdirsOpt != null)
-            path.addDirectories(extdirsOpt);
-        else
-            path.addDirectories(System.getProperty("java.ext.dirs"), false);
-
-        isDefaultBootClassPath =
-                (xbootclasspathPrependOpt == null) &&
-                (bootclasspathOpt == null) &&
-                (xbootclasspathAppendOpt == null);
-
-        return path;
-    }
-
-    private Path computeUserClassPath() {
-        String cp = options.get(CLASSPATH);
-
-        // CLASSPATH environment variable when run from `javac'.
-        if (cp == null) cp = System.getProperty("env.class.path");
-
-        // If invoked via a java VM (not the javac launcher), use the
-        // platform class path
-        if (cp == null && System.getProperty("application.home") == null)
-            cp = System.getProperty("java.class.path");
-
-        // Default to current working directory.
-        if (cp == null) cp = ".";
-
-        return new Path()
-            .expandJarClassPaths(true)        // Only search user jars for Class-Paths
-            .emptyPathDefault(new File("."))  // Empty path elt ==> current directory
-            .addFiles(cp);
-    }
-
-    private Path computeSourcePath() {
-        String sourcePathArg = options.get(SOURCEPATH);
-        if (sourcePathArg == null)
-            return null;
-
-        return new Path().addFiles(sourcePathArg);
-    }
-
-    private Path computeAnnotationProcessorPath() {
-        String processorPathArg = options.get(PROCESSORPATH);
-        if (processorPathArg == null)
-            return null;
-
-        return new Path().addFiles(processorPathArg);
-    }
-
-    /** The actual effective locations searched for sources */
-    private Path sourceSearchPath;
-
-    public Collection<File> sourceSearchPath() {
-        if (sourceSearchPath == null) {
-            lazy();
-            Path sourcePath = getPathForLocation(SOURCE_PATH);
-            Path userClassPath = getPathForLocation(CLASS_PATH);
-            sourceSearchPath = sourcePath != null ? sourcePath : userClassPath;
-        }
-        return Collections.unmodifiableCollection(sourceSearchPath);
-    }
-
-    /** The actual effective locations searched for classes */
-    private Path classSearchPath;
-
-    public Collection<File> classSearchPath() {
-        if (classSearchPath == null) {
-            lazy();
-            Path bootClassPath = getPathForLocation(PLATFORM_CLASS_PATH);
-            Path userClassPath = getPathForLocation(CLASS_PATH);
-            classSearchPath = new Path();
-            classSearchPath.addAll(bootClassPath);
-            classSearchPath.addAll(userClassPath);
-        }
-        return Collections.unmodifiableCollection(classSearchPath);
-    }
-
-    /** The actual effective locations for non-source, non-class files */
-    private Path otherSearchPath;
-
-    Collection<File> otherSearchPath() {
-        if (otherSearchPath == null) {
-            lazy();
-            Path userClassPath = getPathForLocation(CLASS_PATH);
-            Path sourcePath = getPathForLocation(SOURCE_PATH);
-            if (sourcePath == null)
-                otherSearchPath = userClassPath;
-            else {
-                otherSearchPath = new Path();
-                otherSearchPath.addAll(userClassPath);
-                otherSearchPath.addAll(sourcePath);
-            }
-        }
-        return Collections.unmodifiableCollection(otherSearchPath);
-    }
-
-    /** Is this the name of an archive file? */
-    private boolean isArchive(File file) {
-        String n = file.getName().toLowerCase();
-        return fsInfo.isFile(file)
-            && (n.endsWith(".jar") || n.endsWith(".zip"));
-    }
-
-    /**
-     * Utility method for converting a search path string to an array
-     * of directory and JAR file URLs.
-     *
-     * Note that this method is called by apt and the DocletInvoker.
-     *
-     * @param path the search path string
-     * @return the resulting array of directory and JAR file URLs
-     */
-    public static URL[] pathToURLs(String path) {
-        StringTokenizer st = new StringTokenizer(path, File.pathSeparator);
-        URL[] urls = new URL[st.countTokens()];
-        int count = 0;
-        while (st.hasMoreTokens()) {
-            URL url = fileToURL(new File(st.nextToken()));
-            if (url != null) {
-                urls[count++] = url;
-            }
-        }
-        if (urls.length != count) {
-            URL[] tmp = new URL[count];
-            System.arraycopy(urls, 0, tmp, 0, count);
-            urls = tmp;
-        }
-        return urls;
-    }
-
-    /**
-     * Returns the directory or JAR file URL corresponding to the specified
-     * local file name.
-     *
-     * @param file the File object
-     * @return the resulting directory or JAR file URL, or null if unknown
-     */
-    private static URL fileToURL(File file) {
-        String name;
-        try {
-            name = file.getCanonicalPath();
-        } catch (IOException e) {
-            name = file.getAbsolutePath();
-        }
-        name = name.replace(File.separatorChar, '/');
-        if (!name.startsWith("/")) {
-            name = "/" + name;
-        }
-        // If the file does not exist, then assume that it's a directory
-        if (!file.isFile()) {
-            name = name + "/";
-        }
-        try {
-            return new URL("file", "", name);
-        } catch (MalformedURLException e) {
-            throw new IllegalArgumentException(file.toString());
-        }
-    }
-}
--- a/langtools/src/share/classes/com/sun/tools/javac/jvm/Code.java	Wed Jul 05 17:53:51 2017 +0200
+++ b/langtools/src/share/classes/com/sun/tools/javac/jvm/Code.java	Wed Jul 05 17:54:24 2017 +0200
@@ -1542,7 +1542,28 @@
      */
     public void addCatch(
         char startPc, char endPc, char handlerPc, char catchType) {
-        catchInfo.append(new char[]{startPc, endPc, handlerPc, catchType});
+            catchInfo.append(new char[]{startPc, endPc, handlerPc, catchType});
+        }
+
+
+    public void compressCatchTable() {
+        ListBuffer<char[]> compressedCatchInfo = ListBuffer.lb();
+        List<Integer> handlerPcs = List.nil();
+        for (char[] catchEntry : catchInfo.elems) {
+            handlerPcs = handlerPcs.prepend((int)catchEntry[2]);
+        }
+        for (char[] catchEntry : catchInfo.elems) {
+            int startpc = catchEntry[0];
+            int endpc = catchEntry[1];
+            if (startpc == endpc ||
+                    (startpc == (endpc - 1) &&
+                    handlerPcs.contains(startpc))) {
+                continue;
+            } else {
+                compressedCatchInfo.append(catchEntry);
+            }
+        }
+        catchInfo = compressedCatchInfo;
     }
 
 
--- a/langtools/src/share/classes/com/sun/tools/javac/jvm/Gen.java	Wed Jul 05 17:53:51 2017 +0200
+++ b/langtools/src/share/classes/com/sun/tools/javac/jvm/Gen.java	Wed Jul 05 17:54:24 2017 +0200
@@ -959,6 +959,9 @@
                     code.lastFrame = null;
                     code.frameBeforeLast = null;
                 }
+
+                //compress exception table
+                code.compressCatchTable();
             }
         }
 
@@ -1437,7 +1440,6 @@
                     code.markDead();
                 }
             }
-
             // Resolve all breaks.
             code.resolve(exitChain);
 
@@ -1496,23 +1498,21 @@
         void registerCatch(DiagnosticPosition pos,
                            int startpc, int endpc,
                            int handler_pc, int catch_type) {
-            if (startpc != endpc) {
-                char startpc1 = (char)startpc;
-                char endpc1 = (char)endpc;
-                char handler_pc1 = (char)handler_pc;
-                if (startpc1 == startpc &&
-                    endpc1 == endpc &&
-                    handler_pc1 == handler_pc) {
-                    code.addCatch(startpc1, endpc1, handler_pc1,
-                                  (char)catch_type);
+            char startpc1 = (char)startpc;
+            char endpc1 = (char)endpc;
+            char handler_pc1 = (char)handler_pc;
+            if (startpc1 == startpc &&
+                endpc1 == endpc &&
+                handler_pc1 == handler_pc) {
+                code.addCatch(startpc1, endpc1, handler_pc1,
+                              (char)catch_type);
+            } else {
+                if (!useJsrLocally && !target.generateStackMapTable()) {
+                    useJsrLocally = true;
+                    throw new CodeSizeOverflow();
                 } else {
-                    if (!useJsrLocally && !target.generateStackMapTable()) {
-                        useJsrLocally = true;
-                        throw new CodeSizeOverflow();
-                    } else {
-                        log.error(pos, "limit.code.too.large.for.try.stmt");
-                        nerrs++;
-                    }
+                    log.error(pos, "limit.code.too.large.for.try.stmt");
+                    nerrs++;
                 }
             }
         }
--- a/langtools/src/share/classes/com/sun/tools/javac/nio/JavacPathFileManager.java	Wed Jul 05 17:53:51 2017 +0200
+++ b/langtools/src/share/classes/com/sun/tools/javac/nio/JavacPathFileManager.java	Wed Jul 05 17:54:24 2017 +0200
@@ -25,9 +25,7 @@
 
 package com.sun.tools.javac.nio;
 
-
 import java.io.File;
-import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.net.MalformedURLException;
 import java.net.URL;
@@ -60,7 +58,6 @@
 import static java.nio.file.FileVisitOption.*;
 import static javax.tools.StandardLocation.*;
 
-import com.sun.tools.javac.file.Paths;
 import com.sun.tools.javac.util.BaseFileManager;
 import com.sun.tools.javac.util.Context;
 import com.sun.tools.javac.util.List;
@@ -125,9 +122,8 @@
      * Set the context for JavacPathFileManager.
      */
     @Override
-    protected void setContext(Context context) {
+    public void setContext(Context context) {
         super.setContext(context);
-        searchPaths = Paths.instance(context);
     }
 
     @Override
@@ -173,7 +169,7 @@
 
     @Override
     public boolean isDefaultBootClassPath() {
-        return searchPaths.isDefaultBootClassPath();
+        return locations.isDefaultBootClassPath();
     }
 
     // <editor-fold defaultstate="collapsed" desc="Location handling">
@@ -231,13 +227,13 @@
         if (locn instanceof StandardLocation) {
             switch ((StandardLocation) locn) {
                 case CLASS_PATH:
-                    files = searchPaths.userClassPath();
+                    files = locations.userClassPath();
                     break;
                 case PLATFORM_CLASS_PATH:
-                    files = searchPaths.bootClassPath();
+                    files = locations.bootClassPath();
                     break;
                 case SOURCE_PATH:
-                    files = searchPaths.sourcePath();
+                    files = locations.sourcePath();
                     break;
                 case CLASS_OUTPUT: {
                     String arg = options.get(D);
@@ -272,7 +268,6 @@
         private boolean inited = false;
 
     private Map<Location, PathsForLocation> pathsForLocation;
-    private Paths searchPaths;
 
     private static class PathsForLocation extends LinkedHashSet<Path> {
         private static final long serialVersionUID = 6788510222394486733L;
--- a/langtools/src/share/classes/com/sun/tools/javac/parser/DocCommentScanner.java	Wed Jul 05 17:53:51 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,420 +0,0 @@
-/*
- * Copyright (c) 2004, 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.  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.parser;
-
-import java.nio.*;
-
-import com.sun.tools.javac.util.*;
-import static com.sun.tools.javac.util.LayoutCharacters.*;
-
-/** An extension to the base lexical analyzer that captures
- *  and processes the contents of doc comments.  It does so by
- *  translating Unicode escape sequences and by stripping the
- *  leading whitespace and starts from each line of the comment.
- *
- *  <p><b>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.</b>
- */
-public class DocCommentScanner extends Scanner {
-
-    /** Create a scanner from the input buffer.  buffer must implement
-     *  array() and compact(), and remaining() must be less than limit().
-     */
-    protected DocCommentScanner(ScannerFactory fac, CharBuffer buffer) {
-        super(fac, buffer);
-    }
-
-    /** Create a scanner from the input array.  The array must have at
-     *  least a single character of extra space.
-     */
-    protected DocCommentScanner(ScannerFactory fac, char[] input, int inputLength) {
-        super(fac, input, inputLength);
-    }
-
-    /** Starting position of the comment in original source
-     */
-    private int pos;
-
-    /** The comment input buffer, index of next chacter to be read,
-     *  index of one past last character in buffer.
-     */
-    private char[] buf;
-    private int bp;
-    private int buflen;
-
-    /** The current character.
-     */
-    private char ch;
-
-    /** The column number position of the current character.
-     */
-    private int col;
-
-    /** The buffer index of the last converted Unicode character
-     */
-    private int unicodeConversionBp = 0;
-
-    /**
-     * Buffer for doc comment.
-     */
-    private char[] docCommentBuffer = new char[1024];
-
-    /**
-     * Number of characters in doc comment buffer.
-     */
-    private int docCommentCount;
-
-    /**
-     * Translated and stripped contents of doc comment
-     */
-    private String docComment = null;
-
-
-    /** Unconditionally expand the comment buffer.
-     */
-    private void expandCommentBuffer() {
-        char[] newBuffer = new char[docCommentBuffer.length * 2];
-        System.arraycopy(docCommentBuffer, 0, newBuffer,
-                         0, docCommentBuffer.length);
-        docCommentBuffer = newBuffer;
-    }
-
-    /** Convert an ASCII digit from its base (8, 10, or 16)
-     *  to its value.
-     */
-    private int digit(int base) {
-        char c = ch;
-        int result = Character.digit(c, base);
-        if (result >= 0 && c > 0x7f) {
-            ch = "0123456789abcdef".charAt(result);
-        }
-        return result;
-    }
-
-    /** Convert Unicode escape; bp points to initial '\' character
-     *  (Spec 3.3).
-     */
-    private void convertUnicode() {
-        if (ch == '\\' && unicodeConversionBp != bp) {
-            bp++; ch = buf[bp]; col++;
-            if (ch == 'u') {
-                do {
-                    bp++; ch = buf[bp]; col++;
-                } while (ch == 'u');
-                int limit = bp + 3;
-                if (limit < buflen) {
-                    int d = digit(16);
-                    int code = d;
-                    while (bp < limit && d >= 0) {
-                        bp++; ch = buf[bp]; col++;
-                        d = digit(16);
-                        code = (code << 4) + d;
-                    }
-                    if (d >= 0) {
-                        ch = (char)code;
-                        unicodeConversionBp = bp;
-                        return;
-                    }
-                }
-                // "illegal.Unicode.esc", reported by base scanner
-            } else {
-                bp--;
-                ch = '\\';
-                col--;
-            }
-        }
-    }
-
-
-    /** Read next character.
-     */
-    private void scanChar() {
-        bp++;
-        ch = buf[bp];
-        switch (ch) {
-        case '\r': // return
-            col = 0;
-            break;
-        case '\n': // newline
-            if (bp == 0 || buf[bp-1] != '\r') {
-                col = 0;
-            }
-            break;
-        case '\t': // tab
-            col = (col / TabInc * TabInc) + TabInc;
-            break;
-        case '\\': // possible Unicode
-            col++;
-            convertUnicode();
-            break;
-        default:
-            col++;
-            break;
-        }
-    }
-
-    /**
-     * Read next character in doc comment, skipping over double '\' characters.
-     * If a double '\' is skipped, put in the buffer and update buffer count.
-     */
-    private void scanDocCommentChar() {
-        scanChar();
-        if (ch == '\\') {
-            if (buf[bp+1] == '\\' && unicodeConversionBp != bp) {
-                if (docCommentCount == docCommentBuffer.length)
-                    expandCommentBuffer();
-                docCommentBuffer[docCommentCount++] = ch;
-                bp++; col++;
-            } else {
-                convertUnicode();
-            }
-        }
-    }
-
-    /* Reset doc comment before reading each new token
-     */
-    public void nextToken() {
-        docComment = null;
-        super.nextToken();
-    }
-
-    /**
-     * Returns the documentation string of the current token.
-     */
-    public String docComment() {
-        return docComment;
-    }
-
-    /**
-     * Process a doc comment and make the string content available.
-     * Strips leading whitespace and stars.
-     */
-    @SuppressWarnings("fallthrough")
-    protected void processComment(CommentStyle style) {
-        if (style != CommentStyle.JAVADOC) {
-            return;
-        }
-
-        pos = pos();
-        buf = getRawCharacters(pos, endPos());
-        buflen = buf.length;
-        bp = 0;
-        col = 0;
-
-        docCommentCount = 0;
-
-        boolean firstLine = true;
-
-        // Skip over first slash
-        scanDocCommentChar();
-        // Skip over first star
-        scanDocCommentChar();
-
-        // consume any number of stars
-        while (bp < buflen && ch == '*') {
-            scanDocCommentChar();
-        }
-        // is the comment in the form /**/, /***/, /****/, etc. ?
-        if (bp < buflen && ch == '/') {
-            docComment = "";
-            return;
-        }
-
-        // skip a newline on the first line of the comment.
-        if (bp < buflen) {
-            if (ch == LF) {
-                scanDocCommentChar();
-                firstLine = false;
-            } else if (ch == CR) {
-                scanDocCommentChar();
-                if (ch == LF) {
-                    scanDocCommentChar();
-                    firstLine = false;
-                }
-            }
-        }
-
-    outerLoop:
-
-        // The outerLoop processes the doc comment, looping once
-        // for each line.  For each line, it first strips off
-        // whitespace, then it consumes any stars, then it
-        // puts the rest of the line into our buffer.
-        while (bp < buflen) {
-
-            // The wsLoop consumes whitespace from the beginning
-            // of each line.
-        wsLoop:
-
-            while (bp < buflen) {
-                switch(ch) {
-                case ' ':
-                    scanDocCommentChar();
-                    break;
-                case '\t':
-                    col = ((col - 1) / TabInc * TabInc) + TabInc;
-                    scanDocCommentChar();
-                    break;
-                case FF:
-                    col = 0;
-                    scanDocCommentChar();
-                    break;
-// Treat newline at beginning of line (blank line, no star)
-// as comment text.  Old Javadoc compatibility requires this.
-/*---------------------------------*
-                case CR: // (Spec 3.4)
-                    scanDocCommentChar();
-                    if (ch == LF) {
-                        col = 0;
-                        scanDocCommentChar();
-                    }
-                    break;
-                case LF: // (Spec 3.4)
-                    scanDocCommentChar();
-                    break;
-*---------------------------------*/
-                default:
-                    // we've seen something that isn't whitespace;
-                    // jump out.
-                    break wsLoop;
-                }
-            }
-
-            // Are there stars here?  If so, consume them all
-            // and check for the end of comment.
-            if (ch == '*') {
-                // skip all of the stars
-                do {
-                    scanDocCommentChar();
-                } while (ch == '*');
-
-                // check for the closing slash.
-                if (ch == '/') {
-                    // We're done with the doc comment
-                    // scanChar() and breakout.
-                    break outerLoop;
-                }
-            } else if (! firstLine) {
-                //The current line does not begin with a '*' so we will indent it.
-                for (int i = 1; i < col; i++) {
-                    if (docCommentCount == docCommentBuffer.length)
-                        expandCommentBuffer();
-                    docCommentBuffer[docCommentCount++] = ' ';
-                }
-            }
-
-            // The textLoop processes the rest of the characters
-            // on the line, adding them to our buffer.
-        textLoop:
-            while (bp < buflen) {
-                switch (ch) {
-                case '*':
-                    // Is this just a star?  Or is this the
-                    // end of a comment?
-                    scanDocCommentChar();
-                    if (ch == '/') {
-                        // This is the end of the comment,
-                        // set ch and return our buffer.
-                        break outerLoop;
-                    }
-                    // This is just an ordinary star.  Add it to
-                    // the buffer.
-                    if (docCommentCount == docCommentBuffer.length)
-                        expandCommentBuffer();
-                    docCommentBuffer[docCommentCount++] = '*';
-                    break;
-                case ' ':
-                case '\t':
-                    if (docCommentCount == docCommentBuffer.length)
-                        expandCommentBuffer();
-                    docCommentBuffer[docCommentCount++] = ch;
-                    scanDocCommentChar();
-                    break;
-                case FF:
-                    scanDocCommentChar();
-                    break textLoop; // treat as end of line
-                case CR: // (Spec 3.4)
-                    scanDocCommentChar();
-                    if (ch != LF) {
-                        // Canonicalize CR-only line terminator to LF
-                        if (docCommentCount == docCommentBuffer.length)
-                            expandCommentBuffer();
-                        docCommentBuffer[docCommentCount++] = (char)LF;
-                        break textLoop;
-                    }
-                    /* fall through to LF case */
-                case LF: // (Spec 3.4)
-                    // We've seen a newline.  Add it to our
-                    // buffer and break out of this loop,
-                    // starting fresh on a new line.
-                    if (docCommentCount == docCommentBuffer.length)
-                        expandCommentBuffer();
-                    docCommentBuffer[docCommentCount++] = ch;
-                    scanDocCommentChar();
-                    break textLoop;
-                default:
-                    // Add the character to our buffer.
-                    if (docCommentCount == docCommentBuffer.length)
-                        expandCommentBuffer();
-                    docCommentBuffer[docCommentCount++] = ch;
-                    scanDocCommentChar();
-                }
-            } // end textLoop
-            firstLine = false;
-        } // end outerLoop
-
-        if (docCommentCount > 0) {
-            int i = docCommentCount - 1;
-        trailLoop:
-            while (i > -1) {
-                switch (docCommentBuffer[i]) {
-                case '*':
-                    i--;
-                    break;
-                default:
-                    break trailLoop;
-                }
-            }
-            docCommentCount = i + 1;
-
-            // Store the text of the doc comment
-            docComment = new String(docCommentBuffer, 0 , docCommentCount);
-        } else {
-            docComment = "";
-        }
-    }
-
-    /** Build a map for translating between line numbers and
-     * positions in the input.
-     *
-     * @return a LineMap */
-    public Position.LineMap getLineMap() {
-        char[] buf = getRawCharacters();
-        return Position.makeLineMap(buf, buf.length, true);
-    }
-}
--- a/langtools/src/share/classes/com/sun/tools/javac/parser/EndPosParser.java	Wed Jul 05 17:53:51 2017 +0200
+++ b/langtools/src/share/classes/com/sun/tools/javac/parser/EndPosParser.java	Wed Jul 05 17:54:24 2017 +0200
@@ -67,14 +67,14 @@
     /** {@inheritDoc} */
     @Override
     protected <T extends JCTree> T to(T t) {
-        storeEnd(t, S.endPos());
+        storeEnd(t, token.endPos);
         return t;
     }
 
     /** {@inheritDoc} */
     @Override
     protected <T extends JCTree> T toP(T t) {
-        storeEnd(t, S.prevEndPos());
+        storeEnd(t, S.prevToken().endPos);
         return t;
     }
 
@@ -88,7 +88,7 @@
     /** {@inheritDoc} */
     @Override
     JCExpression parExpression() {
-        int pos = S.pos();
+        int pos = token.pos;
         JCExpression t = super.parExpression();
         return toP(F.at(pos).Parens(t));
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/share/classes/com/sun/tools/javac/parser/JavaTokenizer.java	Wed Jul 05 17:54:24 2017 +0200
@@ -0,0 +1,896 @@
+/*
+ * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
+ * 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.parser;
+
+import java.nio.CharBuffer;
+import com.sun.tools.javac.code.Source;
+import com.sun.tools.javac.util.*;
+
+
+import static com.sun.tools.javac.parser.Tokens.*;
+import static com.sun.tools.javac.util.LayoutCharacters.*;
+
+/** The lexical analyzer maps an input stream consisting of
+ *  ASCII characters and Unicode escapes into a token sequence.
+ *
+ *  <p><b>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.</b>
+ */
+public class JavaTokenizer {
+
+    private static boolean scannerDebug = false;
+
+    /** Allow hex floating-point literals.
+     */
+    private boolean allowHexFloats;
+
+    /** Allow binary literals.
+     */
+    private boolean allowBinaryLiterals;
+
+    /** Allow underscores in literals.
+     */
+    private boolean allowUnderscoresInLiterals;
+
+    /** The source language setting.
+     */
+    private Source source;
+
+    /** The log to be used for error reporting.
+     */
+    private final Log log;
+
+    /** The name table. */
+    private final Names names;
+
+    /** The token factory. */
+    private final Tokens tokens;
+
+    /** The token kind, set by nextToken().
+     */
+    protected TokenKind tk;
+
+    /** The token's radix, set by nextToken().
+     */
+    protected int radix;
+
+    /** The token's name, set by nextToken().
+     */
+    protected Name name;
+
+    /** The position where a lexical error occurred;
+     */
+    protected int errPos = Position.NOPOS;
+
+    /** Has a @deprecated been encountered in last doc comment?
+     *  this needs to be reset by client.
+     */
+    protected boolean deprecatedFlag = false;
+
+    /** A character buffer for saved chars.
+     */
+    protected char[] sbuf = new char[128];
+    protected int sp;
+
+    protected UnicodeReader reader;
+
+    private static final boolean hexFloatsWork = hexFloatsWork();
+    private static boolean hexFloatsWork() {
+        try {
+            Float.valueOf("0x1.0p1");
+            return true;
+        } catch (NumberFormatException ex) {
+            return false;
+        }
+    }
+
+    /**
+     * Create a scanner from the input array.  This method might
+     * modify the array.  To avoid copying the input array, ensure
+     * that {@code inputLength < input.length} or
+     * {@code input[input.length -1]} is a white space character.
+     *
+     * @param fac the factory which created this Scanner
+     * @param input the input, might be modified
+     * @param inputLength the size of the input.
+     * Must be positive and less than or equal to input.length.
+     */
+    protected JavaTokenizer(ScannerFactory fac, CharBuffer buf) {
+        this(fac, new UnicodeReader(fac, buf));
+    }
+
+    protected JavaTokenizer(ScannerFactory fac, char[] buf, int inputLength) {
+        this(fac, new UnicodeReader(fac, buf, inputLength));
+    }
+
+    protected JavaTokenizer(ScannerFactory fac, UnicodeReader reader) {
+        log = fac.log;
+        names = fac.names;
+        tokens = fac.tokens;
+        source = fac.source;
+        this.reader = reader;
+        allowBinaryLiterals = source.allowBinaryLiterals();
+        allowHexFloats = source.allowHexFloats();
+        allowUnderscoresInLiterals = source.allowUnderscoresInLiterals();
+    }
+
+    /** Report an error at the given position using the provided arguments.
+     */
+    protected void lexError(int pos, String key, Object... args) {
+        log.error(pos, key, args);
+        tk = TokenKind.ERROR;
+        errPos = pos;
+    }
+
+    /** Read next character in comment, skipping over double '\' characters.
+     */
+    protected void scanCommentChar() {
+        reader.scanChar();
+        if (reader.ch == '\\') {
+            if (reader.peekChar() == '\\' && !reader.isUnicode()) {
+                reader.skipChar();
+            } else {
+                reader.convertUnicode();
+            }
+        }
+    }
+
+    /** Append a character to sbuf.
+     */
+    private void putChar(char ch) {
+        if (sp == sbuf.length) {
+            char[] newsbuf = new char[sbuf.length * 2];
+            System.arraycopy(sbuf, 0, newsbuf, 0, sbuf.length);
+            sbuf = newsbuf;
+        }
+        sbuf[sp++] = ch;
+    }
+
+    /** Read next character in character or string literal and copy into sbuf.
+     */
+    private void scanLitChar(int pos) {
+        if (reader.ch == '\\') {
+            if (reader.peekChar() == '\\' && !reader.isUnicode()) {
+                reader.skipChar();
+                putChar('\\');
+                reader.scanChar();
+            } else {
+                reader.scanChar();
+                switch (reader.ch) {
+                case '0': case '1': case '2': case '3':
+                case '4': case '5': case '6': case '7':
+                    char leadch = reader.ch;
+                    int oct = reader.digit(pos, 8);
+                    reader.scanChar();
+                    if ('0' <= reader.ch && reader.ch <= '7') {
+                        oct = oct * 8 + reader.digit(pos, 8);
+                        reader.scanChar();
+                        if (leadch <= '3' && '0' <= reader.ch && reader.ch <= '7') {
+                            oct = oct * 8 + reader.digit(pos, 8);
+                            reader.scanChar();
+                        }
+                    }
+                    putChar((char)oct);
+                    break;
+                case 'b':
+                    putChar('\b'); reader.scanChar(); break;
+                case 't':
+                    putChar('\t'); reader.scanChar(); break;
+                case 'n':
+                    putChar('\n'); reader.scanChar(); break;
+                case 'f':
+                    putChar('\f'); reader.scanChar(); break;
+                case 'r':
+                    putChar('\r'); reader.scanChar(); break;
+                case '\'':
+                    putChar('\''); reader.scanChar(); break;
+                case '\"':
+                    putChar('\"'); reader.scanChar(); break;
+                case '\\':
+                    putChar('\\'); reader.scanChar(); break;
+                default:
+                    lexError(reader.bp, "illegal.esc.char");
+                }
+            }
+        } else if (reader.bp != reader.buflen) {
+            putChar(reader.ch); reader.scanChar();
+        }
+    }
+
+    private void scanDigits(int pos, int digitRadix) {
+        char saveCh;
+        int savePos;
+        do {
+            if (reader.ch != '_') {
+                putChar(reader.ch);
+            } else {
+                if (!allowUnderscoresInLiterals) {
+                    lexError(pos, "unsupported.underscore.lit", source.name);
+                    allowUnderscoresInLiterals = true;
+                }
+            }
+            saveCh = reader.ch;
+            savePos = reader.bp;
+            reader.scanChar();
+        } while (reader.digit(pos, digitRadix) >= 0 || reader.ch == '_');
+        if (saveCh == '_')
+            lexError(savePos, "illegal.underscore");
+    }
+
+    /** Read fractional part of hexadecimal floating point number.
+     */
+    private void scanHexExponentAndSuffix(int pos) {
+        if (reader.ch == 'p' || reader.ch == 'P') {
+            putChar(reader.ch);
+            reader.scanChar();
+            skipIllegalUnderscores();
+            if (reader.ch == '+' || reader.ch == '-') {
+                putChar(reader.ch);
+                reader.scanChar();
+            }
+            skipIllegalUnderscores();
+            if ('0' <= reader.ch && reader.ch <= '9') {
+                scanDigits(pos, 10);
+                if (!allowHexFloats) {
+                    lexError(pos, "unsupported.fp.lit", source.name);
+                    allowHexFloats = true;
+                }
+                else if (!hexFloatsWork)
+                    lexError(pos, "unsupported.cross.fp.lit");
+            } else
+                lexError(pos, "malformed.fp.lit");
+        } else {
+            lexError(pos, "malformed.fp.lit");
+        }
+        if (reader.ch == 'f' || reader.ch == 'F') {
+            putChar(reader.ch);
+            reader.scanChar();
+            tk = TokenKind.FLOATLITERAL;
+            radix = 16;
+        } else {
+            if (reader.ch == 'd' || reader.ch == 'D') {
+                putChar(reader.ch);
+                reader.scanChar();
+            }
+            tk = TokenKind.DOUBLELITERAL;
+            radix = 16;
+        }
+    }
+
+    /** Read fractional part of floating point number.
+     */
+    private void scanFraction(int pos) {
+        skipIllegalUnderscores();
+        if ('0' <= reader.ch && reader.ch <= '9') {
+            scanDigits(pos, 10);
+        }
+        int sp1 = sp;
+        if (reader.ch == 'e' || reader.ch == 'E') {
+            putChar(reader.ch);
+            reader.scanChar();
+            skipIllegalUnderscores();
+            if (reader.ch == '+' || reader.ch == '-') {
+                putChar(reader.ch);
+                reader.scanChar();
+            }
+            skipIllegalUnderscores();
+            if ('0' <= reader.ch && reader.ch <= '9') {
+                scanDigits(pos, 10);
+                return;
+            }
+            lexError(pos, "malformed.fp.lit");
+            sp = sp1;
+        }
+    }
+
+    /** Read fractional part and 'd' or 'f' suffix of floating point number.
+     */
+    private void scanFractionAndSuffix(int pos) {
+        radix = 10;
+        scanFraction(pos);
+        if (reader.ch == 'f' || reader.ch == 'F') {
+            putChar(reader.ch);
+            reader.scanChar();
+            tk = TokenKind.FLOATLITERAL;
+        } else {
+            if (reader.ch == 'd' || reader.ch == 'D') {
+                putChar(reader.ch);
+                reader.scanChar();
+            }
+            tk = TokenKind.DOUBLELITERAL;
+        }
+    }
+
+    /** Read fractional part and 'd' or 'f' suffix of floating point number.
+     */
+    private void scanHexFractionAndSuffix(int pos, boolean seendigit) {
+        radix = 16;
+        Assert.check(reader.ch == '.');
+        putChar(reader.ch);
+        reader.scanChar();
+        skipIllegalUnderscores();
+        if (reader.digit(pos, 16) >= 0) {
+            seendigit = true;
+            scanDigits(pos, 16);
+        }
+        if (!seendigit)
+            lexError(pos, "invalid.hex.number");
+        else
+            scanHexExponentAndSuffix(pos);
+    }
+
+    private void skipIllegalUnderscores() {
+        if (reader.ch == '_') {
+            lexError(reader.bp, "illegal.underscore");
+            while (reader.ch == '_')
+                reader.scanChar();
+        }
+    }
+
+    /** Read a number.
+     *  @param radix  The radix of the number; one of 2, j8, 10, 16.
+     */
+    private void scanNumber(int pos, int radix) {
+        // for octal, allow base-10 digit in case it's a float literal
+        this.radix = radix;
+        int digitRadix = (radix == 8 ? 10 : radix);
+        boolean seendigit = false;
+        if (reader.digit(pos, digitRadix) >= 0) {
+            seendigit = true;
+            scanDigits(pos, digitRadix);
+        }
+        if (radix == 16 && reader.ch == '.') {
+            scanHexFractionAndSuffix(pos, seendigit);
+        } else if (seendigit && radix == 16 && (reader.ch == 'p' || reader.ch == 'P')) {
+            scanHexExponentAndSuffix(pos);
+        } else if (digitRadix == 10 && reader.ch == '.') {
+            putChar(reader.ch);
+            reader.scanChar();
+            scanFractionAndSuffix(pos);
+        } else if (digitRadix == 10 &&
+                   (reader.ch == 'e' || reader.ch == 'E' ||
+                    reader.ch == 'f' || reader.ch == 'F' ||
+                    reader.ch == 'd' || reader.ch == 'D')) {
+            scanFractionAndSuffix(pos);
+        } else {
+            if (reader.ch == 'l' || reader.ch == 'L') {
+                reader.scanChar();
+                tk = TokenKind.LONGLITERAL;
+            } else {
+                tk = TokenKind.INTLITERAL;
+            }
+        }
+    }
+
+    /** Read an identifier.
+     */
+    private void scanIdent() {
+        boolean isJavaIdentifierPart;
+        char high;
+        do {
+            if (sp == sbuf.length) putChar(reader.ch); else sbuf[sp++] = reader.ch;
+            // optimization, was: putChar(reader.ch);
+
+            reader.scanChar();
+            switch (reader.ch) {
+            case 'A': case 'B': case 'C': case 'D': case 'E':
+            case 'F': case 'G': case 'H': case 'I': case 'J':
+            case 'K': case 'L': case 'M': case 'N': case 'O':
+            case 'P': case 'Q': case 'R': case 'S': case 'T':
+            case 'U': case 'V': case 'W': case 'X': case 'Y':
+            case 'Z':
+            case 'a': case 'b': case 'c': case 'd': case 'e':
+            case 'f': case 'g': case 'h': case 'i': case 'j':
+            case 'k': case 'l': case 'm': case 'n': case 'o':
+            case 'p': case 'q': case 'r': case 's': case 't':
+            case 'u': case 'v': case 'w': case 'x': case 'y':
+            case 'z':
+            case '$': case '_':
+            case '0': case '1': case '2': case '3': case '4':
+            case '5': case '6': case '7': case '8': case '9':
+            case '\u0000': case '\u0001': case '\u0002': case '\u0003':
+            case '\u0004': case '\u0005': case '\u0006': case '\u0007':
+            case '\u0008': case '\u000E': case '\u000F': case '\u0010':
+            case '\u0011': case '\u0012': case '\u0013': case '\u0014':
+            case '\u0015': case '\u0016': case '\u0017':
+            case '\u0018': case '\u0019': case '\u001B':
+            case '\u007F':
+                break;
+            case '\u001A': // EOI is also a legal identifier part
+                if (reader.bp >= reader.buflen) {
+                    name = names.fromChars(sbuf, 0, sp);
+                    tk = tokens.lookupKind(name);
+                    return;
+                }
+                break;
+            default:
+                if (reader.ch < '\u0080') {
+                    // all ASCII range chars already handled, above
+                    isJavaIdentifierPart = false;
+                } else {
+                    high = reader.scanSurrogates();
+                    if (high != 0) {
+                        if (sp == sbuf.length) {
+                            putChar(high);
+                        } else {
+                            sbuf[sp++] = high;
+                        }
+                        isJavaIdentifierPart = Character.isJavaIdentifierPart(
+                            Character.toCodePoint(high, reader.ch));
+                    } else {
+                        isJavaIdentifierPart = Character.isJavaIdentifierPart(reader.ch);
+                    }
+                }
+                if (!isJavaIdentifierPart) {
+                    name = names.fromChars(sbuf, 0, sp);
+                    tk = tokens.lookupKind(name);
+                    return;
+                }
+            }
+        } while (true);
+    }
+
+    /** Return true if reader.ch can be part of an operator.
+     */
+    private boolean isSpecial(char ch) {
+        switch (ch) {
+        case '!': case '%': case '&': case '*': case '?':
+        case '+': case '-': case ':': case '<': case '=':
+        case '>': case '^': case '|': case '~':
+        case '@':
+            return true;
+        default:
+            return false;
+        }
+    }
+
+    /** Read longest possible sequence of special characters and convert
+     *  to token.
+     */
+    private void scanOperator() {
+        while (true) {
+            putChar(reader.ch);
+            Name newname = names.fromChars(sbuf, 0, sp);
+            TokenKind tk1 = tokens.lookupKind(newname);
+            if (tk1 == TokenKind.IDENTIFIER) {
+                sp--;
+                break;
+            }
+            tk = tk1;
+            reader.scanChar();
+            if (!isSpecial(reader.ch)) break;
+        }
+    }
+
+    /**
+     * Scan a documentation comment; determine if a deprecated tag is present.
+     * Called once the initial /, * have been skipped, positioned at the second *
+     * (which is treated as the beginning of the first line).
+     * Stops positioned at the closing '/'.
+     */
+    @SuppressWarnings("fallthrough")
+    private void scanDocComment() {
+        boolean deprecatedPrefix = false;
+
+        forEachLine:
+        while (reader.bp < reader.buflen) {
+
+            // Skip optional WhiteSpace at beginning of line
+            while (reader.bp < reader.buflen && (reader.ch == ' ' || reader.ch == '\t' || reader.ch == FF)) {
+                scanCommentChar();
+            }
+
+            // Skip optional consecutive Stars
+            while (reader.bp < reader.buflen && reader.ch == '*') {
+                scanCommentChar();
+                if (reader.ch == '/') {
+                    return;
+                }
+            }
+
+            // Skip optional WhiteSpace after Stars
+            while (reader.bp < reader.buflen && (reader.ch == ' ' || reader.ch == '\t' || reader.ch == FF)) {
+                scanCommentChar();
+            }
+
+            deprecatedPrefix = false;
+            // At beginning of line in the JavaDoc sense.
+            if (reader.bp < reader.buflen && reader.ch == '@' && !deprecatedFlag) {
+                scanCommentChar();
+                if (reader.bp < reader.buflen && reader.ch == 'd') {
+                    scanCommentChar();
+                    if (reader.bp < reader.buflen && reader.ch == 'e') {
+                        scanCommentChar();
+                        if (reader.bp < reader.buflen && reader.ch == 'p') {
+                            scanCommentChar();
+                            if (reader.bp < reader.buflen && reader.ch == 'r') {
+                                scanCommentChar();
+                                if (reader.bp < reader.buflen && reader.ch == 'e') {
+                                    scanCommentChar();
+                                    if (reader.bp < reader.buflen && reader.ch == 'c') {
+                                        scanCommentChar();
+                                        if (reader.bp < reader.buflen && reader.ch == 'a') {
+                                            scanCommentChar();
+                                            if (reader.bp < reader.buflen && reader.ch == 't') {
+                                                scanCommentChar();
+                                                if (reader.bp < reader.buflen && reader.ch == 'e') {
+                                                    scanCommentChar();
+                                                    if (reader.bp < reader.buflen && reader.ch == 'd') {
+                                                        deprecatedPrefix = true;
+                                                        scanCommentChar();
+                                                    }}}}}}}}}}}
+            if (deprecatedPrefix && reader.bp < reader.buflen) {
+                if (Character.isWhitespace(reader.ch)) {
+                    deprecatedFlag = true;
+                } else if (reader.ch == '*') {
+                    scanCommentChar();
+                    if (reader.ch == '/') {
+                        deprecatedFlag = true;
+                        return;
+                    }
+                }
+            }
+
+            // Skip rest of line
+            while (reader.bp < reader.buflen) {
+                switch (reader.ch) {
+                case '*':
+                    scanCommentChar();
+                    if (reader.ch == '/') {
+                        return;
+                    }
+                    break;
+                case CR: // (Spec 3.4)
+                    scanCommentChar();
+                    if (reader.ch != LF) {
+                        continue forEachLine;
+                    }
+                    /* fall through to LF case */
+                case LF: // (Spec 3.4)
+                    scanCommentChar();
+                    continue forEachLine;
+                default:
+                    scanCommentChar();
+                }
+            } // rest of line
+        } // forEachLine
+        return;
+    }
+
+    /** Read token.
+     */
+    public Token readToken() {
+
+        sp = 0;
+        name = null;
+        deprecatedFlag = false;
+        radix = 0;
+        int pos = 0;
+        int endPos = 0;
+
+        try {
+            loop: while (true) {
+                pos = reader.bp;
+                switch (reader.ch) {
+                case ' ': // (Spec 3.6)
+                case '\t': // (Spec 3.6)
+                case FF: // (Spec 3.6)
+                    do {
+                        reader.scanChar();
+                    } while (reader.ch == ' ' || reader.ch == '\t' || reader.ch == FF);
+                    processWhiteSpace(pos, reader.bp);
+                    break;
+                case LF: // (Spec 3.4)
+                    reader.scanChar();
+                    processLineTerminator(pos, reader.bp);
+                    break;
+                case CR: // (Spec 3.4)
+                    reader.scanChar();
+                    if (reader.ch == LF) {
+                        reader.scanChar();
+                    }
+                    processLineTerminator(pos, reader.bp);
+                    break;
+                case 'A': case 'B': case 'C': case 'D': case 'E':
+                case 'F': case 'G': case 'H': case 'I': case 'J':
+                case 'K': case 'L': case 'M': case 'N': case 'O':
+                case 'P': case 'Q': case 'R': case 'S': case 'T':
+                case 'U': case 'V': case 'W': case 'X': case 'Y':
+                case 'Z':
+                case 'a': case 'b': case 'c': case 'd': case 'e':
+                case 'f': case 'g': case 'h': case 'i': case 'j':
+                case 'k': case 'l': case 'm': case 'n': case 'o':
+                case 'p': case 'q': case 'r': case 's': case 't':
+                case 'u': case 'v': case 'w': case 'x': case 'y':
+                case 'z':
+                case '$': case '_':
+                    scanIdent();
+                    break loop;
+                case '0':
+                    reader.scanChar();
+                    if (reader.ch == 'x' || reader.ch == 'X') {
+                        reader.scanChar();
+                        skipIllegalUnderscores();
+                        if (reader.ch == '.') {
+                            scanHexFractionAndSuffix(pos, false);
+                        } else if (reader.digit(pos, 16) < 0) {
+                            lexError(pos, "invalid.hex.number");
+                        } else {
+                            scanNumber(pos, 16);
+                        }
+                    } else if (reader.ch == 'b' || reader.ch == 'B') {
+                        if (!allowBinaryLiterals) {
+                            lexError(pos, "unsupported.binary.lit", source.name);
+                            allowBinaryLiterals = true;
+                        }
+                        reader.scanChar();
+                        skipIllegalUnderscores();
+                        if (reader.digit(pos, 2) < 0) {
+                            lexError(pos, "invalid.binary.number");
+                        } else {
+                            scanNumber(pos, 2);
+                        }
+                    } else {
+                        putChar('0');
+                        if (reader.ch == '_') {
+                            int savePos = reader.bp;
+                            do {
+                                reader.scanChar();
+                            } while (reader.ch == '_');
+                            if (reader.digit(pos, 10) < 0) {
+                                lexError(savePos, "illegal.underscore");
+                            }
+                        }
+                        scanNumber(pos, 8);
+                    }
+                    break loop;
+                case '1': case '2': case '3': case '4':
+                case '5': case '6': case '7': case '8': case '9':
+                    scanNumber(pos, 10);
+                    break loop;
+                case '.':
+                    reader.scanChar();
+                    if ('0' <= reader.ch && reader.ch <= '9') {
+                        putChar('.');
+                        scanFractionAndSuffix(pos);
+                    } else if (reader.ch == '.') {
+                        putChar('.'); putChar('.');
+                        reader.scanChar();
+                        if (reader.ch == '.') {
+                            reader.scanChar();
+                            putChar('.');
+                            tk = TokenKind.ELLIPSIS;
+                        } else {
+                            lexError(pos, "malformed.fp.lit");
+                        }
+                    } else {
+                        tk = TokenKind.DOT;
+                    }
+                    break loop;
+                case ',':
+                    reader.scanChar(); tk = TokenKind.COMMA; break loop;
+                case ';':
+                    reader.scanChar(); tk = TokenKind.SEMI; break loop;
+                case '(':
+                    reader.scanChar(); tk = TokenKind.LPAREN; break loop;
+                case ')':
+                    reader.scanChar(); tk = TokenKind.RPAREN; break loop;
+                case '[':
+                    reader.scanChar(); tk = TokenKind.LBRACKET; break loop;
+                case ']':
+                    reader.scanChar(); tk = TokenKind.RBRACKET; break loop;
+                case '{':
+                    reader.scanChar(); tk = TokenKind.LBRACE; break loop;
+                case '}':
+                    reader.scanChar(); tk = TokenKind.RBRACE; break loop;
+                case '/':
+                    reader.scanChar();
+                    if (reader.ch == '/') {
+                        do {
+                            scanCommentChar();
+                        } while (reader.ch != CR && reader.ch != LF && reader.bp < reader.buflen);
+                        if (reader.bp < reader.buflen) {
+                            processComment(pos, reader.bp, CommentStyle.LINE);
+                        }
+                        break;
+                    } else if (reader.ch == '*') {
+                        reader.scanChar();
+                        CommentStyle style;
+                        if (reader.ch == '*') {
+                            style = CommentStyle.JAVADOC;
+                            scanDocComment();
+                        } else {
+                            style = CommentStyle.BLOCK;
+                            while (reader.bp < reader.buflen) {
+                                if (reader.ch == '*') {
+                                    reader.scanChar();
+                                    if (reader.ch == '/') break;
+                                } else {
+                                    scanCommentChar();
+                                }
+                            }
+                        }
+                        if (reader.ch == '/') {
+                            reader.scanChar();
+                            processComment(pos, reader.bp, style);
+                            break;
+                        } else {
+                            lexError(pos, "unclosed.comment");
+                            break loop;
+                        }
+                    } else if (reader.ch == '=') {
+                        tk = TokenKind.SLASHEQ;
+                        reader.scanChar();
+                    } else {
+                        tk = TokenKind.SLASH;
+                    }
+                    break loop;
+                case '\'':
+                    reader.scanChar();
+                    if (reader.ch == '\'') {
+                        lexError(pos, "empty.char.lit");
+                    } else {
+                        if (reader.ch == CR || reader.ch == LF)
+                            lexError(pos, "illegal.line.end.in.char.lit");
+                        scanLitChar(pos);
+                        char ch2 = reader.ch;
+                        if (reader.ch == '\'') {
+                            reader.scanChar();
+                            tk = TokenKind.CHARLITERAL;
+                        } else {
+                            lexError(pos, "unclosed.char.lit");
+                        }
+                    }
+                    break loop;
+                case '\"':
+                    reader.scanChar();
+                    while (reader.ch != '\"' && reader.ch != CR && reader.ch != LF && reader.bp < reader.buflen)
+                        scanLitChar(pos);
+                    if (reader.ch == '\"') {
+                        tk = TokenKind.STRINGLITERAL;
+                        reader.scanChar();
+                    } else {
+                        lexError(pos, "unclosed.str.lit");
+                    }
+                    break loop;
+                default:
+                    if (isSpecial(reader.ch)) {
+                        scanOperator();
+                    } else {
+                        boolean isJavaIdentifierStart;
+                        if (reader.ch < '\u0080') {
+                            // all ASCII range chars already handled, above
+                            isJavaIdentifierStart = false;
+                        } else {
+                            char high = reader.scanSurrogates();
+                            if (high != 0) {
+                                if (sp == sbuf.length) {
+                                    putChar(high);
+                                } else {
+                                    sbuf[sp++] = high;
+                                }
+
+                                isJavaIdentifierStart = Character.isJavaIdentifierStart(
+                                    Character.toCodePoint(high, reader.ch));
+                            } else {
+                                isJavaIdentifierStart = Character.isJavaIdentifierStart(reader.ch);
+                            }
+                        }
+                        if (isJavaIdentifierStart) {
+                            scanIdent();
+                        } else if (reader.bp == reader.buflen || reader.ch == EOI && reader.bp + 1 == reader.buflen) { // JLS 3.5
+                            tk = TokenKind.EOF;
+                            pos = reader.buflen;
+                        } else {
+                            lexError(pos, "illegal.char", String.valueOf((int)reader.ch));
+                            reader.scanChar();
+                        }
+                    }
+                    break loop;
+                }
+            }
+            endPos = reader.bp;
+            switch (tk.tag) {
+                case DEFAULT: return new Token(tk, pos, endPos, deprecatedFlag);
+                case NAMED: return new NamedToken(tk, pos, endPos, name, deprecatedFlag);
+                case STRING: return new StringToken(tk, pos, endPos, new String(sbuf, 0, sp), deprecatedFlag);
+                case NUMERIC: return new NumericToken(tk, pos, endPos, new String(sbuf, 0, sp), radix, deprecatedFlag);
+                default: throw new AssertionError();
+            }
+        }
+        finally {
+            if (scannerDebug) {
+                    System.out.println("nextToken(" + pos
+                                       + "," + endPos + ")=|" +
+                                       new String(reader.getRawCharacters(pos, endPos))
+                                       + "|");
+            }
+        }
+    }
+
+    /** Return the position where a lexical error occurred;
+     */
+    public int errPos() {
+        return errPos;
+    }
+
+    /** Set the position where a lexical error occurred;
+     */
+    public void errPos(int pos) {
+        errPos = pos;
+    }
+
+    public enum CommentStyle {
+        LINE,
+        BLOCK,
+        JAVADOC,
+    }
+
+    /**
+     * Called when a complete comment has been scanned. pos and endPos
+     * will mark the comment boundary.
+     */
+    protected void processComment(int pos, int endPos, CommentStyle style) {
+        if (scannerDebug)
+            System.out.println("processComment(" + pos
+                               + "," + endPos + "," + style + ")=|"
+                               + new String(reader.getRawCharacters(pos, endPos))
+                               + "|");
+    }
+
+    /**
+     * Called when a complete whitespace run has been scanned. pos and endPos
+     * will mark the whitespace boundary.
+     */
+    protected void processWhiteSpace(int pos, int endPos) {
+        if (scannerDebug)
+            System.out.println("processWhitespace(" + pos
+                               + "," + endPos + ")=|" +
+                               new String(reader.getRawCharacters(pos, endPos))
+                               + "|");
+    }
+
+    /**
+     * Called when a line terminator has been processed.
+     */
+    protected void processLineTerminator(int pos, int endPos) {
+        if (scannerDebug)
+            System.out.println("processTerminator(" + pos
+                               + "," + endPos + ")=|" +
+                               new String(reader.getRawCharacters(pos, endPos))
+                               + "|");
+    }
+
+    /** Build a map for translating between line numbers and
+     * positions in the input.
+     *
+     * @return a LineMap */
+    public Position.LineMap getLineMap() {
+        return Position.makeLineMap(reader.getRawCharacters(), reader.buflen, false);
+    }
+}
--- a/langtools/src/share/classes/com/sun/tools/javac/parser/JavacParser.java	Wed Jul 05 17:53:51 2017 +0200
+++ b/langtools/src/share/classes/com/sun/tools/javac/parser/JavacParser.java	Wed Jul 05 17:54:24 2017 +0200
@@ -28,6 +28,7 @@
 import java.util.*;
 
 import com.sun.tools.javac.code.*;
+import com.sun.tools.javac.parser.Tokens.*;
 import com.sun.tools.javac.tree.*;
 import com.sun.tools.javac.tree.JCTree.*;
 import com.sun.tools.javac.util.*;
@@ -36,7 +37,7 @@
 import com.sun.tools.javac.util.List;
 
 import static com.sun.tools.javac.util.ListBuffer.lb;
-import static com.sun.tools.javac.parser.Token.*;
+import static com.sun.tools.javac.parser.Tokens.TokenKind.*;
 
 /** The parser maps a token sequence into an abstract syntax
  *  tree. It operates by recursive descent, with code derived
@@ -67,9 +68,6 @@
      */
     private Log log;
 
-    /** The keyword table. */
-    private Keywords keywords;
-
     /** The Source language setting. */
     private Source source;
 
@@ -83,11 +81,10 @@
                      boolean keepDocComments,
                      boolean keepLineMap) {
         this.S = S;
-        S.nextToken(); // prime the pump
+        nextToken(); // prime the pump
         this.F = fac.F;
         this.log = fac.log;
         this.names = fac.names;
-        this.keywords = fac.keywords;
         this.source = fac.source;
         this.allowGenerics = source.allowGenerics();
         this.allowVarargs = source.allowVarargs();
@@ -178,7 +175,16 @@
      */
     private int lastmode = 0;
 
-/* ---------- error recovery -------------- */
+    /* ---------- token management -------------- */
+
+    protected Token token;
+
+    protected void nextToken() {
+        S.nextToken();
+        token = S.token();
+    }
+
+    /* ---------- error recovery -------------- */
 
     private JCErroneous errorTree;
 
@@ -186,9 +192,9 @@
      */
     private void skip(boolean stopAtImport, boolean stopAtMemberDecl, boolean stopAtIdentifier, boolean stopAtStatement) {
          while (true) {
-             switch (S.token()) {
+             switch (token.kind) {
                 case SEMI:
-                    S.nextToken();
+                    nextToken();
                     return;
                 case PUBLIC:
                 case FINAL:
@@ -249,15 +255,15 @@
                         return;
                     break;
             }
-            S.nextToken();
+            nextToken();
         }
     }
 
-    private JCErroneous syntaxError(int pos, String key, Token... args) {
+    private JCErroneous syntaxError(int pos, String key, TokenKind... args) {
         return syntaxError(pos, List.<JCTree>nil(), key, args);
     }
 
-    private JCErroneous syntaxError(int pos, List<JCTree> errs, String key, Token... args) {
+    private JCErroneous syntaxError(int pos, List<JCTree> errs, String key, TokenKind... args) {
         setErrorEndPos(pos);
         JCErroneous err = F.at(pos).Erroneous(errs);
         reportSyntaxError(err, key, (Object[])args);
@@ -287,16 +293,16 @@
     private void reportSyntaxError(JCDiagnostic.DiagnosticPosition diagPos, String key, Object... args) {
         int pos = diagPos.getPreferredPosition();
         if (pos > S.errPos() || pos == Position.NOPOS) {
-            if (S.token() == EOF) {
+            if (token.kind == EOF) {
                 error(diagPos, "premature.eof");
             } else {
                 error(diagPos, key, args);
             }
         }
         S.errPos(pos);
-        if (S.pos() == errorPos)
-            S.nextToken(); // guarantee progress
-        errorPos = S.pos();
+        if (token.pos == errorPos)
+            nextToken(); // guarantee progress
+        errorPos = token.pos;
     }
 
 
@@ -304,25 +310,25 @@
      *  reported at the same position.
      */
     private JCErroneous syntaxError(String key) {
-        return syntaxError(S.pos(), key);
+        return syntaxError(token.pos, key);
     }
 
     /** Generate a syntax error at current position unless one was
      *  already reported at the same position.
      */
-    private JCErroneous syntaxError(String key, Token arg) {
-        return syntaxError(S.pos(), key, arg);
+    private JCErroneous syntaxError(String key, TokenKind arg) {
+        return syntaxError(token.pos, key, arg);
     }
 
     /** If next input token matches given token, skip it, otherwise report
      *  an error.
      */
-    public void accept(Token token) {
-        if (S.token() == token) {
-            S.nextToken();
+    public void accept(TokenKind tk) {
+        if (token.kind == tk) {
+            nextToken();
         } else {
-            setErrorEndPos(S.pos());
-            reportSyntaxError(S.prevEndPos(), "expected", token);
+            setErrorEndPos(token.pos);
+            reportSyntaxError(S.prevToken().endPos, "expected", tk);
         }
     }
 
@@ -340,14 +346,14 @@
     /** Report an illegal start of expression/type error at current position.
      */
     JCExpression illegal() {
-        return illegal(S.pos());
+        return illegal(token.pos);
     }
 
     /** Diagnose a modifier flag from the set, if any. */
     void checkNoMods(long mods) {
         if (mods != 0) {
             long lowestMod = mods & -mods;
-            error(S.pos(), "mod.not.allowed.here",
+            error(token.pos, "mod.not.allowed.here",
                       Flags.asFlagSet(lowestMod));
         }
     }
@@ -435,30 +441,30 @@
      * Ident = IDENTIFIER
      */
     Name ident() {
-        if (S.token() == IDENTIFIER) {
-            Name name = S.name();
-            S.nextToken();
+        if (token.kind == IDENTIFIER) {
+            Name name = token.name();
+            nextToken();
             return name;
-        } else if (S.token() == ASSERT) {
+        } else if (token.kind == ASSERT) {
             if (allowAsserts) {
-                error(S.pos(), "assert.as.identifier");
-                S.nextToken();
+                error(token.pos, "assert.as.identifier");
+                nextToken();
                 return names.error;
             } else {
-                warning(S.pos(), "assert.as.identifier");
-                Name name = S.name();
-                S.nextToken();
+                warning(token.pos, "assert.as.identifier");
+                Name name = token.name();
+                nextToken();
                 return name;
             }
-        } else if (S.token() == ENUM) {
+        } else if (token.kind == ENUM) {
             if (allowEnums) {
-                error(S.pos(), "enum.as.identifier");
-                S.nextToken();
+                error(token.pos, "enum.as.identifier");
+                nextToken();
                 return names.error;
             } else {
-                warning(S.pos(), "enum.as.identifier");
-                Name name = S.name();
-                S.nextToken();
+                warning(token.pos, "enum.as.identifier");
+                Name name = token.name();
+                nextToken();
                 return name;
             }
         } else {
@@ -471,17 +477,17 @@
      * Qualident = Ident { DOT Ident }
      */
     public JCExpression qualident() {
-        JCExpression t = toP(F.at(S.pos()).Ident(ident()));
-        while (S.token() == DOT) {
-            int pos = S.pos();
-            S.nextToken();
+        JCExpression t = toP(F.at(token.pos).Ident(ident()));
+        while (token.kind == DOT) {
+            int pos = token.pos;
+            nextToken();
             t = toP(F.at(pos).Select(t, ident()));
         }
         return t;
     }
 
     JCExpression literal(Name prefix) {
-        return literal(prefix, S.pos());
+        return literal(prefix, token.pos);
     }
 
     /**
@@ -498,27 +504,29 @@
      */
     JCExpression literal(Name prefix, int pos) {
         JCExpression t = errorTree;
-        switch (S.token()) {
+        switch (token.kind) {
         case INTLITERAL:
             try {
                 t = F.at(pos).Literal(
                     TypeTags.INT,
-                    Convert.string2int(strval(prefix), S.radix()));
+                    Convert.string2int(strval(prefix), token.radix()));
             } catch (NumberFormatException ex) {
-                error(S.pos(), "int.number.too.large", strval(prefix));
+                error(token.pos, "int.number.too.large", strval(prefix));
             }
             break;
         case LONGLITERAL:
             try {
                 t = F.at(pos).Literal(
                     TypeTags.LONG,
-                    new Long(Convert.string2long(strval(prefix), S.radix())));
+                    new Long(Convert.string2long(strval(prefix), token.radix())));
             } catch (NumberFormatException ex) {
-                error(S.pos(), "int.number.too.large", strval(prefix));
+                error(token.pos, "int.number.too.large", strval(prefix));
             }
             break;
         case FLOATLITERAL: {
-            String proper = (S.radix() == 16 ? ("0x"+ S.stringVal()) : S.stringVal());
+            String proper = token.radix() == 16 ?
+                    ("0x"+ token.stringVal()) :
+                    token.stringVal();
             Float n;
             try {
                 n = Float.valueOf(proper);
@@ -527,15 +535,17 @@
                 n = Float.NaN;
             }
             if (n.floatValue() == 0.0f && !isZero(proper))
-                error(S.pos(), "fp.number.too.small");
+                error(token.pos, "fp.number.too.small");
             else if (n.floatValue() == Float.POSITIVE_INFINITY)
-                error(S.pos(), "fp.number.too.large");
+                error(token.pos, "fp.number.too.large");
             else
                 t = F.at(pos).Literal(TypeTags.FLOAT, n);
             break;
         }
         case DOUBLELITERAL: {
-            String proper = (S.radix() == 16 ? ("0x"+ S.stringVal()) : S.stringVal());
+            String proper = token.radix() == 16 ?
+                    ("0x"+ token.stringVal()) :
+                    token.stringVal();
             Double n;
             try {
                 n = Double.valueOf(proper);
@@ -544,9 +554,9 @@
                 n = Double.NaN;
             }
             if (n.doubleValue() == 0.0d && !isZero(proper))
-                error(S.pos(), "fp.number.too.small");
+                error(token.pos, "fp.number.too.small");
             else if (n.doubleValue() == Double.POSITIVE_INFINITY)
-                error(S.pos(), "fp.number.too.large");
+                error(token.pos, "fp.number.too.large");
             else
                 t = F.at(pos).Literal(TypeTags.DOUBLE, n);
             break;
@@ -554,17 +564,17 @@
         case CHARLITERAL:
             t = F.at(pos).Literal(
                 TypeTags.CHAR,
-                S.stringVal().charAt(0) + 0);
+                token.stringVal().charAt(0) + 0);
             break;
         case STRINGLITERAL:
             t = F.at(pos).Literal(
                 TypeTags.CLASS,
-                S.stringVal());
+                token.stringVal());
             break;
         case TRUE: case FALSE:
             t = F.at(pos).Literal(
                 TypeTags.BOOLEAN,
-                (S.token() == TRUE ? 1 : 0));
+                (token.kind == TRUE ? 1 : 0));
             break;
         case NULL:
             t = F.at(pos).Literal(
@@ -576,8 +586,8 @@
         }
         if (t == errorTree)
             t = F.at(pos).Erroneous();
-        storeEnd(t, S.endPos());
-        S.nextToken();
+        storeEnd(t, token.endPos);
+        nextToken();
         return t;
     }
 //where
@@ -590,7 +600,7 @@
         }
 
         String strval(Name prefix) {
-            String s = S.stringVal();
+            String s = token.stringVal();
             return prefix.isEmpty() ? s : prefix + s;
         }
 
@@ -627,17 +637,17 @@
     JCExpression term() {
         JCExpression t = term1();
         if ((mode & EXPR) != 0 &&
-            S.token() == EQ || PLUSEQ.compareTo(S.token()) <= 0 && S.token().compareTo(GTGTGTEQ) <= 0)
+            token.kind == EQ || PLUSEQ.compareTo(token.kind) <= 0 && token.kind.compareTo(GTGTGTEQ) <= 0)
             return termRest(t);
         else
             return t;
     }
 
     JCExpression termRest(JCExpression t) {
-        switch (S.token()) {
+        switch (token.kind) {
         case EQ: {
-            int pos = S.pos();
-            S.nextToken();
+            int pos = token.pos;
+            nextToken();
             mode = EXPR;
             JCExpression t1 = term();
             return toP(F.at(pos).Assign(t, t1));
@@ -653,12 +663,12 @@
         case LTLTEQ:
         case GTGTEQ:
         case GTGTGTEQ:
-            int pos = S.pos();
-            Token token = S.token();
-            S.nextToken();
+            int pos = token.pos;
+            TokenKind tk = token.kind;
+            nextToken();
             mode = EXPR;
             JCExpression t1 = term();
-            return F.at(pos).Assignop(optag(token), t, t1);
+            return F.at(pos).Assignop(optag(tk), t, t1);
         default:
             return t;
         }
@@ -670,7 +680,7 @@
      */
     JCExpression term1() {
         JCExpression t = term2();
-        if ((mode & EXPR) != 0 && S.token() == QUES) {
+        if ((mode & EXPR) != 0 && token.kind == QUES) {
             mode = EXPR;
             return term1Rest(t);
         } else {
@@ -681,9 +691,9 @@
     /** Expression1Rest = ["?" Expression ":" Expression1]
      */
     JCExpression term1Rest(JCExpression t) {
-        if (S.token() == QUES) {
-            int pos = S.pos();
-            S.nextToken();
+        if (token.kind == QUES) {
+            int pos = token.pos;
+            nextToken();
             JCExpression t1 = term();
             accept(COLON);
             JCExpression t2 = term1();
@@ -699,7 +709,7 @@
      */
     JCExpression term2() {
         JCExpression t = term3();
-        if ((mode & EXPR) != 0 && prec(S.token()) >= TreeInfo.orPrec) {
+        if ((mode & EXPR) != 0 && prec(token.kind) >= TreeInfo.orPrec) {
             mode = EXPR;
             return term2Rest(t, TreeInfo.orPrec);
         } else {
@@ -725,28 +735,23 @@
         JCExpression[] odStack = newOdStack();
         List<Token[]> savedOp = opStackSupply.elems;
         Token[] opStack = newOpStack();
-        List<int[]> savedPos = posStackSupply.elems;
-        int[] posStack = newPosStack();
+
         // optimization, was odStack = new Tree[...]; opStack = new Tree[...];
         int top = 0;
         odStack[0] = t;
-        int startPos = S.pos();
-        Token topOp = ERROR;
-        int topOpPos = Position.NOPOS;
-        while (prec(S.token()) >= minprec) {
-            posStack[top] = topOpPos;
+        int startPos = token.pos;
+        Token topOp = Tokens.DUMMY;
+        while (prec(token.kind) >= minprec) {
             opStack[top] = topOp;
             top++;
-            topOp = S.token();
-            topOpPos = S.pos();
-            S.nextToken();
-            odStack[top] = (topOp == INSTANCEOF) ? parseType() : term3();
-            while (top > 0 && prec(topOp) >= prec(S.token())) {
-                odStack[top-1] = makeOp(topOpPos, topOp, odStack[top-1],
+            topOp = token;
+            nextToken();
+            odStack[top] = (topOp.kind == INSTANCEOF) ? parseType() : term3();
+            while (top > 0 && prec(topOp.kind) >= prec(token.kind)) {
+                odStack[top-1] = makeOp(topOp.pos, topOp.kind, odStack[top-1],
                                         odStack[top]);
                 top--;
                 topOp = opStack[top];
-                topOpPos = posStack[top];
             }
         }
         Assert.check(top == 0);
@@ -761,14 +766,13 @@
 
         odStackSupply.elems = savedOd; // optimization
         opStackSupply.elems = savedOp; // optimization
-        posStackSupply.elems = savedPos; // optimization
         return t;
     }
 //where
         /** Construct a binary or type test node.
          */
         private JCExpression makeOp(int pos,
-                                    Token topOp,
+                                    TokenKind topOp,
                                     JCExpression od1,
                                     JCExpression od2)
         {
@@ -817,7 +821,6 @@
          */
         ListBuffer<JCExpression[]> odStackSupply = new ListBuffer<JCExpression[]>();
         ListBuffer<Token[]> opStackSupply = new ListBuffer<Token[]>();
-        ListBuffer<int[]> posStackSupply = new ListBuffer<int[]>();
 
         private JCExpression[] newOdStack() {
             if (odStackSupply.elems == odStackSupply.last)
@@ -835,14 +838,6 @@
             return opStack;
         }
 
-        private int[] newPosStack() {
-            if (posStackSupply.elems == posStackSupply.last)
-                posStackSupply.append(new int[infixPrecedenceLevels + 1]);
-            int[] posStack = posStackSupply.elems.head;
-            posStackSupply.elems = posStackSupply.elems.tail;
-            return posStack;
-        }
-
     /** Expression3    = PrefixOp Expression3
      *                 | "(" Expr | TypeNoParams ")" Expression3
      *                 | Primary {Selector} {PostfixOp}
@@ -871,10 +866,10 @@
      *  SuperSuffix    = Arguments | "." Ident [Arguments]
      */
     protected JCExpression term3() {
-        int pos = S.pos();
+        int pos = token.pos;
         JCExpression t;
         List<JCExpression> typeArgs = typeArgumentsOpt(EXPR);
-        switch (S.token()) {
+        switch (token.kind) {
         case QUES:
             if ((mode & TYPE) != 0 && (mode & (TYPEARG|NOPARAMS)) == TYPEARG) {
                 mode = TYPE;
@@ -883,49 +878,49 @@
                 return illegal();
         case PLUSPLUS: case SUBSUB: case BANG: case TILDE: case PLUS: case SUB:
             if (typeArgs == null && (mode & EXPR) != 0) {
-                Token token = S.token();
-                S.nextToken();
+                TokenKind tk = token.kind;
+                nextToken();
                 mode = EXPR;
-                if (token == SUB &&
-                    (S.token() == INTLITERAL || S.token() == LONGLITERAL) &&
-                    S.radix() == 10) {
+                if (tk == SUB &&
+                    (token.kind == INTLITERAL || token.kind == LONGLITERAL) &&
+                    token.radix() == 10) {
                     mode = EXPR;
                     t = literal(names.hyphen, pos);
                 } else {
                     t = term3();
-                    return F.at(pos).Unary(unoptag(token), t);
+                    return F.at(pos).Unary(unoptag(tk), t);
                 }
             } else return illegal();
             break;
         case LPAREN:
             if (typeArgs == null && (mode & EXPR) != 0) {
-                S.nextToken();
+                nextToken();
                 mode = EXPR | TYPE | NOPARAMS;
                 t = term3();
-                if ((mode & TYPE) != 0 && S.token() == LT) {
+                if ((mode & TYPE) != 0 && token.kind == LT) {
                     // Could be a cast to a parameterized type
                     int op = JCTree.LT;
-                    int pos1 = S.pos();
-                    S.nextToken();
+                    int pos1 = token.pos;
+                    nextToken();
                     mode &= (EXPR | TYPE);
                     mode |= TYPEARG;
                     JCExpression t1 = term3();
                     if ((mode & TYPE) != 0 &&
-                        (S.token() == COMMA || S.token() == GT)) {
+                        (token.kind == COMMA || token.kind == GT)) {
                         mode = TYPE;
                         ListBuffer<JCExpression> args = new ListBuffer<JCExpression>();
                         args.append(t1);
-                        while (S.token() == COMMA) {
-                            S.nextToken();
+                        while (token.kind == COMMA) {
+                            nextToken();
                             args.append(typeArgument());
                         }
                         accept(GT);
                         t = toP(F.at(pos1).TypeApply(t, args.toList()));
                         checkGenerics();
-                        while (S.token() == DOT) {
-                            S.nextToken();
+                        while (token.kind == DOT) {
+                            nextToken();
                             mode = TYPE;
-                            t = toP(F.at(S.pos()).Select(t, ident()));
+                            t = toP(F.at(token.pos).Select(t, ident()));
                             t = typeArgumentsOpt(t);
                         }
                         t = bracketsOpt(toP(t));
@@ -948,7 +943,7 @@
                     JCExpression t1 = term3();
                     return F.at(pos).TypeCast(t, t1);
                 } else if ((lastmode & TYPE) != 0) {
-                    switch (S.token()) {
+                    switch (token.kind) {
                     /*case PLUSPLUS: case SUBSUB: */
                     case BANG: case TILDE:
                     case LPAREN: case THIS: case SUPER:
@@ -969,7 +964,7 @@
             if ((mode & EXPR) != 0) {
                 mode = EXPR;
                 t = to(F.at(pos).Ident(names._this));
-                S.nextToken();
+                nextToken();
                 if (typeArgs == null)
                     t = argumentsOpt(null, t);
                 else
@@ -997,22 +992,22 @@
             if (typeArgs != null) return illegal();
             if ((mode & EXPR) != 0) {
                 mode = EXPR;
-                S.nextToken();
-                if (S.token() == LT) typeArgs = typeArguments(false);
+                nextToken();
+                if (token.kind == LT) typeArgs = typeArguments(false);
                 t = creator(pos, typeArgs);
                 typeArgs = null;
             } else return illegal();
             break;
         case IDENTIFIER: case ASSERT: case ENUM:
             if (typeArgs != null) return illegal();
-            t = toP(F.at(S.pos()).Ident(ident()));
+            t = toP(F.at(token.pos).Ident(ident()));
             loop: while (true) {
-                pos = S.pos();
-                switch (S.token()) {
+                pos = token.pos;
+                switch (token.kind) {
                 case LBRACKET:
-                    S.nextToken();
-                    if (S.token() == RBRACKET) {
-                        S.nextToken();
+                    nextToken();
+                    if (token.kind == RBRACKET) {
+                        nextToken();
                         t = bracketsOpt(t);
                         t = toP(F.at(pos).TypeArray(t));
                         t = bracketsSuffix(t);
@@ -1033,24 +1028,24 @@
                     }
                     break loop;
                 case DOT:
-                    S.nextToken();
+                    nextToken();
                     int oldmode = mode;
                     mode &= ~NOPARAMS;
                     typeArgs = typeArgumentsOpt(EXPR);
                     mode = oldmode;
                     if ((mode & EXPR) != 0) {
-                        switch (S.token()) {
+                        switch (token.kind) {
                         case CLASS:
                             if (typeArgs != null) return illegal();
                             mode = EXPR;
                             t = to(F.at(pos).Select(t, names._class));
-                            S.nextToken();
+                            nextToken();
                             break loop;
                         case THIS:
                             if (typeArgs != null) return illegal();
                             mode = EXPR;
                             t = to(F.at(pos).Select(t, names._this));
-                            S.nextToken();
+                            nextToken();
                             break loop;
                         case SUPER:
                             mode = EXPR;
@@ -1061,9 +1056,9 @@
                         case NEW:
                             if (typeArgs != null) return illegal();
                             mode = EXPR;
-                            int pos1 = S.pos();
-                            S.nextToken();
-                            if (S.token() == LT) typeArgs = typeArguments(false);
+                            int pos1 = token.pos;
+                            nextToken();
+                            if (token.kind == LT) typeArgs = typeArguments(false);
                             t = innerCreator(pos1, typeArgs, t);
                             typeArgs = null;
                             break loop;
@@ -1087,8 +1082,8 @@
         case VOID:
             if (typeArgs != null) illegal();
             if ((mode & EXPR) != 0) {
-                S.nextToken();
-                if (S.token() == DOT) {
+                nextToken();
+                if (token.kind == DOT) {
                     JCPrimitiveTypeTree ti = toP(F.at(pos).TypeIdent(TypeTags.VOID));
                     t = bracketsSuffix(ti);
                 } else {
@@ -1099,7 +1094,7 @@
                 // a void type (like other primitive types) to the next phase.
                 // The error will be reported in Attr.attribTypes or Attr.visitApply.
                 JCPrimitiveTypeTree ti = to(F.at(pos).TypeIdent(TypeTags.VOID));
-                S.nextToken();
+                nextToken();
                 return ti;
                 //return illegal();
             }
@@ -1109,14 +1104,14 @@
         }
         if (typeArgs != null) illegal();
         while (true) {
-            int pos1 = S.pos();
-            if (S.token() == LBRACKET) {
-                S.nextToken();
+            int pos1 = token.pos;
+            if (token.kind == LBRACKET) {
+                nextToken();
                 if ((mode & TYPE) != 0) {
                     int oldmode = mode;
                     mode = TYPE;
-                    if (S.token() == RBRACKET) {
-                        S.nextToken();
+                    if (token.kind == RBRACKET) {
+                        nextToken();
                         t = bracketsOpt(t);
                         t = toP(F.at(pos1).TypeArray(t));
                         return t;
@@ -1129,21 +1124,21 @@
                     t = to(F.at(pos1).Indexed(t, t1));
                 }
                 accept(RBRACKET);
-            } else if (S.token() == DOT) {
-                S.nextToken();
+            } else if (token.kind == DOT) {
+                nextToken();
                 typeArgs = typeArgumentsOpt(EXPR);
-                if (S.token() == SUPER && (mode & EXPR) != 0) {
+                if (token.kind == SUPER && (mode & EXPR) != 0) {
                     mode = EXPR;
                     t = to(F.at(pos1).Select(t, names._super));
-                    S.nextToken();
+                    nextToken();
                     t = arguments(typeArgs, t);
                     typeArgs = null;
-                } else if (S.token() == NEW && (mode & EXPR) != 0) {
+                } else if (token.kind == NEW && (mode & EXPR) != 0) {
                     if (typeArgs != null) return illegal();
                     mode = EXPR;
-                    int pos2 = S.pos();
-                    S.nextToken();
-                    if (S.token() == LT) typeArgs = typeArguments(false);
+                    int pos2 = token.pos;
+                    nextToken();
+                    if (token.kind == LT) typeArgs = typeArguments(false);
                     t = innerCreator(pos2, typeArgs, t);
                     typeArgs = null;
                 } else {
@@ -1155,11 +1150,11 @@
                 break;
             }
         }
-        while ((S.token() == PLUSPLUS || S.token() == SUBSUB) && (mode & EXPR) != 0) {
+        while ((token.kind == PLUSPLUS || token.kind == SUBSUB) && (mode & EXPR) != 0) {
             mode = EXPR;
-            t = to(F.at(S.pos()).Unary(
-                  S.token() == PLUSPLUS ? JCTree.POSTINC : JCTree.POSTDEC, t));
-            S.nextToken();
+            t = to(F.at(token.pos).Unary(
+                  token.kind == PLUSPLUS ? JCTree.POSTINC : JCTree.POSTDEC, t));
+            nextToken();
         }
         return toP(t);
     }
@@ -1167,13 +1162,13 @@
     /** SuperSuffix = Arguments | "." [TypeArguments] Ident [Arguments]
      */
     JCExpression superSuffix(List<JCExpression> typeArgs, JCExpression t) {
-        S.nextToken();
-        if (S.token() == LPAREN || typeArgs != null) {
+        nextToken();
+        if (token.kind == LPAREN || typeArgs != null) {
             t = arguments(typeArgs, t);
         } else {
-            int pos = S.pos();
+            int pos = token.pos;
             accept(DOT);
-            typeArgs = (S.token() == LT) ? typeArguments(false) : null;
+            typeArgs = (token.kind == LT) ? typeArguments(false) : null;
             t = toP(F.at(pos).Select(t, ident()));
             t = argumentsOpt(typeArgs, t);
         }
@@ -1183,15 +1178,15 @@
     /** BasicType = BYTE | SHORT | CHAR | INT | LONG | FLOAT | DOUBLE | BOOLEAN
      */
     JCPrimitiveTypeTree basicType() {
-        JCPrimitiveTypeTree t = to(F.at(S.pos()).TypeIdent(typetag(S.token())));
-        S.nextToken();
+        JCPrimitiveTypeTree t = to(F.at(token.pos).TypeIdent(typetag(token.kind)));
+        nextToken();
         return t;
     }
 
     /** ArgumentsOpt = [ Arguments ]
      */
     JCExpression argumentsOpt(List<JCExpression> typeArgs, JCExpression t) {
-        if ((mode & EXPR) != 0 && S.token() == LPAREN || typeArgs != null) {
+        if ((mode & EXPR) != 0 && token.kind == LPAREN || typeArgs != null) {
             mode = EXPR;
             return arguments(typeArgs, t);
         } else {
@@ -1203,24 +1198,24 @@
      */
     List<JCExpression> arguments() {
         ListBuffer<JCExpression> args = lb();
-        if (S.token() == LPAREN) {
-            S.nextToken();
-            if (S.token() != RPAREN) {
+        if (token.kind == LPAREN) {
+            nextToken();
+            if (token.kind != RPAREN) {
                 args.append(parseExpression());
-                while (S.token() == COMMA) {
-                    S.nextToken();
+                while (token.kind == COMMA) {
+                    nextToken();
                     args.append(parseExpression());
                 }
             }
             accept(RPAREN);
         } else {
-            syntaxError(S.pos(), "expected", LPAREN);
+            syntaxError(token.pos, "expected", LPAREN);
         }
         return args.toList();
     }
 
     JCMethodInvocation arguments(List<JCExpression> typeArgs, JCExpression t) {
-        int pos = S.pos();
+        int pos = token.pos;
         List<JCExpression> args = arguments();
         return toP(F.at(pos).Apply(typeArgs, t, args));
     }
@@ -1228,7 +1223,7 @@
     /**  TypeArgumentsOpt = [ TypeArguments ]
      */
     JCExpression typeArgumentsOpt(JCExpression t) {
-        if (S.token() == LT &&
+        if (token.kind == LT &&
             (mode & TYPE) != 0 &&
             (mode & NOPARAMS) == 0) {
             mode = TYPE;
@@ -1243,7 +1238,7 @@
     }
 
     List<JCExpression> typeArgumentsOpt(int useMode) {
-        if (S.token() == LT) {
+        if (token.kind == LT) {
             checkGenerics();
             if ((mode & useMode) == 0 ||
                 (mode & NOPARAMS) != 0) {
@@ -1258,47 +1253,37 @@
     /**  TypeArguments  = "<" TypeArgument {"," TypeArgument} ">"
      */
     List<JCExpression> typeArguments(boolean diamondAllowed) {
-        if (S.token() == LT) {
-            S.nextToken();
-            if (S.token() == GT && diamondAllowed) {
+        if (token.kind == LT) {
+            nextToken();
+            if (token.kind == GT && diamondAllowed) {
                 checkDiamond();
                 mode |= DIAMOND;
-                S.nextToken();
+                nextToken();
                 return List.nil();
             } else {
                 ListBuffer<JCExpression> args = ListBuffer.lb();
                 args.append(((mode & EXPR) == 0) ? typeArgument() : parseType());
-                while (S.token() == COMMA) {
-                    S.nextToken();
+                while (token.kind == COMMA) {
+                    nextToken();
                     args.append(((mode & EXPR) == 0) ? typeArgument() : parseType());
                 }
-                switch (S.token()) {
-                case GTGTGTEQ:
-                    S.token(GTGTEQ);
-                    break;
-                case GTGTEQ:
-                    S.token(GTEQ);
-                    break;
-                case GTEQ:
-                    S.token(EQ);
-                    break;
-                case GTGTGT:
-                    S.token(GTGT);
-                    break;
-                case GTGT:
-                    S.token(GT);
+                switch (token.kind) {
+
+                case GTGTGTEQ: case GTGTEQ: case GTEQ:
+                case GTGTGT: case GTGT:
+                    token = S.split();
                     break;
                 case GT:
-                    S.nextToken();
+                    nextToken();
                     break;
                 default:
-                    args.append(syntaxError(S.pos(), "expected", GT));
+                    args.append(syntaxError(token.pos, "expected", GT));
                     break;
                 }
                 return args.toList();
             }
         } else {
-            return List.<JCExpression>of(syntaxError(S.pos(), "expected", LT));
+            return List.<JCExpression>of(syntaxError(token.pos, "expected", LT));
         }
     }
 
@@ -1308,24 +1293,24 @@
      *               | "?" SUPER Type
      */
     JCExpression typeArgument() {
-        if (S.token() != QUES) return parseType();
-        int pos = S.pos();
-        S.nextToken();
-        if (S.token() == EXTENDS) {
+        if (token.kind != QUES) return parseType();
+        int pos = token.pos;
+        nextToken();
+        if (token.kind == EXTENDS) {
             TypeBoundKind t = to(F.at(pos).TypeBoundKind(BoundKind.EXTENDS));
-            S.nextToken();
+            nextToken();
             JCExpression bound = parseType();
             return F.at(pos).Wildcard(t, bound);
-        } else if (S.token() == SUPER) {
+        } else if (token.kind == SUPER) {
             TypeBoundKind t = to(F.at(pos).TypeBoundKind(BoundKind.SUPER));
-            S.nextToken();
+            nextToken();
             JCExpression bound = parseType();
             return F.at(pos).Wildcard(t, bound);
-        } else if (S.token() == IDENTIFIER) {
+        } else if (token.kind == IDENTIFIER) {
             //error recovery
             TypeBoundKind t = F.at(Position.NOPOS).TypeBoundKind(BoundKind.UNBOUND);
             JCExpression wc = toP(F.at(pos).Wildcard(t, null));
-            JCIdent id = toP(F.at(S.pos()).Ident(ident()));
+            JCIdent id = toP(F.at(token.pos).Ident(ident()));
             JCErroneous err = F.at(pos).Erroneous(List.<JCTree>of(wc, id));
             reportSyntaxError(err, "expected3", GT, EXTENDS, SUPER);
             return err;
@@ -1336,7 +1321,7 @@
     }
 
     JCTypeApply typeArguments(JCExpression t, boolean diamondAllowed) {
-        int pos = S.pos();
+        int pos = token.pos;
         List<JCExpression> args = typeArguments(diamondAllowed);
         return toP(F.at(pos).TypeApply(t, args));
     }
@@ -1344,9 +1329,9 @@
     /** BracketsOpt = {"[" "]"}
      */
     private JCExpression bracketsOpt(JCExpression t) {
-        if (S.token() == LBRACKET) {
-            int pos = S.pos();
-            S.nextToken();
+        if (token.kind == LBRACKET) {
+            int pos = token.pos;
+            nextToken();
             t = bracketsOptCont(t, pos);
             F.at(pos);
         }
@@ -1363,17 +1348,17 @@
      *  BracketsSuffixType =
      */
     JCExpression bracketsSuffix(JCExpression t) {
-        if ((mode & EXPR) != 0 && S.token() == DOT) {
+        if ((mode & EXPR) != 0 && token.kind == DOT) {
             mode = EXPR;
-            int pos = S.pos();
-            S.nextToken();
+            int pos = token.pos;
+            nextToken();
             accept(CLASS);
-            if (S.pos() == errorEndPos) {
+            if (token.pos == errorEndPos) {
                 // error recovery
                 Name name = null;
-                if (S.token() == IDENTIFIER) {
-                    name = S.name();
-                    S.nextToken();
+                if (token.kind == IDENTIFIER) {
+                    name = token.name();
+                    nextToken();
                 } else {
                     name = names.error;
                 }
@@ -1384,7 +1369,7 @@
         } else if ((mode & TYPE) != 0) {
             mode = TYPE;
         } else {
-            syntaxError(S.pos(), "dot.class.expected");
+            syntaxError(token.pos, "dot.class.expected");
         }
         return t;
     }
@@ -1392,7 +1377,7 @@
     /** Creator = Qualident [TypeArguments] ( ArrayCreatorRest | ClassCreatorRest )
      */
     JCExpression creator(int newpos, List<JCExpression> typeArgs) {
-        switch (S.token()) {
+        switch (token.kind) {
         case BYTE: case SHORT: case CHAR: case INT: case LONG: case FLOAT:
         case DOUBLE: case BOOLEAN:
             if (typeArgs == null)
@@ -1405,29 +1390,29 @@
         mode = TYPE;
         boolean diamondFound = false;
         int lastTypeargsPos = -1;
-        if (S.token() == LT) {
+        if (token.kind == LT) {
             checkGenerics();
-            lastTypeargsPos = S.pos();
+            lastTypeargsPos = token.pos;
             t = typeArguments(t, true);
             diamondFound = (mode & DIAMOND) != 0;
         }
-        while (S.token() == DOT) {
+        while (token.kind == DOT) {
             if (diamondFound) {
                 //cannot select after a diamond
                 illegal();
             }
-            int pos = S.pos();
-            S.nextToken();
+            int pos = token.pos;
+            nextToken();
             t = toP(F.at(pos).Select(t, ident()));
-            if (S.token() == LT) {
-                lastTypeargsPos = S.pos();
+            if (token.kind == LT) {
+                lastTypeargsPos = token.pos;
                 checkGenerics();
                 t = typeArguments(t, true);
                 diamondFound = (mode & DIAMOND) != 0;
             }
         }
         mode = oldmode;
-        if (S.token() == LBRACKET) {
+        if (token.kind == LBRACKET) {
             JCExpression e = arrayCreatorRest(newpos, t);
             if (diamondFound) {
                 reportSyntaxError(lastTypeargsPos, "cannot.create.array.with.diamond");
@@ -1441,17 +1426,17 @@
                     // modified to improve error recovery.
                     pos = typeArgs.head.pos;
                 }
-                setErrorEndPos(S.prevEndPos());
+                setErrorEndPos(S.prevToken().endPos);
                 JCErroneous err = F.at(pos).Erroneous(typeArgs.prepend(e));
                 reportSyntaxError(err, "cannot.create.array.with.type.arguments");
                 return toP(err);
             }
             return e;
-        } else if (S.token() == LPAREN) {
+        } else if (token.kind == LPAREN) {
             return classCreatorRest(newpos, null, typeArgs, t);
         } else {
-            setErrorEndPos(S.pos());
-            reportSyntaxError(S.pos(), "expected2", LPAREN, LBRACKET);
+            setErrorEndPos(token.pos);
+            reportSyntaxError(token.pos, "expected2", LPAREN, LBRACKET);
             t = toP(F.at(newpos).NewClass(null, typeArgs, t, List.<JCExpression>nil(), null));
             return toP(F.at(newpos).Erroneous(List.<JCTree>of(t)));
         }
@@ -1460,8 +1445,8 @@
     /** InnerCreator = Ident [TypeArguments] ClassCreatorRest
      */
     JCExpression innerCreator(int newpos, List<JCExpression> typeArgs, JCExpression encl) {
-        JCExpression t = toP(F.at(S.pos()).Ident(ident()));
-        if (S.token() == LT) {
+        JCExpression t = toP(F.at(token.pos).Ident(ident()));
+        if (token.kind == LT) {
             int oldmode = mode;
             checkGenerics();
             t = typeArguments(t, true);
@@ -1475,23 +1460,23 @@
      */
     JCExpression arrayCreatorRest(int newpos, JCExpression elemtype) {
         accept(LBRACKET);
-        if (S.token() == RBRACKET) {
+        if (token.kind == RBRACKET) {
             accept(RBRACKET);
             elemtype = bracketsOpt(elemtype);
-            if (S.token() == LBRACE) {
+            if (token.kind == LBRACE) {
                 return arrayInitializer(newpos, elemtype);
             } else {
                 JCExpression t = toP(F.at(newpos).NewArray(elemtype, List.<JCExpression>nil(), null));
-                return syntaxError(S.pos(), List.<JCTree>of(t), "array.dimension.missing");
+                return syntaxError(token.pos, List.<JCTree>of(t), "array.dimension.missing");
             }
         } else {
             ListBuffer<JCExpression> dims = new ListBuffer<JCExpression>();
             dims.append(parseExpression());
             accept(RBRACKET);
-            while (S.token() == LBRACKET) {
-                int pos = S.pos();
-                S.nextToken();
-                if (S.token() == RBRACKET) {
+            while (token.kind == LBRACKET) {
+                int pos = token.pos;
+                nextToken();
+                if (token.kind == RBRACKET) {
                     elemtype = bracketsOptCont(elemtype, pos);
                 } else {
                     dims.append(parseExpression());
@@ -1511,8 +1496,8 @@
     {
         List<JCExpression> args = arguments();
         JCClassDecl body = null;
-        if (S.token() == LBRACE) {
-            int pos = S.pos();
+        if (token.kind == LBRACE) {
+            int pos = token.pos;
             List<JCTree> defs = classOrInterfaceBody(names.empty, false);
             JCModifiers mods = F.at(Position.NOPOS).Modifiers(0);
             body = toP(F.at(pos).AnonymousClassDef(mods, defs));
@@ -1525,13 +1510,13 @@
     JCExpression arrayInitializer(int newpos, JCExpression t) {
         accept(LBRACE);
         ListBuffer<JCExpression> elems = new ListBuffer<JCExpression>();
-        if (S.token() == COMMA) {
-            S.nextToken();
-        } else if (S.token() != RBRACE) {
+        if (token.kind == COMMA) {
+            nextToken();
+        } else if (token.kind != RBRACE) {
             elems.append(variableInitializer());
-            while (S.token() == COMMA) {
-                S.nextToken();
-                if (S.token() == RBRACE) break;
+            while (token.kind == COMMA) {
+                nextToken();
+                if (token.kind == RBRACE) break;
                 elems.append(variableInitializer());
             }
         }
@@ -1542,7 +1527,7 @@
     /** VariableInitializer = ArrayInitializer | Expression
      */
     public JCExpression variableInitializer() {
-        return S.token() == LBRACE ? arrayInitializer(S.pos(), null) : parseExpression();
+        return token.kind == LBRACE ? arrayInitializer(token.pos, null) : parseExpression();
     }
 
     /** ParExpression = "(" Expression ")"
@@ -1560,19 +1545,19 @@
         accept(LBRACE);
         List<JCStatement> stats = blockStatements();
         JCBlock t = F.at(pos).Block(flags, stats);
-        while (S.token() == CASE || S.token() == DEFAULT) {
-            syntaxError("orphaned", S.token());
+        while (token.kind == CASE || token.kind == DEFAULT) {
+            syntaxError("orphaned", token.kind);
             switchBlockStatementGroups();
         }
         // the Block node has a field "endpos" for first char of last token, which is
         // usually but not necessarily the last char of the last token.
-        t.endpos = S.pos();
+        t.endpos = token.pos;
         accept(RBRACE);
         return toP(t);
     }
 
     public JCBlock block() {
-        return block(S.pos(), 0);
+        return block(token.pos, 0);
     }
 
     /** BlockStatements = { BlockStatement }
@@ -1588,8 +1573,8 @@
         int lastErrPos = -1;
         ListBuffer<JCStatement> stats = new ListBuffer<JCStatement>();
         while (true) {
-            int pos = S.pos();
-            switch (S.token()) {
+            int pos = token.pos;
+            switch (token.kind) {
             case RBRACE: case CASE: case DEFAULT: case EOF:
                 return stats.toList();
             case LBRACE: case IF: case FOR: case WHILE: case DO: case TRY:
@@ -1599,64 +1584,63 @@
                 break;
             case MONKEYS_AT:
             case FINAL: {
-                String dc = S.docComment();
+                String dc = token.docComment;
                 JCModifiers mods = modifiersOpt();
-                if (S.token() == INTERFACE ||
-                    S.token() == CLASS ||
-                    allowEnums && S.token() == ENUM) {
+                if (token.kind == INTERFACE ||
+                    token.kind == CLASS ||
+                    allowEnums && token.kind == ENUM) {
                     stats.append(classOrInterfaceOrEnumDeclaration(mods, dc));
                 } else {
                     JCExpression t = parseType();
                     stats.appendList(variableDeclarators(mods, t,
                                                          new ListBuffer<JCStatement>()));
                     // A "LocalVariableDeclarationStatement" subsumes the terminating semicolon
-                    storeEnd(stats.elems.last(), S.endPos());
+                    storeEnd(stats.elems.last(), token.endPos);
                     accept(SEMI);
                 }
                 break;
             }
             case ABSTRACT: case STRICTFP: {
-                String dc = S.docComment();
+                String dc = token.docComment;
                 JCModifiers mods = modifiersOpt();
                 stats.append(classOrInterfaceOrEnumDeclaration(mods, dc));
                 break;
             }
             case INTERFACE:
             case CLASS:
-                stats.append(classOrInterfaceOrEnumDeclaration(modifiersOpt(),
-                                                               S.docComment()));
+                String dc = token.docComment;
+                stats.append(classOrInterfaceOrEnumDeclaration(modifiersOpt(), dc));
                 break;
             case ENUM:
             case ASSERT:
-                if (allowEnums && S.token() == ENUM) {
-                    error(S.pos(), "local.enum");
-                    stats.
-                        append(classOrInterfaceOrEnumDeclaration(modifiersOpt(),
-                                                                 S.docComment()));
+                if (allowEnums && token.kind == ENUM) {
+                    error(token.pos, "local.enum");
+                    dc = token.docComment;
+                    stats.append(classOrInterfaceOrEnumDeclaration(modifiersOpt(), dc));
                     break;
-                } else if (allowAsserts && S.token() == ASSERT) {
+                } else if (allowAsserts && token.kind == ASSERT) {
                     stats.append(parseStatement());
                     break;
                 }
                 /* fall through to default */
             default:
-                Name name = S.name();
+                Token prevToken = token;
                 JCExpression t = term(EXPR | TYPE);
-                if (S.token() == COLON && t.getTag() == JCTree.IDENT) {
-                    S.nextToken();
+                if (token.kind == COLON && t.getTag() == JCTree.IDENT) {
+                    nextToken();
                     JCStatement stat = parseStatement();
-                    stats.append(F.at(pos).Labelled(name, stat));
+                    stats.append(F.at(pos).Labelled(prevToken.name(), stat));
                 } else if ((lastmode & TYPE) != 0 &&
-                           (S.token() == IDENTIFIER ||
-                            S.token() == ASSERT ||
-                            S.token() == ENUM)) {
-                    pos = S.pos();
+                           (token.kind == IDENTIFIER ||
+                            token.kind == ASSERT ||
+                            token.kind == ENUM)) {
+                    pos = token.pos;
                     JCModifiers mods = F.at(Position.NOPOS).Modifiers(0);
                     F.at(pos);
                     stats.appendList(variableDeclarators(mods, t,
                                                          new ListBuffer<JCStatement>()));
                     // A "LocalVariableDeclarationStatement" subsumes the terminating semicolon
-                    storeEnd(stats.elems.last(), S.endPos());
+                    storeEnd(stats.elems.last(), token.endPos);
                     accept(SEMI);
                 } else {
                     // This Exec is an "ExpressionStatement"; it subsumes the terminating semicolon
@@ -1666,15 +1650,12 @@
             }
 
             // error recovery
-            if (S.pos() == lastErrPos)
+            if (token.pos == lastErrPos)
                 return stats.toList();
-            if (S.pos() <= errorEndPos) {
+            if (token.pos <= errorEndPos) {
                 skip(false, true, true, true);
-                lastErrPos = S.pos();
+                lastErrPos = token.pos;
             }
-
-            // ensure no dangling /** @deprecated */ active
-            S.resetDeprecatedFlag();
         }
     }
 
@@ -1700,29 +1681,29 @@
      */
     @SuppressWarnings("fallthrough")
     public JCStatement parseStatement() {
-        int pos = S.pos();
-        switch (S.token()) {
+        int pos = token.pos;
+        switch (token.kind) {
         case LBRACE:
             return block();
         case IF: {
-            S.nextToken();
+            nextToken();
             JCExpression cond = parExpression();
             JCStatement thenpart = parseStatement();
             JCStatement elsepart = null;
-            if (S.token() == ELSE) {
-                S.nextToken();
+            if (token.kind == ELSE) {
+                nextToken();
                 elsepart = parseStatement();
             }
             return F.at(pos).If(cond, thenpart, elsepart);
         }
         case FOR: {
-            S.nextToken();
+            nextToken();
             accept(LPAREN);
-            List<JCStatement> inits = S.token() == SEMI ? List.<JCStatement>nil() : forInit();
+            List<JCStatement> inits = token.kind == SEMI ? List.<JCStatement>nil() : forInit();
             if (inits.length() == 1 &&
                 inits.head.getTag() == JCTree.VARDEF &&
                 ((JCVariableDecl) inits.head).init == null &&
-                S.token() == COLON) {
+                token.kind == COLON) {
                 checkForeach();
                 JCVariableDecl var = (JCVariableDecl)inits.head;
                 accept(COLON);
@@ -1732,22 +1713,22 @@
                 return F.at(pos).ForeachLoop(var, expr, body);
             } else {
                 accept(SEMI);
-                JCExpression cond = S.token() == SEMI ? null : parseExpression();
+                JCExpression cond = token.kind == SEMI ? null : parseExpression();
                 accept(SEMI);
-                List<JCExpressionStatement> steps = S.token() == RPAREN ? List.<JCExpressionStatement>nil() : forUpdate();
+                List<JCExpressionStatement> steps = token.kind == RPAREN ? List.<JCExpressionStatement>nil() : forUpdate();
                 accept(RPAREN);
                 JCStatement body = parseStatement();
                 return F.at(pos).ForLoop(inits, cond, steps, body);
             }
         }
         case WHILE: {
-            S.nextToken();
+            nextToken();
             JCExpression cond = parExpression();
             JCStatement body = parseStatement();
             return F.at(pos).WhileLoop(cond, body);
         }
         case DO: {
-            S.nextToken();
+            nextToken();
             JCStatement body = parseStatement();
             accept(WHILE);
             JCExpression cond = parExpression();
@@ -1756,21 +1737,21 @@
             return t;
         }
         case TRY: {
-            S.nextToken();
+            nextToken();
             List<JCTree> resources = List.<JCTree>nil();
-            if (S.token() == LPAREN) {
+            if (token.kind == LPAREN) {
                 checkTryWithResources();
-                S.nextToken();
+                nextToken();
                 resources = resources();
                 accept(RPAREN);
             }
             JCBlock body = block();
             ListBuffer<JCCatch> catchers = new ListBuffer<JCCatch>();
             JCBlock finalizer = null;
-            if (S.token() == CATCH || S.token() == FINALLY) {
-                while (S.token() == CATCH) catchers.append(catchClause());
-                if (S.token() == FINALLY) {
-                    S.nextToken();
+            if (token.kind == CATCH || token.kind == FINALLY) {
+                while (token.kind == CATCH) catchers.append(catchClause());
+                if (token.kind == FINALLY) {
+                    nextToken();
                     finalizer = block();
                 }
             } else {
@@ -1783,7 +1764,7 @@
             return F.at(pos).Try(resources, body, catchers.toList(), finalizer);
         }
         case SWITCH: {
-            S.nextToken();
+            nextToken();
             JCExpression selector = parExpression();
             accept(LBRACE);
             List<JCCase> cases = switchBlockStatementGroups();
@@ -1792,41 +1773,41 @@
             return t;
         }
         case SYNCHRONIZED: {
-            S.nextToken();
+            nextToken();
             JCExpression lock = parExpression();
             JCBlock body = block();
             return F.at(pos).Synchronized(lock, body);
         }
         case RETURN: {
-            S.nextToken();
-            JCExpression result = S.token() == SEMI ? null : parseExpression();
+            nextToken();
+            JCExpression result = token.kind == SEMI ? null : parseExpression();
             JCReturn t = to(F.at(pos).Return(result));
             accept(SEMI);
             return t;
         }
         case THROW: {
-            S.nextToken();
+            nextToken();
             JCExpression exc = parseExpression();
             JCThrow t = to(F.at(pos).Throw(exc));
             accept(SEMI);
             return t;
         }
         case BREAK: {
-            S.nextToken();
-            Name label = (S.token() == IDENTIFIER || S.token() == ASSERT || S.token() == ENUM) ? ident() : null;
+            nextToken();
+            Name label = (token.kind == IDENTIFIER || token.kind == ASSERT || token.kind == ENUM) ? ident() : null;
             JCBreak t = to(F.at(pos).Break(label));
             accept(SEMI);
             return t;
         }
         case CONTINUE: {
-            S.nextToken();
-            Name label = (S.token() == IDENTIFIER || S.token() == ASSERT || S.token() == ENUM) ? ident() : null;
+            nextToken();
+            Name label = (token.kind == IDENTIFIER || token.kind == ASSERT || token.kind == ENUM) ? ident() : null;
             JCContinue t =  to(F.at(pos).Continue(label));
             accept(SEMI);
             return t;
         }
         case SEMI:
-            S.nextToken();
+            nextToken();
             return toP(F.at(pos).Skip());
         case ELSE:
             return toP(F.Exec(syntaxError("else.without.if")));
@@ -1835,12 +1816,12 @@
         case CATCH:
             return toP(F.Exec(syntaxError("catch.without.try")));
         case ASSERT: {
-            if (allowAsserts && S.token() == ASSERT) {
-                S.nextToken();
+            if (allowAsserts && token.kind == ASSERT) {
+                nextToken();
                 JCExpression assertion = parseExpression();
                 JCExpression message = null;
-                if (S.token() == COLON) {
-                    S.nextToken();
+                if (token.kind == COLON) {
+                    nextToken();
                     message = parseExpression();
                 }
                 JCAssert t = to(F.at(pos).Assert(assertion, message));
@@ -1851,12 +1832,12 @@
         }
         case ENUM:
         default:
-            Name name = S.name();
+            Token prevToken = token;
             JCExpression expr = parseExpression();
-            if (S.token() == COLON && expr.getTag() == JCTree.IDENT) {
-                S.nextToken();
+            if (token.kind == COLON && expr.getTag() == JCTree.IDENT) {
+                nextToken();
                 JCStatement stat = parseStatement();
-                return F.at(pos).Labelled(name, stat);
+                return F.at(pos).Labelled(prevToken.name(), stat);
             } else {
                 // This Exec is an "ExpressionStatement"; it subsumes the terminating semicolon
                 JCExpressionStatement stat = to(F.at(pos).Exec(checkExprStat(expr)));
@@ -1869,7 +1850,7 @@
     /** CatchClause     = CATCH "(" FormalParameter ")" Block
      */
     protected JCCatch catchClause() {
-        int pos = S.pos();
+        int pos = token.pos;
         accept(CATCH);
         accept(LPAREN);
         JCModifiers mods = optFinal(Flags.PARAMETER);
@@ -1886,9 +1867,9 @@
     List<JCExpression> catchTypes() {
         ListBuffer<JCExpression> catchTypes = ListBuffer.lb();
         catchTypes.add(parseType());
-        while (S.token() == BAR) {
+        while (token.kind == BAR) {
             checkMulticatch();
-            S.nextToken();
+            nextToken();
             catchTypes.add(qualident());
         }
         return catchTypes.toList();
@@ -1901,33 +1882,33 @@
     List<JCCase> switchBlockStatementGroups() {
         ListBuffer<JCCase> cases = new ListBuffer<JCCase>();
         while (true) {
-            int pos = S.pos();
-            switch (S.token()) {
+            int pos = token.pos;
+            switch (token.kind) {
             case CASE: {
-                S.nextToken();
+                nextToken();
                 JCExpression pat = parseExpression();
                 accept(COLON);
                 List<JCStatement> stats = blockStatements();
                 JCCase c = F.at(pos).Case(pat, stats);
                 if (stats.isEmpty())
-                    storeEnd(c, S.prevEndPos());
+                    storeEnd(c, S.prevToken().endPos);
                 cases.append(c);
                 break;
             }
             case DEFAULT: {
-                S.nextToken();
+                nextToken();
                 accept(COLON);
                 List<JCStatement> stats = blockStatements();
                 JCCase c = F.at(pos).Case(null, stats);
                 if (stats.isEmpty())
-                    storeEnd(c, S.prevEndPos());
+                    storeEnd(c, S.prevToken().endPos);
                 cases.append(c);
                 break;
             }
             case RBRACE: case EOF:
                 return cases.toList();
             default:
-                S.nextToken(); // to ensure progress
+                nextToken(); // to ensure progress
                 syntaxError(pos, "expected3",
                     CASE, DEFAULT, RBRACE);
             }
@@ -1941,9 +1922,9 @@
                                                                     T stats) {
         // This Exec is a "StatementExpression"; it subsumes no terminating token
         stats.append(toP(F.at(pos).Exec(checkExprStat(first))));
-        while (S.token() == COMMA) {
-            S.nextToken();
-            pos = S.pos();
+        while (token.kind == COMMA) {
+            nextToken();
+            pos = token.pos;
             JCExpression t = parseExpression();
             // This Exec is a "StatementExpression"; it subsumes no terminating token
             stats.append(toP(F.at(pos).Exec(checkExprStat(t))));
@@ -1956,13 +1937,13 @@
      */
     List<JCStatement> forInit() {
         ListBuffer<JCStatement> stats = lb();
-        int pos = S.pos();
-        if (S.token() == FINAL || S.token() == MONKEYS_AT) {
+        int pos = token.pos;
+        if (token.kind == FINAL || token.kind == MONKEYS_AT) {
             return variableDeclarators(optFinal(0), parseType(), stats).toList();
         } else {
             JCExpression t = term(EXPR | TYPE);
             if ((lastmode & TYPE) != 0 &&
-                (S.token() == IDENTIFIER || S.token() == ASSERT || S.token() == ENUM))
+                (token.kind == IDENTIFIER || token.kind == ASSERT || token.kind == ENUM))
                 return variableDeclarators(modifiersOpt(), t, stats).toList();
             else
                 return moreStatementExpressions(pos, t, stats).toList();
@@ -1972,7 +1953,7 @@
     /** ForUpdate = StatementExpression MoreStatementExpressions
      */
     List<JCExpressionStatement> forUpdate() {
-        return moreStatementExpressions(S.pos(),
+        return moreStatementExpressions(token.pos,
                                         parseExpression(),
                                         new ListBuffer<JCExpressionStatement>()).toList();
     }
@@ -1980,11 +1961,11 @@
     /** AnnotationsOpt = { '@' Annotation }
      */
     List<JCAnnotation> annotationsOpt() {
-        if (S.token() != MONKEYS_AT) return List.nil(); // optimization
+        if (token.kind != MONKEYS_AT) return List.nil(); // optimization
         ListBuffer<JCAnnotation> buf = new ListBuffer<JCAnnotation>();
-        while (S.token() == MONKEYS_AT) {
-            int pos = S.pos();
-            S.nextToken();
+        while (token.kind == MONKEYS_AT) {
+            int pos = token.pos;
+            nextToken();
             buf.append(annotation(pos));
         }
         return buf.toList();
@@ -2004,21 +1985,20 @@
         int pos;
         if (partial == null) {
             flags = 0;
-            pos = S.pos();
+            pos = token.pos;
         } else {
             flags = partial.flags;
             annotations.appendList(partial.annotations);
             pos = partial.pos;
         }
-        if (S.deprecatedFlag()) {
+        if (token.deprecatedFlag) {
             flags |= Flags.DEPRECATED;
-            S.resetDeprecatedFlag();
         }
         int lastPos = Position.NOPOS;
     loop:
         while (true) {
             long flag;
-            switch (S.token()) {
+            switch (token.kind) {
             case PRIVATE     : flag = Flags.PRIVATE; break;
             case PROTECTED   : flag = Flags.PROTECTED; break;
             case PUBLIC      : flag = Flags.PUBLIC; break;
@@ -2031,15 +2011,15 @@
             case SYNCHRONIZED: flag = Flags.SYNCHRONIZED; break;
             case STRICTFP    : flag = Flags.STRICTFP; break;
             case MONKEYS_AT  : flag = Flags.ANNOTATION; break;
-            case ERROR       : flag = 0; S.nextToken(); break;
+            case ERROR       : flag = 0; nextToken(); break;
             default: break loop;
             }
-            if ((flags & flag) != 0) error(S.pos(), "repeated.modifier");
-            lastPos = S.pos();
-            S.nextToken();
+            if ((flags & flag) != 0) error(token.pos, "repeated.modifier");
+            lastPos = token.pos;
+            nextToken();
             if (flag == Flags.ANNOTATION) {
                 checkAnnotations();
-                if (S.token() != INTERFACE) {
+                if (token.kind != INTERFACE) {
                     JCAnnotation ann = annotation(lastPos);
                     // if first modifier is an annotation, set pos to annotation's.
                     if (flags == 0 && annotations.isEmpty())
@@ -2051,7 +2031,7 @@
             }
             flags |= flag;
         }
-        switch (S.token()) {
+        switch (token.kind) {
         case ENUM: flags |= Flags.ENUM; break;
         case INTERFACE: flags |= Flags.INTERFACE; break;
         default: break;
@@ -2064,7 +2044,7 @@
 
         JCModifiers mods = F.at(pos).Modifiers(flags, annotations.toList());
         if (pos != Position.NOPOS)
-            storeEnd(mods, S.prevEndPos());
+            storeEnd(mods, S.prevToken().endPos);
         return mods;
     }
 
@@ -2077,22 +2057,22 @@
         JCTree ident = qualident();
         List<JCExpression> fieldValues = annotationFieldValuesOpt();
         JCAnnotation ann = F.at(pos).Annotation(ident, fieldValues);
-        storeEnd(ann, S.prevEndPos());
+        storeEnd(ann, S.prevToken().endPos);
         return ann;
     }
 
     List<JCExpression> annotationFieldValuesOpt() {
-        return (S.token() == LPAREN) ? annotationFieldValues() : List.<JCExpression>nil();
+        return (token.kind == LPAREN) ? annotationFieldValues() : List.<JCExpression>nil();
     }
 
     /** AnnotationFieldValues   = "(" [ AnnotationFieldValue { "," AnnotationFieldValue } ] ")" */
     List<JCExpression> annotationFieldValues() {
         accept(LPAREN);
         ListBuffer<JCExpression> buf = new ListBuffer<JCExpression>();
-        if (S.token() != RPAREN) {
+        if (token.kind != RPAREN) {
             buf.append(annotationFieldValue());
-            while (S.token() == COMMA) {
-                S.nextToken();
+            while (token.kind == COMMA) {
+                nextToken();
                 buf.append(annotationFieldValue());
             }
         }
@@ -2104,11 +2084,11 @@
      *                          | Identifier "=" AnnotationValue
      */
     JCExpression annotationFieldValue() {
-        if (S.token() == IDENTIFIER) {
+        if (token.kind == IDENTIFIER) {
             mode = EXPR;
             JCExpression t1 = term1();
-            if (t1.getTag() == JCTree.IDENT && S.token() == EQ) {
-                int pos = S.pos();
+            if (t1.getTag() == JCTree.IDENT && token.kind == EQ) {
+                int pos = token.pos;
                 accept(EQ);
                 JCExpression v = annotationValue();
                 return toP(F.at(pos).Assign(t1, v));
@@ -2125,20 +2105,20 @@
      */
     JCExpression annotationValue() {
         int pos;
-        switch (S.token()) {
+        switch (token.kind) {
         case MONKEYS_AT:
-            pos = S.pos();
-            S.nextToken();
+            pos = token.pos;
+            nextToken();
             return annotation(pos);
         case LBRACE:
-            pos = S.pos();
+            pos = token.pos;
             accept(LBRACE);
             ListBuffer<JCExpression> buf = new ListBuffer<JCExpression>();
-            if (S.token() != RBRACE) {
+            if (token.kind != RBRACE) {
                 buf.append(annotationValue());
-                while (S.token() == COMMA) {
-                    S.nextToken();
-                    if (S.token() == RBRACE) break;
+                while (token.kind == COMMA) {
+                    nextToken();
+                    if (token.kind == RBRACE) break;
                     buf.append(annotationValue());
                 }
             }
@@ -2156,7 +2136,7 @@
                                                                          JCExpression type,
                                                                          T vdefs)
     {
-        return variableDeclaratorsRest(S.pos(), mods, type, ident(), false, null, vdefs);
+        return variableDeclaratorsRest(token.pos, mods, type, ident(), false, null, vdefs);
     }
 
     /** VariableDeclaratorsRest = VariableDeclaratorRest { "," VariableDeclarator }
@@ -2174,10 +2154,10 @@
                                                                      T vdefs)
     {
         vdefs.append(variableDeclaratorRest(pos, mods, type, name, reqInit, dc));
-        while (S.token() == COMMA) {
+        while (token.kind == COMMA) {
             // All but last of multiple declarators subsume a comma
-            storeEnd((JCTree)vdefs.elems.last(), S.endPos());
-            S.nextToken();
+            storeEnd((JCTree)vdefs.elems.last(), token.endPos);
+            nextToken();
             vdefs.append(variableDeclarator(mods, type, reqInit, dc));
         }
         return vdefs;
@@ -2187,7 +2167,7 @@
      *  ConstantDeclarator = Ident ConstantDeclaratorRest
      */
     JCVariableDecl variableDeclarator(JCModifiers mods, JCExpression type, boolean reqInit, String dc) {
-        return variableDeclaratorRest(S.pos(), mods, type, ident(), reqInit, dc);
+        return variableDeclaratorRest(token.pos, mods, type, ident(), reqInit, dc);
     }
 
     /** VariableDeclaratorRest = BracketsOpt ["=" VariableInitializer]
@@ -2200,11 +2180,11 @@
                                   boolean reqInit, String dc) {
         type = bracketsOpt(type);
         JCExpression init = null;
-        if (S.token() == EQ) {
-            S.nextToken();
+        if (token.kind == EQ) {
+            nextToken();
             init = variableInitializer();
         }
-        else if (reqInit) syntaxError(S.pos(), "expected", EQ);
+        else if (reqInit) syntaxError(token.pos, "expected", EQ);
         JCVariableDecl result =
             toP(F.at(pos).VarDef(mods, name, type, init));
         attach(result, dc);
@@ -2214,11 +2194,11 @@
     /** VariableDeclaratorId = Ident BracketsOpt
      */
     JCVariableDecl variableDeclaratorId(JCModifiers mods, JCExpression type) {
-        int pos = S.pos();
+        int pos = token.pos;
         Name name = ident();
         if ((mods.flags & Flags.VARARGS) != 0 &&
-                S.token() == LBRACKET) {
-            log.error(S.pos(), "varargs.and.old.array.syntax");
+                token.kind == LBRACKET) {
+            log.error(token.pos, "varargs.and.old.array.syntax");
         }
         type = bracketsOpt(type);
         return toP(F.at(pos).VarDef(mods, name, type, null));
@@ -2229,12 +2209,12 @@
     List<JCTree> resources() {
         ListBuffer<JCTree> defs = new ListBuffer<JCTree>();
         defs.append(resource());
-        while (S.token() == SEMI) {
+        while (token.kind == SEMI) {
             // All but last of multiple declarators must subsume a semicolon
-            storeEnd(defs.elems.last(), S.endPos());
-            int semiColonPos = S.pos();
-            S.nextToken();
-            if (S.token() == RPAREN) { // Optional trailing semicolon
+            storeEnd(defs.elems.last(), token.endPos);
+            int semiColonPos = token.pos;
+            nextToken();
+            if (token.kind == RPAREN) { // Optional trailing semicolon
                                        // after last resource
                 break;
             }
@@ -2248,7 +2228,7 @@
     protected JCTree resource() {
         JCModifiers optFinal = optFinal(Flags.FINAL);
         JCExpression type = parseType();
-        int pos = S.pos();
+        int pos = token.pos;
         Name ident = ident();
         return variableDeclaratorRest(pos, optFinal, type, ident, true, null);
     }
@@ -2256,54 +2236,61 @@
     /** CompilationUnit = [ { "@" Annotation } PACKAGE Qualident ";"] {ImportDeclaration} {TypeDeclaration}
      */
     public JCTree.JCCompilationUnit parseCompilationUnit() {
-        int pos = S.pos();
+        Token firstToken = token;
         JCExpression pid = null;
-        String dc = S.docComment();
         JCModifiers mods = null;
+        boolean consumedToplevelDoc = false;
+        boolean seenImport = false;
+        boolean seenPackage = false;
         List<JCAnnotation> packageAnnotations = List.nil();
-        if (S.token() == MONKEYS_AT)
+        if (token.kind == MONKEYS_AT)
             mods = modifiersOpt();
 
-        if (S.token() == PACKAGE) {
+        if (token.kind == PACKAGE) {
+            seenPackage = true;
             if (mods != null) {
                 checkNoMods(mods.flags);
                 packageAnnotations = mods.annotations;
                 mods = null;
             }
-            S.nextToken();
+            nextToken();
             pid = qualident();
             accept(SEMI);
         }
         ListBuffer<JCTree> defs = new ListBuffer<JCTree>();
         boolean checkForImports = true;
-        while (S.token() != EOF) {
-            if (S.pos() <= errorEndPos) {
+        boolean firstTypeDecl = true;
+        while (token.kind != EOF) {
+            if (token.pos <= errorEndPos) {
                 // error recovery
                 skip(checkForImports, false, false, false);
-                if (S.token() == EOF)
+                if (token.kind == EOF)
                     break;
             }
-            if (checkForImports && mods == null && S.token() == IMPORT) {
+            if (checkForImports && mods == null && token.kind == IMPORT) {
+                seenImport = true;
                 defs.append(importDeclaration());
             } else {
-                JCTree def = typeDeclaration(mods);
-                if (keepDocComments && dc != null && docComments.get(def) == dc) {
-                    // If the first type declaration has consumed the first doc
-                    // comment, then don't use it for the top level comment as well.
-                    dc = null;
+                String docComment = token.docComment;
+                if (firstTypeDecl && !seenImport && !seenPackage) {
+                    docComment = firstToken.docComment;
+                    consumedToplevelDoc = true;
                 }
+                JCTree def = typeDeclaration(mods, docComment);
                 if (def instanceof JCExpressionStatement)
                     def = ((JCExpressionStatement)def).expr;
                 defs.append(def);
                 if (def instanceof JCClassDecl)
                     checkForImports = false;
                 mods = null;
+                firstTypeDecl = false;
             }
         }
-        JCTree.JCCompilationUnit toplevel = F.at(pos).TopLevel(packageAnnotations, pid, defs.toList());
-        attach(toplevel, dc);
+        JCTree.JCCompilationUnit toplevel = F.at(firstToken.pos).TopLevel(packageAnnotations, pid, defs.toList());
+        if (!consumedToplevelDoc)
+            attach(toplevel, firstToken.docComment);
         if (defs.elems.isEmpty())
-            storeEnd(toplevel, S.prevEndPos());
+            storeEnd(toplevel, S.prevToken().endPos);
         if (keepDocComments)
             toplevel.docComments = docComments;
         if (keepLineMap)
@@ -2314,26 +2301,26 @@
     /** ImportDeclaration = IMPORT [ STATIC ] Ident { "." Ident } [ "." "*" ] ";"
      */
     JCTree importDeclaration() {
-        int pos = S.pos();
-        S.nextToken();
+        int pos = token.pos;
+        nextToken();
         boolean importStatic = false;
-        if (S.token() == STATIC) {
+        if (token.kind == STATIC) {
             checkStaticImports();
             importStatic = true;
-            S.nextToken();
+            nextToken();
         }
-        JCExpression pid = toP(F.at(S.pos()).Ident(ident()));
+        JCExpression pid = toP(F.at(token.pos).Ident(ident()));
         do {
-            int pos1 = S.pos();
+            int pos1 = token.pos;
             accept(DOT);
-            if (S.token() == STAR) {
+            if (token.kind == STAR) {
                 pid = to(F.at(pos1).Select(pid, names.asterisk));
-                S.nextToken();
+                nextToken();
                 break;
             } else {
                 pid = toP(F.at(pos1).Select(pid, ident()));
             }
-        } while (S.token() == DOT);
+        } while (token.kind == DOT);
         accept(SEMI);
         return toP(F.at(pos).Import(pid, importStatic));
     }
@@ -2341,14 +2328,13 @@
     /** TypeDeclaration = ClassOrInterfaceOrEnumDeclaration
      *                  | ";"
      */
-    JCTree typeDeclaration(JCModifiers mods) {
-        int pos = S.pos();
-        if (mods == null && S.token() == SEMI) {
-            S.nextToken();
+    JCTree typeDeclaration(JCModifiers mods, String docComment) {
+        int pos = token.pos;
+        if (mods == null && token.kind == SEMI) {
+            nextToken();
             return toP(F.at(pos).Skip());
         } else {
-            String dc = S.docComment();
-            return classOrInterfaceOrEnumDeclaration(modifiersOpt(mods), dc);
+            return classOrInterfaceOrEnumDeclaration(modifiersOpt(mods), docComment);
         }
     }
 
@@ -2358,19 +2344,19 @@
      *  @param dc       The documentation comment for the class, or null.
      */
     JCStatement classOrInterfaceOrEnumDeclaration(JCModifiers mods, String dc) {
-        if (S.token() == CLASS) {
+        if (token.kind == CLASS) {
             return classDeclaration(mods, dc);
-        } else if (S.token() == INTERFACE) {
+        } else if (token.kind == INTERFACE) {
             return interfaceDeclaration(mods, dc);
         } else if (allowEnums) {
-            if (S.token() == ENUM) {
+            if (token.kind == ENUM) {
                 return enumDeclaration(mods, dc);
             } else {
-                int pos = S.pos();
+                int pos = token.pos;
                 List<JCTree> errs;
-                if (S.token() == IDENTIFIER) {
+                if (token.kind == IDENTIFIER) {
                     errs = List.<JCTree>of(mods, toP(F.at(pos).Ident(ident())));
-                    setErrorEndPos(S.pos());
+                    setErrorEndPos(token.pos);
                 } else {
                     errs = List.<JCTree>of(mods);
                 }
@@ -2378,16 +2364,16 @@
                                               CLASS, INTERFACE, ENUM)));
             }
         } else {
-            if (S.token() == ENUM) {
-                error(S.pos(), "enums.not.supported.in.source", source.name);
+            if (token.kind == ENUM) {
+                error(token.pos, "enums.not.supported.in.source", source.name);
                 allowEnums = true;
                 return enumDeclaration(mods, dc);
             }
-            int pos = S.pos();
+            int pos = token.pos;
             List<JCTree> errs;
-            if (S.token() == IDENTIFIER) {
+            if (token.kind == IDENTIFIER) {
                 errs = List.<JCTree>of(mods, toP(F.at(pos).Ident(ident())));
-                setErrorEndPos(S.pos());
+                setErrorEndPos(token.pos);
             } else {
                 errs = List.<JCTree>of(mods);
             }
@@ -2402,20 +2388,20 @@
      *  @param dc       The documentation comment for the class, or null.
      */
     JCClassDecl classDeclaration(JCModifiers mods, String dc) {
-        int pos = S.pos();
+        int pos = token.pos;
         accept(CLASS);
         Name name = ident();
 
         List<JCTypeParameter> typarams = typeParametersOpt();
 
         JCExpression extending = null;
-        if (S.token() == EXTENDS) {
-            S.nextToken();
+        if (token.kind == EXTENDS) {
+            nextToken();
             extending = parseType();
         }
         List<JCExpression> implementing = List.nil();
-        if (S.token() == IMPLEMENTS) {
-            S.nextToken();
+        if (token.kind == IMPLEMENTS) {
+            nextToken();
             implementing = typeList();
         }
         List<JCTree> defs = classOrInterfaceBody(name, false);
@@ -2431,15 +2417,15 @@
      *  @param dc       The documentation comment for the interface, or null.
      */
     JCClassDecl interfaceDeclaration(JCModifiers mods, String dc) {
-        int pos = S.pos();
+        int pos = token.pos;
         accept(INTERFACE);
         Name name = ident();
 
         List<JCTypeParameter> typarams = typeParametersOpt();
 
         List<JCExpression> extending = List.nil();
-        if (S.token() == EXTENDS) {
-            S.nextToken();
+        if (token.kind == EXTENDS) {
+            nextToken();
             extending = typeList();
         }
         List<JCTree> defs = classOrInterfaceBody(name, true);
@@ -2454,13 +2440,13 @@
      *  @param dc       The documentation comment for the enum, or null.
      */
     JCClassDecl enumDeclaration(JCModifiers mods, String dc) {
-        int pos = S.pos();
+        int pos = token.pos;
         accept(ENUM);
         Name name = ident();
 
         List<JCExpression> implementing = List.nil();
-        if (S.token() == IMPLEMENTS) {
-            S.nextToken();
+        if (token.kind == IMPLEMENTS) {
+            nextToken();
             implementing = typeList();
         }
 
@@ -2479,27 +2465,27 @@
     List<JCTree> enumBody(Name enumName) {
         accept(LBRACE);
         ListBuffer<JCTree> defs = new ListBuffer<JCTree>();
-        if (S.token() == COMMA) {
-            S.nextToken();
-        } else if (S.token() != RBRACE && S.token() != SEMI) {
+        if (token.kind == COMMA) {
+            nextToken();
+        } else if (token.kind != RBRACE && token.kind != SEMI) {
             defs.append(enumeratorDeclaration(enumName));
-            while (S.token() == COMMA) {
-                S.nextToken();
-                if (S.token() == RBRACE || S.token() == SEMI) break;
+            while (token.kind == COMMA) {
+                nextToken();
+                if (token.kind == RBRACE || token.kind == SEMI) break;
                 defs.append(enumeratorDeclaration(enumName));
             }
-            if (S.token() != SEMI && S.token() != RBRACE) {
-                defs.append(syntaxError(S.pos(), "expected3",
+            if (token.kind != SEMI && token.kind != RBRACE) {
+                defs.append(syntaxError(token.pos, "expected3",
                                 COMMA, RBRACE, SEMI));
-                S.nextToken();
+                nextToken();
             }
         }
-        if (S.token() == SEMI) {
-            S.nextToken();
-            while (S.token() != RBRACE && S.token() != EOF) {
+        if (token.kind == SEMI) {
+            nextToken();
+            while (token.kind != RBRACE && token.kind != EOF) {
                 defs.appendList(classOrInterfaceBodyDeclaration(enumName,
                                                                 false));
-                if (S.pos() <= errorEndPos) {
+                if (token.pos <= errorEndPos) {
                     // error recovery
                    skip(false, true, true, false);
                 }
@@ -2512,23 +2498,22 @@
     /** EnumeratorDeclaration = AnnotationsOpt [TypeArguments] IDENTIFIER [ Arguments ] [ "{" ClassBody "}" ]
      */
     JCTree enumeratorDeclaration(Name enumName) {
-        String dc = S.docComment();
+        String dc = token.docComment;
         int flags = Flags.PUBLIC|Flags.STATIC|Flags.FINAL|Flags.ENUM;
-        if (S.deprecatedFlag()) {
+        if (token.deprecatedFlag) {
             flags |= Flags.DEPRECATED;
-            S.resetDeprecatedFlag();
         }
-        int pos = S.pos();
+        int pos = token.pos;
         List<JCAnnotation> annotations = annotationsOpt();
         JCModifiers mods = F.at(annotations.isEmpty() ? Position.NOPOS : pos).Modifiers(flags, annotations);
         List<JCExpression> typeArgs = typeArgumentsOpt();
-        int identPos = S.pos();
+        int identPos = token.pos;
         Name name = ident();
-        int createPos = S.pos();
-        List<JCExpression> args = (S.token() == LPAREN)
+        int createPos = token.pos;
+        List<JCExpression> args = (token.kind == LPAREN)
             ? arguments() : List.<JCExpression>nil();
         JCClassDecl body = null;
-        if (S.token() == LBRACE) {
+        if (token.kind == LBRACE) {
             JCModifiers mods1 = F.at(Position.NOPOS).Modifiers(Flags.ENUM | Flags.STATIC);
             List<JCTree> defs = classOrInterfaceBody(names.empty, false);
             body = toP(F.at(identPos).AnonymousClassDef(mods1, defs));
@@ -2538,7 +2523,7 @@
         JCIdent ident = F.at(identPos).Ident(enumName);
         JCNewClass create = F.at(createPos).NewClass(null, typeArgs, ident, args, body);
         if (createPos != identPos)
-            storeEnd(create, S.prevEndPos());
+            storeEnd(create, S.prevToken().endPos);
         ident = F.at(identPos).Ident(enumName);
         JCTree result = toP(F.at(pos).VarDef(mods, name, ident, create));
         attach(result, dc);
@@ -2550,8 +2535,8 @@
     List<JCExpression> typeList() {
         ListBuffer<JCExpression> ts = new ListBuffer<JCExpression>();
         ts.append(parseType());
-        while (S.token() == COMMA) {
-            S.nextToken();
+        while (token.kind == COMMA) {
+            nextToken();
             ts.append(parseType());
         }
         return ts.toList();
@@ -2562,16 +2547,16 @@
      */
     List<JCTree> classOrInterfaceBody(Name className, boolean isInterface) {
         accept(LBRACE);
-        if (S.pos() <= errorEndPos) {
+        if (token.pos <= errorEndPos) {
             // error recovery
             skip(false, true, false, false);
-            if (S.token() == LBRACE)
-                S.nextToken();
+            if (token.kind == LBRACE)
+                nextToken();
         }
         ListBuffer<JCTree> defs = new ListBuffer<JCTree>();
-        while (S.token() != RBRACE && S.token() != EOF) {
+        while (token.kind != RBRACE && token.kind != EOF) {
             defs.appendList(classOrInterfaceBodyDeclaration(className, isInterface));
-            if (S.pos() <= errorEndPos) {
+            if (token.pos <= errorEndPos) {
                // error recovery
                skip(false, true, true, false);
            }
@@ -2598,23 +2583,23 @@
      *      ( ConstantDeclaratorsRest | InterfaceMethodDeclaratorRest ";" )
      */
     protected List<JCTree> classOrInterfaceBodyDeclaration(Name className, boolean isInterface) {
-        if (S.token() == SEMI) {
-            S.nextToken();
+        if (token.kind == SEMI) {
+            nextToken();
             return List.<JCTree>nil();
         } else {
-            String dc = S.docComment();
-            int pos = S.pos();
+            String dc = token.docComment;
+            int pos = token.pos;
             JCModifiers mods = modifiersOpt();
-            if (S.token() == CLASS ||
-                S.token() == INTERFACE ||
-                allowEnums && S.token() == ENUM) {
+            if (token.kind == CLASS ||
+                token.kind == INTERFACE ||
+                allowEnums && token.kind == ENUM) {
                 return List.<JCTree>of(classOrInterfaceOrEnumDeclaration(mods, dc));
-            } else if (S.token() == LBRACE && !isInterface &&
+            } else if (token.kind == LBRACE && !isInterface &&
                        (mods.flags & Flags.StandardFlags & ~Flags.STATIC) == 0 &&
                        mods.annotations.isEmpty()) {
                 return List.<JCTree>of(block(pos, mods.flags));
             } else {
-                pos = S.pos();
+                pos = token.pos;
                 List<JCTypeParameter> typarams = typeParametersOpt();
                 // if there are type parameters but no modifiers, save the start
                 // position of the method in the modifiers.
@@ -2622,26 +2607,26 @@
                     mods.pos = pos;
                     storeEnd(mods, pos);
                 }
-                Name name = S.name();
-                pos = S.pos();
+                Token tk = token;
+                pos = token.pos;
                 JCExpression type;
-                boolean isVoid = S.token() == VOID;
+                boolean isVoid = token.kind == VOID;
                 if (isVoid) {
                     type = to(F.at(pos).TypeIdent(TypeTags.VOID));
-                    S.nextToken();
+                    nextToken();
                 } else {
                     type = parseType();
                 }
-                if (S.token() == LPAREN && !isInterface && type.getTag() == JCTree.IDENT) {
-                    if (isInterface || name != className)
+                if (token.kind == LPAREN && !isInterface && type.getTag() == JCTree.IDENT) {
+                    if (isInterface || tk.name() != className)
                         error(pos, "invalid.meth.decl.ret.type.req");
                     return List.of(methodDeclaratorRest(
                         pos, mods, null, names.init, typarams,
                         isInterface, true, dc));
                 } else {
-                    pos = S.pos();
-                    name = ident();
-                    if (S.token() == LPAREN) {
+                    pos = token.pos;
+                    Name name = ident();
+                    if (token.kind == LPAREN) {
                         return List.of(methodDeclaratorRest(
                             pos, mods, type, name, typarams,
                             isInterface, isVoid, dc));
@@ -2649,16 +2634,16 @@
                         List<JCTree> defs =
                             variableDeclaratorsRest(pos, mods, type, name, isInterface, dc,
                                                     new ListBuffer<JCTree>()).toList();
-                        storeEnd(defs.last(), S.endPos());
+                        storeEnd(defs.last(), token.endPos);
                         accept(SEMI);
                         return defs;
                     } else {
-                        pos = S.pos();
+                        pos = token.pos;
                         List<JCTree> err = isVoid
                             ? List.<JCTree>of(toP(F.at(pos).MethodDef(mods, name, type, typarams,
                                 List.<JCVariableDecl>nil(), List.<JCExpression>nil(), null, null)))
                             : null;
-                        return List.<JCTree>of(syntaxError(S.pos(), err, "expected", LPAREN));
+                        return List.<JCTree>of(syntaxError(token.pos, err, "expected", LPAREN));
                     }
                 }
             }
@@ -2686,27 +2671,27 @@
         List<JCVariableDecl> params = formalParameters();
         if (!isVoid) type = bracketsOpt(type);
         List<JCExpression> thrown = List.nil();
-        if (S.token() == THROWS) {
-            S.nextToken();
+        if (token.kind == THROWS) {
+            nextToken();
             thrown = qualidentList();
         }
         JCBlock body = null;
         JCExpression defaultValue;
-        if (S.token() == LBRACE) {
+        if (token.kind == LBRACE) {
             body = block();
             defaultValue = null;
         } else {
-            if (S.token() == DEFAULT) {
+            if (token.kind == DEFAULT) {
                 accept(DEFAULT);
                 defaultValue = annotationValue();
             } else {
                 defaultValue = null;
             }
             accept(SEMI);
-            if (S.pos() <= errorEndPos) {
+            if (token.pos <= errorEndPos) {
                 // error recovery
                 skip(false, true, false, false);
-                if (S.token() == LBRACE) {
+                if (token.kind == LBRACE) {
                     body = block();
                 }
             }
@@ -2725,8 +2710,8 @@
     List<JCExpression> qualidentList() {
         ListBuffer<JCExpression> ts = new ListBuffer<JCExpression>();
         ts.append(qualident());
-        while (S.token() == COMMA) {
-            S.nextToken();
+        while (token.kind == COMMA) {
+            nextToken();
             ts.append(qualident());
         }
         return ts.toList();
@@ -2735,13 +2720,13 @@
     /** TypeParametersOpt = ["<" TypeParameter {"," TypeParameter} ">"]
      */
     List<JCTypeParameter> typeParametersOpt() {
-        if (S.token() == LT) {
+        if (token.kind == LT) {
             checkGenerics();
             ListBuffer<JCTypeParameter> typarams = new ListBuffer<JCTypeParameter>();
-            S.nextToken();
+            nextToken();
             typarams.append(typeParameter());
-            while (S.token() == COMMA) {
-                S.nextToken();
+            while (token.kind == COMMA) {
+                nextToken();
                 typarams.append(typeParameter());
             }
             accept(GT);
@@ -2756,14 +2741,14 @@
      *  TypeVariable = Ident
      */
     JCTypeParameter typeParameter() {
-        int pos = S.pos();
+        int pos = token.pos;
         Name name = ident();
         ListBuffer<JCExpression> bounds = new ListBuffer<JCExpression>();
-        if (S.token() == EXTENDS) {
-            S.nextToken();
+        if (token.kind == EXTENDS) {
+            nextToken();
             bounds.append(parseType());
-            while (S.token() == AMP) {
-                S.nextToken();
+            while (token.kind == AMP) {
+                nextToken();
                 bounds.append(parseType());
             }
         }
@@ -2778,10 +2763,10 @@
         ListBuffer<JCVariableDecl> params = new ListBuffer<JCVariableDecl>();
         JCVariableDecl lastParam = null;
         accept(LPAREN);
-        if (S.token() != RPAREN) {
+        if (token.kind != RPAREN) {
             params.append(lastParam = formalParameter());
-            while ((lastParam.mods.flags & Flags.VARARGS) == 0 && S.token() == COMMA) {
-                S.nextToken();
+            while ((lastParam.mods.flags & Flags.VARARGS) == 0 && token.kind == COMMA) {
+                nextToken();
                 params.append(lastParam = formalParameter());
             }
         }
@@ -2802,11 +2787,11 @@
     protected JCVariableDecl formalParameter() {
         JCModifiers mods = optFinal(Flags.PARAMETER);
         JCExpression type = parseType();
-        if (S.token() == ELLIPSIS) {
+        if (token.kind == ELLIPSIS) {
             checkVarargs();
             mods.flags |= Flags.VARARGS;
-            type = to(F.at(S.pos()).TypeArray(type));
-            S.nextToken();
+            type = to(F.at(token.pos).TypeArray(type));
+            nextToken();
         }
         return variableDeclaratorId(mods, type);
     }
@@ -2849,7 +2834,7 @@
     /** Return precedence of operator represented by token,
      *  -1 if token is not a binary operator. @see TreeInfo.opPrec
      */
-    static int prec(Token token) {
+    static int prec(TokenKind token) {
         int oc = optag(token);
         return (oc >= 0) ? TreeInfo.opPrec(oc) : -1;
     }
@@ -2869,7 +2854,7 @@
     /** Return operation tag of binary operator represented by token,
      *  -1 if token is not a binary operator.
      */
-    static int optag(Token token) {
+    static int optag(TokenKind token) {
         switch (token) {
         case BARBAR:
             return JCTree.OR;
@@ -2941,7 +2926,7 @@
     /** Return operation tag of unary operator represented by token,
      *  -1 if token is not a binary operator.
      */
-    static int unoptag(Token token) {
+    static int unoptag(TokenKind token) {
         switch (token) {
         case PLUS:
             return JCTree.POS;
@@ -2963,7 +2948,7 @@
     /** Return type tag of basic type represented by token,
      *  -1 if token is not a basic type identifier.
      */
-    static int typetag(Token token) {
+    static int typetag(TokenKind token) {
         switch (token) {
         case BYTE:
             return TypeTags.BYTE;
@@ -2988,49 +2973,49 @@
 
     void checkGenerics() {
         if (!allowGenerics) {
-            error(S.pos(), "generics.not.supported.in.source", source.name);
+            error(token.pos, "generics.not.supported.in.source", source.name);
             allowGenerics = true;
         }
     }
     void checkVarargs() {
         if (!allowVarargs) {
-            error(S.pos(), "varargs.not.supported.in.source", source.name);
+            error(token.pos, "varargs.not.supported.in.source", source.name);
             allowVarargs = true;
         }
     }
     void checkForeach() {
         if (!allowForeach) {
-            error(S.pos(), "foreach.not.supported.in.source", source.name);
+            error(token.pos, "foreach.not.supported.in.source", source.name);
             allowForeach = true;
         }
     }
     void checkStaticImports() {
         if (!allowStaticImport) {
-            error(S.pos(), "static.import.not.supported.in.source", source.name);
+            error(token.pos, "static.import.not.supported.in.source", source.name);
             allowStaticImport = true;
         }
     }
     void checkAnnotations() {
         if (!allowAnnotations) {
-            error(S.pos(), "annotations.not.supported.in.source", source.name);
+            error(token.pos, "annotations.not.supported.in.source", source.name);
             allowAnnotations = true;
         }
     }
     void checkDiamond() {
         if (!allowDiamond) {
-            error(S.pos(), "diamond.not.supported.in.source", source.name);
+            error(token.pos, "diamond.not.supported.in.source", source.name);
             allowDiamond = true;
         }
     }
     void checkMulticatch() {
         if (!allowMulticatch) {
-            error(S.pos(), "multicatch.not.supported.in.source", source.name);
+            error(token.pos, "multicatch.not.supported.in.source", source.name);
             allowMulticatch = true;
         }
     }
     void checkTryWithResources() {
         if (!allowTWR) {
-            error(S.pos(), "try.with.resources.not.supported.in.source", source.name);
+            error(token.pos, "try.with.resources.not.supported.in.source", source.name);
             allowTWR = true;
         }
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/share/classes/com/sun/tools/javac/parser/JavadocTokenizer.java	Wed Jul 05 17:54:24 2017 +0200
@@ -0,0 +1,412 @@
+/*
+ * Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved.
+ * 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.parser;
+
+import com.sun.tools.javac.file.JavacFileManager;
+import com.sun.tools.javac.parser.Tokens.Token;
+import com.sun.tools.javac.util.*;
+
+import java.nio.*;
+
+import static com.sun.tools.javac.util.LayoutCharacters.*;
+
+/** An extension to the base lexical analyzer that captures
+ *  and processes the contents of doc comments.  It does so by
+ *  translating Unicode escape sequences and by stripping the
+ *  leading whitespace and starts from each line of the comment.
+ *
+ *  <p><b>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.</b>
+ */
+public class JavadocTokenizer extends JavaTokenizer {
+
+    /** Create a scanner from the input buffer.  buffer must implement
+     *  array() and compact(), and remaining() must be less than limit().
+     */
+    protected JavadocTokenizer(ScannerFactory fac, CharBuffer buffer) {
+        super(fac, buffer);
+    }
+
+    /** Create a scanner from the input array.  The array must have at
+     *  least a single character of extra space.
+     */
+    protected JavadocTokenizer(ScannerFactory fac, char[] input, int inputLength) {
+        super(fac, input, inputLength);
+    }
+
+    /** The comment input buffer, index of next chacter to be read,
+     *  index of one past last character in buffer.
+     */
+    private char[] buf;
+    private int bp;
+    private int buflen;
+
+    /** The current character.
+     */
+    private char ch;
+
+    /** The column number position of the current character.
+     */
+    private int col;
+
+    /** The buffer index of the last converted Unicode character
+     */
+    private int unicodeConversionBp = 0;
+
+    /**
+     * Buffer for doc comment.
+     */
+    private char[] docCommentBuffer = new char[1024];
+
+    /**
+     * Number of characters in doc comment buffer.
+     */
+    private int docCommentCount;
+
+    /**
+     * Translated and stripped contents of doc comment
+     */
+    private String docComment = null;
+
+
+    /** Unconditionally expand the comment buffer.
+     */
+    private void expandCommentBuffer() {
+        char[] newBuffer = new char[docCommentBuffer.length * 2];
+        System.arraycopy(docCommentBuffer, 0, newBuffer,
+                         0, docCommentBuffer.length);
+        docCommentBuffer = newBuffer;
+    }
+
+    /** Convert an ASCII digit from its base (8, 10, or 16)
+     *  to its value.
+     */
+    private int digit(int base) {
+        char c = ch;
+        int result = Character.digit(c, base);
+        if (result >= 0 && c > 0x7f) {
+            ch = "0123456789abcdef".charAt(result);
+        }
+        return result;
+    }
+
+    /** Convert Unicode escape; bp points to initial '\' character
+     *  (Spec 3.3).
+     */
+    private void convertUnicode() {
+        if (ch == '\\' && unicodeConversionBp != bp) {
+            bp++; ch = buf[bp]; col++;
+            if (ch == 'u') {
+                do {
+                    bp++; ch = buf[bp]; col++;
+                } while (ch == 'u');
+                int limit = bp + 3;
+                if (limit < buflen) {
+                    int d = digit(16);
+                    int code = d;
+                    while (bp < limit && d >= 0) {
+                        bp++; ch = buf[bp]; col++;
+                        d = digit(16);
+                        code = (code << 4) + d;
+                    }
+                    if (d >= 0) {
+                        ch = (char)code;
+                        unicodeConversionBp = bp;
+                        return;
+                    }
+                }
+                // "illegal.Unicode.esc", reported by base scanner
+            } else {
+                bp--;
+                ch = '\\';
+                col--;
+            }
+        }
+    }
+
+
+    /** Read next character.
+     */
+    private void scanChar() {
+        bp++;
+        ch = buf[bp];
+        switch (ch) {
+        case '\r': // return
+            col = 0;
+            break;
+        case '\n': // newline
+            if (bp == 0 || buf[bp-1] != '\r') {
+                col = 0;
+            }
+            break;
+        case '\t': // tab
+            col = (col / TabInc * TabInc) + TabInc;
+            break;
+        case '\\': // possible Unicode
+            col++;
+            convertUnicode();
+            break;
+        default:
+            col++;
+            break;
+        }
+    }
+
+    @Override
+    public Token readToken() {
+        docComment = null;
+        Token tk = super.readToken();
+        tk.docComment = docComment;
+        return tk;
+    }
+
+    /**
+     * Read next character in doc comment, skipping over double '\' characters.
+     * If a double '\' is skipped, put in the buffer and update buffer count.
+     */
+    private void scanDocCommentChar() {
+        scanChar();
+        if (ch == '\\') {
+            if (buf[bp+1] == '\\' && unicodeConversionBp != bp) {
+                if (docCommentCount == docCommentBuffer.length)
+                    expandCommentBuffer();
+                docCommentBuffer[docCommentCount++] = ch;
+                bp++; col++;
+            } else {
+                convertUnicode();
+            }
+        }
+    }
+
+    /**
+     * Process a doc comment and make the string content available.
+     * Strips leading whitespace and stars.
+     */
+    @SuppressWarnings("fallthrough")
+    protected void processComment(int pos, int endPos, CommentStyle style) {
+        if (style != CommentStyle.JAVADOC) {
+            return;
+        }
+
+        buf = reader.getRawCharacters(pos, endPos);
+        buflen = buf.length;
+        bp = 0;
+        col = 0;
+
+        docCommentCount = 0;
+
+        boolean firstLine = true;
+
+        // Skip over first slash
+        scanDocCommentChar();
+        // Skip over first star
+        scanDocCommentChar();
+
+        // consume any number of stars
+        while (bp < buflen && ch == '*') {
+            scanDocCommentChar();
+        }
+        // is the comment in the form /**/, /***/, /****/, etc. ?
+        if (bp < buflen && ch == '/') {
+            docComment = "";
+            return;
+        }
+
+        // skip a newline on the first line of the comment.
+        if (bp < buflen) {
+            if (ch == LF) {
+                scanDocCommentChar();
+                firstLine = false;
+            } else if (ch == CR) {
+                scanDocCommentChar();
+                if (ch == LF) {
+                    scanDocCommentChar();
+                    firstLine = false;
+                }
+            }
+        }
+
+    outerLoop:
+
+        // The outerLoop processes the doc comment, looping once
+        // for each line.  For each line, it first strips off
+        // whitespace, then it consumes any stars, then it
+        // puts the rest of the line into our buffer.
+        while (bp < buflen) {
+
+            // The wsLoop consumes whitespace from the beginning
+            // of each line.
+        wsLoop:
+
+            while (bp < buflen) {
+                switch(ch) {
+                case ' ':
+                    scanDocCommentChar();
+                    break;
+                case '\t':
+                    col = ((col - 1) / TabInc * TabInc) + TabInc;
+                    scanDocCommentChar();
+                    break;
+                case FF:
+                    col = 0;
+                    scanDocCommentChar();
+                    break;
+// Treat newline at beginning of line (blank line, no star)
+// as comment text.  Old Javadoc compatibility requires this.
+/*---------------------------------*
+                case CR: // (Spec 3.4)
+                    scanDocCommentChar();
+                    if (ch == LF) {
+                        col = 0;
+                        scanDocCommentChar();
+                    }
+                    break;
+                case LF: // (Spec 3.4)
+                    scanDocCommentChar();
+                    break;
+*---------------------------------*/
+                default:
+                    // we've seen something that isn't whitespace;
+                    // jump out.
+                    break wsLoop;
+                }
+            }
+
+            // Are there stars here?  If so, consume them all
+            // and check for the end of comment.
+            if (ch == '*') {
+                // skip all of the stars
+                do {
+                    scanDocCommentChar();
+                } while (ch == '*');
+
+                // check for the closing slash.
+                if (ch == '/') {
+                    // We're done with the doc comment
+                    // scanChar() and breakout.
+                    break outerLoop;
+                }
+            } else if (! firstLine) {
+                //The current line does not begin with a '*' so we will indent it.
+                for (int i = 1; i < col; i++) {
+                    if (docCommentCount == docCommentBuffer.length)
+                        expandCommentBuffer();
+                    docCommentBuffer[docCommentCount++] = ' ';
+                }
+            }
+
+            // The textLoop processes the rest of the characters
+            // on the line, adding them to our buffer.
+        textLoop:
+            while (bp < buflen) {
+                switch (ch) {
+                case '*':
+                    // Is this just a star?  Or is this the
+                    // end of a comment?
+                    scanDocCommentChar();
+                    if (ch == '/') {
+                        // This is the end of the comment,
+                        // set ch and return our buffer.
+                        break outerLoop;
+                    }
+                    // This is just an ordinary star.  Add it to
+                    // the buffer.
+                    if (docCommentCount == docCommentBuffer.length)
+                        expandCommentBuffer();
+                    docCommentBuffer[docCommentCount++] = '*';
+                    break;
+                case ' ':
+                case '\t':
+                    if (docCommentCount == docCommentBuffer.length)
+                        expandCommentBuffer();
+                    docCommentBuffer[docCommentCount++] = ch;
+                    scanDocCommentChar();
+                    break;
+                case FF:
+                    scanDocCommentChar();
+                    break textLoop; // treat as end of line
+                case CR: // (Spec 3.4)
+                    scanDocCommentChar();
+                    if (ch != LF) {
+                        // Canonicalize CR-only line terminator to LF
+                        if (docCommentCount == docCommentBuffer.length)
+                            expandCommentBuffer();
+                        docCommentBuffer[docCommentCount++] = (char)LF;
+                        break textLoop;
+                    }
+                    /* fall through to LF case */
+                case LF: // (Spec 3.4)
+                    // We've seen a newline.  Add it to our
+                    // buffer and break out of this loop,
+                    // starting fresh on a new line.
+                    if (docCommentCount == docCommentBuffer.length)
+                        expandCommentBuffer();
+                    docCommentBuffer[docCommentCount++] = ch;
+                    scanDocCommentChar();
+                    break textLoop;
+                default:
+                    // Add the character to our buffer.
+                    if (docCommentCount == docCommentBuffer.length)
+                        expandCommentBuffer();
+                    docCommentBuffer[docCommentCount++] = ch;
+                    scanDocCommentChar();
+                }
+            } // end textLoop
+            firstLine = false;
+        } // end outerLoop
+
+        if (docCommentCount > 0) {
+            int i = docCommentCount - 1;
+        trailLoop:
+            while (i > -1) {
+                switch (docCommentBuffer[i]) {
+                case '*':
+                    i--;
+                    break;
+                default:
+                    break trailLoop;
+                }
+            }
+            docCommentCount = i + 1;
+
+            // Store the text of the doc comment
+            docComment = new String(docCommentBuffer, 0 , docCommentCount);
+        } else {
+            docComment = "";
+        }
+    }
+
+    /** Build a map for translating between line numbers and
+     * positions in the input.
+     *
+     * @return a LineMap */
+    public Position.LineMap getLineMap() {
+        char[] buf = reader.getRawCharacters();
+        return Position.makeLineMap(buf, buf.length, true);
+    }
+}
--- a/langtools/src/share/classes/com/sun/tools/javac/parser/Keywords.java	Wed Jul 05 17:53:51 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,98 +0,0 @@
-/*
- * Copyright (c) 2002, 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.  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.parser;
-
-import com.sun.tools.javac.util.Context;
-import com.sun.tools.javac.util.Log;
-import com.sun.tools.javac.util.Name;
-import com.sun.tools.javac.util.Names;
-
-import static com.sun.tools.javac.parser.Token.*;
-
-/**
- * Map from Name to Token and Token to String.
- *
- * <p><b>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.</b>
- */
-public class Keywords {
-    public static final Context.Key<Keywords> keywordsKey =
-        new Context.Key<Keywords>();
-
-    public static Keywords instance(Context context) {
-        Keywords instance = context.get(keywordsKey);
-        if (instance == null)
-            instance = new Keywords(context);
-        return instance;
-    }
-
-    private final Names names;
-
-    protected Keywords(Context context) {
-        context.put(keywordsKey, this);
-        names = Names.instance(context);
-
-        for (Token t : Token.values()) {
-            if (t.name != null)
-                enterKeyword(t.name, t);
-            else
-                tokenName[t.ordinal()] = null;
-        }
-
-        key = new Token[maxKey+1];
-        for (int i = 0; i <= maxKey; i++) key[i] = IDENTIFIER;
-        for (Token t : Token.values()) {
-            if (t.name != null)
-                key[tokenName[t.ordinal()].getIndex()] = t;
-        }
-    }
-
-
-    public Token key(Name name) {
-        return (name.getIndex() > maxKey) ? IDENTIFIER : key[name.getIndex()];
-    }
-
-    /**
-     * Keyword array. Maps name indices to Token.
-     */
-    private final Token[] key;
-
-    /**  The number of the last entered keyword.
-     */
-    private int maxKey = 0;
-
-    /** The names of all tokens.
-     */
-    private Name[] tokenName = new Name[Token.values().length];
-
-    private void enterKeyword(String s, Token token) {
-        Name n = names.fromString(s);
-        tokenName[token.ordinal()] = n;
-        if (n.getIndex() > maxKey) maxKey = n.getIndex();
-    }
-}
--- a/langtools/src/share/classes/com/sun/tools/javac/parser/Lexer.java	Wed Jul 05 17:53:51 2017 +0200
+++ b/langtools/src/share/classes/com/sun/tools/javac/parser/Lexer.java	Wed Jul 05 17:54:24 2017 +0200
@@ -25,7 +25,7 @@
 
 package com.sun.tools.javac.parser;
 
-import com.sun.tools.javac.util.*;
+import com.sun.tools.javac.parser.Tokens.*;
 import com.sun.tools.javac.util.Position.LineMap;
 
 /**
@@ -40,22 +40,26 @@
 public interface Lexer {
 
     /**
-     * Has a @deprecated been encountered in last doc comment?
-     * This needs to be reset by client with resetDeprecatedFlag.
+     * Consume the next token.
      */
-    boolean deprecatedFlag();
+    void nextToken();
 
-    void resetDeprecatedFlag();
+    /**
+     * Return current token.
+     */
+    Token token();
 
     /**
-     * Returns the documentation string of the current token.
+     * Return the last character position of the previous token.
      */
-    String docComment();
+    Token prevToken();
 
     /**
-     * Return the last character position of the current token.
+     * Splits the current token in two and return the first (splitted) token.
+     * For instance '<<<' is splitted into two tokens '<' and '<<' respectively,
+     * and the latter is returned.
      */
-    int endPos();
+    Token split();
 
     /**
      * Return the position where a lexical error occurred;
@@ -74,69 +78,4 @@
      * @return a LineMap
      */
     LineMap getLineMap();
-
-    /**
-     * Returns a copy of the input buffer, up to its inputLength.
-     * Unicode escape sequences are not translated.
-     */
-    char[] getRawCharacters();
-
-    /**
-     * Returns a copy of a character array subset of the input buffer.
-     * The returned array begins at the <code>beginIndex</code> and
-     * extends to the character at index <code>endIndex - 1</code>.
-     * Thus the length of the substring is <code>endIndex-beginIndex</code>.
-     * This behavior is like
-     * <code>String.substring(beginIndex, endIndex)</code>.
-     * Unicode escape sequences are not translated.
-     *
-     * @param beginIndex the beginning index, inclusive.
-     * @param endIndex the ending index, exclusive.
-     * @throws IndexOutOfBounds if either offset is outside of the
-     *         array bounds
-     */
-    char[] getRawCharacters(int beginIndex, int endIndex);
-
-    /**
-     * Return the name of an identifier or token for the current token.
-     */
-    Name name();
-
-    /**
-     * Read token.
-     */
-    void nextToken();
-
-    /**
-     * Return the current token's position: a 0-based
-     *  offset from beginning of the raw input stream
-     *  (before unicode translation)
-     */
-    int pos();
-
-    /**
-     * Return the last character position of the previous token.
-     */
-    int prevEndPos();
-
-    /**
-     * Return the radix of a numeric literal token.
-     */
-    int radix();
-
-    /**
-     * The value of a literal token, recorded as a string.
-     *  For integers, leading 0x and 'l' suffixes are suppressed.
-     */
-    String stringVal();
-
-    /**
-     * Return the current token, set by nextToken().
-     */
-    Token token();
-
-    /**
-     * Sets the current token.
-     */
-    void token(Token token);
 }
--- a/langtools/src/share/classes/com/sun/tools/javac/parser/ParserFactory.java	Wed Jul 05 17:53:51 2017 +0200
+++ b/langtools/src/share/classes/com/sun/tools/javac/parser/ParserFactory.java	Wed Jul 05 17:54:24 2017 +0200
@@ -55,7 +55,7 @@
 
     final TreeMaker F;
     final Log log;
-    final Keywords keywords;
+    final Tokens tokens;
     final Source source;
     final Names names;
     final Options options;
@@ -67,7 +67,7 @@
         this.F = TreeMaker.instance(context);
         this.log = Log.instance(context);
         this.names = Names.instance(context);
-        this.keywords = Keywords.instance(context);
+        this.tokens = Tokens.instance(context);
         this.source = Source.instance(context);
         this.options = Options.instance(context);
         this.scannerFactory = ScannerFactory.instance(context);
--- a/langtools/src/share/classes/com/sun/tools/javac/parser/Scanner.java	Wed Jul 05 17:53:51 2017 +0200
+++ b/langtools/src/share/classes/com/sun/tools/javac/parser/Scanner.java	Wed Jul 05 17:54:24 2017 +0200
@@ -27,13 +27,11 @@
 
 import java.nio.*;
 
-import com.sun.tools.javac.code.Source;
-import com.sun.tools.javac.file.JavacFileManager;
 import com.sun.tools.javac.util.*;
+import com.sun.tools.javac.util.Position.LineMap;
+import com.sun.tools.javac.parser.JavaTokenizer.*;
 
-
-import static com.sun.tools.javac.parser.Token.*;
-import static com.sun.tools.javac.util.LayoutCharacters.*;
+import static com.sun.tools.javac.parser.Tokens.*;
 
 /** The lexical analyzer maps an input stream consisting of
  *  ASCII characters and Unicode escapes into a token sequence.
@@ -45,119 +43,17 @@
  */
 public class Scanner implements Lexer {
 
-    private static boolean scannerDebug = false;
-
-    /* Output variables; set by nextToken():
-     */
+    private Tokens tokens;
 
     /** The token, set by nextToken().
      */
     private Token token;
 
-    /** Allow hex floating-point literals.
-     */
-    private boolean allowHexFloats;
-
-    /** Allow binary literals.
-     */
-    private boolean allowBinaryLiterals;
-
-    /** Allow underscores in literals.
-     */
-    private boolean allowUnderscoresInLiterals;
-
-    /** The source language setting.
-     */
-    private Source source;
-
-    /** The token's position, 0-based offset from beginning of text.
-     */
-    private int pos;
-
-    /** Character position just after the last character of the token.
+    /** The previous token, set by nextToken().
      */
-    private int endPos;
-
-    /** The last character position of the previous token.
-     */
-    private int prevEndPos;
-
-    /** The position where a lexical error occurred;
-     */
-    private int errPos = Position.NOPOS;
-
-    /** The name of an identifier or token:
-     */
-    private Name name;
-
-    /** The radix of a numeric literal token.
-     */
-    private int radix;
-
-    /** Has a @deprecated been encountered in last doc comment?
-     *  this needs to be reset by client.
-     */
-    protected boolean deprecatedFlag = false;
-
-    /** A character buffer for literals.
-     */
-    private char[] sbuf = new char[128];
-    private int sp;
+    private Token prevToken;
 
-    /** The input buffer, index of next chacter to be read,
-     *  index of one past last character in buffer.
-     */
-    private char[] buf;
-    private int bp;
-    private int buflen;
-    private int eofPos;
-
-    /** The current character.
-     */
-    private char ch;
-
-    /** The buffer index of the last converted unicode character
-     */
-    private int unicodeConversionBp = -1;
-
-    /** The log to be used for error reporting.
-     */
-    private final Log log;
-
-    /** The name table. */
-    private final Names names;
-
-    /** The keyword table. */
-    private final Keywords keywords;
-
-    /** Common code for constructors. */
-    private Scanner(ScannerFactory fac) {
-        log = fac.log;
-        names = fac.names;
-        keywords = fac.keywords;
-        source = fac.source;
-        allowBinaryLiterals = source.allowBinaryLiterals();
-        allowHexFloats = source.allowHexFloats();
-        allowUnderscoresInLiterals = source.allowUnderscoresInLiterals();
-    }
-
-    private static final boolean hexFloatsWork = hexFloatsWork();
-    private static boolean hexFloatsWork() {
-        try {
-            Float.valueOf("0x1.0p1");
-            return true;
-        } catch (NumberFormatException ex) {
-            return false;
-        }
-    }
-
-    /** Create a scanner from the input buffer.  buffer must implement
-     *  array() and compact(), and remaining() must be less than limit().
-     */
-    protected Scanner(ScannerFactory fac, CharBuffer buffer) {
-        this(fac, JavacFileManager.toArray(buffer), buffer.limit());
-    }
-
+    private JavaTokenizer tokenizer;
     /**
      * Create a scanner from the input array.  This method might
      * modify the array.  To avoid copying the input array, ensure
@@ -169,972 +65,49 @@
      * @param inputLength the size of the input.
      * Must be positive and less than or equal to input.length.
      */
-    protected Scanner(ScannerFactory fac, char[] input, int inputLength) {
-        this(fac);
-        eofPos = inputLength;
-        if (inputLength == input.length) {
-            if (input.length > 0 && Character.isWhitespace(input[input.length - 1])) {
-                inputLength--;
-            } else {
-                char[] newInput = new char[inputLength + 1];
-                System.arraycopy(input, 0, newInput, 0, input.length);
-                input = newInput;
-            }
-        }
-        buf = input;
-        buflen = inputLength;
-        buf[buflen] = EOI;
-        bp = -1;
-        scanChar();
-    }
-
-    /** Report an error at the given position using the provided arguments.
-     */
-    private void lexError(int pos, String key, Object... args) {
-        log.error(pos, key, args);
-        token = ERROR;
-        errPos = pos;
-    }
-
-    /** Report an error at the current token position using the provided
-     *  arguments.
-     */
-    private void lexError(String key, Object... args) {
-        lexError(pos, key, args);
-    }
-
-    /** Convert an ASCII digit from its base (8, 10, or 16)
-     *  to its value.
-     */
-    private int digit(int base) {
-        char c = ch;
-        int result = Character.digit(c, base);
-        if (result >= 0 && c > 0x7f) {
-            lexError(pos+1, "illegal.nonascii.digit");
-            ch = "0123456789abcdef".charAt(result);
-        }
-        return result;
-    }
-
-    /** Convert unicode escape; bp points to initial '\' character
-     *  (Spec 3.3).
-     */
-    private void convertUnicode() {
-        if (ch == '\\' && unicodeConversionBp != bp) {
-            bp++; ch = buf[bp];
-            if (ch == 'u') {
-                do {
-                    bp++; ch = buf[bp];
-                } while (ch == 'u');
-                int limit = bp + 3;
-                if (limit < buflen) {
-                    int d = digit(16);
-                    int code = d;
-                    while (bp < limit && d >= 0) {
-                        bp++; ch = buf[bp];
-                        d = digit(16);
-                        code = (code << 4) + d;
-                    }
-                    if (d >= 0) {
-                        ch = (char)code;
-                        unicodeConversionBp = bp;
-                        return;
-                    }
-                }
-                lexError(bp, "illegal.unicode.esc");
-            } else {
-                bp--;
-                ch = '\\';
-            }
-        }
-    }
-
-    /** Read next character.
-     */
-    private void scanChar() {
-        ch = buf[++bp];
-        if (ch == '\\') {
-            convertUnicode();
-        }
-    }
-
-    /** Read next character in comment, skipping over double '\' characters.
-     */
-    private void scanCommentChar() {
-        scanChar();
-        if (ch == '\\') {
-            if (buf[bp+1] == '\\' && unicodeConversionBp != bp) {
-                bp++;
-            } else {
-                convertUnicode();
-            }
-        }
-    }
-
-    /** Append a character to sbuf.
-     */
-    private void putChar(char ch) {
-        if (sp == sbuf.length) {
-            char[] newsbuf = new char[sbuf.length * 2];
-            System.arraycopy(sbuf, 0, newsbuf, 0, sbuf.length);
-            sbuf = newsbuf;
-        }
-        sbuf[sp++] = ch;
-    }
-
-    /** Read next character in character or string literal and copy into sbuf.
-     */
-    private void scanLitChar() {
-        if (ch == '\\') {
-            if (buf[bp+1] == '\\' && unicodeConversionBp != bp) {
-                bp++;
-                putChar('\\');
-                scanChar();
-            } else {
-                scanChar();
-                switch (ch) {
-                case '0': case '1': case '2': case '3':
-                case '4': case '5': case '6': case '7':
-                    char leadch = ch;
-                    int oct = digit(8);
-                    scanChar();
-                    if ('0' <= ch && ch <= '7') {
-                        oct = oct * 8 + digit(8);
-                        scanChar();
-                        if (leadch <= '3' && '0' <= ch && ch <= '7') {
-                            oct = oct * 8 + digit(8);
-                            scanChar();
-                        }
-                    }
-                    putChar((char)oct);
-                    break;
-                case 'b':
-                    putChar('\b'); scanChar(); break;
-                case 't':
-                    putChar('\t'); scanChar(); break;
-                case 'n':
-                    putChar('\n'); scanChar(); break;
-                case 'f':
-                    putChar('\f'); scanChar(); break;
-                case 'r':
-                    putChar('\r'); scanChar(); break;
-                case '\'':
-                    putChar('\''); scanChar(); break;
-                case '\"':
-                    putChar('\"'); scanChar(); break;
-                case '\\':
-                    putChar('\\'); scanChar(); break;
-                default:
-                    lexError(bp, "illegal.esc.char");
-                }
-            }
-        } else if (bp != buflen) {
-            putChar(ch); scanChar();
-        }
-    }
-
-    private void scanDigits(int digitRadix) {
-        char saveCh;
-        int savePos;
-        do {
-            if (ch != '_') {
-                putChar(ch);
-            } else {
-                if (!allowUnderscoresInLiterals) {
-                    lexError("unsupported.underscore.lit", source.name);
-                    allowUnderscoresInLiterals = true;
-                }
-            }
-            saveCh = ch;
-            savePos = bp;
-            scanChar();
-        } while (digit(digitRadix) >= 0 || ch == '_');
-        if (saveCh == '_')
-            lexError(savePos, "illegal.underscore");
-    }
-
-    /** Read fractional part of hexadecimal floating point number.
-     */
-    private void scanHexExponentAndSuffix() {
-        if (ch == 'p' || ch == 'P') {
-            putChar(ch);
-            scanChar();
-            skipIllegalUnderscores();
-            if (ch == '+' || ch == '-') {
-                putChar(ch);
-                scanChar();
-            }
-            skipIllegalUnderscores();
-            if ('0' <= ch && ch <= '9') {
-                scanDigits(10);
-                if (!allowHexFloats) {
-                    lexError("unsupported.fp.lit", source.name);
-                    allowHexFloats = true;
-                }
-                else if (!hexFloatsWork)
-                    lexError("unsupported.cross.fp.lit");
-            } else
-                lexError("malformed.fp.lit");
-        } else {
-            lexError("malformed.fp.lit");
-        }
-        if (ch == 'f' || ch == 'F') {
-            putChar(ch);
-            scanChar();
-            token = FLOATLITERAL;
-        } else {
-            if (ch == 'd' || ch == 'D') {
-                putChar(ch);
-                scanChar();
-            }
-            token = DOUBLELITERAL;
-        }
-    }
-
-    /** Read fractional part of floating point number.
-     */
-    private void scanFraction() {
-        skipIllegalUnderscores();
-        if ('0' <= ch && ch <= '9') {
-            scanDigits(10);
-        }
-        int sp1 = sp;
-        if (ch == 'e' || ch == 'E') {
-            putChar(ch);
-            scanChar();
-            skipIllegalUnderscores();
-            if (ch == '+' || ch == '-') {
-                putChar(ch);
-                scanChar();
-            }
-            skipIllegalUnderscores();
-            if ('0' <= ch && ch <= '9') {
-                scanDigits(10);
-                return;
-            }
-            lexError("malformed.fp.lit");
-            sp = sp1;
-        }
-    }
-
-    /** Read fractional part and 'd' or 'f' suffix of floating point number.
-     */
-    private void scanFractionAndSuffix() {
-        this.radix = 10;
-        scanFraction();
-        if (ch == 'f' || ch == 'F') {
-            putChar(ch);
-            scanChar();
-            token = FLOATLITERAL;
-        } else {
-            if (ch == 'd' || ch == 'D') {
-                putChar(ch);
-                scanChar();
-            }
-            token = DOUBLELITERAL;
-        }
-    }
-
-    /** Read fractional part and 'd' or 'f' suffix of floating point number.
-     */
-    private void scanHexFractionAndSuffix(boolean seendigit) {
-        this.radix = 16;
-        Assert.check(ch == '.');
-        putChar(ch);
-        scanChar();
-        skipIllegalUnderscores();
-        if (digit(16) >= 0) {
-            seendigit = true;
-            scanDigits(16);
-        }
-        if (!seendigit)
-            lexError("invalid.hex.number");
-        else
-            scanHexExponentAndSuffix();
-    }
-
-    private void skipIllegalUnderscores() {
-        if (ch == '_') {
-            lexError(bp, "illegal.underscore");
-            while (ch == '_')
-                scanChar();
-        }
-    }
-
-    /** Read a number.
-     *  @param radix  The radix of the number; one of 2, j8, 10, 16.
-     */
-    private void scanNumber(int radix) {
-        this.radix = radix;
-        // for octal, allow base-10 digit in case it's a float literal
-        int digitRadix = (radix == 8 ? 10 : radix);
-        boolean seendigit = false;
-        if (digit(digitRadix) >= 0) {
-            seendigit = true;
-            scanDigits(digitRadix);
-        }
-        if (radix == 16 && ch == '.') {
-            scanHexFractionAndSuffix(seendigit);
-        } else if (seendigit && radix == 16 && (ch == 'p' || ch == 'P')) {
-            scanHexExponentAndSuffix();
-        } else if (digitRadix == 10 && ch == '.') {
-            putChar(ch);
-            scanChar();
-            scanFractionAndSuffix();
-        } else if (digitRadix == 10 &&
-                   (ch == 'e' || ch == 'E' ||
-                    ch == 'f' || ch == 'F' ||
-                    ch == 'd' || ch == 'D')) {
-            scanFractionAndSuffix();
-        } else {
-            if (ch == 'l' || ch == 'L') {
-                scanChar();
-                token = LONGLITERAL;
-            } else {
-                token = INTLITERAL;
-            }
-        }
-    }
-
-    /** Read an identifier.
-     */
-    private void scanIdent() {
-        boolean isJavaIdentifierPart;
-        char high;
-        do {
-            if (sp == sbuf.length) putChar(ch); else sbuf[sp++] = ch;
-            // optimization, was: putChar(ch);
-
-            scanChar();
-            switch (ch) {
-            case 'A': case 'B': case 'C': case 'D': case 'E':
-            case 'F': case 'G': case 'H': case 'I': case 'J':
-            case 'K': case 'L': case 'M': case 'N': case 'O':
-            case 'P': case 'Q': case 'R': case 'S': case 'T':
-            case 'U': case 'V': case 'W': case 'X': case 'Y':
-            case 'Z':
-            case 'a': case 'b': case 'c': case 'd': case 'e':
-            case 'f': case 'g': case 'h': case 'i': case 'j':
-            case 'k': case 'l': case 'm': case 'n': case 'o':
-            case 'p': case 'q': case 'r': case 's': case 't':
-            case 'u': case 'v': case 'w': case 'x': case 'y':
-            case 'z':
-            case '$': case '_':
-            case '0': case '1': case '2': case '3': case '4':
-            case '5': case '6': case '7': case '8': case '9':
-            case '\u0000': case '\u0001': case '\u0002': case '\u0003':
-            case '\u0004': case '\u0005': case '\u0006': case '\u0007':
-            case '\u0008': case '\u000E': case '\u000F': case '\u0010':
-            case '\u0011': case '\u0012': case '\u0013': case '\u0014':
-            case '\u0015': case '\u0016': case '\u0017':
-            case '\u0018': case '\u0019': case '\u001B':
-            case '\u007F':
-                break;
-            case '\u001A': // EOI is also a legal identifier part
-                if (bp >= buflen) {
-                    name = names.fromChars(sbuf, 0, sp);
-                    token = keywords.key(name);
-                    return;
-                }
-                break;
-            default:
-                if (ch < '\u0080') {
-                    // all ASCII range chars already handled, above
-                    isJavaIdentifierPart = false;
-                } else {
-                    high = scanSurrogates();
-                    if (high != 0) {
-                        if (sp == sbuf.length) {
-                            putChar(high);
-                        } else {
-                            sbuf[sp++] = high;
-                        }
-                        isJavaIdentifierPart = Character.isJavaIdentifierPart(
-                            Character.toCodePoint(high, ch));
-                    } else {
-                        isJavaIdentifierPart = Character.isJavaIdentifierPart(ch);
-                    }
-                }
-                if (!isJavaIdentifierPart) {
-                    name = names.fromChars(sbuf, 0, sp);
-                    token = keywords.key(name);
-                    return;
-                }
-            }
-        } while (true);
+    protected Scanner(ScannerFactory fac, CharBuffer buf) {
+        this(fac, new JavaTokenizer(fac, buf));
     }
 
-    /** Are surrogates supported?
-     */
-    final static boolean surrogatesSupported = surrogatesSupported();
-    private static boolean surrogatesSupported() {
-        try {
-            Character.isHighSurrogate('a');
-            return true;
-        } catch (NoSuchMethodError ex) {
-            return false;
-        }
-    }
-
-    /** Scan surrogate pairs.  If 'ch' is a high surrogate and
-     *  the next character is a low surrogate, then put the low
-     *  surrogate in 'ch', and return the high surrogate.
-     *  otherwise, just return 0.
-     */
-    private char scanSurrogates() {
-        if (surrogatesSupported && Character.isHighSurrogate(ch)) {
-            char high = ch;
-
-            scanChar();
-
-            if (Character.isLowSurrogate(ch)) {
-                return high;
-            }
-
-            ch = high;
-        }
-
-        return 0;
-    }
-
-    /** Return true if ch can be part of an operator.
-     */
-    private boolean isSpecial(char ch) {
-        switch (ch) {
-        case '!': case '%': case '&': case '*': case '?':
-        case '+': case '-': case ':': case '<': case '=':
-        case '>': case '^': case '|': case '~':
-        case '@':
-            return true;
-        default:
-            return false;
-        }
-    }
-
-    /** Read longest possible sequence of special characters and convert
-     *  to token.
-     */
-    private void scanOperator() {
-        while (true) {
-            putChar(ch);
-            Name newname = names.fromChars(sbuf, 0, sp);
-            if (keywords.key(newname) == IDENTIFIER) {
-                sp--;
-                break;
-            }
-            name = newname;
-            token = keywords.key(newname);
-            scanChar();
-            if (!isSpecial(ch)) break;
-        }
-    }
-
-    /**
-     * Scan a documention comment; determine if a deprecated tag is present.
-     * Called once the initial /, * have been skipped, positioned at the second *
-     * (which is treated as the beginning of the first line).
-     * Stops positioned at the closing '/'.
-     */
-    @SuppressWarnings("fallthrough")
-    private void scanDocComment() {
-        boolean deprecatedPrefix = false;
-
-        forEachLine:
-        while (bp < buflen) {
-
-            // Skip optional WhiteSpace at beginning of line
-            while (bp < buflen && (ch == ' ' || ch == '\t' || ch == FF)) {
-                scanCommentChar();
-            }
-
-            // Skip optional consecutive Stars
-            while (bp < buflen && ch == '*') {
-                scanCommentChar();
-                if (ch == '/') {
-                    return;
-                }
-            }
-
-            // Skip optional WhiteSpace after Stars
-            while (bp < buflen && (ch == ' ' || ch == '\t' || ch == FF)) {
-                scanCommentChar();
-            }
-
-            deprecatedPrefix = false;
-            // At beginning of line in the JavaDoc sense.
-            if (bp < buflen && ch == '@' && !deprecatedFlag) {
-                scanCommentChar();
-                if (bp < buflen && ch == 'd') {
-                    scanCommentChar();
-                    if (bp < buflen && ch == 'e') {
-                        scanCommentChar();
-                        if (bp < buflen && ch == 'p') {
-                            scanCommentChar();
-                            if (bp < buflen && ch == 'r') {
-                                scanCommentChar();
-                                if (bp < buflen && ch == 'e') {
-                                    scanCommentChar();
-                                    if (bp < buflen && ch == 'c') {
-                                        scanCommentChar();
-                                        if (bp < buflen && ch == 'a') {
-                                            scanCommentChar();
-                                            if (bp < buflen && ch == 't') {
-                                                scanCommentChar();
-                                                if (bp < buflen && ch == 'e') {
-                                                    scanCommentChar();
-                                                    if (bp < buflen && ch == 'd') {
-                                                        deprecatedPrefix = true;
-                                                        scanCommentChar();
-                                                    }}}}}}}}}}}
-            if (deprecatedPrefix && bp < buflen) {
-                if (Character.isWhitespace(ch)) {
-                    deprecatedFlag = true;
-                } else if (ch == '*') {
-                    scanCommentChar();
-                    if (ch == '/') {
-                        deprecatedFlag = true;
-                        return;
-                    }
-                }
-            }
-
-            // Skip rest of line
-            while (bp < buflen) {
-                switch (ch) {
-                case '*':
-                    scanCommentChar();
-                    if (ch == '/') {
-                        return;
-                    }
-                    break;
-                case CR: // (Spec 3.4)
-                    scanCommentChar();
-                    if (ch != LF) {
-                        continue forEachLine;
-                    }
-                    /* fall through to LF case */
-                case LF: // (Spec 3.4)
-                    scanCommentChar();
-                    continue forEachLine;
-                default:
-                    scanCommentChar();
-                }
-            } // rest of line
-        } // forEachLine
-        return;
-    }
-
-    /** The value of a literal token, recorded as a string.
-     *  For integers, leading 0x and 'l' suffixes are suppressed.
-     */
-    public String stringVal() {
-        return new String(sbuf, 0, sp);
+    protected Scanner(ScannerFactory fac, char[] buf, int inputLength) {
+        this(fac, new JavaTokenizer(fac, buf, inputLength));
     }
 
-    /** Read token.
-     */
-    public void nextToken() {
-
-        try {
-            prevEndPos = endPos;
-            sp = 0;
-
-            while (true) {
-                pos = bp;
-                switch (ch) {
-                case ' ': // (Spec 3.6)
-                case '\t': // (Spec 3.6)
-                case FF: // (Spec 3.6)
-                    do {
-                        scanChar();
-                    } while (ch == ' ' || ch == '\t' || ch == FF);
-                    endPos = bp;
-                    processWhiteSpace();
-                    break;
-                case LF: // (Spec 3.4)
-                    scanChar();
-                    endPos = bp;
-                    processLineTerminator();
-                    break;
-                case CR: // (Spec 3.4)
-                    scanChar();
-                    if (ch == LF) {
-                        scanChar();
-                    }
-                    endPos = bp;
-                    processLineTerminator();
-                    break;
-                case 'A': case 'B': case 'C': case 'D': case 'E':
-                case 'F': case 'G': case 'H': case 'I': case 'J':
-                case 'K': case 'L': case 'M': case 'N': case 'O':
-                case 'P': case 'Q': case 'R': case 'S': case 'T':
-                case 'U': case 'V': case 'W': case 'X': case 'Y':
-                case 'Z':
-                case 'a': case 'b': case 'c': case 'd': case 'e':
-                case 'f': case 'g': case 'h': case 'i': case 'j':
-                case 'k': case 'l': case 'm': case 'n': case 'o':
-                case 'p': case 'q': case 'r': case 's': case 't':
-                case 'u': case 'v': case 'w': case 'x': case 'y':
-                case 'z':
-                case '$': case '_':
-                    scanIdent();
-                    return;
-                case '0':
-                    scanChar();
-                    if (ch == 'x' || ch == 'X') {
-                        scanChar();
-                        skipIllegalUnderscores();
-                        if (ch == '.') {
-                            scanHexFractionAndSuffix(false);
-                        } else if (digit(16) < 0) {
-                            lexError("invalid.hex.number");
-                        } else {
-                            scanNumber(16);
-                        }
-                    } else if (ch == 'b' || ch == 'B') {
-                        if (!allowBinaryLiterals) {
-                            lexError("unsupported.binary.lit", source.name);
-                            allowBinaryLiterals = true;
-                        }
-                        scanChar();
-                        skipIllegalUnderscores();
-                        if (digit(2) < 0) {
-                            lexError("invalid.binary.number");
-                        } else {
-                            scanNumber(2);
-                        }
-                    } else {
-                        putChar('0');
-                        if (ch == '_') {
-                            int savePos = bp;
-                            do {
-                                scanChar();
-                            } while (ch == '_');
-                            if (digit(10) < 0) {
-                                lexError(savePos, "illegal.underscore");
-                            }
-                        }
-                        scanNumber(8);
-                    }
-                    return;
-                case '1': case '2': case '3': case '4':
-                case '5': case '6': case '7': case '8': case '9':
-                    scanNumber(10);
-                    return;
-                case '.':
-                    scanChar();
-                    if ('0' <= ch && ch <= '9') {
-                        putChar('.');
-                        scanFractionAndSuffix();
-                    } else if (ch == '.') {
-                        putChar('.'); putChar('.');
-                        scanChar();
-                        if (ch == '.') {
-                            scanChar();
-                            putChar('.');
-                            token = ELLIPSIS;
-                        } else {
-                            lexError("malformed.fp.lit");
-                        }
-                    } else {
-                        token = DOT;
-                    }
-                    return;
-                case ',':
-                    scanChar(); token = COMMA; return;
-                case ';':
-                    scanChar(); token = SEMI; return;
-                case '(':
-                    scanChar(); token = LPAREN; return;
-                case ')':
-                    scanChar(); token = RPAREN; return;
-                case '[':
-                    scanChar(); token = LBRACKET; return;
-                case ']':
-                    scanChar(); token = RBRACKET; return;
-                case '{':
-                    scanChar(); token = LBRACE; return;
-                case '}':
-                    scanChar(); token = RBRACE; return;
-                case '/':
-                    scanChar();
-                    if (ch == '/') {
-                        do {
-                            scanCommentChar();
-                        } while (ch != CR && ch != LF && bp < buflen);
-                        if (bp < buflen) {
-                            endPos = bp;
-                            processComment(CommentStyle.LINE);
-                        }
-                        break;
-                    } else if (ch == '*') {
-                        scanChar();
-                        CommentStyle style;
-                        if (ch == '*') {
-                            style = CommentStyle.JAVADOC;
-                            scanDocComment();
-                        } else {
-                            style = CommentStyle.BLOCK;
-                            while (bp < buflen) {
-                                if (ch == '*') {
-                                    scanChar();
-                                    if (ch == '/') break;
-                                } else {
-                                    scanCommentChar();
-                                }
-                            }
-                        }
-                        if (ch == '/') {
-                            scanChar();
-                            endPos = bp;
-                            processComment(style);
-                            break;
-                        } else {
-                            lexError("unclosed.comment");
-                            return;
-                        }
-                    } else if (ch == '=') {
-                        name = names.slashequals;
-                        token = SLASHEQ;
-                        scanChar();
-                    } else {
-                        name = names.slash;
-                        token = SLASH;
-                    }
-                    return;
-                case '\'':
-                    scanChar();
-                    if (ch == '\'') {
-                        lexError("empty.char.lit");
-                    } else {
-                        if (ch == CR || ch == LF)
-                            lexError(pos, "illegal.line.end.in.char.lit");
-                        scanLitChar();
-                        if (ch == '\'') {
-                            scanChar();
-                            token = CHARLITERAL;
-                        } else {
-                            lexError(pos, "unclosed.char.lit");
-                        }
-                    }
-                    return;
-                case '\"':
-                    scanChar();
-                    while (ch != '\"' && ch != CR && ch != LF && bp < buflen)
-                        scanLitChar();
-                    if (ch == '\"') {
-                        token = STRINGLITERAL;
-                        scanChar();
-                    } else {
-                        lexError(pos, "unclosed.str.lit");
-                    }
-                    return;
-                default:
-                    if (isSpecial(ch)) {
-                        scanOperator();
-                    } else {
-                        boolean isJavaIdentifierStart;
-                        if (ch < '\u0080') {
-                            // all ASCII range chars already handled, above
-                            isJavaIdentifierStart = false;
-                        } else {
-                            char high = scanSurrogates();
-                            if (high != 0) {
-                                if (sp == sbuf.length) {
-                                    putChar(high);
-                                } else {
-                                    sbuf[sp++] = high;
-                                }
-
-                                isJavaIdentifierStart = Character.isJavaIdentifierStart(
-                                    Character.toCodePoint(high, ch));
-                            } else {
-                                isJavaIdentifierStart = Character.isJavaIdentifierStart(ch);
-                            }
-                        }
-                        if (isJavaIdentifierStart) {
-                            scanIdent();
-                        } else if (bp == buflen || ch == EOI && bp+1 == buflen) { // JLS 3.5
-                            token = EOF;
-                            pos = bp = eofPos;
-                        } else {
-                            lexError("illegal.char", String.valueOf((int)ch));
-                            scanChar();
-                        }
-                    }
-                    return;
-                }
-            }
-        } finally {
-            endPos = bp;
-            if (scannerDebug)
-                System.out.println("nextToken(" + pos
-                                   + "," + endPos + ")=|" +
-                                   new String(getRawCharacters(pos, endPos))
-                                   + "|");
-        }
+    protected Scanner(ScannerFactory fac, JavaTokenizer tokenizer) {
+        this.tokenizer = tokenizer;
+        tokens = fac.tokens;
+        token = prevToken = DUMMY;
     }
 
-    /** Return the current token, set by nextToken().
-     */
     public Token token() {
         return token;
     }
 
-    /** Sets the current token.
-     * This method is primarily used to update the token stream when the
-     * parser is handling the end of nested type arguments such as
-     * {@code List<List<String>>} and needs to disambiguate between
-     * repeated use of ">" and relation operators such as ">>" and ">>>". Noting
-     * that this does not handle arbitrary tokens containing Unicode escape
-     * sequences.
-     */
-    public void token(Token token) {
-        pos += this.token.name.length() - token.name.length();
-        prevEndPos = pos;
-        this.token = token;
-    }
-
-    /** Return the current token's position: a 0-based
-     *  offset from beginning of the raw input stream
-     *  (before unicode translation)
-     */
-    public int pos() {
-        return pos;
-    }
-
-    /** Return the last character position of the current token.
-     */
-    public int endPos() {
-        return endPos;
-    }
-
-    /** Return the last character position of the previous token.
-     */
-    public int prevEndPos() {
-        return prevEndPos;
+    public Token prevToken() {
+        return prevToken;
     }
 
-    /** Return the position where a lexical error occurred;
-     */
-    public int errPos() {
-        return errPos;
-    }
-
-    /** Set the position where a lexical error occurred;
-     */
-    public void errPos(int pos) {
-        errPos = pos;
-    }
-
-    /** Return the name of an identifier or token for the current token.
-     */
-    public Name name() {
-        return name;
-    }
-
-    /** Return the radix of a numeric literal token.
-     */
-    public int radix() {
-        return radix;
-    }
-
-    /** Has a @deprecated been encountered in last doc comment?
-     *  This needs to be reset by client with resetDeprecatedFlag.
-     */
-    public boolean deprecatedFlag() {
-        return deprecatedFlag;
-    }
-
-    public void resetDeprecatedFlag() {
-        deprecatedFlag = false;
-    }
-
-    /**
-     * Returns the documentation string of the current token.
-     */
-    public String docComment() {
-        return null;
+    public void nextToken() {
+        prevToken = token;
+        token = tokenizer.readToken();
     }
 
-    /**
-     * Returns a copy of the input buffer, up to its inputLength.
-     * Unicode escape sequences are not translated.
-     */
-    public char[] getRawCharacters() {
-        char[] chars = new char[buflen];
-        System.arraycopy(buf, 0, chars, 0, buflen);
-        return chars;
-    }
-
-    /**
-     * Returns a copy of a character array subset of the input buffer.
-     * The returned array begins at the <code>beginIndex</code> and
-     * extends to the character at index <code>endIndex - 1</code>.
-     * Thus the length of the substring is <code>endIndex-beginIndex</code>.
-     * This behavior is like
-     * <code>String.substring(beginIndex, endIndex)</code>.
-     * Unicode escape sequences are not translated.
-     *
-     * @param beginIndex the beginning index, inclusive.
-     * @param endIndex the ending index, exclusive.
-     * @throws IndexOutOfBounds if either offset is outside of the
-     *         array bounds
-     */
-    public char[] getRawCharacters(int beginIndex, int endIndex) {
-        int length = endIndex - beginIndex;
-        char[] chars = new char[length];
-        System.arraycopy(buf, beginIndex, chars, 0, length);
-        return chars;
-    }
-
-    public enum CommentStyle {
-        LINE,
-        BLOCK,
-        JAVADOC,
+    public Token split() {
+        Token[] splitTokens = token.split(tokens);
+        prevToken = splitTokens[0];
+        token = splitTokens[1];
+        return token;
     }
 
-    /**
-     * Called when a complete comment has been scanned. pos and endPos
-     * will mark the comment boundary.
-     */
-    protected void processComment(CommentStyle style) {
-        if (scannerDebug)
-            System.out.println("processComment(" + pos
-                               + "," + endPos + "," + style + ")=|"
-                               + new String(getRawCharacters(pos, endPos))
-                               + "|");
+    public LineMap getLineMap() {
+        return tokenizer.getLineMap();
     }
 
-    /**
-     * Called when a complete whitespace run has been scanned. pos and endPos
-     * will mark the whitespace boundary.
-     */
-    protected void processWhiteSpace() {
-        if (scannerDebug)
-            System.out.println("processWhitespace(" + pos
-                               + "," + endPos + ")=|" +
-                               new String(getRawCharacters(pos, endPos))
-                               + "|");
+    public int errPos() {
+        return tokenizer.errPos();
     }
 
-    /**
-     * Called when a line terminator has been processed.
-     */
-    protected void processLineTerminator() {
-        if (scannerDebug)
-            System.out.println("processTerminator(" + pos
-                               + "," + endPos + ")=|" +
-                               new String(getRawCharacters(pos, endPos))
-                               + "|");
+    public void errPos(int pos) {
+        tokenizer.errPos(pos);
     }
-
-    /** Build a map for translating between line numbers and
-     * positions in the input.
-     *
-     * @return a LineMap */
-    public Position.LineMap getLineMap() {
-        return Position.makeLineMap(buf, buflen, false);
-    }
-
 }
--- a/langtools/src/share/classes/com/sun/tools/javac/parser/ScannerFactory.java	Wed Jul 05 17:53:51 2017 +0200
+++ b/langtools/src/share/classes/com/sun/tools/javac/parser/ScannerFactory.java	Wed Jul 05 17:54:24 2017 +0200
@@ -57,7 +57,7 @@
     final Log log;
     final Names names;
     final Source source;
-    final Keywords keywords;
+    final Tokens tokens;
 
     /** Create a new scanner factory. */
     protected ScannerFactory(Context context) {
@@ -65,14 +65,14 @@
         this.log = Log.instance(context);
         this.names = Names.instance(context);
         this.source = Source.instance(context);
-        this.keywords = Keywords.instance(context);
+        this.tokens = Tokens.instance(context);
     }
 
     public Scanner newScanner(CharSequence input, boolean keepDocComments) {
         if (input instanceof CharBuffer) {
             CharBuffer buf = (CharBuffer) input;
             if (keepDocComments)
-                return new DocCommentScanner(this, buf);
+                return new Scanner(this, new JavadocTokenizer(this, buf));
             else
                 return new Scanner(this, buf);
         } else {
@@ -83,7 +83,7 @@
 
     public Scanner newScanner(char[] input, int inputLength, boolean keepDocComments) {
         if (keepDocComments)
-            return new DocCommentScanner(this, input, inputLength);
+            return new Scanner(this, new JavadocTokenizer(this, input, inputLength));
         else
             return new Scanner(this, input, inputLength);
     }
--- a/langtools/src/share/classes/com/sun/tools/javac/parser/Token.java	Wed Jul 05 17:53:51 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,198 +0,0 @@
-/*
- * Copyright (c) 1999, 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.  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.parser;
-
-import java.util.Locale;
-
-import com.sun.tools.javac.api.Formattable;
-import com.sun.tools.javac.api.Messages;
-
-/** An interface that defines codes for Java source tokens
- *  returned from lexical analysis.
- *
- *  <p><b>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.</b>
- */
-public enum Token implements Formattable {
-    EOF,
-    ERROR,
-    IDENTIFIER,
-    ABSTRACT("abstract"),
-    ASSERT("assert"),
-    BOOLEAN("boolean"),
-    BREAK("break"),
-    BYTE("byte"),
-    CASE("case"),
-    CATCH("catch"),
-    CHAR("char"),
-    CLASS("class"),
-    CONST("const"),
-    CONTINUE("continue"),
-    DEFAULT("default"),
-    DO("do"),
-    DOUBLE("double"),
-    ELSE("else"),
-    ENUM("enum"),
-    EXTENDS("extends"),
-    FINAL("final"),
-    FINALLY("finally"),
-    FLOAT("float"),
-    FOR("for"),
-    GOTO("goto"),
-    IF("if"),
-    IMPLEMENTS("implements"),
-    IMPORT("import"),
-    INSTANCEOF("instanceof"),
-    INT("int"),
-    INTERFACE("interface"),
-    LONG("long"),
-    NATIVE("native"),
-    NEW("new"),
-    PACKAGE("package"),
-    PRIVATE("private"),
-    PROTECTED("protected"),
-    PUBLIC("public"),
-    RETURN("return"),
-    SHORT("short"),
-    STATIC("static"),
-    STRICTFP("strictfp"),
-    SUPER("super"),
-    SWITCH("switch"),
-    SYNCHRONIZED("synchronized"),
-    THIS("this"),
-    THROW("throw"),
-    THROWS("throws"),
-    TRANSIENT("transient"),
-    TRY("try"),
-    VOID("void"),
-    VOLATILE("volatile"),
-    WHILE("while"),
-    INTLITERAL,
-    LONGLITERAL,
-    FLOATLITERAL,
-    DOUBLELITERAL,
-    CHARLITERAL,
-    STRINGLITERAL,
-    TRUE("true"),
-    FALSE("false"),
-    NULL("null"),
-    LPAREN("("),
-    RPAREN(")"),
-    LBRACE("{"),
-    RBRACE("}"),
-    LBRACKET("["),
-    RBRACKET("]"),
-    SEMI(";"),
-    COMMA(","),
-    DOT("."),
-    ELLIPSIS("..."),
-    EQ("="),
-    GT(">"),
-    LT("<"),
-    BANG("!"),
-    TILDE("~"),
-    QUES("?"),
-    COLON(":"),
-    EQEQ("=="),
-    LTEQ("<="),
-    GTEQ(">="),
-    BANGEQ("!="),
-    AMPAMP("&&"),
-    BARBAR("||"),
-    PLUSPLUS("++"),
-    SUBSUB("--"),
-    PLUS("+"),
-    SUB("-"),
-    STAR("*"),
-    SLASH("/"),
-    AMP("&"),
-    BAR("|"),
-    CARET("^"),
-    PERCENT("%"),
-    LTLT("<<"),
-    GTGT(">>"),
-    GTGTGT(">>>"),
-    PLUSEQ("+="),
-    SUBEQ("-="),
-    STAREQ("*="),
-    SLASHEQ("/="),
-    AMPEQ("&="),
-    BAREQ("|="),
-    CARETEQ("^="),
-    PERCENTEQ("%="),
-    LTLTEQ("<<="),
-    GTGTEQ(">>="),
-    GTGTGTEQ(">>>="),
-    MONKEYS_AT("@"),
-    CUSTOM;
-
-    Token() {
-        this(null);
-    }
-    Token(String name) {
-        this.name = name;
-    }
-
-    public final String name;
-
-    public String toString() {
-        switch (this) {
-        case IDENTIFIER:
-            return "token.identifier";
-        case CHARLITERAL:
-            return "token.character";
-        case STRINGLITERAL:
-            return "token.string";
-        case INTLITERAL:
-            return "token.integer";
-        case LONGLITERAL:
-            return "token.long-integer";
-        case FLOATLITERAL:
-            return "token.float";
-        case DOUBLELITERAL:
-            return "token.double";
-        case ERROR:
-            return "token.bad-symbol";
-        case EOF:
-            return "token.end-of-input";
-        case DOT: case COMMA: case SEMI: case LPAREN: case RPAREN:
-        case LBRACKET: case RBRACKET: case LBRACE: case RBRACE:
-            return "'" + name + "'";
-        default:
-            return name;
-        }
-    }
-
-    public String getKind() {
-        return "Token";
-    }
-
-    public String toString(Locale locale, Messages messages) {
-        return name != null ? toString() : messages.getLocalizedString(locale, "compiler.misc." + toString());
-    }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/share/classes/com/sun/tools/javac/parser/Tokens.java	Wed Jul 05 17:54:24 2017 +0200
@@ -0,0 +1,423 @@
+/*
+ * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
+ * 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.parser;
+
+import java.util.Locale;
+
+import com.sun.tools.javac.api.Formattable;
+import com.sun.tools.javac.api.Messages;
+import com.sun.tools.javac.parser.Tokens.Token.Tag;
+import com.sun.tools.javac.util.Name;
+import com.sun.tools.javac.util.Context;
+import com.sun.tools.javac.util.Names;
+
+/** A class that defines codes/utilities for Java source tokens
+ *  returned from lexical analysis.
+ *
+ *  <p><b>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.</b>
+ */
+public class Tokens {
+
+    private final Names names;
+
+    /**
+     * Keyword array. Maps name indices to Token.
+     */
+    private final TokenKind[] key;
+
+    /**  The number of the last entered keyword.
+     */
+    private int maxKey = 0;
+
+    /** The names of all tokens.
+     */
+    private Name[] tokenName = new Name[TokenKind.values().length];
+
+    public static final Context.Key<Tokens> tokensKey =
+        new Context.Key<Tokens>();
+
+    public static Tokens instance(Context context) {
+        Tokens instance = context.get(tokensKey);
+        if (instance == null)
+            instance = new Tokens(context);
+        return instance;
+    }
+
+    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);
+            else
+                tokenName[t.ordinal()] = null;
+        }
+
+        key = new TokenKind[maxKey+1];
+        for (int i = 0; i <= maxKey; i++) key[i] = TokenKind.IDENTIFIER;
+        for (TokenKind t : TokenKind.values()) {
+            if (t.name != null)
+            key[tokenName[t.ordinal()].getIndex()] = t;
+        }
+    }
+
+    private void enterKeyword(String s, TokenKind token) {
+        Name n = names.fromString(s);
+        tokenName[token.ordinal()] = n;
+        if (n.getIndex() > maxKey) maxKey = n.getIndex();
+    }
+
+    /**
+     * Create a new token given a name; if the name corresponds to a token name,
+     * a new token of the corresponding kind is returned; otherwise, an
+     * identifier token is returned.
+     */
+    TokenKind lookupKind(Name name) {
+        return (name.getIndex() > maxKey) ? TokenKind.IDENTIFIER : key[name.getIndex()];
+    }
+
+    TokenKind lookupKind(String name) {
+        return lookupKind(names.fromString(name));
+    }
+
+    /**
+     * This enum defines all tokens used by the javac scanner. A token is
+     * optionally associated with a name.
+     */
+    public enum TokenKind implements Formattable {
+        EOF(),
+        ERROR(),
+        IDENTIFIER(Tag.NAMED),
+        ABSTRACT("abstract"),
+        ASSERT("assert", Tag.NAMED),
+        BOOLEAN("boolean", Tag.NAMED),
+        BREAK("break"),
+        BYTE("byte", Tag.NAMED),
+        CASE("case"),
+        CATCH("catch"),
+        CHAR("char", Tag.NAMED),
+        CLASS("class"),
+        CONST("const"),
+        CONTINUE("continue"),
+        DEFAULT("default"),
+        DO("do"),
+        DOUBLE("double", Tag.NAMED),
+        ELSE("else"),
+        ENUM("enum", Tag.NAMED),
+        EXTENDS("extends"),
+        FINAL("final"),
+        FINALLY("finally"),
+        FLOAT("float", Tag.NAMED),
+        FOR("for"),
+        GOTO("goto"),
+        IF("if"),
+        IMPLEMENTS("implements"),
+        IMPORT("import"),
+        INSTANCEOF("instanceof"),
+        INT("int", Tag.NAMED),
+        INTERFACE("interface"),
+        LONG("long", Tag.NAMED),
+        NATIVE("native"),
+        NEW("new"),
+        PACKAGE("package"),
+        PRIVATE("private"),
+        PROTECTED("protected"),
+        PUBLIC("public"),
+        RETURN("return"),
+        SHORT("short", Tag.NAMED),
+        STATIC("static"),
+        STRICTFP("strictfp"),
+        SUPER("super", Tag.NAMED),
+        SWITCH("switch"),
+        SYNCHRONIZED("synchronized"),
+        THIS("this", Tag.NAMED),
+        THROW("throw"),
+        THROWS("throws"),
+        TRANSIENT("transient"),
+        TRY("try"),
+        VOID("void", Tag.NAMED),
+        VOLATILE("volatile"),
+        WHILE("while"),
+        INTLITERAL(Tag.NUMERIC),
+        LONGLITERAL(Tag.NUMERIC),
+        FLOATLITERAL(Tag.NUMERIC),
+        DOUBLELITERAL(Tag.NUMERIC),
+        CHARLITERAL(Tag.NUMERIC),
+        STRINGLITERAL(Tag.STRING),
+        TRUE("true", Tag.NAMED),
+        FALSE("false", Tag.NAMED),
+        NULL("null", Tag.NAMED),
+        LPAREN("("),
+        RPAREN(")"),
+        LBRACE("{"),
+        RBRACE("}"),
+        LBRACKET("["),
+        RBRACKET("]"),
+        SEMI(";"),
+        COMMA(","),
+        DOT("."),
+        ELLIPSIS("..."),
+        EQ("="),
+        GT(">"),
+        LT("<"),
+        BANG("!"),
+        TILDE("~"),
+        QUES("?"),
+        COLON(":"),
+        EQEQ("=="),
+        LTEQ("<="),
+        GTEQ(">="),
+        BANGEQ("!="),
+        AMPAMP("&&"),
+        BARBAR("||"),
+        PLUSPLUS("++"),
+        SUBSUB("--"),
+        PLUS("+"),
+        SUB("-"),
+        STAR("*"),
+        SLASH("/"),
+        AMP("&"),
+        BAR("|"),
+        CARET("^"),
+        PERCENT("%"),
+        LTLT("<<"),
+        GTGT(">>"),
+        GTGTGT(">>>"),
+        PLUSEQ("+="),
+        SUBEQ("-="),
+        STAREQ("*="),
+        SLASHEQ("/="),
+        AMPEQ("&="),
+        BAREQ("|="),
+        CARETEQ("^="),
+        PERCENTEQ("%="),
+        LTLTEQ("<<="),
+        GTGTEQ(">>="),
+        GTGTGTEQ(">>>="),
+        MONKEYS_AT("@"),
+        CUSTOM;
+
+        public final String name;
+        public final Tag tag;
+
+        TokenKind() {
+            this(null, Tag.DEFAULT);
+        }
+
+        TokenKind(String name) {
+            this(name, Tag.DEFAULT);
+        }
+
+        TokenKind(Tag tag) {
+            this(null, tag);
+        }
+
+        TokenKind(String name, Tag tag) {
+            this.name = name;
+            this.tag = tag;
+        }
+
+        public String toString() {
+            switch (this) {
+            case IDENTIFIER:
+                return "token.identifier";
+            case CHARLITERAL:
+                return "token.character";
+            case STRINGLITERAL:
+                return "token.string";
+            case INTLITERAL:
+                return "token.integer";
+            case LONGLITERAL:
+                return "token.long-integer";
+            case FLOATLITERAL:
+                return "token.float";
+            case DOUBLELITERAL:
+                return "token.double";
+            case ERROR:
+                return "token.bad-symbol";
+            case EOF:
+                return "token.end-of-input";
+            case DOT: case COMMA: case SEMI: case LPAREN: case RPAREN:
+            case LBRACKET: case RBRACKET: case LBRACE: case RBRACE:
+                return "'" + name + "'";
+            default:
+                return name;
+            }
+        }
+
+        public String getKind() {
+            return "Token";
+        }
+
+        public String toString(Locale locale, Messages messages) {
+            return name != null ? toString() : messages.getLocalizedString(locale, "compiler.misc." + toString());
+        }
+    }
+
+    /**
+     * This is the class representing a javac token. Each token has several fields
+     * that are set by the javac lexer (i.e. start/end position, string value, etc).
+     */
+    public static class Token {
+
+        /** tags constants **/
+        enum Tag {
+            DEFAULT,
+            NAMED,
+            STRING,
+            NUMERIC;
+        }
+
+        /** The token kind */
+        public final TokenKind kind;
+
+        /** The start position of this token */
+        public final int pos;
+
+        /** The end position of this token */
+        public final int endPos;
+
+        /** Is this token preceeded by a deprecated comment? */
+        public final boolean deprecatedFlag;
+
+        /** Is this token preceeded by a deprecated comment? */
+        public String docComment;
+
+        Token(TokenKind kind, int pos, int endPos,
+                boolean deprecatedFlag) {
+            this.kind = kind;
+            this.pos = pos;
+            this.endPos = endPos;
+            this.deprecatedFlag = deprecatedFlag;
+            checkKind();
+        }
+
+        Token[] split(Tokens tokens) {
+            if (kind.name.length() < 2 || kind.tag != Tag.DEFAULT) {
+                throw new AssertionError("Cant split" + kind);
+            }
+
+            TokenKind t1 = tokens.lookupKind(kind.name.substring(0, 1));
+            TokenKind t2 = tokens.lookupKind(kind.name.substring(1));
+
+            if (t1 == null || t2 == null) {
+                throw new AssertionError("Cant split - bad subtokens");
+            }
+            return new Token[] {
+                new Token(t1, pos, pos + t1.name.length(), deprecatedFlag),
+                new Token(t2, pos + t1.name.length(), endPos, false)
+            };
+        }
+
+        protected void checkKind() {
+            if (kind.tag != Tag.DEFAULT) {
+                throw new AssertionError("Bad token kind - expected " + Tag.STRING);
+            }
+        }
+
+        public Name name() {
+            throw new UnsupportedOperationException();
+        }
+
+        public String stringVal() {
+            throw new UnsupportedOperationException();
+        }
+
+        public int radix() {
+            throw new UnsupportedOperationException();
+        }
+    }
+
+    final static class NamedToken extends Token {
+        /** The name of this token */
+        public final Name name;
+
+        public NamedToken(TokenKind kind, int pos, int endPos, Name name, boolean deprecatedFlag) {
+            super(kind, pos, endPos, deprecatedFlag);
+            this.name = name;
+        }
+
+        protected void checkKind() {
+            if (kind.tag != Tag.NAMED) {
+                throw new AssertionError("Bad token kind - expected " + Tag.NAMED);
+            }
+        }
+
+        @Override
+        public Name name() {
+            return name;
+        }
+    }
+
+    static class StringToken extends Token {
+        /** The string value of this token */
+        public final String stringVal;
+
+        public StringToken(TokenKind kind, int pos, int endPos, String stringVal, boolean deprecatedFlag) {
+            super(kind, pos, endPos, deprecatedFlag);
+            this.stringVal = stringVal;
+        }
+
+        protected void checkKind() {
+            if (kind.tag != Tag.STRING) {
+                throw new AssertionError("Bad token kind - expected " + Tag.STRING);
+            }
+        }
+
+        @Override
+        public String stringVal() {
+            return stringVal;
+        }
+    }
+
+    final static class NumericToken extends StringToken {
+        /** The 'radix' value of this token */
+        public final int radix;
+
+        public NumericToken(TokenKind kind, int pos, int endPos, String stringVal, int radix, boolean deprecatedFlag) {
+            super(kind, pos, endPos, stringVal, deprecatedFlag);
+            this.radix = radix;
+        }
+
+        protected void checkKind() {
+            if (kind.tag != Tag.NUMERIC) {
+                throw new AssertionError("Bad token kind - expected " + Tag.NUMERIC);
+            }
+        }
+
+        @Override
+        public int radix() {
+            return radix;
+        }
+    }
+
+    public static final Token DUMMY =
+                new Token(TokenKind.ERROR, 0, 0, false);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/share/classes/com/sun/tools/javac/parser/UnicodeReader.java	Wed Jul 05 17:54:24 2017 +0200
@@ -0,0 +1,227 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * 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.parser;
+
+import com.sun.tools.javac.file.JavacFileManager;
+import java.nio.CharBuffer;
+import com.sun.tools.javac.util.Log;
+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
+ * them at a later stage.
+ *
+ *  <p><b>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.</b>
+ */
+public class UnicodeReader {
+
+    /** The input buffer, index of next character to be read,
+     *  index of one past last character in buffer.
+     */
+    protected char[] buf;
+    protected int bp;
+    protected final int buflen;
+
+    /** The current character.
+     */
+    protected char ch;
+
+    /** The buffer index of the last converted unicode character
+     */
+    protected int unicodeConversionBp = -1;
+
+    protected Log log;
+
+    /**
+     * Create a scanner from the input array.  This method might
+     * modify the array.  To avoid copying the input array, ensure
+     * that {@code inputLength < input.length} or
+     * {@code input[input.length -1]} is a white space character.
+     *
+     * @param fac the factory which created this Scanner
+     * @param input the input, might be modified
+     * @param inputLength the size of the input.
+     * Must be positive and less than or equal to input.length.
+     */
+    protected UnicodeReader(ScannerFactory sf, CharBuffer buffer) {
+        this(sf, JavacFileManager.toArray(buffer), buffer.limit());
+    }
+
+    protected UnicodeReader(ScannerFactory sf, char[] input, int inputLength) {
+        log = sf.log;
+        if (inputLength == input.length) {
+            if (input.length > 0 && Character.isWhitespace(input[input.length - 1])) {
+                inputLength--;
+            } else {
+                char[] newInput = new char[inputLength + 1];
+                System.arraycopy(input, 0, newInput, 0, input.length);
+                input = newInput;
+            }
+        }
+        buf = input;
+        buflen = inputLength;
+        buf[buflen] = EOI;
+        bp = -1;
+        scanChar();
+    }
+
+    /** Read next character.
+     */
+    protected void scanChar() {
+        if (bp < buflen) {
+            ch = buf[++bp];
+            if (ch == '\\') {
+                convertUnicode();
+            }
+        }
+    }
+
+    /** Convert unicode escape; bp points to initial '\' character
+     *  (Spec 3.3).
+     */
+    protected void convertUnicode() {
+        if (ch == '\\' && unicodeConversionBp != bp) {
+            bp++; ch = buf[bp];
+            if (ch == 'u') {
+                do {
+                    bp++; ch = buf[bp];
+                } while (ch == 'u');
+                int limit = bp + 3;
+                if (limit < buflen) {
+                    int d = digit(bp, 16);
+                    int code = d;
+                    while (bp < limit && d >= 0) {
+                        bp++; ch = buf[bp];
+                        d = digit(bp, 16);
+                        code = (code << 4) + d;
+                    }
+                    if (d >= 0) {
+                        ch = (char)code;
+                        unicodeConversionBp = bp;
+                        return;
+                    }
+                }
+                log.error(bp, "illegal.unicode.esc");
+            } else {
+                bp--;
+                ch = '\\';
+            }
+        }
+    }
+
+    /** Are surrogates supported?
+     */
+    final static boolean surrogatesSupported = surrogatesSupported();
+    private static boolean surrogatesSupported() {
+        try {
+            Character.isHighSurrogate('a');
+            return true;
+        } catch (NoSuchMethodError ex) {
+            return false;
+        }
+    }
+
+    /** Scan surrogate pairs.  If 'ch' is a high surrogate and
+     *  the next character is a low surrogate, then put the low
+     *  surrogate in 'ch', and return the high surrogate.
+     *  otherwise, just return 0.
+     */
+    protected char scanSurrogates() {
+        if (surrogatesSupported && Character.isHighSurrogate(ch)) {
+            char high = ch;
+
+            scanChar();
+
+            if (Character.isLowSurrogate(ch)) {
+                return high;
+            }
+
+            ch = high;
+        }
+
+        return 0;
+    }
+
+    /** Convert an ASCII digit from its base (8, 10, or 16)
+     *  to its value.
+     */
+    protected int digit(int pos, int base) {
+        char c = ch;
+        int result = Character.digit(c, base);
+        if (result >= 0 && c > 0x7f) {
+            log.error(pos + 1, "illegal.nonascii.digit");
+            ch = "0123456789abcdef".charAt(result);
+        }
+        return result;
+    }
+
+    protected boolean isUnicode() {
+        return unicodeConversionBp == bp;
+    }
+
+    protected void skipChar() {
+        bp++;
+    }
+
+    protected char peekChar() {
+        return buf[bp + 1];
+    }
+
+    /**
+     * Returns a copy of the input buffer, up to its inputLength.
+     * Unicode escape sequences are not translated.
+     */
+    public char[] getRawCharacters() {
+        char[] chars = new char[buflen];
+        System.arraycopy(buf, 0, chars, 0, buflen);
+        return chars;
+    }
+
+    /**
+     * Returns a copy of a character array subset of the input buffer.
+     * The returned array begins at the <code>beginIndex</code> and
+     * extends to the character at index <code>endIndex - 1</code>.
+     * Thus the length of the substring is <code>endIndex-beginIndex</code>.
+     * This behavior is like
+     * <code>String.substring(beginIndex, endIndex)</code>.
+     * Unicode escape sequences are not translated.
+     *
+     * @param beginIndex the beginning index, inclusive.
+     * @param endIndex the ending index, exclusive.
+     * @throws IndexOutOfBounds if either offset is outside of the
+     *         array bounds
+     */
+    public char[] getRawCharacters(int beginIndex, int endIndex) {
+        int length = endIndex - beginIndex;
+        char[] chars = new char[length];
+        System.arraycopy(buf, beginIndex, chars, 0, length);
+        return chars;
+    }
+}
--- a/langtools/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java	Wed Jul 05 17:53:51 2017 +0200
+++ b/langtools/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java	Wed Jul 05 17:54:24 2017 +0200
@@ -1072,9 +1072,9 @@
             Assert.checkNonNull(names);
             next.put(Names.namesKey, names);
 
-            Keywords keywords = Keywords.instance(context);
-            Assert.checkNonNull(keywords);
-            next.put(Keywords.keywordsKey, keywords);
+            Tokens tokens = Tokens.instance(context);
+            Assert.checkNonNull(tokens);
+            next.put(Tokens.tokensKey, tokens);
 
             JavaCompiler oldCompiler = JavaCompiler.instance(context);
             JavaCompiler nextCompiler = JavaCompiler.instance(next);
--- a/langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties	Wed Jul 05 17:53:51 2017 +0200
+++ b/langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties	Wed Jul 05 17:54:24 2017 +0200
@@ -1944,6 +1944,55 @@
     (use -source 7 or higher to enable strings in switch)
 
 ########################################
+# Diagnostics for verbose resolution
+# used by Resolve (debug only)
+########################################
+
+# 0: number, 1: symbol, 2: unused
+compiler.misc.applicable.method.found=\
+    #{0} applicable method found: {1}
+
+# 0: number, 1: symbol, 2: message segment
+compiler.misc.applicable.method.found.1=\
+    #{0} applicable method found: {1}\n\
+    ({2})
+
+# 0: number, 1: symbol, 2: message segment
+compiler.misc.not.applicable.method.found=\
+    #{0} not applicable method found: {1}\n\
+    ({2})
+
+# 0: type
+compiler.misc.full.inst.sig=\
+    fully instantiated to: {0}
+
+# 0: type
+compiler.misc.partial.inst.sig=\
+    partially instantiated to: {0}
+
+# 0: name, 1: symbol, 2: number, 3: MethodResolutionPhase, 4: list of type or message segment, 5: list of type or message segment
+compiler.note.verbose.resolve.multi=\
+    resolving method {0} in type {1} to candidate {2}\n\
+    phase: {3}\n\
+    with actuals: {4}\n\
+    with type-args: {5}\n\
+    candidates:
+
+# 0: name, 1: symbol, 2: unused, 3: MethodResolutionPhase, 4: list of type or message segment, 5: list of type or message segment
+compiler.note.verbose.resolve.multi.1=\
+    erroneous resolution for method {0} in type {1}\n\
+    phase: {3}\n\
+    with actuals: {4}\n\
+    with type-args: {5}\n\
+    candidates:
+
+# 0: symbol, 1: type, 2: type
+compiler.note.deferred.method.inst=\
+    Deferred instantiation of method {0}\n\
+    instantiated signature: {1}\n\
+    target-type: {2}
+
+########################################
 # Diagnostics for where clause implementation
 # used by the RichDiagnosticFormatter.
 ########################################
--- a/langtools/src/share/classes/com/sun/tools/javac/util/BaseFileManager.java	Wed Jul 05 17:53:51 2017 +0200
+++ b/langtools/src/share/classes/com/sun/tools/javac/util/BaseFileManager.java	Wed Jul 05 17:54:24 2017 +0200
@@ -25,11 +25,6 @@
 
 package com.sun.tools.javac.util;
 
-import com.sun.tools.javac.code.Source;
-import com.sun.tools.javac.main.JavacOption;
-import com.sun.tools.javac.main.OptionName;
-import com.sun.tools.javac.main.RecognizedOptions;
-import com.sun.tools.javac.util.JCDiagnostic.SimpleDiagnosticPosition;
 import java.io.ByteArrayOutputStream;
 import java.io.Closeable;
 import java.io.IOException;
@@ -54,6 +49,15 @@
 import javax.tools.JavaFileObject;
 import javax.tools.JavaFileObject.Kind;
 
+import com.sun.tools.javac.code.Lint;
+import com.sun.tools.javac.code.Source;
+import com.sun.tools.javac.file.FSInfo;
+import com.sun.tools.javac.file.Locations;
+import com.sun.tools.javac.main.JavacOption;
+import com.sun.tools.javac.main.OptionName;
+import com.sun.tools.javac.main.RecognizedOptions;
+import com.sun.tools.javac.util.JCDiagnostic.SimpleDiagnosticPosition;
+
 /**
  * Utility methods for building a filemanager.
  * There are no references here to file-system specific objects such as
@@ -63,15 +67,21 @@
     protected BaseFileManager(Charset charset) {
         this.charset = charset;
         byteBufferCache = new ByteBufferCache();
+        locations = createLocations();
     }
 
     /**
      * Set the context for JavacPathFileManager.
      */
-    protected void setContext(Context context) {
+    public void setContext(Context context) {
         log = Log.instance(context);
         options = Options.instance(context);
         classLoaderClass = options.get("procloader");
+        locations.update(log, options, Lint.instance(context), FSInfo.instance(context));
+    }
+
+    protected Locations createLocations() {
+        return new Locations();
     }
 
     /**
@@ -88,6 +98,8 @@
 
     protected String classLoaderClass;
 
+    protected Locations locations;
+
     protected Source getSource() {
         String sourceName = options.get(OptionName.SOURCE);
         Source source = null;
--- a/langtools/src/share/classes/com/sun/tools/javadoc/DocletInvoker.java	Wed Jul 05 17:53:51 2017 +0200
+++ b/langtools/src/share/classes/com/sun/tools/javadoc/DocletInvoker.java	Wed Jul 05 17:54:24 2017 +0200
@@ -80,7 +80,7 @@
         cpString = appendPath(System.getProperty("env.class.path"), cpString);
         cpString = appendPath(System.getProperty("java.class.path"), cpString);
         cpString = appendPath(docletPath, cpString);
-        URL[] urls = com.sun.tools.javac.file.Paths.pathToURLs(cpString);
+        URL[] urls = com.sun.tools.javac.file.Locations.pathToURLs(cpString);
         if (docletParentClassLoader == null)
             appClassLoader = new URLClassLoader(urls, getDelegationClassLoader(docletClassName));
         else
--- a/langtools/src/share/classes/com/sun/tools/javadoc/JavadocTool.java	Wed Jul 05 17:53:51 2017 +0200
+++ b/langtools/src/share/classes/com/sun/tools/javadoc/JavadocTool.java	Wed Jul 05 17:54:24 2017 +0200
@@ -39,7 +39,6 @@
 
 import com.sun.tools.javac.code.Symbol.CompletionFailure;
 import com.sun.tools.javac.comp.Annotate;
-import com.sun.tools.javac.parser.DocCommentScanner;
 import com.sun.tools.javac.tree.JCTree;
 import com.sun.tools.javac.tree.JCTree.JCClassDecl;
 import com.sun.tools.javac.tree.JCTree.JCCompilationUnit;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/7102515/T7102515.java	Wed Jul 05 17:54:24 2017 +0200
@@ -0,0 +1,11 @@
+/*
+ * @test /nodynamiccopyright/
+ * @bug 7102515
+ * @summary javac running very very long and not returning
+ * @compile/fail/ref=T7102515.out -XDrawDiagnostics T7102515.java
+ */
+
+class T7102515 {
+    T7102515 badBinary = new T7102515() + new T7102515();
+    Object badUnary = badBinary++;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/7102515/T7102515.out	Wed Jul 05 17:54:24 2017 +0200
@@ -0,0 +1,3 @@
+T7102515.java:9:41: compiler.err.operator.cant.be.applied.1: +, T7102515, T7102515
+T7102515.java:10:32: compiler.err.operator.cant.be.applied: ++, T7102515, null
+2 errors
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/T7093325.java	Wed Jul 05 17:54:24 2017 +0200
@@ -0,0 +1,262 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * 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 7093325
+ * @summary Redundant entry in bytecode exception table
+ */
+
+import com.sun.source.util.JavacTask;
+import com.sun.tools.classfile.Attribute;
+import com.sun.tools.classfile.ClassFile;
+import com.sun.tools.classfile.Code_attribute;
+import com.sun.tools.classfile.ConstantPool.*;
+import com.sun.tools.classfile.Method;
+import com.sun.tools.javac.api.JavacTool;
+
+import java.io.File;
+import java.net.URI;
+import java.util.Arrays;
+import javax.tools.JavaCompiler;
+import javax.tools.JavaFileObject;
+import javax.tools.SimpleJavaFileObject;
+import javax.tools.StandardJavaFileManager;
+import javax.tools.ToolProvider;
+
+
+public class T7093325 {
+
+    /** global decls ***/
+
+    // Create a single file manager and reuse it for each compile to save time.
+    static StandardJavaFileManager fm = JavacTool.create().getStandardFileManager(null, null, null);
+
+    //statistics
+    static int checkCount = 0;
+
+    enum StatementKind {
+        THROW("throw new RuntimeException();", false, false),
+        RETURN_NONEMPTY("System.out.println(); return;", true, false),
+        RETURN_EMPTY("return;", true, true),
+        APPLY("System.out.println();", true, false);
+
+        String stmt;
+        boolean canInline;
+        boolean empty;
+
+        private StatementKind(String stmt, boolean canInline, boolean empty) {
+            this.stmt = stmt;
+            this.canInline = canInline;
+            this.empty = empty;
+        }
+    }
+
+    enum CatchArity {
+        NONE(""),
+        ONE("catch (A a) { #S1 }"),
+        TWO("catch (B b) { #S2 }"),
+        THREE("catch (C c) { #S3 }"),
+        FOUR("catch (D d) { #S4 }");
+
+        String catchStr;
+
+        private CatchArity(String catchStr) {
+            this.catchStr = catchStr;
+        }
+
+        String catchers() {
+            if (this.ordinal() == 0) {
+                return catchStr;
+            } else {
+                return CatchArity.values()[this.ordinal() - 1].catchers() + catchStr;
+            }
+        }
+    }
+
+    public static void main(String... args) throws Exception {
+        for (CatchArity ca : CatchArity.values()) {
+            for (StatementKind stmt0 : StatementKind.values()) {
+                if (ca.ordinal() == 0) {
+                    new T7093325(ca, stmt0).compileAndCheck();
+                    continue;
+                }
+                for (StatementKind stmt1 : StatementKind.values()) {
+                    if (ca.ordinal() == 1) {
+                        new T7093325(ca, stmt0, stmt1).compileAndCheck();
+                        continue;
+                    }
+                    for (StatementKind stmt2 : StatementKind.values()) {
+                        if (ca.ordinal() == 2) {
+                            new T7093325(ca, stmt0, stmt1, stmt2).compileAndCheck();
+                            continue;
+                        }
+                        for (StatementKind stmt3 : StatementKind.values()) {
+                            if (ca.ordinal() == 3) {
+                                new T7093325(ca, stmt0, stmt1, stmt2, stmt3).compileAndCheck();
+                                continue;
+                            }
+                            for (StatementKind stmt4 : StatementKind.values()) {
+                                if (ca.ordinal() == 4) {
+                                    new T7093325(ca, stmt0, stmt1, stmt2, stmt3, stmt4).compileAndCheck();
+                                    continue;
+                                }
+                                for (StatementKind stmt5 : StatementKind.values()) {
+                                    new T7093325(ca, stmt0, stmt1, stmt2, stmt3, stmt4, stmt5).compileAndCheck();
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+
+        System.out.println("Total checks made: " + checkCount);
+    }
+
+    /** instance decls **/
+
+    CatchArity ca;
+    StatementKind[] stmts;
+
+    public T7093325(CatchArity ca, StatementKind... stmts) {
+        this.ca = ca;
+        this.stmts = stmts;
+    }
+
+    void compileAndCheck() throws Exception {
+        final JavaCompiler tool = ToolProvider.getSystemJavaCompiler();
+        JavaSource source = new JavaSource();
+        JavacTask ct = (JavacTask)tool.getTask(null, fm, null,
+                null, null, Arrays.asList(source));
+        ct.call();
+        verifyBytecode(source);
+    }
+
+    void verifyBytecode(JavaSource source) {
+        checkCount++;
+        boolean lastInlined = false;
+        boolean hasCode = false;
+        int gapsCount = 0;
+        for (int i = 0; i < stmts.length ; i++) {
+            lastInlined = stmts[i].canInline;
+            hasCode = hasCode || !stmts[i].empty;
+            if (lastInlined && hasCode) {
+                hasCode = false;
+                gapsCount++;
+            }
+        }
+        if (!lastInlined) {
+            gapsCount++;
+        }
+
+        //System.out.printf("gaps %d \n %s \n", gapsCount, source.toString());
+
+        File compiledTest = new File("Test.class");
+        try {
+            ClassFile cf = ClassFile.read(compiledTest);
+            if (cf == null) {
+                throw new Error("Classfile not found: " + compiledTest.getName());
+            }
+
+            Method test_method = null;
+            for (Method m : cf.methods) {
+                if (m.getName(cf.constant_pool).equals("test")) {
+                    test_method = m;
+                    break;
+                }
+            }
+
+            if (test_method == null) {
+                throw new Error("Method test() not found in class Test");
+            }
+
+            Code_attribute code = null;
+            for (Attribute a : test_method.attributes) {
+                if (a.getName(cf.constant_pool).equals(Attribute.Code)) {
+                    code = (Code_attribute)a;
+                    break;
+                }
+            }
+
+            if (code == null) {
+                throw new Error("Code attribute not found in method test()");
+            }
+
+            int actualGapsCount = 0;
+            for (int i = 0; i < code.exception_table_langth ; i++) {
+                int catchType = code.exception_table[i].catch_type;
+                if (catchType == 0) { //any
+                    actualGapsCount++;
+                }
+            }
+
+            if (actualGapsCount != gapsCount) {
+                throw new Error("Bad exception table for test()\n" +
+                            "expected gaps: " + gapsCount + "\n" +
+                            "found gaps: " + actualGapsCount + "\n" +
+                            source);
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+            throw new Error("error reading " + compiledTest +": " + e);
+        }
+
+    }
+
+    class JavaSource extends SimpleJavaFileObject {
+
+        static final String source_template =
+                "class A extends RuntimeException {} \n" +
+                "class B extends RuntimeException {} \n" +
+                "class C extends RuntimeException {} \n" +
+                "class D extends RuntimeException {} \n" +
+                "class E extends RuntimeException {} \n" +
+                "class Test {\n" +
+                "   void test() {\n" +
+                "   try { #S0 } #C finally { System.out.println(); }\n" +
+                "   }\n" +
+                "}";
+
+        String source;
+
+        public JavaSource() {
+            super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE);
+            source = source_template.replace("#C", ca.catchers());
+            source = source.replace("#S0", stmts[0].stmt);
+            for (int i = 1; i < ca.ordinal() + 1; i++) {
+                source = source.replace("#S" + i, stmts[i].stmt);
+            }
+        }
+
+        @Override
+        public String toString() {
+            return source;
+        }
+
+        @Override
+        public CharSequence getCharContent(boolean ignoreEncodingErrors) {
+            return source;
+        }
+    }
+}
--- a/langtools/test/tools/javac/api/TestJavacTaskScanner.java	Wed Jul 05 17:53:51 2017 +0200
+++ b/langtools/test/tools/javac/api/TestJavacTaskScanner.java	Wed Jul 05 17:54:24 2017 +0200
@@ -32,6 +32,7 @@
 
 import com.sun.tools.javac.api.JavacTaskImpl;
 import com.sun.tools.javac.parser.*;
+import com.sun.tools.javac.parser.Tokens.Token;
 import com.sun.tools.javac.util.*;
 import java.io.*;
 import java.net.*;
@@ -93,7 +94,7 @@
 
         check(numTokens, "#Tokens", 1222);
         check(numParseTypeElements, "#parseTypeElements", 136);
-        check(numAllMembers, "#allMembers", 67);
+        check(numAllMembers, "#allMembers", 52);
     }
 
     void check(int value, String name, int expected) {
@@ -206,7 +207,8 @@
 
     public void nextToken() {
         super.nextToken();
-        System.err.format("Saw token %s (%s)%n", token(), name());
+        Token tk = token();
+        System.err.format("Saw token %s %n", tk.kind);
         test.numTokens++;
     }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/depDocComment/DeprecatedDocComment3.java	Wed Jul 05 17:54:24 2017 +0200
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * 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 7096014
+ * @summary Javac tokens should retain state
+ * @compile -Xlint -Werror DeprecatedDocComment3.java
+ */
+
+class DeprecatedDocComment3 {
+    static class Foo { }
+
+    ; /** @deprecated */ ;
+
+    static class A {}
+
+    static class B {
+       A a; //not deprecated!
+    }
+}
--- a/langtools/test/tools/javac/diags/ArgTypeCompilerFactory.java	Wed Jul 05 17:53:51 2017 +0200
+++ b/langtools/test/tools/javac/diags/ArgTypeCompilerFactory.java	Wed Jul 05 17:54:24 2017 +0200
@@ -35,7 +35,7 @@
 import com.sun.tools.javac.file.*;
 import com.sun.tools.javac.main.Main;
 import com.sun.tools.javac.main.JavaCompiler;
-import com.sun.tools.javac.parser.Token;
+import com.sun.tools.javac.parser.Tokens.TokenKind;
 import com.sun.tools.javac.util.*;
 import com.sun.tools.javac.util.AbstractDiagnosticFormatter.SimpleConfiguration;
 import javax.lang.model.SourceVersion;
@@ -319,7 +319,7 @@
             return "modifier";
         if (o instanceof KindName)
             return "symbol kind";
-        if (o instanceof Token)
+        if (o instanceof TokenKind)
             return "token";
         if (o instanceof Symbol)
             return "symbol";
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/ApplicableMethodFound.java	Wed Jul 05 17:54:24 2017 +0200
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * 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.misc.applicable.method.found
+// key: compiler.note.verbose.resolve.multi
+// options: -XDverboseResolution=applicable,success
+
+class ApplicableMethodFound {
+
+    void m() {}
+
+    { m(); }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/ApplicableMethodFound1.java	Wed Jul 05 17:54:24 2017 +0200
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * 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.misc.applicable.method.found.1
+// key: compiler.note.verbose.resolve.multi
+// key: compiler.misc.full.inst.sig
+// options: -XDverboseResolution=applicable,success
+
+class ApplicableMethodFound1 {
+
+    <X> void m(X x) {}
+
+    { m(1); }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/DeferredMethodInst.java	Wed Jul 05 17:54:24 2017 +0200
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * 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.misc.applicable.method.found.1
+// key: compiler.note.verbose.resolve.multi
+// key: compiler.note.deferred.method.inst
+// key: compiler.misc.partial.inst.sig
+// options: -XDverboseResolution=applicable,success,deferred-inference
+
+class DeferredMethodInst {
+
+    <X> X m() { return null; }
+
+    { Integer i = m(); }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/FullInstSig.java	Wed Jul 05 17:54:24 2017 +0200
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * 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.misc.applicable.method.found.1
+// key: compiler.note.verbose.resolve.multi
+// key: compiler.misc.full.inst.sig
+// options: -XDverboseResolution=applicable,success
+
+class FullInstSig {
+
+    <X> void m(X x) {}
+
+    { m(1); }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/NotApplicableMethodFound.java	Wed Jul 05 17:54:24 2017 +0200
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * 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.misc.not.applicable.method.found
+// key: compiler.note.verbose.resolve.multi.1
+// key: compiler.err.cant.apply.symbol.1
+// key: compiler.misc.no.conforming.assignment.exists
+// options: -XDverboseResolution=inapplicable,failure
+
+class NotApplicableMethodFound {
+
+    void m(int i) {}
+
+    { m(""); }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/PartialInstSig.java	Wed Jul 05 17:54:24 2017 +0200
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * 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.misc.applicable.method.found.1
+// key: compiler.note.verbose.resolve.multi
+// key: compiler.misc.partial.inst.sig
+// options: -XDverboseResolution=applicable,success
+
+class PartialInstSig {
+
+    <X> X m() { return null; }
+
+    { m(); }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/VerboseResolveMulti.java	Wed Jul 05 17:54:24 2017 +0200
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * 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.misc.applicable.method.found
+// key: compiler.note.verbose.resolve.multi
+// options: -XDverboseResolution=applicable,success
+
+class VerboseResolveMulti {
+
+    void m() {}
+
+    { m(); }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/VerboseResolveMulti1.java	Wed Jul 05 17:54:24 2017 +0200
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * 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.misc.not.applicable.method.found
+// key: compiler.note.verbose.resolve.multi.1
+// key: compiler.err.cant.apply.symbol.1
+// key: compiler.misc.no.conforming.assignment.exists
+// options: -XDverboseResolution=inapplicable,failure
+
+class VerboseResolveMulti1 {
+
+    void m(int i) {}
+
+    { m(""); }
+}
--- a/langtools/test/tools/javac/javazip/Test.sh	Wed Jul 05 17:53:51 2017 +0200
+++ b/langtools/test/tools/javac/javazip/Test.sh	Wed Jul 05 17:54:24 2017 +0200
@@ -47,7 +47,7 @@
     ;;
   CYGWIN* )
     FS="/"
-    SCR=`pwd | cygpath -d`
+    SCR=`pwd | cygpath -d -f -`
     ;;
   Windows* )
     FS="\\"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/resolve/Candidate.java	Wed Jul 05 17:54:24 2017 +0200
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * 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.ElementType;
+import java.lang.annotation.Target;
+
+@Target({ElementType.METHOD, ElementType.CONSTRUCTOR})
+@interface Candidate {
+    /**
+     * the candidate position (line/col of the method call for which this candidate
+     * is a potential overload candidate)
+     */
+    Pos pos() default @Pos(userDefined=false);
+    /**
+     * resolution phases for which this candidate is applicable
+     */
+    Phase[] applicable() default { };
+    /**
+     * is this candidate the most specific (in the resolution phases for which it
+     * is also applicable)
+     */
+    boolean mostSpecific() default false;
+    /**
+     * this candidate inferred signature (in the resolution phases for which it
+     * is also applicable, in case it corresponds to a generic method)
+     */
+    String sig() default "";
+}
+
+enum Phase {
+    BASIC("BASIC"),
+    BOX("BOX"),
+    VARARGS("VARARITY");
+
+    final String javacString;
+
+    private Phase(String javacString) {
+        this.javacString = javacString;
+    }
+
+    static Phase fromString(String s) {
+        for (Phase phase : Phase.values()) {
+            if (phase.javacString.equals(s)) {
+                return phase;
+            }
+        }
+        throw new AssertionError("Invalid resolution phase string " + s);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/resolve/Pos.java	Wed Jul 05 17:54:24 2017 +0200
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * 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.ElementType;
+import java.lang.annotation.Target;
+
+@Target(ElementType.ANNOTATION_TYPE)
+@interface Pos {
+    long line() default -1;
+    long col() default -1;
+    boolean userDefined() default true;
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/resolve/ResolveHarness.java	Wed Jul 05 17:54:24 2017 +0200
@@ -0,0 +1,475 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * 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 7098660
+ * @summary Write better overload resolution/inference tests
+ * @library ../lib
+ * @build JavacTestingAbstractProcessor ResolveHarness
+ * @run main ResolveHarness
+ */
+
+import com.sun.source.util.JavacTask;
+import com.sun.tools.javac.api.ClientCodeWrapper.DiagnosticSourceUnwrapper;
+import com.sun.tools.javac.code.Type.MethodType;
+import com.sun.tools.javac.util.JCDiagnostic;
+
+import java.io.File;
+import java.util.Set;
+import java.util.Arrays;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+
+import javax.annotation.processing.AbstractProcessor;
+import javax.annotation.processing.RoundEnvironment;
+import javax.annotation.processing.SupportedAnnotationTypes;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.TypeElement;
+import javax.tools.Diagnostic;
+import javax.tools.Diagnostic.Kind;
+import javax.tools.DiagnosticListener;
+import javax.tools.JavaCompiler;
+import javax.tools.JavaFileObject;
+import javax.tools.StandardJavaFileManager;
+import javax.tools.ToolProvider;
+
+import static javax.tools.StandardLocation.*;
+
+public class ResolveHarness implements javax.tools.DiagnosticListener<JavaFileObject> {
+
+    static int nerrors = 0;
+
+    static final JavaCompiler comp = ToolProvider.getSystemJavaCompiler();
+    static final StandardJavaFileManager fm = comp.getStandardFileManager(null, null, null);
+
+    public static void main(String[] args) throws Exception {
+        fm.setLocation(SOURCE_PATH,
+                Arrays.asList(new File(System.getProperty("test.src"), "tests")));
+        for (JavaFileObject jfo : fm.list(SOURCE_PATH, "", Collections.singleton(JavaFileObject.Kind.SOURCE), true)) {
+            new ResolveHarness(jfo).check();
+        }
+        if (nerrors > 0) {
+            throw new AssertionError("Errors were found");
+        }
+    }
+
+
+    JavaFileObject jfo;
+    DiagnosticProcessor[] diagProcessors;
+    Map<ElementKey, Candidate> candidatesMap = new HashMap<ElementKey, Candidate>();
+    Set<String> declaredKeys = new HashSet<>();
+    List<Diagnostic<? extends JavaFileObject>> diags = new ArrayList<>();
+    List<ElementKey> seenCandidates = new ArrayList<>();
+
+    protected ResolveHarness(JavaFileObject jfo) {
+        this.jfo = jfo;
+        this.diagProcessors = new DiagnosticProcessor[] {
+            new VerboseResolutionNoteProcessor(),
+            new VerboseDeferredInferenceNoteProcessor(),
+            new ErrorProcessor()
+        };
+    }
+
+    protected void check() throws Exception {
+        String[] options = {
+            "-XDshouldStopPolicy=ATTR",
+            "-XDverboseResolution=success,failure,applicable,inapplicable,deferred-inference"
+        };
+
+        AbstractProcessor[] processors = { new ResolveCandidateFinder(), null };
+
+        @SuppressWarnings("unchecked")
+        DiagnosticListener<? super JavaFileObject>[] diagListeners =
+                new DiagnosticListener[] { new DiagnosticHandler(false), new DiagnosticHandler(true) };
+
+        for (int i = 0 ; i < options.length ; i ++) {
+            JavacTask ct = (JavacTask)comp.getTask(null, fm, diagListeners[i],
+                    Arrays.asList(options[i]), null, Arrays.asList(jfo));
+            if (processors[i] != null) {
+                ct.setProcessors(Collections.singleton(processors[i]));
+            }
+            ct.analyze();
+        }
+
+        //check diags
+        for (Diagnostic<? extends JavaFileObject> diag : diags) {
+            for (DiagnosticProcessor proc : diagProcessors) {
+                if (proc.matches(diag)) {
+                    proc.process(diag);
+                    break;
+                }
+            }
+        }
+        //check all candidates have been used up
+        for (Map.Entry<ElementKey, Candidate> entry : candidatesMap.entrySet()) {
+            if (!seenCandidates.contains(entry.getKey())) {
+                error("Redundant @Candidate annotation on method " + entry.getKey().elem);
+            }
+        }
+    }
+
+    public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
+        diags.add(diagnostic);
+    }
+
+    Candidate getCandidateAtPos(Element methodSym, long line, long col) {
+        Candidate c = candidatesMap.get(new ElementKey(methodSym));
+        if (c != null) {
+            Pos pos = c.pos();
+            if (!pos.userDefined() ||
+                    (pos.line() == line && pos.col() == col)) {
+                seenCandidates.add(new ElementKey(methodSym));
+                return c;
+            }
+        } else {
+            error("Missing @Candidate annotation on method " + methodSym);
+        }
+        return null;
+    }
+
+    void checkSig(Candidate c, Element methodSym, MethodType mtype) {
+        if (c.sig().length() > 0 && !c.sig().equals(mtype.toString())) {
+            error("Inferred type mismatch for method: " + methodSym);
+        }
+    }
+
+    protected void error(String msg) {
+        nerrors++;
+        System.err.printf("Error occurred while checking file: %s\nreason: %s\n", jfo.getName(), msg);
+    }
+
+    /**
+     * Base class for diagnostic processor. It provides methods for matching and
+     * processing a given diagnostic object (overridden by subclasses).
+     */
+    abstract class DiagnosticProcessor {
+
+        List<String> codes;
+        Diagnostic.Kind kind;
+
+        public DiagnosticProcessor(Kind kind, String... codes) {
+            this.codes = Arrays.asList(codes);
+            this.kind = kind;
+        }
+
+        abstract void process(Diagnostic<? extends JavaFileObject> diagnostic);
+
+        boolean matches(Diagnostic<? extends JavaFileObject> diagnostic) {
+            return (codes.isEmpty() || codes.contains(diagnostic.getCode())) &&
+                    diagnostic.getKind() == kind;
+        }
+
+        JCDiagnostic asJCDiagnostic(Diagnostic<? extends JavaFileObject> diagnostic) {
+            if (diagnostic instanceof JCDiagnostic) {
+                return (JCDiagnostic)diagnostic;
+            } else if (diagnostic instanceof DiagnosticSourceUnwrapper) {
+                return ((DiagnosticSourceUnwrapper)diagnostic).d;
+            } else {
+                throw new AssertionError("Cannot convert diagnostic to JCDiagnostic: " + diagnostic.getClass().getName());
+            }
+        }
+
+        List<JCDiagnostic> subDiagnostics(Diagnostic<? extends JavaFileObject> diagnostic) {
+            JCDiagnostic diag = asJCDiagnostic(diagnostic);
+            if (diag instanceof JCDiagnostic.MultilineDiagnostic) {
+                return ((JCDiagnostic.MultilineDiagnostic)diag).getSubdiagnostics();
+            } else {
+                throw new AssertionError("Cannot extract subdiagnostics: " + diag.getClass().getName());
+            }
+        }
+    }
+
+    /**
+     * Processor for verbose resolution notes generated by javac. The processor
+     * checks that the diagnostic is associated with a method declared by
+     * a class annotated with the special @TraceResolve marker annotation. If
+     * that's the case, all subdiagnostics (one for each resolution candidate)
+     * are checked against the corresponding @Candidate annotations, using
+     * a VerboseCandidateSubdiagProcessor.
+     */
+    class VerboseResolutionNoteProcessor extends DiagnosticProcessor {
+
+        VerboseResolutionNoteProcessor() {
+            super(Kind.NOTE,
+                    "compiler.note.verbose.resolve.multi",
+                    "compiler.note.verbose.resolve.multi.1");
+        }
+
+        @Override
+        void process(Diagnostic<? extends JavaFileObject> diagnostic) {
+            Element siteSym = getSiteSym(diagnostic);
+            if (siteSym.getAnnotation(TraceResolve.class) == null) {
+                return;
+            }
+            int candidateIdx = 0;
+            for (JCDiagnostic d : subDiagnostics(diagnostic)) {
+                boolean isMostSpecific = candidateIdx++ == mostSpecific(diagnostic);
+                VerboseCandidateSubdiagProcessor subProc =
+                        new VerboseCandidateSubdiagProcessor(isMostSpecific, phase(diagnostic), success(diagnostic));
+                if (subProc.matches(d)) {
+                    subProc.process(d);
+                } else {
+                    throw new AssertionError("Bad subdiagnostic: " + d.getCode());
+                }
+            }
+        }
+
+        Element getSiteSym(Diagnostic<? extends JavaFileObject> diagnostic) {
+            return (Element)asJCDiagnostic(diagnostic).getArgs()[1];
+        }
+
+        int mostSpecific(Diagnostic<? extends JavaFileObject> diagnostic) {
+            return success(diagnostic) ?
+                    (Integer)asJCDiagnostic(diagnostic).getArgs()[2] : -1;
+        }
+
+        boolean success(Diagnostic<? extends JavaFileObject> diagnostic) {
+            return diagnostic.getCode().equals("compiler.note.verbose.resolve.multi");
+        }
+
+        Phase phase(Diagnostic<? extends JavaFileObject> diagnostic) {
+            return Phase.fromString(asJCDiagnostic(diagnostic).getArgs()[3].toString());
+        }
+    }
+
+    /**
+     * Processor for verbose resolution subdiagnostic notes generated by javac.
+     * The processor checks that the details of the overload candidate
+     * match against the info contained in the corresponding @Candidate
+     * annotation (if any).
+     */
+    class VerboseCandidateSubdiagProcessor extends DiagnosticProcessor {
+
+        boolean mostSpecific;
+        Phase phase;
+        boolean success;
+
+        public VerboseCandidateSubdiagProcessor(boolean mostSpecific, Phase phase, boolean success) {
+            super(Kind.OTHER,
+                    "compiler.misc.applicable.method.found",
+                    "compiler.misc.applicable.method.found.1",
+                    "compiler.misc.not.applicable.method.found");
+            this.mostSpecific = mostSpecific;
+            this.phase = phase;
+            this.success = success;
+        }
+
+        @Override
+        void process(Diagnostic<? extends JavaFileObject> diagnostic) {
+            Element methodSym = methodSym(diagnostic);
+            Candidate c = getCandidateAtPos(methodSym,
+                    asJCDiagnostic(diagnostic).getLineNumber(),
+                    asJCDiagnostic(diagnostic).getColumnNumber());
+            if (c == null) {
+                return; //nothing to check
+            }
+
+            if (c.applicable().length == 0 && c.mostSpecific()) {
+                error("Inapplicable method cannot be most specific " + methodSym);
+            }
+
+            if (isApplicable(diagnostic) != Arrays.asList(c.applicable()).contains(phase)) {
+                error("Invalid candidate's applicability " + methodSym);
+            }
+
+            if (success) {
+                for (Phase p : c.applicable()) {
+                    if (phase.ordinal() < p.ordinal()) {
+                        error("Invalid phase " + p + " on method " + methodSym);
+                    }
+                }
+            }
+
+            if (Arrays.asList(c.applicable()).contains(phase)) { //applicable
+                if (c.mostSpecific() != mostSpecific) {
+                    error("Invalid most specific value for method " + methodSym);
+                }
+                MethodType mtype = getSig(diagnostic);
+                if (mtype != null) {
+                    checkSig(c, methodSym, mtype);
+                }
+            }
+        }
+
+        boolean isApplicable(Diagnostic<? extends JavaFileObject> diagnostic) {
+            return !diagnostic.getCode().equals("compiler.misc.not.applicable.method.found");
+        }
+
+        Element methodSym(Diagnostic<? extends JavaFileObject> diagnostic) {
+            return (Element)asJCDiagnostic(diagnostic).getArgs()[1];
+        }
+
+        MethodType getSig(Diagnostic<? extends JavaFileObject> diagnostic) {
+            JCDiagnostic details = (JCDiagnostic)asJCDiagnostic(diagnostic).getArgs()[2];
+            if (details == null) {
+                return null;
+            } else if (details instanceof JCDiagnostic) {
+                return details.getCode().equals("compiler.misc.full.inst.sig") ?
+                        (MethodType)details.getArgs()[0] : null;
+            } else {
+                throw new AssertionError("Bad diagnostic arg: " + details);
+            }
+        }
+    }
+
+    /**
+     * Processor for verbose deferred inference notes generated by javac. The
+     * processor checks that the inferred signature for a given generic method
+     * call corresponds to the one (if any) declared in the @Candidate annotation.
+     */
+    class VerboseDeferredInferenceNoteProcessor extends DiagnosticProcessor {
+
+        public VerboseDeferredInferenceNoteProcessor() {
+            super(Kind.NOTE, "compiler.note.deferred.method.inst");
+        }
+
+        @Override
+        void process(Diagnostic<? extends JavaFileObject> diagnostic) {
+            Element methodSym = methodSym(diagnostic);
+            Candidate c = getCandidateAtPos(methodSym,
+                    asJCDiagnostic(diagnostic).getLineNumber(),
+                    asJCDiagnostic(diagnostic).getColumnNumber());
+            MethodType sig = sig(diagnostic);
+            if (c != null && sig != null) {
+                checkSig(c, methodSym, sig);
+            }
+        }
+
+        Element methodSym(Diagnostic<? extends JavaFileObject> diagnostic) {
+            return (Element)asJCDiagnostic(diagnostic).getArgs()[0];
+        }
+
+        MethodType sig(Diagnostic<? extends JavaFileObject> diagnostic) {
+            return (MethodType)asJCDiagnostic(diagnostic).getArgs()[1];
+        }
+    }
+
+    /**
+     * Processor for all error diagnostics; if the error key is not declared in
+     * the test file header, the processor reports an error.
+     */
+    class ErrorProcessor extends DiagnosticProcessor {
+
+        public ErrorProcessor() {
+            super(Diagnostic.Kind.ERROR);
+        }
+
+        @Override
+        void process(Diagnostic<? extends JavaFileObject> diagnostic) {
+            if (!declaredKeys.contains(diagnostic.getCode())) {
+                error("Unexpected compilation error key '" + diagnostic.getCode() + "'");
+            }
+        }
+    }
+
+    @SupportedAnnotationTypes({"Candidate","TraceResolve"})
+    class ResolveCandidateFinder extends JavacTestingAbstractProcessor {
+
+        @Override
+        public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
+            if (roundEnv.processingOver())
+                return true;
+
+            TypeElement traceResolveAnno = elements.getTypeElement("TraceResolve");
+            TypeElement candidateAnno = elements.getTypeElement("Candidate");
+
+            if (!annotations.contains(traceResolveAnno)) {
+                error("no @TraceResolve annotation found in test class");
+            }
+
+            if (!annotations.contains(candidateAnno)) {
+                error("no @candidate annotation found in test class");
+            }
+
+            for (Element elem: roundEnv.getElementsAnnotatedWith(traceResolveAnno)) {
+                TraceResolve traceResolve = elem.getAnnotation(TraceResolve.class);
+                declaredKeys.addAll(Arrays.asList(traceResolve.keys()));
+            }
+
+            for (Element elem: roundEnv.getElementsAnnotatedWith(candidateAnno)) {
+                candidatesMap.put(new ElementKey(elem), elem.getAnnotation(Candidate.class));
+            }
+            return true;
+        }
+    }
+
+    class ElementKey {
+
+        String key;
+        Element elem;
+
+        public ElementKey(Element elem) {
+            this.elem = elem;
+            this.key = computeKey(elem);
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (obj instanceof ElementKey) {
+                ElementKey other = (ElementKey)obj;
+                return other.key.equals(key);
+            }
+            return false;
+        }
+
+        @Override
+        public int hashCode() {
+            return key.hashCode();
+        }
+
+        String computeKey(Element e) {
+            StringBuilder buf = new StringBuilder();
+            while (e != null) {
+                buf.append(e.toString());
+                e = e.getEnclosingElement();
+            }
+            buf.append(jfo.getName());
+            return buf.toString();
+        }
+
+        @Override
+        public String toString() {
+            return "Key{"+key+"}";
+        }
+    }
+
+    class DiagnosticHandler implements DiagnosticListener<JavaFileObject> {
+
+        boolean shouldRecordDiags;
+
+        DiagnosticHandler(boolean shouldRecordDiags) {
+            this.shouldRecordDiags = shouldRecordDiags;
+        }
+
+        public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
+            if (shouldRecordDiags)
+                diags.add(diagnostic);
+        }
+
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/resolve/TraceResolve.java	Wed Jul 05 17:54:24 2017 +0200
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * 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.ElementType;
+import java.lang.annotation.Target;
+
+@Target(ElementType.TYPE)
+@interface TraceResolve {
+    String[] keys() default {};
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/resolve/tests/BoxedReturnTypeInference.java	Wed Jul 05 17:54:24 2017 +0200
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * 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.
+ */
+
+@TraceResolve
+class BoxedReturnTypeInference {
+    @Candidate(applicable=Phase.BASIC, sig="()java.lang.Byte", mostSpecific=true)
+    static <B> B m_byte() { return null; }
+
+    @Candidate(applicable=Phase.BASIC, sig="()java.lang.Short", mostSpecific=true)
+    static <S> S m_short() { return null; }
+
+    @Candidate(applicable=Phase.BASIC, sig="()java.lang.Integer", mostSpecific=true)
+    static <I> I m_int() { return null; }
+
+    @Candidate(applicable=Phase.BASIC, sig="()java.lang.Long", mostSpecific=true)
+    static <L> L m_long() { return null; }
+
+    @Candidate(applicable=Phase.BASIC, sig="()java.lang.Float", mostSpecific=true)
+    static <F> F m_float() { return null; }
+
+    @Candidate(applicable=Phase.BASIC, sig="()java.lang.Double", mostSpecific=true)
+    static <D> D m_double() { return null; }
+
+    @Candidate(applicable=Phase.BASIC, sig="()java.lang.Character", mostSpecific=true)
+    static <C> C m_char() { return null; }
+
+    @Candidate(applicable=Phase.BASIC, sig="()java.lang.Boolean", mostSpecific=true)
+    static <Z> Z m_bool() { return null; }
+
+    {
+        Byte b = m_byte();
+        Short s = m_short();
+        Integer i = m_int();
+        Long l = m_long();
+        Float f = m_float();
+        Double d = m_double();
+        Character c= m_char();
+        Boolean z = m_bool();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/resolve/tests/PrimitiveOverReferenceOverInferred.java	Wed Jul 05 17:54:24 2017 +0200
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * 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.
+ */
+
+@TraceResolve
+class PrimitiveOverReference {
+    @Candidate(applicable=Phase.BASIC, mostSpecific=true)
+    static void m_byte(byte b) {}
+    @Candidate
+    static void m_byte(Byte b) {}
+    @Candidate
+    static <B> void m_byte(B b) {}
+
+    @Candidate(applicable=Phase.BASIC, mostSpecific=true)
+    static void m_short(short s) {}
+    @Candidate
+    static void m_short(Short s) {}
+    @Candidate
+    static <S> void m_short(S s) {}
+
+    @Candidate(applicable=Phase.BASIC, mostSpecific=true)
+    static void m_int(int i) {}
+    @Candidate
+    static void m_int(Integer i) {}
+    @Candidate
+    static <I> void m_int(I i) {}
+
+    @Candidate(applicable=Phase.BASIC, mostSpecific=true)
+    static void m_long(long l) {}
+    @Candidate
+    static void m_long(Long l) {}
+    @Candidate
+    static <L> void m_long(L l) {}
+
+    @Candidate(applicable=Phase.BASIC, mostSpecific=true)
+    static void m_float(float f) {}
+    @Candidate
+    static void m_float(Float f) {}
+    @Candidate
+    static <F> void m_float(F f) {}
+
+    @Candidate(applicable=Phase.BASIC, mostSpecific=true)
+    static void m_double(double d) {}
+    @Candidate
+    static void m_double(Double d) {}
+    @Candidate
+    static <D> void m_double(D d) {}
+
+    @Candidate(applicable=Phase.BASIC, mostSpecific=true)
+    static void m_char(char c) {}
+    @Candidate
+    static void m_char(Character c) {}
+    @Candidate
+    static <C> void m_char(C c) {}
+
+    @Candidate(applicable=Phase.BASIC, mostSpecific=true)
+    static void m_bool(boolean z) {}
+    @Candidate
+    static void m_bool(Boolean z) {}
+    @Candidate
+    static <Z> void m_bool(Z z) {}
+
+    {
+        m_byte((byte)0);
+        m_short((short)0);
+        m_int(0);
+        m_long(0L);
+        m_float(0.0f);
+        m_double(0.0);
+        m_char('?');
+        m_bool(false);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/resolve/tests/PrimitiveOverReferenceOverVarargs.java	Wed Jul 05 17:54:24 2017 +0200
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * 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.
+ */
+
+@TraceResolve
+class PrimitiveOverReference {
+    @Candidate(applicable=Phase.BASIC, mostSpecific=true)
+    static void m_byte(byte b) {}
+    @Candidate
+    static void m_byte(Byte b) {}
+    @Candidate
+    static void m_byte(byte... b) {}
+    @Candidate
+    static void m_byte(Byte... b) {}
+
+    @Candidate(applicable=Phase.BASIC, mostSpecific=true)
+    static void m_short(short s) {}
+    @Candidate
+    static void m_short(Short s) {}
+    @Candidate
+    static void m_short(short... s) {}
+    @Candidate
+    static void m_short(Short... s) {}
+
+    @Candidate(applicable=Phase.BASIC, mostSpecific=true)
+    static void m_int(int i) {}
+    @Candidate
+    static void m_int(Integer i) {}
+    @Candidate
+    static void m_int(int... i) {}
+    @Candidate
+    static void m_int(Integer... i) {}
+
+    @Candidate(applicable=Phase.BASIC, mostSpecific=true)
+    static void m_long(long l) {}
+    @Candidate
+    static void m_long(Long l) {}
+    @Candidate
+    static void m_long(long... l) {}
+    @Candidate
+    static void m_long(Long... l) {}
+
+    @Candidate(applicable=Phase.BASIC, mostSpecific=true)
+    static void m_float(float f) {}
+    @Candidate
+    static void m_float(Float f) {}
+    @Candidate
+    static void m_float(float... f) {}
+    @Candidate
+    static void m_float(Float... f) {}
+
+    @Candidate(applicable=Phase.BASIC, mostSpecific=true)
+    static void m_double(double d) {}
+    @Candidate
+    static void m_double(Double d) {}
+    @Candidate
+    static void m_double(double... d) {}
+    @Candidate
+    static void m_double(Double... d) {}
+
+    @Candidate(applicable=Phase.BASIC, mostSpecific=true)
+    static void m_char(char c) {}
+    @Candidate
+    static void m_char(Character c) {}
+    @Candidate
+    static void m_char(char... c) {}
+    @Candidate
+    static void m_char(Character... c) {}
+
+    @Candidate(applicable=Phase.BASIC, mostSpecific=true)
+    static void m_bool(boolean z) {}
+    @Candidate
+    static void m_bool(Boolean z) {}
+    @Candidate
+    static void m_bool(boolean... z) {}
+    @Candidate
+    static void m_bool(Boolean... z) {}
+
+    {
+        m_byte((byte)0);
+        m_short((short)0);
+        m_int(0);
+        m_long(0L);
+        m_float(0.0f);
+        m_double(0.0);
+        m_char('?');
+        m_bool(false);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/resolve/tests/PrimitiveOverReferenceVarargsAmbiguous.java	Wed Jul 05 17:54:24 2017 +0200
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * 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.
+ */
+
+@TraceResolve(keys={"compiler.err.ref.ambiguous"})
+class PrimitiveOverReferenceVarargsAmbiguous {
+    @Candidate(applicable=Phase.VARARGS, mostSpecific=false)
+    static void m_byte(byte... b) {}
+    @Candidate(applicable=Phase.VARARGS, mostSpecific=false)
+    static void m_byte(Byte... b) {}
+
+    @Candidate(applicable=Phase.VARARGS, mostSpecific=false)
+    static void m_short(short... s) {}
+    @Candidate(applicable=Phase.VARARGS, mostSpecific=false)
+    static void m_short(Short... s) {}
+
+    @Candidate(applicable=Phase.VARARGS, mostSpecific=false)
+    static void m_int(int... i) {}
+    @Candidate(applicable=Phase.VARARGS, mostSpecific=false)
+    static void m_int(Integer... i) {}
+
+    @Candidate(applicable=Phase.VARARGS, mostSpecific=false)
+    static void m_long(long... l) {}
+    @Candidate(applicable=Phase.VARARGS, mostSpecific=false)
+    static void m_long(Long... l) {}
+
+    @Candidate(applicable=Phase.VARARGS, mostSpecific=false)
+    static void m_float(float... f) {}
+    @Candidate(applicable=Phase.VARARGS, mostSpecific=false)
+    static void m_float(Float... f) {}
+
+    @Candidate(applicable=Phase.VARARGS, mostSpecific=false)
+    static void m_double(double... d) {}
+    @Candidate(applicable=Phase.VARARGS, mostSpecific=false)
+    static void m_double(Double... d) {}
+
+    @Candidate(applicable=Phase.VARARGS, mostSpecific=false)
+    static void m_char(char... c) {}
+    @Candidate(applicable=Phase.VARARGS, mostSpecific=false)
+    static void m_char(Character... c) {}
+
+    @Candidate(applicable=Phase.VARARGS, mostSpecific=false)
+    static void m_bool(boolean... z) {}
+    @Candidate(applicable=Phase.VARARGS, mostSpecific=false)
+    static void m_bool(Boolean... z) {}
+
+    {
+        m_byte((byte)0);
+        m_short((short)0);
+        m_int(0);
+        m_long(0L);
+        m_float(0.0f);
+        m_double(0.0);
+        m_char('?');
+        m_bool(false);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/resolve/tests/PrimitiveOverload.java	Wed Jul 05 17:54:24 2017 +0200
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * 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.
+ */
+
+@TraceResolve
+class PrimitiveOverload {
+
+    @Candidate(applicable=Phase.BASIC, mostSpecific=true)
+    static void m_byte(byte b) {}
+    @Candidate(applicable=Phase.BASIC, mostSpecific=false)
+    static void m_byte(short b) {}
+    @Candidate(applicable=Phase.BASIC, mostSpecific=false)
+    static void m_byte(int b) {}
+    @Candidate(applicable=Phase.BASIC, mostSpecific=false)
+    static void m_byte(long b) {}
+    @Candidate(applicable=Phase.BASIC, mostSpecific=false)
+    static void m_byte(float b) {}
+    @Candidate(applicable=Phase.BASIC, mostSpecific=false)
+    static void m_byte(double b) {}
+
+    @Candidate
+    static void m_short(byte b) {}
+    @Candidate(applicable=Phase.BASIC, mostSpecific=true)
+    static void m_short(short b) {}
+    @Candidate(applicable=Phase.BASIC, mostSpecific=false)
+    static void m_short(int b) {}
+    @Candidate(applicable=Phase.BASIC, mostSpecific=false)
+    static void m_short(long b) {}
+    @Candidate(applicable=Phase.BASIC, mostSpecific=false)
+    static void m_short(float b) {}
+    @Candidate(applicable=Phase.BASIC, mostSpecific=false)
+    static void m_short(double b) {}
+
+    @Candidate
+    static void m_int(byte b) {}
+    @Candidate
+    static void m_int(short b) {}
+    @Candidate(applicable=Phase.BASIC, mostSpecific=true)
+    static void m_int(int b) {}
+    @Candidate(applicable=Phase.BASIC, mostSpecific=false)
+    static void m_int(long b) {}
+    @Candidate(applicable=Phase.BASIC, mostSpecific=false)
+    static void m_int(float b) {}
+    @Candidate(applicable=Phase.BASIC, mostSpecific=false)
+    static void m_int(double b) {}
+
+    @Candidate
+    static void m_long(byte b) {}
+    @Candidate
+    static void m_long(short b) {}
+    @Candidate
+    static void m_long(int b) {}
+    @Candidate(applicable=Phase.BASIC, mostSpecific=true)
+    static void m_long(long b) {}
+    @Candidate(applicable=Phase.BASIC, mostSpecific=false)
+    static void m_long(float b) {}
+    @Candidate(applicable=Phase.BASIC, mostSpecific=false)
+    static void m_long(double b) {}
+
+    @Candidate
+    static void m_float(byte b) {}
+    @Candidate
+    static void m_float(short b) {}
+    @Candidate
+    static void m_float(int b) {}
+    @Candidate
+    static void m_float(long b) {}
+    @Candidate(applicable=Phase.BASIC, mostSpecific=true)
+    static void m_float(float b) {}
+    @Candidate(applicable=Phase.BASIC, mostSpecific=false)
+    static void m_float(double b) {}
+
+    @Candidate
+    static void m_double(byte b) {}
+    @Candidate
+    static void m_double(short b) {}
+    @Candidate
+    static void m_double(int b) {}
+    @Candidate
+    static void m_double(long b) {}
+    @Candidate
+    static void m_double(float b) {}
+    @Candidate(applicable=Phase.BASIC, mostSpecific=true)
+    static void m_double(double b) {}
+
+    {
+        m_byte((byte)0);
+        m_short((short)0);
+        m_int(0);
+        m_long(0L);
+        m_float(0.0f);
+        m_double(0.0);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/resolve/tests/PrimitiveReturnTypeInference.java	Wed Jul 05 17:54:24 2017 +0200
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * 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.
+ */
+
+@TraceResolve
+class PrimitiveReturnTypeInference {
+    @Candidate(applicable=Phase.BASIC, sig="()java.lang.Byte", mostSpecific=true)
+    static <B> B m_byte() { return null; }
+
+    @Candidate(applicable=Phase.BASIC, sig="()java.lang.Short", mostSpecific=true)
+    static <S> S m_short() { return null; }
+
+    @Candidate(applicable=Phase.BASIC, sig="()java.lang.Integer", mostSpecific=true)
+    static <I> I m_int() { return null; }
+
+    @Candidate(applicable=Phase.BASIC, sig="()java.lang.Long", mostSpecific=true)
+    static <L> L m_long() { return null; }
+
+    @Candidate(applicable=Phase.BASIC, sig="()java.lang.Float", mostSpecific=true)
+    static <F> F m_float() { return null; }
+
+    @Candidate(applicable=Phase.BASIC, sig="()java.lang.Double", mostSpecific=true)
+    static <D> D m_double() { return null; }
+
+    @Candidate(applicable=Phase.BASIC, sig="()java.lang.Character", mostSpecific=true)
+    static <C> C m_char() { return null; }
+
+    @Candidate(applicable=Phase.BASIC, sig="()java.lang.Boolean", mostSpecific=true)
+    static <Z> Z m_bool() { return null; }
+
+    {
+        byte b = m_byte();
+        short s = m_short();
+        int i = m_int();
+        long l = m_long();
+        float f = m_float();
+        double d = m_double();
+        char c= m_char();
+        boolean z = m_bool();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/resolve/tests/ReferenceOverInferred.java	Wed Jul 05 17:54:24 2017 +0200
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * 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.
+ */
+
+@TraceResolve
+class PrimitiveOverInferred {
+    @Candidate(applicable=Phase.BOX, mostSpecific=true)
+    static void m_byte(Byte b) {}
+    @Candidate(applicable=Phase.BOX, sig="(java.lang.Byte)void")
+    static <B> void m_byte(B b) {}
+
+    @Candidate(applicable=Phase.BOX, mostSpecific=true)
+    static void m_short(Short s) {}
+    @Candidate(applicable=Phase.BOX, sig="(java.lang.Short)void")
+    static <S> void m_short(S s) {}
+
+    @Candidate(applicable=Phase.BOX, mostSpecific=true)
+    static void m_int(Integer i) {}
+    @Candidate(applicable=Phase.BOX, sig="(java.lang.Integer)void")
+    static <I> void m_int(I i) {}
+
+    @Candidate(applicable=Phase.BOX, mostSpecific=true)
+    static void m_long(Long l) {}
+    @Candidate(applicable=Phase.BOX, sig="(java.lang.Long)void")
+    static <L> void m_long(L l) {}
+
+    @Candidate(applicable=Phase.BOX, mostSpecific=true)
+    static void m_float(Float f) {}
+    @Candidate(applicable=Phase.BOX, sig="(java.lang.Float)void")
+    static <F> void m_float(F f) {}
+
+    @Candidate(applicable=Phase.BOX, mostSpecific=true)
+    static void m_double(Double d) {}
+    @Candidate(applicable=Phase.BOX, sig="(java.lang.Double)void")
+    static <D> void m_double(D d) {}
+
+    @Candidate(applicable=Phase.BOX, mostSpecific=true)
+    static void m_char(Character c) {}
+    @Candidate(applicable=Phase.BOX, sig="(java.lang.Character)void")
+    static <C> void m_char(C c) {}
+
+    @Candidate(applicable=Phase.BOX, mostSpecific=true)
+    static void m_bool(Boolean z) {}
+    @Candidate(applicable=Phase.BOX, sig="(java.lang.Boolean)void")
+    static <Z> void m_bool(Z z) {}
+
+    {
+        m_byte((byte)0);
+        m_short((short)0);
+        m_int(0);
+        m_long(0L);
+        m_float(0.0f);
+        m_double(0.0);
+        m_char('?');
+        m_bool(false);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/resolve/tests/ReferenceOverVarargs.java	Wed Jul 05 17:54:24 2017 +0200
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * 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.
+ */
+
+@TraceResolve
+class ReferenceOverVarargs {
+
+    @Candidate(applicable=Phase.BOX, mostSpecific=true)
+    static void m_byte(Byte b) {}
+    @Candidate
+    static void m_byte(byte... b) {}
+    @Candidate
+    static void m_byte(Byte... b) {}
+
+    @Candidate(applicable=Phase.BOX, mostSpecific=true)
+    static void m_short(Short s) {}
+    @Candidate
+    static void m_short(short... s) {}
+    @Candidate
+    static void m_short(Short... s) {}
+
+    @Candidate(applicable=Phase.BOX, mostSpecific=true)
+    static void m_int(Integer i) {}
+    @Candidate
+    static void m_int(int... i) {}
+    @Candidate
+    static void m_int(Integer... i) {}
+
+    @Candidate(applicable=Phase.BOX, mostSpecific=true)
+    static void m_long(Long l) {}
+    @Candidate
+    static void m_long(long... l) {}
+    @Candidate
+    static void m_long(Long... l) {}
+
+    @Candidate(applicable=Phase.BOX, mostSpecific=true)
+    static void m_float(Float f) {}
+    @Candidate
+    static void m_float(float... f) {}
+    @Candidate
+    static void m_float(Float... f) {}
+
+    @Candidate(applicable=Phase.BOX, mostSpecific=true)
+    static void m_double(Double d) {}
+    @Candidate
+    static void m_double(double... d) {}
+    @Candidate
+    static void m_double(Double... d) {}
+
+    @Candidate(applicable=Phase.BOX, mostSpecific=true)
+    static void m_char(Character c) {}
+    @Candidate
+    static void m_char(char... c) {}
+    @Candidate
+    static void m_char(Character... c) {}
+
+    @Candidate(applicable=Phase.BOX, mostSpecific=true)
+    static void m_bool(Boolean z) {}
+    @Candidate
+    static void m_bool(boolean... z) {}
+    @Candidate
+    static void m_bool(Boolean... z) {}
+
+    {
+        m_byte((byte)0);
+        m_short((short)0);
+        m_int(0);
+        m_long(0L);
+        m_float(0.0f);
+        m_double(0.0);
+        m_char('?');
+        m_bool(false);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/resolve/tests/ReferenceOverload.java	Wed Jul 05 17:54:24 2017 +0200
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * 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.
+ */
+
+@TraceResolve
+class ReferenceOverload {
+
+    static class A {}
+    static class B extends A {}
+    static class C extends B {}
+    static class D extends C {}
+    static class E extends D {}
+
+    @Candidate(applicable=Phase.BASIC, mostSpecific=true)
+    static void m_A(A a) {}
+    @Candidate
+    static void m_A(B a) {}
+    @Candidate
+    static void m_A(C a) {}
+    @Candidate
+    static void m_A(D a) {}
+    @Candidate
+    static void m_A(E a) {}
+
+    @Candidate(applicable=Phase.BASIC, mostSpecific=false)
+    static void m_B(A b) {}
+    @Candidate(applicable=Phase.BASIC, mostSpecific=true)
+    static void m_B(B b) {}
+    @Candidate
+    static void m_B(C b) {}
+    @Candidate
+    static void m_B(D b) {}
+    @Candidate
+    static void m_B(E b) {}
+
+    @Candidate(applicable=Phase.BASIC, mostSpecific=false)
+    static void m_C(A c) {}
+    @Candidate(applicable=Phase.BASIC, mostSpecific=false)
+    static void m_C(B c) {}
+    @Candidate(applicable=Phase.BASIC, mostSpecific=true)
+    static void m_C(C c) {}
+    @Candidate
+    static void m_C(D c) {}
+    @Candidate
+    static void m_C(E c) {}
+
+    @Candidate(applicable=Phase.BASIC, mostSpecific=false)
+    static void m_D(A d) {}
+    @Candidate(applicable=Phase.BASIC, mostSpecific=false)
+    static void m_D(B d) {}
+    @Candidate(applicable=Phase.BASIC, mostSpecific=false)
+    static void m_D(C d) {}
+    @Candidate(applicable=Phase.BASIC, mostSpecific=true)
+    static void m_D(D d) {}
+    @Candidate
+    static void m_D(E d) {}
+
+    @Candidate(applicable=Phase.BASIC, mostSpecific=false)
+    static void m_E(A e) {}
+    @Candidate(applicable=Phase.BASIC, mostSpecific=false)
+    static void m_E(B e) {}
+    @Candidate(applicable=Phase.BASIC, mostSpecific=false)
+    static void m_E(C e) {}
+    @Candidate(applicable=Phase.BASIC, mostSpecific=false)
+    static void m_E(D e) {}
+    @Candidate(applicable=Phase.BASIC, mostSpecific=true)
+    static void m_E(E e) {}
+
+    {
+        m_A((A)null);
+        m_B((B)null);
+        m_C((C)null);
+        m_D((D)null);
+        m_E((E)null);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/tree/DocCommentToplevelTest.java	Wed Jul 05 17:54:24 2017 +0200
@@ -0,0 +1,196 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * 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 7096014
+ * @summary Javac tokens should retain state
+ */
+
+import com.sun.source.tree.*;
+import com.sun.source.util.*;
+import com.sun.tools.javac.tree.JCTree;
+
+import java.net.URI;
+import java.util.*;
+import javax.tools.*;
+
+
+public class DocCommentToplevelTest {
+
+    enum PackageKind {
+        HAS_PKG("package pkg;"),
+        NO_PKG("");
+
+        String pkgStr;
+
+        PackageKind(String pkgStr) {
+            this.pkgStr = pkgStr;
+        }
+    }
+
+    enum ImportKind {
+        ZERO(""),
+        ONE("import java.lang.*;"),
+        TWO("import java.lang.*; import java.util.*;");
+
+        String importStr;
+
+        ImportKind(String importStr) {
+            this.importStr = importStr;
+        }
+    }
+
+    enum ModifierKind {
+        DEFAULT(""),
+        PUBLIC("public");
+
+        String modStr;
+
+        ModifierKind(String modStr) {
+            this.modStr = modStr;
+        }
+    }
+
+    enum ToplevelDocKind {
+        HAS_DOC("/** Toplevel! */"),
+        NO_DOC("");
+
+        String docStr;
+
+        ToplevelDocKind(String docStr) {
+            this.docStr = docStr;
+        }
+    }
+
+    static int errors;
+    static int checks;
+
+    public static void main(String... args) throws Exception {
+        //create default shared JavaCompiler - reused across multiple compilations
+        JavaCompiler comp = ToolProvider.getSystemJavaCompiler();
+        StandardJavaFileManager fm = comp.getStandardFileManager(null, null, null);
+
+        for (PackageKind pk : PackageKind.values()) {
+            for (ImportKind ik : ImportKind.values()) {
+                for (ModifierKind mk1 : ModifierKind.values()) {
+                    for (ModifierKind mk2 : ModifierKind.values()) {
+                        for (ToplevelDocKind tdk : ToplevelDocKind.values()) {
+                            new DocCommentToplevelTest(pk, ik, mk1, mk2, tdk).run(comp, fm);
+                        }
+                    }
+                }
+            }
+        }
+
+        if (errors > 0)
+            throw new AssertionError(errors + " errors found");
+
+        System.out.println(checks + " checks were made");
+    }
+
+    PackageKind pk;
+    ImportKind ik;
+    ModifierKind mk1;
+    ModifierKind mk2;
+    ToplevelDocKind tdk;
+    JavaSource source;
+
+    DocCommentToplevelTest(PackageKind pk, ImportKind ik, ModifierKind mk1, ModifierKind mk2, ToplevelDocKind tdk) {
+        this.pk = pk;
+        this.ik = ik;
+        this.mk1 = mk1;
+        this.mk2 = mk2;
+        this.tdk = tdk;
+        source = new JavaSource();
+    }
+
+    void run(JavaCompiler comp, JavaFileManager fm) throws Exception {
+        JavacTask task = (JavacTask)comp.getTask(null, fm, null, Arrays.asList("-printsource"), null, Arrays.asList(source));
+        for (CompilationUnitTree cu: task.parse()) {
+            check(cu);
+        }
+    }
+
+    void check(CompilationUnitTree cu) {
+        checks++;
+
+        new TreeScanner<ClassTree,Void>() {
+
+            Map<JCTree, String> docComments;
+
+            @Override
+            public ClassTree visitCompilationUnit(CompilationUnitTree node, Void unused) {
+                docComments = ((JCTree.JCCompilationUnit)node).docComments;
+                boolean expectedComment = tdk == ToplevelDocKind.HAS_DOC &&
+                        (pk != PackageKind.NO_PKG || ik != ImportKind.ZERO);
+                boolean foundComment = docComments.get(node) != null;
+                if (expectedComment != foundComment) {
+                    error("Unexpected comment " + docComments.get(node) + " on toplevel");
+                }
+                return super.visitCompilationUnit(node, null);
+            }
+
+            @Override
+            public ClassTree visitClass(ClassTree node, Void unused) {
+                boolean expectedComment = tdk == ToplevelDocKind.HAS_DOC &&
+                        pk == PackageKind.NO_PKG && ik == ImportKind.ZERO &&
+                        node.getSimpleName().toString().equals("First");
+                boolean foundComment = docComments.get(node) != null;
+                if (expectedComment != foundComment) {
+                    error("Unexpected comment " + docComments.get(node) + " on class " + node.getSimpleName());
+                }
+                return super.visitClass(node, unused);
+            }
+        }.scan(cu, null);
+    }
+
+    void error(String msg) {
+        System.err.println("Error: " + msg);
+        System.err.println("Source: " + source.source);
+        errors++;
+    }
+
+    class JavaSource extends SimpleJavaFileObject {
+
+        String template = "#D\n#P\n#I\n" +
+                          "#M1 class First { }\n" +
+                          "#M2 class Second { }\n";
+
+        String source;
+
+        public JavaSource() {
+            super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE);
+            source = template.replace("#P", pk.pkgStr)
+                             .replace("#I", ik.importStr)
+                             .replace("#M1", mk1.modStr)
+                             .replace("#M2", mk2.modStr)
+                             .replace("#D", tdk.docStr);
+        }
+
+        @Override
+        public CharSequence getCharContent(boolean ignoreEncodingErrors) {
+            return source;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/varargs/7097436/T7097436.java	Wed Jul 05 17:54:24 2017 +0200
@@ -0,0 +1,18 @@
+/*
+ * @test /nodynamiccopyright/
+ * @bug     7097436
+ * @summary  ClassCastException occurs in assignment expressions without any heap pollutions
+ * @compile/fail/ref=T7097436.out -Xlint:varargs -Werror -XDrawDiagnostics T7097436.java
+ */
+
+import java.util.List;
+
+class T7097436 {
+    @SafeVarargs
+    static void m(List<String>... ls) {
+        Object o = ls; //warning
+        Object[] oArr = ls; //warning
+        String s = ls; // no warning
+        Integer[] iArr = ls; // no warning
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/varargs/7097436/T7097436.out	Wed Jul 05 17:54:24 2017 +0200
@@ -0,0 +1,6 @@
+T7097436.java:13:20: compiler.warn.varargs.unsafe.use.varargs.param: ls
+T7097436.java:14:25: compiler.warn.varargs.unsafe.use.varargs.param: ls
+T7097436.java:15:20: compiler.err.prob.found.req: (compiler.misc.incompatible.types), java.util.List<java.lang.String>[], java.lang.String
+T7097436.java:16:26: compiler.err.prob.found.req: (compiler.misc.incompatible.types), java.util.List<java.lang.String>[], java.lang.Integer[]
+2 errors
+2 warnings
--- a/langtools/test/tools/javac/varargs/warning/Warn5.java	Wed Jul 05 17:53:51 2017 +0200
+++ b/langtools/test/tools/javac/varargs/warning/Warn5.java	Wed Jul 05 17:54:24 2017 +0200
@@ -23,7 +23,7 @@
 
 /**
  * @test
- * @bug     6993978
+ * @bug     6993978 7097436
  * @summary Project Coin: Annotation to reduce varargs warnings
  * @author  mcimadamore
  * @run main Warn5
@@ -31,8 +31,8 @@
 import com.sun.source.util.JavacTask;
 import com.sun.tools.javac.api.JavacTool;
 import java.net.URI;
-import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.EnumSet;
 import javax.tools.Diagnostic;
 import javax.tools.JavaCompiler;
 import javax.tools.JavaFileObject;
@@ -95,7 +95,6 @@
         METHOD("void m"),
         CONSTRUCTOR("Test");
 
-
         String name;
 
         MethodKind(String name) {
@@ -155,7 +154,124 @@
         }
     }
 
-    static class JavaSource extends SimpleJavaFileObject {
+    enum WarningKind {
+        UNSAFE_BODY,
+        UNSAFE_DECL,
+        MALFORMED_SAFEVARARGS,
+        REDUNDANT_SAFEVARARGS;
+    }
+
+    // Create a single file manager and reuse it for each compile to save time.
+    static StandardJavaFileManager fm = JavacTool.create().getStandardFileManager(null, null, null);
+
+    public static void main(String... args) throws Exception {
+        for (SourceLevel sourceLevel : SourceLevel.values()) {
+            for (XlintOption xlint : XlintOption.values()) {
+                for (TrustMe trustMe : TrustMe.values()) {
+                    for (SuppressLevel suppressLevel : SuppressLevel.values()) {
+                        for (ModifierKind modKind : ModifierKind.values()) {
+                            for (MethodKind methKind : MethodKind.values()) {
+                                for (SignatureKind sig : SignatureKind.values()) {
+                                    for (BodyKind body : BodyKind.values()) {
+                                        new Warn5(sourceLevel,
+                                                xlint,
+                                                trustMe,
+                                                suppressLevel,
+                                                modKind,
+                                                methKind,
+                                                sig,
+                                                body).test();
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    final SourceLevel sourceLevel;
+    final XlintOption xlint;
+    final TrustMe trustMe;
+    final SuppressLevel suppressLevel;
+    final ModifierKind modKind;
+    final MethodKind methKind;
+    final SignatureKind sig;
+    final BodyKind body;
+    final JavaSource source;
+    final DiagnosticChecker dc;
+
+    public Warn5(SourceLevel sourceLevel, XlintOption xlint, TrustMe trustMe, SuppressLevel suppressLevel, ModifierKind modKind, MethodKind methKind, SignatureKind sig, BodyKind body) {
+        this.sourceLevel = sourceLevel;
+        this.xlint = xlint;
+        this.trustMe = trustMe;
+        this.suppressLevel = suppressLevel;
+        this.modKind = modKind;
+        this.methKind = methKind;
+        this.sig = sig;
+        this.body = body;
+        this.source = new JavaSource();
+        this.dc = new DiagnosticChecker();
+    }
+
+    void test() throws Exception {
+        final JavaCompiler tool = ToolProvider.getSystemJavaCompiler();
+        JavacTask ct = (JavacTask)tool.getTask(null, fm, dc,
+                Arrays.asList(xlint.getXlintOption(), "-source", sourceLevel.sourceKey), null, Arrays.asList(source));
+        ct.analyze();
+        check();
+    }
+
+    void check() {
+
+        EnumSet<WarningKind> expectedWarnings = EnumSet.noneOf(WarningKind.class);
+
+        if (sourceLevel == SourceLevel.JDK_7 &&
+                trustMe == TrustMe.TRUST &&
+                suppressLevel != SuppressLevel.VARARGS &&
+                xlint != XlintOption.NONE &&
+                sig.isVarargs && !sig.isReifiableArg && body.hasAliasing &&
+                (methKind == MethodKind.CONSTRUCTOR || (methKind == MethodKind.METHOD && modKind != ModifierKind.NONE))) {
+            expectedWarnings.add(WarningKind.UNSAFE_BODY);
+        }
+
+        if (sourceLevel == SourceLevel.JDK_7 &&
+                trustMe == TrustMe.DONT_TRUST &&
+                sig.isVarargs &&
+                !sig.isReifiableArg &&
+                xlint == XlintOption.ALL) {
+            expectedWarnings.add(WarningKind.UNSAFE_DECL);
+        }
+
+        if (sourceLevel == SourceLevel.JDK_7 &&
+                trustMe == TrustMe.TRUST &&
+                (!sig.isVarargs ||
+                (modKind == ModifierKind.NONE && methKind == MethodKind.METHOD))) {
+            expectedWarnings.add(WarningKind.MALFORMED_SAFEVARARGS);
+        }
+
+        if (sourceLevel == SourceLevel.JDK_7 &&
+                trustMe == TrustMe.TRUST &&
+                xlint != XlintOption.NONE &&
+                suppressLevel != SuppressLevel.VARARGS &&
+                (modKind != ModifierKind.NONE || methKind == MethodKind.CONSTRUCTOR) &&
+                sig.isVarargs &&
+                sig.isReifiableArg) {
+            expectedWarnings.add(WarningKind.REDUNDANT_SAFEVARARGS);
+        }
+
+        if (!expectedWarnings.containsAll(dc.warnings) ||
+                !dc.warnings.containsAll(expectedWarnings)) {
+            throw new Error("invalid diagnostics for source:\n" +
+                    source.getCharContent(true) +
+                    "\nOptions: " + xlint.getXlintOption() +
+                    "\nExpected warnings: " + expectedWarnings +
+                    "\nFound warnings: " + dc.warnings);
+        }
+    }
+
+    class JavaSource extends SimpleJavaFileObject {
 
         String template = "import com.sun.tools.javac.api.*;\n" +
                           "import java.util.List;\n" +
@@ -167,12 +283,11 @@
 
         String source;
 
-        public JavaSource(TrustMe trustMe, SuppressLevel suppressLevel, ModifierKind modKind,
-                MethodKind methKind, SignatureKind meth, BodyKind body) {
+        public JavaSource() {
             super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE);
             source = template.replace("#T", trustMe.anno).
                     replace("#S", suppressLevel.getSuppressAnno()).
-                    replace("#M", meth.getSignature(modKind, methKind)).
+                    replace("#M", sig.getSignature(modKind, methKind)).
                     replace("#B", body.body);
         }
 
@@ -182,117 +297,34 @@
         }
     }
 
-    public static void main(String... args) throws Exception {
-        for (SourceLevel sourceLevel : SourceLevel.values()) {
-            for (XlintOption xlint : XlintOption.values()) {
-                for (TrustMe trustMe : TrustMe.values()) {
-                    for (SuppressLevel suppressLevel : SuppressLevel.values()) {
-                        for (ModifierKind modKind : ModifierKind.values()) {
-                            for (MethodKind methKind : MethodKind.values()) {
-                                for (SignatureKind sig : SignatureKind.values()) {
-                                    for (BodyKind body : BodyKind.values()) {
-                                        test(sourceLevel,
-                                                xlint,
-                                                trustMe,
-                                                suppressLevel,
-                                                modKind,
-                                                methKind,
-                                                sig,
-                                                body);
-                                    }
-                                }
-                            }
-                        }
-                    }
-                }
-            }
-        }
-    }
-
-    // Create a single file manager and reuse it for each compile to save time.
-    static StandardJavaFileManager fm = JavacTool.create().getStandardFileManager(null, null, null);
-
-    static void test(SourceLevel sourceLevel, XlintOption xlint, TrustMe trustMe, SuppressLevel suppressLevel,
-            ModifierKind modKind, MethodKind methKind, SignatureKind sig, BodyKind body) throws Exception {
-        final JavaCompiler tool = ToolProvider.getSystemJavaCompiler();
-        JavaSource source = new JavaSource(trustMe, suppressLevel, modKind, methKind, sig, body);
-        DiagnosticChecker dc = new DiagnosticChecker();
-        JavacTask ct = (JavacTask)tool.getTask(null, fm, dc,
-                Arrays.asList(xlint.getXlintOption(), "-source", sourceLevel.sourceKey), null, Arrays.asList(source));
-        ct.analyze();
-        check(sourceLevel, dc, source, xlint, trustMe,
-                suppressLevel, modKind, methKind, sig, body);
-    }
-
-    static void check(SourceLevel sourceLevel, DiagnosticChecker dc, JavaSource source,
-            XlintOption xlint, TrustMe trustMe, SuppressLevel suppressLevel, ModifierKind modKind,
-            MethodKind methKind, SignatureKind meth, BodyKind body) {
+    class DiagnosticChecker implements javax.tools.DiagnosticListener<JavaFileObject> {
 
-        boolean hasPotentiallyUnsafeBody = sourceLevel == SourceLevel.JDK_7 &&
-                trustMe == TrustMe.TRUST &&
-                suppressLevel != SuppressLevel.VARARGS &&
-                xlint != XlintOption.NONE &&
-                meth.isVarargs && !meth.isReifiableArg && body.hasAliasing &&
-                (methKind == MethodKind.CONSTRUCTOR || (methKind == MethodKind.METHOD && modKind != ModifierKind.NONE));
-
-        boolean hasPotentiallyPollutingDecl = sourceLevel == SourceLevel.JDK_7 &&
-                trustMe == TrustMe.DONT_TRUST &&
-                meth.isVarargs &&
-                !meth.isReifiableArg &&
-                xlint == XlintOption.ALL;
-
-        boolean hasMalformedAnnoInDecl = sourceLevel == SourceLevel.JDK_7 &&
-                trustMe == TrustMe.TRUST &&
-                (!meth.isVarargs ||
-                (modKind == ModifierKind.NONE && methKind == MethodKind.METHOD));
-
-        boolean hasRedundantAnnoInDecl = sourceLevel == SourceLevel.JDK_7 &&
-                trustMe == TrustMe.TRUST &&
-                xlint != XlintOption.NONE &&
-                suppressLevel != SuppressLevel.VARARGS &&
-                (modKind != ModifierKind.NONE || methKind == MethodKind.CONSTRUCTOR) &&
-                meth.isVarargs &&
-                meth.isReifiableArg;
-
-        if (hasPotentiallyUnsafeBody != dc.hasPotentiallyUnsafeBody ||
-                hasPotentiallyPollutingDecl != dc.hasPotentiallyPollutingDecl ||
-                hasMalformedAnnoInDecl != dc.hasMalformedAnnoInDecl ||
-                hasRedundantAnnoInDecl != dc.hasRedundantAnnoInDecl) {
-            throw new Error("invalid diagnostics for source:\n" +
-                    source.getCharContent(true) +
-                    "\nOptions: " + xlint.getXlintOption() +
-                    "\nExpected potentially unsafe body warning: " + hasPotentiallyUnsafeBody +
-                    "\nExpected potentially polluting decl warning: " + hasPotentiallyPollutingDecl +
-                    "\nExpected malformed anno error: " + hasMalformedAnnoInDecl +
-                    "\nExpected redundant anno warning: " + hasRedundantAnnoInDecl +
-                    "\nFound potentially unsafe body warning: " + dc.hasPotentiallyUnsafeBody +
-                    "\nFound potentially polluting decl warning: " + dc.hasPotentiallyPollutingDecl +
-                    "\nFound malformed anno error: " + dc.hasMalformedAnnoInDecl +
-                    "\nFound redundant anno warning: " + dc.hasRedundantAnnoInDecl);
-        }
-    }
-
-    static class DiagnosticChecker implements javax.tools.DiagnosticListener<JavaFileObject> {
-
-        boolean hasPotentiallyUnsafeBody = false;
-        boolean hasPotentiallyPollutingDecl = false;
-        boolean hasMalformedAnnoInDecl = false;
-        boolean hasRedundantAnnoInDecl = false;
+        EnumSet<WarningKind> warnings = EnumSet.noneOf(WarningKind.class);
 
         public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
             if (diagnostic.getKind() == Diagnostic.Kind.WARNING) {
                     if (diagnostic.getCode().contains("unsafe.use.varargs.param")) {
-                        hasPotentiallyUnsafeBody = true;
+                        setWarning(WarningKind.UNSAFE_BODY);
                     } else if (diagnostic.getCode().contains("redundant.trustme")) {
-                        hasRedundantAnnoInDecl = true;
+                        setWarning(WarningKind.REDUNDANT_SAFEVARARGS);
                     }
             } else if (diagnostic.getKind() == Diagnostic.Kind.MANDATORY_WARNING &&
                     diagnostic.getCode().contains("varargs.non.reifiable.type")) {
-                hasPotentiallyPollutingDecl = true;
+                setWarning(WarningKind.UNSAFE_DECL);
             } else if (diagnostic.getKind() == Diagnostic.Kind.ERROR &&
                     diagnostic.getCode().contains("invalid.trustme")) {
-                hasMalformedAnnoInDecl = true;
+                setWarning(WarningKind.MALFORMED_SAFEVARARGS);
             }
         }
+
+        void setWarning(WarningKind wk) {
+            if (!warnings.add(wk)) {
+                throw new AssertionError("Duplicate warning of kind " + wk + " in source:\n" + source);
+            }
+        }
+
+        boolean hasWarning(WarningKind wk) {
+            return warnings.contains(wk);
+        }
     }
 }