--- a/.hgtags Wed Apr 18 14:07:41 2018 -0700
+++ b/.hgtags Fri Apr 20 09:05:05 2018 -0700
@@ -481,3 +481,4 @@
755e1b55a4dff510f9639cdb5c5e82549a7e09b3 jdk-11+8
0c3e252cea44f06aef570ef464950ab97c669970 jdk-11+9
6fa770f9f8ab296e1ce255ec17ccf6d4e1051886 jdk-10+46
+69d7398038c54774d9395b6810e0cca335edc02c jdk-11+10
--- a/make/Init.gmk Wed Apr 18 14:07:41 2018 -0700
+++ b/make/Init.gmk Fri Apr 20 09:05:05 2018 -0700
@@ -310,9 +310,13 @@
ifneq ($(PARALLEL_TARGETS), )
$(call StartGlobalTimer)
$(call PrepareSmartJavac)
+ # JOBS will only be empty for a bootcycle-images recursive call
+ # or if specified via a make argument directly. In those cases
+ # treat it as NOT using jobs at all.
( cd $(TOPDIR) && \
$(NICE) $(MAKE) $(MAKE_ARGS) $(OUTPUT_SYNC_FLAG) \
- -j $(JOBS) -f make/Main.gmk $(USER_MAKE_VARS) \
+ $(if $(JOBS), -j $(JOBS)) \
+ -f make/Main.gmk $(USER_MAKE_VARS) \
$(PARALLEL_TARGETS) $(COMPARE_BUILD_MAKE) $(BUILD_LOG_PIPE) || \
( exitcode=$$? && \
$(PRINTF) "\nERROR: Build failed for $(TARGET_DESCRIPTION) (exit code $$exitcode) \n" \
--- a/make/data/charsetmapping/charsets Wed Apr 18 14:07:41 2018 -0700
+++ b/make/data/charsetmapping/charsets Fri Apr 20 09:05:05 2018 -0700
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@@ -326,6 +326,8 @@
ascii true
alias cp1252 # JDK historical
alias cp5348 # Euro IBM CCSID
+ alias ibm-1252
+ alias ibm1252
charset windows-1253 MS1253
package sun.nio.cs
@@ -933,11 +935,16 @@
charset x-IBM942C IBM942C
package sun.nio.cs.ext
- type source
+ type template
alias cp942C # JDK historical
alias ibm942C
alias ibm-942C
alias 942C
+ alias cp932
+ alias ibm932
+ alias ibm-932
+ alias 932
+ alias x-ibm932
charset x-IBM943 IBM943
package sun.nio.cs.ext
@@ -952,7 +959,7 @@
charset x-IBM943C IBM943C
package sun.nio.cs.ext
- type source
+ type template
alias cp943C # JDK historical
alias ibm943C
alias ibm-943C
@@ -1519,6 +1526,9 @@
alias ibm1383
alias ibm-1383
alias 1383
+ alias ibmeuccn
+ alias ibm-euccn
+ alias cpeuccn
charset x-IBM970 IBM970
package sun.nio.cs.ext
--- a/make/data/charsetmapping/stdcs-aix Wed Apr 18 14:07:41 2018 -0700
+++ b/make/data/charsetmapping/stdcs-aix Fri Apr 20 09:05:05 2018 -0700
@@ -1,6 +1,26 @@
#
# generate these charsets into sun.nio.cs
#
+Big5
+Big5_Solaris
+Big5_HKSCS
EUC_CN
EUC_KR
GBK
+GB18030
+IBM856
+IBM921
+IBM922
+IBM942
+IBM942C
+IBM943
+IBM943C
+IBM950
+IBM970
+IBM1046
+IBM1124
+IBM1383
+ISO_8859_6
+ISO_8859_8
+MS1252
+TIS_620
--- a/make/jdk/src/classes/build/tools/charsetmapping/SPI.java Wed Apr 18 14:07:41 2018 -0700
+++ b/make/jdk/src/classes/build/tools/charsetmapping/SPI.java Fri Apr 20 09:05:05 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -129,7 +129,7 @@
} else if (line.indexOf("_INCLUDE_ALIASES_MAP_") != -1) {
Hasher.genClass(out, aliasKeys, aliasValues,
null, "Aliases", "String",
- 11, 3, true, false, false);
+ 12, 3, true, false, false);
} else if (line.indexOf("_INCLUDE_CLASSES_MAP_") != -1) {
Hasher.genClass(out, clzKeys, clzValues,
null, "Classes", "String",
--- a/make/langtools/tools/propertiesparser/parser/MessageType.java Wed Apr 18 14:07:41 2018 -0700
+++ b/make/langtools/tools/propertiesparser/parser/MessageType.java Fri Apr 20 09:05:05 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -86,13 +86,17 @@
NAME("name", "Name", "com.sun.tools.javac.util"),
NUMBER("number", "int", null),
OPTION_NAME("option name", "Option", "com.sun.tools.javac.main"),
+ PROFILE("profile", "Profile", "com.sun.tools.javac.jvm"),
+ SOURCE("source", "Source", "com.sun.tools.javac.code"),
SOURCE_VERSION("source version", "SourceVersion", "javax.lang.model"),
STRING("string", "String", null),
SYMBOL("symbol", "Symbol", "com.sun.tools.javac.code"),
SYMBOL_KIND("symbol kind", "Kind", "com.sun.tools.javac.code.Kinds"),
KIND_NAME("kind name", "KindName", "com.sun.tools.javac.code.Kinds"),
+ TARGET("target", "Target", "com.sun.tools.javac.jvm"),
TOKEN("token", "TokenKind", "com.sun.tools.javac.parser.Tokens"),
TYPE("type", "Type", "com.sun.tools.javac.code"),
+ URL("url", "URL", "java.net"),
SET("set", "Set", "java.util"),
LIST("list", "List", "java.util"),
OBJECT("object", "Object", null),
--- a/make/lib/Awt2dLibraries.gmk Wed Apr 18 14:07:41 2018 -0700
+++ b/make/lib/Awt2dLibraries.gmk Fri Apr 20 09:05:05 2018 -0700
@@ -224,7 +224,7 @@
format-nonliteral parentheses, \
DISABLED_WARNINGS_clang := logical-op-parentheses extern-initializer, \
DISABLED_WARNINGS_solstudio := E_DECLARATION_IN_CODE, \
- DISABLED_WARNINGS_microsoft := 4297 4244 4267 4996, \
+ DISABLED_WARNINGS_microsoft := 4297 4244 4267 4291 4302 4311 4996, \
ASFLAGS := $(LIBAWT_ASFLAGS), \
LDFLAGS := $(LDFLAGS_JDKLIB) $(call SET_SHARED_LIBRARY_ORIGIN), \
LDFLAGS_macosx := -L$(INSTALL_LIBRARIES_HERE), \
--- a/src/hotspot/cpu/aarch64/gc/shared/modRefBarrierSetAssembler_aarch64.cpp Wed Apr 18 14:07:41 2018 -0700
+++ b/src/hotspot/cpu/aarch64/gc/shared/modRefBarrierSetAssembler_aarch64.cpp Fri Apr 20 09:05:05 2018 -0700
@@ -44,12 +44,6 @@
}
}
-
-void ModRefBarrierSetAssembler::oop_store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
- Address dst, Register val, Register tmp1, Register tmp2) {
- BarrierSetAssembler::store_at(masm, decorators, type, dst, val, tmp1, tmp2);
-}
-
void ModRefBarrierSetAssembler::store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
Address dst, Register val, Register tmp1, Register tmp2) {
if (type == T_OBJECT || type == T_ARRAY) {
--- a/src/hotspot/cpu/aarch64/gc/shared/modRefBarrierSetAssembler_aarch64.hpp Wed Apr 18 14:07:41 2018 -0700
+++ b/src/hotspot/cpu/aarch64/gc/shared/modRefBarrierSetAssembler_aarch64.hpp Fri Apr 20 09:05:05 2018 -0700
@@ -40,7 +40,7 @@
Register start, Register end, Register tmp, RegSet saved_regs) {}
virtual void oop_store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
- Address dst, Register val, Register tmp1, Register tmp2);
+ Address dst, Register val, Register tmp1, Register tmp2) = 0;
public:
virtual void arraycopy_prologue(MacroAssembler* masm, DecoratorSet decorators, bool is_oop,
--- a/src/hotspot/cpu/ppc/gc/shared/modRefBarrierSetAssembler_ppc.cpp Wed Apr 18 14:07:41 2018 -0700
+++ b/src/hotspot/cpu/ppc/gc/shared/modRefBarrierSetAssembler_ppc.cpp Fri Apr 20 09:05:05 2018 -0700
@@ -56,12 +56,6 @@
}
}
-void ModRefBarrierSetAssembler::oop_store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
- Register base, RegisterOrConstant ind_or_offs, Register val,
- Register tmp1, Register tmp2, Register tmp3, bool needs_frame) {
- BarrierSetAssembler::store_at(masm, decorators, type, base, ind_or_offs, val, tmp1, tmp2, tmp3, needs_frame);
-}
-
void ModRefBarrierSetAssembler::store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
Register base, RegisterOrConstant ind_or_offs, Register val,
Register tmp1, Register tmp2, Register tmp3, bool needs_frame) {
--- a/src/hotspot/cpu/ppc/gc/shared/modRefBarrierSetAssembler_ppc.hpp Wed Apr 18 14:07:41 2018 -0700
+++ b/src/hotspot/cpu/ppc/gc/shared/modRefBarrierSetAssembler_ppc.hpp Fri Apr 20 09:05:05 2018 -0700
@@ -41,7 +41,7 @@
virtual void oop_store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
Register base, RegisterOrConstant ind_or_offs, Register val,
- Register tmp1, Register tmp2, Register tmp3, bool needs_frame);
+ Register tmp1, Register tmp2, Register tmp3, bool needs_frame) = 0;
public:
virtual void arraycopy_prologue(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
Register src, Register dst, Register count, Register preserve1, Register preserve2);
--- a/src/hotspot/cpu/s390/gc/shared/barrierSetAssembler_s390.cpp Wed Apr 18 14:07:41 2018 -0700
+++ b/src/hotspot/cpu/s390/gc/shared/barrierSetAssembler_s390.cpp Fri Apr 20 09:05:05 2018 -0700
@@ -24,6 +24,7 @@
*/
#include "precompiled.hpp"
+#include "asm/macroAssembler.inline.hpp"
#include "gc/shared/barrierSetAssembler.hpp"
#include "interpreter/interp_masm.hpp"
--- a/src/hotspot/cpu/s390/gc/shared/modRefBarrierSetAssembler_s390.cpp Wed Apr 18 14:07:41 2018 -0700
+++ b/src/hotspot/cpu/s390/gc/shared/modRefBarrierSetAssembler_s390.cpp Fri Apr 20 09:05:05 2018 -0700
@@ -50,11 +50,6 @@
}
}
-void ModRefBarrierSetAssembler::oop_store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
- const Address& dst, Register val, Register tmp1, Register tmp2, Register tmp3) {
- BarrierSetAssembler::store_at(masm, decorators, type, dst, val, tmp1, tmp2, tmp3);
-}
-
void ModRefBarrierSetAssembler::store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
const Address& dst, Register val, Register tmp1, Register tmp2, Register tmp3) {
if (type == T_OBJECT || type == T_ARRAY) {
--- a/src/hotspot/cpu/s390/gc/shared/modRefBarrierSetAssembler_s390.hpp Wed Apr 18 14:07:41 2018 -0700
+++ b/src/hotspot/cpu/s390/gc/shared/modRefBarrierSetAssembler_s390.hpp Fri Apr 20 09:05:05 2018 -0700
@@ -39,7 +39,7 @@
virtual void gen_write_ref_array_post_barrier(MacroAssembler* masm, DecoratorSet decorators, Register addr, Register count,
bool do_return);
virtual void oop_store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
- const Address& dst, Register val, Register tmp1, Register tmp2, Register tmp3);
+ const Address& dst, Register val, Register tmp1, Register tmp2, Register tmp3) = 0;
public:
virtual void arraycopy_prologue(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
Register src, Register dst, Register count);
--- a/src/hotspot/share/aot/aotCodeHeap.cpp Wed Apr 18 14:07:41 2018 -0700
+++ b/src/hotspot/share/aot/aotCodeHeap.cpp Fri Apr 20 09:05:05 2018 -0700
@@ -445,6 +445,8 @@
SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_handle_wrong_method_stub", address, SharedRuntime::get_handle_wrong_method_stub());
SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_exception_handler_for_return_address", address, SharedRuntime::exception_handler_for_return_address);
SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_register_finalizer", address, SharedRuntime::register_finalizer);
+ SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_object_notify", address, JVMCIRuntime::object_notify);
+ SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_object_notifyAll", address, JVMCIRuntime::object_notifyAll);
SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_OSR_migration_end", address, SharedRuntime::OSR_migration_end);
SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_resolve_dynamic_invoke", address, CompilerRuntime::resolve_dynamic_invoke);
SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_resolve_string_by_symbol", address, CompilerRuntime::resolve_string_by_symbol);
--- a/src/hotspot/share/classfile/classLoader.cpp Wed Apr 18 14:07:41 2018 -0700
+++ b/src/hotspot/share/classfile/classLoader.cpp Fri Apr 20 09:05:05 2018 -0700
@@ -80,13 +80,13 @@
// Entry points in zip.dll for loading zip/jar file entries
-typedef void * * (JNICALL *ZipOpen_t)(const char *name, char **pmsg);
-typedef void (JNICALL *ZipClose_t)(jzfile *zip);
-typedef jzentry* (JNICALL *FindEntry_t)(jzfile *zip, const char *name, jint *sizeP, jint *nameLen);
-typedef jboolean (JNICALL *ReadEntry_t)(jzfile *zip, jzentry *entry, unsigned char *buf, char *namebuf);
-typedef jzentry* (JNICALL *GetNextEntry_t)(jzfile *zip, jint n);
-typedef jboolean (JNICALL *ZipInflateFully_t)(void *inBuf, jlong inLen, void *outBuf, jlong outLen, char **pmsg);
-typedef jint (JNICALL *Crc32_t)(jint crc, const jbyte *buf, jint len);
+typedef void * * (*ZipOpen_t)(const char *name, char **pmsg);
+typedef void (*ZipClose_t)(jzfile *zip);
+typedef jzentry* (*FindEntry_t)(jzfile *zip, const char *name, jint *sizeP, jint *nameLen);
+typedef jboolean (*ReadEntry_t)(jzfile *zip, jzentry *entry, unsigned char *buf, char *namebuf);
+typedef jzentry* (*GetNextEntry_t)(jzfile *zip, jint n);
+typedef jboolean (*ZipInflateFully_t)(void *inBuf, jlong inLen, void *outBuf, jlong outLen, char **pmsg);
+typedef jint (*Crc32_t)(jint crc, const jbyte *buf, jint len);
static ZipOpen_t ZipOpen = NULL;
static ZipClose_t ZipClose = NULL;
--- a/src/hotspot/share/classfile/classLoaderData.cpp Wed Apr 18 14:07:41 2018 -0700
+++ b/src/hotspot/share/classfile/classLoaderData.cpp Fri Apr 20 09:05:05 2018 -0700
@@ -54,6 +54,7 @@
#include "classfile/metadataOnStackMark.hpp"
#include "classfile/moduleEntry.hpp"
#include "classfile/packageEntry.hpp"
+#include "classfile/symbolTable.hpp"
#include "classfile/systemDictionary.hpp"
#include "logging/log.hpp"
#include "logging/logStream.hpp"
@@ -102,8 +103,25 @@
}
}
+// JFR and logging support so that the name and klass are available after the
+// class_loader oop is no longer alive, during unloading.
+void ClassLoaderData::initialize_name_and_klass(Handle class_loader) {
+ _class_loader_klass = class_loader->klass();
+ oop class_loader_name = java_lang_ClassLoader::name(class_loader());
+ if (class_loader_name != NULL) {
+ Thread* THREAD = Thread::current();
+ ResourceMark rm(THREAD);
+ const char* class_loader_instance_name =
+ java_lang_String::as_utf8_string(class_loader_name);
+
+ if (class_loader_instance_name != NULL && class_loader_instance_name[0] != '\0') {
+ // Can't throw InternalError and SymbolTable doesn't throw OOM anymore.
+ _class_loader_name = SymbolTable::new_symbol(class_loader_instance_name, CATCH);
+ }
+ }
+}
+
ClassLoaderData::ClassLoaderData(Handle h_class_loader, bool is_anonymous) :
- _class_loader(h_class_loader()),
_is_anonymous(is_anonymous),
// An anonymous class loader data doesn't have anything to keep
// it from being unloaded during parsing of the anonymous class.
@@ -114,9 +132,14 @@
_claimed(0), _modified_oops(true), _accumulated_modified_oops(false),
_jmethod_ids(NULL), _handles(), _deallocate_list(NULL),
_next(NULL),
+ _class_loader_klass(NULL), _class_loader_name(NULL),
_metaspace_lock(new Mutex(Monitor::leaf+1, "Metaspace allocation lock", true,
Monitor::_safepoint_check_never)) {
+ if (!h_class_loader.is_null()) {
+ _class_loader = _handles.add(h_class_loader());
+ }
+
if (!is_anonymous) {
// The holder is initialized later for anonymous classes, and before calling anything
// that call class_loader().
@@ -269,7 +292,6 @@
clear_modified_oops();
}
- f->do_oop(&_class_loader);
_handles.oops_do(f);
}
@@ -556,7 +578,7 @@
if (lt.is_enabled()) {
ResourceMark rm;
LogStream ls(lt);
- ls.print("unload ");
+ ls.print("unload");
print_value_on(&ls);
ls.cr();
}
@@ -631,7 +653,7 @@
// Unloading support
bool ClassLoaderData::is_alive() const {
bool alive = keep_alive() // null class loader and incomplete anonymous klasses.
- || (_holder.peek() != NULL); // not cleaned by weak reference processing
+ || (_holder.peek() != NULL); // and not cleaned by the GC weak handle processing.
return alive;
}
@@ -887,13 +909,23 @@
}
const char* ClassLoaderData::loader_name() const {
- // Handles null class loader
- return SystemDictionary::loader_name(class_loader());
+ if (is_unloading()) {
+ if (_class_loader_klass == NULL) {
+ return "<bootloader>";
+ } else if (_class_loader_name != NULL) {
+ return _class_loader_name->as_C_string();
+ } else {
+ return _class_loader_klass->name()->as_C_string();
+ }
+ } else {
+ // Handles null class loader
+ return SystemDictionary::loader_name(class_loader());
+ }
}
void ClassLoaderData::print_value_on(outputStream* out) const {
- if (class_loader() != NULL) {
+ if (!is_unloading() && class_loader() != NULL) {
out->print("loader data: " INTPTR_FORMAT " for instance ", p2i(this));
class_loader()->print_value_on(out); // includes loader_name() and address of class loader instance
} else {
@@ -908,7 +940,7 @@
#ifndef PRODUCT
void ClassLoaderData::print_on(outputStream* out) const {
out->print("ClassLoaderData CLD: " PTR_FORMAT ", loader: " PTR_FORMAT ", loader_klass: %s {",
- p2i(this), p2i((void *)class_loader()), loader_name());
+ p2i(this), p2i(_class_loader.ptr_raw()), loader_name());
if (is_anonymous()) out->print(" anonymous");
if (claimed()) out->print(" claimed");
if (is_unloading()) out->print(" unloading");
@@ -962,10 +994,10 @@
// Add a new class loader data node to the list. Assign the newly created
// ClassLoaderData into the java/lang/ClassLoader object as a hidden field
-ClassLoaderData* ClassLoaderDataGraph::add(Handle loader, bool is_anonymous) {
+ClassLoaderData* ClassLoaderDataGraph::add_to_graph(Handle loader, bool is_anonymous) {
NoSafepointVerifier no_safepoints; // we mustn't GC until we've installed the
// ClassLoaderData in the graph since the CLD
- // contains unhandled oops
+ // contains oops in _handles that must be walked.
ClassLoaderData* cld = new ClassLoaderData(loader, is_anonymous);
@@ -1002,6 +1034,16 @@
} while (true);
}
+ClassLoaderData* ClassLoaderDataGraph::add(Handle loader, bool is_anonymous) {
+ ClassLoaderData* loader_data = add_to_graph(loader, is_anonymous);
+ // Initialize name and class after the loader data is added to the CLDG
+ // because adding the Symbol for the name might safepoint.
+ if (loader.not_null()) {
+ loader_data->initialize_name_and_klass(loader);
+ }
+ return loader_data;
+}
+
void ClassLoaderDataGraph::oops_do(OopClosure* f, bool must_claim) {
for (ClassLoaderData* cld = _head; cld != NULL; cld = cld->next()) {
cld->oops_do(f, must_claim);
@@ -1237,8 +1279,7 @@
// Move class loader data from main list to the unloaded list for unloading
// and deallocation later.
-bool ClassLoaderDataGraph::do_unloading(BoolObjectClosure* is_alive_closure,
- bool clean_previous_versions) {
+bool ClassLoaderDataGraph::do_unloading(bool clean_previous_versions) {
ClassLoaderData* data = _head;
ClassLoaderData* prev = NULL;
@@ -1296,7 +1337,7 @@
// Remove entries in the dictionary of live class loader that have
// initiated loading classes in a dead class loader.
if (data->dictionary() != NULL) {
- data->dictionary()->do_unloading(is_alive_closure);
+ data->dictionary()->do_unloading();
}
// Walk a ModuleEntry's reads, and a PackageEntry's exports
// lists to determine if there are modules on those lists that are now
--- a/src/hotspot/share/classfile/classLoaderData.hpp Wed Apr 18 14:07:41 2018 -0700
+++ b/src/hotspot/share/classfile/classLoaderData.hpp Fri Apr 20 09:05:05 2018 -0700
@@ -28,7 +28,6 @@
#include "memory/allocation.hpp"
#include "memory/memRegion.hpp"
#include "memory/metaspace.hpp"
-#include "memory/metaspaceCounters.hpp"
#include "oops/oopHandle.hpp"
#include "oops/weakHandle.hpp"
#include "runtime/mutex.hpp"
@@ -84,6 +83,7 @@
static volatile size_t _num_instance_classes;
static volatile size_t _num_array_classes;
+ static ClassLoaderData* add_to_graph(Handle class_loader, bool anonymous);
static ClassLoaderData* add(Handle class_loader, bool anonymous);
static void post_class_unload_events();
public:
@@ -114,7 +114,7 @@
static void packages_unloading_do(void f(PackageEntry*));
static void loaded_classes_do(KlassClosure* klass_closure);
static void classes_unloading_do(void f(Klass* const));
- static bool do_unloading(BoolObjectClosure* is_alive_closure, bool clean_previous_versions);
+ static bool do_unloading(bool clean_previous_versions);
// dictionary do
// Iterate over all klasses in dictionary, but
@@ -221,7 +221,7 @@
static ClassLoaderData * _the_null_class_loader_data;
WeakHandle<vm_class_loader_data> _holder; // The oop that determines lifetime of this class loader
- oop _class_loader; // The instance of java/lang/ClassLoader associated with
+ OopHandle _class_loader; // The instance of java/lang/ClassLoader associated with
// this ClassLoaderData
ClassLoaderMetaspace * volatile _metaspace; // Meta-space where meta-data defined by the
@@ -234,7 +234,7 @@
bool _modified_oops; // Card Table Equivalent (YC/CMS support)
bool _accumulated_modified_oops; // Mod Union Equivalent (CMS support)
- s2 _keep_alive; // if this CLD is kept alive without a keep_alive_object().
+ s2 _keep_alive; // if this CLD is kept alive.
// Used for anonymous classes and the boot class
// loader. _keep_alive does not need to be volatile or
// atomic since there is one unique CLD per anonymous class.
@@ -265,6 +265,9 @@
// Support for walking class loader data objects
ClassLoaderData* _next; /// Next loader_datas created
+ // JFR support
+ Klass* _class_loader_klass;
+ Symbol* _class_loader_name;
TRACE_DEFINE_TRACE_ID_FIELD;
void set_next(ClassLoaderData* next) { _next = next; }
@@ -305,6 +308,8 @@
MetaWord* allocate(size_t size);
Dictionary* create_dictionary();
+
+ void initialize_name_and_klass(Handle class_loader);
public:
// GC interface.
void clear_claimed() { _claimed = 0; }
@@ -340,9 +345,7 @@
// Returns true if this class loader data is for the boot class loader.
// (Note that the class loader data may be anonymous.)
- bool is_boot_class_loader_data() const {
- return class_loader() == NULL;
- }
+ inline bool is_boot_class_loader_data() const;
bool is_builtin_class_loader_data() const;
bool is_permanent_class_loader_data() const;
@@ -351,10 +354,7 @@
// method will allocate a Metaspace if needed.
ClassLoaderMetaspace* metaspace_non_null();
- oop class_loader() const { return _class_loader; }
-
- // The object the GC is using to keep this ClassLoaderData alive.
- oop keep_alive_object() const;
+ inline oop class_loader() const;
// Returns true if this class loader data is for a loader going away.
bool is_unloading() const {
@@ -363,7 +363,7 @@
}
// Used to refcount an anonymous class's CLD in order to
- // indicate their aliveness without a keep_alive_object().
+ // indicate their aliveness.
void inc_keep_alive();
void dec_keep_alive();
@@ -407,6 +407,9 @@
static ClassLoaderData* class_loader_data_or_null(oop loader);
static ClassLoaderData* anonymous_class_loader_data(Handle loader);
+
+ Klass* class_loader_klass() const { return _class_loader_klass; }
+ Symbol* class_loader_name() const { return _class_loader_name; }
TRACE_DEFINE_TRACE_ID_METHODS;
};
--- a/src/hotspot/share/classfile/classLoaderData.inline.hpp Wed Apr 18 14:07:41 2018 -0700
+++ b/src/hotspot/share/classfile/classLoaderData.inline.hpp Fri Apr 20 09:05:05 2018 -0700
@@ -28,6 +28,18 @@
#include "classfile/classLoaderData.hpp"
#include "classfile/javaClasses.hpp"
#include "oops/oop.inline.hpp"
+#include "oops/oopHandle.inline.hpp"
+#include "oops/weakHandle.inline.hpp"
+
+inline oop ClassLoaderData::class_loader() const {
+ assert(!_unloading, "This oop is not available to unloading class loader data");
+ assert(_holder.is_null() || _holder.peek() != NULL , "This class loader data holder must be alive");
+ return _class_loader.resolve();
+}
+
+inline bool ClassLoaderData::is_boot_class_loader_data() const {
+ return class_loader() == NULL;
+ }
inline ClassLoaderData* ClassLoaderData::class_loader_data_or_null(oop loader) {
if (loader == NULL) {
--- a/src/hotspot/share/classfile/classLoaderStats.cpp Wed Apr 18 14:07:41 2018 -0700
+++ b/src/hotspot/share/classfile/classLoaderStats.cpp Fri Apr 20 09:05:05 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -23,6 +23,7 @@
*/
#include "precompiled.hpp"
+#include "classfile/classLoaderData.inline.hpp"
#include "classfile/classLoaderStats.hpp"
#include "oops/oop.inline.hpp"
#include "utilities/globalDefinitions.hpp"
--- a/src/hotspot/share/classfile/dictionary.cpp Wed Apr 18 14:07:41 2018 -0700
+++ b/src/hotspot/share/classfile/dictionary.cpp Fri Apr 20 09:05:05 2018 -0700
@@ -214,13 +214,13 @@
// During class loading we may have cached a protection domain that has
// since been unreferenced, so this entry should be cleared.
-void Dictionary::clean_cached_protection_domains(BoolObjectClosure* is_alive, DictionaryEntry* probe) {
+void Dictionary::clean_cached_protection_domains(DictionaryEntry* probe) {
assert_locked_or_safepoint(SystemDictionary_lock);
ProtectionDomainEntry* current = probe->pd_set();
ProtectionDomainEntry* prev = NULL;
while (current != NULL) {
- if (!is_alive->do_object_b(current->object_no_keepalive())) {
+ if (current->object_no_keepalive() == NULL) {
LogTarget(Debug, protectiondomain) lt;
if (lt.is_enabled()) {
ResourceMark rm;
@@ -228,7 +228,6 @@
LogStream ls(lt);
ls.print_cr("PD in set is not alive:");
ls.print("class loader: "); loader_data()->class_loader()->print_value_on(&ls);
- ls.print(" protection domain: "); current->object_no_keepalive()->print_value_on(&ls);
ls.print(" loading: "); probe->instance_klass()->print_value_on(&ls);
ls.cr();
}
@@ -249,7 +248,7 @@
}
-void Dictionary::do_unloading(BoolObjectClosure* is_alive) {
+void Dictionary::do_unloading() {
assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint");
// The NULL class loader doesn't initiate loading classes from other class loaders
@@ -276,7 +275,7 @@
continue;
}
// Clean pd_set
- clean_cached_protection_domains(is_alive, probe);
+ clean_cached_protection_domains(probe);
p = probe->next_addr();
}
}
--- a/src/hotspot/share/classfile/dictionary.hpp Wed Apr 18 14:07:41 2018 -0700
+++ b/src/hotspot/share/classfile/dictionary.hpp Fri Apr 20 09:05:05 2018 -0700
@@ -52,7 +52,7 @@
DictionaryEntry* get_entry(int index, unsigned int hash, Symbol* name);
- void clean_cached_protection_domains(BoolObjectClosure* is_alive, DictionaryEntry* probe);
+ void clean_cached_protection_domains(DictionaryEntry* probe);
protected:
static size_t entry_size();
@@ -72,20 +72,16 @@
InstanceKlass* find_shared_class(int index, unsigned int hash, Symbol* name);
- // GC support
- void oops_do(OopClosure* f);
- void roots_oops_do(OopClosure* strong, OopClosure* weak);
-
void classes_do(void f(InstanceKlass*));
void classes_do(void f(InstanceKlass*, TRAPS), TRAPS);
void all_entries_do(void f(InstanceKlass*, ClassLoaderData*));
void classes_do(MetaspaceClosure* it);
- void unlink(BoolObjectClosure* is_alive);
+ void unlink();
void remove_classes_in_error_state();
// Unload classes whose defining loaders are unloaded
- void do_unloading(BoolObjectClosure* is_alive);
+ void do_unloading();
// Protection domains
InstanceKlass* find(unsigned int hash, Symbol* name, Handle protection_domain);
--- a/src/hotspot/share/classfile/loaderConstraints.cpp Wed Apr 18 14:07:41 2018 -0700
+++ b/src/hotspot/share/classfile/loaderConstraints.cpp Fri Apr 20 09:05:05 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -99,7 +99,7 @@
InstanceKlass* klass = probe->klass();
// Remove klass that is no longer alive
if (klass != NULL &&
- klass->class_loader_data()->is_unloading()) {
+ !klass->is_loader_alive()) {
probe->set_klass(NULL);
if (lt.is_enabled()) {
ResourceMark rm;
@@ -116,31 +116,31 @@
int n = 0;
while (n < probe->num_loaders()) {
if (probe->loader_data(n)->is_unloading()) {
- if (lt.is_enabled()) {
- ResourceMark rm;
- lt.print("purging loader %s from constraint for name %s",
- probe->loader_data(n)->loader_name(),
- probe->name()->as_C_string()
- );
- }
+ if (lt.is_enabled()) {
+ ResourceMark rm;
+ lt.print("purging loader %s from constraint for name %s",
+ probe->loader_data(n)->loader_name(),
+ probe->name()->as_C_string()
+ );
+ }
- // Compact array
- int num = probe->num_loaders() - 1;
- probe->set_num_loaders(num);
+ // Compact array
+ int num = probe->num_loaders() - 1;
+ probe->set_num_loaders(num);
probe->set_loader_data(n, probe->loader_data(num));
probe->set_loader_data(num, NULL);
- if (lt.is_enabled()) {
- ResourceMark rm;
- lt.print("new loader list:");
- for (int i = 0; i < probe->num_loaders(); i++) {
- lt.print(" [%d]: %s", i,
- probe->loader_data(i)->loader_name());
- }
+ if (lt.is_enabled()) {
+ ResourceMark rm;
+ lt.print("new loader list:");
+ for (int i = 0; i < probe->num_loaders(); i++) {
+ lt.print(" [%d]: %s", i,
+ probe->loader_data(i)->loader_name());
}
+ }
- continue; // current element replaced, so restart without
- // incrementing n
+ continue; // current element replaced, so restart without
+ // incrementing n
}
n++;
}
@@ -159,9 +159,7 @@
} else {
#ifdef ASSERT
if (probe->klass() != NULL) {
- ClassLoaderData* loader_data =
- probe->klass()->class_loader_data();
- assert(!loader_data->is_unloading(), "klass should be live");
+ assert(probe->klass()->is_loader_alive(), "klass should be live");
}
#endif
// Go to next entry
--- a/src/hotspot/share/classfile/moduleEntry.cpp Wed Apr 18 14:07:41 2018 -0700
+++ b/src/hotspot/share/classfile/moduleEntry.cpp Fri Apr 20 09:05:05 2018 -0700
@@ -24,7 +24,7 @@
#include "precompiled.hpp"
#include "jni.h"
-#include "classfile/classLoaderData.hpp"
+#include "classfile/classLoaderData.inline.hpp"
#include "classfile/javaClasses.hpp"
#include "classfile/moduleEntry.hpp"
#include "logging/log.hpp"
--- a/src/hotspot/share/classfile/placeholders.cpp Wed Apr 18 14:07:41 2018 -0700
+++ b/src/hotspot/share/classfile/placeholders.cpp Fri Apr 20 09:05:05 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -23,6 +23,7 @@
*/
#include "precompiled.hpp"
+#include "classfile/classLoaderData.inline.hpp"
#include "classfile/placeholders.hpp"
#include "classfile/systemDictionary.hpp"
#include "oops/oop.inline.hpp"
--- a/src/hotspot/share/classfile/protectionDomainCache.cpp Wed Apr 18 14:07:41 2018 -0700
+++ b/src/hotspot/share/classfile/protectionDomainCache.cpp Fri Apr 20 09:05:05 2018 -0700
@@ -30,6 +30,7 @@
#include "memory/iterator.hpp"
#include "memory/resourceArea.hpp"
#include "oops/oop.inline.hpp"
+#include "oops/weakHandle.inline.hpp"
#include "utilities/hashtable.inline.hpp"
unsigned int ProtectionDomainCacheTable::compute_hash(Handle protection_domain) {
@@ -42,26 +43,26 @@
}
ProtectionDomainCacheTable::ProtectionDomainCacheTable(int table_size)
- : Hashtable<oop, mtClass>(table_size, sizeof(ProtectionDomainCacheEntry))
+ : Hashtable<ClassLoaderWeakHandle, mtClass>(table_size, sizeof(ProtectionDomainCacheEntry))
{
}
-void ProtectionDomainCacheTable::unlink(BoolObjectClosure* is_alive) {
+void ProtectionDomainCacheTable::unlink() {
assert(SafepointSynchronize::is_at_safepoint(), "must be");
for (int i = 0; i < table_size(); ++i) {
ProtectionDomainCacheEntry** p = bucket_addr(i);
ProtectionDomainCacheEntry* entry = bucket(i);
while (entry != NULL) {
- if (is_alive->do_object_b(entry->object_no_keepalive())) {
+ oop pd = entry->object_no_keepalive();
+ if (pd != NULL) {
p = entry->next_addr();
} else {
LogTarget(Debug, protectiondomain) lt;
if (lt.is_enabled()) {
LogStream ls(lt);
- ls.print("protection domain unlinked: ");
- entry->object_no_keepalive()->print_value_on(&ls);
- ls.cr();
+ ls.print_cr("protection domain unlinked at %d", i);
}
+ entry->literal().release();
*p = entry->next();
free_entry(entry);
}
@@ -70,16 +71,6 @@
}
}
-void ProtectionDomainCacheTable::oops_do(OopClosure* f) {
- for (int index = 0; index < table_size(); index++) {
- for (ProtectionDomainCacheEntry* probe = bucket(index);
- probe != NULL;
- probe = probe->next()) {
- probe->oops_do(f);
- }
- }
-}
-
void ProtectionDomainCacheTable::print_on(outputStream* st) const {
st->print_cr("Protection domain cache table (table_size=%d, classes=%d)",
table_size(), number_of_entries());
@@ -97,7 +88,7 @@
}
oop ProtectionDomainCacheEntry::object() {
- return RootAccess<ON_PHANTOM_OOP_REF>::oop_load(literal_addr());
+ return literal().resolve();
}
oop ProtectionDomainEntry::object() {
@@ -108,7 +99,7 @@
// keeping it alive. This is okay to do in the VM thread state if it is not
// leaked out to become strongly reachable.
oop ProtectionDomainCacheEntry::object_no_keepalive() {
- return RootAccess<ON_PHANTOM_OOP_REF | AS_NO_KEEPALIVE>::oop_load(literal_addr());
+ return literal().peek();
}
oop ProtectionDomainEntry::object_no_keepalive() {
@@ -116,7 +107,7 @@
}
void ProtectionDomainCacheEntry::verify() {
- guarantee(oopDesc::is_oop(object_no_keepalive()), "must be an oop");
+ guarantee(object_no_keepalive() == NULL || oopDesc::is_oop(object_no_keepalive()), "must be an oop");
}
ProtectionDomainCacheEntry* ProtectionDomainCacheTable::get(Handle protection_domain) {
@@ -127,6 +118,8 @@
if (entry == NULL) {
entry = add_entry(index, hash, protection_domain);
}
+ // keep entry alive
+ (void)entry->object();
return entry;
}
@@ -145,7 +138,8 @@
assert(index == index_for(protection_domain), "incorrect index?");
assert(find_entry(index, protection_domain) == NULL, "no double entry");
- ProtectionDomainCacheEntry* p = new_entry(hash, protection_domain);
- Hashtable<oop, mtClass>::add_entry(index, p);
+ ClassLoaderWeakHandle w = ClassLoaderWeakHandle::create(protection_domain);
+ ProtectionDomainCacheEntry* p = new_entry(hash, w);
+ Hashtable<ClassLoaderWeakHandle, mtClass>::add_entry(index, p);
return p;
}
--- a/src/hotspot/share/classfile/protectionDomainCache.hpp Wed Apr 18 14:07:41 2018 -0700
+++ b/src/hotspot/share/classfile/protectionDomainCache.hpp Fri Apr 20 09:05:05 2018 -0700
@@ -26,6 +26,7 @@
#define SHARE_VM_CLASSFILE_PROTECTIONDOMAINCACHE_HPP
#include "oops/oop.hpp"
+#include "oops/weakHandle.hpp"
#include "memory/iterator.hpp"
#include "utilities/hashtable.hpp"
@@ -34,22 +35,18 @@
// to dictionary.hpp pd_set for more information about how protection domain entries
// are used.
// This table is walked during GC, rather than the class loader data graph dictionaries.
-class ProtectionDomainCacheEntry : public HashtableEntry<oop, mtClass> {
+class ProtectionDomainCacheEntry : public HashtableEntry<ClassLoaderWeakHandle, mtClass> {
friend class VMStructs;
public:
oop object();
oop object_no_keepalive();
ProtectionDomainCacheEntry* next() {
- return (ProtectionDomainCacheEntry*)HashtableEntry<oop, mtClass>::next();
+ return (ProtectionDomainCacheEntry*)HashtableEntry<ClassLoaderWeakHandle, mtClass>::next();
}
ProtectionDomainCacheEntry** next_addr() {
- return (ProtectionDomainCacheEntry**)HashtableEntry<oop, mtClass>::next_addr();
- }
-
- void oops_do(OopClosure* f) {
- f->do_oop(literal_addr());
+ return (ProtectionDomainCacheEntry**)HashtableEntry<ClassLoaderWeakHandle, mtClass>::next_addr();
}
void verify();
@@ -64,20 +61,21 @@
// we only need to iterate over this set.
// The amount of different protection domains used is typically magnitudes smaller
// than the number of system dictionary entries (loaded classes).
-class ProtectionDomainCacheTable : public Hashtable<oop, mtClass> {
+class ProtectionDomainCacheTable : public Hashtable<ClassLoaderWeakHandle, mtClass> {
friend class VMStructs;
private:
ProtectionDomainCacheEntry* bucket(int i) const {
- return (ProtectionDomainCacheEntry*) Hashtable<oop, mtClass>::bucket(i);
+ return (ProtectionDomainCacheEntry*) Hashtable<ClassLoaderWeakHandle, mtClass>::bucket(i);
}
// The following method is not MT-safe and must be done under lock.
ProtectionDomainCacheEntry** bucket_addr(int i) {
- return (ProtectionDomainCacheEntry**) Hashtable<oop, mtClass>::bucket_addr(i);
+ return (ProtectionDomainCacheEntry**) Hashtable<ClassLoaderWeakHandle, mtClass>::bucket_addr(i);
}
- ProtectionDomainCacheEntry* new_entry(unsigned int hash, Handle protection_domain) {
- ProtectionDomainCacheEntry* entry = (ProtectionDomainCacheEntry*) Hashtable<oop, mtClass>::new_entry(hash, protection_domain());
+ ProtectionDomainCacheEntry* new_entry(unsigned int hash, ClassLoaderWeakHandle protection_domain) {
+ ProtectionDomainCacheEntry* entry = (ProtectionDomainCacheEntry*)
+ Hashtable<ClassLoaderWeakHandle, mtClass>::new_entry(hash, protection_domain);
return entry;
}
@@ -91,10 +89,7 @@
ProtectionDomainCacheTable(int table_size);
ProtectionDomainCacheEntry* get(Handle protection_domain);
- void unlink(BoolObjectClosure* cl);
-
- // GC support
- void oops_do(OopClosure* f);
+ void unlink();
void print_on(outputStream* st) const;
void verify();
--- a/src/hotspot/share/classfile/resolutionErrors.cpp Wed Apr 18 14:07:41 2018 -0700
+++ b/src/hotspot/share/classfile/resolutionErrors.cpp Fri Apr 20 09:05:05 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -125,9 +125,8 @@
assert(entry->pool() != (ConstantPool*)NULL, "resolution error table is corrupt");
ConstantPool* pool = entry->pool();
assert(pool->pool_holder() != NULL, "Constant pool without a class?");
- ClassLoaderData* loader_data =
- pool->pool_holder()->class_loader_data();
- if (!loader_data->is_unloading()) {
+
+ if (pool->pool_holder()->is_loader_alive()) {
p = entry->next_addr();
} else {
*p = entry->next();
--- a/src/hotspot/share/classfile/systemDictionary.cpp Wed Apr 18 14:07:41 2018 -0700
+++ b/src/hotspot/share/classfile/systemDictionary.cpp Fri Apr 20 09:05:05 2018 -0700
@@ -1831,24 +1831,6 @@
}
-#ifdef ASSERT
-class VerifySDReachableAndLiveClosure : public OopClosure {
-private:
- BoolObjectClosure* _is_alive;
-
- template <class T> void do_oop_work(T* p) {
- oop obj = RawAccess<>::oop_load(p);
- guarantee(_is_alive->do_object_b(obj), "Oop in protection domain cache table must be live");
- }
-
-public:
- VerifySDReachableAndLiveClosure(BoolObjectClosure* is_alive) : OopClosure(), _is_alive(is_alive) { }
-
- virtual void do_oop(oop* p) { do_oop_work(p); }
- virtual void do_oop(narrowOop* p) { do_oop_work(p); }
-};
-#endif
-
// Assumes classes in the SystemDictionary are only unloaded at a safepoint
// Note: anonymous classes are not in the SD.
bool SystemDictionary::do_unloading(BoolObjectClosure* is_alive,
@@ -1865,8 +1847,7 @@
GCTraceTime(Debug, gc, phases) t("ClassLoaderData", gc_timer);
// First, mark for unload all ClassLoaderData referencing a dead class loader.
- unloading_occurred = ClassLoaderDataGraph::do_unloading(is_alive,
- do_cleaning);
+ unloading_occurred = ClassLoaderDataGraph::do_unloading(do_cleaning);
}
if (unloading_occurred) {
@@ -1880,17 +1861,12 @@
// Oops referenced by the protection domain cache table may get unreachable independently
// of the class loader (eg. cached protection domain oops). So we need to
// explicitly unlink them here.
- _pd_cache_table->unlink(is_alive);
-
-#ifdef ASSERT
- VerifySDReachableAndLiveClosure cl(is_alive);
- _pd_cache_table->oops_do(&cl);
-#endif
+ _pd_cache_table->unlink();
}
if (do_cleaning) {
GCTraceTime(Debug, gc, phases) t("ResolvedMethodTable", gc_timer);
- ResolvedMethodTable::unlink(is_alive);
+ ResolvedMethodTable::unlink();
}
return unloading_occurred;
@@ -1906,21 +1882,15 @@
if (strong == weak || !ClassUnloading) {
// Only the protection domain oops contain references into the heap. Iterate
// over all of them.
- _pd_cache_table->oops_do(strong);
vm_weak_oop_storage()->oops_do(strong);
} else {
if (weak != NULL) {
- _pd_cache_table->oops_do(weak);
vm_weak_oop_storage()->oops_do(weak);
}
}
// Visit extra methods
invoke_method_table()->oops_do(strong);
-
- if (weak != NULL) {
- ResolvedMethodTable::oops_do(weak);
- }
}
void SystemDictionary::oops_do(OopClosure* f) {
@@ -1929,15 +1899,9 @@
f->do_oop(&_system_loader_lock_obj);
CDS_ONLY(SystemDictionaryShared::oops_do(f);)
- // Only the protection domain oops contain references into the heap. Iterate
- // over all of them.
- _pd_cache_table->oops_do(f);
-
// Visit extra methods
invoke_method_table()->oops_do(f);
- ResolvedMethodTable::oops_do(f);
-
vm_weak_oop_storage()->oops_do(f);
}
--- a/src/hotspot/share/classfile/systemDictionaryShared.cpp Wed Apr 18 14:07:41 2018 -0700
+++ b/src/hotspot/share/classfile/systemDictionaryShared.cpp Fri Apr 20 09:05:05 2018 -0700
@@ -357,6 +357,14 @@
return pd;
}
+bool SystemDictionaryShared::is_sharing_possible(ClassLoaderData* loader_data) {
+ oop class_loader = loader_data->class_loader();
+ return (class_loader == NULL ||
+ (UseAppCDS && (SystemDictionary::is_system_class_loader(class_loader) ||
+ SystemDictionary::is_platform_class_loader(class_loader)))
+ );
+}
+
// Currently AppCDS only archives classes from the run-time image, the
// -Xbootclasspath/a path, the class path, and the module path.
//
--- a/src/hotspot/share/classfile/systemDictionaryShared.hpp Wed Apr 18 14:07:41 2018 -0700
+++ b/src/hotspot/share/classfile/systemDictionaryShared.hpp Fri Apr 20 09:05:05 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -300,13 +300,7 @@
}
// Check if sharing is supported for the class loader.
- static bool is_sharing_possible(ClassLoaderData* loader_data) {
- oop class_loader = loader_data->class_loader();
- return (class_loader == NULL ||
- (UseAppCDS && (SystemDictionary::is_system_class_loader(class_loader) ||
- SystemDictionary::is_platform_class_loader(class_loader)))
- );
- }
+ static bool is_sharing_possible(ClassLoaderData* loader_data);
static bool is_shared_class_visible_for_classloader(InstanceKlass* ik,
Handle class_loader,
const char* pkg_string,
--- a/src/hotspot/share/code/codeHeapState.cpp Wed Apr 18 14:07:41 2018 -0700
+++ b/src/hotspot/share/code/codeHeapState.cpp Fri Apr 20 09:05:05 2018 -0700
@@ -613,16 +613,22 @@
//---< some sanity checks >---
// Do not assert here, just check, print error message and return.
// This is a diagnostic function. It is not supposed to tear down the VM.
- if ((char*)h < low_bound ) {
+ if ((char*)h < low_bound) {
insane = true; ast->print_cr("Sanity check: HeapBlock @%p below low bound (%p)", (char*)h, low_bound);
}
- if (ix_end >= granules ) {
+ if ((char*)h > (low_bound + res_size)) {
+ insane = true; ast->print_cr("Sanity check: HeapBlock @%p outside reserved range (%p)", (char*)h, low_bound + res_size);
+ }
+ if ((char*)h > (low_bound + size)) {
+ insane = true; ast->print_cr("Sanity check: HeapBlock @%p outside used range (%p)", (char*)h, low_bound + size);
+ }
+ if (ix_end >= granules) {
insane = true; ast->print_cr("Sanity check: end index (%d) out of bounds (" SIZE_FORMAT ")", ix_end, granules);
}
if (size != heap->capacity()) {
insane = true; ast->print_cr("Sanity check: code heap capacity has changed (" SIZE_FORMAT "K to " SIZE_FORMAT "K)", size/(size_t)K, heap->capacity()/(size_t)K);
}
- if (ix_beg > ix_end ) {
+ if (ix_beg > ix_end) {
insane = true; ast->print_cr("Sanity check: end index (%d) lower than begin index (%d)", ix_end, ix_beg);
}
if (insane) {
@@ -988,6 +994,11 @@
ast->print_cr(" deadSpace = " SIZE_FORMAT_W(8) "k, nBlocks_dead = %6d, %10.3f%% of capacity, %10.3f%% of max_capacity", deadSpace/(size_t)K, nBlocks_dead, (100.0*deadSpace)/size, (100.0*deadSpace)/res_size);
ast->print_cr(" stubSpace = " SIZE_FORMAT_W(8) "k, nBlocks_stub = %6d, %10.3f%% of capacity, %10.3f%% of max_capacity", stubSpace/(size_t)K, nBlocks_stub, (100.0*stubSpace)/size, (100.0*stubSpace)/res_size);
ast->print_cr("ZombieBlocks = %8d. These are HeapBlocks which could not be identified as CodeBlobs.", nBlocks_zomb);
+ ast->cr();
+ ast->print_cr("Segment start = " INTPTR_FORMAT ", used space = " SIZE_FORMAT_W(8)"k", p2i(low_bound), size/K);
+ ast->print_cr("Segment end (used) = " INTPTR_FORMAT ", remaining space = " SIZE_FORMAT_W(8)"k", p2i(low_bound) + size, (res_size - size)/K);
+ ast->print_cr("Segment end (reserved) = " INTPTR_FORMAT ", reserved space = " SIZE_FORMAT_W(8)"k", p2i(low_bound) + res_size, res_size/K);
+ ast->cr();
ast->print_cr("latest allocated compilation id = %d", latest_compilation_id);
ast->print_cr("highest observed compilation id = %d", highest_compilation_id);
ast->print_cr("Building TopSizeList iterations = %ld", total_iterations);
@@ -1218,14 +1229,14 @@
blob_name = this_blob->name();
nm = this_blob->as_nmethod_or_null();
//---< blob address >---
- ast->print("%p", this_blob);
+ ast->print(INTPTR_FORMAT, p2i(this_blob));
ast->fill_to(19);
//---< blob offset from CodeHeap begin >---
ast->print("(+" PTR32_FORMAT ")", (unsigned int)((char*)this_blob-low_bound));
ast->fill_to(33);
} else {
//---< block address >---
- ast->print("%p", TopSizeArray[i].start);
+ ast->print(INTPTR_FORMAT, p2i(TopSizeArray[i].start));
ast->fill_to(19);
//---< block offset from CodeHeap begin >---
ast->print("(+" PTR32_FORMAT ")", (unsigned int)((char*)TopSizeArray[i].start-low_bound));
@@ -1404,7 +1415,7 @@
unsigned int ix = 0;
for (ix = 0; ix < alloc_freeBlocks-1; ix++) {
- ast->print("%p: Len[%4d] = " HEX32_FORMAT ",", FreeArray[ix].start, ix, FreeArray[ix].len);
+ ast->print(INTPTR_FORMAT ": Len[%4d] = " HEX32_FORMAT ",", p2i(FreeArray[ix].start), ix, FreeArray[ix].len);
ast->fill_to(38);
ast->print("Gap[%4d..%4d]: " HEX32_FORMAT " bytes,", ix, ix+1, FreeArray[ix].gap);
ast->fill_to(71);
@@ -1414,7 +1425,7 @@
}
STRINGSTREAM_FLUSH_LOCKED("\n")
}
- ast->print_cr("%p: Len[%4d] = " HEX32_FORMAT, FreeArray[ix].start, ix, FreeArray[ix].len);
+ ast->print_cr(INTPTR_FORMAT ": Len[%4d] = " HEX32_FORMAT, p2i(FreeArray[ix].start), ix, FreeArray[ix].len);
STRINGSTREAM_FLUSH_LOCKED("\n\n")
}
@@ -2039,10 +2050,16 @@
}
+#define JDK8200450_REMEDY
+#define JDK8200450_TRACE
void CodeHeapState::print_names(outputStream* out, CodeHeap* heap) {
if (!initialization_complete) {
return;
}
+#ifdef JDK8200450_TRACE
+ out->print_cr("print_names() entered for heap @ " INTPTR_FORMAT, p2i(heap));
+ out->flush();
+#endif
const char* heapName = get_heapName(heap);
get_HeapStatGlobals(out, heapName);
@@ -2057,7 +2074,7 @@
CodeBlob* last_blob = NULL;
bool name_in_addr_range = true;
- //---< print at least 128K per block >---
+ //---< print at least 128K per block (i.e. between headers) >---
if (granules_per_line*granule_size < 128*K) {
granules_per_line = (unsigned int)((128*K)/granule_size);
}
@@ -2067,7 +2084,7 @@
" Due to the living nature of the code heap and because the CodeCache_lock\n"
" is not continuously held, the displayed name might be wrong or no name\n"
" might be found at all. The likelihood for that to happen increases\n"
- " over time passed between analysis and print step.\n");
+ " over time passed between aggregtion and print steps.\n");
STRINGSTREAM_FLUSH_LOCKED("")
for (unsigned int ix = 0; ix < alloc_granules; ix++) {
@@ -2078,23 +2095,69 @@
}
name_in_addr_range = false;
+ size_t end_ix = (ix+granules_per_line <= alloc_granules) ? ix+granules_per_line : alloc_granules;
ast->cr();
ast->print_cr("--------------------------------------------------------------------");
- ast->print_cr("Address range [%p,%p), " SIZE_FORMAT "k", low_bound+ix*granule_size, low_bound+(ix+granules_per_line)*granule_size, granules_per_line*granule_size/(size_t)K);
+ ast->print_cr("Address range [" INTPTR_FORMAT "," INTPTR_FORMAT "), " SIZE_FORMAT "k", p2i(low_bound+ix*granule_size), p2i(low_bound + end_ix*granule_size), (end_ix - ix)*granule_size/(size_t)K);
ast->print_cr("--------------------------------------------------------------------");
STRINGSTREAM_FLUSH_LOCKED("")
}
// Only check granule if it contains at least one blob.
unsigned int nBlobs = StatArray[ix].t1_count + StatArray[ix].t2_count + StatArray[ix].tx_count +
StatArray[ix].stub_count + StatArray[ix].dead_count;
- if (nBlobs > 0 ) {
+#ifdef JDK8200450_REMEDY
+ if (nBlobs > 0 )
+#endif
+ {
for (unsigned int is = 0; is < granule_size; is+=(unsigned int)seg_size) {
// heap->find_start() is safe. Only working with _segmap. Returns NULL or void*. Returned CodeBlob may be uninitialized.
CodeBlob* this_blob = (CodeBlob *)(heap->find_start(low_bound+ix*granule_size+is));
- bool blob_initialized = (this_blob != NULL) &&
- ((char*)this_blob + this_blob->header_size() == (char*)(this_blob->relocation_begin())) &&
- ((char*)this_blob + CodeBlob::align_code_offset(this_blob->header_size() + this_blob->relocation_size()) == (char*)(this_blob->content_begin()));
+#ifndef JDK8200450_REMEDY
+ bool blob_initialized = (this_blob != NULL)
+#else
+#ifndef JDK8200450_TRACE
+ bool blob_initialized = (this_blob != NULL) && (this_blob->header_size() >= 0) && (this_blob->relocation_size() >= 0) &&
+ ((address)this_blob + this_blob->header_size() == (address)(this_blob->relocation_begin())) &&
+ ((address)this_blob + CodeBlob::align_code_offset(this_blob->header_size() + this_blob->relocation_size()) == (address)(this_blob->content_begin()) &&
+ is_readable_pointer((address)(this_blob->relocation_begin()) &&
+ is_readable_pointer(this_blob->content_begin());
+#else
+ int hdr_size = 0;
+ int reloc_size = 0;
+ address reloc_begin = NULL;
+ address cntnt_begin = NULL;
+ if (this_blob != NULL) {
+ hdr_size = this_blob->header_size();
+ reloc_size = this_blob->relocation_size();
+ reloc_begin = (address)(this_blob->relocation_begin());
+ cntnt_begin = this_blob->content_begin();
+ }
+ bool blob_initialized = (this_blob != NULL) && (hdr_size >= 0) && (reloc_size >= 0) &&
+ ((address)this_blob + hdr_size == reloc_begin) &&
+ ((address)this_blob + CodeBlob::align_code_offset(hdr_size + reloc_size) == cntnt_begin) &&
+ is_readable_pointer(reloc_begin) &&
+ is_readable_pointer(cntnt_begin);
+#endif
+#endif
if (blob_initialized && (this_blob != last_blob)) {
+ last_blob = this_blob;
+
+ //---< get type and name >---
+ blobType cbType = noType;
+ if (segment_granules) {
+ cbType = (blobType)StatArray[ix].type;
+ } else {
+ cbType = get_cbType(this_blob); // Is this here safe?
+ }
+ // this_blob->name() could return NULL if no name is given to CTOR. Inlined, maybe invisible on stack
+ const char* blob_name = this_blob->name();
+#ifdef JDK8200450_REMEDY
+ if (blob_name == NULL) {
+ blob_name = "<unavailable>";
+ }
+#endif
+
+ //---< print table header for new print range >---
if (!name_in_addr_range) {
name_in_addr_range = true;
ast->fill_to(51);
@@ -2102,32 +2165,34 @@
ast->fill_to(61);
ast->print_cr("%6s", "method");
ast->print_cr("%18s %13s %17s %9s %5s %18s %s", "Addr(module) ", "offset", "size", " type lvl", " temp", "blobType ", "Name");
+ STRINGSTREAM_FLUSH_LOCKED("")
}
- //---< Print blobTypeName as recorded during analysis >---
- ast->print("%p", this_blob);
+ //---< print line prefix (address and offset from CodeHeap start) >---
+ ast->print(INTPTR_FORMAT, p2i(this_blob));
ast->fill_to(19);
ast->print("(+" PTR32_FORMAT ")", (unsigned int)((char*)this_blob-low_bound));
ast->fill_to(33);
- //---< print size, name, and signature (for nMethods) >---
- // this_blob->name() could return NULL if no name is given to CTOR. Inlined, maybe not visible on stack
- const char* blob_name = this_blob->name();
- if (blob_name == 0) {
- blob_name = "<unavailable>";
- }
- // this_blob->as_nmethod_or_null() is safe. Inlined, maybe not visible on stack.
- nmethod* nm = this_blob->as_nmethod_or_null();
- blobType cbType = noType;
- if (segment_granules) {
- cbType = (blobType)StatArray[ix].type;
- } else {
- cbType = get_cbType(this_blob);
- }
- if ((nm != NULL) && (nm->method() != NULL)) {
+#ifdef JDK8200450_TRACE
+ STRINGSTREAM_FLUSH_LOCKED("") // Remove before push!!!
+#endif
+
+ // this_blob->as_nmethod_or_null() is safe. Inlined, maybe invisible on stack.
+ nmethod* nm = this_blob->as_nmethod_or_null();
+ Method* method = (nm == NULL) ? NULL : nm->method(); // may be uninitialized, i.e. != NULL, but invalid
+#ifdef JDK8200450_REMEDY
+ if ((nm != NULL) && (method != NULL) && is_readable_pointer(method) && is_readable_pointer(method->constants())) {
+#else
+ if ((nm != NULL) && (method != NULL)) {
+#endif
ResourceMark rm;
+ //---< collect all data to locals as quickly as possible >---
+ unsigned int total_size = nm->total_size();
+ int hotness = nm->hotness_counter();
+ bool nm_zombie = nm->is_zombie();
+ bool get_name = nm->is_in_use() || nm->is_not_entrant();
//---< nMethod size in hex >---
- unsigned int total_size = nm->total_size();
ast->print(PTR32_FORMAT, total_size);
ast->print("(" SIZE_FORMAT_W(4) "K)", total_size/K);
//---< compiler information >---
@@ -2135,21 +2200,36 @@
ast->print("%5s %3d", compTypeName[StatArray[ix].compiler], StatArray[ix].level);
//---< method temperature >---
ast->fill_to(62);
- ast->print("%5d", nm->hotness_counter());
+ ast->print("%5d", hotness);
//---< name and signature >---
ast->fill_to(62+6);
ast->print("%s", blobTypeName[cbType]);
ast->fill_to(82+6);
- if (nm->is_in_use()) {
- blob_name = nm->method()->name_and_sig_as_C_string();
- }
- if (nm->is_not_entrant()) {
- blob_name = nm->method()->name_and_sig_as_C_string();
- }
- if (nm->is_zombie()) {
+ if (nm_zombie) {
ast->print("%14s", " zombie method");
}
- ast->print("%s", blob_name);
+
+#ifdef JDK8200450_TRACE
+ STRINGSTREAM_FLUSH_LOCKED("") // Remove before push!!!
+#endif
+
+ if (get_name) {
+#ifdef JDK8200450_REMEDY
+ Symbol* methName = method->name();
+ const char* methNameS = (methName == NULL) ? NULL : methName->as_C_string();
+ methNameS = (methNameS == NULL) ? "<method name unavailable>" : methNameS;
+ Symbol* methSig = method->signature();
+ const char* methSigS = (methSig == NULL) ? NULL : methSig->as_C_string();
+ methSigS = (methSigS == NULL) ? "<method signature unavailable>" : methSigS;
+ ast->print("%s", methNameS);
+ ast->print("%s", methSigS);
+#else
+ blob_name = method->name_and_sig_as_C_string();
+ ast->print("%s", blob_name);
+#endif
+ } else {
+ ast->print("%s", blob_name);
+ }
} else {
ast->fill_to(62+6);
ast->print("%s", blobTypeName[cbType]);
@@ -2157,12 +2237,48 @@
ast->print("%s", blob_name);
}
STRINGSTREAM_FLUSH_LOCKED("\n")
+#ifdef JDK8200450_TRACE
+ if ((nm != NULL) && (method != NULL) && !(is_readable_pointer(method) && is_readable_pointer(method->constants()))) {
+ ast->print("Potential CodeHeap State Analytics issue found.\n");
+ if (is_readable_pointer(method)) {
+ ast->print(" Issue would have been detected by is_readable_pointer(" INTPTR_FORMAT "(method->constants())) check.\n", p2i(method->constants()));
+ } else {
+ ast->print(" Issue would have been detected by is_readable_pointer(" INTPTR_FORMAT "(method)) check.\n", p2i(method));
+ }
+ STRINGSTREAM_FLUSH_LOCKED("\n")
+ }
+#endif
+ } else if (!blob_initialized && (this_blob != last_blob) && (this_blob != NULL)) {
last_blob = this_blob;
- } else if (!blob_initialized && (this_blob != NULL)) {
- last_blob = this_blob;
+#ifdef JDK8200450_TRACE
+ ast->print("Potential CodeHeap State Analytics issue found.\n");
+ if (nBlobs == 0) {
+ ast->print(" Issue would have been detected by (nBlobs > 0) check.\n");
+ } else {
+ if (!((address)this_blob + hdr_size == reloc_begin)) {
+ ast->print(" Issue would have been detected by (this(" INTPTR_FORMAT ") + header(%d) == relocation_begin(" INTPTR_FORMAT ")) check.\n", p2i(this_blob), hdr_size, p2i(reloc_begin));
+ }
+ if (!((address)this_blob + CodeBlob::align_code_offset(hdr_size + reloc_size) == cntnt_begin)) {
+ ast->print(" Issue would have been detected by (this(" INTPTR_FORMAT ") + header(%d) + relocation(%d) == content_begin(" INTPTR_FORMAT ")) check.\n", p2i(this_blob), hdr_size, reloc_size, p2i(cntnt_begin));
+ }
+ if (hdr_size != this_blob->header_size()) {
+ ast->print(" header_size meanwhile changed from %d to %d\n", hdr_size, this_blob->header_size());
+ }
+ if (reloc_size != this_blob->relocation_size()) {
+ ast->print(" relocation_size meanwhile changed from %d to %d\n", reloc_size, this_blob->relocation_size());
+ }
+ if (reloc_begin != (address)(this_blob->relocation_begin())) {
+ ast->print(" relocation_begin meanwhile changed from " INTPTR_FORMAT " to " INTPTR_FORMAT "\n", p2i(reloc_begin), p2i(this_blob->relocation_begin()));
+ }
+ if (cntnt_begin != this_blob->content_begin()) {
+ ast->print(" relocation_begin meanwhile changed from " INTPTR_FORMAT " to " INTPTR_FORMAT "\n", p2i(cntnt_begin), p2i(this_blob->content_begin()));
+ }
+ }
+ STRINGSTREAM_FLUSH_LOCKED("\n")
+#endif
}
}
- }
+ } // nBlobs > 0
}
STRINGSTREAM_FLUSH_LOCKED("\n\n")
}
@@ -2287,7 +2403,7 @@
ast->cr();
assert(out == ast, "must use the same stream!");
- ast->print("%p", low_bound + ix*granule_size);
+ ast->print(INTPTR_FORMAT, p2i(low_bound + ix*granule_size));
ast->fill_to(19);
ast->print("(+" PTR32_FORMAT "): |", (unsigned int)(ix*granule_size));
}
@@ -2307,7 +2423,7 @@
ast->reset();
}
- ast->print("%p", low_bound + ix*granule_size);
+ ast->print(INTPTR_FORMAT, p2i(low_bound + ix*granule_size));
ast->fill_to(19);
ast->print("(+" PTR32_FORMAT "): |", (unsigned int)(ix*granule_size));
}
@@ -2336,3 +2452,17 @@
}
return noType;
}
+
+// Check if pointer can be read from (4-byte read access).
+// Helps to prove validity of a not-NULL pointer.
+// Returns true in very early stages of VM life when stub is not yet generated.
+#define SAFEFETCH_DEFAULT true
+bool CodeHeapState::is_readable_pointer(const void* p) {
+ if (!CanUseSafeFetch32()) {
+ return SAFEFETCH_DEFAULT;
+ }
+ int* const aligned = (int*) align_down((intptr_t)p, 4);
+ int cafebabe = 0xcafebabe; // tester value 1
+ int deadbeef = 0xdeadbeef; // tester value 2
+ return (SafeFetch32(aligned, cafebabe) != cafebabe) || (SafeFetch32(aligned, deadbeef) != deadbeef);
+}
--- a/src/hotspot/share/code/codeHeapState.hpp Wed Apr 18 14:07:41 2018 -0700
+++ b/src/hotspot/share/code/codeHeapState.hpp Fri Apr 20 09:05:05 2018 -0700
@@ -93,6 +93,7 @@
static void print_line_delim(outputStream* out, bufferedStream *sst, char* low_bound, unsigned int ix, unsigned int gpl);
static void print_line_delim(outputStream* out, outputStream *sst, char* low_bound, unsigned int ix, unsigned int gpl);
static blobType get_cbType(CodeBlob* cb);
+ static bool is_readable_pointer(const void* p);
public:
static void discard(outputStream* out, CodeHeap* heap);
--- a/src/hotspot/share/code/compiledMethod.cpp Wed Apr 18 14:07:41 2018 -0700
+++ b/src/hotspot/share/code/compiledMethod.cpp Fri Apr 20 09:05:05 2018 -0700
@@ -99,7 +99,7 @@
release_set_exception_cache(new_entry);
}
-void CompiledMethod::clean_exception_cache(BoolObjectClosure* is_alive) {
+void CompiledMethod::clean_exception_cache() {
ExceptionCache* prev = NULL;
ExceptionCache* curr = exception_cache();
@@ -107,7 +107,7 @@
ExceptionCache* next = curr->next();
Klass* ex_klass = curr->exception_type();
- if (ex_klass != NULL && !ex_klass->is_loader_alive(is_alive)) {
+ if (ex_klass != NULL && !ex_klass->is_loader_alive()) {
if (prev == NULL) {
set_exception_cache(next);
} else {
@@ -369,56 +369,42 @@
}
#ifdef ASSERT
-
-class CheckClass : AllStatic {
- static BoolObjectClosure* _is_alive;
-
- // Check class_loader is alive for this bit of metadata.
- static void check_class(Metadata* md) {
- Klass* klass = NULL;
- if (md->is_klass()) {
- klass = ((Klass*)md);
- } else if (md->is_method()) {
- klass = ((Method*)md)->method_holder();
- } else if (md->is_methodData()) {
- klass = ((MethodData*)md)->method()->method_holder();
- } else {
- md->print();
- ShouldNotReachHere();
- }
- assert(klass->is_loader_alive(_is_alive), "must be alive");
- }
- public:
- static void do_check_class(BoolObjectClosure* is_alive, CompiledMethod* nm) {
- assert(SafepointSynchronize::is_at_safepoint(), "this is only ok at safepoint");
- _is_alive = is_alive;
- nm->metadata_do(check_class);
- }
-};
-
-// This is called during a safepoint so can use static data
-BoolObjectClosure* CheckClass::_is_alive = NULL;
+// Check class_loader is alive for this bit of metadata.
+static void check_class(Metadata* md) {
+ Klass* klass = NULL;
+ if (md->is_klass()) {
+ klass = ((Klass*)md);
+ } else if (md->is_method()) {
+ klass = ((Method*)md)->method_holder();
+ } else if (md->is_methodData()) {
+ klass = ((MethodData*)md)->method()->method_holder();
+ } else {
+ md->print();
+ ShouldNotReachHere();
+ }
+ assert(klass->is_loader_alive(), "must be alive");
+}
#endif // ASSERT
-void CompiledMethod::clean_ic_if_metadata_is_dead(CompiledIC *ic, BoolObjectClosure *is_alive) {
+void CompiledMethod::clean_ic_if_metadata_is_dead(CompiledIC *ic) {
if (ic->is_icholder_call()) {
// The only exception is compiledICHolder oops which may
// yet be marked below. (We check this further below).
CompiledICHolder* cichk_oop = ic->cached_icholder();
- if (cichk_oop->is_loader_alive(is_alive)) {
+ if (cichk_oop->is_loader_alive()) {
return;
}
} else {
Metadata* ic_oop = ic->cached_metadata();
if (ic_oop != NULL) {
if (ic_oop->is_klass()) {
- if (((Klass*)ic_oop)->is_loader_alive(is_alive)) {
+ if (((Klass*)ic_oop)->is_loader_alive()) {
return;
}
} else if (ic_oop->is_method()) {
- if (((Method*)ic_oop)->method_holder()->is_loader_alive(is_alive)) {
+ if (((Method*)ic_oop)->method_holder()->is_loader_alive()) {
return;
}
} else {
@@ -453,7 +439,7 @@
// all strong references alive. Any weak references should have been
// cleared as well. Visit all the metadata and ensure that it's
// really alive.
-void CompiledMethod::verify_metadata_loaders(address low_boundary, BoolObjectClosure* is_alive) {
+void CompiledMethod::verify_metadata_loaders(address low_boundary) {
#ifdef ASSERT
RelocIterator iter(this, low_boundary);
while (iter.next()) {
@@ -483,7 +469,7 @@
}
}
// Check that the metadata embedded in the nmethod is alive
- CheckClass::do_check_class(is_alive, this);
+ metadata_do(check_class);
#endif
}
@@ -518,7 +504,7 @@
}
// Exception cache
- clean_exception_cache(is_alive);
+ clean_exception_cache();
// If class unloading occurred we first iterate over all inline caches and
// clear ICs where the cached oop is referring to an unloaded klass or method.
@@ -529,7 +515,7 @@
while(iter.next()) {
if (iter.type() == relocInfo::virtual_call_type) {
CompiledIC *ic = CompiledIC_at(&iter);
- clean_ic_if_metadata_is_dead(ic, is_alive);
+ clean_ic_if_metadata_is_dead(ic);
}
}
}
@@ -545,7 +531,7 @@
#endif
// Ensure that all metadata is still alive
- verify_metadata_loaders(low_boundary, is_alive);
+ verify_metadata_loaders(low_boundary);
}
template <class CompiledICorStaticCall>
@@ -606,7 +592,7 @@
}
// Exception cache
- clean_exception_cache(is_alive);
+ clean_exception_cache();
bool postponed = false;
@@ -619,7 +605,7 @@
if (unloading_occurred) {
// If class unloading occurred we first iterate over all inline caches and
// clear ICs where the cached oop is referring to an unloaded klass or method.
- clean_ic_if_metadata_is_dead(CompiledIC_at(&iter), is_alive);
+ clean_ic_if_metadata_is_dead(CompiledIC_at(&iter));
}
postponed |= clean_if_nmethod_is_unloaded(CompiledIC_at(&iter), is_alive, this);
@@ -656,7 +642,7 @@
#endif
// Ensure that all metadata is still alive
- verify_metadata_loaders(low_boundary, is_alive);
+ verify_metadata_loaders(low_boundary);
return postponed;
}
--- a/src/hotspot/share/code/compiledMethod.hpp Wed Apr 18 14:07:41 2018 -0700
+++ b/src/hotspot/share/code/compiledMethod.hpp Fri Apr 20 09:05:05 2018 -0700
@@ -295,7 +295,7 @@
void release_set_exception_cache(ExceptionCache *ec);
address handler_for_exception_and_pc(Handle exception, address pc);
void add_handler_for_exception_and_pc(Handle exception, address pc, address handler);
- void clean_exception_cache(BoolObjectClosure* is_alive);
+ void clean_exception_cache();
void add_exception_cache_entry(ExceptionCache* new_entry);
ExceptionCache* exception_cache_entry_for_exception(Handle exception);
@@ -364,10 +364,10 @@
void set_unloading_next(CompiledMethod* next) { _unloading_next = next; }
CompiledMethod* unloading_next() { return _unloading_next; }
- void static clean_ic_if_metadata_is_dead(CompiledIC *ic, BoolObjectClosure *is_alive);
+ void static clean_ic_if_metadata_is_dead(CompiledIC *ic);
// Check that all metadata is still alive
- void verify_metadata_loaders(address low_boundary, BoolObjectClosure* is_alive);
+ void verify_metadata_loaders(address low_boundary);
virtual void do_unloading(BoolObjectClosure* is_alive, bool unloading_occurred);
// The parallel versions are used by G1.
--- a/src/hotspot/share/code/nmethod.cpp Wed Apr 18 14:07:41 2018 -0700
+++ b/src/hotspot/share/code/nmethod.cpp Fri Apr 20 09:05:05 2018 -0700
@@ -1365,7 +1365,7 @@
}
// During GC the is_alive closure is non-NULL, and is used to
// determine liveness of dependees that need to be updated.
- if (is_alive == NULL || klass->is_loader_alive(is_alive)) {
+ if (is_alive == NULL || klass->is_loader_alive()) {
// The GC defers deletion of this entry, since there might be multiple threads
// iterating over the _dependencies graph. Other call paths are single-threaded
// and may delete it immediately.
--- a/src/hotspot/share/gc/cms/cmsOopClosures.hpp Wed Apr 18 14:07:41 2018 -0700
+++ b/src/hotspot/share/gc/cms/cmsOopClosures.hpp Fri Apr 20 09:05:05 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2007, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -113,7 +113,7 @@
public:
PushAndMarkClosure(CMSCollector* collector,
MemRegion span,
- ReferenceProcessor* rp,
+ ReferenceDiscoverer* rd,
CMSBitMap* bit_map,
CMSBitMap* mod_union_table,
CMSMarkStack* mark_stack,
@@ -141,7 +141,7 @@
public:
ParPushAndMarkClosure(CMSCollector* collector,
MemRegion span,
- ReferenceProcessor* rp,
+ ReferenceDiscoverer* rd,
CMSBitMap* bit_map,
OopTaskQueue* work_queue);
virtual void do_oop(oop* p);
@@ -166,7 +166,7 @@
DO_OOP_WORK_DEFN
public:
MarkRefsIntoAndScanClosure(MemRegion span,
- ReferenceProcessor* rp,
+ ReferenceDiscoverer* rd,
CMSBitMap* bit_map,
CMSBitMap* mod_union_table,
CMSMarkStack* mark_stack,
@@ -204,7 +204,7 @@
public:
ParMarkRefsIntoAndScanClosure(CMSCollector* collector,
MemRegion span,
- ReferenceProcessor* rp,
+ ReferenceDiscoverer* rd,
CMSBitMap* bit_map,
OopTaskQueue* work_queue);
virtual void do_oop(oop* p);
--- a/src/hotspot/share/gc/cms/concurrentMarkSweepGeneration.cpp Wed Apr 18 14:07:41 2018 -0700
+++ b/src/hotspot/share/gc/cms/concurrentMarkSweepGeneration.cpp Fri Apr 20 09:05:05 2018 -0700
@@ -5244,7 +5244,7 @@
CodeCache::do_unloading(&_is_alive_closure, purged_class);
// Prune dead klasses from subklass/sibling/implementor lists.
- Klass::clean_weak_klass_links(&_is_alive_closure);
+ Klass::clean_weak_klass_links();
}
{
@@ -5825,7 +5825,7 @@
_span(span),
_bitMap(bitMap)
{
- assert(ref_processor() == NULL, "deliberately left NULL");
+ assert(ref_discoverer() == NULL, "deliberately left NULL");
assert(_bitMap->covers(_span), "_bitMap/_span mismatch");
}
@@ -5847,7 +5847,7 @@
_span(span),
_bitMap(bitMap)
{
- assert(ref_processor() == NULL, "deliberately left NULL");
+ assert(ref_discoverer() == NULL, "deliberately left NULL");
assert(_bitMap->covers(_span), "_bitMap/_span mismatch");
}
@@ -5871,7 +5871,7 @@
_verification_bm(verification_bm),
_cms_bm(cms_bm)
{
- assert(ref_processor() == NULL, "deliberately left NULL");
+ assert(ref_discoverer() == NULL, "deliberately left NULL");
assert(_verification_bm->covers(_span), "_verification_bm/_span mismatch");
}
@@ -5900,7 +5900,7 @@
//////////////////////////////////////////////////
MarkRefsIntoAndScanClosure::MarkRefsIntoAndScanClosure(MemRegion span,
- ReferenceProcessor* rp,
+ ReferenceDiscoverer* rd,
CMSBitMap* bit_map,
CMSBitMap* mod_union_table,
CMSMarkStack* mark_stack,
@@ -5911,15 +5911,15 @@
_span(span),
_bit_map(bit_map),
_mark_stack(mark_stack),
- _pushAndMarkClosure(collector, span, rp, bit_map, mod_union_table,
+ _pushAndMarkClosure(collector, span, rd, bit_map, mod_union_table,
mark_stack, concurrent_precleaning),
_yield(should_yield),
_concurrent_precleaning(concurrent_precleaning),
_freelistLock(NULL)
{
// FIXME: Should initialize in base class constructor.
- assert(rp != NULL, "ref_processor shouldn't be NULL");
- set_ref_processor_internal(rp);
+ assert(rd != NULL, "ref_discoverer shouldn't be NULL");
+ set_ref_discoverer_internal(rd);
}
// This closure is used to mark refs into the CMS generation at the
@@ -6004,18 +6004,18 @@
// MarkRefsIntoAndScanClosure
///////////////////////////////////////////////////////////
ParMarkRefsIntoAndScanClosure::ParMarkRefsIntoAndScanClosure(
- CMSCollector* collector, MemRegion span, ReferenceProcessor* rp,
+ CMSCollector* collector, MemRegion span, ReferenceDiscoverer* rd,
CMSBitMap* bit_map, OopTaskQueue* work_queue):
_span(span),
_bit_map(bit_map),
_work_queue(work_queue),
_low_water_mark(MIN2((work_queue->max_elems()/4),
((uint)CMSWorkQueueDrainThreshold * ParallelGCThreads))),
- _parPushAndMarkClosure(collector, span, rp, bit_map, work_queue)
+ _parPushAndMarkClosure(collector, span, rd, bit_map, work_queue)
{
// FIXME: Should initialize in base class constructor.
- assert(rp != NULL, "ref_processor shouldn't be NULL");
- set_ref_processor_internal(rp);
+ assert(rd != NULL, "ref_discoverer shouldn't be NULL");
+ set_ref_discoverer_internal(rd);
}
// This closure is used to mark refs into the CMS generation at the
@@ -6842,12 +6842,12 @@
PushAndMarkClosure::PushAndMarkClosure(CMSCollector* collector,
MemRegion span,
- ReferenceProcessor* rp,
+ ReferenceDiscoverer* rd,
CMSBitMap* bit_map,
CMSBitMap* mod_union_table,
CMSMarkStack* mark_stack,
bool concurrent_precleaning):
- MetadataAwareOopClosure(rp),
+ MetadataAwareOopClosure(rd),
_collector(collector),
_span(span),
_bit_map(bit_map),
@@ -6855,7 +6855,7 @@
_mark_stack(mark_stack),
_concurrent_precleaning(concurrent_precleaning)
{
- assert(ref_processor() != NULL, "ref_processor shouldn't be NULL");
+ assert(ref_discoverer() != NULL, "ref_discoverer shouldn't be NULL");
}
// Grey object rescan during pre-cleaning and second checkpoint phases --
@@ -6916,16 +6916,16 @@
ParPushAndMarkClosure::ParPushAndMarkClosure(CMSCollector* collector,
MemRegion span,
- ReferenceProcessor* rp,
+ ReferenceDiscoverer* rd,
CMSBitMap* bit_map,
OopTaskQueue* work_queue):
- MetadataAwareOopClosure(rp),
+ MetadataAwareOopClosure(rd),
_collector(collector),
_span(span),
_bit_map(bit_map),
_work_queue(work_queue)
{
- assert(ref_processor() != NULL, "ref_processor shouldn't be NULL");
+ assert(ref_discoverer() != NULL, "ref_discoverer shouldn't be NULL");
}
void PushAndMarkClosure::do_oop(oop* p) { PushAndMarkClosure::do_oop_work(p); }
--- a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp Wed Apr 18 14:07:41 2018 -0700
+++ b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp Fri Apr 20 09:05:05 2018 -0700
@@ -3125,7 +3125,7 @@
ReferenceProcessor* rp = _g1h->ref_processor_stw();
G1ParScanThreadState* pss = _pss->state_for_worker(worker_id);
- pss->set_ref_processor(rp);
+ pss->set_ref_discoverer(rp);
double start_strong_roots_sec = os::elapsedTime();
@@ -3457,13 +3457,11 @@
Monitor* G1CodeCacheUnloadingTask::_lock = new Monitor(Mutex::leaf, "Code Cache Unload lock", false, Monitor::_safepoint_check_never);
class G1KlassCleaningTask : public StackObj {
- BoolObjectClosure* _is_alive;
volatile int _clean_klass_tree_claimed;
ClassLoaderDataGraphKlassIteratorAtomic _klass_iterator;
public:
- G1KlassCleaningTask(BoolObjectClosure* is_alive) :
- _is_alive(is_alive),
+ G1KlassCleaningTask() :
_clean_klass_tree_claimed(0),
_klass_iterator() {
}
@@ -3490,7 +3488,7 @@
public:
void clean_klass(InstanceKlass* ik) {
- ik->clean_weak_instanceklass_links(_is_alive);
+ ik->clean_weak_instanceklass_links();
}
void work() {
@@ -3498,7 +3496,7 @@
// One worker will clean the subklass/sibling klass tree.
if (claim_clean_klass_tree_task()) {
- Klass::clean_subklass_tree(_is_alive);
+ Klass::clean_subklass_tree();
}
// All workers will help cleaning the classes,
@@ -3510,11 +3508,10 @@
};
class G1ResolvedMethodCleaningTask : public StackObj {
- BoolObjectClosure* _is_alive;
volatile int _resolved_method_task_claimed;
public:
- G1ResolvedMethodCleaningTask(BoolObjectClosure* is_alive) :
- _is_alive(is_alive), _resolved_method_task_claimed(0) {}
+ G1ResolvedMethodCleaningTask() :
+ _resolved_method_task_claimed(0) {}
bool claim_resolved_method_task() {
if (_resolved_method_task_claimed) {
@@ -3526,7 +3523,7 @@
// These aren't big, one thread can do it all.
void work() {
if (claim_resolved_method_task()) {
- ResolvedMethodTable::unlink(_is_alive);
+ ResolvedMethodTable::unlink();
}
}
};
@@ -3546,8 +3543,8 @@
AbstractGangTask("Parallel Cleaning"),
_string_symbol_task(is_alive, true, true, G1StringDedup::is_enabled()),
_code_cache_task(num_workers, is_alive, unloading_occurred),
- _klass_cleaning_task(is_alive),
- _resolved_method_cleaning_task(is_alive) {
+ _klass_cleaning_task(),
+ _resolved_method_cleaning_task() {
}
// The parallel work done by all worker threads.
@@ -3823,7 +3820,7 @@
G1STWIsAliveClosure is_alive(_g1h);
G1ParScanThreadState* pss = _pss->state_for_worker(worker_id);
- pss->set_ref_processor(NULL);
+ pss->set_ref_discoverer(NULL);
// Keep alive closure.
G1CopyingKeepAliveClosure keep_alive(_g1h, pss->closures()->raw_strong_oops(), pss);
@@ -3915,7 +3912,7 @@
HandleMark hm;
G1ParScanThreadState* pss = _pss->state_for_worker(worker_id);
- pss->set_ref_processor(NULL);
+ pss->set_ref_discoverer(NULL);
assert(pss->queue_is_empty(), "both queue and overflow should be empty");
// Is alive closure
@@ -4021,7 +4018,7 @@
// Use only a single queue for this PSS.
G1ParScanThreadState* pss = per_thread_states->state_for_worker(0);
- pss->set_ref_processor(NULL);
+ pss->set_ref_discoverer(NULL);
assert(pss->queue_is_empty(), "pre-condition");
// Keep alive closure.
--- a/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp Wed Apr 18 14:07:41 2018 -0700
+++ b/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp Fri Apr 20 09:05:05 2018 -0700
@@ -1413,14 +1413,13 @@
class G1CMKeepAliveAndDrainClosure : public OopClosure {
G1ConcurrentMark* _cm;
G1CMTask* _task;
- int _ref_counter_limit;
- int _ref_counter;
+ uint _ref_counter_limit;
+ uint _ref_counter;
bool _is_serial;
public:
G1CMKeepAliveAndDrainClosure(G1ConcurrentMark* cm, G1CMTask* task, bool is_serial) :
_cm(cm), _task(task), _is_serial(is_serial),
_ref_counter_limit(G1RefProcDrainInterval) {
- assert(_ref_counter_limit > 0, "sanity");
assert(!_is_serial || _task->worker_id() == 0, "only task 0 for serial code");
_ref_counter = _ref_counter_limit;
}
--- a/src/hotspot/share/gc/g1/g1FullCollector.cpp Wed Apr 18 14:07:41 2018 -0700
+++ b/src/hotspot/share/gc/g1/g1FullCollector.cpp Fri Apr 20 09:05:05 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -37,6 +37,7 @@
#include "gc/g1/g1OopClosures.hpp"
#include "gc/g1/g1Policy.hpp"
#include "gc/g1/g1StringDedup.hpp"
+#include "gc/shared/adaptiveSizePolicy.hpp"
#include "gc/shared/gcTraceTime.inline.hpp"
#include "gc/shared/preservedMarks.hpp"
#include "gc/shared/referenceProcessor.hpp"
@@ -72,10 +73,40 @@
return _heap->ref_processor_stw();
}
+uint G1FullCollector::calc_active_workers() {
+ G1CollectedHeap* heap = G1CollectedHeap::heap();
+ uint max_worker_count = heap->workers()->total_workers();
+ // Only calculate number of workers if UseDynamicNumberOfGCThreads
+ // is enabled, otherwise use max.
+ if (!UseDynamicNumberOfGCThreads) {
+ return max_worker_count;
+ }
+
+ // Consider G1HeapWastePercent to decide max number of workers. Each worker
+ // will in average cause half a region waste.
+ uint max_wasted_regions_allowed = ((heap->num_regions() * G1HeapWastePercent) / 100);
+ uint waste_worker_count = MAX2((max_wasted_regions_allowed * 2) , 1u);
+ uint heap_waste_worker_limit = MIN2(waste_worker_count, max_worker_count);
+
+ // Also consider HeapSizePerGCThread by calling AdaptiveSizePolicy to calculate
+ // the number of workers.
+ uint current_active_workers = heap->workers()->active_workers();
+ uint adaptive_worker_limit = AdaptiveSizePolicy::calc_active_workers(max_worker_count, current_active_workers, 0);
+
+ // Update active workers to the lower of the limits.
+ uint worker_count = MIN2(heap_waste_worker_limit, adaptive_worker_limit);
+ log_debug(gc, task)("Requesting %u active workers for full compaction (waste limited workers: %u, adaptive workers: %u)",
+ worker_count, heap_waste_worker_limit, adaptive_worker_limit);
+ worker_count = heap->workers()->update_active_workers(worker_count);
+ log_info(gc, task)("Using %u workers of %u for full compaction", worker_count, max_worker_count);
+
+ return worker_count;
+}
+
G1FullCollector::G1FullCollector(G1CollectedHeap* heap, GCMemoryManager* memory_manager, bool explicit_gc, bool clear_soft_refs) :
_heap(heap),
_scope(memory_manager, explicit_gc, clear_soft_refs),
- _num_workers(heap->workers()->active_workers()),
+ _num_workers(calc_active_workers()),
_oop_queue_set(_num_workers),
_array_queue_set(_num_workers),
_preserved_marks_set(true),
--- a/src/hotspot/share/gc/g1/g1FullCollector.hpp Wed Apr 18 14:07:41 2018 -0700
+++ b/src/hotspot/share/gc/g1/g1FullCollector.hpp Fri Apr 20 09:05:05 2018 -0700
@@ -56,6 +56,8 @@
G1IsAliveClosure _is_alive;
ReferenceProcessorIsAliveMutator _is_alive_mutator;
+ static uint calc_active_workers();
+
public:
G1FullCollector(G1CollectedHeap* heap, GCMemoryManager* memory_manager, bool explicit_gc, bool clear_soft_refs);
~G1FullCollector();
--- a/src/hotspot/share/gc/g1/g1FullGCOopClosures.hpp Wed Apr 18 14:07:41 2018 -0700
+++ b/src/hotspot/share/gc/g1/g1FullGCOopClosures.hpp Fri Apr 20 09:05:05 2018 -0700
@@ -60,7 +60,7 @@
uint _worker_id;
public:
- G1MarkAndPushClosure(uint worker, G1FullGCMarker* marker, ReferenceProcessor* ref) :
+ G1MarkAndPushClosure(uint worker, G1FullGCMarker* marker, ReferenceDiscoverer* ref) :
_marker(marker),
_worker_id(worker),
ExtendedOopClosure(ref) { }
--- a/src/hotspot/share/gc/g1/g1MonitoringSupport.cpp Wed Apr 18 14:07:41 2018 -0700
+++ b/src/hotspot/share/gc/g1/g1MonitoringSupport.cpp Fri Apr 20 09:05:05 2018 -0700
@@ -27,6 +27,7 @@
#include "gc/g1/g1MonitoringSupport.hpp"
#include "gc/g1/g1Policy.hpp"
#include "gc/shared/hSpaceCounters.hpp"
+#include "memory/metaspaceCounters.hpp"
G1GenerationCounters::G1GenerationCounters(G1MonitoringSupport* g1mm,
const char* name,
--- a/src/hotspot/share/gc/g1/g1OopClosures.hpp Wed Apr 18 14:07:41 2018 -0700
+++ b/src/hotspot/share/gc/g1/g1OopClosures.hpp Fri Apr 20 09:05:05 2018 -0700
@@ -96,8 +96,8 @@
virtual void do_oop(oop* p) { do_oop_nv(p); }
virtual void do_oop(narrowOop* p) { do_oop_nv(p); }
- void set_ref_processor(ReferenceProcessor* rp) {
- set_ref_processor_internal(rp);
+ void set_ref_discoverer(ReferenceDiscoverer* rd) {
+ set_ref_discoverer_internal(rd);
}
};
--- a/src/hotspot/share/gc/g1/g1ParScanThreadState.hpp Wed Apr 18 14:07:41 2018 -0700
+++ b/src/hotspot/share/gc/g1/g1ParScanThreadState.hpp Fri Apr 20 09:05:05 2018 -0700
@@ -87,7 +87,7 @@
G1ParScanThreadState(G1CollectedHeap* g1h, uint worker_id, size_t young_cset_length);
virtual ~G1ParScanThreadState();
- void set_ref_processor(ReferenceProcessor* rp) { _scanner.set_ref_processor(rp); }
+ void set_ref_discoverer(ReferenceDiscoverer* rd) { _scanner.set_ref_discoverer(rd); }
#ifdef ASSERT
bool queue_is_empty() const { return _refs->is_empty(); }
--- a/src/hotspot/share/gc/g1/g1_globals.hpp Wed Apr 18 14:07:41 2018 -0700
+++ b/src/hotspot/share/gc/g1/g1_globals.hpp Fri Apr 20 09:05:05 2018 -0700
@@ -74,7 +74,7 @@
"in milliseconds.") \
range(1.0, DBL_MAX) \
\
- product(int, G1RefProcDrainInterval, 10, \
+ product(uint, G1RefProcDrainInterval, 1000, \
"The number of discovered reference objects to process before " \
"draining concurrent marking work queues.") \
range(1, INT_MAX) \
--- a/src/hotspot/share/gc/parallel/parallelScavengeHeap.cpp Wed Apr 18 14:07:41 2018 -0700
+++ b/src/hotspot/share/gc/parallel/parallelScavengeHeap.cpp Fri Apr 20 09:05:05 2018 -0700
@@ -41,6 +41,7 @@
#include "gc/shared/gcLocker.hpp"
#include "gc/shared/gcWhen.hpp"
#include "logging/log.hpp"
+#include "memory/metaspaceCounters.hpp"
#include "oops/oop.inline.hpp"
#include "runtime/handles.inline.hpp"
#include "runtime/java.hpp"
--- a/src/hotspot/share/gc/parallel/psMarkSweep.cpp Wed Apr 18 14:07:41 2018 -0700
+++ b/src/hotspot/share/gc/parallel/psMarkSweep.cpp Fri Apr 20 09:05:05 2018 -0700
@@ -562,7 +562,7 @@
CodeCache::do_unloading(is_alive_closure(), purged_class);
// Prune dead klasses from subklass/sibling/implementor lists.
- Klass::clean_weak_klass_links(is_alive_closure());
+ Klass::clean_weak_klass_links();
}
{
--- a/src/hotspot/share/gc/parallel/psParallelCompact.cpp Wed Apr 18 14:07:41 2018 -0700
+++ b/src/hotspot/share/gc/parallel/psParallelCompact.cpp Fri Apr 20 09:05:05 2018 -0700
@@ -2139,7 +2139,7 @@
CodeCache::do_unloading(is_alive_closure(), purged_class);
// Prune dead klasses from subklass/sibling/implementor lists.
- Klass::clean_weak_klass_links(is_alive_closure());
+ Klass::clean_weak_klass_links();
}
{
--- a/src/hotspot/share/gc/serial/genMarkSweep.cpp Wed Apr 18 14:07:41 2018 -0700
+++ b/src/hotspot/share/gc/serial/genMarkSweep.cpp Fri Apr 20 09:05:05 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -234,7 +234,7 @@
CodeCache::do_unloading(&is_alive, purged_class);
// Prune dead klasses from subklass/sibling/implementor lists.
- Klass::clean_weak_klass_links(&is_alive);
+ Klass::clean_weak_klass_links();
}
{
--- a/src/hotspot/share/gc/serial/markSweep.cpp Wed Apr 18 14:07:41 2018 -0700
+++ b/src/hotspot/share/gc/serial/markSweep.cpp Fri Apr 20 09:05:05 2018 -0700
@@ -211,7 +211,7 @@
void MarkSweep::set_ref_processor(ReferenceProcessor* rp) {
_ref_processor = rp;
- mark_and_push_closure.set_ref_processor(_ref_processor);
+ mark_and_push_closure.set_ref_discoverer(_ref_processor);
}
AdjustPointerClosure MarkSweep::adjust_pointer_closure;
--- a/src/hotspot/share/gc/serial/markSweep.hpp Wed Apr 18 14:07:41 2018 -0700
+++ b/src/hotspot/share/gc/serial/markSweep.hpp Fri Apr 20 09:05:05 2018 -0700
@@ -184,8 +184,8 @@
virtual void do_cld(ClassLoaderData* cld);
void do_cld_nv(ClassLoaderData* cld);
- void set_ref_processor(ReferenceProcessor* rp) {
- set_ref_processor_internal(rp);
+ void set_ref_discoverer(ReferenceDiscoverer* rd) {
+ set_ref_discoverer_internal(rd);
}
};
--- a/src/hotspot/share/gc/shared/adaptiveSizePolicy.hpp Wed Apr 18 14:07:41 2018 -0700
+++ b/src/hotspot/share/gc/shared/adaptiveSizePolicy.hpp Fri Apr 20 09:05:05 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2004, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -355,6 +355,7 @@
// For ParNew collections
// For PS scavenge and ParOld collections
// For G1 evacuation pauses (subject to update)
+ // For G1 Full GCs (subject to update)
// Other collection phases inherit the number of
// GC workers from the calls above. For example,
// a CMS parallel remark uses the same number of GC
--- a/src/hotspot/share/gc/shared/genCollectedHeap.cpp Wed Apr 18 14:07:41 2018 -0700
+++ b/src/hotspot/share/gc/shared/genCollectedHeap.cpp Fri Apr 20 09:05:05 2018 -0700
@@ -49,6 +49,7 @@
#include "gc/shared/weakProcessor.hpp"
#include "gc/shared/workgroup.hpp"
#include "memory/filemap.hpp"
+#include "memory/metaspaceCounters.hpp"
#include "memory/resourceArea.hpp"
#include "oops/oop.inline.hpp"
#include "runtime/biasedLocking.hpp"
--- a/src/hotspot/share/gc/shared/genOopClosures.hpp Wed Apr 18 14:07:41 2018 -0700
+++ b/src/hotspot/share/gc/shared/genOopClosures.hpp Fri Apr 20 09:05:05 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -151,7 +151,7 @@
template <class T> inline void do_oop_work(T* p);
public:
FilteringClosure(HeapWord* boundary, ExtendedOopClosure* cl) :
- ExtendedOopClosure(cl->ref_processor()), _boundary(boundary),
+ ExtendedOopClosure(cl->ref_discoverer()), _boundary(boundary),
_cl(cl) {}
virtual void do_oop(oop* p);
virtual void do_oop(narrowOop* p);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/shared/referenceDiscoverer.hpp Fri Apr 20 09:05:05 2018 -0700
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
+ * 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.
+ *
+ */
+
+#ifndef SHARE_GC_SHARED_REFERENCEDISCOVERER_HPP
+#define SHARE_GC_SHARED_REFERENCEDISCOVERER_HPP
+
+#include "memory/allocation.hpp"
+#include "memory/referenceType.hpp"
+#include "oops/oopsHierarchy.hpp"
+
+class ReferenceDiscoverer : public CHeapObj<mtGC> {
+public:
+ virtual bool discover_reference(oop obj, ReferenceType type) = 0;
+};
+
+#endif // SHARE_GC_SHARED_REFERENCEDISCOVERER_HPP
--- a/src/hotspot/share/gc/shared/referenceProcessor.hpp Wed Apr 18 14:07:41 2018 -0700
+++ b/src/hotspot/share/gc/shared/referenceProcessor.hpp Fri Apr 20 09:05:05 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -25,6 +25,7 @@
#ifndef SHARE_VM_GC_SHARED_REFERENCEPROCESSOR_HPP
#define SHARE_VM_GC_SHARED_REFERENCEPROCESSOR_HPP
+#include "gc/shared/referenceDiscoverer.hpp"
#include "gc/shared/referencePolicy.hpp"
#include "gc/shared/referenceProcessorPhaseTimes.hpp"
#include "gc/shared/referenceProcessorStats.hpp"
@@ -166,7 +167,7 @@
}
};
-class ReferenceProcessor : public CHeapObj<mtGC> {
+class ReferenceProcessor : public ReferenceDiscoverer {
private:
size_t total_count(DiscoveredList lists[]) const;
@@ -405,7 +406,7 @@
void verify_list(DiscoveredList& ref_list);
// Discover a Reference object, using appropriate discovery criteria
- bool discover_reference(oop obj, ReferenceType rt);
+ virtual bool discover_reference(oop obj, ReferenceType rt);
// Has discovered references that need handling
bool has_discovered_references();
--- a/src/hotspot/share/gc/shared/threadLocalAllocBuffer.hpp Wed Apr 18 14:07:41 2018 -0700
+++ b/src/hotspot/share/gc/shared/threadLocalAllocBuffer.hpp Fri Apr 20 09:05:05 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -164,6 +164,13 @@
static size_t refill_waste_limit_increment() { return TLABWasteIncrement; }
+ template <typename T> void addresses_do(T f) {
+ f(&_start);
+ f(&_top);
+ f(&_pf_top);
+ f(&_end);
+ }
+
// Code generation support
static ByteSize start_offset() { return byte_offset_of(ThreadLocalAllocBuffer, _start); }
static ByteSize end_offset() { return byte_offset_of(ThreadLocalAllocBuffer, _end ); }
--- a/src/hotspot/share/jvmci/jvmciRuntime.cpp Wed Apr 18 14:07:41 2018 -0700
+++ b/src/hotspot/share/jvmci/jvmciRuntime.cpp Fri Apr 20 09:05:05 2018 -0700
@@ -415,6 +415,34 @@
}
JRT_END
+// Object.notify() fast path, caller does slow path
+JRT_LEAF(jboolean, JVMCIRuntime::object_notify(JavaThread *thread, oopDesc* obj))
+
+ // Very few notify/notifyAll operations find any threads on the waitset, so
+ // the dominant fast-path is to simply return.
+ // Relatedly, it's critical that notify/notifyAll be fast in order to
+ // reduce lock hold times.
+ if (!SafepointSynchronize::is_synchronizing()) {
+ if (ObjectSynchronizer::quick_notify(obj, thread, false)) {
+ return true;
+ }
+ }
+ return false; // caller must perform slow path
+
+JRT_END
+
+// Object.notifyAll() fast path, caller does slow path
+JRT_LEAF(jboolean, JVMCIRuntime::object_notifyAll(JavaThread *thread, oopDesc* obj))
+
+ if (!SafepointSynchronize::is_synchronizing() ) {
+ if (ObjectSynchronizer::quick_notify(obj, thread, true)) {
+ return true;
+ }
+ }
+ return false; // caller must perform slow path
+
+JRT_END
+
JRT_ENTRY(void, JVMCIRuntime::throw_and_post_jvmti_exception(JavaThread* thread, const char* exception, const char* message))
TempNewSymbol symbol = SymbolTable::new_symbol(exception, CHECK);
SharedRuntime::throw_and_post_jvmti_exception(thread, symbol, message);
--- a/src/hotspot/share/jvmci/jvmciRuntime.hpp Wed Apr 18 14:07:41 2018 -0700
+++ b/src/hotspot/share/jvmci/jvmciRuntime.hpp Fri Apr 20 09:05:05 2018 -0700
@@ -139,6 +139,8 @@
static address exception_handler_for_pc(JavaThread* thread);
static void monitorenter(JavaThread* thread, oopDesc* obj, BasicLock* lock);
static void monitorexit (JavaThread* thread, oopDesc* obj, BasicLock* lock);
+ static jboolean object_notify(JavaThread* thread, oopDesc* obj);
+ static jboolean object_notifyAll(JavaThread* thread, oopDesc* obj);
static void vm_error(JavaThread* thread, jlong where, jlong format, jlong value);
static oopDesc* load_and_clear_exception(JavaThread* thread);
static void log_printf(JavaThread* thread, oopDesc* format, jlong v1, jlong v2, jlong v3);
--- a/src/hotspot/share/jvmci/vmStructs_jvmci.cpp Wed Apr 18 14:07:41 2018 -0700
+++ b/src/hotspot/share/jvmci/vmStructs_jvmci.cpp Fri Apr 20 09:05:05 2018 -0700
@@ -625,6 +625,8 @@
declare_function(JVMCIRuntime::exception_handler_for_pc) \
declare_function(JVMCIRuntime::monitorenter) \
declare_function(JVMCIRuntime::monitorexit) \
+ declare_function(JVMCIRuntime::object_notify) \
+ declare_function(JVMCIRuntime::object_notifyAll) \
declare_function(JVMCIRuntime::throw_and_post_jvmti_exception) \
declare_function(JVMCIRuntime::throw_klass_external_name_exception) \
declare_function(JVMCIRuntime::throw_class_cast_exception) \
--- a/src/hotspot/share/memory/heapInspection.cpp Wed Apr 18 14:07:41 2018 -0700
+++ b/src/hotspot/share/memory/heapInspection.cpp Fri Apr 20 09:05:05 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -23,7 +23,7 @@
*/
#include "precompiled.hpp"
-#include "classfile/classLoaderData.hpp"
+#include "classfile/classLoaderData.inline.hpp"
#include "classfile/moduleEntry.hpp"
#include "classfile/systemDictionary.hpp"
#include "gc/shared/collectedHeap.hpp"
--- a/src/hotspot/share/memory/iterator.hpp Wed Apr 18 14:07:41 2018 -0700
+++ b/src/hotspot/share/memory/iterator.hpp Fri Apr 20 09:05:05 2018 -0700
@@ -31,7 +31,7 @@
class CodeBlob;
class nmethod;
-class ReferenceProcessor;
+class ReferenceDiscoverer;
class DataLayout;
class KlassClosure;
class ClassLoaderData;
@@ -60,17 +60,17 @@
// pollute the OopClosure interface.
class ExtendedOopClosure : public OopClosure {
private:
- ReferenceProcessor* _ref_processor;
+ ReferenceDiscoverer* _ref_discoverer;
protected:
- ExtendedOopClosure(ReferenceProcessor* rp) : _ref_processor(rp) { }
- ExtendedOopClosure() : _ref_processor(NULL) { }
+ ExtendedOopClosure(ReferenceDiscoverer* rd) : _ref_discoverer(rd) { }
+ ExtendedOopClosure() : _ref_discoverer(NULL) { }
~ExtendedOopClosure() { }
- void set_ref_processor_internal(ReferenceProcessor* rp) { _ref_processor = rp; }
+ void set_ref_discoverer_internal(ReferenceDiscoverer* rd) { _ref_discoverer = rd; }
public:
- ReferenceProcessor* ref_processor() const { return _ref_processor; }
+ ReferenceDiscoverer* ref_discoverer() const { return _ref_discoverer; }
// Iteration of InstanceRefKlasses differ depending on the closure,
// the below enum describes the different alternatives.
@@ -165,7 +165,7 @@
public:
MetadataAwareOopClosure() : ExtendedOopClosure() { }
- MetadataAwareOopClosure(ReferenceProcessor* rp) : ExtendedOopClosure(rp) { }
+ MetadataAwareOopClosure(ReferenceDiscoverer* rd) : ExtendedOopClosure(rd) { }
bool do_metadata_nv() { return true; }
virtual bool do_metadata() { return do_metadata_nv(); }
--- a/src/hotspot/share/memory/universe.cpp Wed Apr 18 14:07:41 2018 -0700
+++ b/src/hotspot/share/memory/universe.cpp Fri Apr 20 09:05:05 2018 -0700
@@ -46,6 +46,7 @@
#include "memory/filemap.hpp"
#include "memory/metadataFactory.hpp"
#include "memory/metaspaceClosure.hpp"
+#include "memory/metaspaceCounters.hpp"
#include "memory/metaspaceShared.hpp"
#include "memory/oopFactory.hpp"
#include "memory/resourceArea.hpp"
--- a/src/hotspot/share/oops/compiledICHolder.hpp Wed Apr 18 14:07:41 2018 -0700
+++ b/src/hotspot/share/oops/compiledICHolder.hpp Fri Apr 20 09:05:05 2018 -0700
@@ -74,12 +74,12 @@
CompiledICHolder* next() { return _next; }
void set_next(CompiledICHolder* n) { _next = n; }
- inline bool is_loader_alive(BoolObjectClosure* is_alive) {
+ inline bool is_loader_alive() {
Klass* k = _is_metadata_method ? ((Method*)_holder_metadata)->method_holder() : (Klass*)_holder_metadata;
- if (!k->is_loader_alive(is_alive)) {
+ if (!k->is_loader_alive()) {
return false;
}
- if (!_holder_klass->is_loader_alive(is_alive)) {
+ if (!_holder_klass->is_loader_alive()) {
return false;
}
return true;
--- a/src/hotspot/share/oops/instanceKlass.cpp Wed Apr 18 14:07:41 2018 -0700
+++ b/src/hotspot/share/oops/instanceKlass.cpp Fri Apr 20 09:05:05 2018 -0700
@@ -28,6 +28,7 @@
#include "classfile/classFileParser.hpp"
#include "classfile/classFileStream.hpp"
#include "classfile/classLoader.hpp"
+#include "classfile/classLoaderData.inline.hpp"
#include "classfile/javaClasses.hpp"
#include "classfile/moduleEntry.hpp"
#include "classfile/systemDictionary.hpp"
@@ -1891,22 +1892,22 @@
}
#endif //PRODUCT
-void InstanceKlass::clean_weak_instanceklass_links(BoolObjectClosure* is_alive) {
- clean_implementors_list(is_alive);
- clean_method_data(is_alive);
+void InstanceKlass::clean_weak_instanceklass_links() {
+ clean_implementors_list();
+ clean_method_data();
// Since GC iterates InstanceKlasses sequentially, it is safe to remove stale entries here.
DependencyContext dep_context(&_dep_context);
dep_context.expunge_stale_entries();
}
-void InstanceKlass::clean_implementors_list(BoolObjectClosure* is_alive) {
- assert(class_loader_data()->is_alive(), "this klass should be live");
+void InstanceKlass::clean_implementors_list() {
+ assert(is_loader_alive(), "this klass should be live");
if (is_interface()) {
if (ClassUnloading) {
Klass* impl = implementor();
if (impl != NULL) {
- if (!impl->is_loader_alive(is_alive)) {
+ if (!impl->is_loader_alive()) {
// remove this guy
Klass** klass = adr_implementor();
assert(klass != NULL, "null klass");
@@ -1919,11 +1920,11 @@
}
}
-void InstanceKlass::clean_method_data(BoolObjectClosure* is_alive) {
+void InstanceKlass::clean_method_data() {
for (int m = 0; m < methods()->length(); m++) {
MethodData* mdo = methods()->at(m)->method_data();
if (mdo != NULL) {
- mdo->clean_method_data(is_alive);
+ mdo->clean_method_data(/*always_clean*/false);
}
}
}
--- a/src/hotspot/share/oops/instanceKlass.hpp Wed Apr 18 14:07:41 2018 -0700
+++ b/src/hotspot/share/oops/instanceKlass.hpp Fri Apr 20 09:05:05 2018 -0700
@@ -1148,9 +1148,9 @@
void adjust_default_methods(InstanceKlass* holder, bool* trace_name_printed);
#endif // INCLUDE_JVMTI
- void clean_weak_instanceklass_links(BoolObjectClosure* is_alive);
- void clean_implementors_list(BoolObjectClosure* is_alive);
- void clean_method_data(BoolObjectClosure* is_alive);
+ void clean_weak_instanceklass_links();
+ void clean_implementors_list();
+ void clean_method_data();
// Explicit metaspace deallocation of fields
// For RedefineClasses and class file parsing errors, we need to deallocate
--- a/src/hotspot/share/oops/instanceRefKlass.inline.hpp Wed Apr 18 14:07:41 2018 -0700
+++ b/src/hotspot/share/oops/instanceRefKlass.inline.hpp Fri Apr 20 09:05:05 2018 -0700
@@ -63,14 +63,14 @@
template <typename T, class OopClosureType>
bool InstanceRefKlass::try_discover(oop obj, ReferenceType type, OopClosureType* closure) {
- ReferenceProcessor* rp = closure->ref_processor();
- if (rp != NULL) {
+ ReferenceDiscoverer* rd = closure->ref_discoverer();
+ if (rd != NULL) {
T referent_oop = RawAccess<>::oop_load((T*)java_lang_ref_Reference::referent_addr_raw(obj));
if (!CompressedOops::is_null(referent_oop)) {
oop referent = CompressedOops::decode_not_null(referent_oop);
if (!referent->is_gc_marked()) {
// Only try to discover if not yet marked.
- return rp->discover_reference(obj, type);
+ return rd->discover_reference(obj, type);
}
}
}
--- a/src/hotspot/share/oops/klass.cpp Wed Apr 18 14:07:41 2018 -0700
+++ b/src/hotspot/share/oops/klass.cpp Fri Apr 20 09:05:05 2018 -0700
@@ -23,6 +23,7 @@
*/
#include "precompiled.hpp"
+#include "classfile/classLoaderData.inline.hpp"
#include "classfile/dictionary.hpp"
#include "classfile/javaClasses.hpp"
#include "classfile/systemDictionary.hpp"
@@ -381,22 +382,7 @@
debug_only(verify();)
}
-bool Klass::is_loader_alive(BoolObjectClosure* is_alive) {
-#ifdef ASSERT
- // The class is alive iff the class loader is alive.
- oop loader = class_loader();
- bool loader_alive = (loader == NULL) || is_alive->do_object_b(loader);
-#endif // ASSERT
-
- // The class is alive if it's mirror is alive (which should be marked if the
- // loader is alive) unless it's an anoymous class.
- bool mirror_alive = is_alive->do_object_b(java_mirror());
- assert(!mirror_alive || loader_alive, "loader must be alive if the mirror is"
- " but not the other way around with anonymous classes");
- return mirror_alive;
-}
-
-void Klass::clean_weak_klass_links(BoolObjectClosure* is_alive, bool clean_alive_klasses) {
+void Klass::clean_weak_klass_links(bool clean_alive_klasses) {
if (!ClassUnloading) {
return;
}
@@ -408,11 +394,11 @@
while (!stack.is_empty()) {
Klass* current = stack.pop();
- assert(current->is_loader_alive(is_alive), "just checking, this should be live");
+ assert(current->is_loader_alive(), "just checking, this should be live");
// Find and set the first alive subklass
Klass* sub = current->subklass();
- while (sub != NULL && !sub->is_loader_alive(is_alive)) {
+ while (sub != NULL && !sub->is_loader_alive()) {
#ifndef PRODUCT
if (log_is_enabled(Trace, class, unload)) {
ResourceMark rm;
@@ -428,7 +414,7 @@
// Find and set the first alive sibling
Klass* sibling = current->next_sibling();
- while (sibling != NULL && !sibling->is_loader_alive(is_alive)) {
+ while (sibling != NULL && !sibling->is_loader_alive()) {
if (log_is_enabled(Trace, class, unload)) {
ResourceMark rm;
log_trace(class, unload)("[Unlinking class (sibling) %s]", sibling->external_name());
@@ -443,12 +429,12 @@
// Clean the implementors list and method data.
if (clean_alive_klasses && current->is_instance_klass()) {
InstanceKlass* ik = InstanceKlass::cast(current);
- ik->clean_weak_instanceklass_links(is_alive);
+ ik->clean_weak_instanceklass_links();
// JVMTI RedefineClasses creates previous versions that are not in
// the class hierarchy, so process them here.
while ((ik = ik->previous_versions()) != NULL) {
- ik->clean_weak_instanceklass_links(is_alive);
+ ik->clean_weak_instanceklass_links();
}
}
}
--- a/src/hotspot/share/oops/klass.hpp Wed Apr 18 14:07:41 2018 -0700
+++ b/src/hotspot/share/oops/klass.hpp Fri Apr 20 09:05:05 2018 -0700
@@ -25,6 +25,7 @@
#ifndef SHARE_VM_OOPS_KLASS_HPP
#define SHARE_VM_OOPS_KLASS_HPP
+#include "classfile/classLoaderData.hpp"
#include "gc/shared/specialized_oop_closures.hpp"
#include "memory/iterator.hpp"
#include "memory/memRegion.hpp"
@@ -52,7 +53,6 @@
// Forward declarations.
template <class T> class Array;
template <class T> class GrowableArray;
-class ClassLoaderData;
class fieldDescriptor;
class KlassSizeStats;
class klassVtable;
@@ -634,13 +634,12 @@
virtual MetaspaceObj::Type type() const { return ClassType; }
// Iff the class loader (or mirror for anonymous classes) is alive the
- // Klass is considered alive.
- // The is_alive closure passed in depends on the Garbage Collector used.
- bool is_loader_alive(BoolObjectClosure* is_alive);
+ // Klass is considered alive. Has already been marked as unloading.
+ bool is_loader_alive() const { return !class_loader_data()->is_unloading(); }
- static void clean_weak_klass_links(BoolObjectClosure* is_alive, bool clean_alive_klasses = true);
- static void clean_subklass_tree(BoolObjectClosure* is_alive) {
- clean_weak_klass_links(is_alive, false /* clean_alive_klasses */);
+ static void clean_weak_klass_links(bool clean_alive_klasses = true);
+ static void clean_subklass_tree() {
+ clean_weak_klass_links(false /* clean_alive_klasses */);
}
// GC specific object visitors
--- a/src/hotspot/share/oops/methodData.cpp Wed Apr 18 14:07:41 2018 -0700
+++ b/src/hotspot/share/oops/methodData.cpp Fri Apr 20 09:05:05 2018 -0700
@@ -71,9 +71,9 @@
}
}
-void DataLayout::clean_weak_klass_links(BoolObjectClosure* cl) {
+void DataLayout::clean_weak_klass_links(bool always_clean) {
ResourceMark m;
- data_in()->clean_weak_klass_links(cl);
+ data_in()->clean_weak_klass_links(always_clean);
}
@@ -315,23 +315,20 @@
}
}
-bool TypeEntries::is_loader_alive(BoolObjectClosure* is_alive_cl, intptr_t p) {
- Klass* k = (Klass*)klass_part(p);
- return k != NULL && k->is_loader_alive(is_alive_cl);
-}
-
-void TypeStackSlotEntries::clean_weak_klass_links(BoolObjectClosure* is_alive_cl) {
+void TypeStackSlotEntries::clean_weak_klass_links(bool always_clean) {
for (int i = 0; i < _number_of_entries; i++) {
intptr_t p = type(i);
- if (!is_loader_alive(is_alive_cl, p)) {
+ Klass* k = (Klass*)klass_part(p);
+ if (k != NULL && (always_clean || !k->is_loader_alive())) {
set_type(i, with_status((Klass*)NULL, p));
}
}
}
-void ReturnTypeEntry::clean_weak_klass_links(BoolObjectClosure* is_alive_cl) {
+void ReturnTypeEntry::clean_weak_klass_links(bool always_clean) {
intptr_t p = type();
- if (!is_loader_alive(is_alive_cl, p)) {
+ Klass* k = (Klass*)klass_part(p);
+ if (k != NULL && (always_clean || !k->is_loader_alive())) {
set_type(with_status((Klass*)NULL, p));
}
}
@@ -408,21 +405,21 @@
// that the check is reached, and a series of (Klass*, count) pairs
// which are used to store a type profile for the receiver of the check.
-void ReceiverTypeData::clean_weak_klass_links(BoolObjectClosure* is_alive_cl) {
+void ReceiverTypeData::clean_weak_klass_links(bool always_clean) {
for (uint row = 0; row < row_limit(); row++) {
Klass* p = receiver(row);
- if (p != NULL && !p->is_loader_alive(is_alive_cl)) {
+ if (p != NULL && (always_clean || !p->is_loader_alive())) {
clear_row(row);
}
}
}
#if INCLUDE_JVMCI
-void VirtualCallData::clean_weak_klass_links(BoolObjectClosure* is_alive_cl) {
- ReceiverTypeData::clean_weak_klass_links(is_alive_cl);
+void VirtualCallData::clean_weak_klass_links(bool always_clean) {
+ ReceiverTypeData::clean_weak_klass_links(always_clean);
for (uint row = 0; row < method_row_limit(); row++) {
Method* p = method(row);
- if (p != NULL && !p->method_holder()->is_loader_alive(is_alive_cl)) {
+ if (p != NULL && (always_clean || !p->method_holder()->is_loader_alive())) {
clear_method_row(row);
}
}
@@ -1669,12 +1666,11 @@
// Check for entries that reference an unloaded method
class CleanExtraDataKlassClosure : public CleanExtraDataClosure {
-private:
- BoolObjectClosure* _is_alive;
+ bool _always_clean;
public:
- CleanExtraDataKlassClosure(BoolObjectClosure* is_alive) : _is_alive(is_alive) {}
+ CleanExtraDataKlassClosure(bool always_clean) : _always_clean(always_clean) {}
bool is_live(Method* m) {
- return m->method_holder()->is_loader_alive(_is_alive);
+ return !(_always_clean) && m->method_holder()->is_loader_alive();
}
};
@@ -1757,19 +1753,19 @@
#endif
}
-void MethodData::clean_method_data(BoolObjectClosure* is_alive) {
+void MethodData::clean_method_data(bool always_clean) {
ResourceMark rm;
for (ProfileData* data = first_data();
is_valid(data);
data = next_data(data)) {
- data->clean_weak_klass_links(is_alive);
+ data->clean_weak_klass_links(always_clean);
}
ParametersTypeData* parameters = parameters_type_data();
if (parameters != NULL) {
- parameters->clean_weak_klass_links(is_alive);
+ parameters->clean_weak_klass_links(always_clean);
}
- CleanExtraDataKlassClosure cl(is_alive);
+ CleanExtraDataKlassClosure cl(always_clean);
clean_extra_data(&cl);
verify_extra_data_clean(&cl);
}
--- a/src/hotspot/share/oops/methodData.hpp Wed Apr 18 14:07:41 2018 -0700
+++ b/src/hotspot/share/oops/methodData.hpp Fri Apr 20 09:05:05 2018 -0700
@@ -254,7 +254,7 @@
ProfileData* data_in();
// GC support
- void clean_weak_klass_links(BoolObjectClosure* cl);
+ void clean_weak_klass_links(bool always_clean);
// Redefinition support
void clean_weak_method_links();
@@ -505,7 +505,7 @@
virtual void post_initialize(BytecodeStream* stream, MethodData* mdo) {}
// GC support
- virtual void clean_weak_klass_links(BoolObjectClosure* is_alive_closure) {}
+ virtual void clean_weak_klass_links(bool always_clean) {}
// Redefinition support
virtual void clean_weak_method_links() {}
@@ -820,9 +820,6 @@
static void print_klass(outputStream* st, intptr_t k);
- // GC support
- static bool is_loader_alive(BoolObjectClosure* is_alive_cl, intptr_t p);
-
protected:
// ProfileData object these entries are part of
ProfileData* _pd;
@@ -930,7 +927,7 @@
}
// GC support
- void clean_weak_klass_links(BoolObjectClosure* is_alive_closure);
+ void clean_weak_klass_links(bool always_clean);
void print_data_on(outputStream* st) const;
};
@@ -973,7 +970,7 @@
}
// GC support
- void clean_weak_klass_links(BoolObjectClosure* is_alive_closure);
+ void clean_weak_klass_links(bool always_clean);
void print_data_on(outputStream* st) const;
};
@@ -1157,12 +1154,12 @@
}
// GC support
- virtual void clean_weak_klass_links(BoolObjectClosure* is_alive_closure) {
+ virtual void clean_weak_klass_links(bool always_clean) {
if (has_arguments()) {
- _args.clean_weak_klass_links(is_alive_closure);
+ _args.clean_weak_klass_links(always_clean);
}
if (has_return()) {
- _ret.clean_weak_klass_links(is_alive_closure);
+ _ret.clean_weak_klass_links(always_clean);
}
}
@@ -1303,7 +1300,7 @@
}
// GC support
- virtual void clean_weak_klass_links(BoolObjectClosure* is_alive_closure);
+ virtual void clean_weak_klass_links(bool always_clean);
#ifdef CC_INTERP
static int receiver_type_data_size_in_bytes() {
@@ -1433,7 +1430,7 @@
}
// GC support
- virtual void clean_weak_klass_links(BoolObjectClosure* is_alive_closure);
+ virtual void clean_weak_klass_links(bool always_clean);
// Redefinition support
virtual void clean_weak_method_links();
@@ -1562,13 +1559,13 @@
}
// GC support
- virtual void clean_weak_klass_links(BoolObjectClosure* is_alive_closure) {
- ReceiverTypeData::clean_weak_klass_links(is_alive_closure);
+ virtual void clean_weak_klass_links(bool always_clean) {
+ ReceiverTypeData::clean_weak_klass_links(always_clean);
if (has_arguments()) {
- _args.clean_weak_klass_links(is_alive_closure);
+ _args.clean_weak_klass_links(always_clean);
}
if (has_return()) {
- _ret.clean_weak_klass_links(is_alive_closure);
+ _ret.clean_weak_klass_links(always_clean);
}
}
@@ -2021,8 +2018,8 @@
_parameters.set_type(i, TypeEntries::with_status((intptr_t)k, current));
}
- virtual void clean_weak_klass_links(BoolObjectClosure* is_alive_closure) {
- _parameters.clean_weak_klass_links(is_alive_closure);
+ virtual void clean_weak_klass_links(bool always_clean) {
+ _parameters.clean_weak_klass_links(always_clean);
}
virtual void print_data_on(outputStream* st, const char* extra = NULL) const;
@@ -2610,7 +2607,7 @@
static bool profile_parameters();
static bool profile_return_jsr292_only();
- void clean_method_data(BoolObjectClosure* is_alive);
+ void clean_method_data(bool always_clean);
void clean_weak_method_links();
DEBUG_ONLY(void verify_clean_weak_method_links();)
Mutex* extra_data_lock() { return &_extra_data_lock; }
--- a/src/hotspot/share/oops/oopHandle.hpp Wed Apr 18 14:07:41 2018 -0700
+++ b/src/hotspot/share/oops/oopHandle.hpp Fri Apr 20 09:05:05 2018 -0700
@@ -46,7 +46,7 @@
inline oop resolve() const;
// Used only for removing handle.
- oop* ptr_raw() { return _obj; }
+ oop* ptr_raw() const { return _obj; }
};
#endif // SHARE_VM_OOPS_OOPHANDLE_HPP
--- a/src/hotspot/share/oops/weakHandle.cpp Wed Apr 18 14:07:41 2018 -0700
+++ b/src/hotspot/share/oops/weakHandle.cpp Fri Apr 20 09:05:05 2018 -0700
@@ -51,8 +51,8 @@
void WeakHandle<T>::release() const {
// Only release if the pointer to the object has been created.
if (_obj != NULL) {
- // Clear the WeakHandle. For class loader data race, the handle may not have
- // been previously cleared by GC.
+ // Clear the WeakHandle. For race in creating ClassLoaderData, we can release this
+ // WeakHandle before it is cleared by GC.
RootAccess<ON_PHANTOM_OOP_REF>::oop_store(_obj, (oop)NULL);
get_storage()->release(_obj);
}
--- a/src/hotspot/share/oops/weakHandle.hpp Wed Apr 18 14:07:41 2018 -0700
+++ b/src/hotspot/share/oops/weakHandle.hpp Fri Apr 20 09:05:05 2018 -0700
@@ -63,4 +63,6 @@
void print_on(outputStream* st) const;
};
+typedef WeakHandle<vm_class_loader_data> ClassLoaderWeakHandle;
+
#endif // SHARE_VM_OOPS_WEAKHANDLE_HPP
--- a/src/hotspot/share/prims/jvm.cpp Wed Apr 18 14:07:41 2018 -0700
+++ b/src/hotspot/share/prims/jvm.cpp Fri Apr 20 09:05:05 2018 -0700
@@ -2768,15 +2768,14 @@
return len;
}
-
// HotSpot specific jio method
-void jio_print(const char* s) {
+void jio_print(const char* s, size_t len) {
// Try to make this function as atomic as possible.
if (Arguments::vfprintf_hook() != NULL) {
- jio_fprintf(defaultStream::output_stream(), "%s", s);
+ jio_fprintf(defaultStream::output_stream(), "%.*s", (int)len, s);
} else {
// Make an unused local variable to avoid warning from gcc 4.x compiler.
- size_t count = ::write(defaultStream::output_fd(), s, (int)strlen(s));
+ size_t count = ::write(defaultStream::output_fd(), s, (int)len);
}
}
--- a/src/hotspot/share/prims/jvmtiGetLoadedClasses.cpp Wed Apr 18 14:07:41 2018 -0700
+++ b/src/hotspot/share/prims/jvmtiGetLoadedClasses.cpp Fri Apr 20 09:05:05 2018 -0700
@@ -23,6 +23,7 @@
*/
#include "precompiled.hpp"
+#include "classfile/classLoaderData.inline.hpp"
#include "classfile/systemDictionary.hpp"
#include "gc/shared/collectedHeap.hpp"
#include "memory/universe.hpp"
--- a/src/hotspot/share/prims/resolvedMethodTable.cpp Wed Apr 18 14:07:41 2018 -0700
+++ b/src/hotspot/share/prims/resolvedMethodTable.cpp Fri Apr 20 09:05:05 2018 -0700
@@ -30,6 +30,7 @@
#include "oops/oop.inline.hpp"
#include "oops/method.hpp"
#include "oops/symbol.hpp"
+#include "oops/weakHandle.inline.hpp"
#include "prims/resolvedMethodTable.hpp"
#include "runtime/handles.inline.hpp"
#include "runtime/mutexLocker.hpp"
@@ -39,7 +40,7 @@
oop ResolvedMethodEntry::object() {
- return RootAccess<ON_PHANTOM_OOP_REF>::oop_load(literal_addr());
+ return literal().resolve();
}
oop ResolvedMethodEntry::object_no_keepalive() {
@@ -48,11 +49,11 @@
// not leak out past a thread transition where a safepoint can happen.
// A subsequent oop_load without AS_NO_KEEPALIVE (the object() accessor)
// keeps the oop alive before doing so.
- return RootAccess<ON_PHANTOM_OOP_REF | AS_NO_KEEPALIVE>::oop_load(literal_addr());
+ return literal().peek();
}
ResolvedMethodTable::ResolvedMethodTable()
- : Hashtable<oop, mtClass>(_table_size, sizeof(ResolvedMethodEntry)) { }
+ : Hashtable<ClassLoaderWeakHandle, mtClass>(_table_size, sizeof(ResolvedMethodEntry)) { }
oop ResolvedMethodTable::lookup(int index, unsigned int hash, Method* method) {
for (ResolvedMethodEntry* p = bucket(index); p != NULL; p = p->next()) {
@@ -62,7 +63,7 @@
oop target = p->object_no_keepalive();
// The method is in the table as a target already
- if (java_lang_invoke_ResolvedMethodName::vmtarget(target) == method) {
+ if (target != NULL && java_lang_invoke_ResolvedMethodName::vmtarget(target) == method) {
ResourceMark rm;
log_debug(membername, table) ("ResolvedMethod entry found for %s index %d",
method->name_and_sig_as_C_string(), index);
@@ -88,7 +89,7 @@
return lookup(index, hash, method);
}
-oop ResolvedMethodTable::basic_add(Method* method, oop rmethod_name) {
+oop ResolvedMethodTable::basic_add(Method* method, Handle rmethod_name) {
assert_locked_or_safepoint(ResolvedMethodTable_lock);
unsigned int hash = compute_hash(method);
@@ -100,12 +101,13 @@
return entry;
}
- ResolvedMethodEntry* p = (ResolvedMethodEntry*) Hashtable<oop, mtClass>::new_entry(hash, rmethod_name);
- Hashtable<oop, mtClass>::add_entry(index, p);
+ ClassLoaderWeakHandle w = ClassLoaderWeakHandle::create(rmethod_name);
+ ResolvedMethodEntry* p = (ResolvedMethodEntry*) Hashtable<ClassLoaderWeakHandle, mtClass>::new_entry(hash, w);
+ Hashtable<ClassLoaderWeakHandle, mtClass>::add_entry(index, p);
ResourceMark rm;
log_debug(membername, table) ("ResolvedMethod entry added for %s index %d",
method->name_and_sig_as_C_string(), index);
- return rmethod_name;
+ return rmethod_name();
}
ResolvedMethodTable* ResolvedMethodTable::_the_table = NULL;
@@ -134,7 +136,7 @@
// have any membernames in the table.
method->method_holder()->set_has_resolved_methods();
- return _the_table->basic_add(method, resolved_method_name());
+ return _the_table->basic_add(method, resolved_method_name);
}
// Removing entries
@@ -143,7 +145,7 @@
// Serially invoke removed unused oops from the table.
// This is done late during GC.
-void ResolvedMethodTable::unlink(BoolObjectClosure* is_alive) {
+void ResolvedMethodTable::unlink() {
_oops_removed = 0;
_oops_counted = 0;
for (int i = 0; i < _the_table->table_size(); ++i) {
@@ -151,38 +153,27 @@
ResolvedMethodEntry* entry = _the_table->bucket(i);
while (entry != NULL) {
_oops_counted++;
- if (is_alive->do_object_b(entry->object_no_keepalive())) {
+ oop l = entry->object_no_keepalive();
+ if (l != NULL) {
p = entry->next_addr();
} else {
+ // Entry has been removed.
_oops_removed++;
if (log_is_enabled(Debug, membername, table)) {
- Method* m = (Method*)java_lang_invoke_ResolvedMethodName::vmtarget(entry->object_no_keepalive());
- ResourceMark rm;
- log_debug(membername, table) ("ResolvedMethod entry removed for %s index %d",
- m->name_and_sig_as_C_string(), i);
+ log_debug(membername, table) ("ResolvedMethod entry removed for index %d", i);
}
+ entry->literal().release();
*p = entry->next();
_the_table->free_entry(entry);
}
// get next entry
- entry = (ResolvedMethodEntry*)HashtableEntry<oop, mtClass>::make_ptr(*p);
+ entry = (ResolvedMethodEntry*)HashtableEntry<ClassLoaderWeakHandle, mtClass>::make_ptr(*p);
}
}
log_debug(membername, table) ("ResolvedMethod entries counted %d removed %d",
_oops_counted, _oops_removed);
}
-// Serially invoke "f->do_oop" on the locations of all oops in the table.
-void ResolvedMethodTable::oops_do(OopClosure* f) {
- for (int i = 0; i < _the_table->table_size(); ++i) {
- ResolvedMethodEntry* entry = _the_table->bucket(i);
- while (entry != NULL) {
- f->do_oop(entry->literal_addr());
- entry = entry->next();
- }
- }
-}
-
#ifndef PRODUCT
void ResolvedMethodTable::print() {
for (int i = 0; i < table_size(); ++i) {
@@ -190,9 +181,11 @@
while (entry != NULL) {
tty->print("%d : ", i);
oop rmethod_name = entry->object_no_keepalive();
- rmethod_name->print();
- Method* m = (Method*)java_lang_invoke_ResolvedMethodName::vmtarget(rmethod_name);
- m->print();
+ if (rmethod_name != NULL) {
+ rmethod_name->print();
+ Method* m = (Method*)java_lang_invoke_ResolvedMethodName::vmtarget(rmethod_name);
+ m->print();
+ }
entry = entry->next();
}
}
@@ -205,9 +198,15 @@
assert(SafepointSynchronize::is_at_safepoint(), "only called at safepoint");
// For each entry in RMT, change to new method
for (int i = 0; i < _the_table->table_size(); ++i) {
- ResolvedMethodEntry* entry = _the_table->bucket(i);
- while (entry != NULL) {
+ for (ResolvedMethodEntry* entry = _the_table->bucket(i);
+ entry != NULL;
+ entry = entry->next()) {
+
oop mem_name = entry->object_no_keepalive();
+ // except ones removed
+ if (mem_name == NULL) {
+ continue;
+ }
Method* old_method = (Method*)java_lang_invoke_ResolvedMethodName::vmtarget(mem_name);
if (old_method->is_old()) {
@@ -235,7 +234,6 @@
("ResolvedMethod method update: %s(%s)",
new_method->name()->as_C_string(), new_method->signature()->as_C_string());
}
- entry = entry->next();
}
}
}
--- a/src/hotspot/share/prims/resolvedMethodTable.hpp Wed Apr 18 14:07:41 2018 -0700
+++ b/src/hotspot/share/prims/resolvedMethodTable.hpp Fri Apr 20 09:05:05 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -26,22 +26,23 @@
#define SHARE_VM_PRIMS_RESOLVEDMETHOD_HPP
#include "oops/symbol.hpp"
+#include "oops/weakHandle.hpp"
#include "utilities/hashtable.hpp"
// Hashtable to record Method* used in ResolvedMethods, via. ResolvedMethod oops.
// This is needed for redefinition to replace Method* with redefined versions.
-// Entry in a ResolvedMethodTable, mapping a single oop of java_lang_invoke_ResolvedMethodName which
-// holds JVM Method* in vmtarget.
+// Entry in a ResolvedMethodTable, mapping a ClassLoaderWeakHandle for a single oop of
+// java_lang_invoke_ResolvedMethodName which holds JVM Method* in vmtarget.
-class ResolvedMethodEntry : public HashtableEntry<oop, mtClass> {
+class ResolvedMethodEntry : public HashtableEntry<ClassLoaderWeakHandle, mtClass> {
public:
ResolvedMethodEntry* next() const {
- return (ResolvedMethodEntry*)HashtableEntry<oop, mtClass>::next();
+ return (ResolvedMethodEntry*)HashtableEntry<ClassLoaderWeakHandle, mtClass>::next();
}
ResolvedMethodEntry** next_addr() {
- return (ResolvedMethodEntry**)HashtableEntry<oop, mtClass>::next_addr();
+ return (ResolvedMethodEntry**)HashtableEntry<ClassLoaderWeakHandle, mtClass>::next_addr();
}
oop object();
@@ -50,7 +51,7 @@
void print_on(outputStream* st) const;
};
-class ResolvedMethodTable : public Hashtable<oop, mtClass> {
+class ResolvedMethodTable : public Hashtable<ClassLoaderWeakHandle, mtClass> {
enum Constants {
_table_size = 1007
};
@@ -61,11 +62,11 @@
static ResolvedMethodTable* _the_table;
private:
ResolvedMethodEntry* bucket(int i) {
- return (ResolvedMethodEntry*) Hashtable<oop, mtClass>::bucket(i);
+ return (ResolvedMethodEntry*) Hashtable<ClassLoaderWeakHandle, mtClass>::bucket(i);
}
ResolvedMethodEntry** bucket_addr(int i) {
- return (ResolvedMethodEntry**) Hashtable<oop, mtClass>::bucket_addr(i);
+ return (ResolvedMethodEntry**) Hashtable<ClassLoaderWeakHandle, mtClass>::bucket_addr(i);
}
unsigned int compute_hash(Method* method);
@@ -75,7 +76,7 @@
oop lookup(Method* method);
// must be done under ResolvedMethodTable_lock
- oop basic_add(Method* method, oop rmethod_name);
+ oop basic_add(Method* method, Handle rmethod_name);
public:
ResolvedMethodTable();
@@ -95,8 +96,7 @@
#endif // INCLUDE_JVMTI
// Cleanup cleared entries
- static void unlink(BoolObjectClosure* is_alive);
- static void oops_do(OopClosure* f);
+ static void unlink();
#ifndef PRODUCT
void print();
--- a/src/hotspot/share/prims/whitebox.cpp Wed Apr 18 14:07:41 2018 -0700
+++ b/src/hotspot/share/prims/whitebox.cpp Fri Apr 20 09:05:05 2018 -0700
@@ -933,8 +933,6 @@
return result;
WB_END
-static AlwaysFalseClosure always_false;
-
WB_ENTRY(void, WB_ClearMethodState(JNIEnv* env, jobject o, jobject method))
jmethodID jmid = reflected_method_to_jmid(thread, env, method);
CHECK_JNI_EXCEPTION(env);
@@ -951,7 +949,7 @@
mdo->set_arg_modified(i, 0);
}
MutexLockerEx mu(mdo->extra_data_lock());
- mdo->clean_method_data(&always_false);
+ mdo->clean_method_data(/*always_clean*/true);
}
mh->clear_not_c1_compilable();
--- a/src/hotspot/share/runtime/mutex.hpp Wed Apr 18 14:07:41 2018 -0700
+++ b/src/hotspot/share/runtime/mutex.hpp Fri Apr 20 09:05:05 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -106,7 +106,8 @@
access = event + 1,
special = access + 2,
suspend_resume = special + 1,
- leaf = suspend_resume + 2,
+ vmweak = suspend_resume + 2,
+ leaf = vmweak + 2,
safepoint = leaf + 10,
barrier = safepoint + 1,
nonleaf = barrier + 1,
--- a/src/hotspot/share/runtime/mutexLocker.cpp Wed Apr 18 14:07:41 2018 -0700
+++ b/src/hotspot/share/runtime/mutexLocker.cpp Fri Apr 20 09:05:05 2018 -0700
@@ -182,6 +182,9 @@
def(CGC_lock , PaddedMonitor, special, true, Monitor::_safepoint_check_never); // coordinate between fore- and background GC
def(STS_lock , PaddedMonitor, leaf, true, Monitor::_safepoint_check_never);
+ def(VMWeakAlloc_lock , PaddedMutex , vmweak, true, Monitor::_safepoint_check_never);
+ def(VMWeakActive_lock , PaddedMutex , vmweak-1, true, Monitor::_safepoint_check_never);
+
if (UseConcMarkSweepGC || UseG1GC) {
def(FullGCCount_lock , PaddedMonitor, leaf, true, Monitor::_safepoint_check_never); // in support of ExplicitGCInvokesConcurrent
}
@@ -262,8 +265,6 @@
def(JNIGlobalActive_lock , PaddedMutex , nonleaf-1, true, Monitor::_safepoint_check_never);
def(JNIWeakAlloc_lock , PaddedMutex , nonleaf, true, Monitor::_safepoint_check_never);
def(JNIWeakActive_lock , PaddedMutex , nonleaf-1, true, Monitor::_safepoint_check_never);
- def(VMWeakAlloc_lock , PaddedMutex , nonleaf, true, Monitor::_safepoint_check_never);
- def(VMWeakActive_lock , PaddedMutex , nonleaf-1, true, Monitor::_safepoint_check_never);
def(JNICritical_lock , PaddedMonitor, nonleaf, true, Monitor::_safepoint_check_always); // used for JNI critical regions
def(AdapterHandlerLibrary_lock , PaddedMutex , nonleaf, true, Monitor::_safepoint_check_always);
--- a/src/hotspot/share/runtime/thread.cpp Wed Apr 18 14:07:41 2018 -0700
+++ b/src/hotspot/share/runtime/thread.cpp Fri Apr 20 09:05:05 2018 -0700
@@ -1495,7 +1495,6 @@
jlong* JavaThread::_jvmci_old_thread_counters;
bool jvmci_counters_include(JavaThread* thread) {
- oop threadObj = thread->threadObj();
return !JVMCICountersExcludeCompiler || !thread->is_Compiler_thread();
}
--- a/src/hotspot/share/runtime/vmStructs.cpp Wed Apr 18 14:07:41 2018 -0700
+++ b/src/hotspot/share/runtime/vmStructs.cpp Fri Apr 20 09:05:05 2018 -0700
@@ -543,7 +543,7 @@
/*******************/ \
/* ClassLoaderData */ \
/*******************/ \
- nonstatic_field(ClassLoaderData, _class_loader, oop) \
+ nonstatic_field(ClassLoaderData, _class_loader, OopHandle) \
nonstatic_field(ClassLoaderData, _next, ClassLoaderData*) \
volatile_nonstatic_field(ClassLoaderData, _klasses, Klass*) \
nonstatic_field(ClassLoaderData, _is_anonymous, bool) \
--- a/src/hotspot/share/services/classLoadingService.cpp Wed Apr 18 14:07:41 2018 -0700
+++ b/src/hotspot/share/services/classLoadingService.cpp Fri Apr 20 09:05:05 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -53,7 +53,7 @@
len = name->utf8_length(); \
} \
HOTSPOT_CLASS_##type( /* type = unloaded, loaded */ \
- data, len, (void*)(clss)->class_loader(), (shared)); \
+ data, len, (void*)(clss)->class_loader_data(), (shared)); \
}
#else // ndef DTRACE_ENABLED
--- a/src/hotspot/share/services/diagnosticCommand.cpp Wed Apr 18 14:07:41 2018 -0700
+++ b/src/hotspot/share/services/diagnosticCommand.cpp Fri Apr 20 09:05:05 2018 -0700
@@ -931,7 +931,7 @@
//---< BEGIN >--- CodeHeap State Analytics.
CodeHeapAnalyticsDCmd::CodeHeapAnalyticsDCmd(outputStream* output, bool heap) :
DCmdWithParser(output, heap),
- _function("function", "Function to be performed (aggregate, UsedSpace, FreeSpace, MethodCount, MethodSpace, MethodAge, discard", "STRING", false, "all"),
+ _function("function", "Function to be performed (aggregate, UsedSpace, FreeSpace, MethodCount, MethodSpace, MethodAge, MethodNames, discard", "STRING", false, "all"),
_granularity("granularity", "Detail level - smaller value -> more detail", "STRING", false, "4096") {
_dcmdparser.add_dcmd_argument(&_function);
_dcmdparser.add_dcmd_argument(&_granularity);
--- a/src/hotspot/share/trace/traceStream.cpp Wed Apr 18 14:07:41 2018 -0700
+++ b/src/hotspot/share/trace/traceStream.cpp Fri Apr 20 09:05:05 2018 -0700
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+* Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -25,7 +25,7 @@
#include "precompiled.hpp"
#include "trace/traceStream.hpp"
#if INCLUDE_TRACE
-#include "classfile/classLoaderData.hpp"
+#include "classfile/classLoaderData.inline.hpp"
#include "classfile/javaClasses.inline.hpp"
#include "memory/resourceArea.hpp"
#include "oops/klass.hpp"
--- a/src/hotspot/share/utilities/bitMap.cpp Wed Apr 18 14:07:41 2018 -0700
+++ b/src/hotspot/share/utilities/bitMap.cpp Fri Apr 20 09:05:05 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -72,7 +72,7 @@
};
template <class Allocator>
-BitMap::bm_word_t* BitMap::reallocate(const Allocator& allocator, bm_word_t* old_map, idx_t old_size_in_bits, idx_t new_size_in_bits) {
+BitMap::bm_word_t* BitMap::reallocate(const Allocator& allocator, bm_word_t* old_map, idx_t old_size_in_bits, idx_t new_size_in_bits, bool clear) {
size_t old_size_in_words = calc_size_in_words(old_size_in_bits);
size_t new_size_in_words = calc_size_in_words(new_size_in_bits);
@@ -86,7 +86,7 @@
MIN2(old_size_in_words, new_size_in_words));
}
- if (new_size_in_words > old_size_in_words) {
+ if (clear && new_size_in_words > old_size_in_words) {
clear_range_of_words(map, old_size_in_words, new_size_in_words);
}
}
@@ -99,9 +99,9 @@
}
template <class Allocator>
-bm_word_t* BitMap::allocate(const Allocator& allocator, idx_t size_in_bits) {
+bm_word_t* BitMap::allocate(const Allocator& allocator, idx_t size_in_bits, bool clear) {
// Reuse reallocate to ensure that the new memory is cleared.
- return reallocate(allocator, NULL, 0, size_in_bits);
+ return reallocate(allocator, NULL, 0, size_in_bits, clear);
}
template <class Allocator>
@@ -153,8 +153,8 @@
: BitMap(allocate(ArenaBitMapAllocator(arena), size_in_bits), size_in_bits) {
}
-CHeapBitMap::CHeapBitMap(idx_t size_in_bits, MEMFLAGS flags)
- : BitMap(allocate(CHeapBitMapAllocator(flags), size_in_bits), size_in_bits), _flags(flags) {
+CHeapBitMap::CHeapBitMap(idx_t size_in_bits, MEMFLAGS flags, bool clear)
+ : BitMap(allocate(CHeapBitMapAllocator(flags), size_in_bits, clear), size_in_bits), _flags(flags) {
}
CHeapBitMap::~CHeapBitMap() {
--- a/src/hotspot/share/utilities/bitMap.hpp Wed Apr 18 14:07:41 2018 -0700
+++ b/src/hotspot/share/utilities/bitMap.hpp Fri Apr 20 09:05:05 2018 -0700
@@ -123,11 +123,11 @@
// Allocates and clears the bitmap memory.
template <class Allocator>
- static bm_word_t* allocate(const Allocator&, idx_t size_in_bits);
+ static bm_word_t* allocate(const Allocator&, idx_t size_in_bits, bool clear = true);
// Reallocates and clears the new bitmap memory.
template <class Allocator>
- static bm_word_t* reallocate(const Allocator&, bm_word_t* map, idx_t old_size_in_bits, idx_t new_size_in_bits);
+ static bm_word_t* reallocate(const Allocator&, bm_word_t* map, idx_t old_size_in_bits, idx_t new_size_in_bits, bool clear = true);
// Free the bitmap memory.
template <class Allocator>
@@ -359,7 +359,7 @@
public:
CHeapBitMap(MEMFLAGS flags = mtInternal) : BitMap(NULL, 0), _flags(flags) {}
// Clears the bitmap memory.
- CHeapBitMap(idx_t size_in_bits, MEMFLAGS flags = mtInternal);
+ CHeapBitMap(idx_t size_in_bits, MEMFLAGS flags = mtInternal, bool clear = true);
~CHeapBitMap();
// Resize the backing bitmap memory.
--- a/src/hotspot/share/utilities/hashtable.cpp Wed Apr 18 14:07:41 2018 -0700
+++ b/src/hotspot/share/utilities/hashtable.cpp Fri Apr 20 09:05:05 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -35,6 +35,7 @@
#include "memory/metaspaceShared.hpp"
#include "memory/resourceArea.hpp"
#include "oops/oop.inline.hpp"
+#include "oops/weakHandle.inline.hpp"
#include "runtime/safepoint.hpp"
#include "utilities/dtrace.hpp"
#include "utilities/hashtable.hpp"
@@ -148,7 +149,6 @@
}
// give the new table the free list as well
new_table->copy_freelist(this);
- assert(new_table->number_of_entries() == saved_entry_count, "lost entry on dictionary copy?");
// Destroy memory used by the buckets in the hashtable. The memory
// for the elements has been used in a new table and is not
@@ -263,6 +263,10 @@
}
}
+static int literal_size(ClassLoaderWeakHandle v) {
+ return literal_size(v.peek());
+}
+
template <MEMFLAGS F> bool BasicHashtable<F>::resize(int new_size) {
assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint");
@@ -382,6 +386,13 @@
}
#ifndef PRODUCT
+template <class T> void print_literal(T l) {
+ l->print();
+}
+
+static void print_literal(ClassLoaderWeakHandle l) {
+ l.print();
+}
template <class T, MEMFLAGS F> void Hashtable<T, F>::print() {
ResourceMark rm;
@@ -390,7 +401,7 @@
HashtableEntry<T, F>* entry = bucket(i);
while(entry != NULL) {
tty->print("%d : ", i);
- entry->literal()->print();
+ print_literal(entry->literal());
tty->cr();
entry = entry->next();
}
@@ -443,21 +454,19 @@
#endif
template class Hashtable<ConstantPool*, mtClass>;
template class RehashableHashtable<Symbol*, mtSymbol>;
-template class RehashableHashtable<oopDesc*, mtSymbol>;
+template class RehashableHashtable<oop, mtSymbol>;
template class Hashtable<Symbol*, mtSymbol>;
template class Hashtable<Klass*, mtClass>;
template class Hashtable<InstanceKlass*, mtClass>;
-template class Hashtable<oop, mtClass>;
+template class Hashtable<ClassLoaderWeakHandle, mtClass>;
template class Hashtable<Symbol*, mtModule>;
-#if defined(SOLARIS) || defined(CHECK_UNHANDLED_OOPS)
template class Hashtable<oop, mtSymbol>;
-template class RehashableHashtable<oop, mtSymbol>;
-#endif // SOLARIS || CHECK_UNHANDLED_OOPS
-template class Hashtable<oopDesc*, mtSymbol>;
+template class Hashtable<ClassLoaderWeakHandle, mtSymbol>;
template class Hashtable<Symbol*, mtClass>;
template class HashtableEntry<Symbol*, mtSymbol>;
template class HashtableEntry<Symbol*, mtClass>;
template class HashtableEntry<oop, mtSymbol>;
+template class HashtableEntry<ClassLoaderWeakHandle, mtSymbol>;
template class HashtableBucket<mtClass>;
template class BasicHashtableEntry<mtSymbol>;
template class BasicHashtableEntry<mtCode>;
--- a/src/hotspot/share/utilities/ostream.cpp Wed Apr 18 14:07:41 2018 -0700
+++ b/src/hotspot/share/utilities/ostream.cpp Fri Apr 20 09:05:05 2018 -0700
@@ -36,7 +36,9 @@
#include "utilities/vmError.hpp"
#include "utilities/xmlstream.hpp"
-extern "C" void jio_print(const char* s); // Declarationtion of jvm method
+// Declarations of jvm methods
+extern "C" void jio_print(const char* s, size_t len);
+extern "C" int jio_printf(const char *fmt, ...);
outputStream::outputStream(int width) {
_width = width;
@@ -612,19 +614,15 @@
// Try again to open the file in the temp directory.
delete file;
- char warnbuf[O_BUFLEN*2];
- jio_snprintf(warnbuf, sizeof(warnbuf), "Warning: Cannot open log file: %s\n", log_name);
- // Note: This feature is for maintainer use only. No need for L10N.
- jio_print(warnbuf);
+ // Note: This feature is for maintainer use only. No need for L10N.
+ jio_printf("Warning: Cannot open log file: %s\n", log_name);
try_name = make_log_name(log_name, os::get_temp_directory());
if (try_name == NULL) {
warning("Cannot open file %s: file name is too long for directory %s.\n", log_name, os::get_temp_directory());
return NULL;
}
- jio_snprintf(warnbuf, sizeof(warnbuf),
- "Warning: Forcing option -XX:LogFile=%s\n", try_name);
- jio_print(warnbuf);
+ jio_printf("Warning: Forcing option -XX:LogFile=%s\n", try_name);
file = new(ResourceObj::C_HEAP, mtInternal) fileStream(try_name);
FREE_C_HEAP_ARRAY(char, try_name);
@@ -824,20 +822,6 @@
tty_lock->unlock();
}
-
-// Yuck: jio_print does not accept char*/len.
-static void call_jio_print(const char* s, size_t len) {
- char buffer[O_BUFLEN+100];
- if (len > sizeof(buffer)-1) {
- warning("increase O_BUFLEN in ostream.cpp -- output truncated");
- len = sizeof(buffer)-1;
- }
- strncpy(buffer, s, len);
- buffer[len] = '\0';
- jio_print(buffer);
-}
-
-
void defaultStream::write(const char* s, size_t len) {
intx thread_id = os::current_thread_id();
intx holder = hold(thread_id);
@@ -845,11 +829,7 @@
if (DisplayVMOutput &&
(_outer_xmlStream == NULL || !_outer_xmlStream->inside_attrs())) {
// print to output stream. It can be redirected by a vfprintf hook
- if (s[len] == '\0') {
- jio_print(s);
- } else {
- call_jio_print(s, len);
- }
+ jio_print(s, len);
}
// print to log file
--- a/src/java.base/share/classes/java/util/Optional.java Wed Apr 18 14:07:41 2018 -0700
+++ b/src/java.base/share/classes/java/util/Optional.java Fri Apr 20 09:05:05 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -160,6 +160,17 @@
}
/**
+ * If a value is not present, returns {@code true}, otherwise
+ * {@code false}.
+ *
+ * @return {@code true} if a value is not present, otherwise {@code false}
+ * @since 11
+ */
+ public boolean isEmpty() {
+ return value == null;
+ }
+
+ /**
* If a value is present, performs the given action with the value,
* otherwise does nothing.
*
--- a/src/java.base/share/classes/java/util/OptionalDouble.java Wed Apr 18 14:07:41 2018 -0700
+++ b/src/java.base/share/classes/java/util/OptionalDouble.java Fri Apr 20 09:05:05 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -140,6 +140,17 @@
}
/**
+ * If a value is not present, returns {@code true}, otherwise
+ * {@code false}.
+ *
+ * @return {@code true} if a value is not present, otherwise {@code false}
+ * @since 11
+ */
+ public boolean isEmpty() {
+ return !isPresent;
+ }
+
+ /**
* If a value is present, performs the given action with the value,
* otherwise does nothing.
*
--- a/src/java.base/share/classes/java/util/OptionalInt.java Wed Apr 18 14:07:41 2018 -0700
+++ b/src/java.base/share/classes/java/util/OptionalInt.java Fri Apr 20 09:05:05 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -140,6 +140,17 @@
}
/**
+ * If a value is not present, returns {@code true}, otherwise
+ * {@code false}.
+ *
+ * @return {@code true} if a value is not present, otherwise {@code false}
+ * @since 11
+ */
+ public boolean isEmpty() {
+ return !isPresent;
+ }
+
+ /**
* If a value is present, performs the given action with the value,
* otherwise does nothing.
*
--- a/src/java.base/share/classes/java/util/OptionalLong.java Wed Apr 18 14:07:41 2018 -0700
+++ b/src/java.base/share/classes/java/util/OptionalLong.java Fri Apr 20 09:05:05 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -140,6 +140,17 @@
}
/**
+ * If a value is not present, returns {@code true}, otherwise
+ * {@code false}.
+ *
+ * @return {@code true} if a value is not present, otherwise {@code false}
+ * @since 11
+ */
+ public boolean isEmpty() {
+ return !isPresent;
+ }
+
+ /**
* If a value is present, performs the given action with the value,
* otherwise does nothing.
*
--- a/src/java.base/share/classes/java/util/zip/Deflater.java Wed Apr 18 14:07:41 2018 -0700
+++ b/src/java.base/share/classes/java/util/zip/Deflater.java Fri Apr 20 09:05:05 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -26,7 +26,13 @@
package java.util.zip;
import java.lang.ref.Cleaner.Cleanable;
+import java.lang.ref.Reference;
+import java.nio.ByteBuffer;
+import java.nio.ReadOnlyBufferException;
+import java.util.Objects;
+
import jdk.internal.ref.CleanerFactory;
+import sun.nio.ch.DirectBuffer;
/**
* This class provides support for general purpose compression using the
@@ -35,8 +41,14 @@
* protected by patents. It is fully described in the specifications at
* the <a href="package-summary.html#package.description">java.util.zip
* package description</a>.
- *
- * <p>The following code fragment demonstrates a trivial compression
+ * <p>
+ * This class deflates sequences of bytes into ZLIB compressed data format.
+ * The input byte sequence is provided in either byte array or byte buffer,
+ * via one of the {@code setInput()} methods. The output byte sequence is
+ * written to the output byte array or byte buffer passed to the
+ * {@code deflate()} methods.
+ * <p>
+ * The following code fragment demonstrates a trivial compression
* and decompression of a string using {@code Deflater} and
* {@code Inflater}.
*
@@ -92,8 +104,9 @@
public class Deflater {
private final DeflaterZStreamRef zsRef;
- private byte[] buf = new byte[0];
- private int off, len;
+ private ByteBuffer input = ZipUtils.defaultBuf;
+ private byte[] inputArray;
+ private int inputPos, inputLim;
private int level, strategy;
private boolean setParams;
private boolean finish, finished;
@@ -170,9 +183,14 @@
*/
public static final int FULL_FLUSH = 3;
+ /**
+ * Flush mode to use at the end of output. Can only be provided by the
+ * user by way of {@link #finish()}.
+ */
+ private static final int FINISH = 4;
+
static {
ZipUtils.loadLibrary();
- initIDs();
}
/**
@@ -208,59 +226,70 @@
}
/**
- * Sets input data for compression. This should be called whenever
- * needsInput() returns true indicating that more input data is required.
- * @param b the input data bytes
+ * Sets input data for compression.
+ * <p>
+ * One of the {@code setInput()} methods should be called whenever
+ * {@code needsInput()} returns true indicating that more input data
+ * is required.
+ * <p>
+ * @param input the input data bytes
* @param off the start offset of the data
* @param len the length of the data
* @see Deflater#needsInput
*/
- public void setInput(byte[] b, int off, int len) {
- if (b== null) {
- throw new NullPointerException();
- }
- if (off < 0 || len < 0 || off > b.length - len) {
+ public void setInput(byte[] input, int off, int len) {
+ if (off < 0 || len < 0 || off > input.length - len) {
throw new ArrayIndexOutOfBoundsException();
}
synchronized (zsRef) {
- this.buf = b;
- this.off = off;
- this.len = len;
+ this.input = null;
+ this.inputArray = input;
+ this.inputPos = off;
+ this.inputLim = off + len;
}
}
/**
- * Sets input data for compression. This should be called whenever
- * needsInput() returns true indicating that more input data is required.
- * @param b the input data bytes
+ * Sets input data for compression.
+ * <p>
+ * One of the {@code setInput()} methods should be called whenever
+ * {@code needsInput()} returns true indicating that more input data
+ * is required.
+ * <p>
+ * @param input the input data bytes
* @see Deflater#needsInput
*/
- public void setInput(byte[] b) {
- setInput(b, 0, b.length);
+ public void setInput(byte[] input) {
+ setInput(input, 0, input.length);
}
/**
- * Sets preset dictionary for compression. A preset dictionary is used
- * when the history buffer can be predetermined. When the data is later
- * uncompressed with Inflater.inflate(), Inflater.getAdler() can be called
- * in order to get the Adler-32 value of the dictionary required for
- * decompression.
- * @param b the dictionary data bytes
- * @param off the start offset of the data
- * @param len the length of the data
- * @see Inflater#inflate
- * @see Inflater#getAdler
+ * Sets input data for compression.
+ * <p>
+ * One of the {@code setInput()} methods should be called whenever
+ * {@code needsInput()} returns true indicating that more input data
+ * is required.
+ * <p>
+ * The given buffer's position will be advanced as deflate
+ * operations are performed, up to the buffer's limit.
+ * The input buffer may be modified (refilled) between deflate
+ * operations; doing so is equivalent to creating a new buffer
+ * and setting it with this method.
+ * <p>
+ * Modifying the input buffer's contents, position, or limit
+ * concurrently with an deflate operation will result in
+ * undefined behavior, which may include incorrect operation
+ * results or operation failure.
+ *
+ * @param input the input data bytes
+ * @see Deflater#needsInput
+ * @since 11
*/
- public void setDictionary(byte[] b, int off, int len) {
- if (b == null) {
- throw new NullPointerException();
- }
- if (off < 0 || len < 0 || off > b.length - len) {
- throw new ArrayIndexOutOfBoundsException();
- }
+ public void setInput(ByteBuffer input) {
+ Objects.requireNonNull(input);
synchronized (zsRef) {
- ensureOpen();
- setDictionary(zsRef.address(), b, off, len);
+ this.input = input;
+ this.inputArray = null;
}
}
@@ -270,12 +299,69 @@
* uncompressed with Inflater.inflate(), Inflater.getAdler() can be called
* in order to get the Adler-32 value of the dictionary required for
* decompression.
- * @param b the dictionary data bytes
+ * @param dictionary the dictionary data bytes
+ * @param off the start offset of the data
+ * @param len the length of the data
+ * @see Inflater#inflate
+ * @see Inflater#getAdler
+ */
+ public void setDictionary(byte[] dictionary, int off, int len) {
+ if (off < 0 || len < 0 || off > dictionary.length - len) {
+ throw new ArrayIndexOutOfBoundsException();
+ }
+ synchronized (zsRef) {
+ ensureOpen();
+ setDictionary(zsRef.address(), dictionary, off, len);
+ }
+ }
+
+ /**
+ * Sets preset dictionary for compression. A preset dictionary is used
+ * when the history buffer can be predetermined. When the data is later
+ * uncompressed with Inflater.inflate(), Inflater.getAdler() can be called
+ * in order to get the Adler-32 value of the dictionary required for
+ * decompression.
+ * @param dictionary the dictionary data bytes
* @see Inflater#inflate
* @see Inflater#getAdler
*/
- public void setDictionary(byte[] b) {
- setDictionary(b, 0, b.length);
+ public void setDictionary(byte[] dictionary) {
+ setDictionary(dictionary, 0, dictionary.length);
+ }
+
+ /**
+ * Sets preset dictionary for compression. A preset dictionary is used
+ * when the history buffer can be predetermined. When the data is later
+ * uncompressed with Inflater.inflate(), Inflater.getAdler() can be called
+ * in order to get the Adler-32 value of the dictionary required for
+ * decompression.
+ * <p>
+ * The bytes in given byte buffer will be fully consumed by this method. On
+ * return, its position will equal its limit.
+ *
+ * @param dictionary the dictionary data bytes
+ * @see Inflater#inflate
+ * @see Inflater#getAdler
+ */
+ public void setDictionary(ByteBuffer dictionary) {
+ synchronized (zsRef) {
+ int position = dictionary.position();
+ int remaining = Math.max(dictionary.limit() - position, 0);
+ ensureOpen();
+ if (dictionary.isDirect()) {
+ long address = ((DirectBuffer) dictionary).address();
+ try {
+ setDictionaryBuffer(zsRef.address(), address + position, remaining);
+ } finally {
+ Reference.reachabilityFence(dictionary);
+ }
+ } else {
+ byte[] array = ZipUtils.getBufferArray(dictionary);
+ int offset = ZipUtils.getBufferOffset(dictionary);
+ setDictionary(zsRef.address(), array, offset + position, remaining);
+ }
+ dictionary.position(position + remaining);
+ }
}
/**
@@ -331,14 +417,17 @@
}
/**
- * Returns true if the input data buffer is empty and setInput()
- * should be called in order to provide more input.
+ * Returns true if no data remains in the input buffer. This can
+ * be used to determine if one of the {@code setInput()} methods should be
+ * called in order to provide more input.
+ *
* @return true if the input data buffer is empty and setInput()
* should be called in order to provide more input
*/
public boolean needsInput() {
synchronized (zsRef) {
- return len <= 0;
+ ByteBuffer input = this.input;
+ return input == null ? inputLim == inputPos : ! input.hasRemaining();
}
}
@@ -375,14 +464,14 @@
* yields the same result as the invocation of
* {@code deflater.deflate(b, off, len, Deflater.NO_FLUSH)}.
*
- * @param b the buffer for the compressed data
+ * @param output the buffer for the compressed data
* @param off the start offset of the data
* @param len the maximum number of bytes of compressed data
* @return the actual number of bytes of compressed data written to the
* output buffer
*/
- public int deflate(byte[] b, int off, int len) {
- return deflate(b, off, len, NO_FLUSH);
+ public int deflate(byte[] output, int off, int len) {
+ return deflate(output, off, len, NO_FLUSH);
}
/**
@@ -396,12 +485,32 @@
* yields the same result as the invocation of
* {@code deflater.deflate(b, 0, b.length, Deflater.NO_FLUSH)}.
*
- * @param b the buffer for the compressed data
+ * @param output the buffer for the compressed data
* @return the actual number of bytes of compressed data written to the
* output buffer
*/
- public int deflate(byte[] b) {
- return deflate(b, 0, b.length, NO_FLUSH);
+ public int deflate(byte[] output) {
+ return deflate(output, 0, output.length, NO_FLUSH);
+ }
+
+ /**
+ * Compresses the input data and fills specified buffer with compressed
+ * data. Returns actual number of bytes of compressed data. A return value
+ * of 0 indicates that {@link #needsInput() needsInput} should be called
+ * in order to determine if more input data is required.
+ *
+ * <p>This method uses {@link #NO_FLUSH} as its compression flush mode.
+ * An invocation of this method of the form {@code deflater.deflate(output)}
+ * yields the same result as the invocation of
+ * {@code deflater.deflate(output, Deflater.NO_FLUSH)}.
+ *
+ * @param output the buffer for the compressed data
+ * @return the actual number of bytes of compressed data written to the
+ * output buffer
+ * @since 11
+ */
+ public int deflate(ByteBuffer output) {
+ return deflate(output, NO_FLUSH);
}
/**
@@ -441,7 +550,11 @@
* repeatedly output to the output buffer every time this method is
* invoked.
*
- * @param b the buffer for the compressed data
+ * <p>If the {@link #setInput(ByteBuffer)} method was called to provide a buffer
+ * for input, the input buffer's position will be advanced by the number of bytes
+ * consumed by this operation.
+ *
+ * @param output the buffer for the compressed data
* @param off the start offset of the data
* @param len the maximum number of bytes of compressed data
* @param flush the compression flush mode
@@ -451,25 +564,248 @@
* @throws IllegalArgumentException if the flush mode is invalid
* @since 1.7
*/
- public int deflate(byte[] b, int off, int len, int flush) {
- if (b == null) {
- throw new NullPointerException();
+ public int deflate(byte[] output, int off, int len, int flush) {
+ if (off < 0 || len < 0 || off > output.length - len) {
+ throw new ArrayIndexOutOfBoundsException();
}
- if (off < 0 || len < 0 || off > b.length - len) {
- throw new ArrayIndexOutOfBoundsException();
+ if (flush != NO_FLUSH && flush != SYNC_FLUSH && flush != FULL_FLUSH) {
+ throw new IllegalArgumentException();
}
synchronized (zsRef) {
ensureOpen();
- if (flush == NO_FLUSH || flush == SYNC_FLUSH ||
- flush == FULL_FLUSH) {
- int thisLen = this.len;
- int n = deflateBytes(zsRef.address(), b, off, len, flush);
- bytesWritten += n;
- bytesRead += (thisLen - this.len);
- return n;
+
+ ByteBuffer input = this.input;
+ if (finish) {
+ // disregard given flush mode in this case
+ flush = FINISH;
+ }
+ int params;
+ if (setParams) {
+ // bit 0: true to set params
+ // bit 1-2: strategy (0, 1, or 2)
+ // bit 3-31: level (0..9 or -1)
+ params = 1 | strategy << 1 | level << 3;
+ } else {
+ params = 0;
+ }
+ int inputPos;
+ long result;
+ if (input == null) {
+ inputPos = this.inputPos;
+ result = deflateBytesBytes(zsRef.address(),
+ inputArray, inputPos, inputLim - inputPos,
+ output, off, len,
+ flush, params);
+ } else {
+ inputPos = input.position();
+ int inputRem = Math.max(input.limit() - inputPos, 0);
+ if (input.isDirect()) {
+ try {
+ long inputAddress = ((DirectBuffer) input).address();
+ result = deflateBufferBytes(zsRef.address(),
+ inputAddress + inputPos, inputRem,
+ output, off, len,
+ flush, params);
+ } finally {
+ Reference.reachabilityFence(input);
+ }
+ } else {
+ byte[] inputArray = ZipUtils.getBufferArray(input);
+ int inputOffset = ZipUtils.getBufferOffset(input);
+ result = deflateBytesBytes(zsRef.address(),
+ inputArray, inputOffset + inputPos, inputRem,
+ output, off, len,
+ flush, params);
+ }
+ }
+ int read = (int) (result & 0x7fff_ffffL);
+ int written = (int) (result >>> 31 & 0x7fff_ffffL);
+ if ((result >>> 62 & 1) != 0) {
+ finished = true;
+ }
+ if (params != 0 && (result >>> 63 & 1) == 0) {
+ setParams = false;
+ }
+ if (input != null) {
+ input.position(inputPos + read);
+ } else {
+ this.inputPos = inputPos + read;
}
+ bytesWritten += written;
+ bytesRead += read;
+ return written;
+ }
+ }
+
+ /**
+ * Compresses the input data and fills the specified buffer with compressed
+ * data. Returns actual number of bytes of data compressed.
+ *
+ * <p>Compression flush mode is one of the following three modes:
+ *
+ * <ul>
+ * <li>{@link #NO_FLUSH}: allows the deflater to decide how much data
+ * to accumulate, before producing output, in order to achieve the best
+ * compression (should be used in normal use scenario). A return value
+ * of 0 in this flush mode indicates that {@link #needsInput()} should
+ * be called in order to determine if more input data is required.
+ *
+ * <li>{@link #SYNC_FLUSH}: all pending output in the deflater is flushed,
+ * to the specified output buffer, so that an inflater that works on
+ * compressed data can get all input data available so far (In particular
+ * the {@link #needsInput()} returns {@code true} after this invocation
+ * if enough output space is provided). Flushing with {@link #SYNC_FLUSH}
+ * may degrade compression for some compression algorithms and so it
+ * should be used only when necessary.
+ *
+ * <li>{@link #FULL_FLUSH}: all pending output is flushed out as with
+ * {@link #SYNC_FLUSH}. The compression state is reset so that the inflater
+ * that works on the compressed output data can restart from this point
+ * if previous compressed data has been damaged or if random access is
+ * desired. Using {@link #FULL_FLUSH} too often can seriously degrade
+ * compression.
+ * </ul>
+ *
+ * <p>In the case of {@link #FULL_FLUSH} or {@link #SYNC_FLUSH}, if
+ * the return value is equal to the {@linkplain ByteBuffer#remaining() remaining space}
+ * of the buffer, this method should be invoked again with the same
+ * {@code flush} parameter and more output space. Make sure that
+ * the buffer has at least 6 bytes of remaining space to avoid the
+ * flush marker (5 bytes) being repeatedly output to the output buffer
+ * every time this method is invoked.
+ *
+ * <p>On success, the position of the given {@code output} byte buffer will be
+ * advanced by as many bytes as were produced by the operation, which is equal
+ * to the number returned by this method.
+ *
+ * <p>If the {@link #setInput(ByteBuffer)} method was called to provide a buffer
+ * for input, the input buffer's position will be advanced by the number of bytes
+ * consumed by this operation.
+ *
+ * @param output the buffer for the compressed data
+ * @param flush the compression flush mode
+ * @return the actual number of bytes of compressed data written to
+ * the output buffer
+ *
+ * @throws IllegalArgumentException if the flush mode is invalid
+ * @since 11
+ */
+ public int deflate(ByteBuffer output, int flush) {
+ if (output.isReadOnly()) {
+ throw new ReadOnlyBufferException();
+ }
+ if (flush != NO_FLUSH && flush != SYNC_FLUSH && flush != FULL_FLUSH) {
throw new IllegalArgumentException();
}
+ synchronized (zsRef) {
+ ensureOpen();
+
+ ByteBuffer input = this.input;
+ if (finish) {
+ // disregard given flush mode in this case
+ flush = FINISH;
+ }
+ int params;
+ if (setParams) {
+ // bit 0: true to set params
+ // bit 1-2: strategy (0, 1, or 2)
+ // bit 3-31: level (0..9 or -1)
+ params = 1 | strategy << 1 | level << 3;
+ } else {
+ params = 0;
+ }
+ int outputPos = output.position();
+ int outputRem = Math.max(output.limit() - outputPos, 0);
+ int inputPos;
+ long result;
+ if (input == null) {
+ inputPos = this.inputPos;
+ if (output.isDirect()) {
+ long outputAddress = ((DirectBuffer) output).address();
+ try {
+ result = deflateBytesBuffer(zsRef.address(),
+ inputArray, inputPos, inputLim - inputPos,
+ outputAddress + outputPos, outputRem,
+ flush, params);
+ } finally {
+ Reference.reachabilityFence(output);
+ }
+ } else {
+ byte[] outputArray = ZipUtils.getBufferArray(output);
+ int outputOffset = ZipUtils.getBufferOffset(output);
+ result = deflateBytesBytes(zsRef.address(),
+ inputArray, inputPos, inputLim - inputPos,
+ outputArray, outputOffset + outputPos, outputRem,
+ flush, params);
+ }
+ } else {
+ inputPos = input.position();
+ int inputRem = Math.max(input.limit() - inputPos, 0);
+ if (input.isDirect()) {
+ long inputAddress = ((DirectBuffer) input).address();
+ try {
+ if (output.isDirect()) {
+ long outputAddress = outputPos + ((DirectBuffer) output).address();
+ try {
+ result = deflateBufferBuffer(zsRef.address(),
+ inputAddress + inputPos, inputRem,
+ outputAddress, outputRem,
+ flush, params);
+ } finally {
+ Reference.reachabilityFence(output);
+ }
+ } else {
+ byte[] outputArray = ZipUtils.getBufferArray(output);
+ int outputOffset = ZipUtils.getBufferOffset(output);
+ result = deflateBufferBytes(zsRef.address(),
+ inputAddress + inputPos, inputRem,
+ outputArray, outputOffset + outputPos, outputRem,
+ flush, params);
+ }
+ } finally {
+ Reference.reachabilityFence(input);
+ }
+ } else {
+ byte[] inputArray = ZipUtils.getBufferArray(input);
+ int inputOffset = ZipUtils.getBufferOffset(input);
+ if (output.isDirect()) {
+ long outputAddress = ((DirectBuffer) output).address();
+ try {
+ result = deflateBytesBuffer(zsRef.address(),
+ inputArray, inputOffset + inputPos, inputRem,
+ outputAddress + outputPos, outputRem,
+ flush, params);
+ } finally {
+ Reference.reachabilityFence(output);
+ }
+ } else {
+ byte[] outputArray = ZipUtils.getBufferArray(output);
+ int outputOffset = ZipUtils.getBufferOffset(output);
+ result = deflateBytesBytes(zsRef.address(),
+ inputArray, inputOffset + inputPos, inputRem,
+ outputArray, outputOffset + outputPos, outputRem,
+ flush, params);
+ }
+ }
+ }
+ int read = (int) (result & 0x7fff_ffffL);
+ int written = (int) (result >>> 31 & 0x7fff_ffffL);
+ if ((result >>> 62 & 1) != 0) {
+ finished = true;
+ }
+ if (params != 0 && (result >>> 63 & 1) == 0) {
+ setParams = false;
+ }
+ if (input != null) {
+ input.position(inputPos + read);
+ } else {
+ this.inputPos = inputPos + read;
+ }
+ output.position(outputPos + written);
+ bytesWritten += written;
+ bytesRead += read;
+ return written;
+ }
}
/**
@@ -545,7 +881,8 @@
reset(zsRef.address());
finish = false;
finished = false;
- off = len = 0;
+ input = ZipUtils.defaultBuf;
+ inputArray = null;
bytesRead = bytesWritten = 0;
}
}
@@ -560,7 +897,7 @@
public void end() {
synchronized (zsRef) {
zsRef.clean();
- buf = null;
+ input = ZipUtils.defaultBuf;
}
}
@@ -585,11 +922,26 @@
throw new NullPointerException("Deflater has been closed");
}
- private static native void initIDs();
private static native long init(int level, int strategy, boolean nowrap);
- private static native void setDictionary(long addr, byte[] b, int off, int len);
- private native int deflateBytes(long addr, byte[] b, int off, int len,
- int flush);
+ private static native void setDictionary(long addr, byte[] b, int off,
+ int len);
+ private static native void setDictionaryBuffer(long addr, long bufAddress, int len);
+ private native long deflateBytesBytes(long addr,
+ byte[] inputArray, int inputOff, int inputLen,
+ byte[] outputArray, int outputOff, int outputLen,
+ int flush, int params);
+ private native long deflateBytesBuffer(long addr,
+ byte[] inputArray, int inputOff, int inputLen,
+ long outputAddress, int outputLen,
+ int flush, int params);
+ private native long deflateBufferBytes(long addr,
+ long inputAddress, int inputLen,
+ byte[] outputArray, int outputOff, int outputLen,
+ int flush, int params);
+ private native long deflateBufferBuffer(long addr,
+ long inputAddress, int inputLen,
+ long outputAddress, int outputLen,
+ int flush, int params);
private static native int getAdler(long addr);
private static native void reset(long addr);
private static native void end(long addr);
--- a/src/java.base/share/classes/java/util/zip/Inflater.java Wed Apr 18 14:07:41 2018 -0700
+++ b/src/java.base/share/classes/java/util/zip/Inflater.java Fri Apr 20 09:05:05 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -26,7 +26,13 @@
package java.util.zip;
import java.lang.ref.Cleaner.Cleanable;
+import java.lang.ref.Reference;
+import java.nio.ByteBuffer;
+import java.nio.ReadOnlyBufferException;
+import java.util.Objects;
+
import jdk.internal.ref.CleanerFactory;
+import sun.nio.ch.DirectBuffer;
/**
* This class provides support for general purpose decompression using the
@@ -35,8 +41,13 @@
* protected by patents. It is fully described in the specifications at
* the <a href="package-summary.html#package.description">java.util.zip
* package description</a>.
- *
- * <p>The following code fragment demonstrates a trivial compression
+ * <p>
+ * This class inflates sequences of ZLIB compressed bytes. The input byte
+ * sequence is provided in either byte array or byte buffer, via one of the
+ * {@code setInput()} methods. The output byte sequence is written to the
+ * output byte array or byte buffer passed to the {@code deflate()} methods.
+ * <p>
+ * The following code fragment demonstrates a trivial compression
* and decompression of a string using {@code Deflater} and
* {@code Inflater}.
*
@@ -92,14 +103,20 @@
public class Inflater {
private final InflaterZStreamRef zsRef;
- private byte[] buf = defaultBuf;
- private int off, len;
+ private ByteBuffer input = ZipUtils.defaultBuf;
+ private byte[] inputArray;
+ private int inputPos, inputLim;
private boolean finished;
private boolean needDict;
private long bytesRead;
private long bytesWritten;
- private static final byte[] defaultBuf = new byte[0];
+ /*
+ * These fields are used as an "out" parameter from JNI when a
+ * DataFormatException is thrown during the inflate operation.
+ */
+ private int inputConsumed;
+ private int outputConsumed;
static {
ZipUtils.loadLibrary();
@@ -129,37 +146,71 @@
}
/**
- * Sets input data for decompression. Should be called whenever
- * needsInput() returns true indicating that more input data is
- * required.
- * @param b the input data bytes
+ * Sets input data for decompression.
+ * <p>
+ * One of the {@code setInput()} methods should be called whenever
+ * {@code needsInput()} returns true indicating that more input data
+ * is required.
+ *
+ * @param input the input data bytes
* @param off the start offset of the input data
* @param len the length of the input data
* @see Inflater#needsInput
*/
- public void setInput(byte[] b, int off, int len) {
- if (b == null) {
- throw new NullPointerException();
- }
- if (off < 0 || len < 0 || off > b.length - len) {
+ public void setInput(byte[] input, int off, int len) {
+ if (off < 0 || len < 0 || off > input.length - len) {
throw new ArrayIndexOutOfBoundsException();
}
synchronized (zsRef) {
- this.buf = b;
- this.off = off;
- this.len = len;
+ this.input = null;
+ this.inputArray = input;
+ this.inputPos = off;
+ this.inputLim = off + len;
}
}
/**
- * Sets input data for decompression. Should be called whenever
- * needsInput() returns true indicating that more input data is
- * required.
- * @param b the input data bytes
+ * Sets input data for decompression.
+ * <p>
+ * One of the {@code setInput()} methods should be called whenever
+ * {@code needsInput()} returns true indicating that more input data
+ * is required.
+ *
+ * @param input the input data bytes
* @see Inflater#needsInput
*/
- public void setInput(byte[] b) {
- setInput(b, 0, b.length);
+ public void setInput(byte[] input) {
+ setInput(input, 0, input.length);
+ }
+
+ /**
+ * Sets input data for decompression.
+ * <p>
+ * One of the {@code setInput()} methods should be called whenever
+ * {@code needsInput()} returns true indicating that more input data
+ * is required.
+ * <p>
+ * The given buffer's position will be advanced as inflate
+ * operations are performed, up to the buffer's limit.
+ * The input buffer may be modified (refilled) between inflate
+ * operations; doing so is equivalent to creating a new buffer
+ * and setting it with this method.
+ * <p>
+ * Modifying the input buffer's contents, position, or limit
+ * concurrently with an inflate operation will result in
+ * undefined behavior, which may include incorrect operation
+ * results or operation failure.
+ *
+ * @param input the input data bytes
+ * @see Inflater#needsInput
+ * @since 11
+ */
+ public void setInput(ByteBuffer input) {
+ Objects.requireNonNull(input);
+ synchronized (zsRef) {
+ this.input = input;
+ this.inputArray = null;
+ }
}
/**
@@ -167,22 +218,19 @@
* called when inflate() returns 0 and needsDictionary() returns true
* indicating that a preset dictionary is required. The method getAdler()
* can be used to get the Adler-32 value of the dictionary needed.
- * @param b the dictionary data bytes
+ * @param dictionary the dictionary data bytes
* @param off the start offset of the data
* @param len the length of the data
* @see Inflater#needsDictionary
* @see Inflater#getAdler
*/
- public void setDictionary(byte[] b, int off, int len) {
- if (b == null) {
- throw new NullPointerException();
- }
- if (off < 0 || len < 0 || off > b.length - len) {
+ public void setDictionary(byte[] dictionary, int off, int len) {
+ if (off < 0 || len < 0 || off > dictionary.length - len) {
throw new ArrayIndexOutOfBoundsException();
}
synchronized (zsRef) {
ensureOpen();
- setDictionary(zsRef.address(), b, off, len);
+ setDictionary(zsRef.address(), dictionary, off, len);
needDict = false;
}
}
@@ -192,12 +240,48 @@
* called when inflate() returns 0 and needsDictionary() returns true
* indicating that a preset dictionary is required. The method getAdler()
* can be used to get the Adler-32 value of the dictionary needed.
- * @param b the dictionary data bytes
+ * @param dictionary the dictionary data bytes
* @see Inflater#needsDictionary
* @see Inflater#getAdler
*/
- public void setDictionary(byte[] b) {
- setDictionary(b, 0, b.length);
+ public void setDictionary(byte[] dictionary) {
+ setDictionary(dictionary, 0, dictionary.length);
+ }
+
+ /**
+ * Sets the preset dictionary to the bytes in the given buffer. Should be
+ * called when inflate() returns 0 and needsDictionary() returns true
+ * indicating that a preset dictionary is required. The method getAdler()
+ * can be used to get the Adler-32 value of the dictionary needed.
+ * <p>
+ * The bytes in given byte buffer will be fully consumed by this method. On
+ * return, its position will equal its limit.
+ *
+ * @param dictionary the dictionary data bytes
+ * @see Inflater#needsDictionary
+ * @see Inflater#getAdler
+ * @since 11
+ */
+ public void setDictionary(ByteBuffer dictionary) {
+ synchronized (zsRef) {
+ int position = dictionary.position();
+ int remaining = Math.max(dictionary.limit() - position, 0);
+ ensureOpen();
+ if (dictionary.isDirect()) {
+ long address = ((DirectBuffer) dictionary).address();
+ try {
+ setDictionaryBuffer(zsRef.address(), address + position, remaining);
+ } finally {
+ Reference.reachabilityFence(dictionary);
+ }
+ } else {
+ byte[] array = ZipUtils.getBufferArray(dictionary);
+ int offset = ZipUtils.getBufferOffset(dictionary);
+ setDictionary(zsRef.address(), array, offset + position, remaining);
+ }
+ dictionary.position(position + remaining);
+ needDict = false;
+ }
}
/**
@@ -208,19 +292,22 @@
*/
public int getRemaining() {
synchronized (zsRef) {
- return len;
+ ByteBuffer input = this.input;
+ return input == null ? inputLim - inputPos : input.remaining();
}
}
/**
* Returns true if no data remains in the input buffer. This can
- * be used to determine if #setInput should be called in order
- * to provide more input.
+ * be used to determine if one of the {@code setInput()} methods should be
+ * called in order to provide more input.
+ *
* @return true if no data remains in the input buffer
*/
public boolean needsInput() {
synchronized (zsRef) {
- return len <= 0;
+ ByteBuffer input = this.input;
+ return input == null ? inputLim == inputPos : ! input.hasRemaining();
}
}
@@ -254,30 +341,103 @@
* determine if more input data or a preset dictionary is required.
* In the latter case, getAdler() can be used to get the Adler-32
* value of the dictionary required.
- * @param b the buffer for the uncompressed data
+ * <p>
+ * If the {@link #setInput(ByteBuffer)} method was called to provide a buffer
+ * for input, the input buffer's position will be advanced by the number of bytes
+ * consumed by this operation, even in the event that a {@link DataFormatException}
+ * is thrown.
+ * <p>
+ * The {@linkplain #getRemaining() remaining byte count} will be reduced by
+ * the number of consumed input bytes. If the {@link #setInput(ByteBuffer)}
+ * method was called to provide a buffer for input, the input buffer's position
+ * will be advanced the number of consumed bytes.
+ * <p>
+ * These byte totals, as well as
+ * the {@linkplain #getBytesRead() total bytes read}
+ * and the {@linkplain #getBytesWritten() total bytes written}
+ * values, will be updated even in the event that a {@link DataFormatException}
+ * is thrown to reflect the amount of data consumed and produced before the
+ * exception occurred.
+ *
+ * @param output the buffer for the uncompressed data
* @param off the start offset of the data
* @param len the maximum number of uncompressed bytes
* @return the actual number of uncompressed bytes
- * @exception DataFormatException if the compressed data format is invalid
+ * @throws DataFormatException if the compressed data format is invalid
* @see Inflater#needsInput
* @see Inflater#needsDictionary
*/
- public int inflate(byte[] b, int off, int len)
+ public int inflate(byte[] output, int off, int len)
throws DataFormatException
{
- if (b == null) {
- throw new NullPointerException();
- }
- if (off < 0 || len < 0 || off > b.length - len) {
+ if (off < 0 || len < 0 || off > output.length - len) {
throw new ArrayIndexOutOfBoundsException();
}
synchronized (zsRef) {
ensureOpen();
- int thisLen = this.len;
- int n = inflateBytes(zsRef.address(), b, off, len);
- bytesWritten += n;
- bytesRead += (thisLen - this.len);
- return n;
+ ByteBuffer input = this.input;
+ long result;
+ int inputPos;
+ try {
+ if (input == null) {
+ inputPos = this.inputPos;
+ try {
+ result = inflateBytesBytes(zsRef.address(),
+ inputArray, inputPos, inputLim - inputPos,
+ output, off, len);
+ } catch (DataFormatException e) {
+ this.inputPos = inputPos + inputConsumed;
+ throw e;
+ }
+ } else {
+ inputPos = input.position();
+ try {
+ int inputRem = Math.max(input.limit() - inputPos, 0);
+ if (input.isDirect()) {
+ try {
+ long inputAddress = ((DirectBuffer) input).address();
+ result = inflateBufferBytes(zsRef.address(),
+ inputAddress + inputPos, inputRem,
+ output, off, len);
+ } finally {
+ Reference.reachabilityFence(input);
+ }
+ } else {
+ byte[] inputArray = ZipUtils.getBufferArray(input);
+ int inputOffset = ZipUtils.getBufferOffset(input);
+ result = inflateBytesBytes(zsRef.address(),
+ inputArray, inputOffset + inputPos, inputRem,
+ output, off, len);
+ }
+ } catch (DataFormatException e) {
+ input.position(inputPos + inputConsumed);
+ throw e;
+ }
+ }
+ } catch (DataFormatException e) {
+ bytesRead += inputConsumed;
+ inputConsumed = 0;
+ int written = outputConsumed;
+ bytesWritten += written;
+ outputConsumed = 0;
+ throw e;
+ }
+ int read = (int) (result & 0x7fff_ffffL);
+ int written = (int) (result >>> 31 & 0x7fff_ffffL);
+ if ((result >>> 62 & 1) != 0) {
+ finished = true;
+ }
+ if ((result >>> 63 & 1) != 0) {
+ needDict = true;
+ }
+ if (input != null) {
+ input.position(inputPos + read);
+ } else {
+ this.inputPos = inputPos + read;
+ }
+ bytesWritten += written;
+ bytesRead += read;
+ return written;
}
}
@@ -288,14 +448,177 @@
* determine if more input data or a preset dictionary is required.
* In the latter case, getAdler() can be used to get the Adler-32
* value of the dictionary required.
- * @param b the buffer for the uncompressed data
+ * <p>
+ * The {@linkplain #getRemaining() remaining byte count} will be reduced by
+ * the number of consumed input bytes. If the {@link #setInput(ByteBuffer)}
+ * method was called to provide a buffer for input, the input buffer's position
+ * will be advanced the number of consumed bytes.
+ * <p>
+ * These byte totals, as well as
+ * the {@linkplain #getBytesRead() total bytes read}
+ * and the {@linkplain #getBytesWritten() total bytes written}
+ * values, will be updated even in the event that a {@link DataFormatException}
+ * is thrown to reflect the amount of data consumed and produced before the
+ * exception occurred.
+ *
+ * @param output the buffer for the uncompressed data
* @return the actual number of uncompressed bytes
- * @exception DataFormatException if the compressed data format is invalid
+ * @throws DataFormatException if the compressed data format is invalid
* @see Inflater#needsInput
* @see Inflater#needsDictionary
*/
- public int inflate(byte[] b) throws DataFormatException {
- return inflate(b, 0, b.length);
+ public int inflate(byte[] output) throws DataFormatException {
+ return inflate(output, 0, output.length);
+ }
+
+ /**
+ * Uncompresses bytes into specified buffer. Returns actual number
+ * of bytes uncompressed. A return value of 0 indicates that
+ * needsInput() or needsDictionary() should be called in order to
+ * determine if more input data or a preset dictionary is required.
+ * In the latter case, getAdler() can be used to get the Adler-32
+ * value of the dictionary required.
+ * <p>
+ * On success, the position of the given {@code output} byte buffer will be
+ * advanced by as many bytes as were produced by the operation, which is equal
+ * to the number returned by this method. Note that the position of the
+ * {@code output} buffer will be advanced even in the event that a
+ * {@link DataFormatException} is thrown.
+ * <p>
+ * The {@linkplain #getRemaining() remaining byte count} will be reduced by
+ * the number of consumed input bytes. If the {@link #setInput(ByteBuffer)}
+ * method was called to provide a buffer for input, the input buffer's position
+ * will be advanced the number of consumed bytes.
+ * <p>
+ * These byte totals, as well as
+ * the {@linkplain #getBytesRead() total bytes read}
+ * and the {@linkplain #getBytesWritten() total bytes written}
+ * values, will be updated even in the event that a {@link DataFormatException}
+ * is thrown to reflect the amount of data consumed and produced before the
+ * exception occurred.
+ *
+ * @param output the buffer for the uncompressed data
+ * @return the actual number of uncompressed bytes
+ * @throws DataFormatException if the compressed data format is invalid
+ * @throws ReadOnlyBufferException if the given output buffer is read-only
+ * @see Inflater#needsInput
+ * @see Inflater#needsDictionary
+ * @since 11
+ */
+ public int inflate(ByteBuffer output) throws DataFormatException {
+ if (output.isReadOnly()) {
+ throw new ReadOnlyBufferException();
+ }
+ synchronized (zsRef) {
+ ensureOpen();
+ ByteBuffer input = this.input;
+ long result;
+ int inputPos;
+ int outputPos = output.position();
+ int outputRem = Math.max(output.limit() - outputPos, 0);
+ try {
+ if (input == null) {
+ inputPos = this.inputPos;
+ try {
+ if (output.isDirect()) {
+ long outputAddress = ((DirectBuffer) output).address();
+ try {
+ result = inflateBytesBuffer(zsRef.address(),
+ inputArray, inputPos, inputLim - inputPos,
+ outputAddress + outputPos, outputRem);
+ } finally {
+ Reference.reachabilityFence(output);
+ }
+ } else {
+ byte[] outputArray = ZipUtils.getBufferArray(output);
+ int outputOffset = ZipUtils.getBufferOffset(output);
+ result = inflateBytesBytes(zsRef.address(),
+ inputArray, inputPos, inputLim - inputPos,
+ outputArray, outputOffset + outputPos, outputRem);
+ }
+ } catch (DataFormatException e) {
+ this.inputPos = inputPos + inputConsumed;
+ throw e;
+ }
+ } else {
+ inputPos = input.position();
+ int inputRem = Math.max(input.limit() - inputPos, 0);
+ try {
+ if (input.isDirect()) {
+ long inputAddress = ((DirectBuffer) input).address();
+ try {
+ if (output.isDirect()) {
+ long outputAddress = ((DirectBuffer) output).address();
+ try {
+ result = inflateBufferBuffer(zsRef.address(),
+ inputAddress + inputPos, inputRem,
+ outputAddress + outputPos, outputRem);
+ } finally {
+ Reference.reachabilityFence(output);
+ }
+ } else {
+ byte[] outputArray = ZipUtils.getBufferArray(output);
+ int outputOffset = ZipUtils.getBufferOffset(output);
+ result = inflateBufferBytes(zsRef.address(),
+ inputAddress + inputPos, inputRem,
+ outputArray, outputOffset + outputPos, outputRem);
+ }
+ } finally {
+ Reference.reachabilityFence(input);
+ }
+ } else {
+ byte[] inputArray = ZipUtils.getBufferArray(input);
+ int inputOffset = ZipUtils.getBufferOffset(input);
+ if (output.isDirect()) {
+ long outputAddress = ((DirectBuffer) output).address();
+ try {
+ result = inflateBytesBuffer(zsRef.address(),
+ inputArray, inputOffset + inputPos, inputRem,
+ outputAddress + outputPos, outputRem);
+ } finally {
+ Reference.reachabilityFence(output);
+ }
+ } else {
+ byte[] outputArray = ZipUtils.getBufferArray(output);
+ int outputOffset = ZipUtils.getBufferOffset(output);
+ result = inflateBytesBytes(zsRef.address(),
+ inputArray, inputOffset + inputPos, inputRem,
+ outputArray, outputOffset + outputPos, outputRem);
+ }
+ }
+ } catch (DataFormatException e) {
+ input.position(inputPos + inputConsumed);
+ throw e;
+ }
+ }
+ } catch (DataFormatException e) {
+ bytesRead += inputConsumed;
+ inputConsumed = 0;
+ int written = outputConsumed;
+ output.position(outputPos + written);
+ bytesWritten += written;
+ outputConsumed = 0;
+ throw e;
+ }
+ int read = (int) (result & 0x7fff_ffffL);
+ int written = (int) (result >>> 31 & 0x7fff_ffffL);
+ if ((result >>> 62 & 1) != 0) {
+ finished = true;
+ }
+ if ((result >>> 63 & 1) != 0) {
+ needDict = true;
+ }
+ if (input != null) {
+ input.position(inputPos + read);
+ } else {
+ this.inputPos = inputPos + read;
+ }
+ // Note: this method call also serves to keep the byteBuffer ref alive
+ output.position(outputPos + written);
+ bytesWritten += written;
+ bytesRead += read;
+ return written;
+ }
}
/**
@@ -368,10 +691,10 @@
synchronized (zsRef) {
ensureOpen();
reset(zsRef.address());
- buf = defaultBuf;
+ input = ZipUtils.defaultBuf;
+ inputArray = null;
finished = false;
needDict = false;
- off = len = 0;
bytesRead = bytesWritten = 0;
}
}
@@ -386,7 +709,8 @@
public void end() {
synchronized (zsRef) {
zsRef.clean();
- buf = null;
+ input = ZipUtils.defaultBuf;
+ inputArray = null;
}
}
@@ -416,18 +740,23 @@
throw new NullPointerException("Inflater has been closed");
}
- boolean ended() {
- synchronized (zsRef) {
- return zsRef.address() == 0;
- }
- }
-
private static native void initIDs();
private static native long init(boolean nowrap);
private static native void setDictionary(long addr, byte[] b, int off,
int len);
- private native int inflateBytes(long addr, byte[] b, int off, int len)
- throws DataFormatException;
+ private static native void setDictionaryBuffer(long addr, long bufAddress, int len);
+ private native long inflateBytesBytes(long addr,
+ byte[] inputArray, int inputOff, int inputLen,
+ byte[] outputArray, int outputOff, int outputLen) throws DataFormatException;
+ private native long inflateBytesBuffer(long addr,
+ byte[] inputArray, int inputOff, int inputLen,
+ long outputAddress, int outputLen) throws DataFormatException;
+ private native long inflateBufferBytes(long addr,
+ long inputAddress, int inputLen,
+ byte[] outputArray, int outputOff, int outputLen) throws DataFormatException;
+ private native long inflateBufferBuffer(long addr,
+ long inputAddress, int inputLen,
+ long outputAddress, int outputLen) throws DataFormatException;
private static native int getAdler(long addr);
private static native void reset(long addr);
private static native void end(long addr);
--- a/src/java.base/share/classes/java/util/zip/ZipUtils.java Wed Apr 18 14:07:41 2018 -0700
+++ b/src/java.base/share/classes/java/util/zip/ZipUtils.java Fri Apr 20 09:05:05 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -25,6 +25,8 @@
package java.util.zip;
+import java.nio.Buffer;
+import java.nio.ByteBuffer;
import java.nio.file.attribute.FileTime;
import java.security.AccessController;
import java.security.PrivilegedAction;
@@ -37,6 +39,9 @@
import static java.util.zip.ZipConstants.ENDHDR;
+import jdk.internal.misc.Unsafe;
+import sun.nio.ch.DirectBuffer;
+
class ZipUtils {
// used to adjust values between Windows and java epoch
@@ -45,6 +50,9 @@
// used to indicate the corresponding windows time is not available
public static final long WINDOWS_TIME_NOT_AVAILABLE = Long.MIN_VALUE;
+ // static final ByteBuffer defaultBuf = ByteBuffer.allocateDirect(0);
+ static final ByteBuffer defaultBuf = ByteBuffer.allocate(0);
+
/**
* Converts Windows time (in microseconds, UTC/GMT) time to FileTime.
*/
@@ -281,4 +289,17 @@
AccessController.doPrivileged(pa);
}
}
+
+ private static final Unsafe unsafe = Unsafe.getUnsafe();
+
+ private static final long byteBufferArrayOffset = unsafe.objectFieldOffset(ByteBuffer.class, "hb");
+ private static final long byteBufferOffsetOffset = unsafe.objectFieldOffset(ByteBuffer.class, "offset");
+
+ static byte[] getBufferArray(ByteBuffer byteBuffer) {
+ return (byte[]) unsafe.getObject(byteBuffer, byteBufferArrayOffset);
+ }
+
+ static int getBufferOffset(ByteBuffer byteBuffer) {
+ return unsafe.getInt(byteBuffer, byteBufferOffsetOffset);
+ }
}
--- a/src/java.base/share/native/launcher/main.c Wed Apr 18 14:07:41 2018 -0700
+++ b/src/java.base/share/native/launcher/main.c Fri Apr 20 09:05:05 2018 -0700
@@ -93,7 +93,7 @@
__initenv = _environ;
#else /* JAVAW */
-JNIEXPORT int JNICALL
+JNIEXPORT int
main(int argc, char **argv)
{
int margc;
--- a/src/java.base/share/native/libjimage/jimage.cpp Wed Apr 18 14:07:41 2018 -0700
+++ b/src/java.base/share/native/libjimage/jimage.cpp Fri Apr 20 09:05:05 2018 -0700
@@ -55,7 +55,7 @@
* }
* ...
*/
-extern "C" JNIEXPORT JImageFile* JNICALL
+extern "C" JNIEXPORT JImageFile*
JIMAGE_Open(const char *name, jint* error) {
// TODO - return a meaningful error code
*error = 0;
@@ -72,7 +72,7 @@
* Ex.
* (*JImageClose)(image);
*/
-extern "C" JNIEXPORT void JNICALL
+extern "C" JNIEXPORT void
JIMAGE_Close(JImageFile* image) {
ImageFileReader::close((ImageFileReader*) image);
}
@@ -89,7 +89,7 @@
* tty->print_cr(package);
* -> java.base
*/
-extern "C" JNIEXPORT const char* JNICALL
+extern "C" JNIEXPORT const char*
JIMAGE_PackageToModule(JImageFile* image, const char* package_name) {
return ((ImageFileReader*) image)->get_image_module_data()->package_to_module(package_name);
}
@@ -108,7 +108,7 @@
* JImageLocationRef location = (*JImageFindResource)(image,
* "java.base", "9.0", "java/lang/String.class", &size);
*/
-extern "C" JNIEXPORT JImageLocationRef JNICALL
+extern "C" JNIEXPORT JImageLocationRef
JIMAGE_FindResource(JImageFile* image,
const char* module_name, const char* version, const char* name,
jlong* size) {
@@ -155,7 +155,7 @@
* char* buffer = new char[size];
* (*JImageGetResource)(image, location, buffer, size);
*/
-extern "C" JNIEXPORT jlong JNICALL
+extern "C" JNIEXPORT jlong
JIMAGE_GetResource(JImageFile* image, JImageLocationRef location,
char* buffer, jlong size) {
((ImageFileReader*) image)->get_resource((u4) location, (u1*) buffer);
@@ -184,7 +184,7 @@
* }
* (*JImageResourceIterator)(image, ctw_visitor, loader);
*/
-extern "C" JNIEXPORT void JNICALL
+extern "C" JNIEXPORT void
JIMAGE_ResourceIterator(JImageFile* image,
JImageResourceVisitor_t visitor, void* arg) {
ImageFileReader* imageFile = (ImageFileReader*) image;
@@ -226,7 +226,7 @@
* char path[JIMAGE_MAX_PATH];
* (*JImageResourcePath)(image, location, path, JIMAGE_MAX_PATH);
*/
-extern "C" JNIEXPORT bool JNICALL
+extern "C" JNIEXPORT bool
JIMAGE_ResourcePath(JImageFile* image, JImageLocationRef locationRef,
char* path, size_t max) {
ImageFileReader* imageFile = (ImageFileReader*) image;
--- a/src/java.base/share/native/libjimage/jimage.hpp Wed Apr 18 14:07:41 2018 -0700
+++ b/src/java.base/share/native/libjimage/jimage.hpp Fri Apr 20 09:05:05 2018 -0700
@@ -72,7 +72,7 @@
* ...
*/
-extern "C" JNIEXPORT JImageFile* JNICALL
+extern "C" JNIEXPORT JImageFile*
JIMAGE_Open(const char *name, jint* error);
typedef JImageFile* (*JImageOpen_t)(const char *name, jint* error);
@@ -87,7 +87,7 @@
* (*JImageClose)(image);
*/
-extern "C" JNIEXPORT void JNICALL
+extern "C" JNIEXPORT void
JIMAGE_Close(JImageFile* jimage);
typedef void (*JImageClose_t)(JImageFile* jimage);
@@ -106,7 +106,7 @@
* -> java.base
*/
-extern "C" JNIEXPORT const char * JNICALL
+extern "C" JNIEXPORT const char *
JIMAGE_PackageToModule(JImageFile* jimage, const char* package_name);
typedef const char* (*JImagePackageToModule_t)(JImageFile* jimage, const char* package_name);
@@ -150,7 +150,7 @@
* char* buffer = new char[size];
* (*JImageGetResource)(image, location, buffer, size);
*/
-extern "C" JNIEXPORT jlong JNICALL
+extern "C" JNIEXPORT jlong
JIMAGE_GetResource(JImageFile* jimage, JImageLocationRef location,
char* buffer, jlong size);
@@ -185,7 +185,7 @@
const char* module_name, const char* version, const char* package,
const char* name, const char* extension, void* arg);
-extern "C" JNIEXPORT void JNICALL
+extern "C" JNIEXPORT void
JIMAGE_ResourceIterator(JImageFile* jimage,
JImageResourceVisitor_t visitor, void *arg);
@@ -202,7 +202,7 @@
* char path[JIMAGE_MAX_PATH];
* (*JImageResourcePath)(image, location, path, JIMAGE_MAX_PATH);
*/
-extern "C" JNIEXPORT bool JNICALL
+extern "C" JNIEXPORT bool
JIMAGE_ResourcePath(JImageFile* image, JImageLocationRef locationRef,
char* path, size_t max);
--- a/src/java.base/share/native/libzip/CRC32.c Wed Apr 18 14:07:41 2018 -0700
+++ b/src/java.base/share/native/libzip/CRC32.c Fri Apr 20 09:05:05 2018 -0700
@@ -54,7 +54,7 @@
return crc;
}
-JNIEXPORT jint JNICALL
+JNIEXPORT jint
ZIP_CRC32(jint crc, const jbyte *buf, jint len)
{
return crc32(crc, (Bytef*)buf, len);
--- a/src/java.base/share/native/libzip/Deflater.c Wed Apr 18 14:07:41 2018 -0700
+++ b/src/java.base/share/native/libzip/Deflater.c Fri Apr 20 09:05:05 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -38,34 +38,6 @@
#define DEF_MEM_LEVEL 8
-static jfieldID levelID;
-static jfieldID strategyID;
-static jfieldID setParamsID;
-static jfieldID finishID;
-static jfieldID finishedID;
-static jfieldID bufID, offID, lenID;
-
-JNIEXPORT void JNICALL
-Java_java_util_zip_Deflater_initIDs(JNIEnv *env, jclass cls)
-{
- levelID = (*env)->GetFieldID(env, cls, "level", "I");
- CHECK_NULL(levelID);
- strategyID = (*env)->GetFieldID(env, cls, "strategy", "I");
- CHECK_NULL(strategyID);
- setParamsID = (*env)->GetFieldID(env, cls, "setParams", "Z");
- CHECK_NULL(setParamsID);
- finishID = (*env)->GetFieldID(env, cls, "finish", "Z");
- CHECK_NULL(finishID);
- finishedID = (*env)->GetFieldID(env, cls, "finished", "Z");
- CHECK_NULL(finishedID);
- bufID = (*env)->GetFieldID(env, cls, "buf", "[B");
- CHECK_NULL(bufID);
- offID = (*env)->GetFieldID(env, cls, "off", "I");
- CHECK_NULL(offID);
- lenID = (*env)->GetFieldID(env, cls, "len", "I");
- CHECK_NULL(lenID);
-}
-
JNIEXPORT jlong JNICALL
Java_java_util_zip_Deflater_init(JNIEnv *env, jclass cls, jint level,
jint strategy, jboolean nowrap)
@@ -104,17 +76,9 @@
}
}
-JNIEXPORT void JNICALL
-Java_java_util_zip_Deflater_setDictionary(JNIEnv *env, jclass cls, jlong addr,
- jarray b, jint off, jint len)
+static void doSetDictionary(JNIEnv *env, jlong addr, jbyte *buf, jint len)
{
- Bytef *buf = (*env)->GetPrimitiveArrayCritical(env, b, 0);
- int res;
- if (buf == 0) {/* out of memory */
- return;
- }
- res = deflateSetDictionary((z_stream *)jlong_to_ptr(addr), buf + off, len);
- (*env)->ReleasePrimitiveArrayCritical(env, b, buf, 0);
+ int res = deflateSetDictionary(jlong_to_ptr(addr), (Bytef *) buf, len);
switch (res) {
case Z_OK:
break;
@@ -127,94 +91,173 @@
}
}
-JNIEXPORT jint JNICALL
-Java_java_util_zip_Deflater_deflateBytes(JNIEnv *env, jobject this, jlong addr,
- jarray b, jint off, jint len, jint flush)
+JNIEXPORT void JNICALL
+Java_java_util_zip_Deflater_setDictionary(JNIEnv *env, jclass cls, jlong addr,
+ jbyteArray b, jint off, jint len)
+{
+ jbyte *buf = (*env)->GetPrimitiveArrayCritical(env, b, 0);
+ if (buf == NULL) /* out of memory */
+ return;
+ doSetDictionary(env, addr, buf + off, len);
+ (*env)->ReleasePrimitiveArrayCritical(env, b, buf, 0);
+}
+
+JNIEXPORT void JNICALL
+Java_java_util_zip_Deflater_setDictionaryBuffer(JNIEnv *env, jclass cls, jlong addr,
+ jlong bufferAddr, jint len)
+{
+ jbyte *buf = jlong_to_ptr(bufferAddr);
+ doSetDictionary(env, addr, buf, len);
+}
+
+static jlong doDeflate(JNIEnv *env, jobject this, jlong addr,
+ jbyte *input, jint inputLen,
+ jbyte *output, jint outputLen,
+ jint flush, jint params)
{
z_stream *strm = jlong_to_ptr(addr);
+ jint inputUsed = 0, outputUsed = 0;
+ int finished = 0;
+ int setParams = params & 1;
- jarray this_buf = (*env)->GetObjectField(env, this, bufID);
- jint this_off = (*env)->GetIntField(env, this, offID);
- jint this_len = (*env)->GetIntField(env, this, lenID);
- jbyte *in_buf;
- jbyte *out_buf;
- int res;
- if ((*env)->GetBooleanField(env, this, setParamsID)) {
- int level = (*env)->GetIntField(env, this, levelID);
- int strategy = (*env)->GetIntField(env, this, strategyID);
- in_buf = (*env)->GetPrimitiveArrayCritical(env, this_buf, 0);
- if (in_buf == NULL) {
- // Throw OOME only when length is not zero
- if (this_len != 0 && (*env)->ExceptionOccurred(env) == NULL)
- JNU_ThrowOutOfMemoryError(env, 0);
- return 0;
- }
- out_buf = (*env)->GetPrimitiveArrayCritical(env, b, 0);
- if (out_buf == NULL) {
- (*env)->ReleasePrimitiveArrayCritical(env, this_buf, in_buf, 0);
- if (len != 0 && (*env)->ExceptionOccurred(env) == NULL)
- JNU_ThrowOutOfMemoryError(env, 0);
- return 0;
- }
+ strm->next_in = (Bytef *) input;
+ strm->next_out = (Bytef *) output;
+ strm->avail_in = inputLen;
+ strm->avail_out = outputLen;
- strm->next_in = (Bytef *) (in_buf + this_off);
- strm->next_out = (Bytef *) (out_buf + off);
- strm->avail_in = this_len;
- strm->avail_out = len;
- res = deflateParams(strm, level, strategy);
- (*env)->ReleasePrimitiveArrayCritical(env, b, out_buf, 0);
- (*env)->ReleasePrimitiveArrayCritical(env, this_buf, in_buf, 0);
+ if (setParams) {
+ int strategy = (params >> 1) & 3;
+ int level = params >> 3;
+ int res = deflateParams(strm, level, strategy);
switch (res) {
case Z_OK:
- (*env)->SetBooleanField(env, this, setParamsID, JNI_FALSE);
+ setParams = 0;
+ /* fall through */
case Z_BUF_ERROR:
- this_off += this_len - strm->avail_in;
- (*env)->SetIntField(env, this, offID, this_off);
- (*env)->SetIntField(env, this, lenID, strm->avail_in);
- return (jint) (len - strm->avail_out);
+ inputUsed = inputLen - strm->avail_in;
+ outputUsed = outputLen - strm->avail_out;
+ break;
default:
JNU_ThrowInternalError(env, strm->msg);
return 0;
}
} else {
- jboolean finish = (*env)->GetBooleanField(env, this, finishID);
- in_buf = (*env)->GetPrimitiveArrayCritical(env, this_buf, 0);
- if (in_buf == NULL) {
- if (this_len != 0)
- JNU_ThrowOutOfMemoryError(env, 0);
- return 0;
- }
- out_buf = (*env)->GetPrimitiveArrayCritical(env, b, 0);
- if (out_buf == NULL) {
- (*env)->ReleasePrimitiveArrayCritical(env, this_buf, in_buf, 0);
- if (len != 0)
- JNU_ThrowOutOfMemoryError(env, 0);
-
- return 0;
- }
-
- strm->next_in = (Bytef *) (in_buf + this_off);
- strm->next_out = (Bytef *) (out_buf + off);
- strm->avail_in = this_len;
- strm->avail_out = len;
- res = deflate(strm, finish ? Z_FINISH : flush);
- (*env)->ReleasePrimitiveArrayCritical(env, b, out_buf, 0);
- (*env)->ReleasePrimitiveArrayCritical(env, this_buf, in_buf, 0);
+ int res = deflate(strm, flush);
switch (res) {
case Z_STREAM_END:
- (*env)->SetBooleanField(env, this, finishedID, JNI_TRUE);
+ finished = 1;
/* fall through */
case Z_OK:
case Z_BUF_ERROR:
- this_off += this_len - strm->avail_in;
- (*env)->SetIntField(env, this, offID, this_off);
- (*env)->SetIntField(env, this, lenID, strm->avail_in);
- return len - strm->avail_out;
+ inputUsed = inputLen - strm->avail_in;
+ outputUsed = outputLen - strm->avail_out;
+ break;
default:
JNU_ThrowInternalError(env, strm->msg);
return 0;
}
}
+ return ((jlong)inputUsed) | (((jlong)outputUsed) << 31) | (((jlong)finished) << 62) | (((jlong)setParams) << 63);
+}
+
+JNIEXPORT jlong JNICALL
+Java_java_util_zip_Deflater_deflateBytesBytes(JNIEnv *env, jobject this, jlong addr,
+ jbyteArray inputArray, jint inputOff, jint inputLen,
+ jbyteArray outputArray, jint outputOff, jint outputLen,
+ jint flush, jint params)
+{
+ jbyte *input = (*env)->GetPrimitiveArrayCritical(env, inputArray, 0);
+ jbyte *output;
+ jlong retVal;
+ if (input == NULL) {
+ if (inputLen != 0 && (*env)->ExceptionOccurred(env) == NULL)
+ JNU_ThrowOutOfMemoryError(env, 0);
+ return 0L;
+ }
+ output = (*env)->GetPrimitiveArrayCritical(env, outputArray, 0);
+ if (output == NULL) {
+ (*env)->ReleasePrimitiveArrayCritical(env, inputArray, input, 0);
+ if (outputLen != 0 && (*env)->ExceptionOccurred(env) == NULL)
+ JNU_ThrowOutOfMemoryError(env, 0);
+ return 0L;
+ }
+
+ retVal = doDeflate(env, this, addr,
+ input + inputOff, inputLen,
+ output + outputOff, outputLen,
+ flush, params);
+
+ (*env)->ReleasePrimitiveArrayCritical(env, outputArray, output, 0);
+ (*env)->ReleasePrimitiveArrayCritical(env, inputArray, input, 0);
+
+ return retVal;
+}
+
+
+JNIEXPORT jlong JNICALL
+Java_java_util_zip_Deflater_deflateBytesBuffer(JNIEnv *env, jobject this, jlong addr,
+ jbyteArray inputArray, jint inputOff, jint inputLen,
+ jlong outputBuffer, jint outputLen,
+ jint flush, jint params)
+{
+ jbyte *input = (*env)->GetPrimitiveArrayCritical(env, inputArray, 0);
+ jbyte *output;
+ jlong retVal;
+ if (input == NULL) {
+ if (inputLen != 0 && (*env)->ExceptionOccurred(env) == NULL)
+ JNU_ThrowOutOfMemoryError(env, 0);
+ return 0L;
+ }
+ output = jlong_to_ptr(outputBuffer);
+
+ retVal = doDeflate(env, this, addr,
+ input + inputOff, inputLen,
+ output, outputLen,
+ flush, params);
+
+ (*env)->ReleasePrimitiveArrayCritical(env, inputArray, input, 0);
+
+ return retVal;
+}
+
+JNIEXPORT jlong JNICALL
+Java_java_util_zip_Deflater_deflateBufferBytes(JNIEnv *env, jobject this, jlong addr,
+ jlong inputBuffer, jint inputLen,
+ jbyteArray outputArray, jint outputOff, jint outputLen,
+ jint flush, jint params)
+{
+ jbyte *input = jlong_to_ptr(inputBuffer);
+ jbyte *output = (*env)->GetPrimitiveArrayCritical(env, outputArray, 0);
+ jlong retVal;
+ if (output == NULL) {
+ if (outputLen != 0 && (*env)->ExceptionOccurred(env) == NULL)
+ JNU_ThrowOutOfMemoryError(env, 0);
+ return 0L;
+ }
+
+ retVal = doDeflate(env, this, addr,
+ input, inputLen,
+ output + outputOff, outputLen,
+ flush, params);
+
+ (*env)->ReleasePrimitiveArrayCritical(env, outputArray, input, 0);
+
+ return retVal;
+}
+
+JNIEXPORT jlong JNICALL
+Java_java_util_zip_Deflater_deflateBufferBuffer(JNIEnv *env, jobject this, jlong addr,
+ jlong inputBuffer, jint inputLen,
+ jlong outputBuffer, jint outputLen,
+ jint flush, jint params)
+{
+ jbyte *input = jlong_to_ptr(inputBuffer);
+ jbyte *output = jlong_to_ptr(outputBuffer);
+
+ return doDeflate(env, this, addr,
+ input, inputLen,
+ output, outputLen,
+ flush, params);
}
JNIEXPORT jint JNICALL
--- a/src/java.base/share/native/libzip/Inflater.c Wed Apr 18 14:07:41 2018 -0700
+++ b/src/java.base/share/native/libzip/Inflater.c Fri Apr 20 09:05:05 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -42,23 +42,16 @@
#define ThrowDataFormatException(env, msg) \
JNU_ThrowByName(env, "java/util/zip/DataFormatException", msg)
-static jfieldID needDictID;
-static jfieldID finishedID;
-static jfieldID bufID, offID, lenID;
+static jfieldID inputConsumedID;
+static jfieldID outputConsumedID;
JNIEXPORT void JNICALL
Java_java_util_zip_Inflater_initIDs(JNIEnv *env, jclass cls)
{
- needDictID = (*env)->GetFieldID(env, cls, "needDict", "Z");
- CHECK_NULL(needDictID);
- finishedID = (*env)->GetFieldID(env, cls, "finished", "Z");
- CHECK_NULL(finishedID);
- bufID = (*env)->GetFieldID(env, cls, "buf", "[B");
- CHECK_NULL(bufID);
- offID = (*env)->GetFieldID(env, cls, "off", "I");
- CHECK_NULL(offID);
- lenID = (*env)->GetFieldID(env, cls, "len", "I");
- CHECK_NULL(lenID);
+ inputConsumedID = (*env)->GetFieldID(env, cls, "inputConsumed", "I");
+ outputConsumedID = (*env)->GetFieldID(env, cls, "outputConsumed", "I");
+ CHECK_NULL(inputConsumedID);
+ CHECK_NULL(outputConsumedID);
}
JNIEXPORT jlong JNICALL
@@ -94,16 +87,9 @@
}
}
-JNIEXPORT void JNICALL
-Java_java_util_zip_Inflater_setDictionary(JNIEnv *env, jclass cls, jlong addr,
- jarray b, jint off, jint len)
+static void doSetDictionary(JNIEnv *env, jlong addr, jbyte *buf, jint len)
{
- Bytef *buf = (*env)->GetPrimitiveArrayCritical(env, b, 0);
- int res;
- if (buf == 0) /* out of memory */
- return;
- res = inflateSetDictionary(jlong_to_ptr(addr), buf + off, len);
- (*env)->ReleasePrimitiveArrayCritical(env, b, buf, 0);
+ int res = inflateSetDictionary(jlong_to_ptr(addr), (Bytef *) buf, len);
switch (res) {
case Z_OK:
break;
@@ -117,68 +103,168 @@
}
}
-JNIEXPORT jint JNICALL
-Java_java_util_zip_Inflater_inflateBytes(JNIEnv *env, jobject this, jlong addr,
- jarray b, jint off, jint len)
+JNIEXPORT void JNICALL
+Java_java_util_zip_Inflater_setDictionary(JNIEnv *env, jclass cls, jlong addr,
+ jbyteArray b, jint off, jint len)
+{
+ jbyte *buf = (*env)->GetPrimitiveArrayCritical(env, b, 0);
+ if (buf == NULL) /* out of memory */
+ return;
+ doSetDictionary(env, addr, buf + off, len);
+ (*env)->ReleasePrimitiveArrayCritical(env, b, buf, 0);
+}
+
+JNIEXPORT void JNICALL
+Java_java_util_zip_Inflater_setDictionaryBuffer(JNIEnv *env, jclass cls, jlong addr,
+ jlong bufferAddr, jint len)
+{
+ jbyte *buf = jlong_to_ptr(bufferAddr);
+ doSetDictionary(env, addr, buf, len);
+}
+
+static jlong doInflate(JNIEnv *env, jobject this, jlong addr,
+ jbyte *input, jint inputLen,
+ jbyte *output, jint outputLen)
{
z_stream *strm = jlong_to_ptr(addr);
- jarray this_buf = (jarray)(*env)->GetObjectField(env, this, bufID);
- jint this_off = (*env)->GetIntField(env, this, offID);
- jint this_len = (*env)->GetIntField(env, this, lenID);
-
- jbyte *in_buf;
- jbyte *out_buf;
+ jint inputUsed = 0, outputUsed = 0;
+ int finished = 0;
+ int needDict = 0;
int ret;
- in_buf = (*env)->GetPrimitiveArrayCritical(env, this_buf, 0);
- if (in_buf == NULL) {
- if (this_len != 0 && (*env)->ExceptionOccurred(env) == NULL)
- JNU_ThrowOutOfMemoryError(env, 0);
- return 0;
- }
- out_buf = (*env)->GetPrimitiveArrayCritical(env, b, 0);
- if (out_buf == NULL) {
- (*env)->ReleasePrimitiveArrayCritical(env, this_buf, in_buf, 0);
- if (len != 0 && (*env)->ExceptionOccurred(env) == NULL)
- JNU_ThrowOutOfMemoryError(env, 0);
- return 0;
- }
- strm->next_in = (Bytef *) (in_buf + this_off);
- strm->next_out = (Bytef *) (out_buf + off);
- strm->avail_in = this_len;
- strm->avail_out = len;
+ strm->next_in = (Bytef *) input;
+ strm->next_out = (Bytef *) output;
+ strm->avail_in = inputLen;
+ strm->avail_out = outputLen;
+
ret = inflate(strm, Z_PARTIAL_FLUSH);
- (*env)->ReleasePrimitiveArrayCritical(env, b, out_buf, 0);
- (*env)->ReleasePrimitiveArrayCritical(env, this_buf, in_buf, 0);
switch (ret) {
case Z_STREAM_END:
- (*env)->SetBooleanField(env, this, finishedID, JNI_TRUE);
+ finished = 1;
/* fall through */
case Z_OK:
- this_off += this_len - strm->avail_in;
- (*env)->SetIntField(env, this, offID, this_off);
- (*env)->SetIntField(env, this, lenID, strm->avail_in);
- return (jint) (len - strm->avail_out);
+ inputUsed = inputLen - strm->avail_in;
+ outputUsed = outputLen - strm->avail_out;
+ break;
case Z_NEED_DICT:
- (*env)->SetBooleanField(env, this, needDictID, JNI_TRUE);
+ needDict = 1;
/* Might have consumed some input here! */
- this_off += this_len - strm->avail_in;
- (*env)->SetIntField(env, this, offID, this_off);
- (*env)->SetIntField(env, this, lenID, strm->avail_in);
- return 0;
+ inputUsed = inputLen - strm->avail_in;
+ /* zlib is unclear about whether output may be produced */
+ outputUsed = outputLen - strm->avail_out;
+ break;
case Z_BUF_ERROR:
- return 0;
+ break;
case Z_DATA_ERROR:
+ inputUsed = inputLen - strm->avail_in;
+ (*env)->SetIntField(env, this, inputConsumedID, inputUsed);
+ outputUsed = outputLen - strm->avail_out;
+ (*env)->SetIntField(env, this, outputConsumedID, outputUsed);
ThrowDataFormatException(env, strm->msg);
- return 0;
+ break;
case Z_MEM_ERROR:
JNU_ThrowOutOfMemoryError(env, 0);
- return 0;
+ break;
default:
JNU_ThrowInternalError(env, strm->msg);
- return 0;
+ break;
+ }
+ return ((jlong)inputUsed) | (((jlong)outputUsed) << 31) | (((jlong)finished) << 62) | (((jlong)needDict) << 63);
+}
+
+JNIEXPORT jlong JNICALL
+Java_java_util_zip_Inflater_inflateBytesBytes(JNIEnv *env, jobject this, jlong addr,
+ jbyteArray inputArray, jint inputOff, jint inputLen,
+ jbyteArray outputArray, jint outputOff, jint outputLen)
+{
+ jbyte *input = (*env)->GetPrimitiveArrayCritical(env, inputArray, 0);
+ jbyte *output;
+ jlong retVal;
+
+ if (input == NULL) {
+ if (inputLen != 0 && (*env)->ExceptionOccurred(env) == NULL)
+ JNU_ThrowOutOfMemoryError(env, 0);
+ return 0L;
+ }
+ output = (*env)->GetPrimitiveArrayCritical(env, outputArray, 0);
+ if (output == NULL) {
+ (*env)->ReleasePrimitiveArrayCritical(env, inputArray, input, 0);
+ if (outputLen != 0 && (*env)->ExceptionOccurred(env) == NULL)
+ JNU_ThrowOutOfMemoryError(env, 0);
+ return 0L;
}
+
+ retVal = doInflate(env, this, addr,
+ input + inputOff, inputLen,
+ output + outputOff, outputLen);
+
+ (*env)->ReleasePrimitiveArrayCritical(env, outputArray, output, 0);
+ (*env)->ReleasePrimitiveArrayCritical(env, inputArray, input, 0);
+
+ return retVal;
+}
+
+JNIEXPORT jlong JNICALL
+Java_java_util_zip_Inflater_inflateBytesBuffer(JNIEnv *env, jobject this, jlong addr,
+ jbyteArray inputArray, jint inputOff, jint inputLen,
+ jlong outputBuffer, jint outputLen)
+{
+ jbyte *input = (*env)->GetPrimitiveArrayCritical(env, inputArray, 0);
+ jbyte *output;
+ jlong retVal;
+
+ if (input == NULL) {
+ if (inputLen != 0 && (*env)->ExceptionOccurred(env) == NULL)
+ JNU_ThrowOutOfMemoryError(env, 0);
+ return 0L;
+ }
+ output = jlong_to_ptr(outputBuffer);
+
+ retVal = doInflate(env, this, addr,
+ input + inputOff, inputLen,
+ output, outputLen);
+
+ (*env)->ReleasePrimitiveArrayCritical(env, inputArray, input, 0);
+
+ return retVal;
+}
+
+JNIEXPORT jlong JNICALL
+Java_java_util_zip_Inflater_inflateBufferBytes(JNIEnv *env, jobject this, jlong addr,
+ jlong inputBuffer, jint inputLen,
+ jbyteArray outputArray, jint outputOff, jint outputLen)
+{
+ jbyte *input = jlong_to_ptr(inputBuffer);
+ jbyte *output = (*env)->GetPrimitiveArrayCritical(env, outputArray, 0);
+ jlong retVal;
+
+ if (output == NULL) {
+ if (outputLen != 0 && (*env)->ExceptionOccurred(env) == NULL)
+ JNU_ThrowOutOfMemoryError(env, 0);
+ return 0L;
+ }
+
+ retVal = doInflate(env, this, addr,
+ input, inputLen,
+ output + outputOff, outputLen);
+
+ (*env)->ReleasePrimitiveArrayCritical(env, outputArray, output, 0);
+
+ return retVal;
+}
+
+JNIEXPORT jlong JNICALL
+Java_java_util_zip_Inflater_inflateBufferBuffer(JNIEnv *env, jobject this, jlong addr,
+ jlong inputBuffer, jint inputLen,
+ jlong outputBuffer, jint outputLen)
+{
+ jbyte *input = jlong_to_ptr(inputBuffer);
+ jbyte *output = jlong_to_ptr(outputBuffer);
+
+ return doInflate(env, this, addr,
+ input, inputLen,
+ output, outputLen);
}
JNIEXPORT jint JNICALL
--- a/src/java.base/share/native/libzip/zip_util.c Wed Apr 18 14:07:41 2018 -0700
+++ b/src/java.base/share/native/libzip/zip_util.c Fri Apr 20 09:05:05 2018 -0700
@@ -881,7 +881,7 @@
* set to the error message text if msg != 0. Otherwise, *msg will be
* set to NULL. Caller doesn't need to free the error message.
*/
-JNIEXPORT jzfile * JNICALL
+JNIEXPORT jzfile *
ZIP_Open(const char *name, char **pmsg)
{
jzfile *file = ZIP_Open_Generic(name, pmsg, O_RDONLY, 0);
@@ -895,7 +895,7 @@
/*
* Closes the specified zip file object.
*/
-JNIEXPORT void JNICALL
+JNIEXPORT void
ZIP_Close(jzfile *zip)
{
MLOCK(zfiles_lock);
@@ -1115,7 +1115,7 @@
* Returns the zip entry corresponding to the specified name, or
* NULL if not found.
*/
-JNIEXPORT jzentry * JNICALL
+JNIEXPORT jzentry *
ZIP_GetEntry(jzfile *zip, char *name, jint ulen)
{
if (ulen == 0) {
@@ -1238,7 +1238,7 @@
* Returns the n'th (starting at zero) zip file entry, or NULL if the
* specified index was out of range.
*/
-JNIEXPORT jzentry * JNICALL
+JNIEXPORT jzentry *
ZIP_GetNextEntry(jzfile *zip, jint n)
{
jzentry *result;
@@ -1439,7 +1439,7 @@
* The current implementation does not support reading an entry that
* has the size bigger than 2**32 bytes in ONE invocation.
*/
-JNIEXPORT jzentry * JNICALL
+JNIEXPORT jzentry *
ZIP_FindEntry(jzfile *zip, char *name, jint *sizeP, jint *nameLenP)
{
jzentry *entry = ZIP_GetEntry(zip, name, 0);
@@ -1456,7 +1456,7 @@
* Note: this is called from the separately delivered VM (hotspot/classic)
* so we have to be careful to maintain the expected behaviour.
*/
-JNIEXPORT jboolean JNICALL
+JNIEXPORT jboolean
ZIP_ReadEntry(jzfile *zip, jzentry *entry, unsigned char *buf, char *entryname)
{
char *msg;
@@ -1515,7 +1515,7 @@
return JNI_TRUE;
}
-JNIEXPORT jboolean JNICALL
+JNIEXPORT jboolean
ZIP_InflateFully(void *inBuf, jlong inLen, void *outBuf, jlong outLen, char **pmsg)
{
z_stream strm;
--- a/src/java.base/share/native/libzip/zip_util.h Wed Apr 18 14:07:41 2018 -0700
+++ b/src/java.base/share/native/libzip/zip_util.h Fri Apr 20 09:05:05 2018 -0700
@@ -241,16 +241,16 @@
*/
#define ZIP_ENDCHAIN ((jint)-1)
-JNIEXPORT jzentry * JNICALL
+JNIEXPORT jzentry *
ZIP_FindEntry(jzfile *zip, char *name, jint *sizeP, jint *nameLenP);
-JNIEXPORT jboolean JNICALL
+JNIEXPORT jboolean
ZIP_ReadEntry(jzfile *zip, jzentry *entry, unsigned char *buf, char *entrynm);
-JNIEXPORT jzentry * JNICALL
+JNIEXPORT jzentry *
ZIP_GetNextEntry(jzfile *zip, jint n);
-JNIEXPORT jzfile * JNICALL
+JNIEXPORT jzfile *
ZIP_Open(const char *name, char **pmsg);
jzfile *
@@ -265,10 +265,10 @@
jzfile *
ZIP_Put_In_Cache0(const char *name, ZFILE zfd, char **pmsg, jlong lastModified, jboolean usemmap);
-JNIEXPORT void JNICALL
+JNIEXPORT void
ZIP_Close(jzfile *zip);
-JNIEXPORT jzentry * JNICALL
+JNIEXPORT jzentry *
ZIP_GetEntry(jzfile *zip, char *name, jint ulen);
JNIEXPORT void JNICALL
ZIP_Lock(jzfile *zip);
@@ -281,7 +281,7 @@
jlong ZIP_GetEntryDataOffset(jzfile *zip, jzentry *entry);
jzentry * ZIP_GetEntry2(jzfile *zip, char *name, jint ulen, jboolean addSlash);
-JNIEXPORT jboolean JNICALL
+JNIEXPORT jboolean
ZIP_InflateFully(void *inBuf, jlong inLen, void *outBuf, jlong outLen, char **pmsg);
#endif /* !_ZIP_H_ */
--- a/src/java.base/windows/classes/java/net/DualStackPlainSocketImpl.java Wed Apr 18 14:07:41 2018 -0700
+++ b/src/java.base/windows/classes/java/net/DualStackPlainSocketImpl.java Fri Apr 20 09:05:05 2018 -0700
@@ -26,14 +26,18 @@
import java.io.IOException;
import java.io.FileDescriptor;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import sun.security.action.GetPropertyAction;
import jdk.internal.misc.SharedSecrets;
import jdk.internal.misc.JavaIOFileDescriptorAccess;
/**
- * This class defines the plain SocketImpl that is used on Windows platforms
- * greater or equal to Windows Vista. These platforms have a dual
- * layer TCP/IP stack and can handle both IPv4 and IPV6 through a
- * single file descriptor.
+ * This class defines the plain SocketImpl.
+ * When java.net.preferIPv4Stack system property is set to true, it uses
+ * IPv4-only socket.
+ * When java.net.preferIPv4Stack is set to false, it handles both IPv4
+ * and IPv6 through a single file descriptor.
*
* @author Chris Hegarty
*/
@@ -43,30 +47,43 @@
private static final JavaIOFileDescriptorAccess fdAccess =
SharedSecrets.getJavaIOFileDescriptorAccess();
- // true if this socket is exclusively bound
- private final boolean exclusiveBind;
+ private static final boolean preferIPv4Stack =
+ Boolean.parseBoolean(AccessController.doPrivileged(
+ new GetPropertyAction("java.net.preferIPv4Stack", "false")));
+
+ /**
+ * Empty value of sun.net.useExclusiveBind is treated as 'true'.
+ */
+ private static final boolean useExclusiveBind;
- // emulates SO_REUSEADDR when exclusiveBind is true
+ static {
+ String exclBindProp = AccessController.doPrivileged(
+ new GetPropertyAction("sun.net.useExclusiveBind", ""));
+ useExclusiveBind = exclBindProp.isEmpty()
+ || Boolean.parseBoolean(exclBindProp);
+ }
+
+ // emulates SO_REUSEADDR when useExclusiveBind is true
private boolean isReuseAddress;
- public DualStackPlainSocketImpl(boolean exclBind) {
- exclusiveBind = exclBind;
+ public DualStackPlainSocketImpl() {
}
- public DualStackPlainSocketImpl(FileDescriptor fd, boolean exclBind) {
+ public DualStackPlainSocketImpl(FileDescriptor fd) {
this.fd = fd;
- exclusiveBind = exclBind;
}
+ @Override
void socketCreate(boolean stream) throws IOException {
if (fd == null)
throw new SocketException("Socket closed");
- int newfd = socket0(stream, false /*v6 Only*/);
+ int newfd = socket0(stream);
fdAccess.set(fd, newfd);
}
+ @Override
void socketConnect(InetAddress address, int port, int timeout)
throws IOException {
int nativefd = checkAndReturnNativeFD();
@@ -74,6 +91,9 @@
if (address == null)
throw new NullPointerException("inet address argument is null.");
+ if (preferIPv4Stack && !(address instanceof Inet4Address))
+ throw new SocketException("Protocol family not supported");
+
int connectResult;
if (timeout <= 0) {
connectResult = connect0(nativefd, address, port);
@@ -97,13 +117,17 @@
localport = localPort0(nativefd);
}
+ @Override
void socketBind(InetAddress address, int port) throws IOException {
int nativefd = checkAndReturnNativeFD();
if (address == null)
throw new NullPointerException("inet address argument is null.");
- bind0(nativefd, address, port, exclusiveBind);
+ if (preferIPv4Stack && !(address instanceof Inet4Address))
+ throw new SocketException("Protocol family not supported");
+
+ bind0(nativefd, address, port, useExclusiveBind);
if (port == 0) {
localport = localPort0(nativefd);
} else {
@@ -113,12 +137,14 @@
this.address = address;
}
+ @Override
void socketListen(int backlog) throws IOException {
int nativefd = checkAndReturnNativeFD();
listen0(nativefd, backlog);
}
+ @Override
void socketAccept(SocketImpl s) throws IOException {
int nativefd = checkAndReturnNativeFD();
@@ -148,13 +174,17 @@
s.port = isa.getPort();
s.address = isa.getAddress();
s.localport = localport;
+ if (preferIPv4Stack && !(s.address instanceof Inet4Address))
+ throw new SocketException("Protocol family not supported");
}
+ @Override
int socketAvailable() throws IOException {
int nativefd = checkAndReturnNativeFD();
return available0(nativefd);
}
+ @Override
void socketClose0(boolean useDeferredClose/*unused*/) throws IOException {
if (fd == null)
throw new SocketException("Socket closed");
@@ -167,6 +197,7 @@
close0(nativefd);
}
+ @Override
void socketShutdown(int howto) throws IOException {
int nativefd = checkAndReturnNativeFD();
shutdown0(nativefd, howto);
@@ -174,41 +205,51 @@
// Intentional fallthrough after SO_REUSEADDR
@SuppressWarnings("fallthrough")
+ @Override
void socketSetOption(int opt, boolean on, Object value)
throws SocketException {
- int nativefd = checkAndReturnNativeFD();
- if (opt == SO_TIMEOUT) { // timeout implemented through select.
- return;
- }
// SO_REUSEPORT is not supported on Windows.
if (opt == SO_REUSEPORT) {
throw new UnsupportedOperationException("unsupported option");
}
+ int nativefd = checkAndReturnNativeFD();
+
+ if (opt == SO_TIMEOUT) {
+ if (preferIPv4Stack) {
+ // Don't enable the socket option on ServerSocket as it's
+ // meaningless (we don't receive on a ServerSocket).
+ if (serverSocket == null) {
+ setSoTimeout0(nativefd, ((Integer)value).intValue());
+ }
+ } // else timeout is implemented through select.
+ return;
+ }
+
int optionValue = 0;
switch(opt) {
- case SO_REUSEADDR :
- if (exclusiveBind) {
+ case SO_REUSEADDR:
+ if (useExclusiveBind) {
// SO_REUSEADDR emulated when using exclusive bind
isReuseAddress = on;
return;
}
// intentional fallthrough
- case TCP_NODELAY :
- case SO_OOBINLINE :
- case SO_KEEPALIVE :
+ case TCP_NODELAY:
+ case SO_OOBINLINE:
+ case SO_KEEPALIVE:
optionValue = on ? 1 : 0;
break;
- case SO_SNDBUF :
- case SO_RCVBUF :
- case IP_TOS :
+ case SO_SNDBUF:
+ case SO_RCVBUF:
+ case IP_TOS:
optionValue = ((Integer)value).intValue();
break;
- case SO_LINGER :
+ case SO_LINGER:
if (on) {
- optionValue = ((Integer)value).intValue();
+ optionValue = ((Integer)value).intValue();
} else {
optionValue = -1;
}
@@ -220,7 +261,15 @@
setIntOption(nativefd, opt, optionValue);
}
- int socketGetOption(int opt, Object iaContainerObj) throws SocketException {
+ @Override
+ int socketGetOption(int opt, Object iaContainerObj)
+ throws SocketException {
+
+ // SO_REUSEPORT is not supported on Windows.
+ if (opt == SO_REUSEPORT) {
+ throw new UnsupportedOperationException("unsupported option");
+ }
+
int nativefd = checkAndReturnNativeFD();
// SO_BINDADDR is not a socket option.
@@ -228,27 +277,24 @@
localAddress(nativefd, (InetAddressContainer)iaContainerObj);
return 0; // return value doesn't matter.
}
- // SO_REUSEPORT is not supported on Windows.
- if (opt == SO_REUSEPORT) {
- throw new UnsupportedOperationException("unsupported option");
- }
// SO_REUSEADDR emulated when using exclusive bind
- if (opt == SO_REUSEADDR && exclusiveBind)
- return isReuseAddress? 1 : -1;
+ if (opt == SO_REUSEADDR && useExclusiveBind)
+ return isReuseAddress ? 1 : -1;
int value = getIntOption(nativefd, opt);
switch (opt) {
- case TCP_NODELAY :
- case SO_OOBINLINE :
- case SO_KEEPALIVE :
- case SO_REUSEADDR :
+ case TCP_NODELAY:
+ case SO_OOBINLINE:
+ case SO_KEEPALIVE:
+ case SO_REUSEADDR:
return (value == 0) ? -1 : 1;
}
return value;
}
+ @Override
void socketSendUrgentData(int data) throws IOException {
int nativefd = checkAndReturnNativeFD();
sendOOB(nativefd, data);
@@ -271,7 +317,7 @@
static native void initIDs();
- static native int socket0(boolean stream, boolean v6Only) throws IOException;
+ static native int socket0(boolean stream) throws IOException;
static native void bind0(int fd, InetAddress localAddress, int localport,
boolean exclBind)
@@ -300,6 +346,8 @@
static native void setIntOption(int fd, int cmd, int optionValue) throws SocketException;
+ static native void setSoTimeout0(int fd, int timeout) throws SocketException;
+
static native int getIntOption(int fd, int cmd) throws SocketException;
static native void sendOOB(int fd, int data) throws IOException;
--- a/src/java.base/windows/classes/java/net/PlainSocketImpl.java Wed Apr 18 14:07:41 2018 -0700
+++ b/src/java.base/windows/classes/java/net/PlainSocketImpl.java Fri Apr 20 09:05:05 2018 -0700
@@ -25,20 +25,13 @@
package java.net;
import java.io.*;
-import java.security.AccessController;
-import java.security.PrivilegedAction;
-import sun.security.action.GetPropertyAction;
/*
* This class PlainSocketImpl simply delegates to the appropriate real
* SocketImpl. We do this because PlainSocketImpl is already extended
* by SocksSocketImpl.
* <p>
- * There are two possibilities for the real SocketImpl,
- * TwoStacksPlainSocketImpl or DualStackPlainSocketImpl. We use
- * DualStackPlainSocketImpl on systems that have a dual stack
- * TCP implementation. Otherwise we create an instance of
- * TwoStacksPlainSocketImpl and delegate to it.
+ * There is one possibility for the real SocketImpl: DualStackPlainSocketImpl.
*
* @author Chris Hegarty
*/
@@ -46,44 +39,18 @@
class PlainSocketImpl extends AbstractPlainSocketImpl {
private AbstractPlainSocketImpl impl;
- /* java.net.preferIPv4Stack */
- private static final boolean preferIPv4Stack;
-
- /* True if exclusive binding is on for Windows */
- private static final boolean exclusiveBind;
-
- static {
- preferIPv4Stack = Boolean.parseBoolean(
- AccessController.doPrivileged(
- new GetPropertyAction("java.net.preferIPv4Stack")));
-
- String exclBindProp = AccessController.doPrivileged(
- new GetPropertyAction("sun.net.useExclusiveBind", ""));
- exclusiveBind = (exclBindProp.isEmpty())
- ? true
- : Boolean.parseBoolean(exclBindProp);
- }
-
/**
* Constructs an empty instance.
*/
PlainSocketImpl() {
- if (!preferIPv4Stack) {
- impl = new DualStackPlainSocketImpl(exclusiveBind);
- } else {
- impl = new TwoStacksPlainSocketImpl(exclusiveBind);
- }
+ impl = new DualStackPlainSocketImpl();
}
/**
* Constructs an instance with the given file descriptor.
*/
PlainSocketImpl(FileDescriptor fd) {
- if (!preferIPv4Stack) {
- impl = new DualStackPlainSocketImpl(fd, exclusiveBind);
- } else {
- impl = new TwoStacksPlainSocketImpl(fd, exclusiveBind);
- }
+ impl = new DualStackPlainSocketImpl(fd);
}
// Override methods in SocketImpl that access impl's fields.
@@ -148,18 +115,10 @@
}
public void setOption(int opt, Object val) throws SocketException {
- if (opt == SocketOptions.SO_REUSEPORT) {
- // SO_REUSEPORT is not supported on Windows.
- throw new UnsupportedOperationException("unsupported option");
- }
impl.setOption(opt, val);
}
public Object getOption(int opt) throws SocketException {
- if (opt == SocketOptions.SO_REUSEPORT) {
- // SO_REUSEPORT is not supported on Windows.
- throw new UnsupportedOperationException("unsupported option");
- }
return impl.getOption(opt);
}
@@ -271,8 +230,8 @@
// Override methods in AbstractPlainSocketImpl that need to be implemented.
- void socketCreate(boolean isServer) throws IOException {
- impl.socketCreate(isServer);
+ void socketCreate(boolean stream) throws IOException {
+ impl.socketCreate(stream);
}
void socketConnect(InetAddress address, int port, int timeout)
@@ -307,18 +266,10 @@
void socketSetOption(int cmd, boolean on, Object value)
throws SocketException {
- if (cmd == SocketOptions.SO_REUSEPORT) {
- // SO_REUSEPORT is not supported on Windows.
- throw new UnsupportedOperationException("unsupported option");
- }
impl.socketSetOption(cmd, on, value);
}
int socketGetOption(int opt, Object iaContainerObj) throws SocketException {
- if (opt == SocketOptions.SO_REUSEPORT) {
- // SO_REUSEPORT is not supported on Windows.
- throw new UnsupportedOperationException("unsupported option");
- }
return impl.socketGetOption(opt, iaContainerObj);
}
--- a/src/java.base/windows/classes/java/net/TwoStacksPlainSocketImpl.java Wed Apr 18 14:07:41 2018 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,324 +0,0 @@
-/*
- * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package java.net;
-
-import java.io.IOException;
-import java.io.FileDescriptor;
-import sun.net.ResourceManager;
-import jdk.internal.misc.SharedSecrets;
-import jdk.internal.misc.JavaIOFileDescriptorAccess;
-
-/*
- * This class defines the plain SocketImpl that is used when
- * the System property java.net.preferIPv4Stack is set to true.
- *
- * @author Chris Hegarty
- */
-
-class TwoStacksPlainSocketImpl extends AbstractPlainSocketImpl {
-
- private static final JavaIOFileDescriptorAccess fdAccess =
- SharedSecrets.getJavaIOFileDescriptorAccess();
-
- // true if this socket is exclusively bound
- private final boolean exclusiveBind;
-
- // emulates SO_REUSEADDR when exclusiveBind is true
- private boolean isReuseAddress;
-
- public TwoStacksPlainSocketImpl(boolean exclBind) {
- exclusiveBind = exclBind;
- }
-
- public TwoStacksPlainSocketImpl(FileDescriptor fd, boolean exclBind) {
- this.fd = fd;
- exclusiveBind = exclBind;
- }
-
- void socketCreate(boolean stream) throws IOException {
- if (fd == null)
- throw new SocketException("Socket closed");
-
- int newfd = socket0(stream, false /*v6 Only*/);
-
- fdAccess.set(fd, newfd);
- }
-
- @Override
- void socketConnect(InetAddress address, int port, int timeout)
- throws IOException {
- int nativefd = checkAndReturnNativeFD();
-
- if (address == null)
- throw new NullPointerException("inet address argument is null.");
-
- int connectResult;
- if (timeout <= 0) {
- connectResult = connect0(nativefd, address, port);
- } else {
- configureBlocking(nativefd, false);
- try {
- connectResult = connect0(nativefd, address, port);
- if (connectResult == WOULDBLOCK) {
- waitForConnect(nativefd, timeout);
- }
- } finally {
- configureBlocking(nativefd, true);
- }
- }
- /*
- * We need to set the local port field. If bind was called
- * previous to the connect (by the client) then localport field
- * will already be set.
- */
- if (localport == 0)
- localport = localPort0(nativefd);
- }
-
- @Override
- void socketBind(InetAddress address, int port) throws IOException {
- int nativefd = checkAndReturnNativeFD();
-
- if (address == null)
- throw new NullPointerException("inet address argument is null.");
-
- bind0(nativefd, address, port, exclusiveBind);
- if (port == 0) {
- localport = localPort0(nativefd);
- } else {
- localport = port;
- }
-
- this.address = address;
- }
-
- @Override
- void socketListen(int backlog) throws IOException {
- int nativefd = checkAndReturnNativeFD();
-
- listen0(nativefd, backlog);
- }
-
- @Override
- void socketAccept(SocketImpl s) throws IOException {
- int nativefd = checkAndReturnNativeFD();
-
- if (s == null)
- throw new NullPointerException("socket is null");
-
- int newfd = -1;
- InetSocketAddress[] isaa = new InetSocketAddress[1];
- if (timeout <= 0) {
- newfd = accept0(nativefd, isaa);
- } else {
- configureBlocking(nativefd, false);
- try {
- waitForNewConnection(nativefd, timeout);
- newfd = accept0(nativefd, isaa);
- if (newfd != -1) {
- configureBlocking(newfd, true);
- }
- } finally {
- configureBlocking(nativefd, true);
- }
- }
- /* Update (SocketImpl)s' fd */
- fdAccess.set(s.fd, newfd);
- /* Update socketImpls remote port, address and localport */
- InetSocketAddress isa = isaa[0];
- s.port = isa.getPort();
- s.address = isa.getAddress();
- s.localport = localport;
- }
-
- @Override
- int socketAvailable() throws IOException {
- int nativefd = checkAndReturnNativeFD();
- return available0(nativefd);
- }
-
- @Override
- void socketClose0(boolean useDeferredClose/*unused*/) throws IOException {
- if (fd == null)
- throw new SocketException("Socket closed");
-
- if (!fd.valid())
- return;
-
- final int nativefd = fdAccess.get(fd);
- fdAccess.set(fd, -1);
- close0(nativefd);
- }
-
- @Override
- void socketShutdown(int howto) throws IOException {
- int nativefd = checkAndReturnNativeFD();
- shutdown0(nativefd, howto);
- }
-
- // Intentional fallthrough after SO_REUSEADDR
- @SuppressWarnings("fallthrough")
- @Override
- void socketSetOption(int opt, boolean on, Object value)
- throws SocketException {
- int nativefd = checkAndReturnNativeFD();
-
- if (opt == SO_TIMEOUT) {
- // Don't enable the socket option on ServerSocket as it's
- // meaningless (we don't receive on a ServerSocket).
- if (serverSocket == null) {
- setSoTimeout0(nativefd, ((Integer)value).intValue());
- }
- return;
- }
- // SO_REUSEPORT is not supported on Windows.
- if (opt == SO_REUSEPORT) {
- throw new UnsupportedOperationException("unsupported option");
- }
-
- int optionValue = 0;
-
- switch(opt) {
- case SO_REUSEADDR :
- if (exclusiveBind) {
- // SO_REUSEADDR emulated when using exclusive bind
- isReuseAddress = on;
- return;
- }
- // intentional fallthrough
- case TCP_NODELAY :
- case SO_OOBINLINE :
- case SO_KEEPALIVE :
- optionValue = on ? 1 : 0;
- break;
- case SO_SNDBUF :
- case SO_RCVBUF :
- case IP_TOS :
- optionValue = ((Integer)value).intValue();
- break;
- case SO_LINGER :
- if (on) {
- optionValue = ((Integer)value).intValue();
- } else {
- optionValue = -1;
- }
- break;
- default :/* shouldn't get here */
- throw new SocketException("Option not supported");
- }
-
- setIntOption(nativefd, opt, optionValue);
- }
-
- @Override
- int socketGetOption(int opt, Object iaContainerObj) throws SocketException {
- int nativefd = checkAndReturnNativeFD();
-
- // SO_BINDADDR is not a socket option.
- if (opt == SO_BINDADDR) {
- localAddress(nativefd, (InetAddressContainer)iaContainerObj);
- return 0; // return value doesn't matter.
- }
- // SO_REUSEPORT is not supported on Windows.
- if (opt == SO_REUSEPORT) {
- throw new UnsupportedOperationException("unsupported option");
- }
-
- // SO_REUSEADDR emulated when using exclusive bind
- if (opt == SO_REUSEADDR && exclusiveBind)
- return isReuseAddress? 1 : -1;
-
- int value = getIntOption(nativefd, opt);
-
- switch (opt) {
- case TCP_NODELAY :
- case SO_OOBINLINE :
- case SO_KEEPALIVE :
- case SO_REUSEADDR :
- return (value == 0) ? -1 : 1;
- }
- return value;
- }
-
- @Override
- void socketSendUrgentData(int data) throws IOException {
- int nativefd = checkAndReturnNativeFD();
- sendOOB(nativefd, data);
- }
-
- private int checkAndReturnNativeFD() throws SocketException {
- if (fd == null || !fd.valid())
- throw new SocketException("Socket closed");
-
- return fdAccess.get(fd);
- }
-
- static final int WOULDBLOCK = -2; // Nothing available (non-blocking)
-
- static {
- initIDs();
- }
-
- /* Native methods */
-
- static native void initIDs();
-
- static native int socket0(boolean stream, boolean v6Only) throws IOException;
-
- static native void bind0(int fd, InetAddress localAddress, int localport,
- boolean exclBind)
- throws IOException;
-
- static native int connect0(int fd, InetAddress remote, int remotePort)
- throws IOException;
-
- static native void waitForConnect(int fd, int timeout) throws IOException;
-
- static native int localPort0(int fd) throws IOException;
-
- static native void localAddress(int fd, InetAddressContainer in) throws SocketException;
-
- static native void listen0(int fd, int backlog) throws IOException;
-
- static native int accept0(int fd, InetSocketAddress[] isaa) throws IOException;
-
- static native void waitForNewConnection(int fd, int timeout) throws IOException;
-
- static native int available0(int fd) throws IOException;
-
- static native void close0(int fd) throws IOException;
-
- static native void shutdown0(int fd, int howto) throws IOException;
-
- static native void setIntOption(int fd, int cmd, int optionValue) throws SocketException;
-
- static native void setSoTimeout0(int fd, int timeout) throws SocketException;
-
- static native int getIntOption(int fd, int cmd) throws SocketException;
-
- static native void sendOOB(int fd, int data) throws IOException;
-
- static native void configureBlocking(int fd, boolean blocking) throws IOException;
-}
--- a/src/java.base/windows/native/libnet/DualStackPlainSocketImpl.c Wed Apr 18 14:07:41 2018 -0700
+++ b/src/java.base/windows/native/libnet/DualStackPlainSocketImpl.c Fri Apr 20 09:05:05 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
* 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,8 +27,8 @@
#include "java_net_DualStackPlainSocketImpl.h"
#include "java_net_SocketOptions.h"
-#define SET_BLOCKING 0
-#define SET_NONBLOCKING 1
+#define SET_BLOCKING 0
+#define SET_NONBLOCKING 1
static jclass isa_class; /* java.net.InetSocketAddress */
static jmethodID isa_ctorID; /* InetSocketAddress(InetAddress, int) */
@@ -60,22 +60,28 @@
* Signature: (ZZ)I
*/
JNIEXPORT jint JNICALL Java_java_net_DualStackPlainSocketImpl_socket0
- (JNIEnv *env, jclass clazz, jboolean stream, jboolean v6Only /*unused*/) {
+ (JNIEnv *env, jclass clazz, jboolean stream) {
int fd, rv, opt=0;
+ int type = (stream ? SOCK_STREAM : SOCK_DGRAM);
+ int domain = ipv6_available() ? AF_INET6 : AF_INET;
- fd = NET_Socket(AF_INET6, (stream ? SOCK_STREAM : SOCK_DGRAM), 0);
+ fd = NET_Socket(domain, type, 0);
+
if (fd == INVALID_SOCKET) {
NET_ThrowNew(env, WSAGetLastError(), "create");
return -1;
}
- rv = setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (char *) &opt, sizeof(opt));
- if (rv == SOCKET_ERROR) {
- NET_ThrowNew(env, WSAGetLastError(), "create");
+ if (domain == AF_INET6) {
+ rv = setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (char *) &opt,
+ sizeof(opt));
+ if (rv == SOCKET_ERROR) {
+ NET_ThrowNew(env, WSAGetLastError(), "create");
+ closesocket(fd);
+ return -1;
+ }
}
- SetHandleInformation((HANDLE)(UINT_PTR)fd, HANDLE_FLAG_INHERIT, FALSE);
-
return fd;
}
@@ -90,10 +96,11 @@
{
SOCKETADDRESS sa;
int rv, sa_len = 0;
+ jboolean v4MappedAddress = ipv6_available() ? JNI_TRUE : JNI_FALSE;
if (NET_InetAddressToSockaddr(env, iaObj, port, &sa,
- &sa_len, JNI_TRUE) != 0) {
- return;
+ &sa_len, v4MappedAddress) != 0) {
+ return;
}
rv = NET_WinBind(fd, &sa, sa_len, exclBind);
@@ -111,10 +118,11 @@
(JNIEnv *env, jclass clazz, jint fd, jobject iaObj, jint port) {
SOCKETADDRESS sa;
int rv, sa_len = 0;
+ jboolean v4MappedAddress = ipv6_available() ? JNI_TRUE : JNI_FALSE;
if (NET_InetAddressToSockaddr(env, iaObj, port, &sa,
- &sa_len, JNI_TRUE) != 0) {
- return -1;
+ &sa_len, v4MappedAddress) != 0) {
+ return -1;
}
rv = connect(fd, &sa.sa, sa_len);
@@ -124,7 +132,8 @@
return java_net_DualStackPlainSocketImpl_WOULDBLOCK;
} else if (err == WSAEADDRNOTAVAIL) {
JNU_ThrowByName(env, JNU_JAVANETPKG "ConnectException",
- "connect: Address is invalid on local machine, or port is not valid on remote machine");
+ "connect: Address is invalid on local machine,"
+ " or port is not valid on remote machine");
} else {
NET_ThrowNew(env, err, "connect");
}
@@ -200,6 +209,10 @@
if (rv == 0) {
JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
"Unable to establish connection");
+ } else if (!ipv6_available() && rv == WSAEADDRNOTAVAIL) {
+ JNU_ThrowByName(env, JNU_JAVANETPKG "ConnectException",
+ "connect: Address is invalid on local machine,"
+ " or port is not valid on remote machine");
} else {
NET_ThrowNew(env, rv, "connect");
}
@@ -284,13 +297,7 @@
newfd = accept(fd, &sa.sa, &len);
if (newfd == INVALID_SOCKET) {
- if (WSAGetLastError() == -2) {
- JNU_ThrowByName(env, JNU_JAVAIOPKG "InterruptedIOException",
- "operation interrupted");
- } else {
- JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
- "socket closed");
- }
+ NET_ThrowNew(env, WSAGetLastError(), "accept failed");
return -1;
}
@@ -298,6 +305,10 @@
ia = NET_SockaddrToInetAddress(env, &sa, &port);
isa = (*env)->NewObject(env, isa_class, isa_ctorID, ia, port);
+ if (isa == NULL) {
+ closesocket(newfd);
+ return -1;
+ }
(*env)->SetObjectArrayElement(env, isaa, 0, isa);
return newfd;
@@ -402,6 +413,51 @@
/*
* Class: java_net_DualStackPlainSocketImpl
+ * Method: setSoTimeout0
+ * Signature: (II)V
+ */
+JNIEXPORT void JNICALL
+Java_java_net_DualStackPlainSocketImpl_setSoTimeout0
+ (JNIEnv *env, jclass clazz, jint fd, jint timeout)
+{
+ /*
+ * SO_TIMEOUT is the socket option used to specify the timeout
+ * for ServerSocket.accept and Socket.getInputStream().read.
+ * It does not typically map to a native level socket option.
+ * For Windows we special-case this and use the SOL_SOCKET/SO_RCVTIMEO
+ * socket option to specify a receive timeout on the socket. This
+ * receive timeout is applicable to Socket only and the socket
+ * option should not be set on ServerSocket.
+ */
+
+ /*
+ * SO_RCVTIMEO is only supported on Microsoft's implementation
+ * of Windows Sockets so if WSAENOPROTOOPT returned then
+ * reset flag and timeout will be implemented using
+ * select() -- see SocketInputStream.socketRead.
+ */
+ if (isRcvTimeoutSupported) {
+ /*
+ * Disable SO_RCVTIMEO if timeout is <= 5 second.
+ */
+ if (timeout <= 5000) {
+ timeout = 0;
+ }
+
+ if (setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout,
+ sizeof(timeout)) < 0) {
+ int err = WSAGetLastError();
+ if (err == WSAENOPROTOOPT) {
+ isRcvTimeoutSupported = JNI_FALSE;
+ } else {
+ NET_ThrowNew(env, err, "setsockopt SO_RCVTIMEO");
+ }
+ }
+ }
+}
+
+/*
+ * Class: java_net_DualStackPlainSocketImpl
* Method: getIntOption
* Signature: (II)I
*/
@@ -466,7 +522,7 @@
int result;
if (blocking == JNI_TRUE) {
- arg = SET_BLOCKING; // 0
+ arg = SET_BLOCKING; // 0
} else {
arg = SET_NONBLOCKING; // 1
}
--- a/src/java.base/windows/native/libnet/TwoStacksPlainSocketImpl.c Wed Apr 18 14:07:41 2018 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,550 +0,0 @@
-/*
- * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
- * 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 "net_util.h"
-
-#include "java_net_TwoStacksPlainSocketImpl.h"
-#include "java_net_SocketOptions.h"
-#include "java_net_InetAddress.h"
-
-#define SET_BLOCKING 0
-#define SET_NONBLOCKING 1
-
-static jclass isa_class; /* java.net.InetSocketAddress */
-static jmethodID isa_ctorID; /* InetSocketAddress(InetAddress, int) */
-
-/************************************************************************
- * TwoStacksPlainSocketImpl
- */
-
-/*
- * The initIDs function is called whenever TwoStacksPlainSocketImpl is
- * loaded, to cache fieldIds for efficiency. This is called everytime
- * the Java class is loaded.
- *
- * Class: java_net_TwoStacksPlainSocketImpl
- * Method: initIDs
- * Signature: ()V
- */
-JNIEXPORT void JNICALL Java_java_net_TwoStacksPlainSocketImpl_initIDs
- (JNIEnv *env, jclass clazz) {
-
- jclass cls = (*env)->FindClass(env, "java/net/InetSocketAddress");
- CHECK_NULL(cls);
- isa_class = (*env)->NewGlobalRef(env, cls);
- CHECK_NULL(isa_class);
- isa_ctorID = (*env)->GetMethodID(env, cls, "<init>",
- "(Ljava/net/InetAddress;I)V");
- CHECK_NULL(isa_ctorID);
-}
-
-/*
- * Class: java_net_TwoStacksPlainSocketImpl
- * Method: socket0
- * Signature: (ZZ)I
- */
-JNIEXPORT jint JNICALL Java_java_net_TwoStacksPlainSocketImpl_socket0
- (JNIEnv *env, jclass clazz, jboolean stream, jboolean v6Only /*unused*/) {
- int fd;
-
- fd = socket(AF_INET, (stream ? SOCK_STREAM: SOCK_DGRAM), 0);
- if (fd == INVALID_SOCKET) {
- NET_ThrowNew(env, WSAGetLastError(), "create");
- return -1;
- }
-
- SetHandleInformation((HANDLE)(UINT_PTR)fd, HANDLE_FLAG_INHERIT, FALSE);
-
- return fd;
-}
-
-/*
- * Class: java_net_TwoStacksPlainSocketImpl
- * Method: bind0
- * Signature: (ILjava/net/InetAddress;I)V
- */
-JNIEXPORT void JNICALL Java_java_net_TwoStacksPlainSocketImpl_bind0
- (JNIEnv *env, jclass clazz, jint fd, jobject iaObj, jint port,
- jboolean exclBind)
-{
- SOCKETADDRESS sa;
- int rv, sa_len = 0;
- /* family is an int field of iaObj */
- int family;
-
- family = getInetAddress_family(env, iaObj);
- if (family != java_net_InetAddress_IPv4) {
- JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
- "Protocol family not supported");
- return;
- }
-
- if (NET_InetAddressToSockaddr(env, iaObj, port, &sa,
- &sa_len, JNI_FALSE) != 0) {
- return;
- }
-
- rv = NET_WinBind(fd, &sa, sa_len, exclBind);
-
- if (rv == SOCKET_ERROR)
- NET_ThrowNew(env, WSAGetLastError(), "NET_Bind");
-}
-
-/*
- * Class: java_net_TwoStacksPlainSocketImpl
- * Method: connect0
- * Signature: (ILjava/net/InetAddress;I)I
- */
-JNIEXPORT jint JNICALL Java_java_net_TwoStacksPlainSocketImpl_connect0
- (JNIEnv *env, jclass clazz, jint fd, jobject iaObj, jint port) {
- SOCKETADDRESS sa;
- int rv, sa_len = 0;
- int family;
-
- if (NET_InetAddressToSockaddr(env, iaObj, port, &sa,
- &sa_len, JNI_FALSE) != 0) {
- return -1;
- }
-
- family = sa.sa.sa_family;
- if (family != AF_INET) {
- JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
- "Protocol family not supported");
- return -1;
- }
-
- rv = connect(fd, &sa.sa, sa_len);
- if (rv == SOCKET_ERROR) {
- int err = WSAGetLastError();
- if (err == WSAEWOULDBLOCK) {
- return java_net_TwoStacksPlainSocketImpl_WOULDBLOCK;
- } else if (err == WSAEADDRNOTAVAIL) {
- JNU_ThrowByName(env, JNU_JAVANETPKG "ConnectException",
- "connect: Address is invalid on local machine, or port is not valid on remote machine");
- } else {
- NET_ThrowNew(env, err, "connect");
- }
- return -1; // return value not important.
- }
- return rv;
-}
-
-/*
- * Class: java_net_TwoStacksPlainSocketImpl
- * Method: waitForConnect
- * Signature: (II)V
- */
-JNIEXPORT void JNICALL Java_java_net_TwoStacksPlainSocketImpl_waitForConnect
- (JNIEnv *env, jclass clazz, jint fd, jint timeout) {
- int rv, retry;
- int optlen = sizeof(rv);
- fd_set wr, ex;
- struct timeval t;
-
- FD_ZERO(&wr);
- FD_ZERO(&ex);
- FD_SET(fd, &wr);
- FD_SET(fd, &ex);
- t.tv_sec = timeout / 1000;
- t.tv_usec = (timeout % 1000) * 1000;
-
- /*
- * Wait for timeout, connection established or
- * connection failed.
- */
- rv = select(fd+1, 0, &wr, &ex, &t);
-
- /*
- * Timeout before connection is established/failed so
- * we throw exception and shutdown input/output to prevent
- * socket from being used.
- * The socket should be closed immediately by the caller.
- */
- if (rv == 0) {
- JNU_ThrowByName(env, JNU_JAVANETPKG "SocketTimeoutException",
- "connect timed out");
- shutdown( fd, SD_BOTH );
- return;
- }
- /*
- * Socket is writable or error occurred. On some Windows editions
- * the socket will appear writable when the connect fails so we
- * check for error rather than writable.
- */
- if (!FD_ISSET(fd, &ex)) {
- return; /* connection established */
- }
-
- /*
- * Connection failed. The logic here is designed to work around
- * bug on Windows NT whereby using getsockopt to obtain the
- * last error (SO_ERROR) indicates there is no error. The workaround
- * on NT is to allow winsock to be scheduled and this is done by
- * yielding and retrying. As yielding is problematic in heavy
- * load conditions we attempt up to 3 times to get the error reason.
- */
- for (retry=0; retry<3; retry++) {
- NET_GetSockOpt(fd, SOL_SOCKET, SO_ERROR,
- (char*)&rv, &optlen);
- if (rv) {
- break;
- }
- Sleep(0);
- }
-
- if (rv == 0) {
- JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
- "Unable to establish connection");
- } else if (rv == WSAEADDRNOTAVAIL) {
- JNU_ThrowByName(env, JNU_JAVANETPKG "ConnectException",
- "connect: Address is invalid on local machine,"
- " or port is not valid on remote machine");
- } else {
- NET_ThrowNew(env, rv, "connect");
- }
-}
-
-/*
- * Class: java_net_TwoStacksPlainSocketImpl
- * Method: localPort0
- * Signature: (I)I
- */
-JNIEXPORT jint JNICALL Java_java_net_TwoStacksPlainSocketImpl_localPort0
- (JNIEnv *env, jclass clazz, jint fd) {
- SOCKETADDRESS sa;
- int len = sizeof(sa);
-
- if (getsockname(fd, &sa.sa, &len) == SOCKET_ERROR) {
- if (WSAGetLastError() == WSAENOTSOCK) {
- JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
- "Socket closed");
- } else {
- NET_ThrowNew(env, WSAGetLastError(), "getsockname failed");
- }
- return -1;
- }
- return (int) ntohs((u_short)GET_PORT(&sa));
-}
-
-/*
- * Class: java_net_TwoStacksPlainSocketImpl
- * Method: localAddress
- * Signature: (ILjava/net/InetAddressContainer;)V
- */
-JNIEXPORT void JNICALL Java_java_net_TwoStacksPlainSocketImpl_localAddress
- (JNIEnv *env, jclass clazz, jint fd, jobject iaContainerObj) {
- int port;
- SOCKETADDRESS sa;
- int len = sizeof(sa);
- jobject iaObj;
- jclass iaContainerClass;
- jfieldID iaFieldID;
-
- if (getsockname(fd, &sa.sa, &len) == SOCKET_ERROR) {
- NET_ThrowNew(env, WSAGetLastError(), "Error getting socket name");
- return;
- }
- iaObj = NET_SockaddrToInetAddress(env, &sa, &port);
- CHECK_NULL(iaObj);
-
- iaContainerClass = (*env)->GetObjectClass(env, iaContainerObj);
- iaFieldID = (*env)->GetFieldID(env, iaContainerClass, "addr", "Ljava/net/InetAddress;");
- CHECK_NULL(iaFieldID);
- (*env)->SetObjectField(env, iaContainerObj, iaFieldID, iaObj);
-}
-
-
-/*
- * Class: java_net_TwoStacksPlainSocketImpl
- * Method: listen0
- * Signature: (II)V
- */
-JNIEXPORT void JNICALL Java_java_net_TwoStacksPlainSocketImpl_listen0
- (JNIEnv *env, jclass clazz, jint fd, jint backlog) {
- if (listen(fd, backlog) == SOCKET_ERROR) {
- NET_ThrowNew(env, WSAGetLastError(), "listen failed");
- }
-}
-
-/*
- * Class: java_net_TwoStacksPlainSocketImpl
- * Method: accept0
- * Signature: (I[Ljava/net/InetSocketAddress;)I
- */
-JNIEXPORT jint JNICALL Java_java_net_TwoStacksPlainSocketImpl_accept0
- (JNIEnv *env, jclass clazz, jint fd, jobjectArray isaa) {
- int newfd, port=0;
- jobject isa;
- jobject ia;
- SOCKETADDRESS sa;
- int len = sizeof(sa);
-
- memset((char *)&sa, 0, len);
- newfd = accept(fd, &sa.sa, &len);
-
- if (newfd < 0) {
- if (newfd == -2) {
- JNU_ThrowByName(env, JNU_JAVAIOPKG "InterruptedIOException",
- "operation interrupted");
- } else {
- JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
- "socket closed");
- }
- return -1;
- }
-
- SetHandleInformation((HANDLE)(UINT_PTR)newfd, HANDLE_FLAG_INHERIT, 0);
-
- if (sa.sa.sa_family != AF_INET) {
- JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
- "Protocol family not supported");
- NET_SocketClose(newfd);
- return -1;
- }
-
- ia = NET_SockaddrToInetAddress(env, &sa, &port);
- isa = (*env)->NewObject(env, isa_class, isa_ctorID, ia, port);
- (*env)->SetObjectArrayElement(env, isaa, 0, isa);
-
- return newfd;
-}
-
-/*
- * Class: java_net_TwoStacksPlainSocketImpl
- * Method: waitForNewConnection
- * Signature: (II)V
- */
-JNIEXPORT void JNICALL Java_java_net_TwoStacksPlainSocketImpl_waitForNewConnection
- (JNIEnv *env, jclass clazz, jint fd, jint timeout) {
- int rv;
-
- rv = NET_Timeout(fd, timeout);
- if (rv == 0) {
- JNU_ThrowByName(env, JNU_JAVANETPKG "SocketTimeoutException",
- "Accept timed out");
- } else if (rv == -1) {
- JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "socket closed");
- } else if (rv == -2) {
- JNU_ThrowByName(env, JNU_JAVAIOPKG "InterruptedIOException",
- "operation interrupted");
- }
-}
-
-/*
- * Class: java_net_TwoStacksPlainSocketImpl
- * Method: available0
- * Signature: (I)I
- */
-JNIEXPORT jint JNICALL Java_java_net_TwoStacksPlainSocketImpl_available0
- (JNIEnv *env, jclass clazz, jint fd) {
- jint available = -1;
-
- if ((ioctlsocket(fd, FIONREAD, &available)) == SOCKET_ERROR) {
- NET_ThrowNew(env, WSAGetLastError(), "socket available");
- }
-
- return available;
-}
-
-/*
- * Class: java_net_TwoStacksPlainSocketImpl
- * Method: close0
- * Signature: (I)V
- */
-JNIEXPORT void JNICALL Java_java_net_TwoStacksPlainSocketImpl_close0
- (JNIEnv *env, jclass clazz, jint fd) {
- NET_SocketClose(fd);
-}
-
-/*
- * Class: java_net_TwoStacksPlainSocketImpl
- * Method: shutdown0
- * Signature: (II)V
- */
-JNIEXPORT void JNICALL Java_java_net_TwoStacksPlainSocketImpl_shutdown0
- (JNIEnv *env, jclass clazz, jint fd, jint howto) {
- shutdown(fd, howto);
-}
-
-
-/*
- * Class: java_net_TwoStacksPlainSocketImpl
- * Method: setIntOption
- * Signature: (III)V
- */
-JNIEXPORT void JNICALL
-Java_java_net_TwoStacksPlainSocketImpl_setIntOption
- (JNIEnv *env, jclass clazz, jint fd, jint cmd, jint value)
-{
- int level = 0, opt = 0;
- struct linger linger = {0, 0};
- char *parg;
- int arglen;
-
- if (NET_MapSocketOption(cmd, &level, &opt) < 0) {
- JNU_ThrowByName(env, "java/net/SocketException", "Invalid option");
- return;
- }
-
- if (opt == java_net_SocketOptions_SO_LINGER) {
- parg = (char *)&linger;
- arglen = sizeof(linger);
- if (value >= 0) {
- linger.l_onoff = 1;
- linger.l_linger = (unsigned short)value;
- } else {
- linger.l_onoff = 0;
- linger.l_linger = 0;
- }
- } else {
- parg = (char *)&value;
- arglen = sizeof(value);
- }
-
- if (NET_SetSockOpt(fd, level, opt, parg, arglen) < 0) {
- NET_ThrowNew(env, WSAGetLastError(), "setsockopt");
- }
-}
-
-/*
- * Class: java_net_TwoStacksPlainSocketImpl
- * Method: setSoTimeout0
- * Signature: (II)V
- */
-JNIEXPORT void JNICALL
-Java_java_net_TwoStacksPlainSocketImpl_setSoTimeout0
- (JNIEnv *env, jclass clazz, jint fd, jint timeout)
-{
- /*
- * SO_TIMEOUT is the socket option used to specify the timeout
- * for ServerSocket.accept and Socket.getInputStream().read.
- * It does not typically map to a native level socket option.
- * For Windows we special-case this and use the SOL_SOCKET/SO_RCVTIMEO
- * socket option to specify a receive timeout on the socket. This
- * receive timeout is applicable to Socket only and the socket
- * option should not be set on ServerSocket.
- */
-
- /*
- * SO_RCVTIMEO is only supported on Microsoft's implementation
- * of Windows Sockets so if WSAENOPROTOOPT returned then
- * reset flag and timeout will be implemented using
- * select() -- see SocketInputStream.socketRead.
- */
- if (isRcvTimeoutSupported) {
- /*
- * Disable SO_RCVTIMEO if timeout is <= 5 second.
- */
- if (timeout <= 5000) {
- timeout = 0;
- }
-
- if (setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout,
- sizeof(timeout)) < 0) {
- int err = WSAGetLastError();
- if (err == WSAENOPROTOOPT) {
- isRcvTimeoutSupported = JNI_FALSE;
- } else {
- NET_ThrowNew(env, err, "setsockopt SO_RCVTIMEO");
- }
- }
- }
-}
-
-/*
- * Class: java_net_TwoStacksPlainSocketImpl
- * Method: getIntOption
- * Signature: (II)I
- */
-JNIEXPORT jint JNICALL Java_java_net_TwoStacksPlainSocketImpl_getIntOption
- (JNIEnv *env, jclass clazz, jint fd, jint cmd)
-{
- int level = 0, opt = 0;
- int result=0;
- struct linger linger = {0, 0};
- char *arg;
- int arglen;
-
- if (NET_MapSocketOption(cmd, &level, &opt) < 0) {
- JNU_ThrowByName(env, "java/net/SocketException", "Invalid option");
- return -1;
- }
-
- if (opt == java_net_SocketOptions_SO_LINGER) {
- arg = (char *)&linger;
- arglen = sizeof(linger);
- } else {
- arg = (char *)&result;
- arglen = sizeof(result);
- }
-
- if (NET_GetSockOpt(fd, level, opt, arg, &arglen) < 0) {
- NET_ThrowNew(env, WSAGetLastError(), "getsockopt");
- return -1;
- }
-
- if (opt == java_net_SocketOptions_SO_LINGER)
- return linger.l_onoff ? linger.l_linger : -1;
- else
- return result;
-}
-
-
-/*
- * Class: java_net_TwoStacksPlainSocketImpl
- * Method: sendOOB
- * Signature: (II)V
- */
-JNIEXPORT void JNICALL Java_java_net_TwoStacksPlainSocketImpl_sendOOB
- (JNIEnv *env, jclass clazz, jint fd, jint data) {
- jint n;
- unsigned char d = (unsigned char) data & 0xff;
-
- n = send(fd, (char *)&data, 1, MSG_OOB);
- if (n == SOCKET_ERROR) {
- NET_ThrowNew(env, WSAGetLastError(), "send");
- }
-}
-
-/*
- * Class: java_net_TwoStacksPlainSocketImpl
- * Method: configureBlocking
- * Signature: (IZ)V
- */
-JNIEXPORT void JNICALL Java_java_net_TwoStacksPlainSocketImpl_configureBlocking
- (JNIEnv *env, jclass clazz, jint fd, jboolean blocking) {
- u_long arg;
- int result;
-
- if (blocking == JNI_TRUE) {
- arg = SET_BLOCKING; // 0
- } else {
- arg = SET_NONBLOCKING; // 1
- }
-
- result = ioctlsocket(fd, FIONBIO, &arg);
- if (result == SOCKET_ERROR) {
- NET_ThrowNew(env, WSAGetLastError(), "configureBlocking");
- }
-}
--- a/src/java.desktop/share/native/common/awt/medialib/mlib_ImageCreate.c Wed Apr 18 14:07:41 2018 -0700
+++ b/src/java.desktop/share/native/common/awt/medialib/mlib_ImageCreate.c Fri Apr 20 09:05:05 2018 -0700
@@ -227,7 +227,7 @@
}
/***************************************************************/
-mlib_image *mlib_ImageCreateStruct(mlib_type type,
+JNIEXPORT mlib_image* JNICALL mlib_ImageCreateStruct(mlib_type type,
mlib_s32 channels,
mlib_s32 width,
mlib_s32 height,
@@ -253,7 +253,7 @@
}
/***************************************************************/
-mlib_image *mlib_ImageCreate(mlib_type type,
+JNIEXPORT mlib_image* JNICALL mlib_ImageCreate(mlib_type type,
mlib_s32 channels,
mlib_s32 width,
mlib_s32 height)
@@ -352,7 +352,7 @@
}
/***************************************************************/
-void mlib_ImageDelete(mlib_image *img)
+JNIEXPORT void JNICALL mlib_ImageDelete(mlib_image *img)
{
if (img == NULL) return;
if ((img -> flags & MLIB_IMAGE_USERALLOCATED) == 0) {
--- a/src/java.desktop/share/native/libmlib_image/mlib_ImageAffine.c Wed Apr 18 14:07:41 2018 -0700
+++ b/src/java.desktop/share/native/libmlib_image/mlib_ImageAffine.c Fri Apr 20 09:05:05 2018 -0700
@@ -299,7 +299,7 @@
}
/***************************************************************/
-mlib_status mlib_ImageAffine(mlib_image *dst,
+JNIEXPORT mlib_status JNICALL mlib_ImageAffine(mlib_image *dst,
const mlib_image *src,
const mlib_d64 *mtx,
mlib_filter filter,
--- a/src/java.desktop/share/native/libmlib_image/mlib_ImageConvKernelConvert.c Wed Apr 18 14:07:41 2018 -0700
+++ b/src/java.desktop/share/native/libmlib_image/mlib_ImageConvKernelConvert.c Fri Apr 20 09:05:05 2018 -0700
@@ -78,7 +78,7 @@
#endif /* __sparc */
/***************************************************************/
-mlib_status mlib_ImageConvKernelConvert(mlib_s32 *ikernel,
+JNIEXPORT mlib_status JNICALL mlib_ImageConvKernelConvert(mlib_s32 *ikernel,
mlib_s32 *iscale,
const mlib_d64 *fkernel,
mlib_s32 m,
--- a/src/java.desktop/share/native/libmlib_image/mlib_ImageConvMxN.c Wed Apr 18 14:07:41 2018 -0700
+++ b/src/java.desktop/share/native/libmlib_image/mlib_ImageConvMxN.c Fri Apr 20 09:05:05 2018 -0700
@@ -90,7 +90,7 @@
#include "mlib_ImageConvEdge.h"
/***************************************************************/
-mlib_status mlib_ImageConvMxN(mlib_image *dst,
+JNIEXPORT mlib_status JNICALL mlib_ImageConvMxN(mlib_image *dst,
const mlib_image *src,
const mlib_s32 *kernel,
mlib_s32 m,
--- a/src/java.desktop/share/native/libmlib_image/mlib_c_ImageLookUp.c Wed Apr 18 14:07:41 2018 -0700
+++ b/src/java.desktop/share/native/libmlib_image/mlib_c_ImageLookUp.c Fri Apr 20 09:05:05 2018 -0700
@@ -78,7 +78,7 @@
#include "mlib_c_ImageLookUp.h"
/***************************************************************/
-mlib_status mlib_ImageLookUp(mlib_image *dst,
+JNIEXPORT mlib_status JNICALL mlib_ImageLookUp(mlib_image *dst,
const mlib_image *src,
const void **table)
{
--- a/src/java.desktop/share/native/libsplashscreen/splashscreen_impl.h Wed Apr 18 14:07:41 2018 -0700
+++ b/src/java.desktop/share/native/libsplashscreen/splashscreen_impl.h Fri Apr 20 09:05:05 2018 -0700
@@ -132,9 +132,6 @@
unsigned SplashTime();
char* SplashConvertStringAlloc(const char* in, int *size);
-jboolean SplashGetScaledImageName(const char* jarName,
- const char* fileName, float *scaleFactor,
- char *scaleImageName, const size_t scaledImageNameLength);
void SplashLock(Splash * splash);
void SplashUnlock(Splash * splash);
@@ -157,8 +154,7 @@
void SplashUpdateScreenData(Splash * splash);
void SplashCleanup(Splash * splash);
-void SplashSetScaleFactor(float scaleFactor);
-int SplashGetScaledImgNameMaxPstfixLen(const char *fileName);
+
void cleanUp(char *fName, char *xName, char *pctName, float *scaleFactor);
jboolean GetScaledImageName(const char *fileName, char *scaledImgName,
float *scaleFactor, const size_t scaledImageLength);
--- a/src/java.desktop/windows/native/libsplashscreen/splashscreen_sys.c Wed Apr 18 14:07:41 2018 -0700
+++ b/src/java.desktop/windows/native/libsplashscreen/splashscreen_sys.c Fri Apr 20 09:05:05 2018 -0700
@@ -574,7 +574,7 @@
PostMessage(splash->hWnd, WM_SPLASHRECONFIGURE, 0, 0);
}
-jboolean
+JNIEXPORT jboolean JNICALL
SplashGetScaledImageName(const char* jarName, const char* fileName,
float *scaleFactor, char *scaleImageName,
const size_t scaledImageLength)
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/BinaryContainer.java Wed Apr 18 14:07:41 2018 -0700
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/BinaryContainer.java Fri Apr 20 09:05:05 2018 -0700
@@ -230,6 +230,8 @@
{"JVMCIRuntime::monitorenter", "_aot_jvmci_runtime_monitorenter"},
{"JVMCIRuntime::monitorexit", "_aot_jvmci_runtime_monitorexit"},
+ {"JVMCIRuntime::object_notify", "_aot_object_notify"},
+ {"JVMCIRuntime::object_notifyAll", "_aot_object_notifyAll"},
{"JVMCIRuntime::log_object", "_aot_jvmci_runtime_log_object"},
{"JVMCIRuntime::log_printf", "_aot_jvmci_runtime_log_printf"},
{"JVMCIRuntime::vm_message", "_aot_jvmci_runtime_vm_message"},
--- a/src/jdk.charsets/share/classes/sun/nio/cs/ext/IBM942C.java Wed Apr 18 14:07:41 2018 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,93 +0,0 @@
-/*
- * Copyright (c) 2003, 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.nio.cs.ext;
-
-import java.nio.charset.Charset;
-import java.nio.charset.CharsetDecoder;
-import java.nio.charset.CharsetEncoder;
-import java.util.Arrays;
-import sun.nio.cs.DoubleByte;
-import sun.nio.cs.HistoricallyNamedCharset;
-import static sun.nio.cs.CharsetMapping.*;
-
-public class IBM942C extends Charset implements HistoricallyNamedCharset
-{
- public IBM942C() {
- super("x-IBM942C", ExtendedCharsets.aliasesFor("x-IBM942C"));
- }
-
- public String historicalName() {
- return "Cp942C";
- }
-
- public boolean contains(Charset cs) {
- return ((cs.name().equals("US-ASCII"))
- || (cs instanceof IBM942C));
- }
-
- public CharsetDecoder newDecoder() {
- return new DoubleByte.Decoder(this,
- IBM942.b2c,
- b2cSB,
- 0x40,
- 0xfc);
- }
-
- public CharsetEncoder newEncoder() {
- return new DoubleByte.Encoder(this, c2b, c2bIndex);
- }
-
- final static char[] b2cSB;
- final static char[] c2b;
- final static char[] c2bIndex;
-
- static {
- IBM942.initb2c();
-
- // the mappings need udpate are
- // u+001a <-> 0x1a
- // u+001c <-> 0x1c
- // u+005c <-> 0x5c
- // u+007e <-> 0x7e
- // u+007f <-> 0x7f
-
- b2cSB = Arrays.copyOf(IBM942.b2cSB, IBM942.b2cSB.length);
- b2cSB[0x1a] = 0x1a;
- b2cSB[0x1c] = 0x1c;
- b2cSB[0x5c] = 0x5c;
- b2cSB[0x7e] = 0x7e;
- b2cSB[0x7f] = 0x7f;
-
- IBM942.initc2b();
- c2b = Arrays.copyOf(IBM942.c2b, IBM942.c2b.length);
- c2bIndex = Arrays.copyOf(IBM942.c2bIndex, IBM942.c2bIndex.length);
- c2b[c2bIndex[0] + 0x1a] = 0x1a;
- c2b[c2bIndex[0] + 0x1c] = 0x1c;
- c2b[c2bIndex[0] + 0x5c] = 0x5c;
- c2b[c2bIndex[0] + 0x7e] = 0x7e;
- c2b[c2bIndex[0] + 0x7f] = 0x7f;
- }
-}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.charsets/share/classes/sun/nio/cs/ext/IBM942C.java.template Fri Apr 20 09:05:05 2018 -0700
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
+ * 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 $PACKAGE$;
+
+import java.nio.charset.Charset;
+import java.nio.charset.CharsetDecoder;
+import java.nio.charset.CharsetEncoder;
+import java.util.Arrays;
+import sun.nio.cs.DoubleByte;
+import sun.nio.cs.HistoricallyNamedCharset;
+import static sun.nio.cs.CharsetMapping.*;
+
+public class IBM942C extends Charset implements HistoricallyNamedCharset
+{
+ public IBM942C() {
+ super("x-IBM942C", $ALIASES$);
+ }
+
+ public String historicalName() {
+ return "Cp942C";
+ }
+
+ public boolean contains(Charset cs) {
+ return ((cs.name().equals("US-ASCII"))
+ || (cs instanceof IBM942C));
+ }
+
+ public CharsetDecoder newDecoder() {
+ return new DoubleByte.Decoder(this,
+ IBM942.b2c,
+ b2cSB,
+ 0x40,
+ 0xfc);
+ }
+
+ public CharsetEncoder newEncoder() {
+ return new DoubleByte.Encoder(this, c2b, c2bIndex);
+ }
+
+ final static char[] b2cSB;
+ final static char[] c2b;
+ final static char[] c2bIndex;
+
+ static {
+ IBM942.initb2c();
+
+ // the mappings need udpate are
+ // u+001a <-> 0x1a
+ // u+001c <-> 0x1c
+ // u+005c <-> 0x5c
+ // u+007e <-> 0x7e
+ // u+007f <-> 0x7f
+
+ b2cSB = Arrays.copyOf(IBM942.b2cSB, IBM942.b2cSB.length);
+ b2cSB[0x1a] = 0x1a;
+ b2cSB[0x1c] = 0x1c;
+ b2cSB[0x5c] = 0x5c;
+ b2cSB[0x7e] = 0x7e;
+ b2cSB[0x7f] = 0x7f;
+
+ IBM942.initc2b();
+ c2b = Arrays.copyOf(IBM942.c2b, IBM942.c2b.length);
+ c2bIndex = Arrays.copyOf(IBM942.c2bIndex, IBM942.c2bIndex.length);
+ c2b[c2bIndex[0] + 0x1a] = 0x1a;
+ c2b[c2bIndex[0] + 0x1c] = 0x1c;
+ c2b[c2bIndex[0] + 0x5c] = 0x5c;
+ c2b[c2bIndex[0] + 0x7e] = 0x7e;
+ c2b[c2bIndex[0] + 0x7f] = 0x7f;
+ }
+}
--- a/src/jdk.charsets/share/classes/sun/nio/cs/ext/IBM943C.java Wed Apr 18 14:07:41 2018 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,85 +0,0 @@
-/*
- * Copyright (c) 2003, 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.nio.cs.ext;
-
-import java.nio.charset.Charset;
-import java.nio.charset.CharsetDecoder;
-import java.nio.charset.CharsetEncoder;
-import java.util.Arrays;
-import sun.nio.cs.DoubleByte;
-import sun.nio.cs.HistoricallyNamedCharset;
-
-public class IBM943C extends Charset implements HistoricallyNamedCharset
-{
-
- public IBM943C() {
- super("x-IBM943C", ExtendedCharsets.aliasesFor("x-IBM943C"));
- }
-
- public String historicalName() {
- return "Cp943C";
- }
-
- public boolean contains(Charset cs) {
- return ((cs.name().equals("US-ASCII"))
- || (cs instanceof IBM943C));
- }
-
- public CharsetDecoder newDecoder() {
- return new DoubleByte.Decoder(this,
- IBM943.b2c,
- b2cSB,
- 0x40,
- 0xfc);
- }
-
- public CharsetEncoder newEncoder() {
- return new DoubleByte.Encoder(this, c2b, c2bIndex);
- }
-
- final static char[] b2cSB;
- final static char[] c2b;
- final static char[] c2bIndex;
-
- static {
- IBM943.initb2c();
- b2cSB = new char[0x100];
- for (int i = 0; i < 0x80; i++) {
- b2cSB[i] = (char)i;
- }
- for (int i = 0x80; i < 0x100; i++) {
- b2cSB[i] = IBM943.b2cSB[i];
- }
-
- IBM943.initc2b();
- c2b = Arrays.copyOf(IBM943.c2b, IBM943.c2b.length);
- c2bIndex = Arrays.copyOf(IBM943.c2bIndex, IBM943.c2bIndex.length);
- for (char c = '\0'; c < '\u0080'; ++c) {
- int index = c2bIndex[c >> 8];
- c2b[index + (c & 0xff)] = c;
- }
- }
-}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.charsets/share/classes/sun/nio/cs/ext/IBM943C.java.template Fri Apr 20 09:05:05 2018 -0700
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
+ * 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 $PACKAGE$;
+
+import java.nio.charset.Charset;
+import java.nio.charset.CharsetDecoder;
+import java.nio.charset.CharsetEncoder;
+import java.util.Arrays;
+import sun.nio.cs.DoubleByte;
+import sun.nio.cs.HistoricallyNamedCharset;
+
+public class IBM943C extends Charset implements HistoricallyNamedCharset
+{
+
+ public IBM943C() {
+ super("x-IBM943C", $ALIASES$);
+ }
+
+ public String historicalName() {
+ return "Cp943C";
+ }
+
+ public boolean contains(Charset cs) {
+ return ((cs.name().equals("US-ASCII"))
+ || (cs instanceof IBM943C));
+ }
+
+ public CharsetDecoder newDecoder() {
+ return new DoubleByte.Decoder(this,
+ IBM943.b2c,
+ b2cSB,
+ 0x40,
+ 0xfc);
+ }
+
+ public CharsetEncoder newEncoder() {
+ return new DoubleByte.Encoder(this, c2b, c2bIndex);
+ }
+
+ final static char[] b2cSB;
+ final static char[] c2b;
+ final static char[] c2bIndex;
+
+ static {
+ IBM943.initb2c();
+ b2cSB = new char[0x100];
+ for (int i = 0; i < 0x80; i++) {
+ b2cSB[i] = (char)i;
+ }
+ for (int i = 0x80; i < 0x100; i++) {
+ b2cSB[i] = IBM943.b2cSB[i];
+ }
+
+ IBM943.initc2b();
+ c2b = Arrays.copyOf(IBM943.c2b, IBM943.c2b.length);
+ c2bIndex = Arrays.copyOf(IBM943.c2bIndex, IBM943.c2bIndex.length);
+ for (char c = '\0'; c < '\u0080'; ++c) {
+ int index = c2bIndex[c >> 8];
+ c2b[index + (c & 0xff)] = c;
+ }
+ }
+}
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/api/JavacTaskImpl.java Wed Apr 18 14:07:41 2018 -0700
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/api/JavacTaskImpl.java Fri Apr 20 09:05:05 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -172,7 +172,7 @@
if (compiler == null || compiler.errorCount() == 0
|| Options.instance(context).isSet("dev")) {
Log log = Log.instance(context);
- log.printLines(PrefixKind.JAVAC, "msg.bug", JavaCompiler.version());
+ log.printLines("msg.bug", JavaCompiler.version());
ex.printStackTrace(log.getWriter(WriterKind.NOTICE));
}
return abnormalErrorResult;
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Arguments.java Wed Apr 18 14:07:41 2018 -0700
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Arguments.java Fri Apr 20 09:05:05 2018 -0700
@@ -54,7 +54,6 @@
import com.sun.tools.doclint.DocLint;
import com.sun.tools.javac.code.Lint.LintCategory;
import com.sun.tools.javac.code.Source;
-import com.sun.tools.javac.code.Source.Feature;
import com.sun.tools.javac.file.BaseFileManager;
import com.sun.tools.javac.file.JavacFileManager;
import com.sun.tools.javac.jvm.Profile;
@@ -66,6 +65,7 @@
import com.sun.tools.javac.resources.CompilerProperties.Warnings;
import com.sun.tools.javac.util.Context;
import com.sun.tools.javac.util.JCDiagnostic;
+import com.sun.tools.javac.util.JCDiagnostic.DiagnosticInfo;
import com.sun.tools.javac.util.List;
import com.sun.tools.javac.util.ListBuffer;
import com.sun.tools.javac.util.Log;
@@ -295,7 +295,7 @@
String platformString = options.get(Option.RELEASE);
checkOptionAllowed(platformString == null,
- option -> error("err.release.bootclasspath.conflict", option.getPrimaryName()),
+ option -> reportDiag(Errors.ReleaseBootclasspathConflict(option)),
Option.BOOT_CLASS_PATH, Option.XBOOTCLASSPATH, Option.XBOOTCLASSPATH_APPEND,
Option.XBOOTCLASSPATH_PREPEND,
Option.ENDORSEDDIRS, Option.DJAVA_ENDORSED_DIRS,
@@ -308,7 +308,7 @@
PlatformUtils.lookupPlatformDescription(platformString);
if (platformDescription == null) {
- error("err.unsupported.release.version", platformString);
+ reportDiag(Errors.UnsupportedReleaseVersion(platformString));
return false;
}
@@ -363,7 +363,7 @@
while (argIter.hasNext()) {
String arg = argIter.next();
if (arg.isEmpty()) {
- error("err.invalid.flag", arg);
+ reportDiag(Errors.InvalidFlag(arg));
return false;
}
@@ -392,7 +392,7 @@
}
// none of the above
- error("err.invalid.flag", arg);
+ reportDiag(Errors.InvalidFlag(arg));
return false;
}
@@ -457,9 +457,9 @@
if (!emptyAllowed) {
if (!errors) {
if (JavaCompiler.explicitAnnotationProcessingRequested(options)) {
- error("err.no.source.files.classes");
+ reportDiag(Errors.NoSourceFilesClasses);
} else {
- error("err.no.source.files");
+ reportDiag(Errors.NoSourceFiles);
}
}
return false;
@@ -520,13 +520,9 @@
if (target.compareTo(source.requiredTarget()) < 0) {
if (targetString != null) {
if (sourceString == null) {
- error("warn.target.default.source.conflict",
- targetString,
- source.requiredTarget().name);
+ reportDiag(Warnings.TargetDefaultSourceConflict(targetString, source.requiredTarget()));
} else {
- error("warn.source.target.conflict",
- sourceString,
- source.requiredTarget().name);
+ reportDiag(Warnings.SourceTargetConflict(sourceString, source.requiredTarget()));
}
return false;
} else {
@@ -539,13 +535,11 @@
if (options.isSet(Option.PREVIEW)) {
if (sourceString == null) {
//enable-preview must be used with explicit -source or --release
- error("err.preview.without.source.or.release");
+ report(Errors.PreviewWithoutSourceOrRelease);
return false;
} else if (source != Source.DEFAULT) {
//enable-preview must be used with latest source version
- error("err.preview.not.latest",
- sourceString,
- Source.DEFAULT.name);
+ report(Errors.PreviewNotLatest(sourceString, Source.DEFAULT));
return false;
}
}
@@ -554,18 +548,18 @@
if (profileString != null) {
Profile profile = Profile.lookup(profileString);
if (!profile.isValid(target)) {
- error("warn.profile.target.conflict", profileString, target.name);
+ reportDiag(Warnings.ProfileTargetConflict(profile, target));
}
// This check is only effective in command line mode,
// where the file manager options are added to options
if (options.get(Option.BOOT_CLASS_PATH) != null) {
- error("err.profile.bootclasspath.conflict");
+ reportDiag(Errors.ProfileBootclasspathConflict);
}
}
if (options.isSet(Option.SOURCE_PATH) && options.isSet(Option.MODULE_SOURCE_PATH)) {
- error("err.sourcepath.modulesourcepath.conflict");
+ reportDiag(Errors.SourcepathModulesourcepathConflict);
}
boolean lintOptions = options.isUnset(Option.XLINT_CUSTOM, "-" + LintCategory.OPTIONS.option);
@@ -586,15 +580,15 @@
}
if (target.compareTo(Target.MIN) < 0) {
- log.error(Errors.OptionRemovedTarget(target.name, Target.MIN.name));
+ log.error(Errors.OptionRemovedTarget(target, Target.MIN));
} else if (target == Target.MIN && lintOptions) {
- log.warning(LintCategory.OPTIONS, Warnings.OptionObsoleteTarget(target.name));
+ log.warning(LintCategory.OPTIONS, Warnings.OptionObsoleteTarget(target));
obsoleteOptionFound = true;
}
final Target t = target;
checkOptionAllowed(t.compareTo(Target.JDK1_8) <= 0,
- option -> error("err.option.not.allowed.with.target", option.getPrimaryName(), t.name),
+ option -> reportDiag(Errors.OptionNotAllowedWithTarget(option, t)),
Option.BOOT_CLASS_PATH,
Option.XBOOTCLASSPATH_PREPEND, Option.XBOOTCLASSPATH, Option.XBOOTCLASSPATH_APPEND,
Option.ENDORSEDDIRS, Option.DJAVA_ENDORSED_DIRS,
@@ -602,7 +596,7 @@
Option.PROFILE);
checkOptionAllowed(t.compareTo(Target.JDK1_9) >= 0,
- option -> error("err.option.not.allowed.with.target", option.getPrimaryName(), t.name),
+ option -> reportDiag(Errors.OptionNotAllowedWithTarget(option, t)),
Option.MODULE_SOURCE_PATH, Option.UPGRADE_MODULE_PATH,
Option.SYSTEM, Option.MODULE_PATH, Option.ADD_MODULES,
Option.ADD_EXPORTS, Option.ADD_OPENS, Option.ADD_READS,
@@ -610,7 +604,7 @@
Option.PATCH_MODULE);
if (lintOptions && options.isSet(Option.PARAMETERS) && !target.hasMethodParameters()) {
- log.warning(Warnings.OptionParametersUnsupported(target.name, Target.JDK1_8.name));
+ log.warning(Warnings.OptionParametersUnsupported(target, Target.JDK1_8));
}
if (fm.hasLocation(StandardLocation.MODULE_SOURCE_PATH)) {
@@ -871,7 +865,7 @@
}
Path file = Paths.get(value);
if (Files.exists(file) && !Files.isDirectory(file)) {
- error("err.file.not.directory", value);
+ reportDiag(Errors.FileNotDirectory(value));
return false;
}
return true;
@@ -889,35 +883,19 @@
}
}
- void error(JCDiagnostic.Error error) {
+ void reportDiag(DiagnosticInfo diag) {
errors = true;
switch (errorMode) {
case ILLEGAL_ARGUMENT: {
- String msg = log.localize(error);
+ String msg = log.localize(diag);
throw new PropagatedException(new IllegalArgumentException(msg));
}
case ILLEGAL_STATE: {
- String msg = log.localize(error);
+ String msg = log.localize(diag);
throw new PropagatedException(new IllegalStateException(msg));
}
case LOG:
- report(error);
- }
- }
-
- void error(String key, Object... args) {
- errors = true;
- switch (errorMode) {
- case ILLEGAL_ARGUMENT: {
- String msg = log.localize(PrefixKind.JAVAC, key, args);
- throw new PropagatedException(new IllegalArgumentException(msg));
- }
- case ILLEGAL_STATE: {
- String msg = log.localize(PrefixKind.JAVAC, key, args);
- throw new PropagatedException(new IllegalStateException(msg));
- }
- case LOG:
- report(key, args);
+ report(diag);
}
}
@@ -932,22 +910,17 @@
throw new PropagatedException(new IllegalStateException(msg, f.getCause()));
}
case LOG:
- log.printRawLines(ownName + ": " + msg);
+ log.printRawLines(msg);
}
}
- void warning(String key, Object... args) {
- report(key, args);
- }
-
- private void report(String key, Object... args) {
+ private void report(DiagnosticInfo diag) {
// Would be good to have support for -XDrawDiagnostics here
- log.printRawLines(ownName + ": " + log.localize(PrefixKind.JAVAC, key, args));
- }
-
- private void report(JCDiagnostic.Error error) {
- // Would be good to have support for -XDrawDiagnostics here
- log.printRawLines(ownName + ": " + log.localize(error));
+ if (diag instanceof JCDiagnostic.Error) {
+ log.error((JCDiagnostic.Error)diag);
+ } else if (diag instanceof JCDiagnostic.Warning){
+ log.warning((JCDiagnostic.Warning)diag);
+ }
}
private JavaFileManager getFileManager() {
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Main.java Wed Apr 18 14:07:41 2018 -0700
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Main.java Fri Apr 20 09:05:05 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -49,7 +49,9 @@
import com.sun.tools.javac.main.CommandLine.UnmatchedQuote;
import com.sun.tools.javac.platform.PlatformDescription;
import com.sun.tools.javac.processing.AnnotationProcessingError;
+import com.sun.tools.javac.resources.CompilerProperties.Errors;
import com.sun.tools.javac.util.*;
+import com.sun.tools.javac.util.JCDiagnostic.DiagnosticInfo;
import com.sun.tools.javac.util.Log.PrefixKind;
import com.sun.tools.javac.util.Log.WriterKind;
@@ -138,19 +140,22 @@
/** Report a usage error.
*/
- void error(String key, Object... args) {
+ void reportDiag(DiagnosticInfo diag) {
if (apiMode) {
- String msg = log.localize(PrefixKind.JAVAC, key, args);
+ String msg = log.localize(diag);
throw new PropagatedException(new IllegalStateException(msg));
}
- warning(key, args);
+ reportHelper(diag);
log.printLines(PrefixKind.JAVAC, "msg.usage", ownName);
}
- /** Report a warning.
+ /** Report helper.
*/
- void warning(String key, Object... args) {
- log.printRawLines(ownName + ": " + log.localize(PrefixKind.JAVAC, key, args));
+ void reportHelper(DiagnosticInfo diag) {
+ String msg = log.localize(diag);
+ String errorPrefix = log.localize(Errors.Error);
+ msg = msg.startsWith(errorPrefix) ? msg : errorPrefix + msg;
+ log.printRawLines(msg);
}
@@ -209,10 +214,10 @@
try {
argv = CommandLine.parse(ENV_OPT_NAME, argv);
} catch (UnmatchedQuote ex) {
- error("err.unmatched.quote", ex.variableName);
+ reportDiag(Errors.UnmatchedQuote(ex.variableName));
return Result.CMDERR;
} catch (FileNotFoundException | NoSuchFileException e) {
- warning("err.file.not.found", e.getMessage());
+ reportHelper(Errors.FileNotFound(e.getMessage()));
return Result.SYSERR;
} catch (IOException ex) {
log.printLines(PrefixKind.JAVAC, "msg.io");
@@ -366,11 +371,10 @@
CodeSource otherClassCodeSource = otherClass.getProtectionDomain().getCodeSource();
CodeSource javacCodeSource = this.getClass().getProtectionDomain().getCodeSource();
if (otherClassCodeSource != null && javacCodeSource != null) {
- log.printLines(PrefixKind.JAVAC, "err.two.class.loaders.2",
- otherClassCodeSource.getLocation(),
- javacCodeSource.getLocation());
+ log.printLines(Errors.TwoClassLoaders2(otherClassCodeSource.getLocation(),
+ javacCodeSource.getLocation()));
} else {
- log.printLines(PrefixKind.JAVAC, "err.two.class.loaders.1");
+ log.printLines(Errors.TwoClassLoaders1);
}
return true;
}
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Option.java Wed Apr 18 14:07:41 2018 -0700
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Option.java Fri Apr 20 09:05:05 2018 -0700
@@ -59,6 +59,7 @@
import com.sun.tools.javac.jvm.Target;
import com.sun.tools.javac.platform.PlatformProvider;
import com.sun.tools.javac.processing.JavacProcessingEnvironment;
+import com.sun.tools.javac.resources.CompilerProperties.Errors;
import com.sun.tools.javac.util.Assert;
import com.sun.tools.javac.util.Log;
import com.sun.tools.javac.util.Log.PrefixKind;
@@ -197,7 +198,7 @@
@Override
public void process(OptionHelper helper, String option, String arg) throws InvalidValueException {
if (arg.isEmpty()) {
- throw helper.newInvalidValueException("err.no.value.for.option", option);
+ throw helper.newInvalidValueException(Errors.NoValueForOption(option));
} else if (getPattern().matcher(arg).matches()) {
String prev = helper.get(PATCH_MODULE);
if (prev == null) {
@@ -209,13 +210,13 @@
.collect(Collectors.toSet())
.contains(argModulePackage);
if (isRepeated) {
- throw helper.newInvalidValueException("err.repeated.value.for.patch.module", argModulePackage);
+ throw helper.newInvalidValueException(Errors.RepeatedValueForPatchModule(argModulePackage));
} else {
super.process(helper, option, prev + '\0' + arg);
}
}
} else {
- throw helper.newInvalidValueException("err.bad.value.for.option", option, arg);
+ throw helper.newInvalidValueException(Errors.BadValueForOption(option, arg));
}
}
@@ -290,7 +291,7 @@
public void process(OptionHelper helper, String option, String operand) throws InvalidValueException {
Source source = Source.lookup(operand);
if (source == null) {
- throw helper.newInvalidValueException("err.invalid.source", operand);
+ throw helper.newInvalidValueException(Errors.InvalidSource(operand));
}
super.process(helper, option, operand);
}
@@ -301,7 +302,7 @@
public void process(OptionHelper helper, String option, String operand) throws InvalidValueException {
Target target = Target.lookup(operand);
if (target == null) {
- throw helper.newInvalidValueException("err.invalid.target", operand);
+ throw helper.newInvalidValueException(Errors.InvalidTarget(operand));
}
super.process(helper, option, operand);
}
@@ -337,7 +338,7 @@
public void process(OptionHelper helper, String option, String operand) throws InvalidValueException {
Profile profile = Profile.lookup(operand);
if (profile == null) {
- throw helper.newInvalidValueException("err.invalid.profile", operand);
+ throw helper.newInvalidValueException(Errors.InvalidProfile(operand));
}
super.process(helper, option, operand);
}
@@ -392,12 +393,12 @@
public void process(OptionHelper helper, String option) throws InvalidValueException {
int argLength = option.length();
if (argLength == 2) {
- throw helper.newInvalidValueException("err.empty.A.argument");
+ throw helper.newInvalidValueException(Errors.EmptyAArgument);
}
int sepIndex = option.indexOf('=');
String key = option.substring(2, (sepIndex != -1 ? sepIndex : argLength) );
if (!JavacProcessingEnvironment.isValidOptionName(key)) {
- throw helper.newInvalidValueException("err.invalid.A.key", option);
+ throw helper.newInvalidValueException(Errors.InvalidAKey(option));
}
helper.put(option, option);
}
@@ -410,14 +411,13 @@
public void process(OptionHelper helper, String option, String arg) throws InvalidValueException {
String prev = helper.get(DEFAULT_MODULE_FOR_CREATED_FILES);
if (prev != null) {
- throw helper.newInvalidValueException("err.option.too.many",
- DEFAULT_MODULE_FOR_CREATED_FILES.primaryName);
+ throw helper.newInvalidValueException(Errors.OptionTooMany(DEFAULT_MODULE_FOR_CREATED_FILES.primaryName));
} else if (arg.isEmpty()) {
- throw helper.newInvalidValueException("err.no.value.for.option", option);
+ throw helper.newInvalidValueException(Errors.NoValueForOption(option));
} else if (getPattern().matcher(arg).matches()) {
helper.put(DEFAULT_MODULE_FOR_CREATED_FILES.primaryName, arg);
} else {
- throw helper.newInvalidValueException("err.bad.value.for.option", option, arg);
+ throw helper.newInvalidValueException(Errors.BadValueForOption(option, arg));
}
}
@@ -487,7 +487,7 @@
Log log = helper.getLog();
log.setWriters(new PrintWriter(new FileWriter(arg), true));
} catch (java.io.IOException e) {
- throw helper.newInvalidValueException("err.error.writing.file", arg, e);
+ throw helper.newInvalidValueException(Errors.ErrorWritingFile(arg, e.getMessage()));
}
super.process(helper, option, arg);
}
@@ -570,12 +570,12 @@
@Override
public void process(OptionHelper helper, String option, String arg) throws InvalidValueException {
if (arg.isEmpty()) {
- throw helper.newInvalidValueException("err.no.value.for.option", option);
+ throw helper.newInvalidValueException(Errors.NoValueForOption(option));
} else if (getPattern().matcher(arg).matches()) {
String prev = helper.get(ADD_EXPORTS);
helper.put(ADD_EXPORTS.primaryName, (prev == null) ? arg : prev + '\0' + arg);
} else {
- throw helper.newInvalidValueException("err.bad.value.for.option", option, arg);
+ throw helper.newInvalidValueException(Errors.BadValueForOption(option, arg));
}
}
@@ -591,12 +591,12 @@
@Override
public void process(OptionHelper helper, String option, String arg) throws InvalidValueException {
if (arg.isEmpty()) {
- throw helper.newInvalidValueException("err.no.value.for.option", option);
+ throw helper.newInvalidValueException(Errors.NoValueForOption(option));
} else if (getPattern().matcher(arg).matches()) {
String prev = helper.get(ADD_READS);
helper.put(ADD_READS.primaryName, (prev == null) ? arg : prev + '\0' + arg);
} else {
- throw helper.newInvalidValueException("err.bad.value.for.option", option, arg);
+ throw helper.newInvalidValueException(Errors.BadValueForOption(option, arg));
}
}
@@ -612,14 +612,14 @@
@Override
public void process(OptionHelper helper, String option, String arg) throws InvalidValueException {
if (arg.isEmpty()) {
- throw helper.newInvalidValueException("err.no.value.for.option", option);
+ throw helper.newInvalidValueException(Errors.NoValueForOption(option));
} else if (getPattern().matcher(arg).matches()) {
String prev = helper.get(ADD_MODULES);
// since the individual values are simple names, we can simply join the
// values of multiple --add-modules options with ','
helper.put(ADD_MODULES.primaryName, (prev == null) ? arg : prev + ',' + arg);
} else {
- throw helper.newInvalidValueException("err.bad.value.for.option", option, arg);
+ throw helper.newInvalidValueException(Errors.BadValueForOption(option, arg));
}
}
@@ -633,11 +633,11 @@
@Override
public void process(OptionHelper helper, String option, String arg) throws InvalidValueException {
if (arg.isEmpty()) {
- throw helper.newInvalidValueException("err.no.value.for.option", option);
+ throw helper.newInvalidValueException(Errors.NoValueForOption(option));
} else if (getPattern().matcher(arg).matches()) {
helper.put(LIMIT_MODULES.primaryName, arg); // last one wins
} else {
- throw helper.newInvalidValueException("err.bad.value.for.option", option, arg);
+ throw helper.newInvalidValueException(Errors.BadValueForOption(option, arg));
}
}
@@ -651,13 +651,13 @@
@Override
public void process(OptionHelper helper, String option, String arg) throws InvalidValueException {
if (arg.isEmpty()) {
- throw helper.newInvalidValueException("err.no.value.for.option", option);
+ throw helper.newInvalidValueException(Errors.NoValueForOption(option));
} else {
// use official parser if available
try {
ModuleDescriptor.Version.parse(arg);
} catch (IllegalArgumentException e) {
- throw helper.newInvalidValueException("err.bad.value.for.option", option, arg);
+ throw helper.newInvalidValueException(Errors.BadValueForOption(option, arg));
}
}
super.process(helper, option, arg);
@@ -692,10 +692,10 @@
if (option.endsWith(".java") ) {
Path p = Paths.get(option);
if (!Files.exists(p)) {
- throw helper.newInvalidValueException("err.file.not.found", p);
+ throw helper.newInvalidValueException(Errors.FileNotFound(p.toString()));
}
if (!Files.isRegularFile(p)) {
- throw helper.newInvalidValueException("err.file.not.file", p);
+ throw helper.newInvalidValueException(Errors.FileNotFile(p));
}
helper.addFile(p);
} else {
@@ -1078,7 +1078,7 @@
operand = arg.substring(sep + 1);
} else {
if (!rest.hasNext()) {
- throw helper.newInvalidValueException("err.req.arg", arg);
+ throw helper.newInvalidValueException(Errors.ReqArg(this.primaryName));
}
option = arg;
operand = rest.next();
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/main/OptionHelper.java Wed Apr 18 14:07:41 2018 -0700
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/main/OptionHelper.java Fri Apr 20 09:05:05 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -27,7 +27,9 @@
import java.nio.file.Path;
+import com.sun.tools.javac.resources.CompilerProperties.Errors;
import com.sun.tools.javac.util.JCDiagnostic;
+import com.sun.tools.javac.util.JCDiagnostic.Error;
import com.sun.tools.javac.util.Log;
import com.sun.tools.javac.util.Log.PrefixKind;
@@ -89,8 +91,8 @@
* @param args the arguments, if any, for the resource string
* @return the InvalidValueException
*/
- Option.InvalidValueException newInvalidValueException(String key, Object... args) {
- return new Option.InvalidValueException(getLog().localize(PrefixKind.JAVAC, key, args));
+ Option.InvalidValueException newInvalidValueException(Error error) {
+ return new Option.InvalidValueException(getLog().localize(error));
}
/** Record a file to be compiled. */
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties Wed Apr 18 14:07:41 2018 -0700
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties Fri Apr 20 09:05:05 2018 -0700
@@ -39,13 +39,18 @@
# name a name, typically a Java identifier
# number an integer
# option name the name of a command line option
-# source version a source version number, such as 1.5, 1.6, 1.7
+# path a path
+# profile a profile name
+# source a source version number, such as 1.5, 1.6, 1.7, taken from a com.sun.tools.javac.code.Source
+# source version a source version number, such as 1.5, 1.6, 1.7, taken from a javax.lang.model.SourceVersion
# string a general string
# symbol the name of a declared type
# symbol kind the kind of a symbol (i.e. method, variable)
# kind name an informative description of the kind of a declaration; see compiler.misc.kindname.*
+# target a target version number, such as 1.5, 1.6, 1.7, taken from a com.sun.tools.javac.jvm.Target
# token the name of a non-terminal in source code; see compiler.misc.token.*
# type a Java type; e.g. int, X, X<T>
+# url a URL
# object a Java object (unspecified)
# unused the value is not used in this message
#
@@ -1779,7 +1784,7 @@
compiler.warn.option.obsolete.source=\
source value {0} is obsolete and will be removed in a future release
-# 0: string
+# 0: target
compiler.warn.option.obsolete.target=\
target value {0} is obsolete and will be removed in a future release
@@ -1787,12 +1792,12 @@
compiler.err.option.removed.source=\
Source option {0} is no longer supported. Use {1} or later.
-# 0: string, 1: string
+# 0: target, 1: target
compiler.err.option.removed.target=\
Target option {0} is no longer supported. Use {1} or later.
-# 0: string, 1: string
+# 0: target, 1: target
compiler.warn.option.parameters.unsupported=\
-parameters is not supported for target value {0}. Use {1} or later.
@@ -3257,3 +3262,123 @@
# 0: string, 1: string
compiler.err.illegal.argument.for.option=\
illegal argument for {0}: {1}
+
+
+############################################
+# messages previouly at javac.properties
+
+compiler.err.empty.A.argument=\
+ -A requires an argument; use ''-Akey'' or ''-Akey=value''
+
+# 0: string
+compiler.err.invalid.A.key=\
+ key in annotation processor option ''{0}'' is not a dot-separated sequence of identifiers
+
+# 0: string
+compiler.err.invalid.flag=\
+ invalid flag: {0}
+
+compiler.err.profile.bootclasspath.conflict=\
+ profile and bootclasspath options cannot be used together
+
+# 0: string
+compiler.err.invalid.profile=\
+ invalid profile: {0}
+
+# 0: string
+compiler.err.invalid.target=\
+ invalid target release: {0}
+
+# 0: option name, 1: target
+compiler.err.option.not.allowed.with.target=\
+ option {0} not allowed with target {1}
+
+# 0: string
+compiler.err.option.too.many=\
+ option {0} can only be specified once
+
+compiler.err.no.source.files=\
+ no source files
+
+compiler.err.no.source.files.classes=\
+ no source files or class names
+
+# 0: string
+compiler.err.req.arg=\
+ {0} requires an argument
+
+# 0: string
+compiler.err.invalid.source=\
+ invalid source release: {0}
+
+# 0: string, 1: string
+compiler.err.error.writing.file=\
+ error writing {0}; {1}
+
+compiler.err.sourcepath.modulesourcepath.conflict=\
+ cannot specify both --source-path and --module-source-path
+
+# 0: string, 1: target
+compiler.warn.source.target.conflict=\
+ source release {0} requires target release {1}
+
+# 0: string, 1: target
+compiler.warn.target.default.source.conflict=\
+ target release {0} conflicts with default source release {1}
+
+# 0: profile, 1: target
+compiler.warn.profile.target.conflict=\
+ profile {0} is not valid for target release {1}
+
+# 0: string
+compiler.err.file.not.directory=\
+ not a directory: {0}
+
+# 0: object
+compiler.err.file.not.file=\
+ not a file: {0}
+
+compiler.err.two.class.loaders.1=\
+ javac is split between multiple class loaders: check your configuration
+
+# 0: url, 1: url
+compiler.err.two.class.loaders.2=\
+ javac is split between multiple class loaders:\n\
+ one class comes from file: {0}\n\
+ while javac comes from {1}
+
+# 0: string, 1: string
+compiler.err.bad.value.for.option=\
+ bad value for {0} option: ''{1}''
+
+# 0: string
+compiler.err.no.value.for.option=\
+ no value for {0} option
+
+# 0: string
+compiler.err.repeated.value.for.patch.module=\
+ --patch-module specified more than once for {0}
+
+# 0: string
+compiler.err.unmatched.quote=\
+ unmatched quote in environment variable {0}
+
+# 0: option name
+compiler.err.release.bootclasspath.conflict=\
+ option {0} cannot be used together with --release
+
+# 0: string
+compiler.err.unsupported.release.version=\
+ release version {0} not supported
+
+# 0: string
+compiler.err.file.not.found=\
+ file not found: {0}
+
+# 0: string, 1: source
+compiler.err.preview.not.latest=\
+ invalid source release {0} with --enable-preview\n\
+ (preview language features are only supported for release {1})
+
+compiler.err.preview.without.source.or.release=\
+ --enable-preview must be used with either -source or --release
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac.properties Wed Apr 18 14:07:41 2018 -0700
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac.properties Fri Apr 20 09:05:05 2018 -0700
@@ -335,71 +335,6 @@
javac.opt.default.module.for.created.files=\
Fallback target module for files created by annotation processors, if none specified or inferred.
-## errors
-
-javac.err.empty.A.argument=\
- -A requires an argument; use ''-Akey'' or ''-Akey=value''
-javac.err.invalid.arg=\
- invalid argument: {0}
-javac.err.invalid.A.key=\
- key in annotation processor option ''{0}'' is not a dot-separated sequence of identifiers
-javac.err.invalid.flag=\
- invalid flag: {0}
-javac.err.profile.bootclasspath.conflict=\
- profile and bootclasspath options cannot be used together
-javac.err.invalid.profile=\
- invalid profile: {0}
-javac.err.invalid.target=\
- invalid target release: {0}
-javac.err.option.not.allowed.with.target=\
- option {0} not allowed with target {1}
-javac.err.option.too.many=\
- option {0} can only be specified once
-javac.err.no.source.files=\
- no source files
-javac.err.no.source.files.classes=\
- no source files or class names
-javac.err.req.arg=\
- {0} requires an argument
-javac.err.invalid.source=\
- invalid source release: {0}
-javac.err.error.writing.file=\
- error writing {0}; {1}
-javac.err.sourcepath.modulesourcepath.conflict=\
- cannot specify both --source-path and --module-source-path
-javac.warn.source.target.conflict=\
- source release {0} requires target release {1}
-javac.warn.target.default.source.conflict=\
- target release {0} conflicts with default source release {1}
-javac.warn.profile.target.conflict=\
- profile {0} is not valid for target release {1}
-javac.err.preview.not.latest=\
- invalid source release {0} with --enable-preview\n\
- (preview language features are only supported for release {1})
-javac.err.preview.without.source.or.release=\
- --enable-preview must be used with either -source or --release
-javac.err.file.not.found=\
- file not found: {0}
-javac.err.file.not.directory=\
- not a directory: {0}
-javac.err.file.not.file=\
- not a file: {0}
-javac.err.two.class.loaders.1=\
- javac is split between multiple class loaders: check your configuration
-javac.err.two.class.loaders.2=\
- javac is split between multiple class loaders:\n\
- one class comes from file: {0}\n\
- while javac comes from {1}
-javac.err.bad.value.for.option=\
- bad value for {0} option: ''{1}''
-javac.err.no.value.for.option=\
- no value for {0} option
-javac.err.repeated.value.for.patch.module=\
- --patch-module specified more than once for {0}
-
-javac.err.unmatched.quote=\
- unmatched quote in environment variable %s
-
## messages
javac.msg.usage.header=\
@@ -437,9 +372,3 @@
javac.version={0} {1}
javac.fullVersion={0} full version "{1}"
-
-javac.err.release.bootclasspath.conflict=\
- option {0} cannot be used together with --release
-
-javac.err.unsupported.release.version=\
- release version {0} not supported
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/util/AbstractDiagnosticFormatter.java Wed Apr 18 14:07:41 2018 -0700
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/util/AbstractDiagnosticFormatter.java Fri Apr 20 09:05:05 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved.
* 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,13 @@
import com.sun.tools.javac.api.Formattable;
import com.sun.tools.javac.code.Lint.LintCategory;
import com.sun.tools.javac.code.Printer;
+import com.sun.tools.javac.code.Source;
import com.sun.tools.javac.code.Symbol;
import com.sun.tools.javac.code.Type;
import com.sun.tools.javac.code.Type.CapturedType;
import com.sun.tools.javac.file.PathFileObject;
import com.sun.tools.javac.jvm.Profile;
+import com.sun.tools.javac.jvm.Target;
import com.sun.tools.javac.main.Option;
import com.sun.tools.javac.tree.JCTree.*;
import com.sun.tools.javac.tree.Pretty;
@@ -211,6 +213,12 @@
else if (arg instanceof Formattable) {
return ((Formattable)arg).toString(l, messages);
}
+ else if (arg instanceof Target) {
+ return ((Target)arg).name;
+ }
+ else if (arg instanceof Source) {
+ return ((Source)arg).name;
+ }
else {
return String.valueOf(arg);
}
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/util/JavacMessages.java Wed Apr 18 14:07:41 2018 -0700
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/util/JavacMessages.java Fri Apr 20 09:05:05 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -26,6 +26,7 @@
package com.sun.tools.javac.util;
import com.sun.tools.javac.api.Messages;
+
import java.lang.ref.SoftReference;
import java.util.ResourceBundle;
import java.util.MissingResourceException;
@@ -34,6 +35,10 @@
import java.util.Locale;
import java.util.Map;
+import com.sun.tools.javac.api.DiagnosticFormatter;
+import com.sun.tools.javac.util.JCDiagnostic.Factory;
+import com.sun.tools.javac.resources.CompilerProperties.Errors;
+
/**
* Support for formatted localized messages.
*
@@ -61,6 +66,9 @@
private Locale currentLocale;
private List<ResourceBundle> currentBundles;
+ private DiagnosticFormatter<JCDiagnostic> diagFormatter;
+ private JCDiagnostic.Factory diagFactory;
+
public Locale getCurrentLocale() {
return currentLocale;
}
@@ -73,11 +81,18 @@
this.currentLocale = locale;
}
+ Context context;
+
/** Creates a JavacMessages object.
*/
public JavacMessages(Context context) {
this(defaultBundleName, context.get(Locale.class));
+ this.context = context;
context.put(messagesKey, this);
+ Options options = Options.instance(context);
+ boolean rawDiagnostics = options.isSet("rawDiagnostics");
+ this.diagFormatter = rawDiagnostics ? new RawDiagnosticFormatter(options) :
+ new BasicDiagnosticFormatter(options, this);
}
/** Creates a JavacMessages object.
@@ -140,6 +155,10 @@
return getLocalizedString(currentLocale, key, args);
}
+ public String getLocalizedString(JCDiagnostic.DiagnosticInfo diagInfo) {
+ return getLocalizedString(currentLocale, diagInfo);
+ }
+
@Override
public String getLocalizedString(Locale l, String key, Object... args) {
if (l == null)
@@ -147,6 +166,12 @@
return getLocalizedString(getBundles(l), key, args);
}
+ public String getLocalizedString(Locale l, JCDiagnostic.DiagnosticInfo diagInfo) {
+ if (l == null)
+ l = getCurrentLocale();
+ return getLocalizedString(getBundles(l), diagInfo);
+ }
+
/* Static access:
* javac has a firmly entrenched notion of a default message bundle
* which it can access from any static context. This is used to get
@@ -185,7 +210,7 @@
}
}
- private static String getLocalizedString(List<ResourceBundle> bundles,
+ static private String getLocalizedString(List<ResourceBundle> bundles,
String key,
Object... args) {
String msg = null;
@@ -205,6 +230,36 @@
return MessageFormat.format(msg, args);
}
+ private String getLocalizedString(List<ResourceBundle> bundles, JCDiagnostic.DiagnosticInfo diagInfo) {
+ String msg = null;
+ for (List<ResourceBundle> l = bundles; l.nonEmpty() && msg == null; l = l.tail) {
+ ResourceBundle rb = l.head;
+ try {
+ msg = rb.getString(diagInfo.key());
+ }
+ catch (MissingResourceException e) {
+ // ignore, try other bundles in list
+ }
+ }
+ if (msg == null) {
+ msg = "compiler message file broken: key=" + diagInfo.key() +
+ " arguments={0}, {1}, {2}, {3}, {4}, {5}, {6}, {7}";
+ }
+ if (diagInfo == Errors.Error) {
+ return MessageFormat.format(msg, new Object[0]);
+ } else {
+ return diagFormatter.format(getDiagFactory().create(DiagnosticSource.NO_SOURCE, null, diagInfo),
+ getCurrentLocale());
+ }
+ }
+
+ JCDiagnostic.Factory getDiagFactory() {
+ if (diagFactory == null) {
+ this.diagFactory = JCDiagnostic.Factory.instance(context);
+ }
+ return diagFactory;
+ }
+
/**
* This provides a way for the JavacMessager to retrieve a
* ResourceBundle from another module such as jdk.javadoc.
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Log.java Wed Apr 18 14:07:41 2018 -0700
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Log.java Fri Apr 20 09:05:05 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -42,6 +42,7 @@
import com.sun.tools.javac.main.Option;
import com.sun.tools.javac.tree.EndPosTable;
import com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag;
+import com.sun.tools.javac.util.JCDiagnostic.DiagnosticInfo;
import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
import com.sun.tools.javac.util.JCDiagnostic.DiagnosticType;
@@ -597,6 +598,11 @@
printRawLines(noticeWriter, localize(key, args));
}
+ public void printLines(DiagnosticInfo diag) {
+ PrintWriter noticeWriter = writers.get(WriterKind.NOTICE);
+ printRawLines(noticeWriter, localize(diag));
+ }
+
public void printLines(PrefixKind pk, String key, Object... args) {
PrintWriter noticeWriter = writers.get(WriterKind.NOTICE);
printRawLines(noticeWriter, localize(pk, key, args));
@@ -789,7 +795,7 @@
if (useRawMessages) {
return diagInfo.key();
} else {
- return messages.getLocalizedString(diagInfo.key(), diagInfo.args);
+ return messages.getLocalizedString(diagInfo);
}
}
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/classfile/ClassLoaderData.java Wed Apr 18 14:07:41 2018 -0700
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/classfile/ClassLoaderData.java Fri Apr 20 09:05:05 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -42,14 +42,14 @@
private static synchronized void initialize(TypeDataBase db) throws WrongTypeException {
Type type = db.lookupType("ClassLoaderData");
- classLoaderField = type.getOopField("_class_loader");
+ classLoaderField = type.getAddressField("_class_loader");
nextField = type.getAddressField("_next");
klassesField = new MetadataField(type.getAddressField("_klasses"), 0);
isAnonymousField = new CIntField(type.getCIntegerField("_is_anonymous"), 0);
dictionaryField = type.getAddressField("_dictionary");
}
- private static sun.jvm.hotspot.types.OopField classLoaderField;
+ private static AddressField classLoaderField;
private static AddressField nextField;
private static MetadataField klassesField;
private static CIntField isAnonymousField;
@@ -72,7 +72,13 @@
}
public Oop getClassLoader() {
- return VM.getVM().getObjectHeap().newOop(classLoaderField.getValue(getAddress()));
+ Address handle = classLoaderField.getValue(getAddress());
+ if (handle != null) {
+ // Load through the handle
+ OopHandle refs = handle.getOopHandleAt(0);
+ return (Instance)VM.getVM().getObjectHeap().newOop(refs);
+ }
+ return null;
}
public boolean getIsAnonymous() {
--- a/src/jdk.pack/share/native/unpack200/main.cpp Wed Apr 18 14:07:41 2018 -0700
+++ b/src/jdk.pack/share/native/unpack200/main.cpp Fri Apr 20 09:05:05 2018 -0700
@@ -59,7 +59,7 @@
#include "unpack.h"
-JNIEXPORT int JNICALL
+JNIEXPORT int
main(int argc, char **argv) {
return unpacker::run(argc, argv);
}
--- a/test/hotspot/gtest/utilities/test_globalCounter.cpp Wed Apr 18 14:07:41 2018 -0700
+++ b/test/hotspot/gtest/utilities/test_globalCounter.cpp Fri Apr 20 09:05:05 2018 -0700
@@ -29,8 +29,8 @@
#include "utilities/globalCounter.inline.hpp"
#include "utilitiesHelper.inline.hpp"
-#define GOOD 1337
-#define BAD 4711
+#define GOOD_VALUE 1337
+#define BAD_VALUE 4711
struct TestData {
long test_value;
@@ -50,13 +50,13 @@
GlobalCounter::critical_section_begin(this);
volatile TestData* test = OrderAccess::load_acquire(_test);
long value = OrderAccess::load_acquire(&test->test_value);
- ASSERT_EQ(value, GOOD);
+ ASSERT_EQ(value, GOOD_VALUE);
GlobalCounter::critical_section_end(this);
{
GlobalCounter::CriticalSection cs(this);
volatile TestData* test = OrderAccess::load_acquire(_test);
long value = OrderAccess::load_acquire(&test->test_value);
- ASSERT_EQ(value, GOOD);
+ ASSERT_EQ(value, GOOD_VALUE);
}
}
}
@@ -81,7 +81,7 @@
RCUReaderThread* reader4 = new RCUReaderThread(&post, &test, &wrt_start);
TestData* tmp = new TestData();
- tmp->test_value = GOOD;
+ tmp->test_value = GOOD_VALUE;
OrderAccess::release_store_fence(&test, tmp);
reader1->doit();
@@ -98,10 +98,10 @@
for (int i = 0; i < 100000 && stop_ms > os::javaTimeMillis(); i++) {
volatile TestData* free_tmp = test;
tmp = new TestData();
- tmp->test_value = GOOD;
+ tmp->test_value = GOOD_VALUE;
OrderAccess::release_store(&test, tmp);
GlobalCounter::write_synchronize();
- free_tmp->test_value = BAD;
+ free_tmp->test_value = BAD_VALUE;
delete free_tmp;
}
RCUReaderThread::_exit = true;
--- a/test/hotspot/jtreg/TEST.groups Wed Apr 18 14:07:41 2018 -0700
+++ b/test/hotspot/jtreg/TEST.groups Fri Apr 20 09:05:05 2018 -0700
@@ -70,7 +70,13 @@
hotspot_not_fast_compiler = \
:hotspot_compiler \
- -:tier1_compiler
+ -:tier1_compiler \
+ -:hotspot_slow_compiler
+
+hotspot_slow_compiler = \
+ compiler/codegen/aes \
+ compiler/codecache/stress \
+ compiler/gcbarriers/PreserveFPRegistersTest.java
tier1_compiler_1 = \
compiler/arraycopy/ \
@@ -102,9 +108,7 @@
compiler/integerArithmetic/ \
compiler/interpreter/ \
compiler/jvmci/ \
- -compiler/codegen/aes \
- -compiler/codecache/stress \
- -compiler/gcbarriers/PreserveFPRegistersTest.java
+ -:hotspot_slow_compiler
tier1_compiler_3 = \
compiler/intrinsics/ \
@@ -133,12 +137,21 @@
ctw_1 = \
applications/ctw/modules/ \
- -:ctw_2
+ -:ctw_2 \
+ -:ctw_3
ctw_2 = \
applications/ctw/modules/java_base.java \
applications/ctw/modules/java_desktop.java
+ctw_3 = \
+ applications/ctw/modules/javafx_graphics.java \
+ applications/ctw/modules/java_xml.java \
+ applications/ctw/modules/jdk_compiler.java \
+ applications/ctw/modules/jdk_internal_vm_compiler.java \
+ applications/ctw/modules/jdk_localedata.java \
+ applications/ctw/modules/jdk_scripting_nashorn.java \
+
tier1_gc = \
:tier1_gc_1 \
:tier1_gc_2 \
--- a/test/hotspot/jtreg/runtime/MemberName/MemberNameLeak.java Wed Apr 18 14:07:41 2018 -0700
+++ b/test/hotspot/jtreg/runtime/MemberName/MemberNameLeak.java Fri Apr 20 09:05:05 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -61,7 +61,7 @@
OutputAnalyzer output = new OutputAnalyzer(pb.start());
output.shouldContain("ResolvedMethod entry added for MemberNameLeak$Leak.callMe()V");
output.shouldContain("ResolvedMethod entry found for MemberNameLeak$Leak.callMe()V");
- output.shouldContain("ResolvedMethod entry removed for MemberNameLeak$Leak.callMe()V");
+ output.shouldContain("ResolvedMethod entry removed");
output.shouldHaveExitValue(0);
}
--- a/test/jdk/TEST.groups Wed Apr 18 14:07:41 2018 -0700
+++ b/test/jdk/TEST.groups Fri Apr 20 09:05:05 2018 -0700
@@ -1,4 +1,4 @@
-# Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@@ -34,12 +34,14 @@
java/nio/Buffer \
com/sun/crypto/provider/Cipher \
:jdk_math \
- tools/pack200
+ tools/pack200 \
+ -java/util/Arrays/TimSortStackSize2.java
tier2 = \
:tier2_part1 \
:tier2_part2 \
- :tier2_part3
+ :tier2_part3 \
+ java/util/Arrays/TimSortStackSize2.java
# com/sun/crypto/provider/Cipher is in tier1 because of JDK-8132855
tier2_part1 = \
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/net/Socket/RejectIPv6.java Fri Apr 20 09:05:05 2018 -0700
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * 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 8201510
+ * @summary Make sure IPv6 addresses are rejected when the System option
+ * java.net.preferIPv4Stack is set to true
+ * @run main/othervm -Djava.net.preferIPv4Stack=true RejectIPv6
+ */
+
+import java.net.InetSocketAddress;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.net.SocketException;
+
+public class RejectIPv6 {
+
+ public static void main(String [] argv) throws Throwable {
+ ServerSocket serverSocket = new ServerSocket(0);
+ serverSocket.setSoTimeout(1000);
+ int serverPort = serverSocket.getLocalPort();
+ Socket clientSocket = new Socket();
+
+ test("bind", () -> clientSocket.bind(
+ new InetSocketAddress("::1", 0)));
+
+ test("connect", () -> clientSocket.connect(
+ new InetSocketAddress("::1", serverPort), 1000));
+ }
+
+ static void test(String msg, CodeToTest codeToTest) throws Throwable {
+ Thread client = new Thread(() ->
+ {
+ try {
+ codeToTest.run();
+ throw new RuntimeException(msg +
+ " failed to reject IPv6 address");
+ } catch (SocketException ok) {
+ } catch (Exception exc) {
+ throw new RuntimeException("unexpected", exc);
+ }
+ });
+ client.start();
+ client.join();
+ }
+
+ interface CodeToTest {
+ void run() throws Exception;
+ }
+}
--- a/test/jdk/java/net/Socket/setReuseAddress/Basic.java Wed Apr 18 14:07:41 2018 -0700
+++ b/test/jdk/java/net/Socket/setReuseAddress/Basic.java Fri Apr 20 09:05:05 2018 -0700
@@ -25,11 +25,15 @@
* @test
* @bug 4476378
* @summary Check the specific behaviour of the setReuseAddress(boolean)
- * method.
+ * method.
* @run main Basic
* @run main/othervm -Dsun.net.useExclusiveBind Basic
+ * @run main/othervm -Dsun.net.useExclusiveBind=true Basic
* @run main/othervm -Djava.net.preferIPv4Stack=true Basic
- * @run main/othervm -Dsun.net.useExclusiveBind -Djava.net.preferIPv4Stack=true Basic
+ * @run main/othervm -Dsun.net.useExclusiveBind
+ * -Djava.net.preferIPv4Stack=true Basic
+ * @run main/othervm -Dsun.net.useExclusiveBind=true
+ * -Djava.net.preferIPv4Stack=true Basic
*/
import java.net.*;
--- a/test/jdk/java/net/Socket/setReuseAddress/Restart.java Wed Apr 18 14:07:41 2018 -0700
+++ b/test/jdk/java/net/Socket/setReuseAddress/Restart.java Fri Apr 20 09:05:05 2018 -0700
@@ -28,8 +28,12 @@
* after a crash.
* @run main Restart
* @run main/othervm -Dsun.net.useExclusiveBind Restart
+ * @run main/othervm -Dsun.net.useExclusiveBind=true Restart
* @run main/othervm -Djava.net.preferIPv4Stack=true Restart
- * @run main/othervm -Dsun.net.useExclusiveBind -Djava.net.preferIPv4Stack=true Restart
+ * @run main/othervm -Dsun.net.useExclusiveBind
+ * -Djava.net.preferIPv4Stack=true Restart
+ * @run main/othervm -Dsun.net.useExclusiveBind=true
+ * -Djava.net.preferIPv4Stack=true Restart
*/
import java.net.*;
--- a/test/jdk/java/nio/channels/AsynchronousSocketChannel/Basic.java Wed Apr 18 14:07:41 2018 -0700
+++ b/test/jdk/java/nio/channels/AsynchronousSocketChannel/Basic.java Fri Apr 20 09:05:05 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -25,8 +25,8 @@
* @bug 4607272 6842687 6878369 6944810 7023403
* @summary Unit test for AsynchronousSocketChannel(use -Dseed=X to set PRNG seed)
* @library /test/lib
- * @build jdk.test.lib.RandomFactory
- * @run main Basic -skipSlowConnectTest
+ * @build jdk.test.lib.RandomFactory jdk.test.lib.Utils
+ * @run main/othervm/timeout=600 Basic -skipSlowConnectTest
* @key randomness intermittent
*/
@@ -79,11 +79,16 @@
private final InetSocketAddress address;
Server() throws IOException {
- ssc = ServerSocketChannel.open().bind(new InetSocketAddress(0));
+ this(0);
+ }
- InetAddress lh = InetAddress.getLocalHost();
- int port = ((InetSocketAddress)(ssc.getLocalAddress())).getPort();
- address = new InetSocketAddress(lh, port);
+ Server(int recvBufSize) throws IOException {
+ ssc = ServerSocketChannel.open();
+ if (recvBufSize > 0) {
+ ssc.setOption(SO_RCVBUF, recvBufSize);
+ }
+ ssc.bind(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0));
+ address = (InetSocketAddress)ssc.getLocalAddress();
}
InetSocketAddress address() {
@@ -293,7 +298,7 @@
System.out.println("-- asynchronous close when reading --");
- try (Server server = new Server()) {
+ try (Server server = new Server(1)) {
ch = AsynchronousSocketChannel.open();
ch.connect(server.address()).get();
@@ -325,6 +330,8 @@
ch = AsynchronousSocketChannel.open();
ch.connect(server.address()).get();
+ SocketChannel peer = server.accept();
+ peer.setOption(SO_RCVBUF, 1);
final AtomicReference<Throwable> writeException =
new AtomicReference<Throwable>();
@@ -333,10 +340,13 @@
final AtomicInteger numCompleted = new AtomicInteger();
ch.write(genBuffer(), ch, new CompletionHandler<Integer,AsynchronousSocketChannel>() {
public void completed(Integer result, AsynchronousSocketChannel ch) {
+ System.out.println("completed write to async channel: " + result);
numCompleted.incrementAndGet();
ch.write(genBuffer(), ch, this);
+ System.out.println("started another write to async channel: " + result);
}
public void failed(Throwable x, AsynchronousSocketChannel ch) {
+ System.out.println("failed write to async channel");
writeException.set(x);
}
});
@@ -347,7 +357,8 @@
// the internal channel state indicates it is writing
int prevNumCompleted = numCompleted.get();
do {
- Thread.sleep(1000);
+ Thread.sleep((long)(1000 * jdk.test.lib.Utils.TIMEOUT_FACTOR));
+ System.out.println("check if buffer is filled up");
if (numCompleted.get() == prevNumCompleted) {
break;
}
@@ -357,14 +368,19 @@
// attempt a concurrent write -
// should fail with WritePendingException
try {
+ System.out.println("concurrent write to async channel");
ch.write(genBuffer());
+ System.out.format("prevNumCompleted: %d, numCompleted: %d%n",
+ prevNumCompleted, numCompleted.get());
throw new RuntimeException("WritePendingException expected");
} catch (WritePendingException x) {
}
// close channel - should cause initial write to complete
+ System.out.println("closing async channel...");
ch.close();
- server.accept().close();
+ System.out.println("closed async channel");
+ peer.close();
// wait for exception
while (writeException.get() == null) {
--- a/test/jdk/java/util/Arrays/TimSortStackSize2.java Wed Apr 18 14:07:41 2018 -0700
+++ b/test/jdk/java/util/Arrays/TimSortStackSize2.java Fri Apr 20 09:05:05 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -34,6 +34,7 @@
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
* -XX:+WhiteBoxAPI TimSortStackSize2
* @summary Test TimSort stack size on big arrays
+ * @key intermittent
*/
import java.util.ArrayList;
import java.util.Arrays;
--- a/test/jdk/java/util/Optional/Basic.java Wed Apr 18 14:07:41 2018 -0700
+++ b/test/jdk/java/util/Optional/Basic.java Fri Apr 20 09:05:05 2018 -0700
@@ -52,6 +52,7 @@
assertFalse(empty.equals("unexpected"));
assertFalse(empty.isPresent());
+ assertTrue(empty.isEmpty());
assertEquals(empty.hashCode(), 0);
assertEquals(empty.orElse("x"), "x");
assertEquals(empty.orElseGet(() -> "y"), "y");
@@ -87,6 +88,7 @@
assertFalse(opt.equals("unexpected"));
assertTrue(opt.isPresent());
+ assertFalse(opt.isEmpty());
assertEquals(opt.hashCode(), expected.hashCode());
assertEquals(opt.orElse("unexpected"), expected);
assertEquals(opt.orElseGet(() -> "unexpected"), expected);
--- a/test/jdk/java/util/Optional/BasicDouble.java Wed Apr 18 14:07:41 2018 -0700
+++ b/test/jdk/java/util/Optional/BasicDouble.java Fri Apr 20 09:05:05 2018 -0700
@@ -51,6 +51,7 @@
assertFalse(empty.equals("unexpected"));
assertFalse(empty.isPresent());
+ assertTrue(empty.isEmpty());
assertEquals(empty.hashCode(), 0);
assertEquals(empty.orElse(UNEXPECTED), UNEXPECTED);
assertEquals(empty.orElseGet(() -> UNEXPECTED), UNEXPECTED);
@@ -86,6 +87,7 @@
assertFalse(opt.equals("unexpected"));
assertTrue(opt.isPresent());
+ assertFalse(opt.isEmpty());
assertEquals(opt.hashCode(), Double.hashCode(expected));
assertEquals(opt.orElse(UNEXPECTED), expected);
assertEquals(opt.orElseGet(() -> UNEXPECTED), expected);
--- a/test/jdk/java/util/Optional/BasicInt.java Wed Apr 18 14:07:41 2018 -0700
+++ b/test/jdk/java/util/Optional/BasicInt.java Fri Apr 20 09:05:05 2018 -0700
@@ -52,6 +52,7 @@
assertFalse(empty.equals("unexpected"));
assertFalse(empty.isPresent());
+ assertTrue(empty.isEmpty());
assertEquals(empty.hashCode(), 0);
assertEquals(empty.orElse(UNEXPECTED), UNEXPECTED);
assertEquals(empty.orElseGet(() -> UNEXPECTED), UNEXPECTED);
@@ -87,6 +88,7 @@
assertFalse(opt.equals("unexpected"));
assertTrue(opt.isPresent());
+ assertFalse(opt.isEmpty());
assertEquals(opt.hashCode(), Integer.hashCode(expected));
assertEquals(opt.orElse(UNEXPECTED), expected);
assertEquals(opt.orElseGet(() -> UNEXPECTED), expected);
--- a/test/jdk/java/util/Optional/BasicLong.java Wed Apr 18 14:07:41 2018 -0700
+++ b/test/jdk/java/util/Optional/BasicLong.java Fri Apr 20 09:05:05 2018 -0700
@@ -51,6 +51,7 @@
assertFalse(empty.equals("unexpected"));
assertFalse(empty.isPresent());
+ assertTrue(empty.isEmpty());
assertEquals(empty.hashCode(), 0);
assertEquals(empty.orElse(UNEXPECTED), UNEXPECTED);
assertEquals(empty.orElseGet(() -> UNEXPECTED), UNEXPECTED);
@@ -86,6 +87,7 @@
assertFalse(opt.equals("unexpected"));
assertTrue(opt.isPresent());
+ assertFalse(opt.isEmpty());
assertEquals(opt.hashCode(), Long.hashCode(expected));
assertEquals(opt.orElse(UNEXPECTED), expected);
assertEquals(opt.orElseGet(() -> UNEXPECTED), expected);
--- a/test/jdk/java/util/zip/DeInflate.java Wed Apr 18 14:07:41 2018 -0700
+++ b/test/jdk/java/util/zip/DeInflate.java Fri Apr 20 09:05:05 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -23,17 +23,23 @@
/**
* @test
- * @bug 7110149 8184306
+ * @bug 7110149 8184306 6341887
* @summary Test basic deflater & inflater functionality
* @key randomness
*/
import java.io.*;
+import java.nio.*;
import java.util.*;
import java.util.zip.*;
+import static java.nio.charset.StandardCharsets.UTF_8;
+
public class DeInflate {
+ private static Random rnd = new Random();
+
+
static void checkStream(Deflater def, byte[] in, int len,
byte[] out1, byte[] out2, boolean nowrap)
throws Throwable
@@ -61,6 +67,57 @@
}
}
+ static void checkByteBuffer(Deflater def, Inflater inf,
+ ByteBuffer in, ByteBuffer out1, ByteBuffer out2,
+ byte[] expected, int len, byte[] result,
+ boolean out1ReadOnlyWhenInflate)
+ throws Throwable {
+ def.reset();
+ inf.reset();
+
+ def.setInput(in);
+ def.finish();
+ int m = def.deflate(out1);
+
+ out1.flip();
+ if (out1ReadOnlyWhenInflate)
+ out1 = out1.asReadOnlyBuffer();
+ inf.setInput(out1);
+ int n = inf.inflate(out2);
+
+ out2.flip();
+ out2.get(result, 0, n);
+
+ if (n != len || out2.position() != len ||
+ !Arrays.equals(Arrays.copyOf(expected, len), Arrays.copyOf(result, len)) ||
+ inf.inflate(result) != 0) {
+ throw new RuntimeException("De/inflater(buffer) failed:" + def);
+ }
+ }
+
+ static void checkByteBufferReadonly(Deflater def, Inflater inf,
+ ByteBuffer in, ByteBuffer out1, ByteBuffer out2)
+ throws Throwable {
+ def.reset();
+ inf.reset();
+ def.setInput(in);
+ def.finish();
+ int m = -1;
+ if (!out2.isReadOnly())
+ out2 = out2.asReadOnlyBuffer();
+ try {
+ m = def.deflate(out2);
+ throw new RuntimeException("deflater: ReadOnlyBufferException: failed");
+ } catch (ReadOnlyBufferException robe) {}
+ m = def.deflate(out1);
+ out1.flip();
+ inf.setInput(out1);
+ try {
+ inf.inflate(out2);
+ throw new RuntimeException("inflater: ReadOnlyBufferException: failed");
+ } catch (ReadOnlyBufferException robe) {}
+ }
+
static void check(Deflater def, byte[] in, int len,
byte[] out1, byte[] out2, boolean nowrap)
throws Throwable
@@ -83,6 +140,107 @@
m, n, len, Arrays.equals(in, out2));
throw new RuntimeException("De/inflater failed:" + def);
}
+
+ // readable
+ Arrays.fill(out1, (byte)0);
+ Arrays.fill(out2, (byte)0);
+ ByteBuffer bbIn = ByteBuffer.wrap(in, 0, len);
+ ByteBuffer bbOut1 = ByteBuffer.wrap(out1);
+ ByteBuffer bbOut2 = ByteBuffer.wrap(out2);
+ checkByteBuffer(def, inf, bbIn, bbOut1, bbOut2, in, len, out2, false);
+ checkByteBufferReadonly(def, inf, bbIn, bbOut1, bbOut2);
+
+ // readonly in
+ Arrays.fill(out1, (byte)0);
+ Arrays.fill(out2, (byte)0);
+ bbIn = ByteBuffer.wrap(in, 0, len).asReadOnlyBuffer();
+ bbOut1 = ByteBuffer.wrap(out1);
+ bbOut2 = ByteBuffer.wrap(out2);
+ checkByteBuffer(def, inf, bbIn, bbOut1, bbOut2, in, len, out2, false);
+ checkByteBufferReadonly(def, inf, bbIn, bbOut1, bbOut2);
+
+ // readonly out1 when inflate
+ Arrays.fill(out1, (byte)0);
+ Arrays.fill(out2, (byte)0);
+ bbIn = ByteBuffer.wrap(in, 0, len);
+ bbOut1 = ByteBuffer.wrap(out1);
+ bbOut2 = ByteBuffer.wrap(out2);
+ checkByteBuffer(def, inf, bbIn, bbOut1, bbOut2, in, len, out2, true);
+ checkByteBufferReadonly(def, inf, bbIn, bbOut1, bbOut2);
+
+ // direct
+ bbIn = ByteBuffer.allocateDirect(in.length);
+ bbIn.put(in, 0, n).flip();
+ bbOut1 = ByteBuffer.allocateDirect(out1.length);
+ bbOut2 = ByteBuffer.allocateDirect(out2.length);
+ checkByteBuffer(def, inf, bbIn, bbOut1, bbOut2, in, len, out2, false);
+ checkByteBufferReadonly(def, inf, bbIn, bbOut1, bbOut2);
+ }
+
+ static void checkDict(Deflater def, Inflater inf, byte[] src,
+ byte[] dstDef, byte[] dstInf,
+ ByteBuffer dictDef, ByteBuffer dictInf) throws Throwable {
+ def.reset();
+ inf.reset();
+
+ def.setDictionary(dictDef);
+ def.setInput(src);
+ def.finish();
+ int n = def.deflate(dstDef);
+
+ inf.setInput(dstDef, 0, n);
+ n = inf.inflate(dstInf);
+ if (n != 0 || !inf.needsDictionary()) {
+ throw new RuntimeException("checkDict failed: need dict to continue");
+ }
+ inf.setDictionary(dictInf);
+ n = inf.inflate(dstInf);
+ // System.out.println("result: " + new String(dstInf, 0, n));
+ if (n != src.length || !Arrays.equals(Arrays.copyOf(dstInf, n), src)) {
+ throw new RuntimeException("checkDict failed: inflate result");
+ }
+ }
+
+ static void checkDict(int level, int strategy) throws Throwable {
+
+ Deflater def = newDeflater(level, strategy, false, new byte[0]);
+ Inflater inf = new Inflater();
+
+ byte[] src = "hello world, hello world, hello sherman".getBytes();
+ byte[] dict = "hello".getBytes();
+
+ byte[] dstDef = new byte[1024];
+ byte[] dstInf = new byte[1024];
+
+ def.setDictionary(dict);
+ def.setInput(src);
+ def.finish();
+ int n = def.deflate(dstDef);
+
+ inf.setInput(dstDef, 0, n);
+ n = inf.inflate(dstInf);
+ if (n != 0 || !inf.needsDictionary()) {
+ throw new RuntimeException("checkDict failed: need dict to continue");
+ }
+ inf.setDictionary(dict);
+ n = inf.inflate(dstInf);
+ //System.out.println("result: " + new String(dstInf, 0, n));
+ if (n != src.length || !Arrays.equals(Arrays.copyOf(dstInf, n), src)) {
+ throw new RuntimeException("checkDict failed: inflate result");
+ }
+
+ ByteBuffer dictDef = ByteBuffer.wrap(dict);
+ ByteBuffer dictInf = ByteBuffer.wrap(dict);
+ checkDict(def, inf, src, dstDef, dstInf, dictDef, dictInf);
+
+ dictDef = ByteBuffer.allocateDirect(dict.length);
+ dictInf = ByteBuffer.allocateDirect(dict.length);
+ dictDef.put(dict).flip();
+ dictInf.put(dict).flip();
+ checkDict(def, inf, src, dstDef, dstInf, dictDef, dictInf);
+
+ def.end();
+ inf.end();
}
private static Deflater newDeflater(int level, int strategy, boolean dowrap, byte[] tmp) {
@@ -109,7 +267,7 @@
public static void main(String[] args) throws Throwable {
byte[] dataIn = new byte[1024 * 512];
- new Random().nextBytes(dataIn);
+ rnd.nextBytes(dataIn);
byte[] dataOut1 = new byte[dataIn.length + 1024];
byte[] dataOut2 = new byte[dataIn.length];
@@ -130,6 +288,7 @@
// use a new deflater
Deflater def = newDeflater(level, strategy, dowrap, dataOut2);
check(def, dataIn, len, dataOut1, dataOut2, dowrap);
+ def.end();
// reuse the deflater (with reset) and test on stream, which
// uses a "smaller" buffer (smaller than the overall data)
@@ -137,6 +296,8 @@
checkStream(def, dataIn, len, dataOut1, dataOut2, dowrap);
}
}
+ // test setDictionary()
+ checkDict(level, strategy);
}
}
}
--- a/test/jdk/java/util/zip/FlaterTest.java Wed Apr 18 14:07:41 2018 -0700
+++ b/test/jdk/java/util/zip/FlaterTest.java Fri Apr 20 09:05:05 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -23,13 +23,12 @@
/**
* @test
- * @bug 6348045
+ * @bug 6348045 6341887
* @summary GZipOutputStream/InputStream goes critical(calls JNI_Get*Critical)
* and causes slowness. This test uses Deflater and Inflater directly.
* @key randomness
*/
-import java.io.*;
import java.nio.*;
import java.util.*;
import java.util.zip.*;
@@ -41,35 +40,37 @@
*/
public class FlaterTest extends Thread {
private static final int DATA_LEN = 1024 * 128;
- private static byte[] data;
+
+ private static ByteBuffer dataDirect;
+ private static ByteBuffer dataHeap;
// If true, print extra info.
private static final boolean debug = false;
// Set of Flater threads running.
- private static Set flaters =
- Collections.synchronizedSet(new HashSet());
+ private static Set<Flater> flaters =
+ Collections.synchronizedSet(new HashSet<>());
/** Fill in {@code data} with random values. */
static void createData() {
- ByteBuffer bb = ByteBuffer.allocate(8);
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
- for (int i = 0; i < DATA_LEN; i++) {
- bb.putDouble(0, Math.random());
- baos.write(bb.array(), 0, 8);
+ ByteBuffer bb = ByteBuffer.allocateDirect(DATA_LEN * 8);
+ for (int i = 0; i < DATA_LEN * 8; i += 8) {
+ bb.putDouble(i, Math.random());
}
- data = baos.toByteArray();
- if (debug) System.out.println("data length is " + data.length);
+ dataDirect = bb;
+ final ByteBuffer hb = ByteBuffer.allocate(bb.capacity());
+ hb.duplicate().put(bb.duplicate());
+ dataHeap = hb;
+ if (debug) System.out.println("data length is " + bb.capacity());
}
/** @return the length of the deflated {@code data}. */
- private static int getDeflatedLength() throws Throwable {
- int rc = 0;
+ private static int getDeflatedLength() {
Deflater deflater = new Deflater();
- deflater.setInput(data);
+ deflater.setInput(dataDirect.duplicate());
deflater.finish();
- byte[] out = new byte[data.length];
- rc = deflater.deflate(out);
+ byte[] out = new byte[dataDirect.capacity()];
+ int rc = deflater.deflate(out);
deflater.end();
if (debug) System.out.println("deflatedLength is " + rc);
return rc;
@@ -78,70 +79,98 @@
/** Compares given bytes with those in {@code data}.
* @throws Exception if given bytes don't match {@code data}.
*/
- private static void validate(byte[] buf, int offset, int len) throws Exception {
+ private static void validate(ByteBuffer buf, int offset, int len) throws Exception {
for (int i = 0; i < len; i++ ) {
- if (buf[i] != data[offset+i]) {
+ if (buf.get(i) != dataDirect.get(offset+i)) {
throw new Exception("mismatch at " + (offset + i));
}
}
}
- public static void realMain(String[] args) throws Throwable {
+ public static void realMain(String[] args) {
+ int numThreads = args.length > 0 ? Integer.parseInt(args[0]) : 5;
createData();
- int numThreads = args.length > 0 ? Integer.parseInt(args[0]) : 5;
- new FlaterTest().go(numThreads);
+ for (int srcMode = 0; srcMode <= 2; srcMode ++) {
+ for (int dstMode = 0; dstMode <= 2; dstMode ++) {
+ new FlaterTest().go(numThreads, srcMode, dstMode);
+ }
+ }
}
- private synchronized void go(int numThreads) throws Throwable {
+ private synchronized void go(int numThreads, int srcMode, int dstMode) {
int deflatedLength = getDeflatedLength();
long time = System.currentTimeMillis();
for (int i = 0; i < numThreads; i++) {
- Flater f = new Flater(deflatedLength);
+ Flater f = new Flater(deflatedLength, srcMode, dstMode);
flaters.add(f);
f.start();
}
- while (flaters.size() != 0) {
- try {
- Thread.currentThread().sleep(10);
- } catch (InterruptedException ex) {
- unexpected(ex);
+ synchronized (flaters) {
+ while (flaters.size() != 0) {
+ try {
+ flaters.wait();
+ } catch (InterruptedException ex) {
+ unexpected(ex);
+ }
}
}
time = System.currentTimeMillis() - time;
System.out.println("Time needed for " + numThreads
- + " threads to deflate/inflate: " + time + " ms.");
+ + " threads to deflate/inflate: " + time + " ms (srcMode="+srcMode+",dstMode="+dstMode+")");
}
/** Deflates and inflates data. */
static class Flater extends Thread {
private final int deflatedLength;
+ private final int srcMode, dstMode;
- private Flater(int length) {
+ private Flater(int length, int srcMode, int dstMode) {
this.deflatedLength = length;
+ this.srcMode = srcMode;
+ this.dstMode = dstMode;
}
/** Deflates and inflates {@code data}. */
public void run() {
if (debug) System.out.println(getName() + " starting run()");
try {
- byte[] deflated = DeflateData(deflatedLength);
+ ByteBuffer deflated = DeflateData(deflatedLength);
InflateData(deflated);
} catch (Throwable t) {
t.printStackTrace();
fail(getName() + " failed");
} finally {
- flaters.remove(this);
+ synchronized (flaters) {
+ flaters.remove(this);
+ if (flaters.isEmpty()) {
+ flaters.notifyAll();
+ }
+ }
}
}
/** Returns a copy of {@code data} in deflated form. */
- private byte[] DeflateData(int length) throws Throwable {
+ private ByteBuffer DeflateData(int length) {
Deflater deflater = new Deflater();
- deflater.setInput(data);
+ if (srcMode == 0) {
+ deflater.setInput(dataHeap.array());
+ } else if (srcMode == 1) {
+ deflater.setInput(dataHeap.duplicate());
+ } else {
+ assert srcMode == 2;
+ deflater.setInput(dataDirect.duplicate());
+ }
deflater.finish();
- byte[] out = new byte[length];
- deflater.deflate(out);
+ ByteBuffer out = dstMode == 2 ? ByteBuffer.allocateDirect(length) : ByteBuffer.allocate(length);
+ int deflated;
+ if (dstMode == 0) {
+ deflated = deflater.deflate(out.array(), 0, length);
+ out.position(deflated);
+ } else {
+ deflater.deflate(out);
+ }
+ out.flip();
return out;
}
@@ -149,14 +178,30 @@
* inflation.
* @throws Exception if inflated bytes don't match {@code data}.
*/
- private void InflateData(byte[] bytes) throws Throwable {
+ private void InflateData(ByteBuffer bytes) throws Throwable {
Inflater inflater = new Inflater();
- inflater.setInput(bytes, 0, bytes.length);
+ if (dstMode == 0) {
+ inflater.setInput(bytes.array(), 0, bytes.remaining());
+ } else {
+ inflater.setInput(bytes);
+ }
+ if (inflater.getRemaining() == 0) {
+ throw new Exception("Nothing to inflate (bytes=" + bytes + ")");
+ }
int len = 1024 * 8;
int offset = 0;
+ ByteBuffer buf = srcMode == 2 ? ByteBuffer.allocateDirect(len) : ByteBuffer.allocate(len);
while (inflater.getRemaining() > 0) {
- byte[] buf = new byte[len];
- int inflated = inflater.inflate(buf, 0, len);
+ buf.clear();
+ int inflated;
+ if (srcMode == 0) {
+ inflated = inflater.inflate(buf.array(), 0, buf.remaining());
+ } else {
+ inflated = inflater.inflate(buf);
+ }
+ if (inflated == 0) {
+ throw new Exception("Nothing inflated (dst=" + buf + ",offset=" + offset + ",rem=" + inflater.getRemaining() + ",srcMode="+srcMode+",dstMode="+dstMode+")");
+ }
validate(buf, offset, inflated);
offset += inflated;
}
--- a/test/langtools/jdk/javadoc/tool/BadOptionsTest.java Wed Apr 18 14:07:41 2018 -0700
+++ b/test/langtools/jdk/javadoc/tool/BadOptionsTest.java Fri Apr 20 09:05:05 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved.
* 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,7 @@
.run(Task.Expect.FAIL)
.writeAll();
checkFound(result.getOutput(Task.OutputKind.DIRECT),
- "javadoc: error - no value for --add-modules option");
+ "javadoc: error - error: no value for --add-modules option");
checkNotFound(result, "Exception", "at jdk.javadoc/");
}
@@ -104,7 +104,7 @@
.run(Task.Expect.FAIL)
.writeAll();
checkFound(result.getOutput(Task.OutputKind.DIRECT),
- "javadoc: error - no value for --add-exports option");
+ "javadoc: error - error: no value for --add-exports option");
checkNotFound(result, "Exception", "at jdk.javadoc/");
}
@@ -116,7 +116,7 @@
.run(Task.Expect.FAIL)
.writeAll();
checkFound(result.getOutput(Task.OutputKind.DIRECT),
- "javadoc: error - bad value for --add-exports option");
+ "javadoc: error - error: bad value for --add-exports option: 'm/p'");
checkNotFound(result, "Exception", "at jdk.javadoc/");
}
@@ -146,7 +146,7 @@
.run(Task.Expect.FAIL)
.writeAll();
checkFound(result.getOutput(Task.OutputKind.DIRECT),
- "javadoc: cannot specify both --source-path and --module-source-path");
+ "error: cannot specify both --source-path and --module-source-path");
checkFound(result.getOutput(Task.OutputKind.DIRECT),
"1 error");
}
--- a/test/langtools/tools/javac/6410653/T6410653.java Wed Apr 18 14:07:41 2018 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,59 +0,0 @@
-/*
- * Copyright (c) 2006, 2016, Oracle and/or its affiliates. All rights reserved.
- * 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 6410653 6401277
- * @summary REGRESSION: javac crashes if -d or -s argument is a file
- * @author Peter von der Ah\u00e9
- * @modules java.compiler
- * jdk.compiler/com.sun.tools.javac.util:open
- */
-
-import java.lang.reflect.Field;
-import java.io.File;
-import java.io.ByteArrayOutputStream;
-import javax.tools.*;
-
-public class T6410653 {
- public static void main(String... args) throws Exception {
- File testSrc = new File(System.getProperty("test.src"));
- String source = new File(testSrc, "T6410653.java").getPath();
- Tool compiler = ToolProvider.getSystemJavaCompiler();
- Module compilerModule = compiler.getClass().getModule();
- Class<?> log = Class.forName(compilerModule, "com.sun.tools.javac.util.Log");
- Field useRawMessages = log.getDeclaredField("useRawMessages");
- useRawMessages.setAccessible(true);
- useRawMessages.setBoolean(null, true);
- ByteArrayOutputStream out = new ByteArrayOutputStream();
- compiler.run(null, null, out, "-d", source, source);
- System.err.println(">>>" + out + "<<<");
- useRawMessages.setBoolean(null, false);
- if (!out.toString().equals(String.format("%s%n",
- "javac: javac.err.file.not.directory"))) {
- throw new AssertionError(out);
- }
- System.out.println("Test PASSED. Running javac again to see localized output:");
- compiler.run(null, null, System.out, "-d", source, source);
- }
-}
--- a/test/langtools/tools/javac/T8009640/CheckRejectProfileBCPOptionsIfUsedTogetherTest.java Wed Apr 18 14:07:41 2018 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,69 +0,0 @@
-/*
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
- * 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 8009640
- * @summary -profile <compact> does not work when -bootclasspath specified
- * @library /tools/lib
- * @modules jdk.compiler/com.sun.tools.javac.api
- * jdk.compiler/com.sun.tools.javac.main
- * jdk.compiler/com.sun.tools.javac.util
- * jdk.jdeps/com.sun.tools.javap
- * @build toolbox.ToolBox toolbox.JavacTask
- * @run main CheckRejectProfileBCPOptionsIfUsedTogetherTest
- */
-
-import java.nio.file.Paths;
-
-import com.sun.tools.javac.util.Assert;
-
-import toolbox.JavacTask;
-import toolbox.Task;
-import toolbox.ToolBox;
-
-public class CheckRejectProfileBCPOptionsIfUsedTogetherTest {
-
- private static final String TestSrc =
- "public class Test {\n" +
- " javax.swing.JButton b;\n" +
- "}";
-
- public static void main(String args[]) throws Exception {
- ToolBox tb = new ToolBox();
- tb.writeFile("Test.java", TestSrc);
-
- Task.Result result = new JavacTask(tb, Task.Mode.CMDLINE)
- .options("-profile", "compact1",
- "-bootclasspath", Paths.get(ToolBox.testJDK, "jre/lib/rt.jar").toString())
- .files("Test.java")
- .run(Task.Expect.FAIL)
- .writeAll();
-
- String out = result.getOutput(Task.OutputKind.DIRECT);
- Assert.check(out.startsWith(
- "javac: profile and bootclasspath options cannot be used together"),
- "Incorrect javac error output");
- }
-
-}
--- a/test/langtools/tools/javac/diags/CheckResourceKeys.java Wed Apr 18 14:07:41 2018 -0700
+++ b/test/langtools/tools/javac/diags/CheckResourceKeys.java Fri Apr 20 09:05:05 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -233,7 +233,6 @@
"compiler.misc.non.denotable.type", // UNUSED
"compiler.misc.unnamed.package", // should be required, CR 6964147
"compiler.warn.proc.type.already.exists", // TODO in JavacFiler
- "javac.err.invalid.arg", // UNUSED ??
"javac.opt.arg.class", // UNUSED ??
"javac.opt.arg.pathname", // UNUSED ??
"javac.opt.moreinfo", // option commented out
--- a/test/langtools/tools/javac/diags/examples.not-yet.txt Wed Apr 18 14:07:41 2018 -0700
+++ b/test/langtools/tools/javac/diags/examples.not-yet.txt Fri Apr 20 09:05:05 2018 -0700
@@ -157,3 +157,35 @@
compiler.err.locn.module-info.not.allowed.on.patch.path
compiler.misc.cant.resolve.modules
compiler.misc.file.does.not.contain.module
+
+# these keys were in javac.properties and examples are hard to be produced for them
+# basically because in most cases the compilation ends with an exception
+compiler.err.bad.value.for.option
+compiler.err.empty.A.argument
+compiler.err.error.writing.file
+compiler.err.file.not.directory
+compiler.err.file.not.file
+compiler.err.file.not.found
+compiler.err.invalid.A.key
+compiler.err.invalid.flag
+compiler.err.invalid.profile
+compiler.err.invalid.source
+compiler.err.invalid.target
+compiler.err.no.source.files.classes
+compiler.err.no.value.for.option
+compiler.err.option.not.allowed.with.target
+compiler.err.option.too.many
+compiler.err.profile.bootclasspath.conflict
+compiler.err.release.bootclasspath.conflict
+compiler.err.repeated.value.for.patch.module
+compiler.err.req.arg
+compiler.err.sourcepath.modulesourcepath.conflict
+compiler.err.two.class.loaders.1
+compiler.err.two.class.loaders.2
+compiler.err.unmatched.quote
+compiler.err.unsupported.release.version
+compiler.warn.profile.target.conflict
+compiler.warn.source.target.conflict
+compiler.warn.target.default.source.conflict
+compiler.err.preview.not.latest
+compiler.err.preview.without.source.or.release
\ No newline at end of file
--- a/test/langtools/tools/javac/diags/examples/DirPathElementNotDirectory/DirPathElementNotDirectory.java Wed Apr 18 14:07:41 2018 -0700
+++ b/test/langtools/tools/javac/diags/examples/DirPathElementNotDirectory/DirPathElementNotDirectory.java Fri Apr 20 09:05:05 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -22,5 +22,6 @@
*/
// key: compiler.warn.dir.path.element.not.directory
+// key: compiler.err.no.source.files
// options: -Xlint:path
// run: simple
--- a/test/langtools/tools/javac/doclint/DocLintTest.java Wed Apr 18 14:07:41 2018 -0700
+++ b/test/langtools/tools/javac/doclint/DocLintTest.java Fri Apr 20 09:05:05 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -84,7 +84,7 @@
DL_ERR9(ERROR, "Test.java:9:14: compiler.err.proc.messager: reference not found"),
DL_WRN12(WARNING, "Test.java:12:9: compiler.warn.proc.messager: no description for @return"),
- OPT_BADARG(ERROR, "invalid flag: -Xdoclint:badarg");
+ OPT_BADARG(ERROR, "error: invalid flag: -Xdoclint:badarg");
final Diagnostic.Kind kind;
final String text;
--- a/test/langtools/tools/javac/doclint/IncludePackagesTest.java Wed Apr 18 14:07:41 2018 -0700
+++ b/test/langtools/tools/javac/doclint/IncludePackagesTest.java Fri Apr 20 09:05:05 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -96,7 +96,7 @@
p1sp1sp2T(ERROR, "p1sp1sp2T.java:2:12: compiler.err.proc.messager: malformed HTML"),
p2T(ERROR, "p2T.java:2:12: compiler.err.proc.messager: malformed HTML"),
Default(ERROR, "Default.java:1:12: compiler.err.proc.messager: malformed HTML"),
- INVALID_PACKAGE_ERROR(ERROR, "invalid flag: -Xdoclint/package:wrong+package");
+ INVALID_PACKAGE_ERROR(ERROR, "error: invalid flag: -Xdoclint/package:wrong+package");
final Diagnostic.Kind kind;
final String text;
--- a/test/langtools/tools/javac/modules/AddExportsTest.java Wed Apr 18 14:07:41 2018 -0700
+++ b/test/langtools/tools/javac/modules/AddExportsTest.java Fri Apr 20 09:05:05 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -62,7 +62,7 @@
.getOutput(Task.OutputKind.DIRECT);
checkOutputContains(log,
- "javac: no value for --add-exports option");
+ "error: no value for --add-exports option");
}
@Test
@@ -123,7 +123,7 @@
.getOutput(Task.OutputKind.DIRECT);
checkOutputContains(log,
- "javac: bad value for --add-exports option: '" + option + "'");
+ "error: bad value for --add-exports option: '" + option + "'");
}
@Test
@@ -158,7 +158,7 @@
.getOutput(Task.OutputKind.DIRECT);
checkOutputContains(log,
- "javac: bad value for --add-exports option: '" + option + "'");
+ "error: bad value for --add-exports option: '" + option + "'");
}
@Test
--- a/test/langtools/tools/javac/modules/AddLimitMods.java Wed Apr 18 14:07:41 2018 -0700
+++ b/test/langtools/tools/javac/modules/AddLimitMods.java Fri Apr 20 09:05:05 2018 -0700
@@ -264,7 +264,7 @@
.writeAll()
.getOutputLines(Task.OutputKind.DIRECT);
- if (!actual.contains("javac: option --add-modules not allowed with target 1.8")) {
+ if (!actual.contains("- compiler.err.option.not.allowed.with.target: --add-modules, 1.8")) {
throw new IllegalStateException("incorrect errors; actual=" + actual);
}
--- a/test/langtools/tools/javac/modules/AddModulesTest.java Wed Apr 18 14:07:41 2018 -0700
+++ b/test/langtools/tools/javac/modules/AddModulesTest.java Fri Apr 20 09:05:05 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -73,7 +73,7 @@
.getOutput(Task.OutputKind.DIRECT);
checkOutputContains(log,
- "javac: no value for --add-modules option");
+ "error: no value for --add-modules option");
}
@Test
@@ -120,7 +120,7 @@
.getOutput(Task.OutputKind.DIRECT);
checkOutputContains(log,
- "javac: bad value for --add-modules option");
+ "error: bad value for --add-modules option");
}
@Test
--- a/test/langtools/tools/javac/modules/AddReadsTest.java Wed Apr 18 14:07:41 2018 -0700
+++ b/test/langtools/tools/javac/modules/AddReadsTest.java Fri Apr 20 09:05:05 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -352,7 +352,7 @@
.getOutput(Task.OutputKind.DIRECT);
checkOutputContains(log,
- "javac: no value for --add-reads option");
+ "error: no value for --add-reads option");
}
@Test
@@ -421,7 +421,7 @@
.getOutput(Task.OutputKind.DIRECT);
checkOutputContains(log,
- "javac: bad value for --add-reads option: '" + option + "'");
+ "error: bad value for --add-reads option: '" + option + "'");
}
@Test
@@ -572,7 +572,7 @@
.getOutput(Task.OutputKind.DIRECT);
checkOutputContains(log,
- "javac: bad value for --add-reads option: 'm1x:m2x'");
+ "error: bad value for --add-reads option: 'm1x:m2x'");
}
@Test
--- a/test/langtools/tools/javac/modules/LimitModulesTest.java Wed Apr 18 14:07:41 2018 -0700
+++ b/test/langtools/tools/javac/modules/LimitModulesTest.java Fri Apr 20 09:05:05 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -58,7 +58,7 @@
.writeAll()
.getOutput(Task.OutputKind.DIRECT);
- if (!log.contains("javac: no value for --limit-modules option"))
+ if (!log.contains("error: no value for --limit-modules option"))
throw new Exception("expected output not found");
log = new JavacTask(tb, Task.Mode.CMDLINE)
@@ -70,7 +70,7 @@
.writeAll()
.getOutput(Task.OutputKind.DIRECT);
- if (!log.contains("javac: no value for --limit-modules option"))
+ if (!log.contains("error: no value for --limit-modules option"))
throw new Exception("expected output not found");
}
@@ -127,7 +127,7 @@
.writeAll()
.getOutput(Task.OutputKind.DIRECT);
- if (!log.contains("javac: bad value for --limit-modules option"))
+ if (!log.contains("error: bad value for --limit-modules option"))
throw new Exception("expected output not found");
}
--- a/test/langtools/tools/javac/modules/ModuleSourcePathTest.java Wed Apr 18 14:07:41 2018 -0700
+++ b/test/langtools/tools/javac/modules/ModuleSourcePathTest.java Fri Apr 20 09:05:05 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -76,7 +76,7 @@
.writeAll()
.getOutput(Task.OutputKind.DIRECT);
- if (!log.contains("cannot specify both --source-path and --module-source-path"))
+ if (!log.contains("compiler.err.sourcepath.modulesourcepath.conflict"))
throw new Exception("expected diagnostic not found");
}
--- a/test/langtools/tools/javac/modules/PatchModulesTest.java Wed Apr 18 14:07:41 2018 -0700
+++ b/test/langtools/tools/javac/modules/PatchModulesTest.java Fri Apr 20 09:05:05 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -98,19 +98,19 @@
@Test
public void testDuplicates(Path base) throws Exception {
test(asList("java.base=a", "java.compiler=b", "java.base=c"),
- false, "--patch-module specified more than once for java.base");
+ false, "error: --patch-module specified more than once for java.base");
}
@Test
public void testEmpty(Path base) throws Exception {
test(asList(""),
- false, "no value for --patch-module option");
+ false, "error: no value for --patch-module option");
}
@Test
public void testInvalid(Path base) throws Exception {
test(asList("java.base/java.lang=."),
- false, "bad value for --patch-module option: 'java.base/java.lang=.'");
+ false, "error: bad value for --patch-module option: 'java.base/java.lang=.'");
}
void test(List<String> patches, String expect) throws Exception {
--- a/test/langtools/tools/javac/options/release/ReleaseOptionClashes.java Wed Apr 18 14:07:41 2018 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,89 +0,0 @@
-/*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
- * 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 8072480
- * @summary Verify option clash between --release and -source is reported correctly.
- * @modules jdk.compiler/com.sun.tools.javac.util:open
- */
-
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.lang.reflect.Field;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-
-import javax.tools.Tool;
-import javax.tools.ToolProvider;
-
-public class ReleaseOptionClashes {
- public static void main(String... args) throws Exception {
- new ReleaseOptionClashes().run();
- }
-
- void run() throws Exception {
- doRunTest("7", "-bootclasspath", "any");
- doRunTest("7", "-Xbootclasspath:any");
- doRunTest("7", "-Xbootclasspath/a:any");
- doRunTest("7", "-Xbootclasspath/p:any");
- doRunTest("7", "-endorseddirs", "any");
- doRunTest("7", "-extdirs", "any");
- doRunTest("7", "-source", "8");
- doRunTest("7", "-target", "8");
- doRunTest("9", "--system", "none");
- doRunTest("9", "--upgrade-module-path", "any");
- }
-
- void doRunTest(String release, String... args) throws Exception {
- System.out.println("Testing clashes for arguments: " + Arrays.asList(args));
- Class<?> log = Class.forName("com.sun.tools.javac.util.Log", true, cl);
- Field useRawMessages = log.getDeclaredField("useRawMessages");
- useRawMessages.setAccessible(true);
- useRawMessages.setBoolean(null, true);
- ByteArrayOutputStream out = new ByteArrayOutputStream();
- List<String> options = new ArrayList<>();
- options.addAll(Arrays.asList("--release", release));
- options.addAll(Arrays.asList(args));
- options.add(System.getProperty("test.src") + File.separator + "ReleaseOptionClashes.java");
- compiler.run(null, null, out, options.toArray(new String[0]));
- useRawMessages.setBoolean(null, false);
- if (!out.toString().equals(String.format("%s%n%s%n",
- "javac: javac.err.release.bootclasspath.conflict",
- "javac.msg.usage")) &&
- //-Xbootclasspath:any produces two warnings: one for -bootclasspath and one for -Xbootclasspath:
- !out.toString().equals(String.format("%s%n%s%n%s%n%s%n",
- "javac: javac.err.release.bootclasspath.conflict",
- "javac.msg.usage",
- "javac: javac.err.release.bootclasspath.conflict",
- "javac.msg.usage"))) {
- throw new AssertionError(out);
- }
- System.out.println("Test PASSED. Running javac again to see localized output:");
- compiler.run(null, null, System.out, options.toArray(new String[0]));
- }
-
- Tool compiler = ToolProvider.getSystemJavaCompiler();
- ClassLoader cl = compiler.getClass().getClassLoader();
-}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/options/smokeTests/OptionSmokeTest.java Fri Apr 20 09:05:05 2018 -0700
@@ -0,0 +1,266 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * 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 8196433
+ * @summary use the new error diagnostic approach at javac.Main
+ * @library /tools/lib
+ * @modules jdk.compiler/com.sun.tools.javac.api
+ * jdk.compiler/com.sun.tools.javac.main
+ * jdk.compiler/com.sun.tools.javac.util
+ * jdk.jdeps/com.sun.tools.javap
+ * @build toolbox.ToolBox toolbox.JavacTask toolbox.TestRunner
+ * @run main OptionSmokeTest
+ */
+
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+import com.sun.tools.javac.util.Assert;
+
+import toolbox.TestRunner;
+import toolbox.ToolBox;
+import toolbox.JavacTask;
+import toolbox.Task;
+
+public class OptionSmokeTest extends TestRunner {
+ ToolBox tb = new ToolBox();
+
+ public OptionSmokeTest() {
+ super(System.err);
+ }
+
+ protected void runTests() throws Exception {
+ runTests(m -> new Object[] { Paths.get(m.getName()) });
+ }
+
+ Path[] findJavaFiles(Path... paths) throws Exception {
+ return tb.findJavaFiles(paths);
+ }
+
+ public static void main(String... args) throws Exception {
+ new OptionSmokeTest().runTests();
+ }
+
+ @Test
+ public void optionA1(Path base) throws Exception {
+ doTest(base,
+ "error: -A requires an argument; use '-Akey' or '-Akey=value'",
+ "-A");
+ }
+
+ @Test
+ public void optionA2(Path base) throws Exception {
+ doTest(base,
+ "error: key in annotation processor option '-A1e=2' is not a dot-separated sequence of identifiers",
+ "-A1e=2");
+ }
+
+ @Test
+ public void noFlag(Path base) throws Exception {
+ doTest(base, "error: invalid flag: -noFlag", "-noFlag");
+ }
+
+ @Test
+ public void profileAndBSP(Path base) throws Exception {
+ doTest(base, "error: profile and bootclasspath options cannot be used together",
+ "-profile compact1 -bootclasspath . -target 8 -source 8");
+ }
+
+ @Test
+ public void invalidProfile(Path base) throws Exception {
+ doTest(base, "error: invalid profile: noProfile",
+ "-profile noProfile");
+ }
+
+ @Test
+ public void invalidTarget(Path base) throws Exception {
+ doTest(base, "error: invalid target release: 999999",
+ "-target 999999");
+ }
+
+ @Test
+ public void optionNotAvailableWithTarget(Path base) throws Exception {
+ doTest(base, "error: option -profile not allowed with target 11",
+ "-profile compact1 -target 11");
+ }
+
+ @Test
+ public void optionTooMany(Path base) throws Exception {
+ doTest(base, "error: option --default-module-for-created-files can only be specified once",
+ "--default-module-for-created-files=m1x --default-module-for-created-files=m1x");
+ }
+
+ @Test
+ public void noSrcFiles(Path base) throws Exception {
+ doTestNoSource(base, "error: no source files", "-target 11");
+ }
+
+ @Test
+ public void requiresArg(Path base) throws Exception {
+ doTestNoSource(base, "error: -target requires an argument", "-target");
+ }
+
+ @Test
+ public void invalidSource(Path base) throws Exception {
+ doTestNoSource(base, "error: invalid source release: 999999", "-source 999999");
+ }
+
+ @Test
+ public void sourceAndModuleSourceCantBeTogether(Path base) throws Exception {
+ doTest(base, "error: cannot specify both --source-path and --module-source-path",
+ "--source-path . --module-source-path .");
+ }
+
+ @Test
+ public void sourceAndTargetMismatch(Path base) throws Exception {
+ doTest(base, "warning: source release 11 requires target release 11",
+ "-source 11 -target 10");
+ }
+
+ @Test
+ public void targetConflictsWithDefaultSource(Path base) throws Exception {
+ doTest(base, "warning: target release 10 conflicts with default source release 11",
+ "-target 10");
+ }
+
+ @Test
+ public void profileNotValidForTarget(Path base) throws Exception {
+ doTest(base, "warning: profile compact2 is not valid for target release 1.7",
+ "-profile compact2 -target 7 -source 7");
+ }
+
+ @Test
+ public void fileNotFound(Path base) throws Exception {
+ String log = new JavacTask(tb, Task.Mode.CMDLINE)
+ .files("notExistent/T.java")
+ .run(Task.Expect.FAIL)
+ .writeAll()
+ .getOutput(Task.OutputKind.DIRECT);
+ Assert.check(log.startsWith("error: file not found: notExistent" + fileSeparator + "T.java"),
+ "real value of log:" + log);
+ }
+
+ static final String fileSeparator = System.getProperty("file.separator");
+
+ @Test
+ public void notADirectory(Path base) throws Exception {
+ doTest(base, "error: not a directory: notADirectory" + fileSeparator + "src" + fileSeparator + "Dummy.java",
+ "-d notADirectory" + fileSeparator + "src" + fileSeparator + "Dummy.java");
+ }
+
+ @Test
+ public void notAFile(Path base) throws Exception {
+ // looks like a java file, it is a directory
+ Path dir = base.resolve("dir.java");
+ tb.createDirectories(dir);
+ String log = new JavacTask(tb, Task.Mode.CMDLINE)
+ .spaceSeparatedOptions("-XDsourcefile " + dir)
+ .run(Task.Expect.FAIL)
+ .writeAll()
+ .getOutput(Task.OutputKind.DIRECT);
+ Assert.check(log.startsWith("error: not a file: notAFile" + fileSeparator + "dir.java"));
+ }
+
+ @Test
+ public void badValueForOption(Path base) throws Exception {
+ doTestNoSource(base, "error: bad value for --patch-module option: \'notExistent\'",
+ "--patch-module notExistent");
+ }
+
+ @Test
+ public void patchModuleMoreThanOnce(Path base) throws Exception {
+ doTestNoSource(base, "error: --patch-module specified more than once for m",
+ "--patch-module m=. --patch-module m=.");
+ }
+
+ @Test
+ public void unmatchedQuoteInEnvVar(Path base) throws Exception {
+ Path src = base.resolve("src");
+ tb.writeJavaFiles(src, "class Dummy {}");
+ String log = new JavacTask(tb, Task.Mode.EXEC)
+ .envVar("JDK_JAVAC_OPTIONS", "--add-exports jdk.compiler" + fileSeparator + "com.sun.tools.javac.jvm=\"ALL-UNNAMED")
+ .files(findJavaFiles(src))
+ .run(Task.Expect.FAIL)
+ .writeAll()
+ .getOutput(Task.OutputKind.STDERR);
+ Assert.check(log.startsWith("error: unmatched quote in environment variable JDK_JAVAC_OPTIONS"));
+ }
+
+ @Test
+ public void optionCantBeUsedWithRelease(Path base) throws Exception {
+ doTestNoSource(base, "error: option -source cannot be used together with --release",
+ "--release 7 -source 7");
+ }
+
+ @Test
+ public void releaseVersionNotSupported(Path base) throws Exception {
+ doTestNoSource(base, "error: release version 99999999 not supported",
+ "--release 99999999");
+ }
+
+ // taken from former test: tools/javac/options/release/ReleaseOptionClashes
+ @Test
+ public void releaseAndBootclasspath(Path base) throws Exception {
+ doTestNoSource(base, "error: option --boot-class-path cannot be used together with --release",
+ "--release 7 -bootclasspath any");
+ doTestNoSource(base, "error: option -Xbootclasspath: cannot be used together with --release",
+ "--release 7 -Xbootclasspath:any");
+ doTestNoSource(base, "error: option -Xbootclasspath/p: cannot be used together with --release",
+ "--release 7 -Xbootclasspath/p:any");
+ doTestNoSource(base, "error: option -endorseddirs cannot be used together with --release",
+ "--release 7 -endorseddirs any");
+ doTestNoSource(base, "error: option -extdirs cannot be used together with --release",
+ "--release 7 -extdirs any");
+ doTestNoSource(base, "error: option -source cannot be used together with --release",
+ "--release 7 -source 8");
+ doTestNoSource(base, "error: option -target cannot be used together with --release",
+ "--release 7 -target 8");
+ doTestNoSource(base, "error: option --system cannot be used together with --release",
+ "--release 9 --system none");
+ doTestNoSource(base, "error: option --upgrade-module-path cannot be used together with --release",
+ "--release 9 --upgrade-module-path any");
+ }
+
+ void doTest(Path base, String output, String options) throws Exception {
+ Path src = base.resolve("src");
+ tb.writeJavaFiles(src, "class Dummy { }");
+ String log = new JavacTask(tb, Task.Mode.CMDLINE)
+ .spaceSeparatedOptions(options)
+ .files(findJavaFiles(src))
+ .run(Task.Expect.FAIL)
+ .writeAll()
+ .getOutput(Task.OutputKind.DIRECT);
+ Assert.check(log.startsWith(output), "expected:\n" + output + '\n' + "found:\n" + log);
+ }
+
+ void doTestNoSource(Path base, String output, String options) throws Exception {
+ String log = new JavacTask(tb, Task.Mode.CMDLINE)
+ .spaceSeparatedOptions(options)
+ .run(Task.Expect.FAIL)
+ .writeAll()
+ .getOutput(Task.OutputKind.DIRECT);
+ Assert.check(log.startsWith(output), "expected:\n" + output + '\n' + "found:\n" + log);
+ }
+}
--- a/test/langtools/tools/javac/platform/PlatformProviderTest.java Wed Apr 18 14:07:41 2018 -0700
+++ b/test/langtools/tools/javac/platform/PlatformProviderTest.java Fri Apr 20 09:05:05 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -141,7 +141,7 @@
List<String> expectedOutput =
Arrays.asList("getSupportedPlatformNames",
"getPlatform(fail, )",
- "javac: javac.err.unsupported.release.version",
+ "error: release version fail not supported",
"javac.msg.usage");
List<String> actualOutput = result.getOutputLines(Task.OutputKind.STDERR);
result.writeAll();
--- a/test/langtools/tools/javadoc/BadOptionsTest.java Wed Apr 18 14:07:41 2018 -0700
+++ b/test/langtools/tools/javadoc/BadOptionsTest.java Fri Apr 20 09:05:05 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -96,7 +96,7 @@
.run(Task.Expect.FAIL)
.writeAll();
checkFound(result.getOutput(Task.OutputKind.DIRECT),
- "javadoc: error - no value for --add-modules option");
+ "javadoc: error - error: no value for --add-modules option");
checkNotFound(result, "Exception", "at jdk.javadoc/");
}
@@ -122,7 +122,7 @@
.run(Task.Expect.FAIL)
.writeAll();
checkFound(result.getOutput(Task.OutputKind.DIRECT),
- "javadoc: error - no value for --add-exports option");
+ "javadoc: error - error: no value for --add-exports option");
checkNotFound(result, "Exception", "at jdk.javadoc/");
}
@@ -135,7 +135,7 @@
.run(Task.Expect.FAIL)
.writeAll();
checkFound(result.getOutput(Task.OutputKind.DIRECT),
- "javadoc: error - bad value for --add-exports option");
+ "javadoc: error - error: bad value for --add-exports option: 'm/p'");
checkNotFound(result, "Exception", "at jdk.javadoc/");
}
--- a/test/langtools/tools/lib/toolbox/JavacTask.java Wed Apr 18 14:07:41 2018 -0700
+++ b/test/langtools/tools/lib/toolbox/JavacTask.java Fri Apr 20 09:05:05 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -179,6 +179,16 @@
/**
* Sets the options.
+ * @param spaceSeparatedOption the space separated options
+ * @return this task object
+ */
+ public JavacTask spaceSeparatedOptions(String spaceSeparatedOption) {
+ this.options = Arrays.asList(spaceSeparatedOption.split("\\s+"));
+ return this;
+ }
+
+ /**
+ * Sets the options.
* @param options the options
* @return this task object
*/