defender methods analysis, classloading and java.lang.StackOverflowError
Sergey Kuksenko
sergey.kuksenko at oracle.com
Wed Mar 14 08:17:05 PDT 2012
On 03/14/2012 07:08 PM, Sergey Kuksenko wrote:
> Hi All,
>
> It is not a big secret that HotSpot do classloading of
> superclasses/superinterfaces recursively.
> That means - for any fixed stack size there is classes/interfaces
> chain which causes java.lang.StackOverflowError
> For example, on Linux x86-32, chain of 512 interfaces needs at least
> 2.5Megabytes stack size using jdk7u2 (default stack size == 320k).
> Maybe it is not a good idea to do classloading with recursion, but it
> is a topic for another mail list.
>
> Let's back to defenders.
> I was playing with interface chains. All interfaces (except the first)
> are empty. There are no defender methods here.
> As result I've got on Linux x86-32:
> - jdk7u2 requires ~4.8K per interface
> - jdk8 requires ~5K per interface
> - lambda build requires ~13K per interface.
>
> Lambda's HotSpot requires 2.5 larger stack size settings than jdk8.
> This is really significant change. Jdk7 & 8 with default stack size
> (Linux32) may load chain of ~60 classes/interfaces, but lambda may
> load chain only of ~20 classes/interfaces. The source of that is
> declaration "GenericAnalyzer ga;" in the
> "ClassFileParser::parseClassFile" method and it doesn't matter that
> the declaration is inside never executed scope/block.
> We may say "thank you" to gcc. I didn't check, but expecting the
> similar problem for other C++ compilers and platforms.
>
> I've attached patch which solves that problem. Simple extracting
> couple lines of code into separate method bring back lambda to jdk8
> stack size requirements.
>
It looks like I lost the attachment, trying to repeat.
------------------------------
diff -r 108d1e7220ee src/share/vm/classfile/classFileParser.cpp
--- a/src/share/vm/classfile/classFileParser.cpp Thu Feb 02 01:53:12
2012 -0500
+++ b/src/share/vm/classfile/classFileParser.cpp Tue Mar 13 19:24:51
2012 +0400
@@ -3396,13 +3396,9 @@
#endif
if (has_default_methods && !access_flags.is_interface()) {
- ResourceMark rm(THREAD);
-
- GenericAnalyzer ga;
- ga.run(
- class_name, this_klass, super_klass, &all_mirandas,
- methods, methods_annotations, methods_parameter_annotations,
- methods_default_annotations, CHECK_(nullHandle));
+ analyze_defaults(class_name, this_klass, super_klass, &all_mirandas,
+ methods, methods_annotations,
methods_parameter_annotations,
+ methods_default_annotations, CHECK_(nullHandle));
}
// Miranda methods
@@ -3523,6 +3519,22 @@
return this_klass;
}
+void ClassFileParser::analyze_defaults(
+ Symbol* class_name, instanceKlassHandle klass,
+ instanceKlassHandle super, GrowableArray<methodOop>* mirandas,
+ objArrayHandle methods, objArrayHandle annotations,
+ objArrayHandle annot_params, objArrayHandle annot_defaults, TRAPS){
+
+ ResourceMark rm(THREAD);
+
+ GenericAnalyzer ga;
+ ga.run(
+ class_name, klass, super, mirandas,
+ methods, annotations, annot_params,
+ annot_defaults, THREAD);
+
+}
+
unsigned int
ClassFileParser::compute_oop_map_count(instanceKlassHandle super,
diff -r 108d1e7220ee src/share/vm/classfile/classFileParser.hpp
--- a/src/share/vm/classfile/classFileParser.hpp Thu Feb 02 01:53:12
2012 -0500
+++ b/src/share/vm/classfile/classFileParser.hpp Tue Mar 13 19:24:51
2012 +0400
@@ -139,6 +139,12 @@
void parse_classfile_signature_attribute(constantPoolHandle cp,
instanceKlassHandle k, TRAPS);
void parse_classfile_bootstrap_methods_attribute(constantPoolHandle
cp, instanceKlassHandle k, u4 attribute_length, TRAPS);
+ void analyze_defaults(
+ Symbol* class_name, instanceKlassHandle klass,
+ instanceKlassHandle super, GrowableArray<methodOop>* mirandas,
+ objArrayHandle methods, objArrayHandle annotations,
+ objArrayHandle annot_params, objArrayHandle annot_defaults, TRAPS);
+
// Annotations handling
typeArrayHandle assemble_annotations(u1* runtime_visible_annotations,
int
runtime_visible_annotations_length,
--
Best regards,
Sergey Kuksenko
More information about the lambda-dev
mailing list